From 02caa5fcbba196971a3f1c3ca47ef4f83575149b Mon Sep 17 00:00:00 2001 From: CasualPokePlayer <50538166+CasualPokePlayer@users.noreply.github.com> Date: Wed, 29 Mar 2023 04:00:10 -0700 Subject: [PATCH] update ares, fix some lingering issues with recompiler --- Assets/dll/ares64.wbx.zst | Bin 471253 -> 486100 bytes waterbox/ares64/BizInterface.cpp | 78 +- waterbox/ares64/Makefile | 11 +- waterbox/ares64/ares/ares/ares/ares.hpp | 5 +- .../ares/ares/ares/memory/fixed-allocator.cpp | 2 +- .../ares/ares/ares/node/audio/stream.hpp | 2 +- .../ares/node/debugger/tracer/instruction.hpp | 8 +- waterbox/ares64/ares/ares/ares/platform.hpp | 1 + .../component/processor/sm5k/disassembler.cpp | 96 +- .../component/processor/sm5k/instruction.cpp | 96 +- waterbox/ares64/ares/ares/n64/accuracy.hpp | 9 +- waterbox/ares64/ares/ares/n64/ai/ai.hpp | 6 +- waterbox/ares64/ares/ares/n64/ai/io.cpp | 4 +- .../ares/ares/n64/cartridge/cartridge.cpp | 7 + .../ares/ares/n64/cartridge/cartridge.hpp | 30 +- .../ares/ares/n64/cartridge/isviewer.cpp | 45 +- .../ares64/ares/ares/n64/cartridge/joybus.cpp | 75 + .../ares64/ares/ares/n64/cartridge/rtc.cpp | 102 + .../ares/ares/n64/cartridge/serialization.cpp | 1 + waterbox/ares64/ares/ares/n64/cic/cic.cpp | 93 + waterbox/ares64/ares/ares/n64/cic/cic.hpp | 60 + .../ares64/ares/ares/n64/cic/commands.cpp | 65 + waterbox/ares64/ares/ares/n64/cic/io.cpp | 21 + .../ares/ares/n64/cic/serialization.cpp | 10 + .../ares/ares/n64/controller/controller.hpp | 1 + .../ares/n64/controller/gamepad/gamepad.cpp | 83 +- .../ares/n64/controller/gamepad/mbc/mbc.hpp | 5 + .../ares/n64/controller/gamepad/mbc/mbc3.hpp | 4 +- .../ares64/ares/ares/n64/controller/port.cpp | 2 +- .../ares64/ares/ares/n64/cpu/algorithms.cpp | 24 +- waterbox/ares64/ares/ares/n64/cpu/cpu.cpp | 24 +- waterbox/ares64/ares/ares/n64/cpu/cpu.hpp | 56 +- waterbox/ares64/ares/ares/n64/cpu/dcache.cpp | 40 +- .../ares64/ares/ares/n64/cpu/debugger.cpp | 6 + .../ares64/ares/ares/n64/cpu/disassembler.cpp | 2 +- .../ares64/ares/ares/n64/cpu/exceptions.cpp | 12 +- .../ares/ares/n64/cpu/interpreter-fpu.cpp | 88 +- .../ares/ares/n64/cpu/interpreter-ipu.cpp | 38 +- waterbox/ares64/ares/ares/n64/cpu/memory.cpp | 129 +- .../ares64/ares/ares/n64/cpu/recompiler.cpp | 57 +- .../ares/ares/n64/cpu/serialization.cpp | 1 + waterbox/ares64/ares/ares/n64/dd/dd.cpp | 6 +- waterbox/ares64/ares/ares/n64/dd/dd.hpp | 13 +- waterbox/ares64/ares/ares/n64/dd/drive.cpp | 2 +- waterbox/ares64/ares/ares/n64/dd/io.cpp | 206 +- waterbox/ares64/ares/ares/n64/dd/rtc.cpp | 16 +- .../ares64/ares/ares/n64/dd/serialization.cpp | 110 +- waterbox/ares64/ares/ares/n64/memory/bus.hpp | 60 +- waterbox/ares64/ares/ares/n64/memory/io.hpp | 85 +- .../ares64/ares/ares/n64/memory/memory.hpp | 4 +- waterbox/ares64/ares/ares/n64/mi/io.cpp | 4 +- waterbox/ares64/ares/ares/n64/mi/mi.hpp | 6 +- waterbox/ares64/ares/ares/n64/n64.hpp | 15 +- waterbox/ares64/ares/ares/n64/pi/bus.hpp | 11 +- waterbox/ares64/ares/ares/n64/pi/pi.hpp | 8 +- waterbox/ares64/ares/ares/n64/pif/hle.cpp | 373 +++ waterbox/ares64/ares/ares/n64/pif/io.cpp | 30 +- waterbox/ares64/ares/ares/n64/pif/pif.cpp | 281 +- waterbox/ares64/ares/ares/n64/pif/pif.hpp | 46 +- .../ares/ares/n64/pif/serialization.cpp | 13 +- waterbox/ares64/ares/ares/n64/rdp/io.cpp | 8 +- waterbox/ares64/ares/ares/n64/rdp/rdp.hpp | 12 +- waterbox/ares64/ares/ares/n64/rdram/io.cpp | 4 +- waterbox/ares64/ares/ares/n64/rdram/rdram.hpp | 6 +- waterbox/ares64/ares/ares/n64/ri/io.cpp | 4 +- waterbox/ares64/ares/ares/n64/ri/ri.hpp | 6 +- .../ares64/ares/ares/n64/rsp/disassembler.cpp | 8 +- .../ares/ares/n64/rsp/interpreter-scc.cpp | 8 +- .../ares/ares/n64/rsp/interpreter-vpu.cpp | 29 +- .../ares64/ares/ares/n64/rsp/interpreter.cpp | 3 +- waterbox/ares64/ares/ares/n64/rsp/io.cpp | 8 +- .../ares64/ares/ares/n64/rsp/recompiler.cpp | 57 +- waterbox/ares64/ares/ares/n64/rsp/rsp.cpp | 22 +- waterbox/ares64/ares/ares/n64/rsp/rsp.hpp | 21 +- .../ares/ares/n64/rsp/serialization.cpp | 23 +- waterbox/ares64/ares/ares/n64/si/dma.cpp | 12 +- waterbox/ares64/ares/ares/n64/si/io.cpp | 38 +- .../ares64/ares/ares/n64/si/serialization.cpp | 1 + waterbox/ares64/ares/ares/n64/si/si.cpp | 8 - waterbox/ares64/ares/ares/n64/si/si.hpp | 11 +- .../ares/ares/n64/system/serialization.cpp | 3 + .../ares64/ares/ares/n64/system/system.cpp | 6 +- waterbox/ares64/ares/ares/n64/vi/io.cpp | 4 +- waterbox/ares64/ares/ares/n64/vi/vi.hpp | 6 +- waterbox/ares64/ares/nall/arguments.hpp | 4 +- waterbox/ares64/ares/nall/bcd.hpp | 12 + waterbox/ares64/ares/nall/case-range.hpp | 279 ++ waterbox/ares64/ares/nall/cd.hpp | 1 + waterbox/ares64/ares/nall/cd/session.hpp | 5 - waterbox/ares64/ares/nall/chrono.hpp | 7 +- waterbox/ares64/ares/nall/cipher/chacha20.hpp | 2 +- .../ares64/ares/nall/database/sqlite3.hpp | 12 +- waterbox/ares64/ares/nall/decode/chd.hpp | 33 +- waterbox/ares64/ares/nall/directory.cpp | 86 + waterbox/ares64/ares/nall/directory.hpp | 81 +- waterbox/ares64/ares/nall/dl.cpp | 39 + waterbox/ares64/ares/nall/dl.hpp | 34 +- waterbox/ares64/ares/nall/file-map.cpp | 80 + waterbox/ares64/ares/nall/file-map.hpp | 75 +- waterbox/ares64/ares/nall/file.hpp | 2 +- waterbox/ares64/ares/nall/function.hpp | 7 - waterbox/ares64/ares/nall/http/client.cpp | 36 + waterbox/ares64/ares/nall/http/client.hpp | 31 +- waterbox/ares64/ares/nall/http/response.hpp | 2 + waterbox/ares64/ares/nall/http/server.cpp | 185 ++ waterbox/ares64/ares/nall/http/server.hpp | 188 +- waterbox/ares64/ares/nall/inode.cpp | 15 + waterbox/ares64/ares/nall/inode.hpp | 30 +- waterbox/ares64/ares/nall/intrinsics.hpp | 25 +- waterbox/ares64/ares/nall/main.cpp | 55 + waterbox/ares64/ares/nall/main.hpp | 35 +- waterbox/ares64/ares/nall/memory.cpp | 47 + waterbox/ares64/ares/nall/memory.hpp | 46 +- waterbox/ares64/ares/nall/nall.cpp | 33 + waterbox/ares64/ares/nall/path.cpp | 144 + waterbox/ares64/ares/nall/path.hpp | 139 +- waterbox/ares64/ares/nall/platform.cpp | 33 + waterbox/ares64/ares/nall/platform.hpp | 81 +- .../ares64/ares/nall/primitives/bit-field.hpp | 2 + .../ares64/ares/nall/primitives/bit-range.hpp | 2 + .../ares64/ares/nall/primitives/literals.hpp | 2 +- .../ares64/ares/nall/primitives/types.hpp | 2 +- waterbox/ares64/ares/nall/priority-queue.hpp | 9 +- waterbox/ares64/ares/nall/random.cpp | 40 + waterbox/ares64/ares/nall/random.hpp | 47 +- .../recompiler/amd64/encoder-instructions.hpp | 136 +- .../generic/encoder-instructions.hpp | 12 +- .../ares/nall/recompiler/generic/generic.hpp | 2 + waterbox/ares64/ares/nall/run.cpp | 102 + waterbox/ares64/ares/nall/run.hpp | 92 +- waterbox/ares64/ares/nall/serializer.hpp | 5 +- waterbox/ares64/ares/nall/shared-pointer.hpp | 2 +- waterbox/ares64/ares/nall/smtp.cpp | 149 + waterbox/ares64/ares/nall/smtp.hpp | 154 +- waterbox/ares64/ares/nall/stdint.hpp | 5 + .../ares64/ares/nall/string/markup/node.hpp | 8 +- .../ares64/ares/nall/string/markup/xml.hpp | 22 +- .../ares64/ares/nall/string/transform/dml.hpp | 12 +- waterbox/ares64/ares/nall/string/utility.hpp | 2 +- waterbox/ares64/ares/nall/terminal.cpp | 21 + waterbox/ares64/ares/nall/terminal.hpp | 27 +- waterbox/ares64/ares/nall/thread.cpp | 53 + waterbox/ares64/ares/nall/thread.hpp | 48 +- waterbox/ares64/ares/nall/traits.hpp | 1 + waterbox/ares64/ares/nall/vfs/cdrom.hpp | 21 +- waterbox/ares64/ares/nall/windows/detour.cpp | 69 + waterbox/ares64/ares/nall/windows/detour.hpp | 144 +- waterbox/ares64/ares/nall/windows/guard.hpp | 32 - waterbox/ares64/ares/nall/windows/guid.cpp | 17 + waterbox/ares64/ares/nall/windows/guid.hpp | 30 +- .../ares64/ares/nall/windows/launcher.cpp | 93 + .../ares64/ares/nall/windows/launcher.hpp | 90 +- .../ares64/ares/nall/windows/registry.cpp | 113 + .../ares64/ares/nall/windows/registry.hpp | 146 +- waterbox/ares64/ares/nall/windows/utf8.cpp | 37 + waterbox/ares64/ares/nall/windows/utf8.hpp | 36 +- waterbox/ares64/ares/nall/windows/windows.hpp | 12 + waterbox/ares64/ares/thirdparty/angrylion-rdp | 2 +- .../ares64/ares/thirdparty/sljit/API_CHANGES | 27 +- .../ares64/ares/thirdparty/sljit/Makefile | 5 +- .../allocator_src/sljitExecAllocatorApple.c | 118 + .../sljitExecAllocatorCore.c} | 237 +- .../allocator_src/sljitExecAllocatorFreeBSD.c | 89 + .../allocator_src/sljitExecAllocatorPosix.c | 62 + .../allocator_src/sljitExecAllocatorWindows.c | 40 + .../sljitProtExecAllocatorNetBSD.c | 72 + .../sljitProtExecAllocatorPosix.c | 172 ++ .../sljitWXExecAllocatorPosix.c} | 101 +- .../sljitWXExecAllocatorWindows.c | 102 + .../thirdparty/sljit/sljit_src/sljitConfig.h | 4 +- .../sljit/sljit_src/sljitConfigInternal.h | 41 +- .../thirdparty/sljit/sljit_src/sljitLir.c | 662 +++-- .../thirdparty/sljit/sljit_src/sljitLir.h | 857 +++--- .../sljit/sljit_src/sljitNativeARM_32.c | 551 +++- .../sljit/sljit_src/sljitNativeARM_64.c | 399 ++- .../sljit/sljit_src/sljitNativeARM_T2_32.c | 566 ++-- .../sljit/sljit_src/sljitNativeMIPS_32.c | 31 +- .../sljit/sljit_src/sljitNativeMIPS_64.c | 18 +- .../sljit/sljit_src/sljitNativeMIPS_common.c | 745 +++-- .../sljit/sljit_src/sljitNativePPC_32.c | 137 +- .../sljit/sljit_src/sljitNativePPC_64.c | 186 +- .../sljit/sljit_src/sljitNativePPC_common.c | 597 ++-- .../sljit/sljit_src/sljitNativeRISCV_32.c | 46 + .../sljit/sljit_src/sljitNativeRISCV_64.c | 21 + .../sljit/sljit_src/sljitNativeRISCV_common.c | 517 +++- .../sljit/sljit_src/sljitNativeS390X.c | 642 ++++- .../sljit/sljit_src/sljitNativeX86_32.c | 191 +- .../sljit/sljit_src/sljitNativeX86_64.c | 176 +- .../sljit/sljit_src/sljitNativeX86_common.c | 1034 ++++--- .../sljit/sljit_src/sljitProtExecAllocator.c | 474 ---- .../thirdparty/sljit/test_src/sljitTest.c | 2424 +++++++++++++++-- 191 files changed, 12558 insertions(+), 5465 deletions(-) create mode 100644 waterbox/ares64/ares/ares/n64/cartridge/joybus.cpp create mode 100644 waterbox/ares64/ares/ares/n64/cartridge/rtc.cpp create mode 100644 waterbox/ares64/ares/ares/n64/cic/cic.cpp create mode 100644 waterbox/ares64/ares/ares/n64/cic/cic.hpp create mode 100644 waterbox/ares64/ares/ares/n64/cic/commands.cpp create mode 100644 waterbox/ares64/ares/ares/n64/cic/io.cpp create mode 100644 waterbox/ares64/ares/ares/n64/cic/serialization.cpp create mode 100644 waterbox/ares64/ares/ares/n64/pif/hle.cpp create mode 100644 waterbox/ares64/ares/nall/bcd.hpp create mode 100644 waterbox/ares64/ares/nall/case-range.hpp create mode 100644 waterbox/ares64/ares/nall/directory.cpp create mode 100644 waterbox/ares64/ares/nall/dl.cpp create mode 100644 waterbox/ares64/ares/nall/file-map.cpp create mode 100644 waterbox/ares64/ares/nall/http/client.cpp create mode 100644 waterbox/ares64/ares/nall/http/server.cpp create mode 100644 waterbox/ares64/ares/nall/inode.cpp create mode 100644 waterbox/ares64/ares/nall/main.cpp create mode 100644 waterbox/ares64/ares/nall/memory.cpp create mode 100644 waterbox/ares64/ares/nall/nall.cpp create mode 100644 waterbox/ares64/ares/nall/path.cpp create mode 100644 waterbox/ares64/ares/nall/platform.cpp create mode 100644 waterbox/ares64/ares/nall/random.cpp create mode 100644 waterbox/ares64/ares/nall/run.cpp create mode 100644 waterbox/ares64/ares/nall/smtp.cpp create mode 100644 waterbox/ares64/ares/nall/terminal.cpp create mode 100644 waterbox/ares64/ares/nall/thread.cpp create mode 100644 waterbox/ares64/ares/nall/windows/detour.cpp delete mode 100644 waterbox/ares64/ares/nall/windows/guard.hpp create mode 100644 waterbox/ares64/ares/nall/windows/guid.cpp create mode 100644 waterbox/ares64/ares/nall/windows/launcher.cpp create mode 100644 waterbox/ares64/ares/nall/windows/registry.cpp create mode 100644 waterbox/ares64/ares/nall/windows/utf8.cpp create mode 100644 waterbox/ares64/ares/nall/windows/windows.hpp create mode 100644 waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitExecAllocatorApple.c rename waterbox/ares64/ares/thirdparty/sljit/sljit_src/{sljitExecAllocator.c => allocator_src/sljitExecAllocatorCore.c} (64%) create mode 100644 waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitExecAllocatorFreeBSD.c create mode 100644 waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitExecAllocatorPosix.c create mode 100644 waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitExecAllocatorWindows.c create mode 100644 waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitProtExecAllocatorNetBSD.c create mode 100644 waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitProtExecAllocatorPosix.c rename waterbox/ares64/ares/thirdparty/sljit/sljit_src/{sljitWXExecAllocator.c => allocator_src/sljitWXExecAllocatorPosix.c} (66%) create mode 100644 waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitWXExecAllocatorWindows.c delete mode 100644 waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitProtExecAllocator.c diff --git a/Assets/dll/ares64.wbx.zst b/Assets/dll/ares64.wbx.zst index c8bcda7e57743be8f9ce5cf31180eda7aeec9484..7a228052ba1aab30b44664e3cf63251f8c503715 100644 GIT binary patch literal 486100 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≫#odtZI|6=Xhc;N+E$w z(It>%zfb@KSRSh?F{6h(5L(AWA5IPc)tkfK5wJ9%QITN$B%>!41zzxl$h37*LVhaj z{%QMSR+Q|FLB+5@4b-O^zz~W5cgLMuQ_Q-3#g{-^ugEcu*_~pJQ9)G@y-%d{v$4kg z(zEC&iVHVQ_>fPmg6BKe`Cfe?A^re@%W)@TED|V-W3U<|%ZLd&9i#3k-;smMq%Q2`? z=Lyt(u6X5IE(ZAO^b3~NZvakVZPB(_DK=#u_S{0rq`j@}^hR{h%01aZy0;#B(f9!G z?o-wZp1ok2ySN~mo|qufeWWR^TWP^KN2rrJTL@Ul*BpPhlx(Xenmj)L(3uf}H51~$ z-}P#+D{srvtM1T5M3 zxRat}<)wEcoI-{+OS8Jkv`&yRds@aSuE0b@x;<9gDH@Ft7Q3;%D1IoE>rF zEWt=f;9z;rz@;z|SllM_?oVmmzvRC8{!OfD+01M;21~iZ*wH*TJBcW_m5eW_%Fa_u zrYV5g47vwqJyIFS3mMKnF>1CWeB)Bj&()%x0T)TD$l$&07+Ip+4MS8D*I{T~%Z~Y{ zc7uo1e=rLqUC;qz9Q>4B$#4UQQz`GPfADkBxOR<1kWy)@*-M7st_7!C=_!9B^@ zX##DfilTiCek9$Rw{#kQ{L&_S>2#BcR`o%bL9Va@(K{8yXcZNG$2YBqlKeTCqjemlmn8} zUzxTUMLQ9`>XXEV@pBochklP5&xY2U#(;C_4}hT!>AZOcX^nnVqVH^d<|e73+wm#l zfapi>vvSOe>Nw41?3k_THypGCCL0(y8^PGk`${3{iQ z{(xwlXCDW!5d?NyF$O|clfO`soy!wyaBG2%XO@7Gsr}6l^VKnw=$ixyz$2i3gWZUF z9_oO|bfUt$#5^;vLSv4kSIG32u_1A2%=3P;x9}kb6%U!QdEOarjN$S_4%lMz)|SF> z%(Bw0T1|sW#+s0%@n*gjlnT^ zJU9Vx*%2_0%7Z&V8@jBEs|G#(8I7D_48%~rI@){Z1K=bw$K-XT&Tpy^IBXyk85sdp z`6<)E&|0z+66sK*ei*$4v+p{Fx2Y^@|Mq|dp5cA3yTc5uUOJW71Dn{(ykH&f*B3wU z#uiC$it!Zbqv+JJY!^tD9e^{Oh(5*u1?W68Kiz9EGVAy;3Q2FQiBDbJgPCGqBu=*$ zCnGKKr7jZi#Fjl9dh#E`PXD9-DkApR&P4yR3sP8ZcLd@+ySgsCTNQu-qYNo8!4j^0 z!_-_#pKY`0NkeL}$!s>I@Yv1Xa z_$Gy;6#FB3%`m}6)34jexifbev9%O-y^7gC{+<%B@13AovNP-6I;xxn_%M1-+@lQyMT(ArT2!M2MkfmaIPDvgxKcLk3vwr4N z3B3;m8ALVa+gMF|52>vHYAW)!0*3-+eb{=#(R_3OH$Up3QVOIIfpN7g;fyIO*n{g3 z#*K##nbFZvA`WI$fkil(p1BARZZd=4#nSFq#!j}dk=BZrfvzbm4T`Hjw&<8)?08sH zxwr&c3&RX1xsEc8j;lb82fz8wfB(22NNMe zF+)DN07xb8m*Tv@VOl>ii37S_mJpBqDq`HBSXF3Yi@^i9%pk>IRw}v8!&cIuXEoqO z+`2(4PfpH8%*a)s@8)dDPheipUs1I2SeK%hpI>TB(I?CqTZm=VJ_HgMUAe`Xl5OrE z;$$c$AQE;lE|k7_c}Jd4m!2yXSG+%JPSUD+wsfmha%8+aB6QVCxj;dE!s)W-X?`rK z$0P%g3X?HwQYj%w6E!s~_e+@+h}6Hzy43}{D{jIFu-c!3{J!!#@d%Tf^0;wnPLT{# znCyDoZNAy=QGFFwAm#e4p zwQdfnJJ-e?_9~iYsfDDM5sdk=*#v{+BKq#gC}(Qmox+7=F+OH&)s72km!x0T> = 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�owi($AhA6ag4l%Q4JtW>nkElwsGFN_g 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�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 z zzgP3~hm_IsJv4Y;T=*GnL8sO}A3;%-APIO#tXNCs{G+Pffjb|wkchx-oei9s}z@Nb;C=g8-f`jz9O zItVFSvkEz|iXI+&U7wAK4@%iMa+M8JF6h&OMsmw}b{e-^lj=DLHA_B!wMUJMuH8q6?yfsvQP*90oj11L^6C7)>%E#SC8&3PLz|G?ZT6ge zyNJrK`$Qp>1EuIt2?s&)ZD1_Ny_$rU&Es0$Vr19WDo>bfQple16$84h5fI|kjy zUjl2ml3$AQB4#hr#Vmd-aLn24+C*O?H+IEizs;`$yDJ?LIo8^8NKm6JC@N?)slXE- z@|5i1hSR1S={q?u_{AWoQ>x zXi==o{H=ka&0=4myx+!b**VZ3L4+zChW|T6fP~!lkiD(_+o1o)15moC0oPd2{vhKg z3PM$4Dq2&VU0{VUPY9Bv2KzDSD=DYov6sPZufE9>d$B{=C|(0xvFY?6_hRJ}rBI?)A5EMz ztm2Wzu=tOMr;>>faQR@IB&M=FRp}6)(khFJgFUutF)iDqUB+pKqEK$7A4F>-wRc*l z*fZ-0y)4=J4=mH5H^{mEE=Mv~WVf#=D8j*E#+3SD1O?K1axZFAYXcj1k{5A`h_}}Q4koWWd~2?Z(ie)%p-rB zx<;5>wO?}8kG`kt__+Cc01oq89@Q?Faw^0CPR6LErNsa(Eu)s!afgiFcr4O1KJ7r_ zaO&Y5jYbkd2Z%(Y(YX;~HvrM-2y-+l%w_aJVUcD~&u^m-J;GoRCW2cKr?KmU;5xFx zTFD^j5Ukp0Uku);XMBaCky^;;=cOV|FE$bnT;ki*OZ?mqlm};tOYmB-!+B$v#a+a^ zMo*mYxdje{TQxJz8iuuE3ml46r2?W<2$woB2Cln_5d4BmW5DipGOef-Dwayd2cCB4 z6(9U^&j`5MM-Vx~!8$uTvl9Nt9Pt34I!b4Vdi*@g?Y;GKsqO_aliA2tf_oNpqq0IQ za40S!0n0B$eZ_Pm2`&C9(-3c_k72^5F>r<=>*ZmBey#-DP!Ur*#{-FZh$awCADVue ze40Eob!eiSI5cf&($Ms4LZGRqiKl69lACs#GBo*`beeLSdQEZD3)nOjZ@?dyH^@qk zj(t%6ylBw_@fg42K(6sIqWF({U55=eR>}0A#uMRqFF;s`J-<%kw~2o}!Jk|XNr0^h zmILg~KjiQI8TkIc=ctRZa72?+Nh1zpaQ^9XrLOCG=q`yU-nXbiS;VO8KwZ~WIBB4l zy#?ENwxJXl009oM@oMfFo2F@cji$9Q)V6J-;eCA3z^-d!w)wPeo6P1Bgehjn0p)$4 zv{%?-F>Tw1U!4(Tj4J3yeaBL7)I&Jxx;__+AcEA#RU#7-^iecOlEw(v6SG_Ld~BlQ zpB@X8=Q~q2gd&kiOgEAGeJDtA(j9pOA&e93O>$%-R}X^v|#X zg6oWdyBKUvk|arzBuSDe@rLX=$ew{sN--}tPdGuGDB2c?HR3KZdC4-Iq>w&K>oL+S z$GR1ruFg{rGzY%P)Q&^H1N@b zM+Q$$7wpi1G@}5=4I2_1YeYa}Mw3y7ml#&FwY9hglUF|^0z;aP)@8rWs#HI!m4$T$ zb?(gM6Y^-(Z(-1`={eT9+U(VOR;Bt;tt_l7sB>o~pO8nRehY(kP0umxYO`1CS(WNX zwX(3Tpw69{d_o$FdVU)Ti-JQou>PTcvoGGgZX2zdtd=ZcU{e3fs|(8&D^;Qd7=Qq< zrhEXV$r2^Pn?rq_Qk8+>g*3FSq$LQ5y3+8A_@wnBcF;iwU#?IrlS@2uL5 zOcfzAB$>ez22L03us}xz$Q%?*fa8V@363=)m?0xZlTp8gK|6+D5L|8cY9%wqg%-rH z5az7RtV;ExT3J|EQ0LA}J|T}r{T2r8nx5kiTy6GhJ*!fEF0QA33xg(v?3#{wI5#^T z>{X0Hvq<<6Ytp~jCnY8INN9#z+vMU!HgKj7exs4r2Oc1z=cr*LNU;< zqM(_XnU@%fWr1n)gaT$m378PFOOO}=3=#qKMXVn%rMkjkZQ;yIH3e!GA4~KEtrD`R zU`@Gt0$t*)+L~f2lRlnyAaNXL7>jy-v&}$C`Y5IDMcvxG&X`5}2*(x37OGn&oG^C_ zOukr(jy?VEST#CRfYa|x0uNWAo!XoifV8R_fgP3s3x z)tKjBL;|%AiwzrX7HnLIvoov``lZJ&uLJGwjK{cG7zVx);GzY33E*oDX)SNcU{z13 zoX{dz&##-+kr62ALR(B1vSE=y4?vIis9m4E^U(qLpaMqXK*&dL`DSHZd+q4fOjz== zNlUO_-XR!Tg~v=6zRD$w{n@t;$~h_>jgXwjo#Lz1-@;M(9SmDpLFz)Aeq-(Rj0$Gu zExu7FEGbQ(NO%s!?xOG>qH8ZA17_foDLnBF*|2=)hCEfqIJwu>lb z$GU<#l^}gc5gv`Ylv~P?6j}-}D`l1vOL4Vw)fTd-epJf@=M&`4Og{0rx{FuzmGCNf zWna}-BD7b#YW8Y9V?hgxGYjhq+T=+Y4}53Z?A4kU%>vcR!n*n(Ii)`#kH#2KY$!!g zTqrdZ8p;eMhLU4_K=iCi^}(*FB%#ioNyLcbiLF1mp9r4>pP+aWKlxdoxZ3R1jGw|) zR4WT>0L&_5@(Fpg;Uwt9$Vu$Pc2YZ`oy<;pu4;ViS(QqLRRZ%0>fDhWcQgqa^(J={ zVUq@$%uRl-P2wi5HtR<9g5^iGvJS8>IWm(^NF7XsO!6#~nMsg|&7@}HfeGCvn?;@7 ztGu-mxd5xGPA6np5&BIVn9SBczB`${#h`N)r>)~HEZV{chmNK{z9SwvhT>&kjmjG2 zxjPbbVWL}Cal)C&7m44&67(^uXL)u!okj)3QBg$i1eZGa&EMU0Cr&cD(InD%2kW^5 z?7+~Cl@r+lw4J#T8~Kp3GQjD_HO!Tm^wLq7@FWcZF3@pHxN8Ddyr})ksBQ(f=9R$# zP2~nym#EIfgBFS82*gYB3WK-~@(nv$!Yn|p$=k+60aW;HXA=0xiQuKz!xW;>5D|&$ z570vN7jcCbt(&lu=nO#$hLB#wyF}3{XhlM|>N!|S&F_);2wl}sW8lM!VwID`>J`=1@a{{?;^fAiVnMhOAC<@-#rVzgXw z7r_pa<{?5kw85{!i3G(6BLKU>ALJB`(z0{Gl6jx9P|@^N6xLs7q4~AilH4d3A{OG3 zOWDusK9?}m9*X-43oXX*)iBqyw;pSCfjzp0>}odTcXi2f5#wr2xLAlRxNv7LB6B!( zCkRubuY@rZ^Jtp>^3F7UMHjkAN}=o}lU~&@Mce5of+uGY$y_5;OzwV8d^wx*_5W;er$gHi5~TS&M`!04G&!AgHK zc5Pr}$~$(4lD zIMV!8jYVh8T5T+YL@D1eK#6wy>pVME&%9Maz3JC zMdKXrQ&yDLpELc9ei+N+RsZ%pMX5dryBCv*s6>Ae(eS$U>fHOezj`#%i*AJ&$3bEj3%JvLWJ!M6^{i$4(b}iyB%W(DPI?A|5j16*r}Kca zi%Ga+#^1FZ8c}136d@7<$zFfU-on?ecfOY%!_es{ZsP18pN zDDWKspE&anG58_}2>PNFPe_iFL$D<)cYFiAex@PL(f|IVi=-6F-q*jvXax%^N~~D1 zG(-vHicwu*fkV(UpihMkzY_p*nHwYEjuotk#VJzMIG`eyFQy4=ZmHXt?TZQDW?QS9 zSqf3BE)DK)pECCkP%|bNDDw&nOIBF%%4}&TkU@!~^uh`h$CIuh4B9n4Tcx_r!@1eT z*7(+2{PaHOmn1tvQ=N-+2%fnM&+)!{TV`xAM)WiGzx$W$hjds!j*mfZPO1tW{pg(V zE5;N5RYVfiLRjSd!FaxEXnei^P(ZK0D1N&2MfDxDMT+$95G`=~Zrx3(4BO@kTP0F5 z8gV;LL%QP#80#@a;V9njH?M8S!|=@bJUOe>_jBfDF8<|v=Ds0H5F38^7!gy)1i$J- z*&Ch4NF#6qT1B5<8de(x5T%KwEg8hNDdx<};whB{PR~fsAz3_x(|kxr&wT!kLE*LW z97^Ni4o36w*mr}^VH?jp{zAqApNBfDkNafsxh}>t&&PKBFjrd1a@)vr2dNgTm4r8AXA&k>f#@sHN?j3 z7wT>Yk5S!si<-Cho=bD{EOWRTmnR1LrN2I%9S_H0bMYH3bN6nl6RV}KUpD||=F7R@ z-eGfM+&pX!@8S-@=5R81D4oNl?hpZg$8n(?ALrg}?wz;U0cvI76ubo!gBTm0jC-?L zliSAexY*py=H66ysO9kuV*9PrpTnXG`3^9rN{i01F|sls6@@Tv3TP|vxO6Vg%~jx~ zb7J=j{0QkT19z03_!>0XY1^t;}-!}r|b4PmQ z=Io|Ho;$lI^6wSeV8?y2PxO1y|Ag?kePxuAL?3#KqIC4;@2hflyc68^q$e8xFUu}E z%QeCds%=i;>GDjM*T_rOWt%4u>)})Pg<5#LjnjrWELnaFmyGv-KWShHI0#a;wd8;# zO*x1WBT6%%++Yq1Okm*WJbH7LU{Od?`HH93cNbTAVQ03AZWnX8vS@KsS5!Q^ONEM` za_7m`pd}5}ELgOh7s}wYrIA~e~1klgAeo@b~TI?HJ9Q8U_7j5~@Qa9B(|4i1# zUMG_(nqneVL{)r2VTKu;B6TWn&o8 zNB>N}D_N4?iK;A0J{WI6#@RCf<;$8kkxpcmrP%*Xfu`vhN4_TCuw=3+6l$h+}h zc-RZi;;Ol)K0n%$*M?T|vdkt<1W)fd9RCPz{5;QYl5Z~Zxz8>3NpsHUF}UzZP zlZZUOVqKM;&cAI**#SkRJwTyapBjc0MTG7-x;Ae{FD|2RYXD@sZ{n^*~9c=HV29haYMg zGg%bBh%?QEN{!#LT`c!3cBwc1Sn8jZ&{1r+%Oy*J7wc3AVIZ+Q9_S$C&+#w)KpOEo z;M<4_(Q5LJVShh}zXtxliQk>ih&?mS$7F6qW#bMM`MMvF8K@cJTkBSJxHq#I)qVGH zXhdhPlGOQ{*b9Y1Aqm0k9cz`yLSq4*Y3?Gr)f2%neAWqACbG8LIvSr)>uR`lo>>8gFMd|?CHr*CX>lz zw8&&KtxT;3xF>-5B4#b1$jav}#5fG@5DuObsL~OwPDF9yJyI@t2?)QdTR;PrepSv= zj!MdZA%)PLn4v)N>85L;LjN)NI>=M+63X`h@i;CkS`&Na-=q-btLyU5WH6L=rr4NV ztek{KD5+4VoPUfchNS1t$Vb7lEU&7f!?2do&lf%?+s4>e!-gR2mKp<2!oy0|$?Zlz z&Z#^#9^yPXN@LuYzrZX{fG95>*t!@1mz6(ffvpQLE_n--995N;nYU<0Nu`6I#R5M4 zzZ`5liAAeEf16}KnN8Hk{5y`+KV;0x$@V?<6Us0TMX0FdRhZ*!yq2Cm)JM>&lHUe& z*f~{f86(>It3Y^>(o5s%gpYJZN*dd3;4R zf^akY11A!Eq8ZCAqb&u`t1!hJ)nnk2aV1_HBbc6I4%W0YOGb&4s4fzt&$kPQ6p3?}jpF;&a~oKXWSn~mf zvkh&(L96=IpzGZHU|hbCQPH^fmK$KcmJs9{%+0A}@K6>H;8S*@liQ2R4mFla*Ta#0tCc{QlaJC9`73Hl!{D8yJu-I$t<<50(?ig8u~TQm zJk$u=`8j=hP<`Tra;w$C@6&s?s5q*vmfP!FfP6`R2Te-D0Ny^*l~T368PKF2U~I|y z1WMQE$nLXr;kp~HghF937!1BEl2{C|N}Rj_u#)F8ZyOSx;-+Db$M*wVh2s|rtAvfN z>$(ojJG5H>USjKdhP8GU?10oeCNr=o1opn~`=+@ggUzzb!P@q2c%#MHh3(3q_;aTC z|7W9%0GZ@9F{j@yeXbDjK|}hfEC7F7Tge`e1BXJE;4G1 zJLX>9WUWAz?0R_Vp&uWmCbAUI6zAZHJTdGz0?42XO;_ICCz5=Fs8bRdL|xY-%x)Do zEV+CZhfw+?6VpgDxrWEJWtvrOczkY31?CSPpBwUEsMmVw8KQ9HcDGAUqf$bnD&uj` z=!ZSe6ogGOTFFpmq-_YESY!<^L{A*rnOX5g5yTyy*pnOzd7%m*=3TR?3~BU6CLg7H zG}1H<>w3tWVNQSGZ~*dLF__`Y>pSRX6u zF3ZmC=EMz)Di_M)yv9Fi)rg480rRLQcj^KuE-M1o6Y13MYg za`!{WBCtKxCe(3HYhJ{s3v@7y!VkaBr%#SegDGh1e4gNo=|Rw_24LlHg*1XdkTv}` zuWm4NfuccH7Q>69DeLv?i&x=rEw33|6|U^fxxkgdb%DcqCyIQMQBJA0oWpCHI!vNW$0^>ZcpJ*S_>N2mZ{n zJ0qsv9u^IQZqlT?Y6w~Ph2ZRTFILuw2Y?MUaK(lSj#;TeQCS$#=RR5k(eNbY>9et@ApJzNp54)$Lw+O(lIs<}V6{Z*rid1d#O}61_@}6bNmTx7&J^ zM&K|~pu(IK*2A$2qk_7?De6ZBP&1rAHwai4c)j`a`T~Mnt#~DTMA^1Yw0jR2dqE}E z)eweA?=@J)i0V2%cL&%b%NY0~lmHsEu(XqklI*!?#g0xA18*Vi0emVr;o)_qI&N@~L?^T5Zxd#W@?Z@p=fw8{8 zhYlb)csd8&s=^q(^%A$#6j!2yb8r_z_Ci>t%$uwSB2CIP_O7%y#wEvSQYNt{GVgwj z9otx5wavyCnP{56jcg^XUNev<6E*gUUQoV9V?^=)GQf9zC-O}U`>o@tvi;#@01P8d zorHES-YwaT594X*W)NOP+b4Rp&VFD#OJJ3P#*HZk;Fn_HQ!xg7Fog(O$QS9aBx1U* z)AbG<+C}8y?5`A&DctD%##dffo4s1ks#HI!mDR<`-HrN>CsQ9fAg<2?p2iz&DR$QE z+(@K(qS?{rW_Bh4JG!!B3fM>*L87@~B%FkwV5EKPM77IBfKiZN|9K)|RC%qnNstM=rDFmZwD?LSZAyOIS(x_lFQa4^k7;lRZEaA3o;O@lFlm?g_ zh5T($dg9l|X1DboSuY0rH6SNVf{`f$srwh)ZzFDkVQ)dYtAED-l)kVxAl&%^uhlai0j17}eJ^;SkjOG# z2AnuUWLDQ~pk^qs5M2cp$Pk1&$znLoX9E_K)nG#Q24!0=XvmUaNik%qKx$>JWFkJ1 zgQLI;jCGWI7~GJO6F&kxt13eUpOM<`^{wNyHZp|dmwoTrj%a?c$?0iei00TxBwYfd z6H>3Sobc9f@U`{VExKAa>t1pDKH=-kM!v!@uQUk=ed%rKl}L^V0$M5~HL*jJ+F*Js z^mJ=d63i_r@D))v@Wb#6U%`JAdc6gX@d=%mCOx9_$X=s*E~T4m!f2#(ybOA$N6g9F z9{P(i+yUskh=8W&d7fu_o@f1dbRkXHKZ(fsXimm6oLmM#;_;(P%eF&Q5x1Xznx^U3 z3meB=uiHCUV~Y+b*948Q71%$7^$#~;sFZo0=cKF{YZ)_ax;X5bW$z04MF*AJxhCwBzc zl27&GQ+>BHFVz%2^iX{tU((^Fu3Z?L=h^MzWWK6#()U4Et5!|+0Zk6R>y; zy?DdzAqk9c?pw`OviDWwXA=AhT8WxnB&AUHzOrUUqmM2 zc?{eZzD-EY0Z_Pr!THJfmU0&G&~IP1^OlOw2pO^5uw)U`w7k)YoX#C>2+<_+&9;e$ z5ThdFYMA8sm@vr?!1MCFxeFs&{^!bE&pC5U~^Az7gONDENaBFnxsbkC9YF)kr zNUZ#kv&_M5_$+0(Ilrsh@Jmp~IhTCLTF)M@;J4~wo}72`01KtZtzcoCfA&Nd4ojnq zm74}jSB1Jq%9jZHl=g14CJvhP#%^s&fOXwK;7_!O-=g4z01#FnbvOV_ zbA`BOaLBVpGmc%I-%U)3<5lv@bzRqWUDtJ8_jO(Oec$(epOU*1ij}41Q>(A_y}nsD zo@+aJ>qg{La(6s%37st&{OlWoFo0akSDk{eqoCct=By@|dl z;F4q_kxst}(s{yMw{_~_0Xie z66o7IqaX-fB$0LAUOcNke}lOSMT6SQ$$D}cktSPs4jS5&l0NTQtxq%ADURVsiGEOM z1PK!al@cq}cP)wR(?WfKgf%3QGswMoD#>+dKAd$&Vnr`&s)xn_Syz@M2G3&H z*FLvq3k&0Hj-P+cwkqspvro+|Fu;a4<}8gmWxvatesR?(O`$sf3rn3gN18pQPWDLi zM~A_fbHqJsmvpCgXfT$64xUR^BNg^4kyZBB^+6@(G&^;gF?`ZDF4DL$J?#3+y*mf< zY1`5lEV7V&J-H{5Wx?ayj@gYM)0CsyM&&eGqwEJssmlhCU;5OEd_(1^-iW~D7s|;c z$M~}>g+vsWu9eY_ls&{{%xaovU_0W5$o6m$L%;YzNUx%oYkT>RRjTFPdN`BGLT|XG zmrr}sUOpG1IH-innUQLSXaoQN007fv02mSqg(9IKNx~>kybdHL%EaR&<726$jKUxm zq9~9t00Dx4A%G|YKxA$Pqy(T2y^5@>_4!r>jt3QcsF# zV+yoW{e?CUhkc3)9L~m{BBwO&qDo7$sMhvxVe0^7!)olaJfF9VVqTL>56&qLze*)N z6&ghXNo3K2rE$02~@Ts`n{TdVGdkT&A+h~aI-y9^Qv1CTKuJXd_-JIwzet{5&cT!otZF@)#G%Ut1 z>evzc`Cj@7#Tm|}+|zvK%~y8NTkAQNC7`Oyuv%o4Vt#fES|dN6lqDWXJT`3zg{VTc zr~W>;23?GkQ#1MEy)V;DGP;yHKm{+5jjh>;RLd}_BAau0IjvW#VNL5J8;7hYg&Vx# z@~W|*VTe`2W9-K=v9n`Ca6brz>0l8S&yd(I5Whd3HthYV+R)Be8_dyd#D4fA)1%jr z06|t!@m6k;*bvh92_BJRctE@Ek^zhV!P}LU$>MlpnZlgLaMi+#4q`zGRiW~-=fF}| zHAwAZJCFp(*mB(r?9u410RoLyI1#6d)Y0Van1>o|$BvLC+xcFw2B9}BJ*e-Hm?b+D zw=f!nhDe5{G}|?6#Q4-mMB@^;LXb=cs~HQTT`q1ZPK3WZWzfS6>BQYX)Q(B0``SvG zdm-b3FxA|`j1jD-Hw_0LTDTvj1|S2-E+znB(dH2QUnLI)a9}Raqr<3SeTr+ zgE$q24rvjD!XYllKhvwOF!uC$N<)nDFb;5{E`YrDsVl)KE`~`G?(^>Pga2~hq?ExJ zFv^V!(pASmZ#2Qn3sR~{MTx4iI2tf?q4EbXm|I1g_TOI+KW!kJEpYMxMsLUWLx|M? zEo8tju_L6B5Dc@*{U0Y(Xz>gu_e&mai9FqyKVQ}QLKvl9kQ2-Eoi4(Dwor^Xh5PCs z{g#bbWmGXnwis-Fa_whHK<6?WR4lH+(MJC)j?yLc6T%hsp9;P*3r^7dEmKOKr2$k5 z`%3QDQ5x7Gdjmg0{0PZvL(+qLLoSF|%zY&$|G)$bVn3^-+=|hUZf0;SI-;wn4_bwR zvwD;Tuep*`Ov)XUFV--Pm&8e8Bp%iqt6j`FX7{F-IB7dg08Y4Nb<>2PPrWXQqZz&? zR8JG}*EGp&n7UU&OVngRk3EM(@2Qk~sY+o)r51y3Fl$qcefCKW`g{lwT^kW#OWNnG zcr`9p8`t6ZUhQlTq&6c*$0tETvQgyFsLI0%~g$l22Q+l;84`ovxIbW zA1u?`RL-ZC%guPS3#xGGOQQ3F&RftPdc_}A%-3|IcpVCau1fAE)W zr++-Ha?VQV7R1A*&B#KITpXED?-Mi@VN^2GrO5{cEO z&U^1wP$#2Cy7X_G-a&=TKA$Sf#~n9z;2;rJsHv zOe3>*Z|_T-#E`J9>XcjN(1i9JK$0$Y|hzL;f4nk)8fg? zuLCzEEHK(D#>PB}9dkqj1aJT)aAne5_;^O9J%F=9ShLCx9qEQWRC_=_GY%|UjOD(& z6IUb~NR8rA;1C|reqwJb3^D&o{^Kuv{VSX~OynZ`Ur8=g$}JB0m2k93{P?T$#|L|I z`xRVJBdBnCFN>r{Uu`xe=r6tbiucPEbP=?+s2v8n4gVD_rxyx)Vz45Hr%%7fXG6sb zw5l4rVn#y%oUV9=pT~(?e6-FB1mzyyQw6Bf$p9)y5fBK#8Mc9GW85#egi#-ie^v5m zS2s$3URGMxFXd;5y7o-QI#(I$$p_-VaC;7Z*_j3VoSlUHz>BB6Wb%-zy16j(3GE?L z8p?I>VlUlD8S*jX?zPAx7%4E(KI7+F)5(j3pBWOvHf^sBng$^x74Rg%y^)^`a#DDG zG%ts3B;{ZJ_#{c40lx3%I9O;$GClXu0F6n@K0pt!EB(7ltTDggL9{2JTWMxkA<+_u z9#%sTNo)3(Dr#SjD>H_TMbMP*e@yB#$&H`en6`oTX%L}Cl2V0fS!>WDcags#UfmQ? zUe0QT<O#2Sf@u0lFQp5 zCMzv>MoMauv|?M2QSpC*5Anjp19fIBBN z1V+iT=qyNJ&nSKoCRP=l8w5W5md9!glXa`!2xXqCgoiui3o6#fTvU2|DEA=wGBYIJ ziVRArKO&;-c3D@WSe_mU_6#m6`kZP)3+m0@_g2S`wJu7Tj3#yB_TE#Qnw?6=eq3bS zAV3?$Z6nA|$&KN4Q}m>uE#gD*N=vY=tbQIy&$&Bse#xRf*4bPMQMfK%M=cS&d=^*M z18_q73OMem;9`r?h6>aO2$f+4qDIYQF2V*d{h-;t2ZI1%3c>(KO+)Y)0tnm+W3ici z7A2GW0|>uuSD**|1k^QTUN2G#Dc%_611?U@B4JEkOT*13B4kaN*kjw)+vr(t{K4{* zu9JX%x##DI<+8A^g8c1MeLXlP8kWO}e6AXI8Hl^4jR%aYN9W;S9Ukgw%H+xpKje z3Nc5OnXD}sW8U(jhUVdR$S#MxCNg8;(zQw<#kZsMlI<)NXWTXLi>$68iWh7F9f+Rv z9b(#ZkfNlnxfM7~vwAE6o+>Em*YL%e0oY~M^pstR4zt)WN2YmEC~&20A#O5*fh+GY z*ariEUkKrXb{MZPO=Sri*FFr|U}9g$sKGF*Wyepa;klSnOt8loRZ-MC7B~zUbg!2F z);L%Z%f2>sm4ZVw&=YxAm0xf|CwKP`J;#!B7Ayb%rHzY!CL!!xZ;%wbnn>`x0A z3^>{w^BgM0BX1M)7`6`GP`7n)A1nD*P2U^A?Th;-1|p_0jWD`oUQGD8jwAH!@6JV1 ztn&KjFlz3K{-6M&!ktHo{3X}vA8%%o-%_wyGWcQPU*cIK9x^;zx8_WT4A0u+oePHy z@y~QUHe^`x(vi@RA^J(zONI<9I~_R~GQ?l$dgelgXUTi#Vj)B1J6(?o8Mgd%q@j@E zv-RbS2^pRh7w14ihWI;OKM^wQ>~tg`WQhEv>+>MP*P~l2;vmD9)X9W0^q- zI-+Nk+DF6lbPOPMQ=SdKmh@Ef|G!Ytk%QCTf3&;p#yw81H&tH4Wg5)p3o0#{k7|iL z@hqfgnivcb5pYb6GqDR!L5DE1UC>`{;KCEHF)xdZB#QdkooAPHg=(D*?5z+%>)+M#sgrUk?Q2I1aP zE6pq&&EvWclL6I7<0<+L?M1UDpVi5ls;x=iKg9q~?YUp@aJ{LAs)dWh524Yz2o?0< zHHezS=WDC5+YmL*34H@dYrTbI#EDly!yM8sBO}B}9erz=u=R)d=acwhPu~_eS9m;| zjaA7Hy>)-B;nV&9RSZ4*j~)61<aDVmlVC$=+(Uz(Zo*A2 z6(R0XB)U;X7GSzaD6*e@5;wNxQ7A>On#I^n-=oWGyMbCZd{8Nhx2+M8y~*->cJmXRhN(1`;f3K!d;tTf%?PIu&dNZpmsWPD3V?CeLX@I)lARH6UHY7a%jl&2Pvsf7( z?S9Z!KyqJxY8b^G{M)$xBFp1TTDYzk6n6~Q|6!Z|{LuW1Ejk`+RS&F>}xIdbRE<|N@L9M)&5Z@Hf{;TLk6$VYf_q^twu9aLdV z;DR{iYccFZ3=j3WP*(*#vnaVxB#NOGOphqem+kz6;>p5192}Fg(ywsB-W&GB$V#uh z>+kS(ngUI~j3b4~O>IA@2*?o&k=d-Kf^u#awwM@`#ig{4f%#5&wKPnR_31VtA%^S7r5zP>l{zE!lpDSfhkbNH}lTtM2ooZ0o$%M=4VE zn(cDF20k{NG{;8P)ecqK<%+~Qg`ju1>JfnqBRR{G_|OR`s~cJq($kH|x7@u3j6#JB zl*_KFbL8oj7h2inHRz~={5%cIKd2>>PK@Jfgabmsho=AB*}ZoVU3(@)ZVv3b4Cj@0 zTSm>pEC1-jW&xw;+l-a~Q;Zwc3=1ZNk>k_a(V-tzM%4HIP=UA={I2_8o@p+*`RO@e zyb=36n`Z>!{&+cce>WO965TdW32$ct`rSYHW!}aq5ZYXs#}m%=M&01#&J~hbPX)I< zN?cdioJjaI{u{n<4oPr4NyTv@moh9hA9g0rTJ9zrAxHTIin zOXs=JQR19r0?$GiT|x;mKOO$3BbvR%(Lr}qVK@weXA0%@*mtx6i3&x}(=k(P3PD|)4umHga(0QrD^)|N>hLN0E>cb2_2ml?4Zj#d&I%zR zSjI{}b%}F?5fn8f*c&Z(h4@uhKy_Y~YNn~e<%!lybmuZaC!%74GH8@Hi+_)X?V_b_&8S(jkrn(-&8?s?am0|iB9~YoVT90Yi(}(HQF?44 zV8Rqit{njX9E0Ms>ds>3;Ac`(6}tS<(2ZipIHpUR6G!tW8&{rU&LfVp+$BE`I#5rWw1zt{|PYnmd;)}ey<^57X(p6pltr= zc%XbBin@p3rX^~b&*0@jTEk;E8;)$oX8P2QOI|$3sW(-Jkb)u zFtZ13DKde9V@V(@+;Dy=_#!ZUUNPn)7aou}vILXy#}vj=QG@!fD&S29M!%I{lQg%@ z_gvtP2C~b*(J=73IS{Rw8t>5TA%r-OY%-d^@J(0YyTnsA{>9!KjSgBjh|BQ+l>jyyWI8$5p$mv|f6RmQH8Fp8-H> zBeW8@lw)#LCt99=TKjPA%OnUvnG}e_1k8ZqP2Ok4dB>AO)iTHCOg?xiQB8-b98>>% zVRAv~yAk-?1q<1o|GBD81_9Poo0I5~TEybm^Z#jqSyrGKCB~)I+^weMIY*6k&|(iJ zXp{)_2PC1z26wrfTT`~$@rB2$rK!ys`j_CS%@BV1YcUdA_Yl3RMt-!hXgohd94opE z@FA*C&n*`NJ$zkB|EUxWrE_|K^RN{oH>wEqe6Gg95f}9E(bZs-scy_TGD|eL6_`ph zAllqVm8mzf0b1Pv8Pqg4O%=_aaw_Jy!`1>t34B=O5s=sv!wFtD#d21_HdRVA`D8|2 z0^kIA6N9A-eIOir)a{#pPA%&T_nug@aL!H&H0m&t-92dh9i>`-wVesn+%cNH`AMxT;+DwgV=A}Oo5D$x$$ce%XAf%2{}N-ynai6; zJsFLsiv2o~ST#Vm&i!z4T~QcMH)tFh(Fg~S5e3%T-h+g7mtY)*GJQbCCmJ;8XxQ(hsYMBAu~E$tN0v&}`VVfd|lxK=iKb&Bo0B^t-7ZIM#7)Z22$N6$e2eME29x z8iNpR`b?O8i5RZ-YvlBg>X*?n-)^%{*>C zCej#--ebw|SpAzWyHQI;b^ zeah@IFv~TyHK(6{=*nISt}Vtolu;%zlqR~d`k8Kz)qMXp?Y$4M+Yazmb9-AvmA9olv}rTNvkogot@GFA3zI$;u-O#uzlmCRc#Fr{__QQxrFp*BRQ<~z z(9RfRAn$y+mIU=lOMc^jfV_7vA0|ne5Mw7;iYAHZvxz}e_`)0+E|LzWj61bm^x%yc zEL(@s3=0m82gt63^}`S};SNvqN*ZH(yUtEEx0wlo0deR=w2yp=YH=oVR`r)g%eRR3 z+6`*)HuJJVYC;49XO;*e>(c{->A;;pyWHXNtA2r`$jxw-%Jr5K#BQDDhBg$e;W7Mf z^1`w-HdmX(AcuS9wFLV8Xsn)%8$YNio8O2~M6Pw0$#VB3ISGN5&iC^QaHY&5q$plq zBJQIqF^MWOQ>-410Gs(b(2+oMpxb=+P?TpE#@UjvY-?XEML`*v9glCJ!m2X`S>&!T z6`!YAS{Q|}poDTi{ z_SCq`Vhl#p8}pY}O&rRs#;TiQA@+d={v@dsfshY3kBy*j1W2;lx;d^4wP8>lOX%DDSaY&KfM+=l z&3>B(@CmMUiIY#|MFUeknduhR?u-OBF+&q!bM3>RW;`%82_0-MUU+Pth-A|q&IfYx zC4(ZsW`LVyX`0Di;!bv}xLp@O)BGo$9x!$4drg@G7=Z3bw-#5|eYD_gOcwW}c4NBi z)>CXX_M%Nv1U|cm4|H!--G1;ky6RI89_w%YE7H&qB3CP%39D~OHskSbR^#Og{OY=1 zw^&$5{7&^V z1dzC~+F(PJBMvyJ{#+vF4E3jp(i74jB05a@Qg*=Clwqv|BW3luJ?I%gycil0%RUZS z`O`)yIouww+d!h9=xlr-Uj2-*?72r4F^PZ*+mWv=lP6d*Vo^*Q)+K$dFG>rb56+4` z5GN@^tdLFdOz9fl7N*!BGByyewf#Cs5HAc>2(<_3ViMKKf+q(~3{TyI zvd!Ao<<8THlrV}Z{MUcJWDF(j;7{Avh%h52*_7kE=N@(|#&0}ON)KIaaNL{OIhDb= z-^=I5hr75h@gPhm6!840eYU4wL;|+EX6naVd1XK zQx@rDmuxU$l}^ZIOkxjGz(GfFO;N0Yg6sHF82vto2SMvv6buKNNZ9GH5vf@#BzPW9 z5~*R8Q?Y#NoY4Roaxe<@loRV>C`MaQk`qg24ltjnw}_P0o$!bEQ7pdA^xVCR)OiLJCtlt; z;XoGLKOm>sR5=jJBh;956eU|fG9=GoEb`TloNva-$07Y?;qJ#zFE`lmp$-(0i2b{6 zNrw_zaa~v(R8*225jSc!=KvQd zC^_~*ti#Cj5W-#X_zSfZ0Xa$hMV@IU|L7u0}Z8&abZ z_eJcZbly$4vD@Vy9-sETQk~tGgk{EPJf&H@UDXi(QR&|JU#@PM_oQMk-lfB&w4DT& z30wM}8k^oh=nB+DQ<+W-fa<+Y_y}=?5&v{q`lSP*TuKjjm zNtuEVJfBltmwzPI9-W(>#!I1_NHmrJ{<=-Wb-*rRix?jG{*&`SqM-O6?Q;_v5h(d-Q)Z)I*g|} zoWX#QD-v@OqoBp}IEz6L*s8~`m$9z$%F3uE5s|Z8nLkfZ`zc!Gc)&8^07o6!-k%+ z$T*uSiJBT;YA93~tfaA;KJ9jM#+S--!KNUW3T~q5pMImAo_ZvD|fbU8x{O9H^gNfu`Al< zJBL!wbe=$fxrZ~LJ$jHsGzuFH6QvSMuj@6FrV*8`w0=K@)Q7|e#s3ik+Us=eHPNT; z0OYW(9h^<9ba#6v3N3`sV@ggWSRxW56qcpraBR zAqSVfv}=Zk#RVuQ%%+;XTZWVT6zpHmWRpNGJ8r*yWat7ZyquF!XPp+{eo!{8TW1as zN<)am}s`#mxm?jNu|oW&)i^+}-?S7O@9+zfGy6>sGjVWH0ZCmNP!P8ZbhaC=^WYV{y>5b9Ge^f!2O0ioWH<33b1UX}Y2S!$zSYRrAX*|%g3^`&3?_W^@O8;WHp`HLD zgNd8uB?Dz$&+$M+p}M-4LY}}H&nKiJR6EE&5zI)OV0<4ival2adLfts3=HZ(7yLsj z@kmH~u!;*h1@T^I-Mz}dMJ{V&DUd#Old6^tS%+SnmIC(}Zg#3M8D^?kJN*R$>(xZz+8Mwq@^%guZS;~Ztia~ToMSUs z7G73U)YzhfnZ#frgd?S4(6m2^z>J`!|Yvi}vtH ziUQ%#{3PKTVlA{QEz~}MX94%&T1yHG-iZ^9X8CqVSyod4q#`PyR5%5^lFDmR)*Qu* zP(bnn1;*rxRW;Bcne=BPSXZV~O`cex>Ta^Y1nxvIcX97^3lSiQAt!1zbn9{p(8)DxzsUj!PGC-!#cP9p zZ{cUEp*%RYNvM{3S9ApKXbu^b?r7z-^6t%*cDIo^3a;5}C$-}!ai^LUnFPR5hM-)7 z!BS3fyyJq0t_M)G$aia!;^ry>?+;O|k|d-WJFm(3zgkHJFzt$-{ya#Uy<`75|0i5I zhrnN?4!djIZD4IUR$~8~^M(blwoue~87cw#mjz(#Ad;Vv#3GCPEQBpeXjuR95x?+{ z3U5<{?Q2nR+yCHtVh9drqj$*Xmt(p0wjHNC-eu&RE1;8qBQeEx|I4G6e^jxr1jKQC zRu>DC`nuhsFiPRhCY(h{g99gWa055(?Am$+7jE-ttosSBhcOm~4p$<==8morYFFi_J zTjcF$(3_wrtEENS!2E8Rz~e1W`~5eolF+c2zJs?(ACrA>ey4Ao|9_x&5Z&sMjeE7^ ze)PG6Y)S_<-d0}ZVf=d~H5l@_`oD*WG!~OxlQcGes53ih9u0ZFq-~rNL1QykgI~uf zV=Y_PbEI=_;Xnw+u>{HS)P*m?9?B*3BVy)TxJ}nq;!%uZ?uE-D%Dd$}Ho%CS-Y;I> z{4*AgA7p^ib>U8|!}!FwXyE|YrDaHHv9S5UL#bh`h9_A*Tpb6VzZ~0?U1&xavne82 zM4A8^08v1$zZ7Mi&^(E=$gAsFCZp5gowPoUU7Ng!UCQ^+t9BaQSlrMp<7itz&6-rx zOh&nq;Ej>6=$QLdXP`pQ*JEx%9`$$m$SGFu}{UR`O*6BO@bPMaaTSbK;XqN z-*q(@8Pu|IXn}-`L{h*D&m<*<6KdlruO)SXg1CY{Ie^2mVshF`)l0j1f#!scfS901 zLDExQW7prVMySg^!k4dnrBstiaD$FVWM9W{qAU{)wz;&pWE_z*jm! zgUND%&r5}TGeB{`LxF`$k}nYdMFdO|YV-n_b5{AywxZH5uzSb%D*ExQ%bnwq&w>{3 zz$`t{xR2eYxNw~swvrTQMivvvv&nb|*hdwb<@cLegOr}+osuvM$2 z+@ex@ZD6DBk&AbFchzb){WWvQQl(Z5)p!cFxK;jAj=mk}!6}L>RA4c}7nA&E^~R?& zffcWCNW=Py^Ekw5!RyWf-#mhoY>%S|?wdbjlKiWobV6aK|!bH;q}UViJQtQ&XC%XF@4- zU0bnWi1%+#)OSVV#T%C2vOpS136U6Yr-tF&cPKUheAz3QLG6tM)EZ)~88IfH!pj~| zhgpoQaqlB(MD0ie5{^&q4VfBg-(=d(lu-OZ8e1qAV?JB`K}0=91kmv!&eK36nW#w3 z8(1m3AlR*vt?TG|YJIFVGop^P)C?Tur1lM1|Ao~@Avjg1mAyk&eq)fT5ilGd+3Wl= z0zEq>JIgC^8pWM$hUQ#PVEpp}H&9!n7hIk2LtLlYZgB&*nY79Rwkhgt(-TDw0FEKK ziCTijM-hNyMeTqC&3&kDCBuT(#NfoAPxH| zop8?~5Rq2b#{P?s5vf#Ua5b)V{qgiAB_|VW1lZs^z|^_i$@&$`@7RS{4j&H3aPXVf z!PN4(9AaK)lQFnH%fI}xmgUQ2<3F$sy{+30u{L>b(xpUhev|JDiRaRWE4K%{t3u#2 zX|tx)a8TRq3`V4LYD}45s#I# z)IkXv?d=?{PT>J~Q5ZW2n9i_)1$j8LuAHO2kTMQ%L=29~IciQEm*1=tR-l`j(dX_B zY)( zpX@W%RrhwU*`|Fm^)oQH#$`?QAdmYeqo=05;CG7@2+3$=6M;a$>C5L>{OHzKq02-j z5?%3<+^+&vTO3K9j42$fhj>nJplY`b%@M1!u7IMOx*K{c&5>RuFGUdmp?v-R!SXj0 z7JkMU#gtoR9yw$y+~#Z6+v5F%HBh^PjmJNtfuNe;y(y|wx`EaQh;OBjCpRDtS^RW? zy0d~x-6Y_n!J)LDi8!eub4vuOvm~R*emM%uG04{!Kf3A(+1+PpJ&O83&G#`90q+)4 z6Ovi0I;Ydc6uk3RkkuXiU=md^0q(`(VFRejeei#%NS3HPIX2jh&{}VMH+kFl`V~*= zGQp|5EXRwY+>V*1@}ifuCV@0;G+a$qM^gfcbG`PR9PXyL4gXJ%S$K z7-v!tg|V}A9a@Le0^}7nQu9+v(@Jq$2%_2O%bf=vfJ-*vA;BnYM1N9AJ*y`o3x_MC zpW2oi^{*W}15U{J(xBo+O_VCPZx2ZjsX#_)g4W@XC22_X+;c(Zj0+wvpWWOg& zz3Mwznp+JF*KGxD^w|PKo@bk2DnkTWi3!gEb}k*^uD;N(L;t-_sUfpb=KyeC>_v&d z8(m%&8fbrkxb7!CB>LV0_tvSaBm@(}FBp9E5c}3VU6j$`#JD%)a3K_vWuDKvCg%gK zVk|2+wG3tJOkqfiEqx~uZ5uf0g{BpG;B-m_j}Pmh8@>qKEVm;~(+y06rxo%EAh;Hu zMZAxkDYZzPwHYjahV!afzJ1bB`qprj+mOmRo2{LQ>r0MsU@+(6RuIucONT$YCEe6S z3mo?}tV1~aqRDP;=i2D48xROU@!R9rlYSFHG~Hh+)9jgr5*grJR&}=U-MldgW>RUD zhmS_O-ve~8Ef)q;-MhLe=s^RiZpe<BTjzdHe=3vp;QCrS2H#p_dGk?Z2OT{8N-uQeKTeS4R%{$^`uG^KBt%9IxUmM!d z$#fmbjv^L0U^E(>m}3E*B35wQZ{h`RAFzE8miFtx5@R9F63s4u2FqNQw(A_V<01di zucE_vHd;bF0IGa993;QiMi*aAzF8OP>#AvL2O|gc<0vQ~;EWJ)yiZ~Xd7|72x^WJ_ zO)H#vyPJ+cxS0({jNW_*8jASjlKv>B2^zIU55(x|pcPm|J!!IUk-)&64p<^X7UR!l zu60mBgEJP=(wE?X2zk%}IAf@upr^A^PkHna!L7P_7K9p!L(INj-I_74n#r0p9+j4t z3!F1UpwszWYmgEZfnSc&v%z>usJZqWP~ef<$GN)h(i*TJFAaJ1G|87kTH20en0Rh-cHOm}A9(9Y&Fs%6UK@8Wp9V2E^csB$lrm#C@98anEQ?xk9EgcAqTei!c z*W?%Jx7|&)7o-2*3mU)NWE=}!j^~hWKV5(nZ5UsuZFGoNFC`MpQhvDM%$(0atfQw{ ziNi=2euJdo7Rfgb-3EkShxzZT&g^CUOG^((7;8vzEvSr)IlkGXD)S|41(U51bj4?7 zH+kaEv{fQp7PPbz$;4u7%onaeaIX?YQn1rV;y!oCwSq1$AV{!WOInv86%L(At#b8; zchr&)Y#=s--Ap!O(*Nb@@7ea>!if{9(s2J)?r^DIMmGLSshG!c%fLp; z-ryJ`t=B-f1xHbedawp)HpVJWbYm;i!-F#EJ;JZbI<{ig)FzA-1z=?l^&Ae`0_K^d zj>6fjry@AqI#}*_gd0fGy`ho+&_SNU6LTR6IM5s0TrDJGxI&Mn7!a7~z+<}l0h9SA zkquU4fJTqn#LMZb+9B5odcfQ}D4U40)2uh8MgRS4LtTWbL@#~ibP*5T{Ok3N8KAFf z)5-RlHO?#CEG$dsJcVIKVpwryzSUM^K0!QSO;%^=o$I>GI@hJ zS^w#2y>84T&OPVbBC2t6`=`;v5KAEIXcp_CXMnL4Rt$k3Vkq&-B1PQ8SVwWqC%B&k z&gr?5|Ke|d$cNfWtw11*QJMMq;PGvv0t6gk&V*dPy|hsQ5uC4ZvLP2Y^Lc!*r4uHa zIFn{IrccGfM2?m9dlXHafv$?rDmjb#R^df)Vv{``7UNvIfw3vM@IOr3JY(wm4ryCb z2Ks%$Ad3HtAeu!=fd)9jhSI|RrOmj}SC5q;x)Vy{+v!gQp)Jpx0lfmRF`Z?qH0#E*jcR31A_#K(BtJD-m`hUV@d8WGiW+VFWEUcd+Yq}0h0U-Uk>_p4*p6$M#UYo>B|t(e`uguNDIJ|fH-3Zu(lJYZ*M5xZmiU26 zSWGrqQ`*L6hnM4suFALVv--MR}|% z=K~N*2a!;Ivn{7z3({M$4(ZrcgmQofIVE7FHiR#kqHqd9Kd)4B5Eqtcjs7!0=xV2k z_<;sk`=9C6PRBnUdW+0SCd7u`J^#`7=M8t_|3>jr=<+Z1UC?e2ZbD#Zf0Qx;MEU}t zAt(ian-&hjxfeRw9B9;!Q2!Xcy>6D5LGc)nAwK6c{N`ljYe5ZyL2Ce$pyr!mB$84N zkXEfeMS9YJHjiY;xMe!X79QS{I;h=P0K!&aS}=I`3WQiW2q`X|OJ6gAofr$NdG#~= zqB#Jvx{PnmI$L>?EHHK1+4&JI>{V6GvizVf`QKg>7h{a1i?zUlk(!^YW+p;>txvv_ zEJ7)fb~9;!JQe8ZY_3}A+mYlCmOY({Tylr4T%}e*bQzrxci}FIDZ-+l>zTaV!ILP#_Of8eLqchb`(GKo$xgt>#)5Z3EZoWeoccv>R!jK-KzPeg zNmyeAu)x>4%oQ0{%RI@Avw0R)KV6*9ULR+UcgJjWd#Kn5hKCceMdRs60$Iz=_>sP8 zWn)ZBsWG-iDj!$Fo`f13FT;mjFvyf*FX4yJybCWSS-MMa48AW*ZceN{l=&MPt9FegeGhb7dui%(Sn?(>);}Bz+&TvlbfzJ^rFBh?zNq zb%PC(?jJ5Hc8!0bmuu~LELd}f&z?{^0Ds?`Iy-TU$=mLs&p5`J`3D{yIuF;ZV-8$D zJ_79`Sw=V!dPkX?bl^M!4+(aDyAh_C(xj3EG8BZ)$*rw1n<(w(Dkh>%2Hnh2CNzXb zIEbygrK5xRA>6vC>Pr;ozMx{!;uNO3zyEC-viUXjw=C>-cD))A?@uWwu6D7M%;R%N zdSdkVv9#w~iphil(wxOIoz1$5rR|*W%+gI8l!Ajms8ROVjv(?sBoUX1#bd}GE@!My zQNJ^kfVdz&U#2$3u@cQXB?@Sug3~XnareRwRm9Qw2#>N)9H>pMC%ufO`bK=%b#WnX zs$P@yoU{ASfayI)BGHt%piFA9)RNIWzVdYknh&x9JS&KQg#N{BzK_9s>(PM$R=nn@Vz$1@dIB7nbpIb`ad@#9WS3wxO;e#P*Inp088{ za?VspG_g|BwGBO2uNrzBs>n0Y8ewWaRAn77Uw94`m@npNz6Kki$}cZ8brub1Au1)GI%!S=!L5;Z zD6ei=OSfjBy9q$zb9L?@_In0cJ}tx>5N!NItuzoq*eKJk=4TVNhMGM5#GZf$13h&u zH6T9q@@ua`BSSK7pSu^F7gs8@)8*i(>y#EUNRpV9G>NKz$e>HF6U14=@@v3m;Tc+S zc&5$ahGIKAv7;_P-q-bZmHlqr{(|NcUD!@O5`gmcI zWY@L315iHRt1Hy)oWM>qA#ndj7jVOW086KKTlsJjCl|$km|;qqOk9xDnr;V8FHdS< zu(bx^WoYrq=c6Mpmvpjb$J9-+AlyABTqU&s#ya?E1ExhSa&uBz_rfo&Dl&4vtqzqpwM zVL^P6l7U2bTv|98K9fj}DcL6F!c0%HhgdR@ko}2+#a2oX_ErSDq=Y?dbTMS&DWQ)A zR;xuOn-=`>xZ3iry)}wDA$n7?-ni^0Z17d?hP-WQOcx<+ z$ydd`n*J#am8h^slxpZxRIQ(QDcdqnwF+iW;HMLrf8q?i7!9tJs07WEPa}lB{4=Ow zLiXfzqDE?7`ghy)`Zfe6~wylAL_ovSC4EjWPVq ze%P7wke~0%6)@36#4%w()8tvB^%>tD%YKv)R^mCR;svKInE=V(mXiONuY5^az88Fo zj8G)SGUz08C{mt$08~i-EXJh2?RSi6BwlB=UxwIpsFp84aUgS&cij&7XUgr138-y~7Nh!7$u;A+Y|rY5ZW(1$2MCAnFs?1{xgc|=GS`jvmp!GtXD1v~ zytUwPdXaix1$-5_`Hq@l!sPLA?N5H2uyduXFNKyWmmIof9*!!3qR&s#HXhpT@t#}q zlfAN_K0p0Xi7Gaz#@c+=DhXa_NxYFh_S;@!IHQ3(eDC`?LlhcBZ+r8W{C_>9{%CUhgDU4bv-+EP@(dQ^iwt&1?Ld_ z)WmRHAw*P5YCwP#J*(20sPin?I}&#f$9)IU-jQfCUfnekK7f+@X{O0ct0rGyCEHXZe%n zMr~x+)TdhqD++%}KWl@b;yC-i+CggRqp4>-WvQG)9-raKg%t%Uqa9RL`D)RV_?z#d zIoaSMuvY=_>}(4!Toc25(s6S@I9Ma9V14QM25ufwtK@SZRux}`a_eDPkaA=A;zp={ z-hi-TTAhGNl%`#Rp8j^+$NnBM;jSWPtzcOh!B0@diyD(M!DCAL|jRe;dj8D+1 zDUue6b@~vXR+a+oFXYYg+%MkdaXz?76SGG%{l5LHL`N+`-hgumB?(KgRn zif(l4nIt!YTj4MOL>3A2O;J2e{i+;&2(L&7>2B`l!3ar>`{F+c%sh8m@IY%R82R-y z0cVCg(k%R`=(m6A{p8@G!xaG>v9r!ua~u+u$TmC zxg{$zxU*U6W}j7UnjCZT^fs=~RK;tt#&4$-o_m}58@UmVWfUWKum~~^aoH7FCk%1` zJ$%NhTXOj z$yt9sFvUGO^T3AeuWALepT9e@qM10bW5y7ewM0q*JS1X9if7hHwZ{$5&ga#(c4HS5 zGvO&86f?6@_k4xm-Z5B~#-ReQ*VUec=!+KQ#wfOm1YtU>HBfUZ^PA$TM4VKfqAo+~ zm_iFUj51xzD`m84@$HbbJ6}l@^lT<1G(n$h32C4jzn_>E3x|IMNf*tPJ&d7Y|6%!` zlO5A^P?A6Hhm9t}W%v|eh&9`zK`=SnpJ~(bu^Eg}Q(nBl9pEVEgUVlGOj7&FN zdbLIsTLhX;6e19fcuveG^%6(tV78o)rI=1L@u2VN@{Woo=eo70V>Dkv=-QR$vvTuJ zNi;MO8<@(P;_51wHYiYH>0+y(r6w<$S$}9iS1Bi}@-l>CpFxM|osJ~AtDO?1=*CVB z0?d**Nj{RJRD;GE&vI^>`GUX+&3h&PyaZi+2_D-l)iT6mHge59Q!#d2^Et0g)%W2mW^wA6!>(gqPFtS~ zEp20n`u?WNRxas3KX_qfY%B#v+JIQWMFd?-13$uNi>H#N9*x#@_qqg|`MK6L^%4e2 z`O9WVSTFKs4dD=@z#2h$0Wo1yCrcW&&hS^Q1QUg=rr<#05nfYxs3>3U&W?$hMn`Wp{RZVRDSCM!UtS*+K}+K;I#+@1-Mkr7s$#b@k!Ia6N#E1|~r{@T>EEP48<&)iZFGMW>xmI>L$e z#~#ZbtjDu9N*No9BRWa_5ULwFvfy1cYxLl3vR$F)69G|gus(;45^+dmVdlXD$hjZ( zKr{gJ%}zh9wFf&&m_i11dzX@4!1|^uWzr$5n3~C>gENf zQfTt)9p{my1onBI&w8V`fSp4v%E`B18u*_#Jx&o`0#5%XHcO@Li}2_4@@lrs5|ib4 z8aK>rOL5oA*yGsI%~IZUFL#C-500DppQaM3WHB$((YOMjTeL9dm&QLpMQ9T%_2JVQ zO%>cpbGfvvF`qmwUQaSg!VBl({hv2AElP@d{hyx#+)HD(f%(6MwJPlYZX{*4xBnR2 z@AUYWmT|KvSLOFA2~rs291MaQO{>I)UY2e>g#*k%RaDvjRqe`Q>7LhAgLddp(RxrR zi1eP#{r&7vLOL@IkPtD|uXS`B*#B&vqa>HfHjh~Lk8WZckK)X!xiR(W;mVCeBeRYt z;ln6Y=dYJ9^r;L5eaT0*R_cz;*J6A}4}_?rGaS}~g4BI6$MuGazad{e1a>iQz6R_( zMwj7txDgo*22z%BCvt(O_V9Y6#r)?%Rl1or4*D=``$8D}{aB+81si{2LtD46O&%d^ z=w4R3_NMK6Q}9-Ke9o_z5RIVD?)Mp*C}Rk`8vA2K@(BEGv8gJ$HBgXPfilk=` zQ=h!C6nG3QHvZb6B7p~;Wqk>Nv0l`{gkBVM62`S!{fLi~w!2FJg~6 zu{yCpxjbA-os6GgyS+0ooSq=|rL-4`fzcK@xEyF7wB`@Q?uzMs>DwCdUhbkvf6EQ_ zDza3^smJjd7=EW|OHW7W^3;*iyjG%y6~D@hh40Q0{;E<~eAxr7zhX;1N5Uf$ff~(| z$jo6?;-oG>l%A4nNGUMw-AVU^W7=4hbm%_`B*FqJ4Q_i-5EzCfH=Ur+4 zUG1G%8hH#MIS?ZtvQBWgBf+Ap3p|^W-aDfHUbP<3vz^*3d+Z3|=q%Bus6)qmjg zC-Zt(I<^Wo9_mFxT4qOr%8!kS7bAbaaiY6ARMrp*-GHH z`T`W1xk>m=$kBZ-grRvOW%3Dw)BLrDqko37q!)~=kSkNjdrPPN7z!eP(SqdglEmh}psfni8=)QX6&IjQSZ-v_8ax*`aC1Y>Fbof8164!1iIqShyjD5HLX}ly-+5~_NL{x0E>^~KP#+p-oX=Bt z>qX(O-4jyCjOt=oo@`6WpsS*Jhz#mWyn+^hpFOTmU@!09flOWqPi(bbYwxXFuI`>? z(AI2>-(9whueI+*%nw3jZ_7(kE&HU};mjb*c8xLGYm$v$mbC7UMQ5Ml*%=wZpWsm2 zTfr%qV}?(YNGj5ZDhTtXaSnacMMSb<@yZ9w0d@|1 z21hO_Dmr1|aJcfh5HgW{L$o3hTrv~B_n9d)HRVfS6$x}u$*qOW+btP{uDN;He zd0TUz^`G6f8i_Q$sg&~kks_t}07vQ>Ih$nF?J&GlV9N8-{KY7n-P?ikn}_1M+nR-e z=E=4!``GN8tE<^r%kIxwvwOq?-iEXdc$6t=UPT1IgcK%rvupv}%5x6voi>xA2(oEV z!f284ydC=ZWYs)QH?_BvCF8M>+4cw-$I7y+SmEEe- zB7fypQwe~@@+MZ%tn~J>3_85h*>a0bMROANdND^tC%cu`XR=y08l5Yemf-J^6e-0} zBB@Q}OQLa_?bf;v!MYF(%*OGOxGPu0i6``eQ3B1@Eao@iKCjQ~CYODqktb^8Ngp{fsTrkv?^tN>um(#HX$$0NB8n%Fk=~i-Flcw$gW)xAMX#|d zH|<6V$hjI$n0Qj~8amZX^&rE*1`E#t)a)jkU*pU>5HoXlB7kb#V zZF-zsAYwCQ!-C7588%sLNEniOAc?Z5Y+s#AjshPTV_1=hryJDw_=XGw_8CPcK|j zy)#=WT!91iGpcw}6Xu`wEbv{gg?pai`f=(J_M}hCVFe&4ydDJ1zLCT+wD`Wz&oI|fwm*t zXH#+2y7?VQQ?>YMtEL^etXWUM6H8s9X@Hi8HB*~OLxcXvsll-;^kwJ3CA(bkW+~5B zh|AWpZGU#!G9j$nnNM%A@M7A;R*%aHCxW(VT~5$|6^b_f0;!^^IU}VQ%6RM$mgSHN zmfeWjDXY;0md#+sWikA(%;_mQMElBK=#(jcT0BK%CJ3S|prUZuSX3z{R=Q&1>a>h9 z#9OA~b<32V%95UbEBBV{#$nxU{YVAATG$8$qAwjZM)Dz_in7_ahxGW=!gW(u?d|vJ z{eVpMs+qEVw{B|vaa~Siw|{h}USJwkCE&}*^H{(^F>J#j8qpz4OooWrU*KrX19B`< z6tFaqZP2fo>Az_HC+Y*xv)o`;+c(sB&TC*n;)bp#ID0x(7D=|Ls>Php*WxB;GFZV5W(B5 z45*5d**8pX-Fdlee0t}H_;1FOGTKo)9 z1{)yrc;@z8bV7izq~T_D1-zCM;5s)3zgW8Cvx56XSk__SrR~%b==?iV&-wI`%~bI+ z;iSn-DG?b_?mMI?hBHrMv2|UO-YrdTf+M+j7M)3~d_JFVXJ^NTS#5ivZF`~D;rlVx zwac2kds6MYwhdQmWP_KqEox`;>HDW|?Q^%6G`aXRu>ytdJvhgv#7!>`-?hK`ZLb1v zI}lFZrdF+^qqE|*eURxBw0(=#1PT;*2^6@=pF!Mc(WVv!_;JeYC5HF=DyO2kcoX>w z3$X*GY5g|=yd(b;({XL7*y{KnoET0GHYKfYQ9=7nKPZ2uF|=^cEtpXL@&A5r6A*{R!?fq1x!MDBg-)0sOQ(}PGoSAo-aO4t`*fNVVfob9-#GNKc%41=Uw% zt>;8qWeaM59^HsMUUbMoah-z}#7-(F&TDG#idWlve+_uA@)!8d=}UOr8Dq4Ry;|Bc z7YY8p?>qM1unGUka18VH$|Ghg^f69%RAl)swIrD5@hEDAcSGcrj-qUT!j}rQ@iqQ^0pjN_F^?Mmxe^J?eKO9oO69jNjwNsCcyG3^@ZLYx)o(BPCZAhZql$N zkYKCIfoveZOuccYktZlhe_?_B20+bok`W|$`vdv z7o9O|C1h1w)hPDTrD9SIaxO5%UhW(*fE$93GXs?>QoeqbqV$jXJsO36rXFxgNx--l-#vPF-(t*f=zTi@Pc98%S^K6x@@Oeaj_>`(p#!8;; zjuPn8DOKxIw=J+OJGQ`oHucBZ=EusX4~V!=<)usrKa~nZ-pW>L;$H_7lU9TmsPz?S zi??(HKjA<~9}7BS@4xVO-fOHj97ZXL_;7xKAzA(2opMK^x6N`V@=%y2RH!d0vM4*W z6`7W|nj-TVfRNE1JFpxSa7`0l7Uh=xSGkE1;)gkq5BZdcd`F60iq4~GU$U;~Eu3#6%JOdIc^+H#0i5Pi@?KmQ)(pHkniN3J-$@U|z;GrZr z50zTes(uHI=fF7ny| z!M0JV!&R#_WM*sc<3!<4JcPs4aFSr01jgs-OW_XH1Z%)p>*;5+RK9vAmx9QVPag0D zdgMWPIJKgx^kAYQ30Rj7XYFLe+bFrQKIDD6f}s9=qYOGhk}_zO8f8%8)4%C5=rn0% zR+qZ2jd*jHZ&kgy z@+mQ8`hY-5uGpt?U9Q-t-P+@decGjCVkhXGsiL$*SeKqsm=g4y`HLQ0UPa~xkPP`$ zh3Uj$Kv1%4^D9X7jYIypEx^l_MLjz39jl3Bs(EYBwPe<``fGc76GI*;DW(abyDbR zxmpl1-aC8&(9`W~i9Ul`yY~XmZNc~r=hF`0aYX18paLm4!mAuk2%j7rx=KSx3rhJx zDQd22zYf!Y)CKR89Vwp}UcX$n9re<-J~DXgtIka$B`Fhck{462Gqdmr{N<`5tqIX- z;r76Z3^WI-Y==>;B zDGX~I4t{Z&uMkcK_ke@*%8)M}Q9PC`k|y$-G1zl88iQO-eaNLmG@p78qh52_b|24jQQO(wOjmE z_b?1cXd3}dn<*kwf;?>-6mG>z)PKP|wwPNG(LwYlXV|slbaOx)!zsjBBOg}Kew+xm zaj)CXfqh_N7@bbsr-%JzK#ItH-31*Wc~O`XS-dRr;Si)dB#$Xrb98U6enqFm#Dl-) ziw?Y75-17^@EbDrtjykEZ<##mA!B7Lep9;vXe}--&W(HLp!1jy#Rxd%uuu;muX^V9 z+mo*u2J<+--L^8nmr--SZC?1E95gSaQcnbZ&(uP;iI;izgPHxy4IP2@tj*%C;VG{; zki}{u%P9i&B^6~zQEN>P2x(*lYaPkaK99cAgGL$#fhtafn&!sG&CO%>7@Q1Bh&lw7cQ|MF4q7A z9&4}1nu-iX@cT!k>&>`;vna2x^6 z>nQ*y#=XO+3RgIzPD7*6ge@F&BYY+XjWEquK27#9S}x9lZurvuQvP=T^Ya5F-++gv z`ONyT=^@?QqTxeGoI`k@&fs+Oy9>N3{K<+o#bt3Y%hDTHP)dIjc390_^`nTcy*yD5 zgU1Cm^UA9VaVbdZ7M2DUjh&U94imZB(rLhTbn0(^EK#~e8?f))*tQ)OuYr|;Ak)6H zyIb;YPj;CNw(X0pIThHhke6}pv?uZv&tK4(6{N+!n`c)3^Wwn z7dq(UmdkCku;FbBAY>0vK!^{keCcy>ktpQOfZZh-xFM9_&j6X8*tTxg_lkfMz{1Z2 zhwV$jyXGU0+ZH~W(ZyG_2XMQ)7BcEpNUm5q$5sj}Z3smhM? zW0j4e$}Y-_RrWCts)j;h?s2U)c+**0aCgs&`^ zYZf}gaj|p@7y*2dm*mqw?27B|=_l6RJ8W|B&{3*^2iG9S4%>P}VMnqq$SA;*`PYny zE7`3ZUxI_M_Ne4KtlwMl`wqdz1chk~`=)73Dhdatx$Mpwv1J0mge8yr{tXd5w08@c zxz*fFvP;Dq*4_7aeln&Qx%KY|?VE_Xw3VdtxC9dtG7mzQxa^q(n3gt?1~spWX~U0c zkO-1_o)08r+WShT;#?%eG^F>3NS%yVS}eMKszx%&S|o2^cU& zkX<~_<_IaKE$x8JI{bTJ&mQtJ|BNv2XKD{R2<28Jued6yZ@PN->M>0oh<&Mb21Cw* zF$+;{P4c46MCtsTvCGw7>YaSzeBVFQ12U%{rk?HnFAL~^3x^C;s8$FyBm^q%VviZQ z&`Yv^sn3>a(;*Dx)2{^EOk-A2t0t|;m>cB*!mi8?Yx%@nnVbek!UmHlM{bD|%3e%; zQoUcW-XTC9plyxBDK03|f`dws2W;7GdUu!Y(t$N(esjA`xn#h1ckl??%VVcpZBxMN zDYEqe5meeXdKaG&$X-aua?*k!5S&-K6B4KzP8mRiK=CY&8yif6*liWgBG5u5y_Hc@NIP9|GuI+QdXrtH5{$akg&v5X{uA7Q-dixUd5e z8;Tj@E*Ta(N_sLmJ;ZqS60UY+AwNBZ#=OJKZZ?yfQU>i>nrRMH2T*md~`3AltGpHZn!X%P}jLD+Xa$ zq_zrlVAlh8tKl(lJhoBt(P<>V9j7#eLgCQL&yPKn^2lHc#|3t8hC>*Jjl!S>!Y`vy z7+1dx^WJ26b0+4sd}~9CS9{YSWK+w35%r()4Fi&{RA`U0nVXVXA-kvYAYqb>1%dYDO8V^mwIPYo(ava}Keq-nM1dhr@Rl~ztt6QG>!q4Hpt`BHrgogoRt;SNXwaRN& zmVM+3ytrgCJaBOayp2KOCML$!1Rl>YJI)pj`hom`{EIypjQLb6B?c*wYXZU-*$GX` zR6qtw+y`Tj;QL9YB>+fk;@#MoAW>6Sw7wD*~V9^nrZJZYL%-N37f|~G@mB>8r zy!j?-x|4GrRNmaelTD{^dfJ)2Qc`}onYF#9YbkKIaA{&~TP|{EXJ=7mn4)sc4$H!Y zQ3DezldN(92w0i|f+dcnT+xUS=Y8-e+9ivBnN4ypHZr3n7%ktDNH5U#=Wc+{ z+E;=V6&+Y|(jeBC8xb^TQ>v;>ut@U=L2=6x0yJNQh?Ozwfng3bKL8`s%Y-e=pb#lx z_kG{D6g>DjlnZ6gG&+AU2(`wt!4o2{V-+eeR;QNra-MBVja!^s^6QP7C92%u3@YXK z1eERE*0g6h{N70CqLD*Ko!t{x>4~FKV5LftQlET@QMrah`+wC@p{_g{mhEp;;KRn4 z7}!?>!gO_!H0leZ0PGWefkoxtliJq%Ria>DE_*~y&7I11w-s1aE%tJZ49J-?++iZG zP~78T22J7>1c=a&4?cnd;9;sm4QMV1hdA$g=ViF>Hv)pLEEfq;f)0?OYhG?e*jFYYpQjt>IL~{A7h3Y-|J=%5v^#Pgs*#)J!m6*v{SnM~tI|-8a2nMST)Id;`ZEwX4 z3{mwPI2E`IB2)$X4?lu@cnClTAhr!=ivfBdG-!IT0X>n&hPitI4Lg2xWXPcg^gW%f z#&MPMQbhr<8$h2xaW2aG+Ne^aO4DV-tADO@^WH@PZv!q{^c(1le3bw*K+L}uMXvl& zD&o=?34i5UJ1jQc=t6L$36UZdxa#(Dp3Q-jLT$wIc$GvNC z?CYk@$nF4DRzY^agu4LFvm2HJTx+<;0;)j+(B>LgsFI40ViIH#^kD|QK}DED`Nr5@ z$llePGp(CfAI;}zUV*nX*?{JgO-5}(k&Q+9vG?*V+3@+KSXg>>a&S){Kr)mR!GHmS ztHfQ=kG$)a1Tr}aF`(OBM{Y?V75`I9Ub|b~opk%%&S2YUy0e>XzlM|WVJU}>CZE}N zk-hzxJg*_&k%PzJxWK|_VV3|UL`)(NNmA{{n#YhQeKvz%9LGVP@7?&WquBn*_D??B z^K7t{gciCpk5z;=cH=nN`n&P381*XHvxMFs`N$? zYS;(7GF;GgCI@>tccr1g7`bc@2B`~tHtUxsQ)W;xv$p6)HmL&LM2ceFARDNQ>lj3|5U zayiX6`vMA=ywE-kiA6nkq{d4WFPr*pHhezt78^h%Ql_Ouicm84N(NLHA~vE zS5XrKDET$244AH&l_gwfr*rEBA}^cSP;_|VQ4E0r*?};gl;VLKXx#!}$7CF~}F9ZhZ2~J};NMQQ}b{ zhnX62gEvL!GxK7%Kj2g3#0`r}b~gqhGrwR=oMu#jU*8nD<%o|5cnr7|P@>vyr7BFw za2Or$=)>b=`D)CT5jT@aQL-1;07oCKlrUg*BY`SI>%a_(*7(7d!;MruI_bL*SWY;q zamK$iKiF0?ofX|+(Z-_J|CrR=)A}|O^RHlHj@c9ym!JxUX1rrzh2*j^FWhmLJE6i% z+L18g2hmv*6|QhA64j(G6%X{3W|f^6uBeqDB8u`_z&j)kfqGhuoYQ>Q+ZZpL+xwE) z3(()(d$Svo0Ne%y9kW356ysKHUgHX#8@hnT12PcSWqJB&f2_6duyio*0Nc_;&OydJ zq=kCPZXS2R8kz3wq5a1oW}kin_=J0BwJRLKJ!MxA5Ws@KPtTV6&Ntm6IrvP$5Y!=j zfF7S&k9us~_tKDNOS=$-O5~JEzj3{U|u9t(#=g* zyX)hT#jnkjZA|`|1iwE%n1omV9VYFyq!*FxO%@o??_<6{z>i2P+tEuR^-sc!J1H_D zZP3Raxt3Bnh-0A8bK4wbCTdP3DtZtMkq#H5J{>)lGfRIes;)cZ9+4^iqbn?^($c<% zm4XcDMe^!_oJgG;1@z~F-UONymgoj)9BD-`w;k^^BKnNml`qjoGzgFaqgJ;Nqd0)q zxcPLh6?)R75_i2sChMhCT=|f1GyRX9VmS`07d@f;O`TR4DbdOIlzV=MG^X-bQf?lx zZk$84`n$L)noyNSp228}-~{yl6dc@n_FEwhCHzu8nv7x+i^EyGO5xkDi=d#&O+oByqN_1l@JSJu~hmg*}SS z8_xE)6Pp=8nprJ&P$huU;@2(x3uO0wI}WygQ;ZwM za!#lVrg9xay}e0q7t)yAc3^|q`@S67BsBK8_eA!}&i1gMZhn56dLTHu8!a7Ce`Z4) z)Qd(yY+!>us&j7exLq~OYNN92{cRL;&Pmm>Qj$B zt~&aKvnQz)s~(rg4%T9Lu%vWu?gbd=b@35nLg8 zZIfd5VvB1uLy_<)h4<3o9M5+Tezv}P5Mu*xq)?YzsQ7dVRioHH8Xba>a|2b!Ex%*zi!Qw!VN$yXn7KUEM*&ii`Oi;v_5GC zkT36RHUoeyIYcdpdDi@})x)q=Ft5M&R3gUB{C_czjWJ}= zMIr`7N1Lo}`Zhhxj{BMYs5K)7ZjgzV_m|6Lal|*)SDG|!NJYAd?r_adFnfrb?qgoC zQ}{QbR|xwT_u$YEf$+ISTK2ZPu^RJq&P7P|R!R&`hST#EFx3k&M+g5nzqzn2H3CD1 zm!nCN9@NU{C_e?|)dl#8OnP1UMiW3rVn}9jxxR~lJ`;yUD8TLi$lOF?;zJE-Hb>IM zlflCnTYIVE$`$OO-?fYvEu|DFc>A8|L1p}065giq z4&VZQMnGFvNoPKHU0@Xcze zrp>I$c#|Ljr>J&}Up~)TBG{!mR1`af-`6BL3V!PO8C)mPZEZLlA3X5?jO@FsE(gfO zR{Iga~B8wS6Aa#?srs?w5Zdgl%p8%^#QZ8emB~~&Ut&Gl_0C*ud z;CJ=#Lcc+U7gCAdCFj|N2d&EpQp@S?i5mSGw)S5Y?5mxodK&f#=#sD}(a6wh*Jf z>LWVZ$b5Mu83ath2A0RJe1^@EwhdGePFj{Rx^4%-h4H@#e!;cGMWX^uB8YM|#bff0 z&z!A?=tXNw2qN4}#tw!qQOPb)s3)HP3hu~ zE$5KOwN5(biQ>90fAL~7$8$=PeX{oP+{{93XA)S81{*Pv5-3?Rd+zld;~|d~&Ve(i zhBB=Vwo^onuk`WJZCS7&Qr@rCf^{(_3h5`7xz?awqUKlVtAYK246ZtTWkr;_zI^RWj?K!?S&PYoEf@=-F z6B$gxrn`MFs^HdS-wcpmOho_7;^h_gxJ~AUBN4SVOnnt_;4J$FfyJL@{a7MWnG~8h zcY38c#6lSeX(RozF{5h~ijLel!Ff$^6^l`4@ z8~Nrg%NN?+yI!t@s~ZdP40b7fWKZkMUMJPeOoqT+m9P#!ja!`Lc$yLnIzg;-WV$>! z?|^Av9Gb*?O8lRUtF6uPAA;44&o`sSBWekFVU!^na6*0^a!v!L3Ms|25h$W847YFU zOyzC$XTM3%YP)RYjTp&Gr2|#f%h$h3eEhD=2T+{jwPA}gpz z(vO=Wgx(ZcuaLkNr+LUq_{pFMi9>Hy3UP{3C_b5FTs!=MTy2KKH4@>%u+R1>)=zP3 zrNnlh|GKQqO%DY;=@v4^P^pom9p>s1x+wJjonQQi6tyz|z*28pqUQD)|7}<;V>g%< z*E)_;8``RP?Yxa9_AD?m`AKY-BMU%Gya+?n|HHSL{R|^o5o67*Us4sFgw^pE}vKz6(>LF#Klo?txF$FPgr-5}cT1_-(&uX&&LaDCe#(O z6eYTPG_A%XUv=avvYBnG_S#>RwlCZp#{wO>AxJ!bWJF=922f`v7H~=H12KP~*I5IEpu|+`6)=nc-oRSB zCL23@WF+&@5v^;8-NbTd-JzEP_yJT{dN1$jPeBu0q;TO$*r8{{9s8dq)Y z1dbd}K%yLQf*?aa+13WNX)xEs-LamyW^L46Y5Gb%k^dlM!^B}*loSKlluN-4O}RJH z@cmC3eTt^(sI&G~I?8B23^i0`$d3;brgLhWORzR2yaFCF9ci34V{UP1Of^%n zA@#CXO2G&>om$pchh~uviNNzBZ$cq1(b=m~r`VDX(m&+M@}$?j+u<2G5Z7Y#kcfsR z92fL^@@20J94^RtSPbL;G)oWXpq9y6&P~kOQ$%btojkxw2y;NV1sTT7==H{)>Rb_O zj9fny297UAu`M0FgIP}}1OIwSAKeGjhF`tK2t-9@hPm+*kWf`P*?#__SCWEPR0bzJ zaD=6T7|sj@2jJUTJ?s1qREoEOr6Hg_i?IHkW!hb0am^&xXk^RZkqa%6xGBt_d#86j zLGj3RoI^X|cS0)T?=_%#wV_ae7N7N{4pQ+PMMIskhAwd#>?=t+g$m=mQ9*fE^Fukn zm7Daj4`;8lITR@_kdnj|?d<7_PKVL%gd3U-wQ#bpjXS#L0QvVhfD=%!hz}H-KKr#K zYe45ry<$AuNOdibUt3JYD3MrZd2!25UR<^JH`tH%C$j5AKmfleLQ&Z!zA@3GD|jPq zFj4zMZ@YqVsBRie*Y%M+zA*iC_I!*k)dip&0hg~Ras$4|$3ThIcfzO}Mwma7)>ybz z$vrc0O-pL)^VCh*_~eIaAmM_xRUG6A1@T3v0s9~a&~P~IVI)5-k)E!i%9Mr9vdSTg z08rt^j)D=@$lnr*f(P=>csd9T_&Z3_MP%9JJe}XeAPmiNK+0>u#q3!mQ25xjGz~8* zEi}NT!*>W{ajGnF8IhS4IIdU6&P>MHH`h@P7HRaigmM+ts&=a+R?%k_`Jcddaxz|K zzDuS0gBG<-TWm&Stc>J6jbIAtma`-&vbRHsc6f==k!+DKk8-1Qm7Njzt8X>T=0d*4 zE^-vx@MAD-Ktw1}VhQC~P=p1QSc7s8f}{6%h0`&IF;Y`=TkNW8G#uY0VH~F}z0~bJ zv?AyNCvNn^@-b2pV+pg-#-87rFXte$&?o9evp{O-Lk$*W2E)l%BZ?GSW_r=(fHzV} z*X}7!{a~CeTf6-P=yqZ>)z*}V+Atnbgf4xH1h`&90f_=7`T~R1UkUK*CE{@%XqgX>^nOK1LQTgL{rnwgWgHX7 z-W11&%*3eCEYoRzG2qZm*+RLSVistjIG5VXNi$hU?}xh|Scn|FbuhR>k#5~&VTCf9 z?Bn!izK7_7&WDf>l7g%m<_djmP_8pWE~7sMP+V>LpOnZ@|4o`j#*oEgVYpCARu!Pa4ntjsh z7auhum0UQFs783Flpl9?2-Mb9qT_DOPD$E6sW#xPA1!zm4-WTqZS}UXbnGa#gNT4n z3+&_hDKwJA=LYfX-Oiey4vnEhf`lT8@rwre)u|#;ag5uNveH03P(WK!TNp|}`+3c5 zi9P;W5H(+-Ssg*<9$7QzeL##D5zEqxT$}JV$)T&w2zD_o|L<1%fb&`RxSYZgpD&1$ znqfxFlcRI*fi^xK83emE&!;BWAH*_=#i|s6>+Y0&Xdx+GCs!1`9YNek!dVuIq~(ae z44HuFn-#BR@GQz|W+TNxBxZ}lXYhCO@*niY2G#;;JOkByEx z10l^~p-HEo!12Rd@&YXq7+5sRd-rrW8L-Yt>^TJwXCeI>W*lp3YCmU@mh#}bfs&&0 zEn0fkg9q+jBnsE|3w>&ya}E{pjk@){9^G}&Q|o)|oyqF!y@UZYO#9+79T{isb z%{gfx^Fr^=)qmKPsp+NR{LJql-^*KKy&z4IR=ejOeITFhp=U4x&z5{YAjr=S2PKOQ z=A$5dm&X!Bc(8NgN}*mTsmnUaf?y!rH-YELR?IZVNI*~++>U(;|3~5u8kC;_TDZhq zG;tlAxEZz}wIu(8ma##yi>T&w-QlZ6H&_^KKn}Swh<+3t-_qKrO9Iwy`fOkm^Dt$T z!7Xaj>Al{jy*22jos06OOKzq7CVtG|lmYn0q1fu7?65ts?vh(HT4-InK1;6cB&HJU z&25HxGjKm+I*;4ph@D@;<*}J%5VW;K0jU~&D$X#@HdNA|cdXB-?G$=l1M~Fs-hYL^ zA%lJXT1MKVw{*0&7Z}5DCdHtIrxdbhx5>Cs(MC?*UN6VUcML!McJ3X76n5goa#Wai z`tqP`VL~!nsI18d$7${TM^+GRK{hzG7eVSSq>7PWaf`ZHkQCv_w0X2$#|=<`-3oU1 z+ebPjOnw(AM<6h<4pqCFuL6xyRS>1Li3GsFGer3bDIe>H)aJxHxQq&8`mkE?bmU7c zp7Zhn!AG`jn*}6YM z1uVnqwv~NgV|Qx*0NNITePqM1vf4WAAGB{5)7LW347IsZJM(;YBJQMBwT@q1f{bmF ztdmbduS9-rk92`9wQV^BVNXws)v}6WOolHQG&0yf2%#jiM{YAm-@!(EJbuh!5sSvH z39nnUV|xkzicgWAGAgV~`4l!aj3Rd~o#cY7g;uSNW-n4O=j$2=1zM`9)e#HIl_`3c!jGU2$@;?De9SvEx^`4vaaPeY80@V{FaYz^`bAHl}@= zCA4*z2W^$Lb(W~KbAv1sVX>(psGfKx?C3WJD?uO)gg_zty~ojfnSyg?{GhV#dc6^f zA{s&5Ttyk7j770$)umUH3v||V;gGJ971;^vUNY5bz|26Nc#4Xm#nTN*wLcitcaahAG;+eAQj=7=d5E6L?PL)HOgJ0XETd$)O zDUkL)wN2|RRVXQA9JG`UlSz0CVTS{=pBV}d=;D=Q_@?;niHgFuz_H67c=j`*c_ zQ*?O-c(pA|n@0`0zA_f@Z9XM{ut}V9xnKms`Wm??@3uB*K!Bsb#tgJVWQ-`=8x1A_ zmv7i!RgyKM%2<&+)T#Q!YqFB%nB3ao7y1B?WTkf~XP}THG5|qpKk$;9-au9VlD{Sw zvcpQEP|*)$@j$*h+sh;~pw|a>b)p7r+UQ&oQdhL%lq0D(pn1n86f3QaV{P-2hhsJM zzbvm*Kuq0IcEm&5a+NUK{@iaSN>j||5w*NR^RdyxdXJ=>3{4Jn4_pXlY~#L5+$bQK zI*W;vE`%cOgonuw_aBklCx@!%v!vH9}_5w53*5wn%^Qb7;f+iQ`Rh{&FB|pe4#^; z1O}wtp&z#lpieLUVhM;L8^sh}gQ}Wm4R?8Xs`>OgLl1;0X#dJCGbAmgEdW2#JLDW{ zw(9;3+2Z7QX1dW*@48l9pCvoG<~H1XQ!1XUNn%j%R>dzX!!w}O)$@!>f#5N+B1uph zipSS9q4X+4+Y@Q{iXc@ZPM3&tbh=n-@CL$KFo z<06W@VU=*yL19C#alv);)^L|rAo9-d7C1@v1vfcPue8qGY(}0yL=kU|=^s_Adq~%M zF4q!+3Hc$a4{9Ws_C+P{)+ID%pu6)362+*%5rO@^k=D6h?-&SKQ(D1jvH&myo4m7u zsECs4g8VInzF=Lo7}o6Q;v*sk5Ji>pn4>6d{tMXIIT0O!n%|!){Jn~mUro}3=w_-G z95W7}CF&#Pp)GXEhcUxyoSM<=^nG2nSIyj$>GD5rMm0xog+|qIn(X`~+r`}6RNPd} zI)-4!e1}P;I4XQcqI}dlb_;icLV&d86oA@Ybf^uy`&hItwDSY!r7a>;bA%bw(45@NoE(``Y+z6LdSgbX^>oS^sR{+aw z>qDonKukT;*~cpjmmYK3)PnaFI;fs-5;|4U)}=XaT(Q88)q`e>*u2m1NaHU*b1iK_ z>{xQ+xx{)XLX1fRiR0KtQf=YXE2i$+u|**!I>+)o22TRy$5db}{Ut}`7H{hj(c|Ko zLb$?6XIR=!pqL#y4>}^?tefeeqy|~cSp!_7Eb^MeCuQ?=x2f2;*bG8q@m0Zzqx1{< z4})A*k%~>!!qR%!aJt@~TD%6Km3APr?Z_`ZSe?9At52Yp^PIp6Pu)ET!_2bU5vK$C z=M9l0vP4$i5f2Rbp=xHTecQ_98=`p%B%{Euzs!w@Cpm*5}rc$k;oB^7wQm_D?ICa(;ESzHWf2_VHB0hJ%C{<5$g(&y# z!y9=)!n&yrZ_EeykvVV7%n;$`Mb?dg(~ApPfZw~y+oI&c5DsQN^Z#kLh6@L?Q3zGD zj)n4NsEyJ_c5KhQS9eC20|Iz(M|vc1Z&L&^!gntUl~eiK=nCN~JE9_qTO__58HeB! z-t>)U{j^>b~~*Nm?r+CdflTM65a@jKLkn=ycLz< zYzGb+jDxi1d7jsB4`Y0h?p1$~U#S?KtbYzzSy;^Gl;p1gOO8Wtudq zin4ZrrjFTR@ZCAD{9U3elH5q?c8SAIoY*${M^~pwfzh-bZ02#oqpixvZK30O`Wqc0 zQr!;U5Gt+SN%6e$5n0U9mFvD}B%eaFtV9;kTsO3zt{S8(6I4PbxNmDFCDEnSAFY3; zK_;S#r$srv&7Ky~a3c0PJ$&^{k$cQuAWne$!0D|vY0XW>hWc=bsv6r~bxU<>D4ciV zK690rG9;82g(e1MGWIFgif0f*x9~6KlO3meMV75QY74R^>cJv_w-#{2fXQ_IE&3`| zB_l`x^CB>`xdlFhfqneJbmuXzCv&K{6s2w(H3<7 zG6xY=_{C+R&o&_%tO+XkU)X3d&pjC2)gge1-b9%u!g!GQC+7#Ud0AX#hCKazoh1-Z zWcRNinVeuk2KEjR+{jjAF=GR*LI}_q{d!c!(@>b}fk74ay1ENrqZ2RmqezOrdywhB zE1f};D^v5t`MA6@&egUVvTGx;Q!tLEzT1zaC`|@|2qhB#V+^th2Bz;q)27vX72(}v z=Fg(Mf5Ojfh1@zB*tO(>9FCDB*dQ%hU#15sR}?>0ZJv1{2}u0`g01QIcdnqfUH?rr zS$`84x5T1o7(qXfd(t}yKXdupT}aO-1m~oFGLga}omNJH$8G{fg0zHWu2nf) z4evEG)siKfcl-U#^dq1^)99}e2rv!3DN(Ic9kxi)A{-}`N7?e0Uhp=+Xz+MHznHj| z*Z(65&R$r3?M`HSDjc_$;wsJ{u6sOqiX&UX`7(}3qA$LCDEz#jp$A@#(m*dGsocLY zpppRNe`H+nvcqW&2-RA1XkmbA6G-JqNf@dp=hV?Kn||}RKRXFV(o2OpJ=5X+kEp<0>+BBc0{h&UhDI5m zY6`kL5@)piu0k?4KfJe zEUh9#%8W&oLu=e4pSyZUhVpf$GvSo?XE^0?5~GB66XzH;qZ;{k4AK@j$(O^A9ONow z#J)N>7`hg;#yccN+~*SCf$u~|j{^jj&LFn?{Lw_@%W2}oAiU6kX1Ex05oWnm9Fh({ zQ~FPz+;~WHpprOk@1fQ{w zLzK+D$Ld>0xxJdTn*dZ^`XCgp!=a;7Cgp%#JP=mrTakB++?-4EjGO3Vvj@)@aNgF! zk3go_`)5CU%cP<2hPV>=fIwUcAfBKrEX9XLc4mZuDakABqmyI~bxk!SXiCL6gvoqs zwL@U^NAKw@1^^)#nws(bVC1Qv6ml{|Sfm5_>pU!Z5PP7-%y`g;Jv$><53>KitzDq! zMtu~>x9RXhGv0!%g{GT}?UYZf%-HToVZc%Nvo`hLAl>(%$rU7^J0Ov^eS;!Uq0U~7 z8G~cJS%x>yKv8e7J-6lIj%K_A7nnfzxu7tCpb==#3VS1|Cy)G_7*3`JJc4@xa-klc z?K8sF@$i~++7kECD@syxCDBgI|EMydmuY5{K8z2+Cf{k4#GLiTUcBzjdB;xR&BT$o zS}X7$U~QLpB)4k>`U7D{lCS{Ww&``SnHXdT<-v_}egVhsB>*=I5CWs>0Y(w|uOoi5 zwIo(gFT}dcZMv3;>3);bfe6yLW>@4E=B%7-f7K>U1BLa2a7q&H`8ZI_cjmsMO+TXa zZ0uNWca;@Tz*ZW7&4{P)$9jT?1&lO|kSoD_78raKqDiOFWS(w9WlRYmuH`XluO(NG z+{{1^wX_d(5#JNO7dks0ex3h=m0(2NWZ-CBpK-nAFVTB%il7;s9O%vIX=??Qu~XGvuPlb*DsWLRe& z{N+(V(D)wyWF?x|z;sbvOD~`s2d05&u8Of~>wE^Win-Lp!uFcD?0{Y$K8F0T|9*b* zDQoYVUci1I;WHPPvh8853yMGko8LG*1cw#>U9SbnkXNW|5a5IZo3@?b$B#4yRf4#W zw-l6qKM0N@-Vd${F1@BIkCa7Sy0EB2={?E5t20g`5h^OA)%%{_J{q4uV?&8KrqJh- z&uBczd^#n+KoaTc$+*VFLxY^e1A@c~hS+|qTjU{4$a}r|Nq`+o1M|@M6+qdO##)qr zhkwx7E4PXxhKp=Nxp&mLhC8V<6VXjHoAPFG4+@xn+VA#$bO5oNF+V#0h(vr^WR0%v zSxGSZjVEjwJGt{T$S57amU9XN_LuvLvsc@7ICLAvF7O8mwZe&_MR> z_}d>I8sm5!~Nv)&$|6|5X@Rm;tbsF{*O&`l>m8*Ls1 zc$6R&uKC-c1ZexRYY7xnnOJeGpvKnUGx7s{WK0CWSnraEhJZA-jM6K6c&tf89t~`~ z!$JpboF6G9)ex-zuds=RL6#<$hbkYuAGW0MI2r#%Jjkr+puB$8k^edQ z%7VGI)jPvy@nL1lU)*`s?+$q~`NNnJQ`&jd4iHpl0Zcj*_E%mF6P(JB>F5oT7#J(l zD#FU(CF!`|Waj(`ba&Eq^4K8A&S{E%r}H2mqa=Ig${~Aci;+?io=cKu8?8cP@1pc4 z9$1d^QB%+|LQV-_3P}MMEAtaetS}NvN7H)Au676`FNmucw#l9C2BQt!n7!pIYR=58 zAP+D!xLJ-Va98}nG!@GPtu3XdGnV8cEZ+Kj6#cP&HrkpTUoC~_MJCH`TPfh$qYGRlcete~G=39mfoquM~52JP*# zT%^YHjL|*&Chuz%>0I?A5xqLlHgvV_$ZIH5)vO5xgeS%z4qFzv*6-i}>OzV+g8nlX zSd$X96?`X|O9Ur)+fYc%??*b5(FOw_hEk$NcTmSZJHv{k<|4DMA`G1}vAH-oZ0WUK zG{67Y)-c9k2$CH)hIZOWZB_g%zY6m^UmMHbew%11P;D+;bwJLIQY}NvY~69VF@mh0 z;AAs=TXtqW9aAVer4Sz|7R9kvrDDA&f_#elYNYMNQc&2@&^RYq2s~Y~(ZgZUp4?y% z9nkDz>xYXnoR)JQN$L`{E|wviB=VX4NaWG#v8l%mZu^$4(isDa(f+XjKZRWBLF#Gv zDRaq^mo3U{yeM#^;g+#E;w(&~amh@G8wS*s>Xcbi2|mEL{DnyYsCEdDvzI!%2fs5) zmgr)5S;s$)-Qv;O+&*>}_P@4|G_Sj0>)hNZrC}89y|9syihGU9g|njKf3}5R#m?Vt z-W3CG6*G=1_)jt$@0{5?=sgcT0r!4>?-QcF9|~?V<6*$~&lEq{A6@yN(k*72!x&4D#8}N>8%gv%jzKZd%H89C<s^U9rDb%bAj%ssb3Ne zF8bA5HJ>}1dKfYD(4MBKyNJiM5+l5OI&ZNz&wPZIr~l2jgPK>y4AO4qk8^4e(C$S|f&n(^S&hfIpaM`rX-R=ZC#n@{({ z7(Q&Q<8p25D<$VDLi+yJvxD3&^83sLFv7=J8GRya+U@`PWrc2U=}P(ZHB+=tqC^Q>Tpk0v!cl@S2!WjHi9=q4pG5Swr%%v#|D-}i;e8cH6FNI8!yZJYV!XK z%dvSWaqM!SkmG}y$ycJ{4f3bs7{wT8EWQa_!;O-yRW;n8iGY)8xAQSWM)@`dw%CT< zXASo;r}kAObSr3Y!{pw(3K!DIoluoUXL|2r8`6SJjgu7mjWEe&c89{U#($>9jp0pJ zFGFO8bvD$4NxW$X#MKLjEobN&!f852Wu|45R2;?Ve8MO{wD%s7kS)(Z@YFnebN9ZZh#2F^AWV;+=L@Y>e!^9Q$9^0F>Hc=QCT;YVnX zs)}Rfmu-(KD|gG=X;`a?_-Z&K(;cG>;1Nlrb#GuEa~UxZ3+W$YHj8LhP>)@t{nFCp z7_l;gJaJ?@Ti>|lf%WcOS*R@H~qW$^oLhHw` zs=rDEj6pcS&FXY0SVb{==VhPCXni;=C z91Vlr{pU`*uG1VOV6iZdy`@PWo)>O45~%pY7rk==iW#zMZ_6>MI^W8lqU3DH4Y=H))q>2=efeS#0PSh|H)wkKJxGC0F}{&SZ zD1PWK+Oa0)vbjk7w|(k_$Q)Oa4xP8911(klD{?f)kbs98yDvXKh9WXijDA#A6= z($TQ7PNzV>bQ2+*1>&;b*UF(~7JxYCfVh_vsT-!tCisy@$T0V~p}_?6oack^O8gCR zQNoHYy(Pu=@9s+NqE{5sk7Klqa9GicOL3Cn0JYjrzTZN_hX~NNoTcn@+4%XE)8&h6 zKxH+C+#*LGhkwR|T#wvM0h;HQ28$qwOtA2Jso0|9f$_QAcd^WgEY+CQ$;S2CdF8QM zuMp6&Fe2Dks2RpLa0z%?MI+Z{XM z46#$pp*48O7YWu5Jq z{V~ky#Z)vlsr1;ax-o+hzrVwDVu#=FgweQN!ad0#R^I5aA%%^|253A)s&QEJnDBOE zz1(P0%f*m<=8`S}q~Q55()*v_IZS5J%l$`$7z4>xMNIzymwVrRP&yyi>7v0@Tl$)T zj-2u!L?=x#49d6&qwEJdc0P`=GtqCfWd{hW4amjwb(!>i6?5qiLMGKNr`GI}KFa&U zu{T-;|8+UHI0O#eV`P{CZ236mwn`@RN+YCAOU1{RcgRUW?j3IL+h|EE3pFlM%G+tK zT@`yho)qeRiAiem*_Vg9+x-V*IDn1BNKuPzi+mN#im>?&?^N?I8W-_s3>2%E@l^5c zv=fK&C(1?Q+lu9H#+nLOSe747k4n+;M_yIxrXdakbe924hbFPYG1JM1j0fDm6 zf3dpw7+AgGw{f3zylaHl*%$KA)t;e`;JfJWYP86|2R-DWGMCGBgSHo+n``ju2@Wa$Cp<`cZRhK z^1)+m(4Pl|xK|BYC~UE}hhB0*S(!YeFs#?)PxHo9)sZM}GfF|7C!lM}K~Y zJ39(?)h2jw(@`gwAD9!2<4Y0vHlt~jl#sXKm+;QE5bGc_jP=8RB;&_F2;J5ZO$}l$ zZZ#t?i9LPM-VW-chR(DM+mC~?g{@#Ib)qC8l;pFCWPft%SUq|{Hq0#(loRA<$3!?W zxO`5tVmHAbC^iZPJ9gGrP?cK>^Ne6wLiqGWMHC~q0c2>4?4oq@?Y7roKG>}zP*?wq zmMq)D$sb9JxEzLBa(;v1TaQSfAu*s9O4Pm-G|WUxa*qMr$pWmJ2P85SjyD?Nq-3J6GZ5 zEL0y>Hbg=Y z%uf5{${62pAk}1WYA(=m701AENGNAx)?o-KKn?QG-JuH98piE}@qEhVHP*wl`)8=k zuz{ZOd2stExlF>>O1CKzH}n8M^8Hd845zc0z;6H}*=pwn>6vt>>hneomc@8Lxx${C zn_IOd;7j;&UqX|OL(1rE81KqFI*ZAli;v$RU!q1@94N!cY9Y}}Wc*_&&Vz7PAGNCm zALE$#xLaZ!^MV>HNKyOsirKRQnc|p2;8U49nkIV6V%e~1I#V0`f(5hJ?AmLTpYcMp zXqXuL!VePpupFlb)WHD?R25NB5D;gfZS^F8{>j*X>~W9R?axF@#!8f;GWY?PjdROD zq7&Lq`$S}^*Cl)AA-{-WnF3Vc*pvXx-0*wR?dH;mLQb@h{$dkfwOw)6Mv=W!{sbfi z*97~~cP9>)S7m6|;n6SZ|LpMa^aqIxKqxzgEuH)2`E%G4F=i9VXn$v*QTvo;Plu2Sm_bmYD8AK~Fh>x8Z!*{a0PIVr+HPM}CHk z7{U7L*aNG0`)O;jTcB+?NEa+raG3t|K9vI4Si%bMKW=Iydq4G1xb>k?w8aVt`miv= z{&^z9s^JF#cMx}j8Xv>j`vEaQa2jF>3@H#2{{lKUwYx5&O2nEeOAl76KMXXfLwbY> zBdRY@xM1Sp_~1b37C?UbD+@mRjgx%1D(u-T;7Ld%nIhX_fD8Bl0sX4p^YP-t0e=q@ zfEvQWf8s|ERPrCPVRZTp6Rwis$*^~J9e(XY9h(15p#5|gOO*Cs#ZcK@B{(8-`O3HnhnOGqN6FKz%CI6hD}N;Rr$m33mt&BiKMbA}mFa;9)RB z{9i@*FbMpIeWKRS7G3s&c)kglKPrQUne8&!bw+dwTD+=e^wy9YiLi zKVc%MmR5DEr`iTpNKBW&;&o7W3hNYKj@)Y>;)|v%t;U}8`s@EDn2f+vVAzVP&X-rF zF7{;j!(WG9yPf>$>6C#Gq`7dlsyb?>bQYhS%}~`uxrZky@^D?2N?&?U{3yY}-{h@) zJWeqc0{-$hPAa&wi+)~|J=Il|Vzj~rke(-mWfz|30JNI#|4JrPg=Hw2X{wz#k7974 zau5sf5ik(t*`Ikk$XMSm+>d`t5=A$qgH?wASijlnBeL5==ZB91@PQ6^Jgt7Ln7Iz< zsgLc%CL4NgNGq+HzPZ$#T_+O9Ji)}EuJ?e!e0g{X?mK3X%5L~o^D!!V#4vR+BShZV z1ttQUMPt6Yk;m@aks!GN0tlmR>9C0H)G$iZcwM&O4U3k15y7n#9W})I>JPv(&a6z)VZJ8IqbvFlFX{PcY& zB^w=pMrLgfuCd2t=0Oa0;!se>o+L$2_rPN6I-=*1kyAe+If>r}lcww49rL#2-V_M7 zW0-tMPk~{~)MNPwl9~(z#;?A*Pe=XrS~%C?%#996VXD8i8U6^2e<0~A?N`A8+&}he zKEzsLamAQw>< z+{youOi8h%Vg)2A9vnn)WNS@wT3xG}Ajy!SYHNcUj#`^Fijo-^oKYOtN{GQXmqY-P zK9q>yQjhOz0E8X&NnsAlSVIgR5MB=j*=M``ek&{G{0#k0HmW;l%$T{_uK|XaS zruo8fLVH390B)}>I;xON%($^4iMQcKh6Uwcr?RW!D6NeeB{W}sh8Q!PwCTBF5-92S z9DfO^Qgf@Wl+xDqk!TtG&f{W!jPfR`vs2tFT;6&lkiqiZ9DOWq6}5OZr-{v ziyzc@f&su|cp@B746+Z^yHeF0Y$K;LuO@T6#mQhuaMKHS>;+etHlD$nU}Q~M0w%LT z=FC`Fo=vT|WYCgzTE46kbh@yaKqu|Y3kQC~iJ|4qP*j0Ur!Q=?rLdhcI zRedQGE0+~neU_Z8w)xDH_?_6)EOw0b4K=LHsFspr0L^abxe_Cz11gVN8b)B$S_*$` zG97_hrGiiG`LLywP)#7ru1qJ_>~FRB6Z*YPVQ>ljV9#y(|LGJjGO1h|uLSWbSBSjq z81y_w?go&~8#kJfw9^xkO6fkT8@KPi@2%r6i3FDvIl?m%(!}ZDLckH<0Pse|O^ch> zJA>N@uMF>z?v~fU5}w0jAQ|ht1&(nDyduT84UY&e%itM<@)I|385lC0SV}BGjAmA$ zL{3hUi$I=|4WJ7uV!&*IE{3^n_R8JRvBHKXit<9yBYeMPfL0}J3NI&?0bVdQ&B)fM9V*p_So)xYcpM(u_C1&`T_(xiXQMSnlm?+Fgzi;3mB4S zdm49^R7k2Ngn*j|hIEU{#m$wpVyXg&rwK!m?5gsE<|fq03HsU=NZei#h`@nB++SH7 zpfO0%V8e&IhTF3RLxJZQR)kL0Je?pLF}z%IYXMIdGk^ydznbq2dx_(YWwlAkq{R6) z)Q)YqXx1_m-q>!6@W;B$Y9@y4<}DCQz6i6Pjjgf!sMqn$QP(u)`ZGLb715NSk=nbU zGihCAtX${S6d$9;X0?{W^@j6+6nDeZF%Fq8OExE7q%x+2T>h0pU>6Ngy?cM!4VDnNp=*bE=6!3+fEf}enTaS}*O&0)#BI86?+>#sL- zPkKjq2yic_T$iTW%y*2bgXK%@WpYTvG6asUDtQ}`h2kbu7WE#`jpNrgSPRot>SnR3 zwe8x7*oLq*#W6q}tvEO?)_ANb)u>p3sr7JyTq0>mX;`Mx(02GC!<-ENsqYu922(xb zV1n7c2+~U}_$lBsmYe_w27VZUzZ6;M@sayR(Bmk!9*yvU_;oxJD-GGqlIe%*Y$5Qg zxz1$fbWoR>%G{-a=q+*{(7A2S3b-SsTPmWX;$hOGQya2Np@V`>Q)hV{?&9#59=dcuUfi5LEcWF>9l+Ea=Fmt0{}p)yPyWRM59MJ~@ZR zCm|i@rRvyJ=iHdrCg)K371qsV^t~D4vnv5gAsDh$`PrJDmdH!%O)V}fbz#y@ zo)&bJMv9B5bInon71PG4Y8&}8P!}6*2*+1Shzk$T&6J}v%?3tP+@b{FO!faQ)Ww2k?Y@*qLnD`dKc_5i0M z$0WfEd>h1{0A?vrt7U-j8!yD`LxM>X#vWdW#~^qZL{Mt)oPWmWgf6H+45T`nj0_{p zxNU)BFW@P%;CtnK z!I4NDSurWq58cjxFFdnc@D&|QO78?Wia2DReTCFNL`%TDm zW09Btu2R`tW_c-LA`~i(YF$BL16ZwDY|jd}ak=vMlI7eO0iiI*d%{>+EFO(KRWWAU zZn?49Rr$YWLu#+(OyE=$e}lv?ij($RhK z%o?U3L=OgmP7pq+Ysv{y^QE$DPQqgN7@7Tc?a(%)wk@^iEEQ(@jj97ub->xnOx=O9 zg+g0+!@f5IV4G(N2ExEx@vR7`LMqkDkUF7KvDPdu>J|^1!CsiFr30G*|F`Kep|63@ z2fVd@d_1jS5Eq^uAeiEKy1Fl4iXStzqD&R;pIi^v7dmt(?VTE#PG@{j<=>UK zLwn%crzK_Yp1hR^>qCT6``GN`n*S9>=WpN^h0_iJ+e>IE9oidlRcBZ>B<)~eD<4l;M0`0bC~+}c|h*I zr-oQrAupjLCX`8KLbxb^_uL+}^l84=CTc@ZXOYb14t;tlDxJ#{3sYVVMf(fSjG4TD zOSWs{PC80&`%PPi4jJ_C_W5LBQneFvJc+suRo@n6taR*hA1kcWysxhQRn@J&y4Gsw z$jn#w3X=uKYe>JVa&CxWh~duxJ2TL;hcBz6KB^izqCz68!i}k8uS;7+^h_N7`Kg1u z5A7sXoeQl=Y#cZ?@Ry4;AEarbNWp+2ZM1;G+`dj|HLy_=XNm1^y<0cLRtQtmqN3#) zQZ^?{rzPTTEH1i+noSZ~g{(rW8@sCrwF{!Vv0)%J*Uuok@-{(7ZFXXtAmVIK>APH) zrX>G=X@!ImuO+s9M-FpNGlABn)`DQ$w_miq?q#r@Ilr4|gM)}YP^?DkNR)miHs*Fv znEQZsv1~v3R`{%}3;qu-Y-9lQfUSTb!1uO_K7L9;AH~ltf@^HQaf_}GFt`W$MR}vN zje$Df5wK`cyt4F~qSRfa(&-&-=K$Y3M$RbbB%&j+s@<4K<`zMkIkHzwB)bAd>{AUzg57z)qN_iv*@tD#dMCq#geYsniHW;v>vlTf#a@<%Ox9jTy>5|~};8nWWZfS3E z;Nc+Of<6^H9y&p(x;^PSU8B1Kq_>t<>pO#0?&+&0^D9>}27$ zF*i2bj=A~u@UfTvu~z|Z6W+dkb^x}#JYhUg7zAF>Gve`Ljx)*aR^W}uqmhgNTs}JR z$)z$m))jKXH>1$z&jMZAT-0?&E&^=nmH%II0n$oWX zcV{4gIr8MmI3Gh6Op)iP)alnB#o8b!0z-HR7>Ywl66H9MBoV^&0W@NW2FlI_2M42) zU^oT~LV=Jd48%bQgE0WYVGIL743RR7D!BrLDFuHuv%Z0RFgMC&KUQx-5V*ZM9%&LE zasKs~{>>XXKjGOyo!II;iAru|c0pe1@^kN^1rP8eV_7OG!=AazTx?Rm=3cFFDULHY zqWx14f)mlvT%;}wvTZjJTG#B@IA{C>nq+w!;8-9AsMaf!?EXecP zx%5x(Yx&8vNp;8Ra1vzY6(5Q_iN@&|o>EQ*d(s7^1q@8wWTfdbV_COowC_I{oojG5 zI(p!Y!WlTZdr~nOht-vNE*8uu^PYeGAo#vQ+0kf+=1+ zIADMU4j5p80Tviyi6Nf2;)o>%SU0{o&P4^j7D3T4$~yTbr=d26-CxH>&2hVOevR=_ zAET2Yn(?M&6f-Kn&86%k5oi8fp$-QYlto{rMr-}|-H*giJ2r&Xz(*sDJUX!3Kbzw{6A`HPkpurBmUor8%o7((-KP(}!h(Vnz#npy7PTGVY;N0^ zhlk4b&m%&2c>i3MdvJINlHq+uHLNwnD*!?ZJg|eEzkY(ABP=z4{fiG`aKSae{yDQh zx@BZ7JV%6bo*7CT*+p8jeI02QST!-#IN`8B`M|PdARSDW8MXNBXEp)(+wM?gE+ z?E|5T=2U^$)&0r*v#7S&EZx{O{3T3wm_ zKAY&}zSsPuV+8X|pfh@ney=aRvwN>L?X9$Qpo0RD0A!T7HYNyU@Vv5@7EbW0U{zV0 zqz{IR3WO4MWu`oU&6+6H?C5-f1wobO-}0ph6bB(3U9(sl>nNX^4k)|ebkwnUu!`}# zIgvOzNPzqT%sv^KdfXXQPNNKdV-WcO^kbQ8i5#j*&TQ@$3E+2BT6VfrIwEd_T)dGa%w^ivul6QfgJJSvDX~QbBls0Vuzdey$r@T2Wie22B+^X3dN+rt0!`>dG$*FzO@ir2dC=g5sj=iu6u`lNZGvPJ;1ZP#N;CuN zOFe(D-NuA{4xYUV1d227E=j`+bE*Qk+hS21jar}yz#xHMW!$anZh}$T+OKmr*NWtT zy)FB@Vvr$L8~;WCpUzG*Ki8d@*Kl+5|5IzP$KzW*-VdRQCG| zs9`Cts>vr!)g<`9VW`!cX{>(K80w5Gx=Ma6xK%&7KP7AXVOoT$KO?6}2d$rdVnAel z)_3ILXuVc~cTw6}vLK8eZxI%fgv7OXZhJ4us|1d9c=M;|C6?`6x&Zreh)2 z5G~m2^!^x%m_CwYdUbZ}`7wL%dGqbkVTQ5Doe(C&fV-x`;Eq_(aheQMZ$c5h^OQ4aA45%@g9z6I zwbRn%i9DPP!`#mZg6^3g{fQ*6nSNF}mNH&=lD|OZIm3$-#)rqKQjffn#Rt!Sfx)5x=2U@ff+B=z;#y?Xrmg)%NCB9nQObqo3J6 zT-q@lHZ>fyX&rsm@~%Zq3o;zVVuEDC@?#PVDI-Zvvf*G*5Y5+9{c|tIfCt@}_fgm;x)Q)=Ut0Nz#^l!&mJS-ge9>I@gOZs73ZSd6a17?DNX~|1=&>Rxi-abv!M=i~vN>Bc* zbYyKzbof3#G6oHRMmVxyQXJr+c_OB5BO7qo(udB(BSU}@h=@}bNcy4C;Y7KzK~f@K zG`%#CIN1|(W1_?JtwavYSX~G2TO~huJDi9^7EDS4ePmz3&P+p$h(7IkXd%nVr6>{0 ziw0SS;H!Y9{dOe5zRO-!$5@n}VaxRqayRbdf0%|v?+zv>DLezixSg6@ouKp5Nwb5P z2sDXDo70l>PBm?ncpQftmzrXx*^rn8uLe88_n{C$kMh^l@nh#_ky60!P(P521DW#yOop7XI#raPs24*NYsi^@BWex-`5Z0u zW6F&Bk~E~5H7s1psIHf>18ZIYXGWsbQq)+2jEIREOcJ%5@5dyN4YUQaqpyT%sY&2a z>(NbTHPT-5Gw4h>0EvjuMij(`$Zp{iKl^w z0_d14)W)LSyckK+2GL5KFYfkLnj}VY>a8O1TV~ay9OOSNHvVQt@sEo{YATORCKBav zAF^h1>>Wg`Qmjls*3K@PQ;HbdI?o&|>v(J@JtQ@@$_9)Wz#ou?hP1n_LvqnPn*tu& zc^Ri=2DR0B%q@f;vn_aX{NQY$U@yf~6UaaD+9}P?Kqco z_z?VKQiURJ0&B5pP}KP0vP8T^K*xVW9nf50tn?Iru}BMbVKd2D>vc>jRF-bmkA^nfbM+!Ju41)4!@6FKYiOGp@r)h1CDK7Eq~HTBS3wF1 z7>w%DlG*Z`Cf&^tSBr_X@EFofiI0J&4aSE0H{PRKG$VV+6;-A;Qs_PJ}+Ls7MWx!BXc1J zS66QHl!tK_8r5A+KCSWj(#{+)cc&|%`U4wXshPhC6i$X+sH7MDzmtWb&Zv*iQroO= zD`-NG%Eb})LB$Qt%YpGDz7LjfV(iwQw58qbU6aSfG%=ZV|_Qk%jEcL23>~ zhpRWM#vz4PRBWiRaH6;scR8(s!}_)ceed=gVfcKf52qc*;gOO@uteQ_(!;+UAb$X@ z@DJM}&d7F-zl{GgMKI&fh8oD1uy2SL)l`S7CiIdSQ*(n)@Q=ja@?|`@^|~vsVa6L8 zAF0Txa=sT{v3bBVbPd{g$K#mwfuDNco_XA2B$Hhv15?{GF`yDZ2W2aMFMzet1GH92 zn;58npxE-q2cJd|!IV%9Q||XO)#e^Cx)7ya<7X*uoq7MD1|}XJR9MI=%K51M#)02i zf{@Gz7@Yt#?v+C)8YI#-o)$;T$MOM^+DHei4zD zR!!(KDfUsL3KZ%12Ig|ZIoYr>Y8zcCz_qt6EO~U|PZ#!m2|M1Ca)iTiDoQ3kk#Rpm z{)s_r{z+zDFDsZA%~^#XoD7cH#PMfw0U1F>CcfI+0`8zriQD}oh&FbiQiX~(=Px?N zjLQW3r5bH=2Z4&$D{(oBe>;GTTu1Z(`-*1Nz1}!D*Qkv+QTmPVPdn;Zp#jyexN6H! zjmCV;=>!~M|5YJ_#0P?Qw=Otcn3bYehnu%N$aS@(#?j$;!lj6`>jZ_Ra23xld)Kc`87gcPBWtm;UYyK8yQtiqO2UQa$xZ|xlgtesP zelZ5Q`FgJb)@;pp`bWjH~D&*9H~qN=m@3K|$SC z)T?Ya!MdEt#g&QzbqPV}uXUo{lEW_JRE6{0o!gM6uWbYDyTsXK8p&U6$h6ZeJPT~v74=C;IHz?{@hfbI#)3lAE&htzmH&JIt3JDI}{7_=U zt7-#mt+sp>9W%!d+4gGQ`i&DcTLIzbC9YHo@sZ}bV)H}n)NxV8mczLHZIfjFsAa>iV`54 zH6^7S!jZD2)mw%vjun)`gvqPS$>m)U!bt5nU}W83q!wlU9HH6-!oVPF^PJ=D?_ldz zH}f0ss?r_HRSqOb{G+9aAa3*6u3-JkParg#Gc-jMZ<^WWWeB5h!?lJ(Xsax^GGzCB zpw)6tr{{V5{9Q3achndz&zN-t25nIL;9J)Pc7dT`jAM@kKqCm2=AHrj805nf%IX+8 z7diw@tyJw+ZoI5y=AW?$ffnwR+`f^St-Uo_(Is7!p>HOHAwynM_t;yEK=upFcOeGZ zL17)jsJ~tN@6~_Se}I(KlB*o|dQ4YQc@(W6Z6H zO|Mw;B|i`wv?CXS*I`z1WvSXw=lXZwJlh2gaOx35Nzf?$W6UB@Raq=Uf8}UgpX;!b zk4#^m5CMDOMLEm4+C3{GKSz-0-KtZ$mc^BFrlJhe0(gs*x7VlURR9{@jxG$OWNw26 z`DltbM9y4g<4wg2hvQiSet4WDi>xTA2`(NK9pdP1LE{k!telAL=#W6L<^(p|CpLYp z&gjY0wmlf-W4)_75VlgwW(tdGimoYb=MV;42DPfY9S@Kg%fXHcrJnmx=uL(0hOTAb!_ptS4R0=`Oz|BhBRH<#|Eqqcri%UuK@FIhoXO&S#tlDbSklQ>X8;@P zw*FavVNz5ju6-JJLAau3CuB<+#c{k83^@k~e%&4VD~bfyXfU`6Ujn zbbxL`qh$3C&Sx7LUXld9q1zLty+MyTMXB(r*$a@wgS zvidvO>M*m<^KhOjRmb6e+1PL}ma6lO1o)kAhoRKWT;1{e*3%$sC>K(##Z(skD4^g) z3^)iVn8$`iEUn?`A&SIe=!v{u2pmP}+C`Kxg|VL2Yc# z>NxBRuc5Ab33cyVo;oD{y~nGreLjwaebvD^@wc^ptg-wy_P50o{KA9b4cx@i_}wM9 z+h2V72mJ*&8`Wpfz_bMt$P(TB;Y~M7J*Gvyg7*U=Y`0>BuyE-EiEzZd`&q`OGpzXE z?Dt^xqc+BqW;pGPCyjy97*87WX=_03O{b;#v@)HR2C6Zh6vmUnj3PT`IN2Ld3KO+8 zq4dVnW;m$~l+JKc8BSEkEOl`G#5tc>rxVW(6t0uwX%>@{+E`Ij^bYjoC1+&N>GZer zCcp2~>qR}Er|0wZeV<-0)crS1%X z0uk+-IXKYz9ae2_dEwA(F?ZjRsh*wH5bN%Tc7_g!{Z33R%C19fqqXJ7ALbB4S1c-w z)*aYP3337LOlZJ4Mu(wbW3L_*SMX--y(J2(s~P$7Gc7j`@o=klsg|}I=j)A|7Oj`A48slZP`70 zHjt@o)Fvu{Q6hmLgqk|_FRo?Wd@@JrY}G`NLG>O0XO6&@+{T=o>%l3DnYQ6sL$=b= z-;u9m--!+0@(zkiUkIeL%N*8t@Pk4+;5NfGU*9o_O}v7s?!mx$9_CR++@c^%#L>&o zP`z!r2^@ggIn4sl05HqH2+hp+YsndKKTn7H@HvBl17e>UHCs=|wdK1H%*knO_$(>X zQY%aN?9$R(9Q`n!A9Ur{du-~E0+nOOb&hlDW3_%zL)kU;*TsqUvVp}JWNg>7oU-X? zMilJL%Y(%mY}tDMQbp6zjs1N`+l@myG#YIbk^sxse$a5J z9U?}05Y~g4VkEtTxSpbUCtbv}D)xL&n&+S|hGu1E96V_Faf5uVC5Z{qhp@yQLE8EBZZ_m@iy(ydM1=BOY8f*npEQwsSuhV%&xDu5wP zo6UKVg(aO&s443tzXi)WHVmIRpCX9Pg@W6IbF?miK$>i1kTz#}b^@_rr>)BU>2@e* zn0thumJnUfe0DxNNTdGRN(SrY{>8)s6t7=-)~_68-im7BKSK>Jyx?RY=&cEcu6z(H zYVbx51dryVRj|TP-n@bINr@Y1a>r7r+B&`9O;Mat6W45b0L+13DLs-PO>{_a2v($BQo3!Khf<}Fi`Ct3d~XMmLtRK z4bbc%$7YMMz0mZ`I+AlX5DqdB%rDmELj4De6;`y&R?)7u*;OGnYe=>v!xfdF>* z!0sQ}y#~8#i0vWStSZ|=lFfs%xe#_6#%>Oj-R~rXVhf-fawVR|yvHStKy+~^FDr=W zqS@cGCrn*#_+J`;R4>5tohX{R@;t4&Z6p{Nv5{t`_jydd*svqD#6upFnr~n*r3_Q? zEyl_@*X_UzKWmqiC&FDUs02G+`qZYdCj%er@D@L~c1Ac<6~;{a6G}gH4|vuMd!Sum z8#%lXKa)wblWmc2ECB`5dU+15v%eDV=-8}OW z&q0S+QzAH)g2S7O=V&EUfkf5BvHOE$JBABx(LPkgn>$l5*<9|9R_eNkcTcPQ=?zHU zs{DihcJSz>1W(QU5EZji_(GQm*~O!BAZ&G0TWWtGJ7j^>e`&Xk+S@%D9TDQI<~q_h z-O*%32!&P484-VbM#P)QAx?S`@`ap8l+as>D1hQ@y23weQkR2mVmMJl$HCVr3ZwAZ~WAIgQ@48?GnWawVIm7W8 zPoJ4+#}z-yRL`TRyT{Xg0_EOJWV*k-+4CsPsxLVMRA$*tpX(MEyTxCMf zWxgirkTwf@me|q^atT;pXAZ*0oLvdn!_n8KVMldKJ0IEtwJyTQ0 z(F$^eR_*eRipfnl-)4xS&@TB!YHv*QyAa>n%~-(6m7@*yD+67Zv<$e)0D(56taXM| z_4%PxEM20?=~D$fPTS3}^6jFw7tn?zW_ zr)Mn#Q{T-UQ$pFo;>aL@$TwWDQB^?f4*J#HThQHkg~BZ+Uyl|LLUgI6PLe6cqecHJ z+1gi$kNPTz-J)_~$j?D7{cmn(YVDO-eCpnXa zFB<|1IR?~XQ%O=*(Hp0Tg)bl{vjYhVE71T}eK{FTVU!zBA;#UN6d&!(0m%S?#JC`Q zj+|iQRb*A6qgumYuyu{#Fk#os#q0ABb{&SI*9UlulW_dXdK~BZyo}DCTW8+>*zpXG zl7|AN=${9EoYtq#8OH2)*lYS50A}U}=Hi!)a z0ZO#-J3xn2-Hq+^cUjGa+g1(Fnq_N;n0Wp~JSU|Vr#3h^G93`9JH-rH_5*Q%c!t4@ z#A=c-W*}mfQ!It|&#&+XU!Qa9G%=$hsN*NUVBCkyll_`>x;-4PT2hHA9768ED)h8{ zMFeJ>jN!)=xEwF8yv=o4|FSGnjV1n&)Q5iDG9&6PYjU7$b@v<~WB^VpCKs_w5+Mdwz<^ zQ*ZUMGY({hSU5ztntN(0J{ECYIh+Lg^JN57)m#4G8wv0kNYB4NzoNIXJ%4^2uLNw6 zc)7yv5WYW@-VZX^(aG*3^kZq|K!(VHeVKp;%Q+BrK8LYbnYflxqwSg6pD*ql2Sw>W zj2``DYig&k@U3}=@chRt62yUoJb~t=zp?d3_cY6^i9fQivXRs^TPlU0ApI43^QK@M zs-AcfTDloq2054}f8D%8orY6LabniULva${!jss?GX#KiW z7_YT|ueMmc&_kzd3}#j!cE%V>JbhmKP;tlGGCFC3+y49f<4;^0W(O1DHSy;Mg`PXe zA$>Un*y^0ivj&Q6^mU0h58ozDm|V_;fK-Pr*+>I_F04mrtd!6LLGJ-<-dZ8dnf~jB zx8>~BD)TEU-D0+OHualsc+4vgNrALg51t1}b;VrpsOpkBg?&~Wn&i51FD3n1{bW%7 z#rm0OVV5io13&=!vX=+$d=(h?@(uyI?CtRj1o{dl5de(b+&U}3nszut-wx72p++V? z{_g5tSA6tp7!D+V0*V+Sd{q!2hg}_!8zOV4gk#eYU%*enHpYi6Pc~?O1UO=kf#TU= zpsM1WOO&YH<1NUsP;O(vQQ@Fppu5oAb>uK==qmfwWTr?Mi02d6%FU6fbGi^Tf|!@WdhbVTDOe`=a$Std#Coq%E91UfJWH-`7fhJHLaPeyde} zVdTkP%U8fpHu_n*S%#4(IYgkQpmg%lMpiA8Nvi>(vd8hnq3!#`mu;0SJ283}rFUg$ ztDz*4)D!2Tsya)axRmyV;K!Est@1m|bftZ*IJdB4bk~301o+>?FAB*>mimY-C zI@t(|CmY@9ID*5>eNxeo9@-xEU$PJOy={49{{9Y0)4sPIH5A`eTxe$-F8C+Q`o^1M z*hWNs>zCaV6ga{Hk=7T0g{TpvKpV9eLTUM2^#i=w$ix@}>km>l`Gs%6`w&>S&Z?KdEGy?*Bbg}#qsA3iy*s+zIMU)$bmgadQY_r30y zwUqpML+P&)su6W!#$hIE?!e)!m7MUr`ahFYTxsVF?S=N-Hzqvihv>3TK*==-NiaZp z)RKjOKih8!4HsZ9Ab>5ccuY*q58iS>&UEHv2pEIURk|Aq`b`m5To%y{)*AJ%spdAs;^8gFB(W<(0LKJEz zyAs6~yF$h3Bfi0^E^xwk955kk2B{JtXKlZEul?qLVL?h8hcRijbu9uE=h6bT>R7tH z0)qY#))}1X&6FKOtNES-wEqSfIy(ZTPCgHqaPPx^W!*f3hd9cAr_4pY7v{e=*8~rM z3t1_viV=b^dIePy78J?12l5VB$!jMc52MrxzavIJ(WL0zZ=MO?MBoG*kv;H3L2Ck$U;=W`kl1`Rv81PRt?{fk}=`HuOHuXV`!?N`KbB(*N(W!%$cp! zNv!qC`T}dyXjt~)t+q3FFGHLzk4OBGRm6_6@26{$D4OkekZyUUSZ5;?EHo)%)|~<^ zKl-&h6R8m?#2=KvCDysKU_sh?ty%(UG021)qM2`Lp?k|#a)U!%1wB$DdC0cs@wp(R z(2r&e`WuVT+JU6VYaNTseFjf)X!cruu7NHnTzGh<4Q}@9cUV;(;a!k*m*WQFij#}u zik51EE1u8X2&*FjL6Kk5Dz9Hl18O1jn#I0K@J z1pX-X3ZqUo!H=X=jBArKcf>u({(c<5nGCHFp(UTfskDAIK^LO=VGs2x-Ehgd6LI74oRfs-` zanB=P>tla!tj-AM`J9Hds5_J0ndR@3p8c?}>i-isB;VVrM}z{~hHS`P3XrF19o2l6 z738~Fw;Ls!zPguzvRC_Wmj8O8q@diD)Mzo?T0rjno{h2Je6ybdrv)Gja@C9puUh*x zw7E@?0eJ_$zk@P{|V+ z&`5e^5C8?Cujp2pGR}nH=&_D~Ji{~e$~}#F>{2|p>VkA4QX(lDZ5X>!_IEU?s?*WT zYhw-Mr%rg6sd$;+v3zAug;0qs*bB%9R?_{ziAl})Q-1%0*YRfH2Npmm2NTG<*f**f zdkNl*1oQ&r$pCqpu^{jLdU`Cwgpc_?1UAs#!|o=gKuXHI{0hn!&v`x{Ly^lyb1Vb3 zxx0Ij^6Bt-=syO?!8b#!W|={Lq4h6Jbnrd-(%)AE%|lOD#+?Gh-gQ=D1~*w z)Yy&QG$@TXDG2->VI4lIU>yWV_6@{QtLF+@kkZ>sQ8asT7?@$0br2x7f|cIimG!e8 zL4>v}Y|xwjO78&PTMPg(8s1UaLIGt7LvAYt`Vp!c8oJVH!r1_lT0l_*5R8+d#5gt< zhbUoEOe9=)LO3ePC*29Pc%dS*Px>3qD|`A6Sx#iQ2X_3To;`7#9FdKK9zvfU`}94v^^@Y69b>MZ-wa8QRHNWAL-tu-(RByg z7X$E!v=S6n6Imj)D<^LEmlw%zISfiFq z)ljbay~zr5|LXA)41qE*w==)!!KOUMBDCsthUAOh4w_?(rl;F>VzmyGiV|sn2!U=B zVfH&7A$O-U`}@WWtRlMfSp%A)K&ADR{hyCvkC9W#^BnUP{5vSA&H7`oA4b+42x6Nf?$JnC0FEL!ssx)a zJzXdR{{cS;#)m=DGyi4tgG{7lL^VhJto6(#=1@)ZJI2f&mPsD#;>j@w!)Obn>nj;} z6{q3-IH*VupA3onv;B%~uXY{bs+K2c&=8gUV*Ox~j2Yi7Lj|z{@_Xh7p_H%#$yue= zqkSJn#B#*BS{sMrYypZWcn--hmmZ;6?ivi&pa4Q^HO(KVWyMv1T%jDIN)Ra$G3W=W z^+$lPt4gD_VWtWoVvOAfppJyNwD#Gxhga26`2*4$_?z>CM?u$s38!}K?{?x!P_)Xv ztEbHw3Lq>K;gDIR9N$7faw;|z*@TidVhMv)%?tGm+4wh9w z$*~D*M!q&DfO7Qu9hMTOF8+^;Vn-h}t6R-fyhOC82_cCjxgq$17$lY;K(wyaY(Q>B zpO73$R1NbKSbmE{lV;cgvjs|t}9x& z{2;{#R>w{P=nh7YhL?)ND9ETbAvL0jY^1d0%`l!gSq6Lw#|XdkLbE0_r4c`Q>05=S_!-)jCh8;VYqut$r%i}YM5R^ z!CbN=5nIG?JhdcE;U|1UdP8E3z>?YskAYbd{z?f!VUrx(`T=Ukjf6`@_*VrFkcnQ%@DP5Hy!o7K9S~g^|5mf1 zjlUN`z86jyV-AE5lwlmrZZ|8~k)fMJKe_vc`1IgV)9+O=8jk9<8wjJb{2vf1KJ>B{Jt`5d=zc1TZhNJS6{L4gwgXsN0ZlMoI1I-H!V0ZQEEi@v=WSum0GOOn4k z#sJxaM4D9zqLeT~{pXw6IU5YOneQJ!T#-TMmM2`>fv@!n3EovZd+dG#vEuz!^p*R|~2QPrL~gB)5?kfi$X3 z#EVpo86@BO06##$zh~G^LzgW+e(k;@_qCLp4`=% zI7DE_2*l{GlRFJ@r9y4+LH1}_EC1k--6Nsu-jt;o+i$bRroxh7H^R-p4pM6K> ziWB{=0-y%1rcu2ewIM2@ry(lCS#yM98s63%xu|#<6<=baLGldGkWx_{ocS*q^H|0N zQX5Ol0#wst%44UUZ;l_T>@uKtY&-W01$zC{o8XMn$KFK)mEe;~mQmdsGxTojIL3r` zEI>)9>Th<-W6#2bzg$3l7lGWn{60p-uSl@N$zIKWZNSk-xEh`duy#u4_5+r z!~r&}6}uPvGDjdXya=4uC~W zuSzZIMmM=Z2}&OIaJ-1|sQet04BW|{yQ`wus(?Oz;%aRNPaLh?WogN%cp4SoSWd|{ z$LNWxeW7EJoC^$+b7^T|Qf(pml4T-YG{1Xcy&Hk(6_RhUF5hj6effRI!uBmPBz!9g zcWqTeukV-aj=1R-jdh*OWh?Xpx@?JlJh|E^RGe&AdBF931AEGBr)(!{o2~E1TC)xM zF>O~Sw3b%;Rs8}T%zvl+cg*)qkL3q@PA&+Bu^=Xqlegor~Kw2(n0u3 zdXJ(FN+V=~BqX&gKe!{-b(%9!+?C))l&*P-tgguXK(Zf)0L6KBT)!Aia+|hUI*tggYi+!(S zMv`V%Fv<~bBw@8M%5{vghf)0!O?_*%llghoetenlqh&u_75j0|`t-k9&RjCzd!4yw z-&;8=^L1OShp|S85GgRuur`~2)*QGvOg{R40V4>uqp|NU+Pn*b&5Y`9qcm(^#fS+r zs%>G#KE`%1>>K^>GwG@PH_3NG(kr$8OnrxXXV;ph|GkY-x^+;k?wE|Czf<|Xh$!?K zp<(h`Mm8{O!r8a=-wBa(WEj?<*x3zcjZR3Lrdi4ggVh=RcWup1$W15YqY=SGL+&~9 z4;~7bQV}Dli}l; zbw}Z&vHccm4)*~@U37<2Fl?`Fh=zcpCNVg`eE1$U`#6(GO# zru|GySS`3kt+6dZ>t5GT8`qq$*=3A7;*|_xu^kjFg&43&h;WYC1yYKa3c^`@H>Av7A1KXe6n?0Twk%S*5*;f&PP(~={woiPIv}7S;k&vq-W2& zDvv#a9T`ch$7e(KsuWUwgWfr2S+%)VSRqvA)zR{&%^-AUre-L)f+k+r{EGa)rLmsIGVv6GXc*|i=CbbJ)V)byJ4r>(y?F2us#-iRu$&D2E%zGG4y?s zPZw&cia8jPyLx;q$UjjCNPW8{5vvF#r<+;)aQ@%)xWcmz@9&5*jML3shbQOwtdLbqP}{zFKgLT4P&+t{LkszcnKbLk(-jv!4bS;U1(F_s$urM89GW z0?Vg&;drO#8LVhw_Pz-NcXRyeo+q!*M5|m!{K_iFZ&-wiCy_*)<{m;SSW>|cJ~u%( z)~EJqgW#wN6f}V7&e|FL^vGb-egDEo=z|=c?4yr8Of4+fXa_BMI%6y14dn+DL~5ZPuO4b=vD^9=cVheqnmwD_k@ZI!H|PL zAwFHF^PA%+D89b0lFq>NXeXdJ2HiznqrpbM4}83k3@q5~b1z{9MbXDxCjG%54Oz(O z3f?*F9imVAZ{K8P5B*%XI1pO&I0!6DeE4jxr>;Y_nU|=NB-5Up^C$x@h8w9Bh8q&w3%KnD zLZu{Eh-bHkLH$Fh#KCZ-bs-@Xg9QOYGO(v|YDp9k5*R|IBv**1Cx zhdi**)@pji6#=qT_Ip{(P57956(-zwo+pe8!u|+LmaQ4d){JY=rXFS=E#@`SM37mH z31@R^{4hpnkSE{?nx{IkhBe7$pLsQj#mg z6J*MWv?d>v&-+$2D!&E1Y*8#SRiZx(!*Ci-u?q(VBUI|P6+R3*)22WkcWwB`T{yrd z4iM%6gP)kXj`fJSoI+tucQrlTKlsE6I>BnFVG$m<7*&cC;Yv#@L&wW09Xo%Ji~hka zV3b9G99d#(cv(?P9#NB$MqlCjK{cEpmoQP1O)~Vz8NgQpWZ<%9&6pbfrM~imK;Q(| z0AVEoLTWGpOIJe>!QGl58z2v|F@D)>esByY*kwns1q(QxptC}d1F>SYqPi^Z+IU2U z|1R;=bo|$V9JtqvaF!k81krHf9U1xv1cqRx@CC$|l=cc^>{h;)=gMMw?)MVR*mr9* zQ;m#K?eE5bT%OY}S7!0P1G7`3hwwOe1Hlt4zl#j)shnC8#mbNpDkZr>Ji8Db+=y_f z^aV1or*djZ)Cxn1P$|h3;@Pd`$aY}GCjnF?2*RlW?3U1QkxC&?jU?B`4W1k?2*Iog zwzN?yqNNKD<3o64N)&D-N4ynl=#BZ{!#SqS6AOP^D4{5;rufznXc($lxh`DE-eeq+ zp^vBDVzMW(s+`innu8^zWPZ#v#yHk~Y}?yryWQ6H<_3q$v#PfkvyP-AWQ{lW( z!qC0n=p%Hi^>o{E_AC-z_Z;2qbJp2`-IRW=%G$ZrdVEA=pbhug6{|PHC+Fr%k|YeR zwTCXyF5H%gwj!MDjrF@Z&;=J(}VoNmVJ33hm<7jiQp;gRAnWJymO`vMNqpuBuJl zMU_S_Z6&4a^7OKHI~J#6t*dRffI=h%B5I-KG0x!Df7V$4Q5Ud zx?qI}UHs&*c9AIsr%ERSQj#W|IK?E@4p96AsTPjEf|J~tr#M{;PInIBeYxx!B7Ht{ z!YtS+T_)ku>UprMin-LpS1w=~VZ$76Vdy1}zrinYA;bnd0%5c=LY2kTVl@CGY+lS) zaCkt>5G8=4dQ+p6$SRVg6K+8lr6scIufa-d5VeS=h#u8gK?agOwTO{TZ|qc+GfGJg z!lq;rjvhQ7AS6(H0Tp2#v)1Vijx0H%b)5yv6IXfYYbyyWaEs0l6+u|37MO~nK0hb` z0vZN^>p?<;&92(vlcnv__2@IrI<~#WtC`o%^}Lo?67nrZ;w~ z${D332Vqk(2}chhBG_iLg&@K7tan05!l)mrbojQXQ!EP*LP&Fb=2z`{2$7JqBs2hz zsU2e!Fd7@S?mD2hY3LbTxAFtQb$>2S^)P#f++5GJ5u>EbNW9CFi#iwS=ASk zvm)xcOo`}`j*lx`lT>ww+w1|eSlTHdIaez_leh_`6eq!D;gu+ecDObrxR?T*M8Qq^ z65t_S_*&+}*+u1wmJeFKxDSl#(^MCFR`#1;O?9oDh53Gp`m#~qEN7j~&)fCmYp&1s zm4_*ssZ-TY)tj^Tr7bG{no&EJvkv|JW`!5V>&KO7nhLH z8rxlgLz6iAgGzU^u3xbkJcH{%Y0D zVNJ6Z*`iaKAbyp4s5HyeII>(aH3R_wC^J+592gErJ&C(<2# znTfnNu=KnuxES`jE1)3j5C17UNoWXu1%G1r72{tlKVtlfEE>mBgNX8E zwZw7T6Lo^U%EV-AxWl5rR3j?mxhN`HKXqN407j?5^Dlio+de!U@7b736aj4Q6;t8Y zXZflC#Fo-OSV)BQ0PMKCSvM<-(#!06Fv~4w_b{8@%yz@9_sY{M{~V5rBC#MDi|!vQUcKS8sN#wT!!kOHuA#2li3dkq!4sI z-u(;?DCDpFL)NYtB@9`BRY?4r7l1%@ky3D?bO>3nRMDq~vQ{8CMOFvA?(JLoqhQ7AL{yvMZUX zYDt?Kc~dk-1j6^sf(}{?R&KehJKD}}6~cNj!9a$#aapzKO&|peTMY%ZGLvg9lvJJo zREhNoFwB^$mb}o?VMxx#t*8OJci9wcKQVh!8RN1N*UU+u>~|Z;-A~!ciC}UN+unmH z2=Am4AOxeWD&>3JCc(;^6_^$}{WTVrE(C))vi@2pg<-Y{qbMtd$;)S6771)n;E2JJ zMMW@@IjLTrZ!&V692I=QJI<=F*BnvOWA6DmH4I2Eb1F3IC_bI3G=~KMOcs+Dk z=!V5~EQpEe7ELnB)8h{f}PhM422!<;( z%6nC@qCpYkRVc_?RYQ`0Nr=_t`1E$+l!HYR$^YVS#xQiO9E=RZolSiCO9KiN)Lw?2 z(iiNeeP7L`ia$CKf12IkTmay_TED}Pe4Ig(W{gUt* zkg2L&HJvY=seFa$D-r&dpkG6bo&a3x2%4iiAG3nlrQ{XRPIqH$_xXwOm(HU|t#TM1 z%8kp*F4jgh0tylh^M9x^pOFmCacjH@>^<+WeC9w}oL^q{OO$P(xSEtLg+}U$YHuS% zGEc5fTLr@-z~H0c*xwhRdi^EhDp#VDD=rl9LG#)X%=P9js(WE+%4vK+U8wZAu$D82 zRL|ap9q0Y*2?8qR*meAhI87TUAvN>Ud6hfSA)bh_&PG~H%LRN8Bfyvet-@HuoQngYolX0PXKsiH^Mv@(0c!y$4E z=ITMml4(%tmE!*JDQjtFq+h@PIky@70(?I~XxS?Sd44HRi9B}g!7DmL3BW&9HO|EY znbdmrdXwMI=^Wf}JJh}TO>@U;nCaq<$iKS@txLPOk(<)p`Y)BC=$XvVDaGt>c)g*R zYrd4?NdC{l$#12!oR(u5v8H3>DF+f9v;b#B2VMrJG|vyGGuVfZqSGxKX9YskaDb^w zC9L(m&l3|95iQ^P;hQNR982-&;z8=Hhu1dodI^-HlK6|t#szn!J#1KGdKft^iZOf? zpT7xl*Nnyxy-}ILIYDCg#%Vcn`i=BR4hQzKHQP-H4iT|Vrmi_6aoQM*jj~UnXxZQg zDH?-)P>o6!fj}tdRs_&|@S6xk$0Z&{u(X&$sgdQHpQ#t25D1{R60|1TH=xy8_zf)j z!78!nWY}QTH&Q^{>69&t9e(OgE76dv!unr)I|J?Y{-=`^9lCox%#{`PV3Gqa2BV5c2&-$>;s^Z-q{hA>$1Xsn&c%bu**vJWn<+yN zT4fP9D!eSmb8+0%o>Q@fq;?dksugz{KIn}IEiouBWud%BuY@a*_X09_MGRr^O8osC#?Xhk*!%88> zGGii)YDAAM=B;vqMpdG|qOCR0<18UO;8NF4>fRZmp(dgR&lVzD3=I^~%GRDos~M2a zmyR@{Octv71lw19!7fT0JwMbXIi7`lh6J5qu7;LxfO;y;5y+4t@E{xF^KklAzh zgt(imZZ8m#&V($xjf6Ivk+h;_TG(bYn-MP|XoDQ?nqQy_22eEVXDj! zkn(;ZKMvJth$Y1Rm`7DsU?V&TJIRh;D}2w~zQiAk`UX`jUD7TR?ny=60e6okXot>V zj?Os5o%7>J4Y$nwLp>_IaYjb8u^^1l*fz%(g(F@Kh8DGzvuF@D5vpv1z_bWW+1g0| zOtj|wX%=jrUc8mJOgm8iz5yuBiEWEpLs_;jJv-PM$5QEC1DuA|!VM?XWKn{gt}AL# zTN9>oFtyM%LYJn%LPFbF`o(9m-gssny>5R_FR@~R&)e7Fmgp@7mS6u)P~GBH#FL;G ztAiUAH~VW@Vy)41|hz(O6ae(19YVR!wXSy^mQ*2pVi*-5K z^Dx)46&Q*18xQzu*z8+ms0mw1{X?wD2bJ< zjQ~+v$MXvqfMOfymTmK=#x|EUV*ZIJ1rTHz7iTL}?M`@Is8K5~oo*Z~g+}|_vHBG>#C+OWb@YF^X zDyQdB^#xEs=7i(5M#;(g8m$;OLjc8u$afMiD^ zx%iZwUS-zu<4KJf7DKp$t{0oakaR5WyN#eo$$ zJxX-sh27F3xP#NN5h8Zaav4>u7=BLpjLH|fwP9oZ5Mv?bQ47j$)$)YS%f{!gn(;ap zg!Gbl*E@<#GbJ__lN7KRSK_>XRwI8^rsCX0FJo$sd$)g-m)Z>b5gv{9a+*@q`)iE`vlP>VB<|6?R$DHd+thzmU#NH(!szZh{+^w#vlF7{|Bhs zpa4qd5YS{`*;YOk@Kuc18;n|H@W%65)L(@S1LXTOcThPSl?V~rf=h9`)C{Nf(W5WD zc^gc6gxud}KwtrKV{Ux}JvSdDGv^DnBv>4J9=z?*2j)?^db^PWPfRztogm)2&MJAx zTah9fIN=4{g8ijHlWg(-tN8bjZ#REvB0@J!Z~<`MO&}tDR~8S@GufpJ~>&V>NgV^ zoB&M5Y2)-bL!CGbIGe`TzXrdgCw9sJj?x37QUCC^7id7cLGasU>A(O6o&f#IM3#Z zjBt!EVurAK+`<_U!xj;J2IM2=uyjC%_u6Qiu6%pTc{XsMIR)^%EFQ*A0nNsoKfcR& ziR21(ItCdL9N-uAn(QHp#dR_59Y-29iN0fvJ=9+Y3OE5Pr=+Ll$2|lF+_H(8I}b?Q zS_O|>P4jP?7VBbIaDTvs>n9Vdm){abj2zIE2T2n`Jz1|Ia$*+yW)5remq~#Sh|SWN z1wG9U?5Q$u{(*#BrR$8Q;ume;%}J6$;a)Mg9ry`;80-0QoCiNdnMW3o!23DHe_#5E zRFA#aFcZHd)&thta6P<1n1A1A33wh;29AOfxWXO&WbbPiMgYS^cZ1EUtx@0)3}Mfs z=>%Y~$JtR#1;d!%tLpJz3^gHulX$W5k`-(@5keLw|L?3T;%0OrYfEdX;`weH59-V* z5-MxC9@e#il(!|VOk_hn4<+@v-_|B8F`_)EzqfbAZ0J?56KIq|&nVlsH}|17aSu>R zGV&Wn(R9^HC|3d~U{M73MTN6jE_iQ5?Cp<383#<$3l%(a{du5+Hm4zaJWr(_9CMx$ zdS(vTg81ll*%2>-NOhira8SX)$>P~s-)0w5s!RDuiK&cVwl zoL$|p{|^Gb`UD*#ho%u7@-H^^4~H{8~fUrEvp^9J1AMkcIVn?b+0 zAP&u`LR%8bksCuyG~V1frG28ZtVx^c}0{3?T?FC}|J$MNoe%fl_@C5f!CO zT+8blsll>Odwo(t|E~P`!qT!c1PcLrq4X8-K9dId-MP_?uW?f;S=S#U^{gX3XXJv4 z$niRQyJ3r<8P$a8JZGxps$rkwwdNNQ`)bBwX^M@$l2t?zwt!1J zzkT9ou`iqCgk*cJYWuh4q7q|1OB$g;TKa&bCORQ|FzH?Y39n8B75*V6VwtSuuyUX} zy6H7$Vfa=r+8CC%4a)g3{J!4}5Yd|x!O$^_A<}UA(YP4ydXf8`Z0)_+u@5p{WfCfx zjmJes(!ZG9NF=<{4G|LvokP>o)x?Yh9t@Jr6aOZ8n5)2}voZ;UkQ!93uSAFF1Zi51 zlg>Pg+Si*TrZY>$#0d>hVBV76mfLEbwSl%A|7s~3S7_59ygeAngci$@z1 zqSPL{m(!a)SjWDBR-b7yGbYTZg&9pt=%Dri-Btq7h854pI1Jfxo`#G{Kr3RKPn$!0 z`_((X*%V=rn@ds^F6x&gPbM~@k9C`|OgKP{u`@y`%_QSwXnM%z0nGDQHltG$(LmcT zp~23#8}vmjFs25vA!bH@VKizC(W>6r+m@7IlbChs_9*v`?UfPspyK63rx49?gt(db zE$H3@Wn{5dgCxWPmXFe{&+?Oxix`dA$MU>Tq-gLhX(k|cKq%x9$j1U6Y>3?B#(*uKfL-u;c&rWa5Itw}%s*T43hfY)Ym`SGu1+KE{CNVjO z#Yc9aN8dbf*ed4CeOcIJq|4o2B%TTsnCgURF?HK)pf$By29vB2)Emev|A#5HGALBl z#|n#CBHZP{`oShSiT9h{#Dn%OFo}}sviB2Onahc2B`>VfYS6$cI#v}h*rpSHKP~tK zhPSKP*Dpo5t`LEVAQCwK$pC|Rx?av=fKZsH3)RA#S9b>}r3$$!r!XHpJZ`rdO4_Mb zUG8I2Ljje5TO*ucDY=%$7gR|1Ve7=$%*0a*(=)*f*}4)lSi$Hf*o_=e4Bt6u~y($BVuM&{?Dg<%|90wZAz{X)rZ7`Ja4FWQ{c?gD^1!K6u z;P2>t)#E28gi`-|cEcx3W2r5}*9Pb9(jzlV#8ozUvuCXZjU3EbJ1W8;(apvM0&Iz=$v>fVLECwe{6=#72{+P!Fcq1CI<-FfH< zqRPK?^5WrjO-+9P+Kl3zywukNw95rL%8RkcROMHK<}&NwzCG#nPBoeR#XPTo-JmF= zoNKP0nB;p^LAZ3g6eb_ZPDFotjW7?}Ta&L>d}6|sDqo4>!O6F<%EZZP8j&xVLw(RgiImAhiahnyR4SEr3&A+>M3HIHJ_P+%_v7-bcPywi(L1cF5I zvbsF?S@+WKG+_F0QBlY`0s`O}zH@T)IYlq~aDSV1DyMbwcZ3)G6oN?}pl^(<5yiAy zx?x7(2g5DV6QVTJiASa&pW0Hthk;7ot#u*0YbA3*+rC&TN+e>j;svQ|!r(%VG+y8v z@3`b#WKPC6j=)89te@0+c9`XVJOFD}c%T}{0sL5d9Gfi80MTyFnYew7p>1XcLc!H5 z#CRGw*6)K{3YsyRz~iP1mH_7w{b1WJi@1YeItfacWu(j)?O`9p0TOAK^0(r|k&)?__cLVb(#509Vl+j8D#=tdDljjt@_sKCN30#IY^tMYfYZ&+Q~vDUL_N z#@Mhs>w&&wz00^~aT3&>^o=IW3NM(Bi|b4d*x4}IfYkMa$1ox6*?2O2qz5mqG z+`A&B9|8FED(D>ck|&MuZbkB8vSLhBSkMGw5;qxRWj&6Z0nfEg8*ozN4$I{xB_1xd zT@c4Js}KOQk5lCbh653t@Sh_gDnOWqq59;m4obITJA6t(2># zxcIwRqIQVECHwIk*9R|6C6KXl7bDbRGGRt&fbx7YubLuZ@Y*9ZdD;XgF8xkI#KN#t z?Zr+|nI#WVX+og{lqmJj5AX$bPDa>X7=@6rqjsGVz!k>dNwxutu;Ejj<$K3XGEp&f z&TO;(ZEC)+KC8`JHRF~=eP+4f`PJI1(j?@l&_?qPEigk=IunrJgXBXdi?DVZFrMVnq)rD+7+kTf zq1>+(QB|vn4-L*~v`__A6a^@#c+z3BsD2j|cJHjm+#0NI-KS9x{^?!jhZ?c~_Z?wPHzE}YfMz0HL%#>xJWOIYEeR$)dY3G+ zt6LCw<;I|2rn}B{bOCVm4>Ym?Y=fxwP&csAZ3ut;bWhErC^sum`l@qlq#9HCGUFP; zUdRmqj8gji4@g8P5GT8p01P*-UqdFym=y2(<3|l>lgLAL>j(pJlEkSqAiW=tM*|YD z;(Lfm7%DipNO9E1jP2S4Lw4}9q(8ocKeVd(GB%6 zapJ(+e22NS>D-Mv95m}Cy-k}jx-7J8=B;r0AfG4u5(BR1<7M7Nuc zl!Xn~z?FmY9LxNBVZpCJ!N4hQS_Z&xJtjMU2$*Y)PYF`>E|-+GF~qwfUm_9j#MYUX zP!hz3!5LW$%+L-o@94|GQ5fK|r~@?C1)SiY;YDrrxdN>`3JsjKA^?Nm_K~94&eXCXbxu*Vl2wJ$48`F@8%jC2S+4~{*i9z}kXzYm?`H-?Q)W;kRD6_&w z?OdM)O0jl^lzT0@0_X4(-$(DtYE#ZlDjv+yVbwib7RqMG_v@QdPoT?m5zQ=u_pq{q z5&tT=wqrcnPpQcx=)`USLDeq-tD6=8uJZJD2?-#k91M+H_$<9NGj6v@yPp}xUKWlE zPUeV$JKc}7Og$&zESalT)O+843hNZM5 zxZadf-wFj|6_}r;+y)C(4P$1w`kEmRy-%_RB!`v^lS7E#Q6(wGYz}oqbrf^7Oo|p8 znWbm&%-sOT!(g^0YSQUjR>j6rVX8QCK_m?dx`Tw&zCT~nvxjFZ-*{k4b}PWQjHFNzzOw((?TpHd#gWfF>~CL zsmM(0%UeJJIQ(p75E>xB8^fHmlmQrpJXarQ*^Y`Y(HGoeu_bK;#^8+MXp5ZXVHWCj z6==`;UbRTclgSJjP*|D1?EjZ8#Bvx&`a1Ss5b9BsblRkEzF^OlteMQ{X=g zOQ<_^ZFw1WVWfl zF*0yi^AdQ1kz|+^Kn~6VB{_zErAGZDUa7?5VJFfIjIMA;$sy2QCJJ$T@^ED9bX*@0w|Vf<&UC@#6!!mg9)dC?jICmXzh$tkni@F=y0l)8p_` zzMCf36k|cK9{()Rp+%!@;Ev9h*Q<{r!8%_T3l7sT>Cfm`FQ)oQwpCnk(Pcg%8N7{O zvxIOF$Hxjo$a-AC`DOi}5*0(4u5Kd0-^3Wu?E2hjnqym68DD_FBRH14-M!y0#TAGn zC@dN~?#fu?C;{l^W^1=#a5W@@z?LY%H8Y6hHlw;Bs38chJ)&0bB@+)VFJ7Y@4C(cg zS3mw_Pv9kE@^1EdzH)@(QB}6{HMnW&Ihnwxypw)@rf%{fj^?a8ppudX4|39o23oKf z4(W7YS>9sGhK|-LL^RJ?Pk#iQ_*c?rU+8`T&~V=3)7?2J`p6H0>KNlJ1drn*+k^~u z9od2%KZ%LnW%VrEiSDQc5p@<6>wHN9UJ2s#soi)k)R>B>rP2XGyGCfhSs-OM3$Xpf zkwnQM>Yj1%@-Ux!MHu5&56FTLy2l@yg|=Q@m*?c;XB%!iOw6)g*Nop&EM!-PX1u~V z9?BuXms^AN8v*0F5UMLSG}bI28O1gWEofK3a}_$*$D;3c9;FxEEMNv~k)1(1l-j~W zEE1xU;r7tIi82AV!uk}I;U2?mxuT*3%p)_*)sssl7_T2kwjz%8tS>EE`Hn@sa%zk_ z0ld{}GfWMtjRX~VWm8Ggc3gA=4fd|t9vD#$@0VRmZ2}F^^QLJuMfLO2mXI=z!i21V zEHi8;YhLAXF}TGb#D3)S(_OeoeTgrvgz9Bz z2UWuwyB&_e$hs&LBHnlbIl4rgKAnSw{~`7m^7|Nk+RdCpB7mL=*fzRDxJr1-_p}H0 zib%ajH{(Id)sOTYse&wky&yH=g0XSh#Iy+xMR?_(47TVa%6`)C1U)H$64*1$X~9h2 zL6@1lp~EY6wSOF84mK!>BubLehSGqkT|Q{l(~!iS}Y4*CnK2v6mZy7;&522a-F9dA^5eqza z#&_9LUT=wR%)YOao7|-`fkct%wA4!3Y$lD4sbt}nM%;-bsY&NQ*2+f^#_o3s@soX6 zTkHiR5v&pb^7gyjP z3(kaz(qn^x!@RO|CgKSXtq2~#Yh-r3BV4ztCaDG%a*UIxOT2mUNi3urNEzJ$=HeTM za|9*iREX^E45YUeYZl_^MRcr9CQk*LiT3zSOSEr5F;d03j0BX7SoMJ#XFBF7 zv76q*j~|)6+S|b>f1d_OX_JvmBE<0i$tbXA$+n>B!zLeUyiA-R$@e^@FUucF8~Wu`MPAD5EztLK7pxBLb~M zjw05CWDc+@qVXp51OK@L(1=UK9JT!bX&to)dF!-hzp>30NO-W*4;{vH%WnQwTmjwI z@3E~?%8ZsNJ)`nkVXhQ^*4Q0=_>pDpC++7!$g&&7N|GRLDk!Y-N8WPQ` z39b`9Jl0+{AZT3BoxQ2CFR&_4v`5Fy)=bc|UX0>^klx7wj&Kg8I_EBd=hDMQ`t z#SYB2V&#hCHa>a|*TZ8?eaTwBWROstNHA)nDB}qX89fC5Y(tI?SkhhaTW~oMIt}Wc zjiP>LK0hK;%OU$0L(<)D(>)!qTAL{kxKh(QuVeJ5Y_8DKQ}=8wD9p&%QXx4iuHSTD zzKGG%nQdP>xN9|@O_rV@)Ba76!v*ZCT#OXB8C6?Dp|B*9HL*I;*y7Cl$DNruc-j4F>dYHriqz2XW$FDROc+wkB4BpFXB7KlZ% zpbeTu@+W>S2?PO8AOhQYLdmZ}VaK_S_UsE)0MJ-{QSc{tZ0ZrIzXKyl*=WEM?P;pg z%9fToCWW|L^s!BTev0FPhccdV5enhq@A~ltGO5wQ`kT7NSfs!$&YnTYtr&Z9TQ*a9 zOs$>n6BVdH(RdISkUNmavd$SHj)N>ZKvx?b zvz6?&@lL;58*o4~ee}uFiAcP~e8#YaepDb0W{}F*5QmhkOoty5 z%R3iMz!AMyVQRx!L}3pww{$@j!;ijfD*knt-iY|ue75z0N zei73=?e=Dt<{yMDXmu77IOH+fik?z8FM-YiP<&}Vlh#PGGC&1CQ5phwZ|KP}p0o&I zrHS#iaGGeI%PrY$3h>eJ?PrQa9k#t4@;m4qJ1y{(acp=S`)OPABPfpH!v#q$}OWqrKC8!YulXOKHM2c5s(7u_^?+ptR?)Ew@ z10eUpiy4-RQeh)Ps@^c`fbl>kc7P8!V;eDLYj(`u!au4 ziU+&G(f+G03z5X=07~b7@A5_&k48y!zos^Eo|a*o#)IQddplQxcOkM_N8#31k@TgA zc0i3OkszSX-Z*_T?@eG-U`V{m*e3fN#huk`+^R{RY7Uhku`-_c*s>_8hP`T{CLSif zA_cvB|N1Jx;}U2Hzr-@3wBeBgL8x65?EzhV;7%ffF`s0UYriR@q*fzwb9hnxloYX6 z-`f-t@h4)`tE9TA0QTnLiZg@roY6!38Gi_)S)W{QU$XbYNau|$01t0*)SDjr>epb8 z^Im_se)QsH#Zb@+@$Y?2%YeS8>?YU{smb87nZyB08*+#HE{X}ct#V^1Ub4Na8KVA> zrP;TncOCzJVg(DJjw!4NrZkrepVn4R9WkS4W2O$+SJO^$f`Kf5$j-4` zLRNu+{WQuI^n7JkjQuDwH9NE$-oASo%B6q8gopWA^3*j}Jfg~FMzbXLcc~BVAwl&Y zjFN_NyFao`ay*&d-c04EEddf)C|D#|1eo>2u%l%&#hn&ITU&hgrASMaI3qrzxvQdW zOQ;3TbwrRRy+EUaXhwCULE}E^+^oG+cW1@+qm|&fO-|MV3PezQz^+Pw!Pm#LezfG}U&7;40CrUFbn>t%5S5kl@s;U^`Fn5in^}XQ z19cNFbZo>tz(mzV)vP%_Gc7X>ISVTbYh7L=L|u*4T)!=1`R>e$u-2lZBO;E^g%$B4 z*FJtBRw~1K`nFD7Spm;kxlrFP@0IvwX{ol=V z$qK%Fz|uh@e_=GbbK`%a5>Z+;{wL}iyi2zpef!^21KsOZ&Q0Vtzs@|CaMD4O{~0xE z)qvje-!KAE9O{BMyZXRz7UJwcogLd|4nuH~NRA&X0X}t!kA+2L8{U@d4E-^`Vtz$j z4r301ro=|TF~g!bmSquYc0E(`zeR0*$;2O_wU0Ju0FU$^uby0TXs#t3sm6R}|7zS< zzc5O$Y}}gW|81l+=?R}b%58dtX1ToPpHvH$^c1Vd7k{aLu-|UM+x}yT0js!S)LYNz zPfuIj532c&|0pVLX|=e9uvdf_H!GySBP>vuV30{`qf5u>5t7Nom*Bt{qlA%4qd)*j zaYRr;@Wa52al&XsQB3XtmMBQa?HFt*H+uO9Znog=#T{u-kZ<99WxJA%Tw+9_Mk2@C z-Bb8Gr|t$~F&RQEV)*&VimUZU+uaAtUwDIE_j`7~{xK#-C0O-#H?7jobkJ~?=0P)QL1bGl-*eI8@WJ$E9PL{gS zE&K@g)#NoK#16q^|I2_8F#=ZRjOQ^5Z`6>p5mGXNBoAmX`0F)i;y?&%yxK+}juVuz zFai)@rVMQsf{Ev)zPGR293lscN8||3vlLpOoM)CKrKMlBS}$%0zsA7z>tqcK-!f%M zv0HT9?7G1;pz5bM*RX|MMx2ot7vdx@iMkNMF!OALI_Jjn67{jnd!dVV(j|ROz6eM! zxWfx54=13EFuw*C3Bnp1)}tCcb_$+66z#~6yPq(EE6lNq&_+tPaQPWF=~}5b74E9C zWGbm|wfCzU<=-vifm8=F(ILiiR+`U7@e z@F0JXj4@lvjCcl03cg@Kxbmg8aY}Ch|4bM=ER`8q21!b1Ky*7N3sy9Q)3g(eRj7!j z^)ve!YyTB41Mj8@%)VH@e_EdckX`*zB0J|Jhy|Axv!gW!BAT70FWmCP2r@x3b~}5D z6hJy!#o;j$%U-s=h_X4(%kpP2BLB028!5>V|e3;o0!6Q zO^%Vkdv7;6A4Kn9iiD?``_PVS%syb>@gtycr!J*}L@w0a-g7LG@2*iFa%1=Vd zpQ2+-ZGY@@*Yx_!nw+_&B%6{Dp_^SB#0vX^s8#bfwb7m%mb#5$wz+`IwXFNG2lIk- zA6hNcgU->kEUrb9pyP~932w~EAUq0jvV_`D6CNj#pk&@|4|~fvV+<~HC5#rw^-%rB zn4Y!FZRo9BA(pw#{Oq3Ez)=77aQ$^&->bLJKjfPqTlw-&O3s2sAEq4!1>em=M_}2& zdnoNSml7iXSU`;i;ZgwD5)nc`=vXQlSQoQ4U_-}T??@lVngPd_Z^x&GP*IFPx^f^? z@{*78r*J_aixE_c2rfnFl&}lQ9E`PA+bw3m(vF1Q4EPlzSOkHM1X#)<6mXb5@nL_z z8QAT^B1|e|_Ij8Z7nE8@+Rd}-fGDmu0549EJ!oBJ0k=>n%`Rx|951|F74WVEubsy5$bgxJR$`r8zqvuHCi$!fNV1Y|g!=@~h>Z~x_lf+zC}iBn-kiO&|~Br8}t3oXn}t=?r^ zY$|^Gf}7qq5jpi3GH}#l)CL8eL<+-{gD<45_Je5x%}BV{!Bz=(-?bt&F3KY9Yf+8? zN|Ongd|NotZupFUowd1a=3%pib|x&TDqlkvk)!@&%2vjTxj{5S>fKpmmkiKkQ!1@@ zblJw0`^5#`uYQTf)o}-{jIky!_~nIotgE60(g|naX{;A1eXQ}lyKZ(}H_HD=K|i86 z6+E@LWUr+rU@qbVL=}wv{Ivc2FS+Z!{#PA;Q7xTADvQ14g=fLji$b0F5;$4}%Ib^7 zMHbWGNm#^{$uHEzfV%O2Tz?}ph|S89|L?Qt0HH#F9ru}kpwL)h!fAjaD8R3y9_*_U zfk6vF4fz6LP{N8(L@S61*T26v>k?iILwlHgMKHTE|9d4+?%9;xb2Y4p_F7f#KNq8q z=-WK0cs09z`kM3Gg4wr`yX%Tjqw0IFwST`@>xaEZ6Zg0Ek(sNQM+P<7i6O?1^*tX`YWy6-uMsJrjvQd!>Y!=i!v9cQaPwrkkq*HQ8apKA zkCpNwK@OZstWNZj!5t6`mEeTpua!mRA3XenLv+f@ALbiz24AU1ve37w>=lRkqFC8C zi=8B%rCAe}5S6#+TA@Jao;sdQ5Id0k08zN-#-f=2)<00N2~PjlWGyVt0-Y-v(eBNA zCLdJZZa#L)Zc&+?ZaTD{INglOH6Ag`du%+Wkd}{#)mGvpSLpIqY&B9<=7anG2oZtR z)t~b1R}3Hv&0)RF@TJAHllf0)%A|^U3;sh80Oq|z$Z4uA ziXA0beot%v)EgRegv130`XrGzLu`^@@9%X>H2LKo4-52(5mL$!S|n=9EPu<1^uU>k z(a|Rx36wDl0v5o`2_0G%rn?og4JqV}8EQlrH!RpF2;pHV?5B1e%wr|0(G`3l|I6-= zPXw@lNaE*&&$q+bW@4j&K5&G&V0a zGE>Mg0T8q#NJlIL$)TqxNS{Bg!Z`Xh@8|HM)r9!#7+|lJWgQHF=gKg?uSGU z3R1brzW_PNDDfAWPQ1B0AV&>Y#&mas$750{-NGeg%M}T?*K}39^w#gzH0* zCJIbU8bdhecNYyK_`5gO^)Hw>;0QY4_D3T44ngmE;PSi%GYg_frrJ9_epL? zi$`?of|5qh@^fM+@pP8Zd`GF3jFu}lWG@~Jsdst@D0317tWYBqsNr9*lE#B0>e2>K zEGxdU`-3<1}a*hC&;o*{$U(c<`+C8b%f6jpY+5lSu6_)1-<% zYM6os%DHW+cC{3W*tP=Z!Fz5p7?L1z!iv5g#m^Io_u@`QtJTMzznoclQ5zM?olcPG zPlRd6X3>(_6f$HfsWNn8mk?nP9}ucXwfxH9tr(SbA;U){<6{MFaQ+yT2OFdoQ>hu) zDb4Yfm8@!OG^su_7O^O1qg$+OY>+rByyHfsVxw_`v=~P1)s2+Kv?ge1pdY*oKX_-Z z*qZU0A!jD;;y}}UsJ*1*Dnb87MZQ(SM4%3_QRA-65!i3}D0e;HmblcIo0*OOT<4oa zt-uR6vp9lfxg?zTiZ$=zR6(hNjx~`fvZ6ApfpuOAlQ|H<%rDX9Q8SHZ&n8N%+!lY1 z9i;l&^*D7^K6Xh`>7j3Bp2*)P>L>MFs4y4D%Piu`>9Z=15c%WEpa^Pr=JML*n%BqZ9?&JWQ0)ryhhDAWTV`{>ou%UI zNIvhj{#)ka_UIR2|C_zM>)M~0-1gbwuT87Yql+r&u`(TWx%|=^&}jIE9XOi*b2ev1 zzrFp`A0!zqaS;n-jhcQQcQBq(V6`YtU9qWs?ZNpxopRRk+}_Fit3pF80S6XnBAARp z(lu}MelVMJ)Ao119~3L8emR*7eVCi$+5&n+ahAK7^uAS`nXf{mQ2IoG=;->Bz@=>w|_JUE|y2Bim```lRN{#!X}OqjUqE{hp`xPHMW4vL^-pR zsU9Gp7No2s-^8G4WfPU&?d4$=P*7P}*%(~;9qQt{O!{#&o=pWR+kH=tu|TAq_IEG% z%dIMt_EvRBr42uBW<-b01x{tzC9rSv{y}#HKyqx%78c zIH>A$AEg69_Uj)H)^1$qnPs%o>fqv9a7)y`HfU;R+9ouwI?K24&FFsHAw++gXzA*E zdb-ab@HM~h{DRmr+a@2V;Cx71Cx>}Wueox z2%5R7O|4h7U22%klCwFQ@Si-&s}HZPXZU6|Hg9+?ul2{YezTFtz&nYb@&OKFjS;vHdFhjR8m@m#S%o87*FnJaBPghhC9$qAKTECwR^S)u{QsJ zNCJl~9Ovog41Uxrc@pHWMiCj@-%YE!OWq(L;lV{5;;weoMv1Aclw?2|0ynOZw5!D6 z$RcHTq)n&t?>p)Fv)0VmNXeorz&_ee5SjtHj<)J2j}cE!S=4A#5P&Xty5AzcE=&c3 zGOdn|d~!=?$^0NA(4hsj5VRKfM`&PuEG9p4Lp%aT1m=KG}4WB z+k})=O6BA1r`E$*qZ7q|At4z8s=39K^zZaO@G_Co$T0vAU`&5KGKzQ3*e*#%Ski_l zSJJc=lW)ayW{3>q?-4_urYsfN;Q%XBAD8{XA(fA4wzanU1VnD2s_*Q7esWc>$ zlBkwZkc^(+ll+m=gTyu17B4o62MtX%+8|9OdcbocyB>8g+4X3X!(f&zM)5*vH~Q>D z##3LRw~VbyCJE?*ifeVFaOT53Ov6cs7^_l13pOpa!!K-77i>e+H6)v*9)*T}g{E-2 zFuLQZG~YFTVUWlj^W@2s()=24kQBpACRfUz(a~=Cp7QyPVnk38FKJ>Pc23CHm_%Ac zRJjP@CzjSvrsKQZTC2FDCbT5kq+eGjEqK<)(}+ql^sJ#_4jAb?X2dbIm)IP&HfSm7 zsO)d$cy>gMJ0Ur=gZLCj8UPv(%cx14Bh?6*{X@AU0S_4zI@UDHMmQlDGO;ol zv$YnyY+0(>y!NDhq|59*qk%;*tUU}FFQDtN<+u~ni5EM|5D97ew={Kts~wt%GnHA` z0@|NggyJ>gLDj15fdTVtCmrwV$Y`VZZ#jb$8r_Mc8EoIM)2?7qP9va!sk{JzgsR=x=46-|3d}dBM zsq}(%1eeILf`+M)Se+?jj!Bp#NM9YS-N`@B&G^T97*%Y_-}2^D2ND8Y69$F+J>~DM zTOd>$%o!Gz5m)o*hcN^QcAY{{xM)`cu4wVz5(;{ka&QD7ub7CbyF#IoS4sfPP6T*D zR6SfHJ4Kp9X~Hj@2r9xLfIh^~=b%VdGm6%-rl5~PVkJIwlZg}Az(;BcQlw7;x$sY| zpu=joa9Ys&Hmay-qS8m{`j{&+fBen#@ASJO;0O$g1 z_bqF4`;^gKHU#T-v&~>Of%QkvVh(ZTv9d*k-6iKvs}L^OK8}>bl{h}QN!H&_p#UE@~W*bmida&`J-(LGD-p*;`!03|)zP($Q>k#7hc?FH4 ztEy_|q{*<~M*HlIfGcH@edmQ)ITP^U=Ap3iWvU{wj0~I8ch>8o&NU@M0Td$EU4N0{pT7tOe5SZ8Z~t*?J}*fS)5>nq)i&L1zKA)0YRch7}<)0 z!~3F#!f6LeGvv^@37HXwqO(ba7@90t)GoYiyjytfS^RjySFW@0&MD^-)a}{P)*z04 z8Y~usb@9xOb=K^6cYc#vBJI>dyHHvQjLD>_3J68d&DVaV|B3{U|B97s|2?T{NFklt zz!sgpuiT;2_iWu7aCiDYI?ZE@kn0BX$JF`Fe+mxQ7vSLgKkC%b_O=1QmJ=CBTf4kq z)1%Y3!u%BT$^J3rf6{W(*(30Kvyp;$IzCQDJaIv%*1Zq=@H2;3@v?4n^N*m;cB4|O z>0Sa>;+NVMc;eRHgKW1C&p}}>`*nXKQi|WZ{C$yl00C_fPx&?rQD%PMR@2mDR|*gs zlYOa>1112A7J_DOC5xhKU2?jOXKl~t_FO%N0Ei{20A4&nR=Sb{zDd~BGV-vQIK@FxC@HvcVF6e$Nr(yw3IhCynd>dh1S^UdJB~DIF#0C;fC{F&!UWohV6pMhuP79;Bl|!S_h^{ zY$$4iSQr2>sZ%Y<+W=C{ah8s}lJl8?tV1D$ypLzGB~uJ?rVq^0m2%C}@>wwum1a=8 zI(VMk%hM*Tv%-PP8YL@--l*%oYk++k7s|AcZ|JXKGWyJgdK!PiU;EJ6&3YNJi?W@@ z4Gs{TT>kGTp&FNz*=l}==tIzR-J|SpMbWy>o14HIFr^wj;-9#0f0=Sc7OQ4*p4UF< zarze=ufPkUU5!r5JC{%X3G3La&W|#FA4D^eE$aG#m_2i;>3e-ni;}n+Ny~WM4G#fL zepo-d0|EX%K{H>J>p7t8#20WquSP*)h>ym&@sAq=ipsQJ-~|r&@<>uC(fK<>48VHg z|IE$i&t&&3Z#;laY^S?w_Pb2;4N8@D#z5C~#${kF50yupnWvA*ZtCfXi~v!x5jz-h zYx1+NMe=r_)OpE$c3eGFn)0l1Kp(x-z^$%;@kXc;hXEEsUFA1zHU5bV`rit4(F!{d zrMPHrq4ZfIUcaYd9TC#+BeL1`_gk*gwoWDn5jws1gBZRE@ z*y(m=29Zp^^}{^yk=#75^mt51!I_aVpyEXygJ92U)LGPjBwY7J9i~d2_>6yDgJ@S` z<|nz*S`g*0qBI(5paw^Z-jn66rylsSw8}rD4BU?tNhk%*igm@&6C(Kl~GM*Hsgreij`(Y?~DNXik?_{ z#ooJ5Lq2| zJW>R8e-PeGHtqW$kPMSgVajm_#e@HMwyhZRee}-wk^5!Px!@@e)8f$ioeDD=rbp{7 zZ#rCtM^6lWXMDIO5qd3STubRlVkV_OdsIVddC(rDQ<}yx8~l4Q@PZY*<+1Lff?(%< zK~_ulPwa=#U0I&=p8ny|Dd-RbNJ~V=+lD2Mp;s9nn7nAXqPnU2+Kng=a5pueQVGSO zMxh}CdZpl5Fy@A9d^?z_Jbi>VTsSRFVS-pFsZLZc&0=A9k-KPmNS4szQ@&PEnAy#8 z?^*Lr#8If0!k=MZ<*AFojdNBJ! zw}t1CvGkaLXt{peW%R+2-WM(PTvMrUFLm#P)xijsD1mh=qCs`M6phQ=G?htgCiWm6 zFwI{g0*^$BPQVE<(Qu>_G%b%1R;Yp_or#z(6Pbwq=tLSv{VWZ4w~gYWKooc|L4CnP zvo|o)s)b%S#lqhP7g?2LFAJ@H2}0xaB5}*q*&z%P5tm*J8Zuq?V?=%vBJm)73dBMv zv+c)Ak6q{ohnG_uZiB&p0Bb`29^!{LZ7eVm(2SuA-!&Bo{Y*JTQ3h3A2~ja4)}Jfv zQQk`p89MB87HU+Gar2i#hhRst9Rt-a$3Hc0Ad2awy91|DKRuSF6SDU~iY+9ux}cR5 z>mxwgETO+(VZQxpf-;8GhAX-7%%-uNf|)W3AK5auk@Po$@T?=Jp*M%JCD06=Dgd2> zf_g_{dm0GI<(JJ+`u%kXm6P|MSFB!?C3*m3s9@SfN+_K^9LAh?;!Z7sBMojL7{Q2N zgN1jLb${qMR}_qxyvF#mOSeAd&wruJ38OAZ@<dnw$5{>*|KO5@ zd$hv!A%AH!wSy78MGG-}XY6d4U3k_K5qyS2Rxt_lnJ&itY}_aGuW(81*hC2KitPKX zYRX1;D~V84x@ojcxrIQ;eCGW&LPKCw=B5 z#js0He5?moHG_CN;pe@Hqlqc|TQzyFM*3Y|GYMNs|Gk{G_#$NE?fX~rUIN~@2V`*biThhAFfrOLBKs2KdR3P)|LDtY$z&2 zEux^yi%ZHy_?H1lGIgjGEI9lYn!nemIh?=DWJ?HVa(M3ql`4s7GM?qetguKXiW5tFz`lo?h}afIu+Rw$5f z*jE&bK}13@xV}fsKXTP=vf2{|B5Vh%I3(-2k5tbr^Y`lDd>Tm6RSH&&5P#^9kb8Qw zsE|~GdGQ)JHl=>RLxxSL_HNx7=JL;S8F14b*yz}J4hf-yZ3A}6m%YbGv0)>TOx?s9 zU0$XDYk2&Yz;lzNN>w;8;`?2sXQ-p^uxh~bH$qy7rJGdxb)+D&tv>wPxIn(UW=VT` z@f&X$VcGs3kyHZ?v?1&exqBwScaru9;~$c&=toJFk@H&lTwGjf5CmxQ!oG`(JqRpC zj$}P1!1o`Q{@Jk*Z4awLZ+9%Cuf>m$Lbzbe{YIqyk{)X!XQngqWy?$jSLTE)zpGZV zns}$zB>2NL28sI#Dd)9`&g%lgU8H{si&LCf9;FlVJlrR@{OX>3yZ`wl(rxOhYCqTd zt8kPK$^eQTMU>Fg|s|lU1>!Wd2al{NmQg zF?+`NMbFI^Lj(;Js6R>*mu4@YU;7qMjP$Msi}|uIh?pKs znm=@}1W5VI{EZp~-JatCK=n7>kEa~NBuVg)%fP$+Qwf)2zY(h9>ielvLI#J`eG;_= zJOu+Vb9@Sw%J6=3@MHqVzB}wqBf+ThZUA(ZEX>URe2uu` zzmR~Qb>}Y$(@|xhYnVh$RDKn$A4Sb!z(l_&`y=foABrhCQ z?u{tUtBPI3y)eJtvPkOwGI2;8D}*ShcJY`}Qf_|~*2;Vf5|5L4C+q<$OsEvd5p70& zL?&5Ky9#eQ=My4tpgi5egRBGh`0ddWJfGA5{n{-AZ9Gac-R$3&T#2Fkg zgo8$d7#r2Qw^b+6#v-7DZ>2k(4uMAXOUG5;ujCFgcQNd&f@F?8z@D&y8wEV>b{|B_ zPlYIv%E;MEH*n?)X2)b$wn2|pYbM=}VdF4}TF^)>Z~|j`?3Mtyv8bdz)7saEt`tZ> zSBx0!Lj0DfXry>%SfWB88}9;%fR=mC1E)o z07v5(Et^hF!D^NZ{hCGHdR{7L6yCFKv;YkB?-4#sOJ1Xu@*#BTew|{18_@E6a>m zoqk6|7ou%WNIy~Vm|4W{3CxLD8d>@k?$~gJzX1#Uz*`BkLYtuPu004zeEJu&LRnFY zfCR0Si3(uNITNqSKq6D~GokjpT#zzDb3zp72%y64?3VB`lA&1U1$o4#-8LW3#-yFo zs4{6U6R#I&-qhG`Dkjz`GwNJQHoYV7g}yU0&N6Om)e3|>mhxeT7{Djrm$%Xy3r;p6 zRits>pW#E*RF7AVXuGNtM&#KWOk~g$Y>~k@V&qdZ4hi7EMOo$X=@QD=WCM_YnZS_# zB-=4B?N0O{cbL`O5&rq%5_H}|WhD2qoCYQ=;TK5>2r}=^XD{MU7YWSx=Qa*wEYeL8 zOlT-b6@w{!UZAT+1_sK$*1`*Noh_Ed3YBI^;M;tv91c6SMdz;uC{RAXm_y7{p0Nw> zD(TM(y83RUZIh{_vULs0vDax7oR2mo z^WCY7uO#$}vJ%B90OR!S)cD>82TdRFY441^BRSo^Q)cr%r8^wUq@|?oC;8`0CJoam0^RW&U|%o^b{A(?UG!`e(eozoGtTM8f*- zb?m-Mdexr*DY9ZU=FZ9Hn+@q5>mT0y?Q;>)r8Bq%#8*OrcL=Q!i&Qi8r!`|PI#b0R zrsO-x6)Ej|2JD!cTxf03O6dd9usRE=_O z&C*CQ2)5z#i3tpx{sIYa_MBAVs9s)|u3ASXT%IzM5*!bPlMn5+5-ea-yHGrKn%p~f z0}uy#VUDTq$B)oLJfm#Lc%sTIK90m&q9r>b?#+JSALwQAU2$4z6a0>p1|6?*-+7=#Ec;*g8D#7rq(Gp+*H>_FY> zitD&xM8&JU@JjDZq6gNUMpSc&iue2uURQ!{62hXe1W1J53DEG^$S*@w5jft2X89dS z%Q}GTYXCapwsn>j)>yywPw#>j9F9prVKy~*LkVyF$N|;!x#g%dwQf1?9RyDny2b~n z*3wNDZD~#J!x{8@dr5lkhLD*ZPkZ;(a6Dk{HM0BU5}-p(EFBtf_khTSgHOws()IL3(B68Ql^TA}zN0pG}KzP#@`;)4y`(Pqu8vpvsZ z_R-^dudiaB_0u7$IoVdKpOznWLQ!k{0CnrdGETge6S=$a4dm5}iW^c7kHe%0wZz#F zBlTJCSohtypC5@|%i+jeRX5hSEet-H$5A~jgH^Mao|_%&eG;ecybFSu=41PV zEA%^w574A?6@%-1p1an!3PcZWLhKbv)PL~j{83V@VcM#JO|5G3p7MX^Q6{__o?@t7 z(NF4U7hesWo1bphF<2U{r5&rJjI3sisiuv52J~og#hG)^w$8x?FsWS0c2UxCyX5ED zbpSkwVM?+-b8?lHI68u|3-c`Wz>Zav*f7BVDhiA^0is`XjZ%5~w^HG?7lyr81q`#v zGDCzt?zpvsT!nrTWxVch_s=5hfz9~IqOO$-xdsh$X#bgzpDUzFhG7hSWWvQWYGCW( zvY`1!wgcWIg{xTtCVi8ZB*7%SpfZXz0+!sw)>#2etl>C}d4oZKt4XAyqK#4prC?)n zClyVUwN@+wu{l{O#kHxP70%bvaUJbyOO!8nne50?5JL+-z&GhOo5a@XpW?TTi5p)j zW=@$a6w6UwGsRk{w*)RbnEys?PSrZ+BQN<~)WL(0ZTj+L(e!pko{h9V)<8=2=T z;H%*dO|RiE!usp*<=z?j*Wj1sh?9-F(Feg%is#VQE-NiFLcV-)ezD#+D+J1AXIv3F z4hcEybHs>F2}H}J^km)a;oI!dtlib4+Xdd`$We~Dc>I70OC0#Jkjq)ccZ^h-QkuJGIr9KHbJLhUbyrl$`DMFzdUi8>!-ywL)HD~7MH1MKgjP>=G5 z`PB@Q9$0&EuHG=1L|v|KD)^1;w^kkqxVmr6G;00*6iC*EVYJOS-9jKl3Hz%iWuL!w zp&?`2xNs_4oTVfiH*6BYNn>tY0iu;2ht65(X+3uclbbCPW51vjJ<~=m7$=UY+6*02 zm+VWnw7az0ud9^X`?MjBV6}X~S zRup#eb`xtS@ii_@0gjy8i98a9^5ULz$hxZP*0T_{$D(1=8zFCU6H+$t#cL7BC%vRM z=*yzm$wK7S(ycFf(ltGu--?lbq{)R%RV~ssPLaQIM`B_tS6+Sd_~CEH-JHVJwM)!f zUFX@NbbgM|sJZ6*^y7VW?NlK(Kw9A;!$93z)4k1!fN6@R0e!W1*xG~Xbx6@{c3t}_ z(e>DW>_c$m>5=du3_L4D!+;M3#ra!xSAM{Lu~)ea#=YnaB7rt67^+4sh6+?94@xKB zUT@W!S2R+37v&^eIMv;8wbLYHdy`o^MnB{#qncv z5jZavVT~9p*7H^g8G;te7OfR)@but@F1O;P~&P%5-E(^07ACukW2*9&`B5LU~A%_YiiE&E%pDG^?0FB%;o z67kJW56ewh;9aY4jH#VTm=A0qpI+K`|JDcX*t|Xgu#-KJm6&MR{?qqK8NYd6ZWGu# z*|a=|8orSs9F>;$4mdt-T5t^H=IqhdPwz0G-|K!bg~4p0cbx;mdxlQc#Y`~hdcdZu zryEeZn{P^*PXwzfq%X{lI#pcN*K^AwF1TZvtK{&h%A7>H%J=|w>(;yIl=T=D;N$)j zxup@q=$|@iZK84usB@=;n}Kg%o#1nB$pg_2}~4`#7hf2)W&*je0>~|#@StZu}Cw? zMcDk)?enuq|D9#zD7GTwq#2Qo3nTO0f?ZtdDb1cNXeA#^1{kxG&NJNLV#KaWbO$O| zsR$}#m5wF*wnx}NpaSlaT8=9@5^RlOIXuLOqgWDy{m<>(Y9^@5V#IC7he_A!`t&Ef zdy$?+KvvrM7y%0u4qoz8<;E=5=x{-3e;PLwzDqcQWvhAkNMr1=J6qbF2KQo0y7}Yc zau#L8@wz@NP_awzC%CQ=7lddBJ!Tcx`*plkrM%2q6OOWFD`7B{#~X=DDVs4-+bZvFbD_G;|gYq$_t7C4av zNJMln$f7+JlvV6B4Y+R8Ny$6spB7yz+C5e5ygRp~OK3l?E$Sr^WbAQiMJkY>!PF)L zx_c_F3{<1AWubo2cBqAXf6gaUbW1bRNAV@?R+P2}r-Pf=5%5XUC+FSLLhUNlZ?3ai zEfZp2y~3m=vW)P1U8>njv9vLeHh*HGdo7>3*Z-5M-LSM0R+EWhS5u_Kr#@m{kKV*Q z=k)BfRFs^OE#4)`oI0Iiz5dM)2YFW_B|`28werf^5s@PCG_E|J+&B4QA>LP9M%^qP z(xTC0(lMtAs|DwkyBIaga!c(&@o|)scyruXORy%`p;KdG0xtWlsUz7uE0-*GDK%(U zJ}fWjogs3YI?SEv;G4VY`DwEgwm)gO@H+zV)g8to1Dbt$Zk0M6w_IY(7u@Z?a8Vn%sYczKAZ{ zX#DThWXqSTmOIV3a_`aca#gEA)h@s6_>QSL=t@DgpyTBAFX~q6d|xY>{GV3o|Jwrn zKYjmAGw`xD2W6|Da`=kNVv?@TGd$p?mCn$nY3u8B8RKr0=oGG)s~K=*gRIc;bhEw9 zC7Tqq4McxTP^o#`i2O7=Sy=a*kp1~9HFxgRrP7Tn-vwhrZ$j}*&4KL;r2CdVSI$8< zIYZ+{CuDA&$`>wJzCic*l3J{Mf$@?mS*_0MP1j0SX^Y!AS6ixDrZ`gL!fCWZnZ&_} z7{(}n6_sv5Uy{9gttyY%&)|irKeU@htXgAM-O*nuEMo1m@W&a#9)fxtXfKnVY{=Jw2IMz~pwmh5PBv=7yd&7#bWIwwiWW zH>n@l)pCP7!jxR6pYIUdD~jNS)}7KmH(2*w-`?^tI){(g4C%7OG0r}I!>KX&%VV~n zDSB`mTqn7kyBq6S#njz2YSya>k7sW6F>u@;GTHS7g`0wjE?xqS$N?%RO_1(S?cC-M zZZT#iY)CaGQZtrz_4Oi5R{O050Lm0}zgP#AKJ$Yd?XfELT1aT8w#sTpoN$4b23lQ2 zAblL0hAknD4yPs$n-<)Y1(hjInx2`F77FP-?LtGbbo_U8aB^zHsto3MJ1+oBU;>qOxDB%LbR_ly>>Ek;Jw8v2KO$y_v3g?x;8 z7^|ovXcE%L?%c|e2Vqr!Ep@1D5Yr}bg5A};P8yBG#G!qqIciLei9xN%5e|o9y@n9C z?G_}zR4qK7#vEVijK-=K>*EA6HEiRtW^qshw~j1A>m(pYOnG>B+1sQX)RbG+{QY8Z zep{P-Ku59$J_fRq8dmIA@Vy?DNY)wO`o zU>->DtcajBdF~>0rTrmb!J$u2N!P9Al(`H=)=z9g<7}@DtC(OKtgaiHnoZp0^|4fD zvYt}$Mx#7|oY+%dYtgd4j;Z`4nF$}FU@n77wa`9nsbz}1d zPTxq@VO?P!w#^F##v1OQK=6fezeKM#j56&*JGm|o+tBCPbyX;*Kp;!(eHTZ6F(msD zA+xoD$_0-4paxTe8C8$W4oevEL;nQ*yeZe|T(9kg1NW_qNZIzO`D%4-@fJZ^|a10m$Jk2l;GlQsJhM&c{mBFYdjOa_kW})Enx0p zwBcSLtzlXmY$6Ym&)4orm~}farK^w&uFC|?&u^nbQ=7j{6_zxVVfz|uop&~SQ4ov* zIFF*GabA^o^b>g(C4T$Wy11|xQwq8p!H(H*gnl>Ulnpag#arYGhkPBq~ z^Jq=9Gj`#riJ}pXNi7bpOwZ+l@UU)$*Z|14YzJ+T=~f|5`kY6hFc@VSENeW5STjq- zlBeqkU@Euu1GJAo0ieF%Y6d2lr-S-bz0!dTuPRvL2XJYS-{u9G;))gz+5pLsL&zp$ zx3CpMb0%!U?nqwKM@YOsY&=1bB>rE_%-S$0fikI4JIKS?u@~%EmMX0y)i%<%HQWoD zmMB53THFaPqJh)d`}_xrUca7i^Kv{V`wg%Nbhl(QR(q@>!NBY&JWpZy+lJ9#1n1B& z7EZ)=Li0VW^%m?LYTc!;M&hnX&*o_0SxMl*zH8Yi|GbA%f$nS>kF6}6OHPNG{@x~ zjqsJqX=Kh2(A5hC;vc#=*mxQ`g<=lCY2w*QsHcqkTc@SdRfE0TT;by{+@Q%usyJqa zV0NAt3_n-D=jo*)q3xCv1{Y^Ez{`!OJPsy#3={>Rd#YnQdB5cyU z-?}U-VTEVAM&>Dg0w#KZE8;}HP3)?QtPl0W;n4k7n&%3qJ#e^g)SrVKi6n?XW*fdH zDTWX#hEE0`(;qeZItJByh6<=~R7ia2L|?ecGHdh=% z#sN*LRkPF%3(bw%sYM|UrQWMS$lJCdmv4F#sQeYLx>TzM4nk##VP6H@EtZY7V^Di0-P|9iVoUJ1!`%L6AB65eCWLpkNN}Dx+O}Nkv zgd>OzdhoW1;CJM%}>iV(-*Hx1XWefA( z2qm0ZJ~tuS7XMeICR>qKbYYGhQwpph(-cAH9p>~OGR0d&qwwD86f>L$KSkA5BNb;0 zmveFw5sUZqjw7k(UpE;J>?<#PC|uq3^Eh9ZaIa9=Jfe+EDj7XDG4qvjOmv+F@l`}U z-?@4Qwe?HJ{3D?w6^$ilxv&nmRYa7&tnG)1T_SH6ly=iL*jL;h3`Z);0!dJ=2Dtz( zMx$>OK}3WlI8_zcY`+P0e#0#BDNI;CKalcxa#-xWRvQ_R7GuQ+88Z;fu6)KGs zOE3xYK%WRObZdYo3>sz<<{d5@&J$xWGc>o@R58C0e25^zFA@^Tnc!xgRQME%P@qh# zD^4^pmtXV&?YS3l?Xe^M0U)z(65=k(9@7`j?}H+KLCQOye2_b${G1 zpey9SsN?4zuLRTwvzM|-hTK_pBytDJ{{mG&s=pvSuA%UjyAOCWdKQO`O8AKhP*6G% zUH`}bi-?*}r*(D9Z#Pyh=V)Oj@|geTmxB|Kg#3>jo{ON-Kaf!)Kq-Oi+8jA`x-Lml zqrj4}vT9`|%mJl9TF}QzYZ@<6o?DUY1tZ?!4(0?B1NEo0v9egNz!YT@!2!(yTrPy= z)N%=*P6znRE%{s)(M9;{4^z(>9dH}%^V?M>;pm!DaRkR@Jv8&2QNP{il#TXRP={;C zhIa^-%LXX>*|w1Ubp4b&82@&SmwL^#F{=YgTg`}?9`l)&ow9K}`AsIuY);-J!CGmi zGErCHF;f)@YCXX=#+2a111kkKFf^j;oV5x02xSB;zp~Me2ohHEVmpd)5D)@1Shl9Y zvb5Qe?3$ln7o6CYqs-cZl-W5^Sv|IFiNYum*tn={cd~;YXP3?6dBXTV0SE{c>w>8J z`tZzmbX@k(Fn-*-ZC`3DvX}b67b5eLL4n~Zi~~*d7x(tuIC{N;f`^fif#}e=9}N{c zBnhbTrlDI{=!qE$y`p&+SiUQA=5z2*e47$eF>EMSkoC%r-5f)%J(ae5=H`Fn#`k@{ zKXLpT6B7p^2?q@o742Xn5gDV#9-#(t;DpY!Zu0&pDgyrbi7`q_UdI4Q-q$h4$3j6n zf&>}5Gk6`VGbmQ)4kQUE&>i_mOFv+xS&_5UOiCe=1_Z+b&X@sR05XwXy&~gSSp&8y zT{Cbg$*x=sXVBTTa`6$;QfQ_cY~PQYg^?xexc;2)x4xe@+|j z+S|)=$lpXN!}gd{FtV#w}wBFu1(>$C*0I32ESlHG{oIG;T0M%|gYYO{S|w^x*Q zP7AmN?28J^Dh&^TD22cVvT3`4{oJ>gR0XxYY8A8y>;|opffs4uxNxa&#AWxC+IhnS zusTrkG%t<8J91F330bBxO@f}zlxA_+028ux8n_^!nlTwScl9Siq6$SUgNlI$^MnoN z;WC(~(BNW+!No9xjPW3&h(Sg-K|M}EJtqY9q!DbC3O23~WTfJ^xQ9^y41AB>owTK4 zd)?Ga^bM>d-;526%l_}5ub?;M`3Uae$vzGM^(pg7hZn@8m&l|aX9C~;9{9C1#jzj* zGZ+DEmL*ylNIxT_|4QWA7AU;PTpXvj(0r<9&b`dTfK5WR$R>FZNBbNgS~);Ub5G7qnmw2W~)RD zPNWBnZsmo~x%fqlTjHuL*d$nLqeUt=l@uHal>8`<6Mc%wenbh6q?n|aI^wq(`I8ch z#1__OBSf$Pd?9oNw7LjxE8#JVDe%zQ%4z|3a`+Q&;A=N_03r=uf{d+N0P&KYF+Ivf zO=N}7R7V9)qreU+!4sepVutd-3*m4VINX4Z0M@5{;RXz|Gz2amErX7olVv|)h|jL} zroyW2gQ*#>z#kxt!W}^6K_KV|1|RGV8t_1z`UHXsdq9|vLuf!Nup0M?9&UH~|t zUZ7l4AiH$o0?1inV70*p{N7NPbOX#zfd;|{H7CyI$qlnukEyg_^^ zFu!|U!kfQ+fFDoR*H3V>=L^XDYrKgm;Ni_m-3m19D%`cP5P;6Y3^@zkHBw1wq-30t z;>}DUm6?h$X38!M)zKHK0K8Duaj7!WQUyb=YIDV^sEXB#DOPNr;6zRGu_gKyUB1sq zcmUe^3v)&M>)P)^Eyj`?GF#KIEzW2RaY5?p51WOLZ4FnJQ+4bsaP(PkHvZ{7Z)?z6 zYi8Ke7`F--c?LCOd(=grg2lg;X2lFuL8CxnbD<$YKSTT{KI~m*I^42Nn+W^8b`85z zdzbK{vu3vbrq)iPzO`;xG}G!ILA8ICsSqzE=r93zu}LJ`Ly-@r%5OL{ojX9cU!1#bh#7M*ifu24bPk0G{WiGn0x0i5 z2-4s1(_H%C9tJt~VtcS#^4K51iF6pAS&N+?gdjRSnBktKFb@%E@YWD$>pd+3(BJ$8 z=f}d=kC4>cwQuq(-7SeoJ3HH^wn9gjfRw{}!Od0H#3ufr`MY+Xid%o;C&P1z*{6Wf zQ9OFdx47U^^b~%sWT+Blii$o_w4Oj|vgNZRD}NG^r>KD3SwXL#pNm{c)}QKucVX+QU$+`c?N>jHl;dR+7^D)?|LI_9!teaw(KTo z)e>0Q7N|;ht?WsCvU0Y_WTyqpbN`n;t8HC-Nt$&DE>;Xe39W87udl)8nkP9wLjLBXSrKm(sv!v9JiT8$(z`ns}1!2B!Z;gI{ z2)gbRA4z*j^nI`xCsW8ZEj8`3hk%%goKj~csf(%Q=tR;`9%$US$r~s^?u#t+37k{U zL09(u1-EFUGc$-@oESRACn*Oy^2H0{A0Wl{b?NOg!#oK_1pEaZk3v6I;$c_nTc1>; zSC{S2v$W~c>c#~ll(alfE@yzwlPzb;Fuv{|Syi}W&c;Y~mJvb#9!Z|cQYaPea1#y* zAOL?jOZYbHq9BhRk)Fe-pl@-UtJEVb2`TsQ}~x?u34ZggkrS@FVra-DwS|tA^QEv2(t#si$#v ztRyI>R28QTQ4~9AOaLv-p+g#{j@3z{YOPw8i&AKQHJ~6JDjtD3dOgW+;2lNwDxaU} zclw|FTz}L5(tq`%K;$FT2|ZAr6sXgN>A#Jlv=|DggU5$S&4<7$YC7z&S95WR4y)QN zigA;u8z;^(qT-l)gf(PvOsEQnoi92=+1M+_`RM4r2!e2&6y8RZONSMx=4c=@=AQ(T zMHrWj`mo~3APR)K@Yq1MhXa9d{%J;AM0v;nFKp97YL>TW{q8DO35X!?5M;0lN_}XC%lzq&IM)@Zb%Od0hVR`hBPy{gxM!>m;j}o7bc;;3yC&J^0+V@CLeFaMChB3B2o51ATj2< zl;}Yi4vqS8!qG)Y1iE%u17#cokx<;}#9oN;K$s3Ap-w_39Q9K&d17Ruvkq3IZDK}J z=Ap);MVuIP;xQ84Itrx5de?zGi1N@A&zK{J**>IjG=%y=hR_kOGY)aU9376x0W#<~ zvMKiK9MUy(ic9bJPo06R%d&>rYSifUOHwtI^xfd1OlPln?SaR;*hZpb2wY%M39q@l33<&AQ8s73bcbD zj*a?IjtV@p#q~kCV8*AK$I?)Fi^+a44 zA1j_rW&<`r>5BeXaaOoO7%HvClWHr?MNCo;rOh>|~hms?rK^TZ~>97OU90g)&lzgZL`bCIG#yDJg zG#LVsPCizk8pnyu7!MoCn-~z4^Qjqa5G8_MevCxf1A$nmpmj4*154cqT1Heii>IkW zhGd*uD4rwfgp!j#2N0SL>4mB=73yDTEW-6?2?rW63xb1LaNChF9;P@M#6;|;k2{dp zQ9>|=zn*9Y84ry5QN)!+NJI=6#lr+L*B8M+Hd5(}b|4KZ$e29XjqZVrAZ9Fn69kHA zt~Xvo>dB!DBy%AVg{Z(ssmq2SsDu#W0Ro)x10Ve1hadRB2mbJbFZkgDKKQ{8e((by zeBlQ_@WU4XoBerbixm%4Rg2@_DeffU`zls97kkG+Mk^szMiZbHSupUy;(1Ct9g49cO90HMJ!o*DqjNMUN$w2Kj z;~x~pR;eindXk$GI#DO2MAc7{6tUvqmvREwVG0q2M};6YyulcXwFm; zZL0df5oQey4Rn7x>Ab6bH0HE-tNB8|3`IZ}bx5`_;~Wtd;x!={-I%JF1SktIda$LJ z6Yi$B*koB<6`(`fJ~2$D?4Dl}a9E-=p0=_!d ze>g0UxMl=U*wAJ5ymwbNd28&63uMtI_G(q86b4_%DKnYV`LaBIvM19l&ybxJf;4cEKf0*~UrUe?9 zlH;!j&|1&y9&y2l;DUu~LX^yme27bNIlIavxzuoSiK_FWhI4A&OC$=r7LbE0SVjU~ zi0*v4&b!e6^0)zpuidLdNzW9l0ft1L2Mos-3sTysh000At zs(}Sna|=5nW%o{VhJ=4qa1lH!dxoLv;OBvRSKWuT?DKX&N=J`ob&JXN18xi4Gq8<- z%!oZUamd@22PG5fP9MySS_J~o5$D|#;-3HAZk_rc6S9W}!yJ%GtAw0oJsq%<@bui<=k_2(~dF@0ogH$qwk}=Rjg;|ucz_>(Sxo0ScBw{6{<=!fN zCedo1)02@sCR!YHioO@HSsDRB({_#)-$S%J}S9fd#rr34?_n$#gj{SJcF37oYL-X7!-T`0S$Xv+^HL zVYzf@4{OfZdbGWA-m_wJUM55DXx9x>N}M{6ZtGzbiilt(22{8AWyREFLoYcry`N+flAR zaeT#oN(P#hqGb11Oa)%)sE*(yB>Jgr>PirOtaP^#d!ar}3U82|<`O{t6`nz55KBfN z4tgpXQ_rgkHR2(`oR^p(nB#RCatEA}CLM;agnL5`r|iv|cZXr%j^SAr&KS6-8L$j3 zlR7gHp*3AAZ8esb*;ckwyM3jaf}jjy z)43+^l)aT~?ji9d#dJwOA<|r9S@O5wNl1D-y4rc+YIsI7_HcvX{DeJSelBv~P1^Vy zOS<8%KmbsK+9{9=xyI0`K~v=5+P*7u4{dut7Vp-1R`X5&H)@`>d)DvUt#Tn(0A@A~ zzy?|q=u1H_YHaDbMQ@X`-KuZ8yYYO6^*8Q5!mQ}6aAZfsf43j=(qj=cvQH7ZTb zcigYJXRUd24+e?=bmg3T3RBS%`g$-kK^M-X)P5f;7%FqqQq*3mdtBTm1`4*dT1%WZ zSNw#D>e%>KAJr*LEHhW(Ic5AxY3MN|vxI!>=kU(rJ(OlF|6o<5g@NTDdO^$d73;Q8 zbMgJ*v}P?jzSfa2Y-Z6oVH}Gnvcg({S@{7Hw_ObDDzK- zp)}(L5D76FQNxTfRZ^3Q$A;z_Y$CAmPq`hJf+>1N=CYTWsC6w>K;zhT_~~e}#5<4A z++mjNBe#OJZ10D*9N8Sbq1L;mpD?dQ?a}xRfJ6g~MsTgv8?QG%Jj0x9<_MZMoG5AG zCpbaVq|b;8R5z~*%rO@VoA`SblSUB*IS&lKtBhr2N8!`ChGuA^UGwRRraLqK3NjMsz&l{M z&&gAH2d73YWBqnr4+I>TL%JArou;=KncumGqANywW#6mjZv6RgWIi~VV`n&%aU3cZ z&Rr+SHVImvV4T&x21<``E+J#-h7fsqK!9RQUK+^;I>;4^I2u_~nR<~YLO*j5RvJ9& z8b4p@RG`+C_a)>TR2FTQEGP$Is_nd%(AdeHm2&+Vp<*B#TUNL2ZF=XkgG0ondP{>F zTkJMAj@XQ7Hc!3T1^l^`qqX!nsHxaU?{jAzdfc-vQOx;y_ls3s5s@YvGKsDmd z4&kw;b8e&Zodu|POi8yYmBPFJo%?W(h(PsQJMH2}e~l;x_%4bK9p8=k3Jn^a$r~hKx9@2kferH! z19cwWExh4v!2@1)6v7Ki3BU`EkG9W5oLvK1Ud(3Lk8LpPbr-q{_jM;Ot1c2@$-io_6 z$#NPt3H$u(g?a-S05X@+H5;#5nOQG)-hdYBP2!U!-XyC~KPxyNX&Z0Zbo4@f#o?`` z`<2A3jOj$p*{iB`4Zkv;)vd1Qf?iUdD_8NFm2_FNp`-l(fi>urB%&Q+RfmR{$Wk3d zS@*cEv>Vo$a>W8A8$-cSUf_5V=!zxuCGcd%O#%)h5^L)911>-W(BLFttW-hj0aUvUV!ct84#Me$q&Y5BxbBW^MEGDwY0~E z18sHoHUUZkt0o$%$zuDnTo9Uq$b0pDF9fzfJs~|DH4J^nif5S$x%B|)!Y~BM*^U4>k`Z#9WGi{(WGS%b7l4V~oV#T1G43=I<|8BsD;Uwb3wbJS#EVjd50hB^;Fzl$Ep zL8c+H4|g!J;g|%x6Uc-qJ|0gmE=5U=OOc}eaGqyHkn0g-*D^K(9bM@0I_K-t1#!L# z%%K_SfgW4WQtwt#=(nEpACv2OL5O{Umz+3Top7ZHm`f#nl0}UZxzQa4@b$FyClf_3 zE95dt>dZ%gAc&+O3L?yb0($0V`vX@)Zz=SD4)pI5jE+*6h|cE>rG-7A zl-ICUM4R`~Z67+r;JR=(MOV@hzsi*0`dm^FNG43kZ_^k6Ec>k~D3F^WU8S+1Y49uR z7+0Z%0^xiU9}1V+01A#SzkKZyP_1HUS-9X*GdNE`vmmcyyQnLSUN+#>QQV(q7kDCC zkik?768=BW&gG(&+gt}Y0yZEn#oEyMRTFx#>nbSdNigJNNRm&&&by;1!D8pX9x#=t z4h9L2eQ)jt=7j>uDc~q%SswT@B#{r5^=UbfQDkGrKkpxo%aPd2oEY5BNmx^YgW1C9 z91D5ub-F37f$Ceh5sadWq;gK3%$UD2^TAPk9_+wwa*MlnmURnlGq}Tg4TS+Jyq#Ru zk+Rk60bdKF$6M{zlyOS2NvOx-N1EnPAYs8Q1KMg~B`v7@%$x0r852^g{GqL#V~_-7 zG%^~jUZ;Gog`uw}qzshduJ7BOkoJ)ga+3H^3L{&euM83HwYx(2Fl!hTRO=;%&~Vk+ z#4GRlDOoUPvSuk3<&E~JB%L5&_E=u7;Ry;xd@e^U=s0Yv{pdDbP)`i&=wFNKYUzA5 znH7tf-#4}EFk+a88^ZM~FVWG1Eg~E?!QN6+W4KpcjpY@OhO)AcyZ9tRb+f!#p+mRE z>KZn#$kwEj6GFe{a^q;ifjItoi^(WjKkK)c`?cQlFd{K8cQ6i@_667gd!T2lvhNcO z+xmU!kl}9u>3rA+r!di%CQJt6;Nk_4@<>n*pbnSKVM2Z_iGe`}razT90OP_1r~o}` zqkvn>)Pvm;GYlfPTM}bbN^6z?o8s#Y;wV3^t+|^X$*c%4eG_j6>RT_2O1VjK4iiS6 z4W{pan#2oKs}I~cfmUF|A6VX9egT%z;{i&`j1Fj8qu}QMHzI>`_Lnm1*vme;=+JxL zuh-^quCiIca^r{BfjybuD?(>9XMBji6edug-Isi=#q5DC1qe`yWSv_$YlVz*ZwS8@<=Zay0MmM8~R z3&NL_-51IM{I%CT1?)>6_;z%J(GC8MD0P0le zL=O{@S}74p7 zXS{?5HfBlr$UX^9*z3`gM;Z3Q#7q}HAA*CvJGJ$%CK_-n+BlCk#Hb)s+1s?^PQ3hx zvPL}E(`tb+A>YQNG9&`ZXCP!tEk7!5So^M=s^A%Y6YYdHtY?_sfEYi^kxvZ9?}2Sb zCGUv=ZU|VH4<1Gjo4)La>h6yFeEQ%-<&>5+UPY}9V@{v}K;!uV0Co2ap==%);sWNq zd(w234SbBiMpZ^>8Sj*eACaaulzOu2%TBOv9lznT2Vqzif6fmBtSSbM7Da>-R}e5J zVK*yC2H3M*)`;S>JV%*K${F#dW)Z)=$%;=m@&+8qXF-!SL0T@VNj7OQTauOJ(Y0=F zp&!yE;ZRk*MshIyH+CbV0w9dPoOkI9e=_<#60&IrPZD1eY7$a@FUL}e+dt=-@^Aj; z)dlT1D$u|7#hY9r(52S(N>Xuagy|b+hZ>osu4Dg|N^X1b@Vyw;@9TT@rfpH=E#KdQ zOQs&Y0_{9q(4pOpC0%O&m+kDXZDP4}NG9*IsZqcpVFVmJJ4c49U#i6Y0C%j`hAVa z%=LqLC^1DjS&yd)#qTkZ=ioXO$Bmj)qh=8%q^a9$MTv{N@`dhSexI6kzC@B=wTN!4 zgz|8If9Rd2K5$^@j^%ePD30sfhz=DIas4Aho(&#h`lhRyVX^O<-vh~h&l9}7ap6$d zMCs@EH$!&NoO;fmqeJC;_UC-bHM@i6?2>fe^L(@q;~ZfvSM&0VMn-S5r+U&|Oo^MO z{C?}^JDCz!4C|p>=xEvvH$%Tx6(#Ol#-?M53YhCAjC?or(T-jHg_ z@d2q>iiZl!MirPTki*c9$O9^nC>+@dntMCW)6)gbJVUu&|DGC|+n^bD6Ex$3 z=9@KW=Ktmiruj6=+!0pGtVT*@bV?$I>8zv_qD005n>d}n(gCkn|9esh@^+CvSEwfK zl4KGlgc=Ax46};6+>C_j_ZaD8`qCpQY+IT9En^~~>C|AUV(ZV4;d&ZLHmeQUg*VtbEgXQRe1 z*_s*@M7K&#&jr!F=|pJQP$37*Yly4Je!(8)Cq!lTV=JZKm%m^UF0v@USeG8)$EZnc z<>UkvNBP0P4Q8kqXU2yt$NYjYnNe2>uZxw0o>H-u-;oYxshH~*w@poAa>{yPemu}0 z6SJRCn*gIw(GwzGNKlB7(^Gu&J@{9F&u2%(WW^?9HHCu7elSb3X1`d3$34Mfe(@YU z!t4`FYe4n{uRceylc#UpXYT43{kskar!FaEw|;N+gR6AF9TDbNonPG(krDjmEk5%( zeejG2!4XGr_%AKQ7j!YhEmA%nV_j5|o|~ZL?s?SvE}Kzj`E0u+rdQqRV0zyj4pRpM zg)7OnD&^=6n}2eNA?1$5;!}88JlBQ4Pxqi1<{$f~2y!=8t zXc~aUXpkHIX>I*tWt#GMynRGgWz|}h+_!lB?02rCpidHv<&jYG2xbzAcG~whxLg57 zAtxq0ME_KkM`7#k5;IgWNfRa@ij?6BR^tfCBdq*bKCW`@*PVQjKQUEgDU zADn@#j)G1^{Ot2$eP4{{GwB5Bq=#ScGOW7ey8ihnk5dTIelb-r_VIa}L@KNwq|s=( zqtQGV0ipv8i6nygy|H&<{}+kHhR#-&c#&90)yjXlKz}ciD4hKe7{`0Gs+HeMp+X{w zX?=$DZ8?H4ydmb}iuoj!@&_Z4$fYGD3?mVs-;^RM1r#qP)GWvzW?B!0V=lDxWUGLdL&4Y z5dA6*%zit*aA6Ysy0jKMz=YwRM4}x7+BxgH*fB;#5`!P;eL_T1`EiTk6M5E~&?RKN zgGuc9eWE0BKTwv|4}Kr|_b0#W#~ciw^jUX8`)B^w_fD0>b+Yp~Ej#~jQVgHTGppZm zXy?up0%1q}`&x4HX5NkR6DOF^cfVs}r=p%s#^uoijdbC zsl1o8vybxbXy4c9+-e%0ptZg9f0Mvu5vdMB9W!iVZfEBAxDkY_(fze$8 zIK~-IH4ELDaA=|6tRFwWq7T0Bd#y|-HN|iypCJr?;5Xn;Z=COj3>m&f0s)j zp2nh?U@$c?fzU#*r37}K*$nb&YQH$ytBXjzvK-ogIurtc{3hFA%y;d&*9Zih_zzMC1o%X!QlRc zS;9bulw%>QF_ZJLiK$X z?`0!}twSp@gZ+B~(J}j69SJ>w*qAw*9K$Lt$8Kv3T5ik*n)-xbF5=z)ymIrS)#g`ntE)0 z$PKjEA)XKJAVp)0d_zNs@MNYtN&WOP7Ze>XlhM8>VF#AqE5!B`68uRTjXoPP zldU}R?oLdQwkH#!uLP5mX-YK1HF-AW)7a7V^Xjqlu=8Ji(oSqzqG9ri4urgj2lkB6 zb}Iqd;i^0XR?x$tGS>I%9GkEs<;U&>^=>cYEQCfM7D$r!7|)x1wTIEK%`hULI~{)r zTvy$@DFP59|8%Om`_yQ|cJ&J|My9%by4VNy*yf<}3&nWKx16od!K5#F%>l>OL5Q%H zY5j1iRQcgn`Mpd`O`>0D2vhs~T2jC0rX6GO2}V1)`z>VjVqCoIZx%X?KzvQ^EOthq zurK6==g0gT$SB0y2(drE(s^>ITIe1_OVn1=U*AW!$WlH#)X8KEEU@WYU%xWY8i8#5 zDL=mlAzX{xtVvuFc1m2&&1&4CA1>F=FM*1mEOiQ!xPHjT-{N1KFyM|;D>Uydux3)z z5oXyVJZbEGi@`OQp?XUh?u6G>2%*$PHNsC+lk}B0oRRmQjBbEAIv59)9$_^HMWP8A zWyIlbq9}N3LUP|~SimP(M9&kPyrU)vQS%&~>x{>(PuUftVY1|JO2IWFO1x-#iq&)|U*Fp?ZkU;S2H$63YkfrcHJ{9_0flD` z4AqQcf4GQjG5=Hy2EUeaST|f4?LvtW?X_XaST1Jg7g9&<7;Ri+wMynnWKcv9c7Hrl zFj$lYE_=8*JnNA{Tx3yQlGy23&f1n;UHOxmCpI`!-`{RT@DVu?Ha^cHtNjUZB9guv zCg((~uu1|B3brMY{WbvwysjVsN@8kyWOrq&ae^;ehjT;rR4(O?Ra1kk@z0tXsMrP; z&(%6%ZmgZdKIz?**61@q7_GxW`?xH$Z$5)IddbOEFq-}Xs%j6{@qe}~joJGB#n05| z;Wk(v_FQkKtne9A-g$Or&f`32w zd=mOi;8Y3`vPrzvGt+R2iks~$!UZ`$o<}$-=<_EJ8vjF03w?yieFhBOkzn|~(|Dn~ zjve3ko&$z&+alL^p>0U|D|^-NRR2b66v74!pKp)l=6l~)n=hWIse@?44ed~hb_yjXaQ%-zpQmUY)XE5S~P%4g}n6yTRn(sWRxILj@ z`et&po2T-%M50O*oV>Gm*UjwK1-8WVJJ&H*-Z!6e^H`u^OZ>k*JjKYnBl)|$y-P~RY#IIFG}keC||h3Yz=WzN|)&p0X$AaW*ytdmYmJAXc@AB?d4-((>O}av)&O7GJ(n; z`&Dwhqw@67;6(%yTOof6bwOK%yaQVW5RlHqkOa^Xb}>wWULPUD#sZ@w zoSUHs1fz2icxL=K1yOW?X4LezH{lAKptIyMfL|$eryuTUKr}~Bu0fU9su%Se}F|dq_96wfIN;jG(dLPLxJt`?CcZ5 z9S>{{gj4>>4G71G?BVt?EZ~kY9CUk~w|C}??lg}Nndy5!fYH6jhn(emS1vTrhkWK+ zgJ=NJsG-q)5VNX>rHalNGHAq{G0~Y6z?&Tgy&aM+gD0CpuZTSWP45IzPI6I`*IO~~ zVE8ZxLJ)Wqja3yF*!Ng|TB8ZfHm&ege&@i3Z5{}bL=bMB$@VSop`5;}Y8({@2XAsl zmcO;SGkP0W&Q6ETa~zhRE1IKUzQ4&ad#fC@inGlIH3JjaON2f9gAIg^Dhz*!8Y)^0 zh0M772=nxE*0}5cDc@`+2#i0(4ncDIGi!r|*y^UT-)t&jr@GS*L^>cZ zN1IK>UmYRXkWD`bdO3>1y^{CN-Ua)o?Dcv*FuyOqxAJ?$pi`60vMle;sy&&a;rglH z{33|^^?Suk-LMBbx+s{nr+zRPL#X6B(NDBEn>m@TZ%?;}P*%UD*pU=z3JlzE38J`Mo39C9M%2 z`>&UpCjCa|@K)A~rFaWqH%Y9<-s2%NOE!VX`^r%a_jWM3WMn-58~`yVwK4adE)CB8 zHsc`O|PLlR9)1)BFfWTKc&CXvCuy zcp->u_47b@5uTKGxqa+hmH^{Sq?tbc#Gi($oRET{RA$jt*Od*!UEoajq3G&>x#C%> zlmU~E`=}imr{jxb}iPF#lju zcp({honDklkBf*ASB>oZGD%#vcZ|7iq^0P{6kX?oNE&WO_6)rc-yyE!doNbP{LYp- zmnDw_avPtF3ms2=ZyPRupJLysCqQPeA0i6dflSHB*-(lYswsQQ+xt5*gc|MjJv{Ux z@E?fFf6F-h1k*=AzS!?&V!vMXoxcXEw`95%3GK-5eb3OR$F8%3OVxy9iA|LDd+xrK zB&U3z#BE4Tq#Q^&Zjd)gpNS25-yFa?Q4>KPVIDT{SV5d&9xnWty9PD8qXdkx1C%NQ zro@UlTd={UnM)+T=v$Egp5P!e1y~5?z{UJ7_kC6cFIQ$2uWnU8iH9&~cIv>{j+$+u z1ft6xZ`uPfZg41$T?(lZfm&waVshorK%M2g0;|t_U$kso(&qZgjyg@fTZ34cfF!IR z2RDw|z7*J<^2_@D41PQG zcW88N>FoEkC6-FYa!a8tu~ShR8X7RUUocd$zPI|XE=59&{-B7KNiU)C5xL)&4^+&i z$)y*$uHM4vDLib64A>F^Y-de(vm|c6p~Ah55tkWvRp1-}6|6vmcMZf37w+Nz^~_T6?|0l& zymlAWZg~pNQ~hrLAc*hVC9uDmkw(2wgqCzPp3wqk0TdzQ{#6P_+*iu&wbG^h_r>g^P%w0c``*QOjrR(1JL_WIUM%kh zvy~aHm!i!R;^lL>$W%8^^+j}f*F&k*(7M1iuwuj=0nQ2^C@VK_#mhJndf|KX>*7eL z1sQBX6DrHkvnW`Bfzh4$^+oq(YQvfy6>G5Gb!17b-Mklc1~PFZWC7AU z;z(%3?MSHRh6)9Puw@*a&3@@uJvUaA?65X9wZ9R^`DxyPY3_L^Jp2^L|*ZAv>5 zWwZJl3|l4Z%tBzDSK#kKzLsPBW1W#wFc+{}1rCS96`Q;i%S3s;XN{m55oH8dRTT@Y zDodXACJ3R3rBQ>(Rg}}uoXK56J2)K zqZBl{WYQg)v}Dy_Jxh%@^+O<1p+t8AI5Ut5UVJYw1V1mqvEfh?U>JgpqaX~zD@85n z_g(}~@lpUq&ct8np=CuKg766b;=@I#4Zu(6fx@-x5_**XuAvzqOzv3z3vV^y$Y28% z$Q=RZSI7qp)Mbj|9q*a9P|ViMX9c3%bS~ zQ1f8(Vc+MBW`E`16y;EKxr<};VRuF#_~koBpB!9w>oNKu1?Q%!`sPQi>KHwX!;zso z&Cd97YV-__F=s{&E{%Juc@=>ygP$kDP6{=!X(g^s25Fu?l0ZX+{H84>?)u(1RZzSt zC?H5?T1S#ImrFi0)7bNE__ai$mu!?)5|fq2WTz1~X~aFUc9g47u*%Lb)JlalCNq6< zag8Zcmq5X$sRkRgK4i3?5zkUPa|~+si#@_m!gQ5EL4IXfd*Wrq(+{c&NKkNcisQD9 zE^L|#k!DsFjWgqUC>g? z=4?$X)v{~EeM-Se&W_Q^r8JIa#KjqLdzE7>gG&ll`r@L8C?@mFE_Jv#kjwknQ-Kb^ zBM>Vq47fu#yQQ5Bp5QAVvw|xOxIvsS)$N495Qyd$Hg0Hjqv)G^=$8Nb1J|Mc62&h7 z0AUKpK(R%R^1YXDX7)V{&}P@_9s_PS50mC>DFgfOJO^14-N zRR7R{ZX`^72T5Mve;|Bv)A~3l%st0+@r2iRLI^5xUxYxU#9e-Gi_&OXoy!N86t)%E zG6#1gr$-J?2tp;UnpVFe<@yYKgb;8x1A^AT>jN_0znDfrB{f{?y> zU|AUlrdQD!Zoi9ZG~Bcw8jba-@WR}@vRwIPH!5FKysLy}LDQt%tZW(kQ*KzGypP?| z{@g(b)0yL$uj^*@fuzwo+z5m;EC7s7DeRO4n@L?UqezG>&M%h`DfuUrxNR8GMawyU z@RPa_`8b;bVan4G!nGw1hN-HQKD|gnk3wcO$cx;x@>l(_Z_`4}{+Y>#(~-p8qmsI; z(Kij-a4KK&ORTZxC`S$(%*h#jSe&6b$3r$ck;KY5!zunhFyFTs2tnND2W*~g8q#y( z$tn7_oE$c!56J~3`|y%~c!rI1v_QgDFuA+peBWUVP>(>vS#v4G#-@Fn5f|+vHL<-R zJWe^>h#UP);Je6V7E+f0S3s!0{k}}`)>_RWF92-pD*mbvDxEmty<&Pah!bQ^PEJlM z#)%Cs7-xBjDjGC`xK#A-?VyQ~QLu&Z`4ieQB$I{^PQK6w=Ae=ACI@0P%t;0r zWDwNiq=gSWJ07@nMdjEi%7tJIg1B40(3sy*(D|=E2Wm5~G({{Tt9kTDctbqnOkNOw zK!kwlyAL|_QB1bO`oLVY=zk@J8%4t?T0{nmabQ<@^vGYn|6q9a)%Rp6`WLOJucEtw zAZ5Q^*5k{sSKWOkrwcke+H5ZT%@KzE-YlK1k~@nZ7Hy9!{yuqcC-Yw&!W-pThyGrt z+Z(Q{Di`W(Vq|-1IhCX;Sk<9IqO5D43$429a4^MIUhc3IWk)i z>3chlBeD=O0CiPKw%p*-kdb2^Y(XwZ!L2i{6QtX0Xh56b+^Zp)w|)ugFg?b8$s2>5 z4k*j%f5_zDGGvi5OUo%zv^_iux8{DyVHboq@XnuEeHg@_k(R8ZWgkA8UMYxDwDtE$ zVGKGr`7A1p^(9GOem)(lNs^;lV+_{y`}&k;f{eBn|58G`m4K+LI)a_$#DinUC<3yqt6%P-ss7+WRXNXngOCgSf>VWa}S5-CiiiwaAwt{ zc~y1HUe%eeUKeH(1?#9mBTOZ1ktF*-!7;Fl3q&3mc`IGOn@uKhuSKqaq~S+^tr4aI z$2~?KSnVjDy1Us?jO5$Glz{)KgScgv><4eF(YHo5<0z52krM^8mw7N#Rp`DjF`;&*p{x%AnhouB~TyMtp}p2>*M=Qu&3MDqC`a zAA-L(iN$U~6hkkzPpSRhCqD#|8lR%c5D}blB8FbN&h_6FhT6?%S$gts-x~sr9!^1f zuSoF!1h??`7z20ePxaLylkH!aZccwSdi$0)6*s%br9eP+s}c(1>bCY}tSO;PUx;1L z%rj)7q09f>8|EDhcTm$RB2M2gv2A4JKIQug767A%-@Ux+$9PxB2M7>dDZjMellM>< z&Vi~CQWGf$QjQzs4Uq4NHecjz>0SSydL>k+x``0AC>>!niyXwo0mptRk_(S8a5ch7 z^z6CH#8zC5RsSWsy}XCC(;?(HyCiPKGjATmjm9SXFqx;k{8b$2?gm|CrNqT)p*v1U5fG&GNGOgl5uu4=nj7`n68+xp{C6IzRepB{-R}H#F*Mv) z%@HjAEjs2MF5Z2kknCzW`|kmS6_|TF{I93L&ir}|>?%H{i7*2;=AYe;i40^^ z%oOzL5}18|2o+8&Jjs#;XZA`p{wwEZ|I>0Hb5Jx;CT zQVf~?|KEGt4c_w`f;Z%%V9#y68XKm+H?aU447YFXPrqmCM4xfnt%sT)X&2z*2mQL8 zrlUXRuSODae{gE!E~7qxp_TlFYBhy~kqwi{JC+SF>ZZJLPdVBmqjWmAGos3t*dv^P zw<*d*$rIB8qs8O^)5qk18XG;618oRKloYLWZ!-6bF3m1=eus2`8wJO!rjxiH$$+{z z!_<`SeWH8SWW9V{nnhB8%ZPYoD2fWl=oJ9xaAEE)2$6gX+OJ*d-1~aB4d7~Vx=^bNAb-0WPWaH=2cDYcX{xL=P()Dl55e9|KoD~Mvl|-V31qyAzkWzg z5BYr!AwNQc4S*q!+F1_~#BKh<^tke?y8W4Liu)5>;41Dr2?*%w(AxI|kOJaPMN#tJ zD>U3IMT%(p)Lj%KMhPs~tPH>>MYdp;BOAOX$ExcmM)Ws2Sa+ktv6W*g$^QA)ww8m# zf{>c>AswvCQG_c6f11Xy5aW5S&&BI&NhlUM-FtQx2FtIrI6L#RCqfc#P01@(tnd=^ z-!Nb4D26b@OJ{vwITC23Ngl!IpU!_wAcm!^E=he zcbMLwF9Vw$CZO~~km*%-$n=D*ekt{!|MFd5dok>_-HHqBGP`!T7GZ}UUU+fFPJYk8 z4&={s{V!TwGF-X49N@`+nfHr^lu^(!Y;!MSW%{9Ub_;}Fiacn~JWso|=y+T%brMk_ zm%Zit_JSgZZ;QT3Sa=@ms;cbPUL|p_ZqTTzAAE)-^+dNom+J@*z^=Oa*fC!H;5&!b zIP-;;@g+xZ?GgD4R;|e8SKiQiQp#U&%8%a2exC`WeUL}8AAD2B(kzp&HK?y@xJ=6` z*D9F>Mm6&C$RxELI*#cv?FMIk-H-7m?B=oD*f3hm?Zw?>p{s7a?8}R3EvbCyt*;&J zw@@XZliL>BXTxMQjLwq8wc9f#pqN(KXOXw=KE*y;rgWA@f@RHq0YkH_P22zKcJ(#& zsr)vK5}QS7%FVA;ZtqwXG4@MI?9)t&Em`zS?m&I@-zxvL|CHpd*X>iOH_xVSeazPC ztrFF3ebPAA&mI(Angw!V`yu)S!?Pk5tN-q>t^6$iP5W<(Xm5o?X0<1@MY|1Y_5Ih7X^R;96`&B>hBXVJ zZTbCJ{S|a_&5Zdql=(8Mp<$Psg*FXCvETee*Jcz|e*lGWMvH))FB`Me&6ZaF!L8zJ zDa!9lqScXjL48&Ldub~MjXq$ubk(TC8004J88EtOHTukSvj2|xwC~Y=|Dwh8(zY#* z)iL{ag4+4Li6Reog{MYtVWlKgOCv!{pq)DFFLeEvPc8r3aa{Qw%U@BuTgH69j*uk_ z?L})90St`p`bBH}C5vfAzxOL_>}-=3)CpCeboXf$U+W-*N!Dcbi;{y;p~@b9(N6fU ze06BMeV2`G_TLkB@&q%jE$El;T^P1i(6yI%`-op`Q3OC- zCILPnLG1e&dJI7-tUetozWTN+6tG><`hM-#ZjtMIJ0{xSyV&i_SB#pX`r87I64$5C z&;k!51L-L7oJ{UTx8+Lu)$e7>$VOV*lHGdNZjn6?-|DCB)-WG-zg+qz45E3L7h%~m zdF$I~o+M#A`3X7WmKm>%XJcOVK*6m@csWv(*weLeAIZwMIDq)U@+YTSH{~ zX&Q0a8lw4!0qb&k6Cq4*0I++&8U-(tXc0EU^kVx8t`O5jWGN(nG%}>-Sdokg6aD{f;mu=4+UkwO&?b|rbPt@<@pH49%XZa6R5FxSiSB`^Ij|7 zo18t(?7aw85Me8M@JYwKAOuF}fp!!}b)Azbb)JS=hyK;i@4wVG7p|0&<#g$FF(Fw0 zH*D%d$9fqh^mi{-n&>=o>bo!`@TG?kwL2UV5^oT5)H4`EHP`nI4G{@b9XJhTUbn-1 z2R?!t05xoOncvCea4()k1(FK6K#tSN?_0hQm-~$iZ&UX?Sda}lTE1pUF#;&*nAt> z*=NT0HlJSNt??)Lqi){_5;aF~jGLksNQQPgfpl4O3Gsm~gB?Tw4q>udQ_+u2l#NYq zs8%2+gzfx%1UX~P7uqHm1(Pu1MqQ~PMZr1FKkp3LHKpDHeH>Vz|FZ&psF@!Hk6``c zHu!bDX(tR7Q~7H0H|F9mnHGzC-25J6CHG{)i*&;K^7|5mJ^^-$ z*ZZ_?{P4hwAS2SO_!7V5$WB&#*s@3}2S?ifpCb*bvP}S}=(<_b&)<&S2jBfdK?Q zVi$dsPhpcJTh&k9Mh5vsD{6=Ju{w&cYV^2>IUeTOd6=mPQVfC`nVRgAVS~)R>gUUP z)W6q9W7qrwVV7UeLd*T5fDp>>ZBofTK7ax1zhnIK>%VEtDIo5cUzEG- z_vIH7qXB;*jsRm#5ckW^iy7{;x}Y*gL7v0dZ7=|Yzc_5TMW<`pBEw~VP=zF6SQmIj z&W8`TugHy~Pwg5_+kAO{f-A(k9U7L*Dd^I?=u9`FuW~3^C|#uoR_A zJh5aw-5UuSg8Gdi=!l7e++njfZx?M#wfLIG%^tHgnw{BY4w zRNMqJzY2zCvh9FXK2ac|a(BsO4@*4lpK&%e=YXD39K}0>%yZ?M0(Y0$0!# zWuhf`J;Ru(QPons$d^%-F=-JFn8Xi=y#dr|2+!2VzUS}=e)KI<_>nNJG4T6kZOqh_ zD5I214IHWdgVR8T2U<{#`Cq(vDZ~91{&uYyUA)e&Y2Ccm_Zw{KqJ{2G z)MPDDqLi88dM`>cvXczd%3Ppl1yBc|dJb?Tw83t7B!q$1FJ2OJ2?~HHoUdWxIB7z)uS zL{h}ljj}n0GDcJxl`_r)$H6GW8R2%`EG;slXM@&jfy3c!UW)1cM3Lj=e7T;RCntdk zYV|~Ir4mI{!4=n%P`^ab5xsa_EkXIWP6$C`HH{QX0O1eVe{psAHAQiQDpkas#G+)+0Q#^G?Sl;X9ab7tXsDtp$77;Y8}oe=A9#l7WLw_SQKpn zWHkB}Ue(Pvlgs~N&2T-_xAg9dr2k8H>;C!Wlv2ypDio`>4sfINoRAsC>Ufm|wODOa zar)Yp!Vw-5Ghr987Ytjl>$NUaPq=icl0w?r?+GT8R%WLIg{Wp08Q{g2HKzTrg6MAD z*cs;b1SYGdu=L5T88py%Q?UFr9`ycx?Rzt%C>kAVuH$4Qq1`c;{X7kpjfcjDE>8?pKG87%Sndls zPcD?uP9g*g7($4=oW#oNGa-K&^fO1dq`KacBR0lfD~g7_NJCS*(tuk8Xlk}l^dMG8 zXK2oAUZzRYGs`G5GfN#bCh9CYQVdZ+;zDZfL}R2*>tU?+k_D)x8=7*P@_F*CSfhpg zqGU8wt*47i%gbp24P=1mdSm}(Vb=&D1_QGgUb~(U0;pFFa>&3MI2;YZu~V}MF#(vn zqml#)E;A&?ms-TN5~N3o3prB+Ju@^;`xl2-pLyw`?O+qCA{t3qm|&#PFY6Iqc70OLvRtbd82{kwFaV|<%x za2I^wQqM#{2VDqI`WT{H!ri0p3)B{B1cX3z6n8KTL8!hE0;8grxd1(~bZ|rPC`Nmo zf=D<4#n>7GggynKQrE2y>CyjEfaT){$4W?%az*$++FgS4F zYjm8T!c+$aOu%Kx^1(v1o0HTD3Wgcb-+z!}!=cfv&9+;=&gN~tir=U>RmbIKt{p%E z^~On32q)r2Cx)b43y`E-5yLv(5V z;95d`Kdc}lY2(%AlCxr}vqsa(CJJuaM8P&u@Q9hy>&|lm)J0p;bllLQiMta@0balZ@JDC1^E+%?`6Z)g=!)k8!*GzL|sRPR=u z063_VOD%Hi758UUIE$p0cv@rMtu{Y}ukorY9+THS5ww$;@q+UVW>M>ARr9p6(j|o~ zb@Un#;gKOxghR3#6k$In$JxyC`per6?5Sny28Lr3hMoU#g*4fuk6H5Sjb(keT&ugZrqTuEMxm)Or0^b3v z5-nyhwG2ZFh>k|spf!$AgOCED8V*n}35Y5bH^>=Bpuhqs@JAyspkC5-CnP&On~ zzkos#4GO@@_zjZe9~3~sln0e8U0Eow@q&V%EgxGL*gO;n)3mmv+?@{!ng$5w&|fT) z=QNT(*S>Prnc)|bE7>%{`#uv>hv*`@Nn(1W;bu|lRHsLls|d~!pIR^g`^sWvsE6Ik zflUSIT&97!;5gJpF#la}Pfsl=%3_!i69bi@oeity&UYM@57Z3-)p&21|E{3_4qFek z>dq;`LPErk=s>x3+<$8)m2bhY%I81%xnk%0+pzg-rf_YuGmaxnD^7tzdCK2R5%one zFcc$c?!W;#6Jih@!7%e_$t+W)I3uFIfh0xSe~KsgYv_q&wZ^P**4X8EO%()8aa*(O+wsufhy9zF#Bl9PvBgYQJ9$||x2(9eOwq}F{R(vJCmZ0BVZaT( z5YDziPINITKZUiSkZkUE)!?oi}| z0)~)>{~n2dbFYgmp6@&Fi{AVpY&5ODlycvj51-S2Fbjm8rj;e-()hU1{ciTm-T#7YXzu;Yc@ zTM&A1AVT`)yOHSXsNB$c!w&rVz@E8;RP2TK936hibKs&hlKUGyr5%J^tqx%*6 zcaQ$gwWKk7K0*pX>MsOC%n*6UIXUJGBbpNV;R6;&(scAE6vKc41IEv-EC7=#QzNyi;pn5-6|uwmtfkQL zgb!&-qihLelzXITnh^>dH*@(IIUE!L%Tcqf!Q`g#UaS<#uk6}T-+j>_fPtC@K~%;|0Jv5;BBV0Y9(-R$&q za+*YzIk@Kcwl5{-r}^8W=)%q$7(E8IWhn(a29t{QBA2zp?AO^MNbZppa1GErJ?Q{S zp@FBm3C7pfGIe++i#)~E82CbJEQ>@isswK4;TYiIh7#HVW<^nXxh-dW zEy&HwpY|ywq`c%SSr82u3a0rh3MGC}l2yl$Hald~yIHtq4#x(UUo!pS^{m+Y3%@k- z?jD7t>{N+PAK6Y2Y^2%oOPJ+sOTP507}EVxqQ97vj8D+ms|JqZ{wm?8tdJHk#HOm44$$(gQI;g3_1!IFPbIHb9JDp*C{%FXHsPKGs zL{b2e1?ML+ol&M4P(SNa^H&jOxGW9M0)3;u`?R_xKkajMyQ<;8_|V%*#`gHG_aweg zBeS}7SIesDdZvn_KH-x{-c%%Cd&)C<#Q0NgS!-BWpsV`*^2S{2LIZ>L-JVs0@71$2 z{;u_orS_>dTawxW6F$tFH>&{aMg~mT4$ckE@2#$HUrTQ1x{wVX`0yFV1MIqcbz2h2OUD*>!{u;`b*tRHE3_ zf2DEd{_j~L2qJ9i3W?hnZ~~x10?drE#YFAwUaWk}{-kMX4kGQpD-DjCZGXNG2u%3z z1pj@u@K1aYe4I2G-ykIu>y#3b(W6-77Kdd~v;DW-`ygM!O2YRdzJI>3QA+YY0ohHi z`Bch1jK4iQWKi@>QKIEC?rmD*yLPfKxdP^imkbAn(gHPmj6qB8xo$A(7U=gi#CpQh zx$IAtQs^xTYl?+}r(yZThvn;GCg|G*j&Vp0PfdUN*U+EI6oL7D4Rgk~s-5c$6iyJq zmIiA(v)FKsF^Kr*r_GJ91jGjFmKFMaMx}Y~7&lcoX=Se2jrkqp+}qsC)!`CJ zy*8G@C_nB}qlpo_;nt{K=JP!}Mxb^Hlz?~m-?*a73#W|iYiA64eyPQ7S7@5V8vS!!wCu1Nf$W=oqw>1mo@!`Q9g1_cVTn+Gsm0aDN6g2IPLjA(zLv5q&DgXLm(Nq(CUlH4xCo9|z-cx9 z(EKgK9^r0N1_~~+>A2!O3=j(MS&VenCY)a^HjoDJFj=$=3blIkZSOunKtTtv*%as) zfO-%B0$pIe=>_FkWY&l4Q~3f~vO)g_nG#tOu=QWxRtzn!{Mg0S7g~3q0O9)+MoVH4 zLdn+WPt^eQ={D#iQv~2e4K8N*g2ILG*#mSQ8H8;4Rv@Cp?OHyswqWcd0CD=>A7azT zqjI_Rve$jr*M!e@PH`UlW+w@a&Da`&xXARMrSGNh&g60*vKn75O;Irp1Re7aaEDEo zTm-_6ISAN-V8ix91q7+s2AKhLIvs6)V28exAsi0vj2&){t4JTdXq(RhzxO=f$*#y4 zHcu;Y{gdHT3;!n}8|@>RGGr+jgm6usy~xqf4q%5B*qBqq%*AH{;R3sY^X56QfhlEu@4T&<-H>2%ltkIh`EB~m-1XllHk&-_G_Td|jmo|u4OI7q zAhfA4muR7wz8cjm3#i`8m`tV<5U97B&FwJbTKFRZ3SLg&qGn5&P5CN_04i11Xw{4* zt+H^l?#t{&`z3B38}AV@_1dS*fryxVfLbP>^v8~ljpXYL(O*s~Zd1B2nBo3zaAk1&tzSV65qoq=91Rr(=Y>QQ79%Xgt`GS+>BCY%YYZiO%!AlZ3n z^QS@UDgRxeU3r+LpPuITWHQ(1MaFKyE%yz*#VPLUmfqaVV$>(*Tr!#c;MNV-!@$Pj zdLYzfSNAf3Q?E5Hd&!WqvzObh_ zq0UcagBaS%zFOE4jOMXt{pJR0AVXUL>*!9|yXGTKX2tp5pNW2Z}chyW*bN1DT{w`u@JHe>VF!C9UWjqs( zF-Y>qRh!Mf=G^){aNSyITF6~6X~k2^=)xef`PmbBE`M^+rEWs|e{l4l9j<`&cO2d~ z^%4-I$u^t7xd$$I=IQ~StEjLN_i6j0StV|C$8}uC5zQ&a4E8PI--CyYQRQ(^DZkY=PAiMZu?g4aOu+Vh? zyi^1LKV22-Ui^)G_;YJq0^aEQt(84)&#zv@8bF)|bha8e`19z_viJ|)8Bg84sYn|$ zmayY7L&vr??0*+&^b%eD>Zm;8f_(bZB|oAtKsYdB*fw;+yN2ln%EDu>)RB#DsXs|N zwDesQ>7SspgFA%3gFq7qKxl)!z93^IR{-S};2tO-{e4EWvHxc@fFIQcM9Vf1UhHi& zXgHkwPf&~W;5u!ft`{&11I+>Uy%$K!j+=y>V?ltSKsxWiL2=+J z6iF<;Ol!j6iOE9ZvUVM`IVer>mb2bn%9$M%h>EAOHJ0eKipFaDVqyQ3n`f}ZB?JYd ztR>HOlGIHWyG(F)B`eWbg_(SgkR{FFa2k*8u{>T!X7sVVARP-%=}&(>omC8#WAP_g zd1?>wG2+<`%qJ5-hhz1QgMl;JHYByG!Zp3#|MUxg@NOta^*?*5b4)Le$l#yxIM&NC zp24>Qmx?G{>fJyV8khYlea?%8dvClMBdSYjO-ft|0Yfz4!^~zBDHR(B0eCtBr&zt7 zB&&@;tMs@od$sgQ(}Xtm1H#xG_u?k@44pLfVo#4%zuj*lA63V zwh~{e7VO5oqLDvjH0D*oNbuH)sx5I=#38w%N++WGYC6Dh)C%cgA(OxnLW)@~p0!O9 zbHsd%rF5gKZ|2yr@=Xp8C`xbgB~9dZLg`Gmh3h^1e8c2&UW3-orwKl1Uzjo1J$0iX7!Kl*+&t*|f^_z?MI=h~m@1+*kY^#JBTFF}T(UrIE-Edg& z@L)Ls=_ZJZm~j$@eJ9rz?E&BV*`9~v%Ap~A<+aj<-nc-kFK<5c*N=2Ty-w}sG~=kH z*VflFgJ8YhZw-U;Lp!BT_?k-6F;hy+8?boKLY-o?~$m^#}#HWQ2}lDd9yXauN}rfqWte+RN7Nt7)>aeJ1+de#7mrC zefZ?~Y=DdtabhCt;PZMOOm$g69cq70?s^w{I))}?jZu^&yHA!Gp_zy(pU+A&Xvs4J z(B-{j&2&mlcG!|hh=5;oC7L{#Gx`pKAN67f5fID>?!w z?gs8vCT~COD9K6&bRzabwP1Wg_OzTd5L%XP)il*XBkUm(9`7cs!oU|#OM!O7iaa7! ztOK;^WOL)WUUE9pm^H~}X&1{6bJKtdt&v%ALit;iO$b^?nT@&1ezKXOE1ji z5J_>=jqh5dJQ@5)tBrxLZaD^pgsv*2Ta%?}eh+hcP{bb$)od9(S;fBTo5a+&kZp*E zQ!7PvSrm+sdp^C@xzTxj7^%-;4L=sEk71HdD2#EqYAMH?Agb&v;g>V6WVS$%rp+_? zA=jyn#liK?OmmOyMATUyUSN=JJ$${YTmMso=T9+K70Iwm!CF9z+20Z>_0gAG3{tr zq0k8hL+>zZ0&56Qia&_SdzgmISb-HY5c_8imZv#c4W;N(QW0knGkhM`a8k^MccEh| zv9n6TDf0@4VtZrI@7IL<3mXlh-`|vcO1`jzzHetydUMwcv4117e?V{f`TYR`5wV~EYgc)?OF7-Ln%kI!>?|nvt22$-?TO%7)xfgFfEUCdkG>ERsWeN$s9VI8Uf%s{mx)|Fp=q z-{lGzSM;pW=S!((;U^+BzoJOdi)Ev-W|d@(am<|Oiwp{8nM2z?A4DReyp%R!wvUFA z5;!#%Z>WZHU~54UslQqHs(}tuYGz8TALG;%C0H(5wxO$3+kSR@cdke#;i0AsE~6I2 zX(nsKam{JmkAaqV1@6d0)}Vr4GESJv%gThW@XW0~gg#|71d#&vb><#toLL$vU2TRY z@kF^v4_YG*mnANbcip-&V|@U8Y;b13S({*rX8aUbq}Q93YsMYUNX23X^JF$(Y0GLps<8kGdxyoe50zIpKi^@DAj&8N>#izNshyl zRH8t^chD|8R3oSLyoJX44DXaVc4SbwG>%!~@*`Tob8a}f?*t@E4h}@#CrMX_xa;7z zDhtCs!WR%9OOh2Iu9ff#_3wHxiyRVV1&e-we=~5NH9;?vuNic>zISGNh+`Ok6euP$ zJBGApO^FJ@%vQUpafBTmm3;IwBB1UO0%zn;Jp5;SdKhw&`^+$V(Zo7?iln)Y= zQwXj`kch5l9}D!7mGF`J2ikmS3;5yh4dN;v0Td=NJcQrGN8p&y-vsyoj`s@C2fe<& z$L&QS<4YRdWAu;A(5yZ=4%8lmRqOs`4+Gi1D{(+qE|=H@kI`j?5AI+bU65|CGMVel zb=017r2ovnNm{3H673CAy_r~2Y&Nlsb+B%%y2ye~v&&gOuUQe#zUUaXEN{_ASJ})Rh5hDvh4))YTx4vKD<;~ z>i;=Ojy#w=143sxj?qOFEE!yF>FsOZHJ>qq9fuWD*k(~&0Z9O`W0{(xvd&LUIi{J! zWESY>LPw$kpcnrD-{1qOf*YKQXu|BxNak6sS5B*`kHL_n5CbPjJhG$A+yoi$xzw@w zwit%@lSftXDF8tc!+MbFH1HhtfR{+4Q2yCKR!jmCUsO9;gUA@BehqCUsgvY>*;G7| zJG)x4QI9?SkeZM=T6($-v5y(o2@h=Gi?WLMMy zE7%@bmbGE*#Pt&3GCoGT2Xx`Mwg_1Y7J!#m%&}c0&9~Tu_7i4shUh}~ zg9V6~O5%ZWXR*Whj61oC<@bJfNVnSVQ!8v$XAL%c0If6H3G-%WRPugz4EA@aA)0Js z0|S5^Dzi1vdSB)$3sS-(o*T^%V8g#QJ@HJuN#%tKh-I<9^_cmq|7jC|L^aGvjPd3p>IzfQd7%;bQTN}BN5aha%2D# zF)bwGN{}Jl{f0js`$d%sMgoNh=0fE}F3})u1q8Y!jvE^?S1knN>hXnghaARob&Tkz zImi+rDl>?jIVpX$Q1{3`eXl7vqcjb!PduZ$R&Z##mKRnA0wh*;sEVEUpKgcFKT=EE z6o1VOiNS1~;lO3?dHn(IkD z#3Xs#h04slTAvD+;m`{LX8KfmR7=g3S-@i&KJWhsPqdd%0@OwM=U=TZ?hRE;e+^K` zC`z2b&U%d`3jiS{u+M$S;&Y5Ak1l77w27zLd(CR}t1kU=yQN6IzXi6m7 z&Vlpqr^EKyLF)(a{_1dgj>~xX2?pH*#|P?enhG>f`*egONJaw)lxqTdhsHT<(TD^8 zBb}RLXNnIo<#~2HfOmEJ7EaNcAs(-tkOY#3!8Ebiy}ngJob%sz=`Wm zvp!Y~aPWmu)(Pj_ALkh~#G(pCZuH!0Y7>7|1RAL}L!SwiZSt+#*=~{_ zZ^S=O5Q9pru~uIS$uLRanL^-_Zb^ISg1j^((g-J>2d2YRvLg0)jb5jb7*Dy#Q^o;F zU_OZPM$dkvJ1XM1lmPWh+K@ehC(%JHgx0rfVGPHb59kpPlArE3@&X8G2H=y!m7Lb> zw>^NT2H+LbtF*uKylNo5kS?d55(kXf8FnCgH%XSe$8maRf2LAaCJMYL2%+99XLw^+ zki)AeQ6t_`!PcYW{ZJ^F9Pxx%GE?$u%%gNKINF!f?Sq$0Ougo1FtUB;S-r7ftge0w zW5BW@26(D;_4+5T$`O_81(Z8r1%H#R4=Z^Ltlqx2wl|IZlYWo?w(5)Y43!n^AFpYs z(560bBEk0GT<_d3Jm+d@!dj5A?Hw1k7E&{CXWKUwSN( z;8T|>fJv<<| zYz6|h3p;%Bn++42bC205?15N3i);V!D7Nyvsl|5msK|~kOdx4$_vbus)>~kG1ovSz zRby20hV_--y3<;U5uv;Sm6v4X-4&bH_#r(Ox^AazzGw&TOKcIp0>iU1%-D6xsOKqK>DWB*MJE>D85h~0^>^f+qg<(ZTSJM$ zSDV?2d?NkzT8ZUd#evWaHM8ofEVMVsJ&(5!TQBKgaKz^!OF&sMsx~e%c!ONLKD)*3 z=<(8fTCd=#htrGT0zu#{3{)e1*{eJpWJl{1MpcZf3PF7V6 zHQa`NdLG9Cm%R&|%bWm2cTDE7fWrd=+B&UfbEvx+_es#WpKD78&Ny?DXP0k$#5@YX zq~m!+4c#^gOG1U^05;OssfR9N`iR}metVFAnY=WS-}IC^Wyj&Rrq%AKqiApXJa)$3=-U!t&Ktf`rBsR4m1IYgv!q30#-u4ZnbuoyAskD)S zD`_Y!ULTlBM+ruYsQ#D{4raQ*xy0d_ zS{vNembDPZu6&~gojHle`}F0!qRL<(+-=k{r>bOpdD$&K6@Y2QuOx~O(CcOcQv0m) zI%U>;&CfI~g!(thvVnK15&}4ab^zd2P;v)irtviD zSP)inmjLU;YRp&iN*>n~XySdCGIHBI7RJQ-$v(Uo9F*Y4mo=ig2JvZy6BQCm# z(hNeB1Q_duN_wfNmed%ZFes`Y_)mIUgFA=bX6I4$Z18ZBmKE!qUg^xh`(CNMVj|x=1Egt9p;3C@lPKs+HI)xOo`F!fwN0x)_g< z{xoLMlnYy|`K$SQ?->wLVhQT{(V)D8P%Ibz(lYW$6bqZ2s4u}>U`*?%Ow619qC$}` z@H@vv?$#1d7V7EbRBR%p(;%QT8Ycy&UgnQ2GNmu@8I2G z*JJ;C^vaNzDHnFCX#Sgk;XWuXV(jW6yvVd@ z7)febZ~CN$^#%RdOdEvVW2(Jr+6-3j&JytUJZrw&T;@>qWvUdkm6F0JeHp}e`?_Th z&m4!gP=GBb@hnqLqSs<~wG>AE_Ig|O(ZwnV#n$hpRT}F)#%fiT79mNblhg>L;Nj6G z;qUzvWrx37XQ!tdTzdE2#k{KHR)r|Dyu3s&8EL&YT?$)dM9?eH-;z- z?!2;Q(rsr;v=P~F@I?Va8TA_;jTef{IJ?$YSVW;#4AxbZr1F~qyZbh50Glaj4o}1$ zcb6!J?Q{vwc>^Th+Ow^jKdvsaIuD=-Ys5}z#Z5K5U{B>8OQW*D@xot1h3O6MZojh0={swf{Kt9mOZ`snZkFC;g4- zZ^5S3#Rkl^RN1>>ZkV7zZ%(6*jR%Su;Zx3I^!JTitg;Lmp6@MZVVl6o!7>WAec}ilLd34rvtdCbO03Kcv|r`8J;jv9dPqG0hnnlf zvIw;0PN1;fC5l=M+Ycn^55Q^FpY6{iiKeBomf4Yw9bu{vxbZ|dt?Le1kahz?s<($C zEPNEvk>YE_8L^AiQ)Z|wSNVh-+6scov>}v^E5>ee@(TjHc>zM=_w?DQ7Cjd{U=6iP z`L!Zm5=o`6OH@DCMV;`&VFFJ%zIwNcJnhy$lDVdPj`YS}6(Yn69fSPP>x~mc_ulmi zu>dTAzKO>A2=qzG>!c&0>e@;}Ry)NvU7oDesYoPSIwz)qf^+PrSEx%x2sOaCFKy!9 z#HKLPJltLToLW(r{xG$8`)_xXm^!yukTEN(AkCtV(aF02a{wE!MFYc>cA3z1l&c^w zE>xXpkbZ+P0X;DW50Wd=91j2E=;*Fus3BF3quv^7grH5%dx#>QPH`NS8_o@R;j7oo9@b)!cuBnJJ1a zIRb=)N2&~ThjuBSivNUyH8+e00~l-~d?Cg2!YSyPEK)03qXNTsQVH?XYX@|pf#gSC zvy&%s26AA))!)+FfzWsb&?E|W>O11GL`ngasO6<=42QOVH}sCOS;YPWvu;Rs`)YX| zh#N#196VR?9wmYMD`iGz>-^}Z{*RQpWP*KeJV8+#oB*@*k{wxPAZL9kQ77+g?tz7a z^bXMmI*tqMhxnx&fVt8fcpm>_RA~iG52zmzV^39Dn3()R(^_q`Pe9*nvss@w`M!OcXF)d&)rA~+?>X%yUz#hZX2|20f* zLeqX*TumjJKTri+K@NU@CeiUWSg0gUKAH}voyuCqE%%ysJ`VV;Zo)RJwaPTG3PGGN zv_8fHc}PnuPaffG@;c@(;wT?a;_{*JXyWbyY~>o}wo90u55scdk!KS0o~8^Qr2y9m z09C{tC}4ktDHHNT{CN#d$I$_aQ5Eot>8YNneHb;Y4c0vPx%*}l#n^9J<7~)!OQ+wq zGh23C;<*Px{mgySw-G%ciL4WZf)%9W7erp@QQr=KOKiVL3ERXRSWt~iawQ7`CyS24 zW$zu($MRFAiFt-&yQ=JBA z$hDT9TeRUglRhS7%+{wePFi)F?Lhh=*qftS+qI;oOJN_<`Y$`4CCTF`$lw!pKlJl0 zsPZbUuMYa0)f|hU>`0?=)me>7LI>^YXJx5=S(W(nvsMA+nhC~j$htd#Y}A;c3x2)5 zs0)^$V~>PKJIWf72+g2nOkS%@nN<=?} z-L<)9M-|VXZAvLgi|J{!%MfRwG{g(D6V$b!xT30g8$Urj507?;Sg0L98rdGgaohmIV zIaY{z|L-2H0-Bj@y~aBSn#kITHCXo}L`cCQg(2vwRetVrk)Tt!`ej5>p4krLd; z43J6E1$OKB@CNo6*SF=y)Qhi5<0{`>O!&9x#5-O`MiLLUO*{0oa4AQT8PSpSL9<1sT5PR*J#mm6KRH*{)~*Oc)0#Bj zMwDX$-L=Pjna}+X103X@W-55GTDS7%GONMo1)@^vF~Vuqz*xmQT0BCJWz(ynS^Asa zS?0C0=9k*vyfyk4+!oM#u&tL@YCVx?in%=}LY(3^%4)NL1dtXPajbD${#IiV&-HOU9fB6VDd zM@%Q4^gd5|E`V}OIh~*lTiX;c7&}XN*-TBkVX>hZ{^e7QIXL_XbjRsYrNTL$Dqeeo z@T4eW?wO<|$sz2In+NKFhhcffYMiySV}&HU_V3_BsKf ze)=t@)12D60tvVt##I7w_{u?ZB+XYOK6%U++4{y5mq{krSb#abR00+F5^m_O&)4rP ziT|P@K1i<(VhtmZX(8;nRT)#za1ANg79!ErjJr zVNot74Wha6IRf+ID0eo8PPrl-h=h;nV&lMQ;!5Drgn=Y<-PsubV4yHB4;aFCa=o9U zr#h#bP{E}HV96&TP9T>-!f%iAcS&GGMwh;(>pDFP%cZlD?DZE$;2m%d~DQ^0jSFHBQ&iDsxxUBpvXknp{^y#ekvI`J|~iy8o$h-3r^s}YOJYVvel@n z9cul%On$Ynw9;py$QYVn*VLq=9rIq`xENExa4<+_8~3%gt!G#Pzi zz+-5VW~^}XZN($LV3xv^uN%wfv`%^F%@z@?6Xxg!h07`LoI96!Mj0w5*?l~`Q1sE| zt!c`KRpgJ7go3*b7Uc@>YBCSeP*;9?4_S%&HP|sXP|FdPILLr795ELCE8j8u7h(&U zI(0WU=%o>y=^KE=X5+?XIM2ay&h$l6$}T^q^l=Iw0?O$5LLmQ8Y3*K|tN>w}6V#EW zC^NnY!aj825-f6JR73zpd(p&~`+)3%E%Hr-So5W;v3(^z_>C>m=iAVl?O4hjKJu~e za?rfF_RA8N`<;XcEZr{C>gMR7K0$A_zu!k1wiqOd5Uj9dz=>7&>JlkUiVzJYBZD*V zu!RJo@Wv24F{F;s`S7IKeiM_Zd(TQ}7nAtiSqR1&*jn*Sh4-gFMcwAZa*0C|6&7~M zXmfPbC4i#zdGb@sbbh5NT_6`EQXw2#jnU*677#A>^+zgy5av`@MX6E+OvcAVWGCIXQrBR9ySqAZzJ}CBr%8S(b!4i$MsKe1&@n_+E za;`k>L0R>IIgv#8=H=;}#oOZ$y((rLAvXVMbR)Th!OBG*WuE*@STleyWc=S06!EFm zvuREdH`<&CZfyYa4gk6d0@C@gS}$LNeujf0y%u^x#d774)zRV+^4Y^K-({p!sz^!L z>Ha)qstZpaY>H8xL9NW4$i>-a8W4)L7aWT6RUp*_W_Un7RIntdcCA@?V{B36rEs%u zP@xMV(3Szb1*dT1VxBl6_SX5|!1h~~7b9RmqH;|9=yWSE4hIE!lmNOjm`)UYKX}Y+ z2B_G0tViqxLjwlNP$zl=5djY9&&Mn!Yr+)wX@f2JTh>UowKloq%21kTuHvn`c-v>- zEA_#1Z5pUxgAyK$CmqLEs!)>q?Z;Vf?tb?V`}W*nREJ^v#GW(YR{- z4NJDy=-GpunQBcvAkFD_b`dJQ`G)m_CVIkmUbXXrZkBvm-bCz*tXNhoywR=Sryx-pd74MCnaM>iR^ zp!`A--VJ&`KEWC}awK0mnL>rEAtS-yIPe|_2Jb1)S85h%;W<*_rluA0d`hPF*fhHY zs2u#Qfvd1ExT2S6O|4oZR`rs}gulxU;W#`)=~4*NV=@@s&fWAD`$jJr=a7emX6j9s zc~E7bW>y3;`VGv+{FQgM`kG~viJjzizjI~N$MzzFZp#{}*pSgz!8D)DL0185&n&Ug zMclZ4&(pVhL_y`#(`D@Muvw#Up+qHBm^>j}x;2Rp5!*h3GqJ*W$->J_T9u6hO%lw6 zA%hGo!SQ$f1RKXzGC01%E8(hxlJR4=i3>czC(5jX`MmH}058w4^TRcTW43LgK?ZJ_*hATyB+s;uz3T+ zTVu}esUwcWVA1o&%=!d#u3Cc}+t@PAFUFs<`ospgA7b6tkkTb6bxv1dET};PVW67| z?>=&J9t;!Y_9l#u-t@TiO>NBBuv~UdoS_vAHV}ITN*-e-GO~^)-)u^}VFLaWB*4=w0hl~N9>$HK>=8(JaOZW#tUar% zt?CYW+clEtwE0E;1l0wH@GFdP;WOQE1c;HaPAu05Ki(Ivb8`g>{s*n#lI|G2m0be6t22>*5WPVdx&@ zB;*GQ5MbMLH@h1LwK-UHx* zjS%j{;p1tV+=KO_SIC3{ykgnf*#MdM1Geo}6% z7U8&E7KP~3EVF_gc|%L%Es7RnGAGzpNp(8sB|^~$`BD)s&D ze|`DJ_;;?*NBMv7ru+_&>^qI);*i7?qXd%ICA#|VTy71*8D=Qx`cjJVZW`2jFw z6_&)`8Ya)9J1%J@mHCLt$Eqv6(5G#aP4%-wsu9(~GnWW+RsBUDnJA$rUcvmT6gxU0 z6{Pe5ly#9!oJt1Nck=G=jQ2`Ag}1{Gaqo4BaT1SIpu92Sc`>VQi+Gu{rRl=sQpwgN z_?yO-WU+0z$+_DoZZY@z=1mdsm^>btMA5%S9-%45X{A|JrREx4#0`xikNZX|PhxHc*sBAzH6Rg`WN`}L_-td}^fk52c)~81mPy=FNY{}2pIxGIklmZUHoei1R{(eqiO^U=r{sXLLR{gHgtDmVXqO8$QlUL(3AC3|0Y|()3y{2khv@0 zBSnZ;Q|={L+rtQ6aOSeOnL!8$$IK|G(g zXgW|CM86VJh9f*C4P$+&*Jf{{QPl1P^1Xp3IM<@jjiD^|6n5{}FU%SkdpXYO8Yuk= zb7P1ds5V=%r}!_Kj5d6-8SuwKQ&WI|QJ!(pCT;`bSUt3F@(JS9Nm2UQ(enU-PO|X< zlLYn9h*HZ#cGJW8OfxV#h~Xbcx9 z2=ZqT0C(}DRVE5a2m&;6s3?V^e9uf_{x5WPTElqy{=!&N?G#X2BT;b9kQ;Pe>@;4? zCJ!XfTArsMZ%EH|;25 z7pE5|su;8|51dsZIZ!SxqO2BHBD`1yai&{tT zj)(gID*mW(CLope@;#!1E@fPU5)Qvr`O~0DP51BO@FK(TTuRD7kym`U>M6NeD zK^jj5DyISD(e7YEb5rc`DVCc9ThBn4u)Puh7Vxk5u=`=mTW3GM1h#>O0Cp{h(p7f= zP8^G$jM`TKYgXgw56uj4Et94qez4IM4T8hWBJXp3)6KL>JpHE~XW|sdGLm%&Qw6n) ztxk~Q{qmPeD1pA9XUj2!gcNeOTDsw=*ohV}@EUIWW8P{bJ$ z416)FxbkB~VK?qDYyTD5i!JibA7JrVk^&}K14y1fM9)&%+=K6b$*LVw(Ck^6 z2n^*kySrc^sS6GQAWPXt(Pu-$@pB*X7=s2%Kk&;7=IAf-*I=BHF)~AeC zxX=yEl@RPnF9reW(51qYET{ocr3G>9paeaw5O*t$HS~}zo&mG(r$Mipmg9K3%pu8j zW#zZhVbQChECxtkszwj*)5qsNC-+b*$csa0(qozZIl2(Y&USO~qobVf5Ft_@DYRzm zT=}ndbj*SBg1>INM&F$P+tJPL>0Rxl#tsmbwF7hq%>F_#-?xWP=ro}x+&g43;F65d zUM0KZTG|X0jl$%{_B}Sk>D?mtr0ZssEy_Y--)DQpQ!g;uyFuQ))nJ?G4!Fuikt*FY zKk^cucZ+WCeAMyj3;w_Ra-lk}#OY|S1Lrqyc2y@z7DI#F2+NJN4#_Hn$+9|4tB!`U zsqwds!mLZVeUjr?lrVGB>Ov=WlrbY!C!*D;cH?u5HcypuSjHMu5D-LOd#$_QI8=Rc$;U|ww^eM*V6nF8hma@>~3Z8z7zJ#cVl$H-N z38EX@QK!1y4~Bi)N+W)(ixj#pnzmVl-zcpMpaU8~=UA;BTaQ(q$YH`Vtm^}sQ8>RR zUZ(*<6j5sp#cm#3tg3VhKmfLpk&BMWd?e<4Z=(cgTy9z26w zA-o%35XdCd-K`b63()Yv-5c8L+25U0ZcATxQKMW`JLiBb^SCj|(y$KB^)(&HHBju= zCQq#8Q^0|?h+IsQ2v72g5X{0Sc;sSCH6j(6V;s9H;g=>iI8KfRbc#>vw_l)Ujo&`* zWSy=>XDD~CG)wWgxSXlTc86R?5p(gp8MFMP%4b~`h>3bEPNr(l^&FO}*t5?8taH6N z9E3LXX<7WnmTeJv5g>^1x& z)TspY-VC!HMFSeHGt!M@+4btZ6L9dmT~wRLT7K%QH#@69FG}*%1nbY?Cr;hI=c?0`8T=J4W>mDvnXv9_tyWa8vYjVPE>3A_G#(ZNsC3|^g_ z%fC;D?)-fO&>zqmK_8USze9WrPxzl;x_)BKGn7b<nEx zI5Nm4;c&~Ffh(n&;Pds?M3bjOd4JVBts=CkVxGWcYgxDN3fIK7#6ja*gJyb$D?M=oX+{fKbQj;r0`0~S!VH^pQk+%h*Oh?t@A&IeU=3vpk`HAx%_*Y2WN@_Ye0 zipQFWyYu8MkXE=uoHU)*Djv40V??Y(L0|o(ak`P^<5du(W222->R97N4NySd%sn4Q zE8`&l!bIWb?xW{x)53@kNf#2=Ejy}~H~(QIqC&wPVtZIva-*zvg)T#JP!sF%_TZDY znC9j;&W06QA1@|6$th~>NnfT;{bO1w+bz(H@A_!pp>}zDB=)8~_$s^`fv7(%FS%)N zjdx1_W2H%`(}|De=cX8Vjy&hukTS#QG__X1pgV2zVRoz_}w@FpIbaIp{`o;ndX&_1o^&_Rcu`%TLCN2^kbDzUzUPlYcg3kDK=y z!K1*JU^iE}*l>o=`CQ=-e3`Z>GJ)XDj%-7JALulP&)jo#A_IjvXV-Eg#P&EB^3 zIEMR86WN;vr#a?xw^VgxBLP0nSs&Cy`Pf!v)!wR-mciIBi+Q;4k&{y|3E7DIjc(=; zs3~Wb+3Oq)$fjB!-BOz57YA2GwF#fB7sqQ1T}8$y-6WW02>k~4|7|uQNlYcMyQ2aC zm|+JBdQJq)VhWKOJPr~dd8cXm5;jg5nazY0`WNwYn~;5o-2}J8R(&*HI$G?zN#{rx z_DVFg$3rcxA!Zm}b0>pW(7hHXe(8Bk;O+}*%r>wIeB$`fy4uAH$K%cdmPGkVYR>?| zaE)+CpD~IyXWDP&3JR_DR~o%6P|Qa<(!&KQ{0xjvsDzsCZ9>EoZyxxhGd&3LK&X|t z#TSQwviH^b&s3Eb0DbiS(Eg1ddwzm??uzM-r=NXcKQ?R2=gaJ9h`2TYAZ}q|ZPi#y z1(+(j(LD0HSh6j;1BKR!)$?m!CJyTiY!gI} z*LIp>ww8mkDD)p`JKzT;&Xb;BuwRCyAELO^FAhJuq$?9E0vWbYM4Rx!6?qu6)vMdK z%~@Pyjgi})eo62DUg@c>2s{mpmggehqE2V@%E&swxGSQ5&Grm0ye`-|(miHDl`{J1 zmC|K{?<&}gd7_9MS8=H7QX8;nvv9Z^K8JD7L|=#{& z-*$a<;oWKNcK!;*PA8=8t@<44W?(oVCM}ow^r~n-mIVcmcb) zLDHZ%YelS9?E0Hpsr#dT;q80|H6j_egtHjRvmcI=7L|*iShF$3KI;P+;*B<^y_0YH z;DRp^$Qhu&aDG{QKRO-;u#eDF>WKJLJo+l?0^`~gC3g(J0H1VPG`2@^)Szj5gX zx%DU{m-JDYV-^9!4DuAeb%12yZttj=eDHw86ShG|aYG4@-G)|MuS0{cI@M|F@8;*t zl1=e(gy+Z@lJ2b2f$EI*_zSeiNdrd7Adl09*=BLIe7V3k>I!GEg2R_$`ms)Jp8AZ& zYS<~2SZta(pt1`;Y!U>kZaH8wsSjuLG2FsBc2}#z!D7@k#(UZl43M<8WOq@}Ivd-B z%TXvmDT$~IqNkjOfPl6u$;^gzgU?CM%!1tQjt<75J)k!`f}ek`JmT9`D$fVY+Jkp;AK5^3(Ja0)3xJ+~c8P4iWg_ zLg@iD=gq!t^jFzKP~YvTZ5ZxTm{TR0Bvj4wO-?T5}>qLH)}@&RFc(x8u*HKnZCW`3XiFU`wl`KIq) z@TIc8(hHdomn2erVhMSa0py~HSB)yg8KwNI?Ri$d`}eY4Fv^iyT?pd@RxxlCHHF~< z?+S%LD-cP6rsP{m1Gqm7n9sPchxuq7Z5ebRj5R`uSx zZMJHwWoA>@nIcTQumvx1GzwdE%&!IHe85JSeM9oQoB^x&wty9e@E;y`tQoswhfe9U zP9B;1bWI0wg_D9>QUVVp%!cR2Ro|hB?Y2G@CieFihlId+9N#B39L{}%YCp!IttAKW z1lMQ?q`XEBb+I;zEdjNA1&m>A$ADL8z>oh3&~>PQxfbG@P7E7x2d!aI117Seq5rWF z1191IJ>}Qf3g3OmYc>dx(Hu#tJ3eMJvU3eWUqk8s%@-WbF4USl8NbdeBZe}hkO(lo zo|-PyN?{1S3lxGf3Ov2+;*HAv2~eR#2EF&`YO7|9VL5{WT1OlNlA+?2MYfez#{|P* z6Ez*{h^G7Vdt-rS&Ho6`s~2QrlJl*9xf>V_ADV<=0X7MC_!D?+e@qW|f#?znpQSbh zt{(`4j7abV5r(3sds4o^H>pbx2m>81B1)l#dIOP{0!pAbDOjk}7~SsYD_uM$D-$63 zYzH_u7X!J04UnK!AhilGY_5cam7elLOK|=HETe0@W>$DjC&0tz22*LLm*4}ah7p(t z?EDB&XO4#gE(3a?JFli%Q^ZZA_8UViUExFBgcvl|yLX?HBn&wb`n`f-7hGxl3lc1I z$h^*fD5bAJzq}HGCzOWq@$W9InGy)XwL-QPWz7fL*wCc99* zk@~Cl;hBxd(1?@A1)mX^QD8I$JK_fw1JPj}WSol4i0f|8lz3(WeA<#)Xfz6C3w)CE zd77Qv;oe0!x=UlbJexo*YsG3x2H(htXPKCI{CTU!zH$9@2#4p@dr&8nPLFG1Fl7K> zY58*^^d9n<((ZU1fv}lC4qWX7KsJur5_LZdZloLyFDxkn5+RmpPtW4vSY&lEO6*O zC)nnA5AA=Bi;=*KZ!bmZr~ef1?v>uM7K{kRNlC2f%lCeK7Xr4)^ag(j?0(axLmk?x zEj0wacDcpi0J6E~t@y(yVPs+cVTU8V)j=O37spI3YgK21B`p`&%65#qIq|Q*UF^e@ z!9|mfcGY%g$m~>2mjSV)D^xFRt&%oEQSMXrvaxOlJbNU44L=9dx`H)0&SfAy@Cc) zr^rA9PeYBWSLDR#!~~C3X8;M_Pc;hn6?5G-01$C|8-LN9+ljh)5@?>AQC{M|oWIZPmx|pKt%+!KH6A2JI<-O#@a_}l+lBZgMRM;(2WoT zC2Y^I$6Zj3J!&{TN%M()9{}UG7FFucyWBFrkHVM!#1l^m3I$|RPY#G;SiQW#d1_jXVg}>95mj%z)yp$TmE^mJyj{m;Ii{P?pj((ph_^i0!!@05Ga&DSh z--+nNO1p@O6jfrtEcsdkISivJ{L`|*sTj}$XDsAXvDq>*OLzl5ZwDW)k@4Z8jz(%o z(Gv6N37ruz&KyZ71N_fdG$_!-BGZg4Pw7k)OChfXplQTm3b@jiB3S_YZepS+9bV(C zh7_YlXhT5!*5{^!U0;h7iI-=<=MTy%xk*_CD!zjR3v$NxeWd`dlCY zk!I~$dao7hgBK{h6kNdhdKI1EKN*|?%LY7sKkaSO%XnJB6W*mhO(**=N+ z;Co!2hwBX>L%K&U2b|92ypS%=ja(9Pers3gNf&YLIA8$@k6N`<3ov(khzt=y6`oI_ z5G07s`HZ;!Ry$uVqpE=++bz$-i~WhP{AGUe$ds;gzczC5b9@z`lUPF;r1BDB*IXI2 zk0(Q-#UNN$oOVW~hUqRkog`3cI)T&sc9U45+nKffqkOOrtB$UTRe+igDqXfYU+}0< z{NB!o^Fks#Kj)Wg^u`z2Ora{8S7i2vs9p1^@h%g2L8zAiA26(WZSAjmMiY$$n%F1i z@vu%&l+bf}C$N`F7=b~@tVaxEJ|k2;+?;VDIdFcT8)rsFkfIRiy)U3=!QA=R5L40syPQxc( zsMBY@Gvvh23lwO3-*zs;;X9PRmFESM%Fq?-VT&cb;LyHta1(;`Sm5vJLhFi z7+U%r^~P4W7s}+%79TC>x6cmxKU9HLX)hbKTyPkX1AYzPVzxU8W`D3IUM94yp~^|Y~1d%>>FO=7^}=i(#XLA!i3R6kd;u2uaDep+c<2ZC&3u&Op3tV@t|ZTPVZT-CeY>8-{XBba9maLbK~ z^f}+b4cYo9Iz!|10jI}N+e_{dAm@yx1*zFMTv8stNdni%?07&!#OL>M-W#1`EBEkF zlw#)uQiR%Zz|r;6I(&N4O6O>_<-&WMM+=%aw&B*_Ix`tZW685LtM+nWRoZJHbtl0yWL^V zE<;lHktt9t5|{~0K@3eMA4n#Rm{u8r@KZ^H-mjYs?aGOE+ALum^85tnVzBF6ZPl=# zay{bsA@U1$cs~==XkGA=4J)H3$6msJ0z|bEbg1;3o7RXK=rnq2dT4V|*4T3gge40j z)Dr%j={muQq$X~pnj#V%iPeC9%4*-SOt|dgfIkD#;(ddM(mC8EINUjTeOgpPWH4s< z3ou&|e7^O4dQO_G<`Yj@IM}=R#jM6oTTNvwr30CmlLq0p(;2V|2O4R24P9{> znQf51g+HQd{QW25db|8+=%ieVn_Q;zkw)yx$04o>)QiA|2C!M3rW=I~vd-<)GLGc9 z(*V)g3#LTRjUZPE!yzg;gUB4Qh%kr6G$Vf>%axACrAoGijtrvVuCs6hx9te}QL`6R zuk&LL5m*EuP{&#R;IdSnOSULDGIxKjIVrt7VCzktRlY0ImveCBOB*!s- zPOr^apQt-0=o0slgxZ<<-7n0T8A%zEk&Yo4-sM;{C^|~#a7l6j6&}fONmQ^7DvTw; zHBP3r9Xcs5L;`99bRdEcXw!No=rkqTGBqUIMkd%$@}WAgj&#DVQ`sLDwR;ZdgU^fu zfg2$tC7<{SJ660(KhldV9v@EtOu61{lC2oQltE7Glv*<%&9M;QuqjPo<_wD&F5zT| zBr~%1Y1N^X!WerSnyn1b>nJo~iOvS7Ir;iy>J$`%J|-ipM(6w-^}ujq8^~;#S?@wJ zgf_vvDVD(s$ccDP&K;vp^K2Ryh9#sYKzYtvtZ;=cD_q$vsC^dgvIr z9i2_o#3JztYoF69 z-f20e+Brv8%A&YaH!5~f(m|ye%|LwNEe>nD{d|OuZVBHACNh_v4I?%N-tVg^Vh_3! zlB%NuxYfiOMQ=UguESP5$T*|vQLHP}pRw#4K`xWoCHL;xS`hC{#L-#xZ{{ld%Z`C9 ztt8%{hc7FJdo$|2>jsE+gC|;~a#P+k6v{hs3R_SkLXkJeB+G3R6A;`igt`aV%33Es z7#yo*eYYM9Af4>-@+4mxpb^J^{87{f;SK3biaj@0(G8)( zZKTEoVCz_vpdXFq=IFWkiwRzA_;QmOHuFK=dO{w%IfceFk%EV0YHWa>UX3(c3K@x* z`iADsEPbN)!YBrcj+FUi|GsD=^s5(E z!^_w5ILt4HG>;vu+YKsuC!DPK>!nh{+IQT=mfp|4 zc&Xgu7Ix)chuuZ=0DxQPn}txIs@|cmf#%I#4m2nubM1}Y&^G0SI5b(ALLL8m)7wHq z4*=l4M1}UUW3;oostIXs!8~PUN0K)NByS6LCdMG(<#5CpoC_t~=00&y&m7U301|*B zOfuCXn!KJ%v9QLFv=%}V7r4TnXI_LQh)i^_TSns!>nsr=0Z0T@T_pHbVf^tFCT{bG zQc^&tyc3k$ThyHuZIf7YfQWf9q~1QxhB<-6aA@-&oq&5FGb~_@UeVEOLknQI<4j#VQxH6 z#uZjz9iA1o7XI zpcn3d@IB-a9r1~U<^D$2hN5{MEtxq?imvX+gMEGCFhM#!rjue<@ur^yHns~ zXV>ouRofiG0&)rPlNk6pnAn)bk-an<(J#(lzU&me&eRB_diIIq2)7QAEw>tk%H;4R z92c}AO0ajnx|kAj6v|8k(Zp^b$Q(vS<}^4+Pb^U=8KN-Kf#=+j(PVV<9676v{(lb& zHdW!s22(XqeE&Qyz7$0&69zWN+nsKH=xC$$uVdLv)F&#`lVokXia5dh3P@DSo^=4U zPbkB7h9rRtWttWuyXN(gNX&sN#0dyKy&X0@o;FwqhZwzo`P^`&3k$xE8Xe!WX z!!th|9YMQJRcLUF5Au>S@ctgWguSFe4m=LmS9>uym~?wU zUD%2_!aHcrbucp%y56Il*7Wr8^QQ59d?OL?fg!Ar$qX(#CD>Wk;s!cE9S=hUDnCAn zP+fA_LOrWL3>e#VTw~76Ejjh|1GO2L`g1P8U@ZgAlZm&vy@jw4Jna~|15@4Q)0Uj< z2j}tNgIuJt2vaUdDN%eQC!5eSS5IBD^^C!7GRZ-}VU|Abq8ZcFW&Ps)GK*!tNYdX2 z%*bI17})ZjQuC3+tlfnpJBzPrEB!JIzEYkV_PRV2*iF-zgq8&t;6%RwuXpD(Z*~4b&s*#ve6pO7kUN@$AH+b|+ zNH}z@d&J}}ad>rtmfh$fil{3K+pK`z#-l!mY7XR_2!2|bsja~2&m(0o?dqU`rJc*X zYE5Q2%Xxr+}8L>c6eaOF*t$O2}Iw<9=zd)D*1FY zk!Y}F&?IP?TKma(OEsj=t#Xvmy$ezS#c69J6>;vf)f3pi85`5YYyH%k1T_ zDsrnduVNQgbD}s?p#RVO@ z0<46b$?Tt6xKSjxC_57wbxK)Gy>#h)4xzt~UC{xGc(QiG^m`5&k>=0}2Eey+U^G`! zmTomUR4;48F=B^dU65>&(At;t#H7}9TE*T)hh3E%8zYV7MTtJak}&)AODTq56W3!_ z3uZ_@Hx~d8<^fy+J@IF+$I(!I5r^7-x}1v)I}?WjDkXT|gCR%!sV6=wH+TagzF&ll zpNOTA*-a-bSgpz;?6@?1k%{@$X$c{YBS5Fc_*v3m2N%(|40`IFyT{`qeg8n_b$(s1 zwj&Ar3&E#Jezq-2xlVR!VJEQbBLGl9ufH1(3Btmt=6}$$H@(7`+ONK0xRQM2SUz=4 zI@l1ph9yO38?F!j0NMhol|;1|#`0%YBW?W^oGNg>aw)an&7_`c;^$1;P*hAIYy!@XZZCkmFWGgf{8!p3Pp zUcT3hxevx>=Dz(bpg&=sZhIj6Xlh^NLFKgHCqtxYeD}YL->Hn_<6D%8bJBhs$k4~^ zN8?w4#C|kPl={Y)hNeG{4D;8_uI)@yK!%kyXF~u8uF4ZE;O6|Smfze1;vTaO0_57j z(M{!)!H`e_z@lZAV}T>d_y;g9T+Rq-bn0%#t<^%?P?)pucFF~Ke~?*F;q`Y0Dx?@C z+|tw{NU+>exzj66%X&cn`GH4I1VCL*fTPt_+s88<4^00#S!$Q{GDnF=%J3*^NzR;# z*nXgTSY-J~mSP0h+kpoptp`s=WKpF6K6?aXLiUHWM3w1&U_JFHM1)7h9@m?wO6Qdf zW;a5%yUcMj&;j8#w8(3rVfznZ6F98VUwyy3qxr8sgd5QPL*}brkYksbSIlG&ZJ_-W zaIayV-mv*`5b~+?u&U(?qjZ=b zMk|0YH335&qUzKKKMrgzmCdH@i2eKu{WcDnhO1=O-|mA$15arYxCwZe1pqY6RNCm}Z@3JTAG4Y8|%K+?;zuL|nmZfHjJ2X)1dlJ;vi^h~ph*L=~Dt+NB)JDd=p} zTka5l&q9cXiWEwv7FsZRcM&R@;Vpx(Vvq?eFGn$REMHQU<)0E@i!7Z+>uPng2 zGL%^52}QT~`>;hXps$5a<7U5k9_q!pp-n|XD+OyKc$5{sr1X|}9yoDu8>0AwG72MP z?90htE(@sbYNZ$3Fmy%ZeMiXxYnhjO6BCn;%DC{~`~6Wp^p$V(%t$UTIG{fa#e#+G zBjn&i*C59tPIVvYuKZ>sf9!|VVm2NuRB3M64?&7({F7fnbrhTx({24-Ta2~QNlx?} zHEI+917d|f!GHQ&epByb$5N-V1QdOXPThoH+tB?UZ2uCV_X>S2)XsZFbAAp6l$n6~ zRa&Cwgg#U%3j1M@d2xkHMKLNf^ysn(H7LskFiZ}h)8olvMuLmMbiGW721Q$Mi}u>> zRVzHhE=q>5Ri2a)Or0n~x_w}$8$_!-+h_a<`SbUIrY$69*cVa@CaW`l?$EN%Q!ii2 znO})ie3Gun_n(zj0ZG8XtbP`XDlO0MP*ZY*N zKqWnsd}^y+(C8rxL%;1c7?Kv}N}Qeu_ls=N&eTkrT7rt|yjjhVHk1FtPYyyE-|GJv zWePIe8RQUQiPFuS5r3h3?+8Hpr ziaGoXY48)zOK#!N*@uECnXg@8dg_9$)F58yCOX`9M)2H>%PAAkPdjjLx86KO^f|JC zD#N;|3GWZx4-)Bbrbm!d-@Z9NipSN7*|r~?-i%lrxk|*vhSypg6OG4@BSr*0i*$RT z!bU9M=)iNzyQdHRk`jjZ6vxB@N%~O%U)tVzRF?WCe~Yguq?Yw3QdtzZ2OSC)QxaJ# zmz|=>J`D!_(9>tq$E19x^UY@g_!~>CiBNF7Wc9RIXN8Kw*_OXeC*M?ZwyxE-E*@BJ znu0cQziAOLY4~#$WzpMxrfoDa59*e8Vh2y}7&DY9-?KU2VGi zH2E(MU(~vzs&Y--bVAj_Gwlm%J05|7u=en+(+@8hLH9D5LG#BOf(%?*E zO@Iu-;6OnQ$zi$wQZ2<=y>I2xt*xppI8=oRSHQ%yQ+-#BG~_M#nAv=oxHoDvYwahj zaO*T^MO0jCh|l5u3hn>gdIfz6mWQ#P=NHV>6d%HbqE0PylV4r-v{YXKN>?}=6^f%# zY$IVsGHf^g8c*!QQQ81J^ht639o#)3(<>(HZ%>57h)Tp3zY@`?W2>@rlypwv<5*@X zLW#HE=?$*eSlG-VQ`pmyJUFM0Gxu!h^f9`3TfEV`1UpWo zhL8+3xYsAJG(R^qcRk0xx(L?@LLavJm#)pJBc99o6YkEcw}7q-*qcqu?QEiLfe$ywninYk>dzXf_B38l$%-IENb-|30 zFTPqt2R`z{uj+QeEnCHKsAM>hezX-doY=vWn3zP+W#(bLnMZt%6Emn(K}} zwj~om_d+*Z>Q*Mzm+)N4d+~?6zK5~Fv@&4$@zlkIW<~dmK6Q@Ew~d21$_0)=zI-k1T3vgTrS@|kCjEaDoW&?84bUOR%Wb)F+!3R$EC?9O4;(IbXk zvAcM&1YIHbMKy4dtb{wCp%^1a)(2OoHJZMxv%|BsXg77a+fT=l8K`t$eBSmF$x#{vU2cP?nXV5m)D)ScCNb`FH;doBQkY z3WeowQ%Aq1j2<1S>mOQb)^5#aD~-F66%4IoU?V)Q%@mm3tynR{Nz3f*Qb+J$tsl?; znZl^MRB%8h_B=S6_<-~Pf@Q73&2ApTbnG6`;nB`G$aeSoU}^BRxv0b*cM7&_;;Zs; zx4BoU%@+z1QGSNrq=kV}rxcm%6=>~`kaAbwxw>h zMFi(`K(r#xWPRXaE%75}V++)lR5fWa};toJcr4Ktsc z6|%v;*mqc?pggi5u|wVPrW{V#?u_%dHh8o>)Et4k8NEvf+_#uTJ8_|KA8^s*54xFm z4DMVCIK1pwn*}Jw>+my7F~87T_D{%k5@IB9Is~e=-;0evu_ny-cU78jTu4|zSGiU4 zfHu3tdP+cI_O52e)=5+*YYWxY{wfk$dYN(z&x2`cJMMXsiAAtN2$EAM8hS2@xYE{6 zn9j)yhE!hyMI7XUZ%?_dFgCVJwl49-xS%U|1jsY|SrZE1#_0w$AP(#bpc(<}|X}jLL4gsi;P315R;jJ^to6Ks4GD_Y`Ib$W>Ef zNDE%^qwSyyeTdIGa8z`QMJSJj<#8IC5XF1U)bo;-|KNgZ%428dAt3PRB0P?*g}o^* zGZJ~~2^-DNQR*V&OD3bk$k+bwTBg6avUp#K02wSnnxWm?Sen^e9G4Y79e^Ph>M#@I zgZ|`U8HVylWkKI&BIh?91W!n7N8Jpe#TX}PBh_b7kgo04M=KO-bU-PU?zl2}=%_;! zJn})^aIdMj%Y6U1{P_X8popz?gi8jav?ptg7}Gkc_Hgp8*Kpqo%aml(b4j@2bH|=U z8P(EoLX@S-GE)C%+yoD}$L;w+vn`G#=>z0;@Cb&WHwv^-w7V6`1b|4aWTHZ`GTx{s z9E2gZSzyr=%DRAx+xsnj|7htb)P6d|rFVMih$%JiP5MM)qNh|I0aQqDjO);_85$fC zM+10EmF^K;b0t|P7#(CmmlZi9$cDpF6M%M^i82`WFq&mZp5up8TOd2*`y(h1eYHC~ zR^ln{R%0l{r|Uw>1LL4n(|pRNtEqwC z0FyIlZ)wS7wOSel?Oyp;6e!r!?fXx*EAmbRCF;IHdNcchM<4mHGK8c;Q_6)w-AfQ> zuZw8YUT%EGaui=C>fX=Fn`^2WY_(eBkigJ-mW46^su!n-MHYA=c{&kpmJ}sb=-FFp z@~bpo#wQ&=(Q zzrb9TkI0#r+%5?J8DB#gb?lcI~f|^2L=eHq2Q znAoWhRj0#<3#TSI4R7{-@%AAHi$-u2e`UZ4>xr>*r94E{sb@iCU^XE7zT#c1pnvyl z;knR}KOaaODFr^_h_c)=sAISKY*?eXbh^If)3%vwv*YiQh;04E&dhFn$fxzIR4E~f;)eT-^0W<0Btpsit5b-ys(#e*lYaK;)ow0Tzf zEE}43sMu^|PInpo`+!ykxzE_wS4Ol71&x9)JDZd9HiCNOJ`R;`PF>%LypzbuY@Q$p zRYWe?)llR`Q5>5@6-^QDr+N=30Z*@$!ukrW5S-^gAJHkJOIH2X`4=JDQgf>}H>`xJ z6;tYYvU&Ms65b4#j?-JE0uqi1nu@5zjv3ldX*RUnmV819w^E@_2>)hp)a*@8*$-J@RDvH5SBIddqC z%(QFyvZ^6LG{q>iRnd(NTWA)bZ`FRF)Ej4CK8j5>iyyF&8lqAx(NF?Y3qz_UE@YoB zZ9Qz<9E5TlL6Mmy^=`e4aLlh1A@a1sY!*uXPHKvW=R$DEDoL$WYsJo_psRrwXV_dQ zK97_!QyZ52J>c;Uy>6=WHQ|W1vx~KTse-0%{5BFolRfn6$g3-AfrS`yHPKeVLJ?x3 z3LeE{I+XGb6smq8%S*P>7I7U-DY})zBA0IRhC0WBLc*dJ#m57-kVr!qey*u#p-RPUbO2g2Rc7BzD;?{NM&~+`YZI0-hMI`T6!kCye4_%uP*dqFb zfVaTVl6~mbTI}L6=|iF2Pm2!>-wsZoR*AS!tZb|zW;C41q7Eij_}Dgpplqhih;&P~ z%J4e-#WrOJY1Ct5VK`a_Z4~fcvloOeJvD$ue~{ds$SrjC4R3KcXDyByi`e+2fA{oL z6xn{-6pmC`b9IxY7Im`FXNmb_u{sr(E$sBV*a;U!NaLe!n10q$j|%USM5+`JF+Rx_le<_aY-k97lUq8*$;f8l zVe4aNi_y*-sS%ef^kDq4iKlcLTwSJtE(d$8+RNnihLz;?zT}!NDeP1ol;+&yzrT1L|6acQ5ywT+8n2mu}NE0k&J6e&7TWVVtxL zJbY!_SHV&f;#j_LZ6{kGikO4QzFe8&sBp4CMb3rDc=7$oa#HK=rV0x9fpr%kcGeAT z*(btcgDTK7VPj8~As|o$+Yp=&jNvPn0Xntl0*>A1_)ztFa@;k- zmH1<_L-o<0W1ptYXl-wGv^>G9_x}4Rzcd_sv>^iC{^|Mg)$ZhR!oG>#_hK+Lf@vY4 zKx2)QodW+DhB~D}6p5@p5JlQ2d@BxC=>V9-<7f|!(6uz)D>(5Xl0qAJ##0LuX=M+d z@=EkgirCCL;~xtdUqR0qR8l)-qT)EmLPM$AL~*a4M{zqS1TmYw28+hlpaJ2Fip+g4 zxsU*)MNsC)qEnbduA@sSD{}&LFoPotLywk+F$0h9YdMU{G6cOOtd0CfEc+F2?*?r& zn;-{mmGV!s^hBCfd*<{FodPVCrI2Fe5J6C$jsniCo|%>sAAEogn(%Chzgy7mn$Bl8 z`+9r_w?%K_z^9>g$Y544w@q9HegrkpKECttMR+a)AlT!r;aiFZCJ_^Vnb=rGsWZi@ zuF2ur+3xf6YXFm8bvvdq9u}P0OI`Q=WeUTBodC*h)l2R{Mh7uYgd99;i6V`}DQ&BU z%q>7RC)C{8U>x66vOj5~7e93bUd>P+x#bB`&M|yi@w8_8+-^b%g8pxB%Q0b&> zZI_Z2IU`_A(Mi^3o_3cmpM!awMkRFiHSMh?3K3bB<|xcLngKk}sF0Aut4@Cm+{t*o z=a>wD+mlN~(83sD)TWS;T*Na7KBXYE9c3{FqiTd=2&$pRZgmkJoAg6-fFjhO*Tg^5 z7|>0r=8-jz;lC9H!9s`RFTO+-2ksH_0G%BsG%!whoJ=H5*_R(2(N4#^Mi%E{+Hf;= z|Ao_axC{>>l;dN)<|LT_#?FBx`ctL%MURyQFbSe%NbWsW{^!1_#G_^jWOA0@){m!sEF$Q=@!OfXIO>1}`#L4mK;h?lPgc8tmq%q~q3Y2wLip8opc zD;X(&38zYm(*k<|QF*O(MAsuCisYhH zPQ+E3%D>fPI~cwr7Ws>;2)SDCK+f2rD@H1$sJ+?md>38|vz(fI`vAlBk?(6mkq=J~ zv)m%N*K*RlHzvWFLm#gIS=(3*xe*>pT*Tc}icI_S0M_0m@UsHp-@|v)4#70Hqe~EQ zbVj004Rx$^9w>gy~GQxyucWgRJfnR(^ zl-6AolejYDy$abP>5XeO>v740R$CaE=JL35?nKTAPml{@Ynq~^YMeZN>bY1tkDmjGKa(wC;J?I03kV9qZo3io11o^I+AUQXP@rZEXu?;1ZgJAJk1pd- z9uV4i4n2`M8v-lKEi6}?j>%+Pqt?us{ej-)2p`45}X#T#TGTnVC zk4qv87A?G~e}0!+usOVt*Y5jx*- zb$rpv@f@rPwfGG-A60^UNeG9z?6(acg9L$~0&kgj6aHRHvPb>|N5~epg#y>kO{&k@ z@&mbJRSM_Xa%i$cpGBr~V&p?``mVVnF^Y@Z|CX6bY$ldrg~C*OrM5u3q=cNU%-&i{ zcfh9|5@?={*~$|l5|ra_P|Ti9M$E)W87}Km82`Y30s{PeyW{x@f>AP*T6K6nv1mTo z5z-sLGw6mV^Inh`r|7osVO8uMwJ{r2>MmMNZFShrgzMQB)-p`BU<+KQiYlA-d(FNW z{TvuOoIccH<{eIlWl98@D|Pzb)5rXRvkic5@tjFCDwOKfqv=&QP{6;}32AA{+ycLe zXMPdE7Pg@DpRoBSeQ6!2z`HP!F!*7cpCg%CV9s;*Y}tgDKb!vCSGd?NGgt6c@!Jh zUVh}swYCJ^4K!RxA-%Bz5|7v!7so%sBRn9=v1;%m`zt#Q_p(&;Nnw%B`=G zZrl60w69|~Ua|N z9CT)Lekx;uaI8~zFML}5yTtl%d@mVset$k;Ld}*6XIQJQEvP z{z_e3-hSaC7)nTO$stP{GwcCc4l?q-14OV*hH8ui_M)%c`&UxBw@mMz+}R3lHnqM| zADE@^qNT3$V^*X+@jq?Sv;6*v&;K^+<{O9QPX`cP7|j_jd?XJ@8lYtgOwRQoJ5s=lbRErxflHVv#k5B#IW1>$MzgUNiG#mIvzmoP)+=eB^^mR&Lb97x zT}J&>WRPU0tfz|{Q1LO?W)u!r-fF0ajfa|M>sF{)&C6bvAMblf{<{|ExQvQ-kl}BW zW&|P->f};!&5zbCKYY+7t)Y@yW2dzER_=-eddyZ1H79&25!M}_4+>B@zyq8fz*j!4 z2_iQn)Co!|5xfN2`lPokup2zC%pBQcZfd^66`~I*P)(?tFE83HFTJ}5s4RqbL!S{sXr?ST}vMYg`sRc8Nx) zfkp4pQ0J{rBUEyERoI;Jt!S&+dUR&u0sv67E9Sj#!F0W~+jD^+h1`;S+vp7h?chd3 z+7UpH@ZlFLBSfd<53110KfUK4EG%4tu%;X+&;aBMjr6DlL2_Famkv2U0qSzGkV6xN zU<$geQ93Hr`nz}dqr?vaOVIrd>4T>7$p2mO9CBXm#94n9kfB4xj)YR4fA6Bm93iy` zR#6avCsNJpdVV6s(#OK^NS)2`?%OW0-WtG?9H(kdQPJPY$`D-|xDvf9#w~TP^~Cg1 z-RM)ylFi3X@3t^jRy0dZa_5px;Nqo`l{}M>gNP1#jzX(56|^@O0__|J#vMEd58704 z!~|h*U{fI)AYbj2iZb?~%1zTZTx|MP7l_FQWIn0OoQq*#f3C4lAuwSmv$M?uAMv%e z*$ek43@J9yvMNTroU3J+j!w_(3A?ov>eweUpj|dOsZcbt#NjI55IoBe1?0s%-v~fIl>ftZT$+k*kMu`Eb)qO-q#(9woIhQZ5Ob~?MUqaJ6?}ox7*N5W0q8brWp^qfqizHUp7M9)Z({`C>7d-_HAEwD5qDg z&~=?YDW}k}AQG;A{9Y3~0Ep<2{uNm~$v`qA-+3C$S;WZ-m4`u&W*%1UwOGgSfyO=o zkh3ln@J7QkN_g2yWWc=60EyXWC=*k^T15 z$AYj*FD|bZN&-qIj#uXyf~defABfT>O4%Q7cP5T2Xr@1|`z{bjC4YYf6ZVw7ioOoN z{jg%GNsZ`3#Xu`MM)G^w*(5&AREk%v%c7|Y}~XxTg|reAqM~0E0rggzNNz! zB?^9#4oY?7(%fdQMkb;Zb<6|_wc}2+!^$5WlX7Hp!b{_3WzK*V+KD3u5lho--;Fie zoN`VVS_N`daowl)eaO>10DYo?l+=RVQA|^-Fm5CP0}9L(-_207_ui$xfIQbQ*Q#a#|34jRY=@%Oe&hXqK6M_Q>h#jslz&a!Ph^}G=Z)T z+_`gt_8Vr?35D18`NHAq>RqW31{c6Poiw)R3p_d14hE{XrFu9TwLn@0*q^USt z1J@oiq5fOb!|G4%3He6}shkBGXFkL{T@@9m3 z4GXiu^BU_HS*tCPk?nv}`w;K(h*kMR$0N3%fM2?Z%y{#7=^)J^v=OTHRBtJ@bs>o2 z)_lE@>6y~0g)cXNqrUGjBT%I03c6QwQ?52RX=r-g!EDrft;L8n!PO(}2I7Y04Uhg< zU!|A-{9k&CH?}XQ6w2a!{-;dvx+`LS+K2wpAx zUaE;p0d@B{1)VE;DW}A6?x=q7Y78ZY&%{n3hK+C3kkCn@oUOt)M#^|Aru#JfbTr)x!=iGJap=GL z%*nW=(zCi~LHDUI{XX7BICl2D`tSL18#&v9VtE6cs08{7ueeeW7-nTRLuM~CQ&>*A z-}7}51y!*oqOlbKZ>ku&pPrK*%||AG7SWKyGc@!KOSYV`1TQ0`iOOyZeUPuZU%#lo zS$<@&E-n^vVBP#aH4l~S6r>A@3%Uz9YG9=fgox)~h^`K@x~9&iN<1ljrifxdhEj1n z(9r0+ts(}r1Zd6sKhO(HHm?Kz zX9-RdDnhdFt2`{;61-9I1{k=!DJtrfdeBb*f8XF_AR}BlsP{n4q#>a93{xJUC!U;SK9yZvV4j0G`adSSj=3Q0X=VU-~mZqe*%+%D(H8s8(8AgDd<@*OFfij6D348GRZN-29 zMt0t}fY61+x7Qi5M|r6co-X7zKs13R2iIyD|O^ zv4CV7jKGua_LDmvNqWdc_8g8ZL}lTxBA;uTp4^Q4LwGrf>o4F3;E3oooz0Bs>@h|^Bf@8upa+;KzV4;e8|e z1bE;ygQBydEd?l3&46ty@6QCWyua52!)w^MK!{*qcL44YFszdVd3@L466-o`?N&P@ z2G0pu8ZZl=)QxmxaeecHci1B=|Xe^;h8AP|89 z_@#F`j)&k}J}|8&0}Suc_z$?|LI2e`fOQCCWY9b3#(opkL!uGw_>FGxfQNisQFCyB zuG+82$6voBw74#(=B|t5p2SGPLLg3FSzQ_J7iG?Yq^BP0y|SHck|3M)v`KlBa(9E5 z!^@i&%1ngwVI4HtY^Tk1kBg6u$m}_^pBxd{o`Y)&1v_vn7vOqYM-)X1XGjJ!`*N&k zcScknA!{R>`>~=I7ruxYZw)WG=8O&kWqdgjf34XvUJ6G!J6$x2-9#~SbzCh3rlZV6 zDZ*_*3YY8`YwU=xV`L%t{6ON1o%j?u(N8H+Vwuk>@-lI(yuq686ZS9R$p{EoULXJv zk_2OGmf#>k-m)U2>+AZ2eGM+rns?P0cjYvIjze7XY;YOOK-LrBWg6N~d(4`3X>n!da0JGY?o?O^5^Dz_h^@S|) z3h}WeJ}~C@m^TQN{YQ@#G_}{%L>~v)!E~5!TafyPaGa53v6-ziJg(Q8jKAA$Ga0;c znAmMaPK>7K65A;9FCXX+v=?4%vyHiB?C91yw9b@SD6|L;#3zuO1oY8+pWHaJi%UVW3Qnc zDZ)+5fkhWuFse?_Lp}@BJ|NgIU>t{x?T()ac4SJ1)Q=x*P{OPpp6cP3kZw(hyjz4@ ztJZ^Ey5vI0+g>}e-n7+a5xGE{EUP9 zJ0l`HVf5vNYIP#|a9BqZo~qZe0LzZA-(*T>E2s8xd=MDK@!$)7@O2@R(j`1aB*{+7 z&eQ#8W2~0duPV_mlbcq%*TB$YW85kmY{;oyQh%``OfF{0P!jfzPh{HEYW2c3U{34`FXBtI~A$u_HDznl=*J zz;^i5R~|O-h7Kb*GWzUH7y@jZSb8&Jqn_Eoj$>xT`Zr^zi{M^3K{0U+L=2~g!1kBU zi6mqa8&?rAUyNWSE-}2WZXP>PfBn#*fG7kLCLwbo9IPbv-~{&?Nb~cudr0C8yIlnT zg3-|$iItD#%J27!^4Fr!{C+Ti}LEu-$-bAP%v*97I?kS9<6;hQE;so5{Pf_TYpm zQ})_}BUgx)MQ|MvbY-Lvk&cJhkkH$7SDe67qz?cecOi*Q0n-zErNmt@3lL&OM0c!L z3*w7J0AUO5q}C;@>g2{smVL*E2?c*5MiR$&Z*W)zz=|Ywb+lX#lGqfvS?GSaHsFW# zxOZ4cP*d_{3xg*Jy7KrLF$O)EW9jn5?NVVZzk;{|xr?F~`eq5o7WeUZJRXUT$K&yM zJRV!z0+@|PrP^pT8jUK9Mx)VaG#Zuawts;iBf2m_9*%M6TX?(3+opP=iwi(uh9HLD z4HzHmk6xz z?YJ?9thZjroVWHvn)#4tG&1t{^WEIIsj5|Qd+w3N} z-GPnE3!5>ByxF#bmv%>JB`kbdb-5WCW!6G;i>cwqM%ZaB-A=OOlF@n6fNAhN11s=R zjI?qOW;4Fz0(Sg^juTL}<5%SPEM?CMNgCHw@6G1E+3Xt0-P3R&jRJZ{G-Nbxy#er1 zip0tzl(}ijh5=wH-|Xiz6ITRWGs(!C=CSRNxfhuDyfuqmn1{$^2I~0X4>{k}Bbuan zAK-ak4UQvFI&wztYhps*m8W?#fRpqYz-VYYk**e2rpRCPBesS=g1Qp@QvXCViQvfG z4vlLc<9IJV;E8Nkl4&b|1UmBqh%$Qu7nHq}Dp|VNZNe}1TW>&72Sb08lY+|KjKs_1 zSx+`Mjfudo<*98b-cr99SMVI&SnZ2%?(u?CY zMA1vI^(I8i7C|>MGGgc^YFg+nG+UcY@tQ_z>~^bQ*^T|s|Ap8{HYiCO|LzVhGZa9Cj$SRgY!E z$K%!bF(DauBpKYpLk2H;(0;ec00vE|_G97&e6j)X|e9?aYEFVy$E`?0%Sr+oJ+@!QR(tLHW;6Ah4do$x9&vmo|H2S0y=-ZSsK1dbQg$lD z+)NLTAgeHPl!Sf!I@6o_nE8@)IvMi=X#A3=amg0lp z7=x~pjC{x)VT)M8MdI^7bH`WVg5%5LhgEjk$xg3k)Q?5=S>Ou@d}ZI6mEx7X2W9X1 zt`Mma;X{D%pa2aIo=unlTaOo6hO0mV8-g+R0Q`>QKsi~~R`w;k5&ST>BB4 zDY_zv9@0+oKn2_f_IinyxLy#jJ1&cZ+LnfFjU9Idr7m9yzHgvMNbEJcZXZ`KI8Xfp z%u_4QrrU3g;Q+C6Zo;L(NBs0OWLz)z3G@ZM2p2ClKwJVcOxBZd6>iNJBJwVW{WB(5 zc(uJZrRgzX*fZQ3bPfw#*l|GIF^mu+fWAm7Kjell%>dUDt_k|zGvjvn*1aeyH)n2Y zS|FpNBvFj4kQS^yxSI=2*hD_G4ro=R*^Ty@Zj1--Xd88iypC|u?Ox zLC7qU2g&Ht`kdVi5-w4n>$!he@Q;I#2_&Nn-Zy=43G6$I@n4L`v5zPxgZY9?Ty%#o z9piw-IRHhL85Agxdr6j1@TIS^Oq-1veUx3Guj3h!+XSIo>TP-$buDXp)L)uy%s2Iq z?jH3S9mLx4;1ljp-QA#n9UU>)PbrMsd}$sy_Qx!^7r=o>#t-fITGvSsYY6>>3+cqz z)r*_H^i5hU#}#EC`W6$&8WCp#GS1>|o#nX0JUB4GaTtDI;stMjmuI~yF8VB9GNa2h zz_kQ3vg4^+;`b$8Ro60w9=uEjI^^$T5k9)Df-wkFA$^7i=^hm{!WT3c4{8OmLC~;N z!vB6hyCp6B4ZWYZwWKU^6Zw+m322v60otA@OuU4PmsWP1$*vUYv&8q$O6sjcFKn_g z2eZIC@ZOI!zk7vD#;uuBQTq)S<-+lXW+K-#P0L~BjYv!F-Oz=sF0E%$=h(1?%&Z?l zzl~rK9;LZ=OD4GqBQwFnt?A)q60XJrN1cSp7Z!8Y3d&5p?N zes)BT!^V9PJHW)a6*uH_+xhI z{us3&XJp2Hd=S;-r;-^D<6n?5YGZ8w>+a5jF26M+&{pWd(t|7q-&51I^}rzsLn4QS zu5E^uo+>rZ0SbH%@QeB_65j5;fuKN zG+%m9%(O&hSwL4_^IGL@J4PV%qz)oJI3v$THhwM^BE&}%4;vpsY~qU0;beHGDM8cI z)E?Z(fJMtU^1E>G?eM-KnQjRwoW12d04`+UcWf#cp-fB#=n}mJ7-+>~P>Ou5n6p6_ zp=VIy6(500l5-3WX{6?v=Yt{G{K408?1xvPE|Qn%PhfDs%W~=I!ZL&jW)lv21AFa* zrtalX^7yFh4mZ+>YNOA#9s8{S|IhZnwjk=JZurG903eRXIE5_PPsSg;c#j$II&2~z zd5p(EXaSz!2<2w1C;;Bd5bl>zqy~D~l|hbRc3kNN#?27#6nC4Z$O^lS3?lYo2pJCt zKD-=Y!{;*_KKYG#k=5C2+S4NES==zffH56mo&&r-Ui4G;C_|j=G{4tO&bg+W$5NL? z4IjW0OG`^Ef_1=SZXa(-GyulhB|`tQqU10nzc9QTaC=>b;)W3}a0`cr@5GW1qb@bC z%ZlqLnFls3Oh}XuSxA_VVf+?59Bg zp`SrVf`5{B@C||IP0Bm&kSFSpJ;3qs)H*swvM!Dru#V1_i{jDIEtTbW9tRiziOT=- zBL-5WpqDWd3WoJr(u*<|%51dI&c*CecCYO`BAXsAv%MxYWjh_mbAR!VM-F?CvlAcQ z>$cPJvMVpHb#$s=nrEv+&iQc}Z5AN$(Y`xTIQ}+-_elRFh1GH9f*+f@2qqG5Jy!|| zhKXukJQ0Z8%}XyrE8>Y3T?fVr+UEuMC)T5&Ycpf184Sd0Q&_1Y+ps(_Dk*vleTWi3 zJ>J*orF;xFrrqg{NS_>-=Qc)ti>!_Uc`Y^L12_w!K&FeXA_(~*^%a~T1tDwPDMQqT z2vGoYW9bcr53uQTuoOe|9JFy4E(~!=vWpT+f^s{R0=b#nCCS4!2#%ECl&tJ?Xv8|R zz4upOeg^c8;@<>CR4}7?fDgmjF4!U0NYP#ZtGVL}3Uly)Wk>;OFBpYs9yOUHc}<60 zq}#C;my=&lfoud1k74m{sTuNpfKk}hpcC^ZH;2I84qgu2oDev=H!^ZsB5t!>cW!KM z4u>u%oPA+E&Y0fUO=spA`VfsrBV>KYN}9d{nz$W0a5pnv2_8ED4DWJ$~#*X`(RfAoSWPoLH`98Vs1xF&IgA+hs;pS z7(0U^_uUv4@Av(HM|(DH&2v%)3S!1%W@`|7MhTTqBK+ zMxxJ9Rt1}Fd!4+t=T4mj9A06#Ry00SQvSP%fTpI46x zx_E#Au#@fI9Xh;S3?|50esm5D^%jmBJUNEC{~>MEm_Un11_rlZz0JZxmi=fw=c!_- z7r-!GJD0n~ZoMZWc4HwCyR)`^QS43<2Nt`v93Xa25GE>i*C2|$-H^kf zLG0e*sXgH8f#h(rq99HIZk<`T1@9OrI>2_geZ}l`BLH9oI0%m`U3ecVfa@{m_2w1; zGQ9<1O1Pk(`iS#@K_8X@9Z&=Q$J+t~;Fh-moRWjN79GfWFn|pN$l^i&1PHPKwE@DE z9pG(*58~VqaDW8#Rs{%y$bCUrU;%I*7$D|{z(oYP5$2{o31sSY@OI`kp168g^{F#~ zh=TF$?w9~yK%l=h>O(+cYqx_pyIB_9R)OCLlGR2IC}PEhSaq! zUFaZ!BWtcg4gb@<@>m5AP&ulR_vj6e zIO>hYp$2-r#Q||VIv<3p6C=M_A)+6F50h|-LvG!~*@@?n0=|Qew8J-Z86FN%@*kfVU_qzNQz9;OF z@bMZ@01-`1*~q&;i~}BDA;Ae#Q~0{K>9us>+uZnGnij;*5D*IsPVobR;SNK355DAa z=Q%3@Qc?~4NZ?ki(F1j_TTw)i*em|A-EKqR8{lPeyxMkM;Ejzih2W)3V)2n^LNy+? z7)^@?9~j7Wyo!3RPtyf21xDOw?hyDUL`_J+;M5e;YFFmnd6xb`_$45rZlxWEQeGAg zv%nwN9+`k`dk*IB8}@#m`Fy-|((~W6=x1NljNo}mvXWlH^(>E2wvgdWbR{Fcj99`k zbwnfc-cab@hUTIdhI?=AI9$(`8+ml1Zz1xXwKx+iiIi}}XnYHC&D?_3b|l`hu$?Qb zwYaxFA6EwJN8nghuC=VPX&@ z(3B;CF{wb-f%b>QZCttxI-kL61IEL^=w6hBzxa*-xZSL3K!DqzgWz%7W?|{MHY)-4 zYQ3t`h=6KUHI+u8RL?DUdu;T|vCZe?K0L}5Hh7d^9@+p%Q(jYF|2t0o%D_{3Jl>{^ zYGdA!Hwt!T72@pGQupGe=jS@vQie4<#i+;A~8?nu{UWV^`;a5 zlDq_!LEn`G4_5G4{`SHicTAY@0dDHjLabBo`?NYWMHcgju>^^jIQj)P{_$hG5iJyH zJB^C5J#9~J)52ss+K#lv;tk(jWmz1;H)h-*j*Tz!Y*-UdK-wKK>bf!Nx{DX6dO{5| zyJ9dVxICrfgMqsZJpf>g2qxU_^^Erg1J^A+R}io=xW)cxtEMR{FDYTEDR9kn1ug?( z1P}x0${OMaNJ+^t50>KW;f0P1j`Mxhb0BOd?0o)+1rsa|c~2oKr+QemP3`rN3$g4d z1=rZAIhZBQw*v`RgPH$%+C2*@*=?{>J+TYMaU4g-XBx+cXptvyBz#ETEvJ0BumO)U+Z82GNcQ^-5i;Mg!kfh8Ki7zhOf-eCAAEo*6S` z%HZMM-PzgI)zQ(BAv0!-7%_8ma&mETaBy#LZf;@1^gS3bJm1#VLJMEMc=5sl3thT! z;j(4RU2scKgrd@NyIbzM4f1yMXx zEUON9Tp>@k0u>}YJ=4<(^76+0W2^Tn5)i3T)9U>xBdq)Fh)neqN4>0X)V5AbKtxp` zEk3_f!Ma?hC)V3`kP@cc!?=cU1%+K|F1wNlBCCen&cP#fHBvd1f@a^rJ&H{Pig**@!LU=XJt}Heh}l~{LSbeuH=~4ld|`=+Z%~x&5Mm*C!^VkvYKdIzp?m(*?q+Y zX#>Lcql%Z>7maId3x@r&3Ni&m>Ic*7{vyA}EfG7knx}+PLFVt?;3Msham2PE+gwGc z78HQ|4bs%iAB_|nn1&ry>ej#4Qp$i~y@N^JF@(wKH>v1rHM@P$y9T z5>Vnr8FD88+`;TbCLTVOmE?p*P2?ic^9UEEY#18hMKC4mfG>7I_(dsWki!^@msw`@MG5wvt2^CcgB@O9A(?2w% z{X_Y&SxmB(P{-qO`j5x#KWhImCn^FFO+V4q)%Fu*KT-aRbS!i}8ZrM7|H$YcA^oEy zb2$GaX|9!YB%N_1eY&=ll1Y2{>DvVpldg?INww2YT1vu`NlZ;oNidR#LeQo@y%S}ZN$PfN_8q@>c_q?JnlR;ux+nzo;Cr>NUj;x2Hf7Ilrg zXdzW6C7YBkTr^!gxrjkCmoy9~yGb+Q%q1n1l5)w^)RbH%Jtb|tu$xL4QB29NbbxNw z_7b0$cnhW`C#G#Lm&+v-oz#RkoopD)CcR|hOi@itE|{R2QsBSowrdg9{4rv0SkR5N|3rzEWe#Y8Wib`po-ge#q*ob0A1zWh#3PEIYU zizOz`q@7PpxD(S^GvQH8P)WG5sdQ>Co0yn1v&n2S)isJH6cY-Xi9X|?J_MNX+M0oAI{MMXtcX#~*h)tOVDGnO+Nje<(4SnPFHa-yrI z(kk|f8kJhBoHo;W+tFyWT8&;sqtR%z${LMEqtR$Is?|QRQK_^lg<7RnD%F+sd4)UY z>^!|*p-(LKnbpj%R#Yt&E8Emsp{Us>=TxV1!1=VQ=G0t?$@-P5s7)=kngW_jQ+%iM zs*Pe%nNqCQRTOBReWWusnleuDRO7o{QThA$+PtE7k(Ge1g zdCr=(&S})iY;s1`e@enRRg(Bqssm4dI*nSgot#Og7)>V(Cl2FRQK!KQ#j8{G_T%x+-Zv zQJ|1kJ(vPVMX07sBs~VMJw^FMXsXn%0_zckG;ZPtyfMO&?nUtTBS;}DN-1PQdCo<_<{at<<={fO7+}sp;;!@>SvmLX4NU6 zS#64_m6~PMsi@TyD6X*DEY+7l`jj%wK37j^K4+m&r7}vxh(42|&}Y@p6*Xr@p;kM} z#H~%yr0dj*!+188s+_b{)OkiUdySH26%|=&pH-!zq6dEVI-Rk4^%+6bDy=3-v8Xxq zikf9sU6q_y)~nS{POY{U6H3iWtRJh;*((;cYBmZvg^t_#YW>>m zRZCT6r6yhTtOVMm`AV8=we(#3wOH3Hs8!GA(QK6}g=VkXth@+)MnKi{bEq`GX0g^E z{Yr}BnU((B358V^RciI6)+_ev3Z1L0)GL<8Q<|mvxmCYjtIa4ioBTOe&t~yw?#!i4 zs;4uWed<-t=N9U8{ycldI-^gjqM~T7eL}NTxsJ6`e=cQJrP8(1s=OMdYV)t>RsBlG zdSpDZJx%A2^r)Hl&OPgasX=tBSPpqD2saQ2WOQBD! zc8*f3Pb@2SF0x*!`IH*HUPYtNx%z}swOUr#d5%7>)grBydd;;+NAtWTp4bvmND)s+ z5m7{?SXrr7N*r3Vu2vdW-REzKQp9O18qgs@H?^9a^Qlw` zb{oybzp`EIo_kN@9AglhKqrvP`C5kta!M#b0*5C71~@FRVMK72MIf+qFX4@3(IHon zhE`ys4^BaXacccy!>2EC-5T)1r6b`I7)f|7sKiH}`vOCrc6pMgWT52fn79iPc`nQh zc@E4Lo;fV<79~&HfE3}Pfp~17UXtBV_}Rv7DP!~_5*z_eJl66}Y^%Fk&>V?NbzPqksVVm-@RG0KoHSm%_2t;0C(-wxiemgCCdZ#N2{|rbOkjU4tFAGxrgi& zA679mbf_!z7gAq+}uPUhx5?KF?w;&Z4Y-*9KFB+5#W{XcCd!Q8VQVp*(2>@7!DwG|SZWilrw^ zkihLNxM?f%-0b>@Y5sC@y@%+_^b7^cOp*PPAHk4|JjZ`@5TJ-#81aw-T{pEH;pXq< zhC_niLTx(c={dp#LcdXV_A-E}RvmzDhz%r+LlKV^ZGp}J&uQT}d))Y~ndyvA+^vGC zd?~7=ixDURVHo-fcSBoCs9{OzOYQvrPUZjx0kFLiZWGWn#u0tC&RM@+`JZb;9`ZC@n3#%7ZZh;4fcWHpTt2W!G(oL5|f=*2i<`iG;a&PUY_mb?nQqU zO46sC_>;h(sL)s*x!IW<@(gCm*{n!5b#Hsp_kOVR{iq^IcF}8TN|cG@f11G#o-8qU zjUlB%y6jagnz2hhT+wVx6;6qs1=glmH_)bIdWcR0k0|l{=-?tBNwzK|ogWb_gy1qs z*jC4DWkliV@$4I_o-6JgpUc4$yCMglkY`(|HJ~Sa#i#y&V^@#&|coYWR z#2SCeNjy7)WO}WN%IVc29Y4`=^#33RnFOu!uq_Y7SM|!bCI-0=z{B@~Y?qD@@*}=9 zr~U^NU|J7Y-AD8{p*2O-H<5 ztgg4hk$n#o`{^(PXjO5fX#)GcHTdyUTdyOC4kdGOPBPx$;)A7 z{?3Cgu)(NLH3heDsc=8>G019`lQM?Z64DWRD;3)cPti`4!K4I7*KDw2gj_SVherr8 zi#P>PK)s=Mdt^J_gSR#Ta9IFOXcNYrQCunoBMr=Ws3vo^2mXlKiV4n_Nt-UB8wx#_ z2<{6Kpv>@iM_C&?dNr=c@CM&H(_gp_ZbbL+03SemVAp~~t3bk=P*@E0c-pAvV?QE< zr*-21GJLS(Wu^)tvaMo-WAdZt>INbnO0D6e5jgmr5#?xu&E)h}-~(8SS9V%Yl2nr8 zu3j66yy(c(VcVsGb-uTNO3DEl10Yim)Qtk`CV?12wsJ+x+~E|~aS#|CNoNS}(QfKZ z#>1fYEa}?+P1>gXJ@imXAcEdm>R>vID{q zM~E))qN_W0E_GjRN~sG?lq|IpOWGtBdNjBK(#P=y;loPZ>Ta37xW{&Rf9aEb4omzm9Rbyg1=Ike@ng_$UOZVBxPYLpzUYy*?H1@K7$jH z8FzU1D7J8HpyD8F?i~hDC~^$3@@aR7B@7ZpQWln(taepmh84Xl$4a)O61axJYOReW zfJhSaN^W?B3j5U18zb#oM7NeHE)w-oLarwVZgD#ikIwZlynDklPDwr`#Wsv{gR+)T z%-&nC|Fdq{N271Aj7%4ju8DFMN<9~`Ay+pOBidEHuk2qlwv7kW}?ie?) znQGFAKiyGBE-=3Rb5dE*l5p4NpnWNMzC*qRgdET>ni|$9c#$#N9^G!WK+-@S6Rb08 zsiIAMK@a}u^F7Ej&03i{aGyjM@HrZ70dfe)sp@c^9P#yI65^T%@t&~q?i>y1C*4e47mY*|QlJOKb$kuwQVsjcc~hYCb+q*VZez(WA1g09 zDP;#YzgFp~nrfxRU2wgq&y}OLXwQ=+Hg3B9Rq02zeI_Q`7?)EHu`;Fu_>N|iU=sbu zmfGzUFDR^sHVUtw16Vp`DLtZZ6WCScajX}u4~T#h8zg44_g3_G1Q3y<+8T zzHt^!^lg=)^Kdz84vuFG1>fGW+fD=NNdL*3N;~4~Wa12@n2a5=$ASXasj6t{;*KuUu3A?d)qSGS>(_Kg<%vpM9JDG z+a0563**F(z~Vl0#TIn%cwO$(wU)&y%is_LM$bz9(FI@d;#zs|1r#-6#4a|pIkG7c zDZJ4S+6?Ng+ZNRZUw+Sa5*F-_^X<%TIv8^MuVDgC z3DEpCSdtG_)~>!Yq1cY zllZbsbfy6l*3p=PoS)LWW?D;H>M&1Mv51EQa70Y2ZnoMPrl|aC0FF}oAz`LL-K;m{ z29k0eAkKLdSLGMCBA&g+NYc`WUT=XF9fxP#cBz7?rnZMBIXKgh?5HpV5*<@9*}-N$ zaN-}dRO>&oovj>Z8-FmHpG*pqobbcHvv91{+rMd^Q81>^xY7dAKpX&2rwz+wG|0zL zbZ_dWg4Q;;i~0yU#T+a0xF18zPLmk^Qtp(e+kWKYp&@_(7%OF{`G%W(TVhJQgmDu_;WV8sD#~Y((pJ-(8m6AO|?ja~)sLJi# z^jb#M-dDLyW;TibL6zjlFrhaWeE%pAB$dLiI!IB4^os82((?T)lbsO4XQb;6(W+N^ z%@RY=XabbePU9jQK2}k<5)edGtml7`%HN&_6=B1y+G~>Y2yOvYBqN6J--w>##gM-B z#^6SR;@AHsmJoJm*gk-%;~(aAm59p;72(a|UGtb#QH?aKS66d*A_|{es-1PAMiEux z@RJfB*9kZ%a2ZNa|F4&@>ohjBj0@{^Us9GrCxK%bB_tO9Xd?QJ$pTJkf$PRbi)MN3 zakHsOjyx^S=qZR%M`+_yx>5^Y=!M5YUm=L2kVBaP&Oln9cgd3A(zcK{;GlE|;48*$;=T$XX zz(ZFFvBKRPPJ}Cx+~(9rG0HM5YbjPdz8aB4q{sPEUK!|UhHm!z+JNCW(idORQVPhN zvWJVhF(tyeFF)@vQb}QNEdgoT`4!~uITD5Z`Qej0_GVX%pr~##8`%t3&vJ}2VUDZ% z>@L1aZ5klrExZEC`ZD2OAaIZPkaLuUYx>+osd457Iw{BPuUG{-?1=O-Y{}~6A0qoh zp~Gt7HoijGFlkd4)aIa|b!ehn=;ci61sI`aMHrB{ zTb#(kn~W6|8T&chY!daVdTUkrBA7CNRAdOs;~qsqN{&of5wERyQ_d?_-TOFXIMeVnCgk;vgt zLHw76=2)?>9B+p~wS9KsuUp|2lO6uD3FAqu&~=`P`RjzcYEt&sbC=PraL+Dk$TCdp zFC00MSpVq$EPu99se|aI826bFs>dmf%r@_1%4ILkutl6B$FEpUWHc6;H~kbS51{kA zR0@~UaXzPk&hBTq`|_xTp(^dgsDM;mUB(aPv91&pK&MYm;WD%hSmO({VrqUU8v#mG z5fKl)ES-CTj!a^#ejExwEK@!~l|FumLiEOQy6kp-#$BCpOHBtQ>k?|>JY$mR?GX~f z1b+ZBAobEWHYp694@*pPe|YI?zL~dV6B7XQvhD8fZQT%MT*O1Lw9ko?V}PF*ug)At zhDx1TVba=F7o}+YhX@~t~naQu953ooISvdTDbTl&cg#u5yS}YR|(Rv(jQm;k^ zKl?__*o~RDy9S4~6>Is^Oyw9tbnIzD^co8Jr~41^K(d7%bNhA>=Hi(b2MUfZ)j z0L#e&Yy?c6sH%s(zU%;cw>VgOuxH*W1xw(b;W8>P4aa;sptj^UefypUVM!nfM+EPW zz>bw}lBU*U$)J-+*o04#pzuqZ>^Y4ud&vKn*S_P(H zGSla60OOiI9LF=x#aV9#pnB7j z*vq&XZV8d`6mKz_EyKy_P02Bl)B{~gM_ndUPYI?8`%7E^p^)pRzswVo(8A*N7Kd`lf!HBDTG4X+2$NKRJ%l!=HkDiW*oKNgo*TB!lWNJn&00N$|_( zPQN&i-r+*GQfxRko(807

1IYj8Q5L8!tku`NI`1e352>>ykpQ>ik@DrEJux2!_R zjxO`_6-wy5MY1yd*)eNAzh=fW-tBv}m9M{+w>U_yw&%K%UYF_cD_s0xq(jfL6Q4z< zWXa9V9s)inOAUy3xE z4o(JU2dC}>zteG`Am}X1AUaV|A%E%PdE+4eNI$##!KkheNZx!8O}(@os1hb<#vWK+ zYHulHdh}U)&Ayhi!3m67fcZAX5B_DOh zTyi@!BXwry%m|iIXEq^9-T8%VQyjC~V7XzD_6OxQ*lo_|Iztwi&u%WUt~&_jDj_)2 zQU;FG8Sgm3Ik5IRoy8Y*Iy1Sp0m#fG(4;CeANnv*8CU>^!J;~-U-#;bvqZF052W|$qPOrBC zwqX9ayR$lD_QQR*k?IVoHldjURkDqynTvIKRhRKy9r+6XAk3YAtv3Z?^mS&w|+!ehO~S|Df1*v%n}7upian!iA+xulW2N z=Pi%^7aeoU5`-%+8bAt(OnF?q9Nn58SRJH{_XtB`(ndB> zcXN)%GT*Y02QViL-xARd%wjPAiW*6fVaU;szH1@R2}A!lsQ?gpCg z;fd3OE#bup@=>)rxhxjOhs2s?r~huGE`pf+D80!P#;QkXCdMBI-X1yN_Vc7{`jA-A zfpDq(;mFO9fb9yzSK=*r<2mo5;NkBJoK&1qNm*l6)6d7zj=!GqV@o0^bbrpA4}`&@MHJAWDF=UgcWB7~xf$p|u>`^b zzxy`GvA){)C)C$F;+FH^0B4F>LzlRy%NM|*mV1C=G1VrNLaDHb=5X%+Isyl6p zZrUC6e~_G$4#EYF$ryRy<5G8F&?_GaSN|2MV9uJoDqZ(EH*4ncT|~46jV7V)r!6fO zUGb&12`XG#yZkQPwKEy6B2Z@$DjO#b84(Pt+VEgRRC{DJyiGNX+e&y{zJKS}; z>jFy}`?#IC_=-Y%Z(4lOpLFtCo+IHyMG3*+Ut1O1-eFCllC_7DqKBumr&R-hhX(-J zO?d_ix|l6Bdf0>)$1w%ss~wA`zZOB!txqz2Zh@Ht)c6JE-KoMB_AIfjZmCRdO>H~5 z<+?i>iWc&^XPBi4$}hsG@BtkijN=Qv1_(ym&^f%=HPGKv3~~0iI$#~DuQUC{09?vn zm{q^_N$iPxoC-52btFj(>qdp-A*vv=c@PdoIdse)HX`thS(PMRdhgTd*`b;Kg#)0p zFeb1Xp`IZO976c8!h{ndbcpan1z4|;|1*5U37t7uqQis_?3ELiAn=!dg3Gf4Z=rh^}%5WX3a!(fl1^K|nrg>8M?F+<_o!X^$w|!x??puQsCzb`xzB=~i%YEd=@K1g#b6 zX$x58eG3`Z zd?G35dvK$YHv@m&0S;m)A@9ey5V6)~!uBNB$C!o90`TFi`9O3t5{8shqs6RK(1+`) zmY>-h?se2;>5)4Trk8R+z~U!_9M~t%L>ahUNg-gcb81s! zl^&Px*sOP?jb-Rny))*nqAM7^pKpWc_-t1d{S&Oa+4ep^RhY)$MFo~NZjqbJ7mhrS zP#{&Oxs!h4nU;L1L$nwMNNSydVTf=mHPes$agB>$X==77e41$mQNQO z%<9rrgD(7W)Ii1l29h)`HK`iSK7}PMV&+-d7*$Pr{tMj_;qnfjlPqdEYNrCQLqND= zSIO*GPpYIMisHlp^sB>I^fur6K-0j~HQvkeE?_8cmTAZv{om!{OrXMpMH|;!Tm|Ty zO}S7XgdC4_0N=F2TVNL%R6U@sw$+shqPZ_npPYNa_>zF-0gZ6~*f?OcP*6KCXXTD* zOww>aj}{}U>jUH@Nsi4ehxf2Os)MGxRV!^V@>NaGW-0E#M0bSm4xFFp&L{CS0^VVn z@3X4)+t2cV;T`tD9jj{}>c|#eWg(LQiG;U%B!`71eR*@qiHnUPx*kas7 zG*_9m#>T%cP1NN1{*c5Qv%+t`;{a!o1ie|pT8{i!iyhH;yErXUw$QFSrM=HeX-TmB zl~J}_9vhvj_LX-o@&cnNbI}p2ewgM1gdkZ9ZFnuN(DQOgV}uaeIm(z@80J@l>j`c7 zw25BTzoNtA)`ij34y@*eP?mFZg>b4DG1?7MvMXie3rymo;D_$TcJSQDP&>78vUYi# zF5X_qW)Nx8orN<1u*1#B39rTdl0l zwy_u%8qN7|Qk@WjA$8`9#7Adr#zytk|36cTDOvB3`Bgikx(m6oGX0-Imgfqo#ImV0 zD(yj`cNIfg`=JXHH{P4rKx%nj@S4eLRdqgz6UxVa`bgk67Vq>(0}$UzE?WylB+D) z7^E8N2}Uo3o9amb8si>NjjGN^@Q~(_1-|m?`S&9!g=pTd^sKeFWU$ zT)5wzdn_u=5@!)WKD`T~=d{d?MCLTkqJ#j81_Ukg1~NcP3+&DiFLI!Wm~zKpS3U{N zsibH58M+$kpMXD$Xq|Y^gFSLaRA;u;u(gC>u z1Z3V!a)*rI+tyYWLw~+L`Eh+wQ8cP8;V!<{ zRx(92$bY!e40XMMTQuk9$TP(}tj}dNQWMqFhLqErCsj$_YO5gX_lMy^%9RtIJ0AM3 zKQvWY<@{hLWxEm);ZMNt$gZ*}@Y;bEE3mNl89q<}wq9{3)wNC6gB%ElmXL`l<|~!p zf?1K*xe?icSKF_?JCKLfrx+Uw=WaYS8TUc@nWITclg|&yIbK0z_$;`OK_TdTbJI`z z?~t6_)vPMN{T%+)c&pg7u87gAlYfN>CE_770E~b1cx@`yW;F`s&u47!!~I351WKd2*s#a2C6;; ztN{zi1@5DuDad{%=~Se}LNtxYS8EGlz3^xW-{dJaoj|Arrt)KnJlFbMwXdbZ2sUl; z^~sU6bmqm2gd&jkRY;Zg%NY8uC0YgxX~Bp}8CPz6)|4~qBUtyTK$5HMhx05z?@0CF zZqOsB0m=s)Zsty`;{6?M93b#YsP3HMM!bIvmd0ZX8Ora?vR6kddL+qB+s~ z`wudy{s)V_sJKsIJfejOFLtgBV<{A!Bi}D|^*!IFD-&DL<#}F9vEq^8EH7WmENYgR zOiL6PMDlpu{o;<@kY#vRuP(HNPK9zLEW8VW&cePLk}1vwXu@e)eZUEpn2tN<)KHO{ zVXo3hJL1poCrc5>cS#J3pA71vi2{{kN~X{?&dM}ISHs7dMcXlQGN`ENO8wdtD1{#$ zZiLf>TPXWOT>otN05wPkG}a~;Ia%O#*HSyo>4>7XUub3yxv z9YJZ25b%Y22TQ}z+kWs@dxvf4LM+lY$QZ-N;>X?RYl#G)1lHLofpfHUIS2S^C<(!s zr6w)VGh)PpJ{6>d9Z+Fa39-0h8Dg!*ngRqt8r2I2@+6ik-F<0x^_R+~@+!8w2hBqN z(C;;SU~O-ok1UkCg8sY{$mxXq3(qg*w0?Uw5c*a-HL4cfnoCuPq7CkfYxllp1B2V} zPebCaAPU(lS6R?>Cb%XH?n=*(T7ITz>rPq+B4hMLPXpQypK@1_%RIux-?k}0bmtrY z&;~&q*(ruNosTcSm%m3g*mF4()SHFEVboxWtKBFpnpsUT4Yp}CsPGbLu+!sRo1bBH zM5n&gJ9P$ol^$_S&9n4FROI!Vt_TuiCFA8rOp42Gax3IO4h-h}2$}&JEBoHivAl({8-$4m(PQ~5;K?lr-M}OT0=dxYj`q)Ia+ZR& zlpvL7z1zzlW*6g{TDsYqY92{QY~oB2f=^zznkJEKyUl4?{4 z*cte#hxdCU2fV-!9Tg+lRkyWb_gUbdnN7UGETMzJVh*d(7ZS@H)9Mjq_fWRtz3^wJ zkha}MH-`;8_L-xo82M4SYT!?ukLPkmQRJAns20b<+89NNEmImW#VL|X0J;6H8B-L+ z$B-lBx)N(@bU6ukP!y%w=T?%@%F;`p+eJh zRF8+Sy>vcRrpf*m9FTrFhXzdb<=Vi)`fV6BKG2Z*%qQc9RenIAW>rMZ;a_F;oq(Q} z!IT7*;Q5FJeK@-W$MzF1(c6SZAW(UW!`@HOrbT_;k?F|;b~CrkJX0K(DPH^_-8t??O=b^2@8NV86g+a7AV9cfMkHz0E^s8;E@fQsQ$5P zN}G6;DF^~}bS+yMha$KORE-zP%GQsiJld>5t$yrZ_%-1TQ#|%`)w!pSp&y_*&c=8q zMnBIiB}(m65jR5csdN;@xA{Hwpl4)C6BCE{5pJ}RUAuU^xDy-{Z7XX8|y@|UqXk|URBjXQ4AmSbE2&%{$R0N!!@Lxis*omAX3M5?255ai45VMNqP@Dcr6bu>A(ZqQ$!7qt`;x27L zi^)N?212iZ*%D#T%A%go5Uym$f@k3C=6y|V3&v#BGp9{SoimokQ8|p9ib%5FNwOB$zDbrrU1s>Yga%$pSJ=w88q|U z=LqFltkFOxZfVWT$g=31B0802{*#`l@wg}bz4Qi71*t(W_cBY@j+SScHcO%l*9Z)L zY%Ev_g;o|Yryj;t1{21GDS@|6`M|eA+YW!^f zRYcZn4h8hzz|s0`s~(sWoyrN^rf0vUFCem}q^uS_&F8qemcaX;S8?r7Z0|~ur_~hF-RYX5Q}Od zw18{ArOwtne3oYEZaGhLhF#DVZu5@oTA^uVn*fp=pE@`D%M^-i7in#0iPG;IEk?Q| znYL=-A3G30gm#U{Qn)5`HSnK!3pVtxoCeFr{Q zaV8w0iC{ghDlsb}MgbL%SWR5O6+DOW-6`$7Nm9D}V^ptVJs%^rpJ2BtPIb|7I!fz@ z=n9Hr4Oo3xDV69^&h_UL`lt}`=@PS%$3i4!k$V4h8>EJA{?64Onw3tg zK0t`3p%Qa+ZQ}cZnzSx+7>s9fbifAi!A7ihi?muaq38=L7WPHGaNEn)0@PFKo9GuIru%0ma9t3M3-yU`{k~Z zGaV!wv`Ol7tl`5XS_0?@2%wS}0j{JetMoy>Cv^wW53CVCy?W>{lg~974hH z3_VmC*fM7BmYqU@DCoS4Al`g=+BNnksAp0)Tqm8kOPDPAa8m}%wnuKUc;@NG86KB6 zSrOk`0{1yS4WCo}XPz3_J;}Xk+yh!hVKJKD-OT1Ttqbz#`SQVqzbt$VZy>Q%JZ_pB zygdVdF|T}k!4Y8vtdzcm92;=N>#<`1aq@{#6jCc{E_TEvQ9j9P-24hn9jJ>Q6Dp;> zue+F6l=&Vfi;*2Ix=IBG%5{{oP~TQ}mY*eM+G0j1^(H7`Nb}~fr+OEu*cGNOy@W-Q zuE++I8v&(+XlR4g*B*ZA5>uf)+akT50a8U>e0V%uVSKcpp4B9Y*K6xzbm&wQD8L`6 z^=CM*)7MXty*~dZ;$b`y{h(0OclK5@s%{#9omM)Rw9;VK}5<%txo<_g{VgLuCh}Y}7qZf%jAr0$|!X zvEc#Lbng?Fj1Eg0BEC=OS2)li*B|U&=@dl-ak>Q2_Jt4wD|Z(IhXQ*VeZ7^v-W z!kVWralVDD9OYNAa5I>fp=O$rO;C1XGjB%;2j-%rcN5YGm>$zX%3+O}(hngU-YJdYc*MvYMu#C_@qk-6np_`K@0wQvdJvC9Og{_aGr=15{38jIZ?-?anm!_~1Xs%q zn3d3~rVT>%0f!moSrI~dEg&2ptyUv&u*Si=;Y-I?!b=`TTtXp{b~33o=5qH*%_lx#bMn$(mN+i^$;+ z?Lp)7qKQh|Kjyh2g+z+ZW==gvj9iFL`>xC5>Q9Ra1~JBnRDI;(7DGvgfSDP1_rQd> z!$+J>6*^>;>in8HYzFgL6);dktB7Vr(CeDzWHzcvusC77HLOVS!c^*_nrZqcygt^6X0NXtI9P z5O~C(!jXK-o@d{pRrG1o>wpC)mikj3Hc+t>``*w$D>3?fws?4z5^?30$3oTdL$Wws zdQP{kn9B;o@0?pSmmFN`-_FNJ*MOx7h&;Y|zkHw&RC+_uqZH{jjKNH3!&H~rH6v+^ z&5jUgyxE-#^PC!(9nh9@2z$k-l<@r}z@O#6x1|`&^Q)th1#dP2y0M@Si_Vcmy*_(+vHjf5OCuVFnO8AW@TLg_a9BRSd6O#{j=N&8q zM$@=s1)Kng1wCQ2*jH#(QhY*_1CxfsVHv(px)F^G_-Lze7)a#f#F0Sg&6IS(n7m8W z)x5v7{}Irm2StpN##yX?=hk#X+#SJBY*+&{KZ~*~4N!KVw-8e33ycQN`#fG6CIh&j zlxGADM<=oYRJ&LZxwlYqaY-ey5e)dC14RNjg!mQlMi_r7^>q|?3+kWqHfKY5Msm$Q zoP=HP!}$iV(uUDl{~X!4@yr(IeVC5$^HcLiZ;TA-(*0cT zj2k@Fm!j)UBIxo`PgTviUPF#gJHtElqa#My`H&R-Z-Ptc;;NBWH||;eyYm3R2azrU z#H%OKjPVb!UpXkootJf_HH$97UlY{NwITE5B*&@Xn=3J8ku_~iaj$23oHGI>M&r;o zwF=uT#dMJU)Ihf?S8>{8s zO5P?gRp8hxq*O|>$y;H%lNA z2zKN$aZ&61KfE3s64-#VBi4GQq5)utr-GNGIUe&vfjV{R*)?I=0bAGm>2YR zwhwt#rr#ObmHR;$g|{_sy#=c!Zg0LF*z2_!lw-IdEU*VblXszQF_-Q-wRt!|B=}?o z2XC+mVa(}~Pr^FJJ%7BwpWS$O1OB|iAr5S9#l>{0(}82Nq(SY)0{%x=9?SGH7XTVQ_R}4NFx9+ZHtiv|;@wjW1<$cif~N z%%k->V(8q-#c;d8+?ajmsPLf~z|m7TP5MMl(gZa{&fh`=$MC9xwn>F~Ew8j)6q*V` z4FZ8ViNm?QsWrqx*ZV(aL*U}k3+?{;{o%!i*@(gw3`Zr>oga9>Qf4j34ng|_omE&N z`9_uBoUS}WG#V5kl?jJZYH@XUH^_tZ9ffy;;a{G(_#g8`-q3iJ028=0Or;)}h(>8X?9n!e*&Wp^H@q+T8 zR&7qoT22-TT|oJGzo~-9k?Y#@u&aWHt6dzXZua7qDId$gBx(p7;i71h$t&8hf9A!F zur355WIcH3V;5us@NtD7t<{ZPvXZNOzu_GYi&HRq877YLl9uYUsOX^8?Q8mr0bq-u zenqSJm3;!*!RY#ysQIlFL;DwTLePIud}WdcO0)hL7VWg&lZ2=b2Qbte36&L2!MV!B zOiLj4Vms#|X1HzccABCWn?`6OSRtsrXOk`Z7N(67m}whpBTUf=F*k?PUZNU+rOGo5 zu5nZTAjU>|At@;fsN=DlvPJVsL8Ika1B~y|K9s~?mQ2?+!pXI85$YS2zBfygFbyY( zNuI9L$=*gl1YIqeQwe+H(v_@IG2ketjdlX(#n8^;&_FvJyZOvM3n}((s&As?ttqFrklhBAHE&>oNhj7ktCD%kh+hLo02y1m}plc z+GTTi_%SlU<-T=D@%gTeP%ehXcB~4hlzLS$HbYEMfTH1;+w*z9wDObx-9&-0H*I=& znyF|c5&NVT0G^v#!3I@pjKkV? z(R#qx;2#l+SkK*j3xuvv2xO?wZ=n#jN}3&+w5qp+)RcRs4GL9+Ix4=nv_3@*ELgX0 z4rppZP-9X7VM=&sg^1`~VbT-rCga4c;edmT7hAzmHtWr9HLakK0PQEMY1022sa9v% zCZm-kg3>4f#ip@AUzN%H+;+TxhPDlKuY#x*N&{PBO8`5c5`X)Kau}4s|A!Q12}ISC z%LGAuHC66002%0izbqkLEev4@t%yz~6kuKTbN65nq+Wo6;uK>9M50d3O1(NZ0yt)L zj}LJOhX?(jTv7sY6XHx6>NID`i@kV$Uk0&slkT$m-arqiExf70xKZINgsQl@FN0X7 z(^yxL{HYXIE~PW#Ii@VTU|{-uJm%qnh=8;?kiA+elY25E0hx&#Y~gsaLbJkOK>L<3 z%lO51_QPsm5j1rPp}8WAFY0rBp{Lv3A=&aWQvA?catiLaffxapcr(h%BComqJj)9b~y z&=Sg58^kh#FM7$Jg*WQH_ozt9w&nX0lNr11%Qxxp`GJukRW|X)itI$41n`05Y}BUV zW{sjoye;e`K#dn96!L!g1eG4Y8{k9uFZ4G-iFUxviS>9Omz zTsJ+yo_m(>iZXkmT0p*?Yn!1{MPX}}6 z!Wuy_iUW)HHRkfxsb%Vf&=b;{sI=^0rv|;ST^Av3WfLUe|MZ>+`2u}i#4)IcE1>)C zAUIM6Pa?R5L;bw&^e&)UVJnY5Ne7%}%F(nx?(Mw}0`@xXoagLdHhZ^@p7sZOFm8c7 z!ciTg!Jr=ux7A3mY=^{$cRmZS0^evqDz}a+pO5BT`8K zj$n}f(Wy@pRYg-wF&syCFQP5-ev-v1trt z8n?>Csz{T?bJe4sz(A-yPCWqp3SWd6%NMFg1fF&L4xBy0z5G7glIOkM_!*xxN5&;0 z1S5CPaU`qw7$u6dpz>)|^jwz=*vdBC>PevDHz}fG)VCBcz4p=HL+;>RAZ&b_kd%G& z5VeNTInH%=0BH^HBYeCKQ|nTRuD{Ip+x|Ii%$fm+PZf5c*)##r>q|NYhph1V`oM|N zdfo5Wy*v}5QBQaWlpveEBoBX!OQptOfce=WxPt~Xap(5pm5jFkV$6wSr1aNYy3jCd&yECg0qjjAvZ8v&9(+u*b3n!=XR}THk?_F$*J|4f| z=wOPq!g3T4^GK>Op2~Sk3rE~x45feR7xVkP{8bSdW~nKPY4inXUBakswV3!&2RTj2 zEZ(lDhl9(15aUkXBq?b`L3gAt-sn-p;M89Gmkljg&X`Yr2174B$|or^mPpU+Fp+cl{|MDv?+{nUES zNRvgy@iN$l6~OQQvK;C|>6);5iItD{ioP26($kegu`w-lvm78{!7`9*i8M1%RXr!a zY+;Tlx9&r!Dt67Ff-$-QFN-@?_E#{*oe@OloK#sjSpi(bAb*Lk?mkW(-I3W~WV-J| zXrb#$oB*k`p?w?1ywDgoTNA_GoHtB@wb9?0Y=r4v+b#c2X}4Tbp9Yg@H>&+I^{Y!V z?xMYZ^3(nm$|ik``27Dwrpcd@?N^BXK|sip=qtwPmHm>9Q_6Id+@YY={^!r6{xJ?& zHgpN*tM?B&*C8rRP-LoL_?hnAu zoipV>>@!jL>k6_#>E967(JVP49e;Oae_d2Z55Rn@Pp#)|k6;Jb?YTQavc0aS< z<0}bTa>y&$)>%(Tk4Yjzn&duL8jYrW`Y{-)Z>uSzN%h(XooKtzbAqsK`OL~;>$f1^_XGtk{d@fj;G{ivlbzK@FG_uf za0tpiXM<^4HyNp4rRt)y^N9X|pw`vTnv<>9iesV9!|q46=vH|ohHtV$BXs+Rc|!NX zw(k9~volXFk9!J8S(VMRi;zVw33_Bia|~{(FIpHlg!AYYCucG5!xxD(aW4^7tlS@% zo9xVk1EP6C_2Rws?TKXjyOx_bSxOv3Sicsb9u zNEC!^m~bH%6LS?%3_Y@ao}>&~6?+Iu_%t$7nPS#~kg#H)9jp?LfHgA=Ju)@|&R{-F zJtJ=Gf$re-2*49aX}dkaE%!V}rh=o-%u)deZ(QOY4VZ71-V?k*Ih#6r>n<|^wHXy% zWyb1#nMLov<*Z(nqGxh+M^Mp$iX0fytc!R42{Qp6O@tl%Ge(1DmlyjM0waOGxWqlvvIzy!+r}E>7ro0Q+lkO-k(jxpuXEVBgQv2IdHvR z=w*C9X7Y1meG{cOmtRK!%)LVqILc2Td1BV9IrYbmwwFWsxv;B?2-~qzVFo z=!;O?u|$>G;+xvWBgplEazf(K`HizNXB1GDZXkKWDh4>aXCrf4bC*qp5GMqR>QsW@#T}U%$rNV|H{5 z4(u4&pZ!WjS^O61RZByiopVuYi5u)^$SmfHQSzSY67nA9FX#_yadLtc0rhsrp8Nst z%^AGNX-)$;6Osu9P*+V@|J&YrRP2!Uf0+aMa?Ieebf_Y?oL7}9b@Twv10<*qJ`U*S z7xRCuj4{8_O6n-da9)-sFNLNcfB^w~c6-D7zIj-}=Lq&b&tgrCZIH5F47dC0HjIFj zM-!cb#YZI)e>-L$t|1FGw3u~haYWkLFYg+KM9W?r?w4Aeojdg;zTQ! zdZx)m`<5>OZp_^~muMdO5rBO4;4LDuGVO`4SBKV2jE^Yc+PnrgzPz4`mE#znd3d;q zX?9cL>m1GxzH0qHj#dnA@Av9uB^}LsDD*uGjVk**yk}-Jp0xMIGh!*|ho2Gj753~_ z?qS(kun^)}NA@t~^`1A=_9W_yYpG@%qPr8Q!wS|N53x!;xkB)yIW-lwPz3@&@VyQdeV521b%T3ld;Ri?H}jaE{8@4<7Ms$E21+!WuS zReXZD3T#B=V}J%Sn_{HNZm*SggIJ7lc{A|^GgTs2xGf|)?DLmiAwIGzON{*GX4wsI zc;f3Mlk5@~E{czYAYc<0wh@PedB#@7aq$4$m%HMqR@m-BW@DA)OCtFl!sGTr%O@|k zK?8Z``|r=!PiX~Kyma&RH%T!%n=dEY?=|1}iZ}p`g+u+w3m*SC-KJ{pe?I6z@dNZF z@7g~u@+Uq`E9tn1D(ljF1gBYfODtI5meFhc)|Yf`+P~L-0VWmStGu)52Nu#zZ*(sRMCdNm zO;abu$fce9}hBdK|hrO%)Ewisamw0H=j8k zMUnuhc$DIyPLwKy|8_7G7Aiz3YkjJ@w6V>*14wEY)!TUujslT~Xr~L1)V1b{zNv_9 zwI9U!HX;rKNiCtIl%wN#;yRsk`h7^t;sZBy( zDyeU%C7`5+JTENvV@kxk4o3q#1&ZJ_56`IV%p9p3)RY}0fTb^qcJ*WmZ|D&*#w$E4 zSgA1X7*g_f+-18;yDN%&@dS}_{`uzq-8acvU zZ(g|9>R6wVZmiTYBk!7$W6}W2UWk^(JS`Phk?@=DuWl1S^b0UcU9Lw?re5ZP!_@dM z^=pr%MxLzH<}sQ2ga0nnb<9!cYD^7r8K5*UqQGAI>I_uHX1Nm z&-lZNQsG`Cx<8G$pBFk5BkaoUOExM_?w1d2e3?l`(tSu6KT^lanj>)VtmB9Ekh(9{ z%I5QE9xD}`Affv$*!r4)hkc@QA5v`Q)i_Dh`NS4W(>~wXbG1|oqd0`;IE_JZz*@I)pcX4M0X`%rC+afut8enb zWABdPMAwG+W|gqzCTj*Ay4OqdZ@Ro{N1Fu|&31>%W-y6rRnQBwqem83DRMskmSbH#{YC4S`2)_m?Z<1H-5t#<>^K6pp7GPGJ(C*d- zlhfN?z4&Q{vf3&!qE7ay52#o(;udU?SZf+=61XSI_l;VGsR!J=fM6Kr4okE8PrF|& zam_36)uEXyqC_V0->Djr0cS{Nkx55#5-NdHaE6*@Y==re6&UhX`91-;|EJMQq?tv9 zDBP|yEr>6ao6ms4@*p@by1uE95MShKx(!=Qcb05adA89@hP6lL&?{*$zQ{rjpDzQ$ z8(+`%B{{4BoWsubQXYuBuM4`%D%7&xl&Q|rfm-mmn@XUgs_Jp+65_~p`I6OCRSc3c z$E?TShG?aj&4nCbwwim}r00o3h7R}SWD6uR$1}Oq&rEkGe>Gjni~WG#8kt==U^Kwu z8!q8yy2SF5Szr~dmpDmpNzZEBaKB|LDMly!$E`~&5v9N161;LA4)O$ZNEer$-%GS# z`?1U5qx!PKT%I<+Me?B%R$1#t$_925PEJO7JtDfPXtTr1S`X4NaNMa(28*LhuM_Wk zCy!*ro#{%!l!mnoW+=LZZmMeOEorFJ_BX+g>SZe16Hpy0Wc0dp6{RNK&9mkyU-=bz za-7f$DeI4K-ImK-Tu}YVMnO7UN)K>+tEX_M4A$FgTxKrLbEBQ%5>=fwd#JaJrY=pj z&p%O#RabS?IeN}pFRKPFf!ZR6iAxwcc+$kS$!omTW&I`smz}}Lb2$$ zK_Sm~?rOd?eFTwK(bW5zGX|0$IHSNnkqA|yn*!zvA3IJoi&eXXa)k>|DUa}QMXM|l zS!VK5A72^GbvxwRUUbIYp2+B#&WNEE{(opku+W)>ThD+MG7PMbq@i!V`6yUz6A_o+wYifYgJxSX#JfJmG~#uBWWWK*^P(O?&umRFnCCghEFNIL%Jr(6(j8CfD#65 z8Zo;$zg1u5aUHLj5#D499Xzb`A?1DY zy&BsBQjSu-h#zJ2OsRecu_67;v}^9<%$@OY;rxE_?jhvoe3Ry2ei4gf| zM?Mi&i#&iMr@}u^kPUEs)p%U2d+}9fWir>6$XBG!wKBSI+XHbgP`WDxq&c&o>ri0# z9u!v;=ekETMk0bN@aGw#cbKBXMok$wbWq)t_m%(`5ND3ZWMZ%eFF9(htnR2>ckz=Z z+E%&=QZt*II95sZM;vv2@=a34n#G=Eo9>%nqBWJ7ECoQ zC`gV~YA?e+#0C>npHLg;VFjkHNXZt~2K_<7soxf7>BFZg&Uyv@J4&*19CebGuTgq2 zIMooRh@tCzK~$@-GxXL}1wPN!`lfIPwi6;tEC{p~rbhj)nwN7H{NI`GcSn0~7?hVR zxGdUI0z94#={b(shheC3U%&vxMbz2L7C7%W!-bH44C5gVJ2%~G0hFWMV`sL{7gR*7 zl*^7Mw0MNyk@Hh$DH$U%C$_zaus^kuwbQcw|Q<{Brq9h zoN=&w%=W|%YWuz4AU$*o>(!WDVgmqaQwqcn`h~!n#|$qutb+9*P0qD^iWSJveOBZR z!1@PHu^OHJ(Pj;pIA+6+19-b8F$i+Cgcm^EC5Fvpp*UQ1I`-s?RSSZ0f8{2$^xo{; z(o$6Gve%T733hr2=GRQS**YeH6=geC%DheI;Bd2`0 zC>nL4)AJj3+!ZPj0p^&p@NQpnlIVF-fuQz!t0^C;<=k@}Sic;bOyp&Z z&^1XS_DU+=BKPTpHp-t_+z=@(vIM7IZ%>N0YSiIQ%XEFVEk5q?4a`r?=sZFPeDbnY=C7UiX>Wlmd%zvHdHTNegPq6J~K@H;`e~k zSUXxX=s*(E)ojDgH>_?F9YsY;N@mkF6m}!}iGrO)^!aFuoXm! za?=XoIZ<8YiyH{-|Gj8ecC2RLo#67Z^8AMDPJTSF=~M1R?5t-(mQZjfJXp3`hiGrD z1KqGe@YT@p=bri=tjC{JC9y^C{;;m}5;;s~^zv$gf&@B6EdERx7`W5kxHa<#$7WFAN{?+ zn3`aKih@H`H&JsX6+lWR1r!{J4bZ3CD6DEUg}B7c*M0z%G;t!e8zhqgO&l_ry&=}< zFAtRp`Y-wMJc=+HF>3%(U&khA6S5#RpV5q-$Z4EmUY4xt-cj!K{Sg;~2@)SNL%z$6 z?g3RifhSTF_GuZD_Cx}Wpo;Ov#Y^T>VNA;-kU;LnPz48)ql$HOF7nHQjaMR1Q(;d{j1Vu^?QP9u7K zu0}^{G^~(#^p3VNJvEgt;5C}1S%%;^k{aU{7({fLH~}3hP)*T?o@vrU`?W=~!9dAlRRk9&nR0Sj z1z%6i--Kf(X@OM%X0K{h1-Iy5tYCLX5~&L12N#fVQNnH@0%Jr0E}-A0T{=ruuz_*D za*_*h*JkD^mXc&G01CdwmG#CX^rE~@4XcbbI$=I~P8FaC%@r5P3yKi{Z5pg2#B!MX z-UfI<8h0n|>Ro8e^FZt%7FhzzZ3S3?2ak#q3Lw(E9L^R#!5t7xF33@OIF;d|<7Xl+ z`-H`YF4&b=y1;c9t|MtKeEm!$yNLr1YncH!SDNVLDmt>OP_l;bi7`cyR)GZzCmmnT zZ$aYjdYVwpA_RIQ2^#U++rHoO*8N?AQL1rauTU|`OZY9{^0fYkQiClnfW?{S3mh{6 zCaZ%B2cvRCyS3;haZVmD1FqecIBEfAn z%CR&D3yK6ZtyI^{eQ#C!#xILnB-r+n^Vc`BjBvK^dY&qDTUJX(;p*j)Ctn||iHIM`-G8KFl62!BB+B#58nX|48RnlB;rOwv!9QqW3og+_Qqb$oRHeot10U_uu zO@a+Ud~Y|XM;z37OC3&SUkoB9fw7RQiK$e_ z#72cys^(-RgVuRJ^D5uyHC2pU33FEPC(bK*dSCvQelLRf=x)*lpXlhE6p(vRI=W^ zE9Eatjk%B%ZWa~HWz&#?#nLX|5x`4ek?~XaJf4Eu&p6bxMlyu~FzbTyiW&taPIt~? zQ)o=?>0kc!NrF$N0520*0jEv$L(WogN0_3~PeD=E^>g-ah4!2wp5n9(n^SOru4MzK zodT3;>kKgO)t|xv4;4xnIi=;OU>~q5-iH+u@$O$wqtFkm;4M;(mtYSOisp>UaluJ; zh-w%w_3Vk@w5quR%otGdd|icJ#pnt}yd00*X`zH(o&W(z;2%_9y&SwLt!7j*Qqib_ zQVOD}!h^dKOh`BCc|2jN4Y4bUv}!9(^%xRC-Ad$0c9}%5YW_K9X@#Q`uc1CTthQI~}b#8=kX0trQMi+1HpCs3ME|E?JvVnV)oZgJ-peDI5bXK;a~ zde=BX2BZHBF9oQwY$q;W$$Rs7u0C4F4)-JmhyLmQ1HKUn&;Th~G2=I&o?H~dG}5M;QQ~41o}10cMYCzHmkW<&niFRNw&!*xlhG!9H4Cy$ zx^$sSNjvF}Do{0_dk1CDOAdBA9raKJ!;Yk07~ts*yHIKrC&KK)`kXj_JhRVW*oAVP z&{Ek>(((Zi#>VD+sxt*;0{0@4OwzXG@qL2|St2&B0By(Bsxw8{t=kK}VMlhs(>ox{ zhSkL`QXk+EN=Eqz^z`fdFS@WP>E&L$g*qJ*8>WPMK61*g?+zGfOTO#YcXH`07n zlb+JOXv41A94u(451<+N!ZEr7Gr>(&rM-4BEqci=SFH(2j zVBy6_K#)x3T{y+?xznojruU4c7_?Xf{v6E@ ze5KXYk?w|O>#{~_h*l(_^(BgY=ptr># zB<*{5$1Rd7;gu$2-Cro;gBj>xNJIzhVghwk;PU@V{?inM2b`* z;cPo~6Kh|}QgLTj2a#L*zNDxwHp{W~bx%ZnJzRn#7t-MCv&~u4Lo%4v3&2|SA-Vq1 zO?Ko+3dLV%zILaU1{E=goKO)3YukQF6E_@N(60;1n2Pdmm)d>qdPjTxAF?A5s5RlF zkRzR!0yVRp?F1xW8^(XO-EcY&tw_bxj zBGu83OpjDGw>0h8ag#I5iJSpKVK@uT4Q$-^8*3O;QY14#{a>UsnO{a2) z;dbm3E4onYg!=>`(|@HmcG*2M7@O1HIZvs6Y|v z>VH-9;Yvb?#VO>uCl96?QHdL;Xg`62h`^rpYl zT{N)H9r!31-=w#^s$U~fD52imghE3OAF`#ax&fpmkc60Z#0DmhZ{68gCW5-@RKW$p zV6*L`+q7^LZpKM3spN(UpbVT(X`qX`kq@3gZrg3ZdCk>Ks%nI6;WK7|POLA!SJY)e zWRM`W8vZSv(qi=isn0)%G{!OxxMWep7O9OSe}S+N985uN+BD`*+KambQt5%eM+u(gM5?6Ul(FyYH> z%pY9A+*l~(AyY^hk{a6x`9DQovIV%;7|Lm`ePbzAV3E%TA~iVP}cDv-3Q^575fsmfC% zgrlyPghwo1cN}yjVc6u!{ms$Qjk3LV3JKO^bqXf+bMeWRmz8X#SB$MFM(4v1tYf8Q zAZ1GieM}T<<6Y+R0FFynG&m|P9F>w!rIq%h>5z8kYt5nPu?ApDNIV&Gni~}M-Ity|<&ONzmjH^uh zl%JFjuEPBCqOL1bOh>aKl>F>5p|n>8vC1e}&MMdNa|umlMR{R@moIloUko52!$|o} zjHPT`nRDwgOAH_})(lpck=EvCgdRYaX~r7qc9tBFr?`WfPul}bP9WVLL6BwXEILb& z(04g@(v!)O7o_bVg@4}g79_IiHhDX0q^P9u~eP{JopDcGw@ z0FEHP+#HOn0|^U(*xL;+Rpdeu(DN z&I{z&Hc-`i*vl948}JBuPy_j$e@DOy=gEQGLpIAu0&gUc8*hJsOc@Xbog&NzIr`Qb z?M96mq&w_65M;YU$n2)kazrXiCPtnfBS(<)rxIN9qrx61NR?*ub_Pd~Q0FSF-D)vh zFA|Nv77+L8dV}_E!%~0PjzR~;9fpreU}WZ}&c1;r73asG71IB6*e?MExyGKsT&X<2 z(O>2ch4^H!F1nj{PqWr;DRMHX%kE0V_@;-=aWqIfk1&!v#r-$l+_!P$L+pRR zA0WBnFGH!-RU}z6boXnfh#i>vZ|4p*CHH^w5NqOr9O);(|XwA3;^1lUaLIrL^1{oMP5RkhK zP>eC61uF@gQH+Vyy%HmbQP_eEQ+5=5bC^vs{dTzHc?(p22~D_Taukm^)d*+5i6aGT z7{(b77i&H?(82PFp&W$qfGRpkWlRgEWe&>XY0I<+f;u``g$u~og9uo@I)Lg{kdZ|v zt%Q&Z+c>eeiaH_|9KA#*@g9L1#)4q=u-t5*H1QXmyfVlP9U>D}PbZP)glTFhYQj3HlEkcxm%5Z{+A$ao`o#dhf=!>QRrOFtTI7Kr>C%Zsto50zG z+Vz#mPy`B6bn=S`tuYh)K>4zeq&E40!R5SAG5{+CDnz868D@0yYGFl`6F{(af!?GU zz;za#B;%)wowX0xA%O}J`K*kHPMQfr7o{o-Hc3_XH>_a8IN1ag0Lr%@4J5tI5uF_L zqerX41SlP~4w@Zb0;7{{DscJa2?XW)NTLIvp3%uSRmQA=8baX;2l=6Lq$4^h$Ajbo z&jQM1jcG$tO&Oi6vxJsLw@fFwFuD9e@xEpxC+NJtiz z5Mzr@V!Am~GNlk!h?VIEBre|QWOpe{ZQw(b0P1>?N0UU9vM8<#c4!3^@}VdZ&<2ZA zCM9aJDia08Gl9cIAQv)GN~bScI%HS@g@ct4sWT@@loBck7X1hS)W{YPIj5#;lv2uv zp`SifEC&Zr64)4I5aqH#pg~X|nS*LDaj}Y0#)1Z2%J_k0B4`)Au>>PZX~9b^@eUAl zD#Aiv1IEfIrB$61VX#D@Ltsc%+Fx8dxS&jsY%2c!Ril*A5qmrknLwvIkOK9WN0c(e zhP)Vhd!R*Zc$l%YITEEbA@-o#X8|?|Bak^lxS~WU=^<8ZX0|||L}qr-kO3`9>0*1o zW?C$hK2|yckP@PlGF(8~n1cgqgos|WfQrE=B@IJddPg3yNg8m+0$p*4QpyQJd7!Yv zP8CEwUg7(SQts#@yn+M;bec!e(QNEXloH4jFIp~av3qeKn9;Kvh*B0wlYO%)#EMNR z^}-&+0fo_%mPtL#i&L&A3?BG z7(1SZtlf!HMn36~W15D&fmXnJi1;E(iOE3=BCISZlno~mSm0FMg{%NG-;eN zpJ1hI&@f1c;X|TB-h+_Nh!UY@0Z5{(Hp>NGOA*Ket{oAa(k`w7ybX1QDA1sqA^N5r z?D>N9#@3r?QRK(=uFv7|cuCoN7ZXBwvnw~RMG%PJaiq)Fkd*UOs^Ix4Mp_1Z8XzWq zk02nPi=i6yyJ@RrHDp&t&~MiNRf!g6Vc^`RB+&z;9B^xGafvIJPW=G=9u3Bc*f&1 z?EIM)h8Gkik^cZW!)vey`7sfQ9&w7)JFwH|NdU3)Vw5=WT6YZjCSZ9!OP&wU4Ws72 zklMTeK3Y5&EGHfhfWkvzl;gQ10P$NI$2=n64F8}Dm)Ckg#Cy@P=(|ZP{2?JHe3q8t z`*!s4d@Nh|5LFI56{#;C(9{M0bpw!p>Tu}a;GytX7K1z#vNSJvAdaWRQsSW?nc>l3 z0P=+|8vW!2tn4r6bUlGFyB|Qnho4Ll^=M@he7&U23&thzOb`I@d){O{;#dV=_<;6$ zPQv_sRpAe(GI$y!5c#I=4^P-ffu9|4`LwPKK28<}e`k`?Yq@s)t#$NOLK1zA4M;qq zeUK*sVAB_#5%AUu9sCv;Zr+S@k5{bY#1mOj%GMj1ga;Ph=lY>9xYE+1&JWJEnL86pDOxt%rA#`r)gh0{9|_i#|SM z`v74QJqlmOpNTWZ3!0jmiYXe%|M?>1I{1e z^SztxlF!<+;pN;t@RoZRz2hbY0Fyv$zds~T^B+1)dC6ITe}Mtezfl6`FVo=hXE?@u z2&oVrs^N?;;D_toD7JYmSq|T(3GS`b^znx^6d$O*^Byc4J)xXE{t$&QU+A^ktd*L!e62ddNP6Hcp-pp_#$VaU&1x@ zV4|=;V}W}t8l3)!i2!~HoZa`8@$p#A3%)Er;r}X-@F!@nc`1Wtd?HIEFB7rzWFolv z3Y&g>AT>k$5f4m!4FL8+lm>Y&?8A@w3I4zs25&}V$^WP#$EP{K#jp7T#T%;O;pg}v z;6E6;`lc5de4Z*|yptl^zaTy0r$!S5$nPFbljE z3_-m9eBsaF3i!MbmM^1+f!`Vv^F=9~`0WZeKO!y8-)3e!9;g^zgbfGY4^Wxc-;jJ2 zkNeHHK`%Jx>FdPB@mXmRJctW$ya7Q^|HbF_E(Wc9*Ni0|u0|67$C{Dm zl{!%QKV;KK!3FVg(+<9?CCR_h>3&lU5ufM}5x=>3$X_Uf=qo@O@KjpZc>!DKd=@1? zzQ?qLzh0o=UlwFMpNcO2$rtZ6M6lw?{Hfp@z@hpYfeby?Eb5;`0`eKSfPSC8@qRBd zy`L{3K1Y`}evK17f1wZAb2`;F8qKf0Dol-9{;Cy!YA0m^Gs_2axV}MFR?-pen#)ZD8_r zc(ukbVM=5&o^j{{2UQb8>zgY$0n?$X6 zJU~r6hi&aguvzneHy-_juJ>_IOJ7yW;nm=;7n7^;PtG*zU{JtU&92z!_i(|dn3%_0CVB5zOMY! zVGW*UuW8MdmApYou)Sq<#OBIQyG%&@> zeZhGwJTiT}Cyh5^v^{l;2v0Uy<=K`>_#&qOehTU7yX;IK!Rm--TEu$6s44#H#S#BO z?uLKEXZY)rFE3ydjn_Im^KO!PzKN9+e-lddO{$Hah@jmk>hR!67|`LF%(3zf7~MQI zi=3}9=HxS6*?BffMEEIVFnBvB7jK2i^Ojx!yci}7zQc_*zKX=>sWjpEHjHBYv{0nK z>`=f@)`|0lRR+GR#``Bdn|^Tw1>XgP)>|I%elLs(Kf59Hd5hdb2?6C{39ru)2g)Bw zW8?AsQF*OCa=e$EF+XFC1W)LBn6nhJR{4ZMdym-!q; z_V_svV$XGF@qPAe@GC}SJ!8}X&mwS#*SwSAx$uee6{6I>OJ~AMJz4RX9r$=XV_UvS zmaD(RbM-z3mVfdFiob9}(TCt6#J})P-h+uM&nEBUqabMG-@s!$hz(Ib$Azaq1gFQ} z#WcJF>YZOOq>z_W>BDPikmX@$PVtm(4160768sepG(OOYKHqr7#z%W#`LBfJkvd%Q zcUU0sfWFM0$rKi!(;4v<@LG7pMke281|2UVtLNs?67BrlUmPE`LXNjeO7bS=Cis6i z^=#53{tWi>YEFW9LJF4rUK$L)K#QV(vTJ!eSf_X6!u27#c7Dat(;s=UG^pW?lr?$E3HF zu(;!+D0IE|BRx7R8=Qv0xl#GBBhe4- zAe|lp2GSCO5&>73p#W8yeAPDsI3c}D+~^@d0So~JShJx@k}eeyJjm1-upos^OF_bz zfdK-Pk`fh3eUZ{@gmiR-Wb`T(C3!#K_mGxABL@+mFI2CAB}p{Q@p2mQq*NnEkipG@ z69C}AL4#;0Dq9t!bcg<&-stE(I$C0)L-asRl1dqmjE=gA{QKl_sa%tDX?tX31fVGi z>HSTwQWDaUQIUVYrhq?rSAtSC5;dRp?`M1L?*oB@8SIACLw zm8gm#Jh-qqszT8}QW_v2+F-!umMca{M@mUXN=HRV{zWQE+H=zeGLMW0=;pDWtLqb| z$CRR?Bi~Kr{Z!2`Z;o%Xhb9FT6ikAKAB6IZ@WU;G0#JYhkTMD!`hGurOuI)fQj*dV zQxgEE00IU~Hy2+eJ5d&XvPf7ljJ` z#jhUHtdm0pz$i~H^A2m`JhYK+4{79J0j7m)Onh+L;L%!HLLVB`R2p9T;n7FUoH8|* zXG*l_0B3>Xl`*u;>=dbk$wN6_3JYmytg_uwlKLo!rw(hgB3^`2L?hK-cT0U~<7Aa#TmCl&Ow9s&nfta&rA=Itr^PAFp% zQwJ~uh6_~|Do~)BFhPQZ2od5K!UG3RM0`d?O`fXA!$n3|BP`Qj`bs}(>MZiFH|0qj*i!gZB&sA~pPhww5-E7mYr z>{6Cp5XP<^#4zb4h8hEeJJMA6V+0Fbl!L~}gh??>!oWBKBO%gGV4sm13pl)pg?(`$ zq0Z{vxLB{S!0}+IVTG(p2P%F~rWlcOBhxAXN|PsaPQ!IEfojSsAhk_JQe zUTPS|J#Ma6l>CT03*%6wU`Uf8$NW&pQRN`RK`&AC>}a(3+L90z1ZjKkPmyXC7^0(I zsp66GlA95hb!R%|;pkCNI>o{PM1qbgwBhh%#YHG4m3lJthRN1S0_tlu{xQn zPJTLUtYKK=?=5cn#`cCK#ahCWqJiaU9Jcudw)M5e*;iawU-s40zFL|y+|Cis`K7Vd zrCFh+S#eo;t0y*1HbWVGe=?{t*q+a)G{=)F$I}xYW@GfB#gW0yMNhgC8J0A~xO5l- z-_p`*tU`uR!G>w+_`itudqfN`oitg;}X%!ZiwGGUx zl9J=3RZk0j7OE*m$$DQC~>`J#GEO z{`{eCDnV*O+}7*t>}(54^|{4@R)K5k=XNweRZc>gwv^;^Nxk(&EbElDV+BuDGnYo?Km9Tw7aPT3cCL@)p+C)t1%PbE`{> zOKVF@ODjuD*22=d(z4QeYIS9CWo>0?Wo2c_Sy)+DSyoxktS*^L-jcQCELoPZzVbGpIFc5^EsihZjwe=1B>vfQcnlswtNjWuVA_)Gvbc!I#+InT`7FEXq%y zW}ja2l!dIDv3~D&w+Ps_&>a-k8wc6YSdxX=0tQF>z z!(l_moD&WQom!X^gH7ku5Le4tg$PjsM2Hh-H7HPBU0JoAU0HSDaCYS(L{%MuCi4OV z3mZXp^=yj3CL_%`7QtCpQBj~uvtu}&zDdT}RodBDm8wDy18E~Y{MVM2wowWz6 zD;dX|+T2{!0*9))w+MAl4smT~8Ysj?;BZ!_M&;B%2IsV3!GxO(=M|XP2n`yX z9H37B0!Iy}+MC+!9n@-K{y_{iD*r%jhFscPR@T)6rv?gCPyZmzmh*r?txX06Dkp~y z{=oyM1PM+G&mM6y+MphSk1hE4f{*Pym309jBObs?K@q^%h&7*KSxTu8C` zSEVA677O&>GFHJ4YC{DJEVIg$2~8_jVTSPMi9=U1h+#mKNXN=0qB6?Xm!%Y~5&M)Z z5|@5*2`o%SK211$knDqkm~^sXrhKBoiwmVI1Xm$_kdhA^8u>hQaI8wBk4vIbNG2UT zaEM%lJR*Wi5lM(HJ&BiwMe4kP&>jfr2S!4dd0<$9h?I~86(NzeH8MhLklxpph(yMZ zhXO;NTP%a0ASa%GgoIfk4l!{B2FQ`A#|jEsA7d5tOlb>yeyFJ810=--6o-#ybhwD^ z>?n(1XxBo*ojbA#czCd&T9F5`jg8ho4vsVD96A^d3Uj=8K&Q?Of{QwlbZn?4a1&Q6 zcymL>6dbu23kc`Z7@)LZaCK$fV6Vm5Cu2Kv2dF0cPsB0XEJQ`Yv=NfibI73iBezk{B3t zOxH6UP4*Z|rWHMk09o)b>OyvR05-%xqqp^=YC2gmA? z=;M;A6p{&_he#z&qO4qsNT77-NuFp}q&nF^Xs-{-*hEPKDp-Mt_{oBbOv&0Bk)kz7 zFUnS;^#}zl82a2-GWZFCKmQ1^Vud)Q$`v3gd0i|n6tq6JRM0ckVqwpZzbZaJvRpXC zg2y2+wzK0)1VcM767Jk}nSh4}AXOeNJrao+(?AZ6t8)&W7zc$p!aSe@211=c9VpHu za1&=n!J8X`Q*h+UEFhdC!ywKW+q)Qy%DSmBu;wkz0X8+TQf=VSAjr?yC{oLx(5$r~ zfSthxDh=D30&3c_@ZcZ~BO7r5kVzwSDiZ@v06`gV1emGa49L}vbevI3@PuX!0Rij` zDX27T2MVZZGXP(xlLW?$j#8Kxg-c>!%wf8o$!QuB2kphnQv}EYk5L!0J4aqx7`|W1 z>>vf!ae;KCn}tt`&A&Y=5^2#x|1D!$&n3@_q$ZhF5KU-W`4eUc_jBUVl|EvKupFXL zqEZ=U(3ho@?TCGfAQG2;fl6Rf0R*Km2L4vuWR0Ru7zYduo{B0JwQk5{vC@Z^<^qEOSA3zwJoy+bP4aZ$G;Ynb z6d>dX2D&I|I{KM|?E)xekHqH=!qet@g~^b*wz3jephB#$;;5v|#y)b;07gOLqf4BU zAV`>uhjGquu^#DR0}X|j4}5C)5SrNnMUMyEnV5$w2yoSq5g&6iT$}*0WuZZV_woxN zCKi?~@zGII-D?p+3i72sb^RyIrFA4D> zG_wVY9uK%PKd~O$#XWEYwLCF$R|CcgsTGw6(*-!zSbTL=Q1IupIVs3+O_nf32$lJB zQpE1Wag5her}u|V4xfxv3amC+D1gYrg1 zO;6gM8#Jzf2N)X+yzm2tjyBDiLp*RSya{8|AS*#aIiPNu!fY4+{Za zRs76E)!C|4}B!ChDyu>t{26%~+pR1}EuE1@{W&PgR8k|%L@)O4wA zazI|D5X^9~Hkoy^x-hWjt?a;>2sV{bTGUYcY9VFW22M&nf($`!gGB;2`w9gzvSQGs zm5HOfRES9w2uKjaT4qz2yvhp??JFW$dZKg z9vvAK75TLfrkhB_rV>D1DnxT?4lx;`HK#mgW?@d}TpHNZECDksKNLE0$b~>DV$w}A zNq`0@7+4t>Tut#HR8SxR38;|-jf9yyXWQrLJ|qvk}m&R`%llW7v6 z>7F^HY39bGpo}s%nd=z%I*YNx#DRGWWcyO?Mwt7jVFT_1Gs{SU|ldX(CDTQ%@H5;S0&je z#6nBf3J5!-pge58Ad!v%U_<+f*s*|t0uPN>5^RAffxzicgX<6}H!}(dDEE4xIdH@k zNQ)ht26zGq#M^*}H%rQ*Dhs5|Q3D1C)MNl40fo5=01o;zMfgLLARv&J7Dq6Y5PYfY zkn~iD1mMkpJ^L3H6L}Fz8B#U?5!PdyLr*+z1i47ryK~UM+~*X6^0~r&K{-Z}%ZlHZ zy{`(Xwj&D$aEVdnJ z+T<$kiG%%8g~Wpf3Bu^0yO9{k>x0fg5lT>&wn`vCWd2}K3)}KTAWQX3pCe^nSzcm? zWi;O4p}AsK+-ZQh2gy&Zr)rJXM4l&xl+qHj9S(>zE#J(sBE<<_4;^t;6zarXA$UFL z=n$i(Ody(D{bC9MTsWW)-d7i3aA3~UnKEnQbO8~Sqan+XsgATV6<<;V@}x~gKX=-! zS;3X9F!@CZ-k{eRGlFCmm|c3=|66gi&GESEafJ?Rn_}kiEvn0SWtvp+RWs2J& zDSDAsD`i@$T<}6A4${v`ls_}-)LymnE=^0OZ$}F*y91bdu6%MkP*hl8;|S9c(GDB9 zF*QigfpNtvp1O^81gYSqm{IVJaS*GX7518Ip`+kiTYfrO-M&0C^U!yV5lf^o7M8fNDoZ`ax3Z=ZkH!AnIP$W*~5(c zTJ(l=HE6)x*^6_r;lK~%R~N(U3BkY^rYj__GsMIpb4S4&Y35BCHj`(hVbrWZaRHH( z6IY_-m@&l%l&&bb*_#44J%Zejp^=4+GQG@LS+fvBq@oP1q>P#36A+9D&e$9YBnu8(8K%5DN_#zYU-uP-kTtt zda6KEpJ7La403ZgGSFj>TRK64p8kviRTI-v64HBQR20N1fYZMX7%Z4lkN|-8i;(8SUoCnqN-UxcPjn>?q?Cm897Ga>59MA`*UF#X#UO64^S6awNtd!AUZdAHhlGX{0x1KM)NANveC51pqWsXjRqvGmyg_WN zctyNfuLJ)III{HK2wP-#t|kbA_L)Qw!mB$hFl@9CL7LwV2mo+s?Ew52vOk zm%=%}rOkkAvk_*1DaspwnGV37DM13C0Ez(A)6+ZP$;pYSfOleI@O0No-ENfvH@GEMC*P>jPEKK|qw;UG>3wB0ODT4im- zzh{`0hFu@_Tn4xd8RXLFGWeo2O#mt^;cAFcJ$ljzYSEyJkVsKYd4500qz#t}9*2$yuNNa{99REyvW zK~JO92AWJ#8nb8~HYsvoJqf_k2`rR@Fq+402AvwJ#2tAYKn0_D;6j7)pjEIQA|dwf zQ9Nq6cZiJJrXhjOggEmU#RGfQ5Fl8EMG}RGG-aZ92A#+#V|zj;^NN8V(K~Kta{x7~ z90-tcg*z3!(>OuOhym!MW7IIeFe42Os%iaWKr(DEYIuVS%>-Gaf;o|LoCH0icAQMT zi3#*rIS!)K&>$fYt#jE$2jrblHc%7LJnYYC9TfsT<5PuSAu}p4D@q3phd?bA4O=Ku z&J7a_c%p?i5WV3(`CTZHx1gcOMCTX|;o7jxI%ORR101v^I>+jeg$qN+EtMPyu@w&5 zqH_2op+&YFlq#vn{JxE7oU$^+OeGHV7RRbPQ9?CeAiMn9Q`{a1q$nIBM}o{^1dc3P z9Sn-T;X)a~5ogCp6%<2V^bLzJHF{5v60jN<+jziJLYD0dA+K#z4V*5#CTEB{Z^{7kM6r2fMOdj{0qWF3 zCfi~Z4GqF0UC<&S5HQn_MueZJ87vqtT1cUh4321tB6$@p?4n*Ct+GkZ1ZP0FolmvBa=U0*~llbqhRYYG4jWnoX)GzUD=X!A}+u$eI=6qay0(;RO*! zsjuL7=Bms|j`od+Ko!R$x=2dQ#1o}DSCH{dpWwJTiDIEKI(>@5L4-2v(;!HU2Jj=* z2YqZSxIH0niNu-0g)H zQt-5p>kpkCk79uB=8ETL=fwD5;@=#CCxb z3$imcNrPAzbP^ZYLR$_M>0p_ zz|i@JDyM=3*&rM)M2w!cX$F1#Im9$b=)+IVX^2+gPM>#;R&g*+iZbgiHcb;juSN{9 z=5bIC1Z;!EKYP|Yw=N}chMqw^3AzlqpecnA1J^@Ftj3@ox*P|*$k5VEU0FKZW;zG;+(|P?wlww7 zL)VyUYsGYMPZf|#GlZCa7K})Uwi&D(;R4E+mm>vyN7T`Y6DKXk!lFroi(_bm957h2 z;Da;c$>pPzmTW8}xlstJ0%?s0v_c|LO2#!mq)-o`If!g9u}A06W*4g(7>i`Nx15NS)Hdi0 zx2iWK2-u>O8ERCM7{@?m(D}j@mS9GdazY^tEbf$m-rFR1m|8fwoPEO`P$Y_1W>Yp1 zKmimag%vsn=jHjuNemkod>Alc_tGFbq@)j!0ky;$JW%`dX*vT$CrXJF_@t6V0=qYv z=tfrL(^VpZAp*;`XXom|XGreIVhaseDlUKn7EEb$(z1%+i6}(au{M2HAbL3yot#vn zaD>bnmTH%T#GO8eqLYnNoRsD10@X{9L&+ShA#Q_tEO%gm2%^&jNt8ftV>&hmp?BL2 zH&-SmI@w1`fu|TUD7DbaI%%cnC`^Y4FR*)P?&QIuF@zFH;sO@b$dnMpL@Pbf$-*_e z7mI4xA#UCWF&@Z>P7=yMpa=m1v<9B6K}~aLqLcX^5G!0N^v0L2g}pixqLbM|adMQ- zV1vkc#UYtbb(1O}w;a*eQ%# z1A@#?A*zEjwW`plXnVxa@fwlPr3!xq?qxC;hHUo5%up!LYzr zbX>N=#+6s?D)J0Q<=uC`yzw_qf&cJpHA+o(eVd__a5CemPx~92XtVJZX7aviXA)CO zYATHO8;h)Y9LR{O-`F_a?{dH2s3!f5b#zsK`;9qp&EJTl5iUmjjc#`vyw+I9*Xk|T zzcDR_hJb$~T8*8pvi%#+UcoB;8((-${YJBz>^F|p+uxXirsn%^L?MIgH-=q*BN%N! z8x`aE8=>~Y-$+2d`;AX_-ESO_CiNScV8PGWrO7_yB$~JBx#}}UW?{V z4X#(QpD~~7�!V_Zb7V(9igV18nb~(Mw$T8Moy4XVmiEea64}hThP3N7P<#J^9Bw z-QYv-5#Q~o+FCjdIOMtfh77phxmi{2a-#Lv#tUP9%V(}B`$cUg<60MW*=T0Z z?k5DL{e%Ww?@vg;P3u({rs@E1q1OI{oG!##z)uK(Y?jNPP*atYR{w;UXe?g+gqGyD z>ih{QS(y5SlCJw+_z5A&_$Tzjcc0Kvg?C5%gpB6vRqqojit8%$6Y>=Pok-93O<6O> zq$)H=YPCAxbt(d6eD7wtJi)2f<;T|%Ztvgw1p~51bslvEQ6{(pIl-?(JX9<9To6U@G77 z!W*aA#PnX}e5-3{=rtSm>VvPIw#K0iU^Q@|w#vW+_O|9W4#ohD+}*WW!0KI}iRA@O zTK#IquI_^Kn5nBBh6ZB?-heNc>lOunb(Z-`JcX80LlZ=at#f{bGC#rl5X9PURckY$ zZ``b2BIUH}SL|J#tMGha3g2r!8Q<@6`mQpd1V+@axSn0hdr|NnspnRzUEOUh7#y2O z0(W(-jidmQ_(;wzU}V(SHq+}*3E$Xojn7{5m|!n&8s+OYi-kZQ+%DXwO7Dfj+To9ahd5xtY72iIQWi+ zgXg6w?S3tkYrJHy@*veS#PJ2LzCcZCF00Ezml-+eZs=tQB!PU8~hMJA~|Y7wYd7 zY;%4=bh}?4WUcPumeyAhb2kd>IyUcsh=UD1v>}9s5M5fXTyMwotwUQhSyd~(%2{xo zLk+=qq@BlBSbo90oPQBZZq$tLEBY!9tOC|nvDq$XI@S7&m7nmNK4VVR8REjazlh<* z@w@s0Ty<$di-=QzsqT7*?i1d~JjW&2_6}wl<6T=j1I7_vGp$_dRO@j3R<&=}`IZ)f zFfUaN|Kfw!X*alW?Hx|vRooY5@Gj8y{l%#(+OC(^lnOvlQNnm+oy!SeTL+s&KzFrO z?kpAGyIC$v9*7N8v3V7Lt42jm>HAd>5|*brp5NiLT>$dk5wB1*)J))!z$1Yt?blx% z@a9_U)xNN)Yh`(Bvi)w`Rf6UBLh-WpNfg!QyFE=EJQ zT^LcE+g93+4+)B|-Kv%boDIchS~-xWtzWVDRGldo=66-hcpLq@-}>^s>Uwx>L;vh? zyL(s@khwRNyL@!hSpbRm4_X80UAa}2*O2aYon zR%tlzeC><#Mn=o`YvGOCcQs8{5x%mU_o}xchie@Q2ficeHn6p7*KFRfdAm55UK0cA zSvOfXSvOAf;ETOh?YCG>KDF<8A&t*>aGJNO%}XQ7*jF#Ft7zE3vza*0Z5(V(Ja=Qk z7jVC?X0@Cx6PJ0%T(5gI7gNuJQ+OCU%!_O9a4>4XsCl*1JCOd;UUR+cmo#6}e2LWX zbmz2}*xtdg@!jRsY5{RT8?fszm(e)UTw<(tOZ6?E&uEEvy%5LmJDZ;W%)B~cexy*ugBr)`33 zZ6j^svMRZ`cB8qHtIX>*WvIt zn8uYh8&SVr+1O?_S@7#Ka5!JHqNZE->D8WVEA`ve%E$rf7_r$dS8=lSIZZ~3(cZ87 zjLKBL--R}e_fAV!U--Q{qSg#|v6t0lS5IGWF@?+?lk?nq+b}I9uBxb0>?iE|8Yav8 zVH6W{2^))(phw7GRuNEkzpsag3v(}cuF_f%P~IK!dc8lu9&l;R_9Qw-(j8t7HS`8^ zvO(4WYi}<5#djC2+ zljVgs{`CUyT~1%C_TH~U!HC*xRZp(JP5_4L-c#YPKgp3_7x0X$`PT!y*4@6rzRr{+ z)^>9(y%Z}UG269Ye_z0_AHnz6jm*AYB!Au8`HA99xmyQOokO)DI-2(%G_#gMF$N_7w|tJ#B7HNo#(^$*Sa?{fd$K+ZFN^`-+dVBbU^e#$8)jGsbsU z`by~fY7y(jSnpcjx)@j+Su4iYt9>ViiM8E&Pz-pz@9n(B1=W9G0^M;speomn-9mh; zSHiFO2Y$<`U(rw8=OzoB(mH(ioKIY+@0szvj@I)^Yi-t&ohLT@ig>=fa^HN%%TSTUbmDr48iB8ocWzq?V_T24-K*9Hl;;pJ z({nj7cCY4d)!D}9IIo_zuEH?k8|&R1PHa}>O^wB6B5ve1JDUt^>})+qtHI#EVw$|E zeZOL3G(*q`L375A+|5{n*i}LJ&gI+5)@$rs1}@aT;WOTpOy(`r@#>vD2Cf3~-iY)y z*4yhG`a?_|sm-s}+pfW6@27DXEtqQ{Zg!!|8<`8<^bG^PvJaUgy}(>os% zA6>Y#r$nvyJin93whoqrWbW=-{0I_#$nM=SB{0{s>td)O_|75cI-O>nsfRhY%T?pD z+{iMu?|2~{_ugG?V5w_ue%~@=8F#A2n6Y~mPqT6s1Kwa&V7%R{wtfNMxfvC+xJ<5A zXTKKko)_9=@tu~Q!a~YEkHOa5w&^IbwtK6PQ&?>+Ru+R2U%T}Q7%;z|ggr5#?K+X? z5-;{ztx3Rh-;_Nf{%TUqLo9L9^{Urg-QV!JI=>*USUwMYQ~7R7V_bW8N97JmI_yD_ zK;P@Ghu5@*Bk(n{?t;1Wv|xWEMCvPM*^OGkuP6t}tG<0jta-kt@UHN#@T~Bx@Gi`> zUInCTM%=Hs-jDh#TKEC|iWPoP?cyTIQ)r`Ezo|VBU$55 zBt#bX6BTF8pSY!`KM_#vk60}IL_aq5C-S-d(F&=bsIB__#5=e@8l(D&b*_OwaZc`! zXs(|~sLlRFH@ZJk@%0ng?1n!v`}(64WIr(ty#0x1Vt<5!?I)Iz{gD`V_Wn>+?ER3! zpLi8={fT099o!8^3W}1Bcu;aXgP76vH+gOzUa8hr$UCbiUHXH z)Bs!hNd?z7aN0m@!L$I>lK@u*SqdptAk|cYVG0x(E>y)?cvh(3q_9PyDYlijo?AXk z4276jopj3~yTNc9*yZ%&LKEv7@n!hs7lO+@A(g`Lgo$a1tdxX5!4>8#qn4qO1%^?< z>P!g2;J$cr1E*$Bu8TkuhhW(cY1_0wG!suSvTPtV4o!iWlmTghtW<&rt1F>mtIpQc z7~2wtB-YfjB}izo`5A_5P7-}1vTf2fKVtjErMKLqZf$5I(7xWNZ(?76B4ju!9NJsp z*E56&G#iFCs3N8zs2{X$7~b%+!4=^{P|bO{Y=|!}v=KPGZ8%2=VmoX4(RoSDR6D#5 z!#d~O2O?|t+`$F0{h-N%hqn_0f%ZWOQPb%#YWz(CA5%Jl)DHR0$hGj*4O0q@rjCOGDN%wq*FAicLy7;7g zPkU(DtS_!Lt}i=ff|jjLIV?fbJkxkIVo)^iq-N2wPc_pGeOX_IY{b^YHEP)AZ8XGn z1vZ{{&YMJ5sp@}=gH6_g3`irx&V$<@Yrg>rw54XbPI2>+rX(qH9 z$+9F2w^^^J>6fp|I@H?W<#pzDM!$`Xh`Y|PxIko;FhoKF$1lkZS1T{;D{IN<=><1D zvz&!;BKgW|#95b@r({nV#1$5Z6doBm5)QR=mKtJj<4h@Z1_RJG2 z4$CDBBztwutAzUQs<*7V2r`_q1ZM zbrwVBQ^KSPlO{{5P@eE9*`rFC62;1-37?WB)j2u39CSHw*mgVSD=3g|T>8~gqacfE>hj|}JrdTv$U`mr!9B;;8Id4;;3xE<|u5ATZ#_0}wY$CLH*A@aFvk zGDat)cn@JRs>J)4kwew{2$EmkOTdj{ct0VhLgGCYCWS%`-dEtlzG`PQMf)PAf2e!ZONwYFwNLLF~$D#5FP`)I@ub z$7<@uo)DHC#5qXB+WJ7Mly8uY5hI3^tAWpw5n~%8+n`R9fz%3(f#8A=BgC+py125M z3!Z4Ojd+qdaW;BFKNaM;b%mux18hXtmSJ`PRlwAt0x<AIljpMP3WdGD=WScyMUMBtCO#BGmiIPp88z$Y~l z^df6ign>7*VzM;?fZY~p;cO8T4%4C(Th5}TB0payiuY$xMMi$=JWzL~CDnS;@&~pC z2(1ErEqyxhjFPQDP(9j{foasD;iBInS`;i}ZZQ|Pjg47qVup1VUdqE-n{w5*e_Sdn zIq>P`3w-%QFBvgRVAb&4w=ERcH}GpPZSeG2@0I1X6(|<_xG4nR=#y}NOdC++(00`M zSs4;o+S(Gg<*9{0-qV*>7it%=E>GD3)2uMkCotS6FCZ(2@$+$F1GoZcV)-y(0tM6s z;JQM4J_QKWbn;egH0ZP%KKx19@|Yx+abC+44LF_xFs8J3ldWp#F?BCKpgS{j#g>>nu^wp^JAjXr=vY;xFDfml5qoYoxPQRq3K0ib+ zIkhe?FR!PSmX{Zum)4nzun;4-oGqRV$^4R}JknBF8JD>jSXN#&yz1J#yx!E{Ky0B1vXG9VQo6%nIWcN=~cSoGy-4=DEH!mZh_GfWuNR81w}5bBw#a0YBNt1 z7+VE~_>AGZQxg;xs7s(PZ4$7t0AN6$ztLuxNztb+W5p32?pOSXfSChv`D8d2%00cju>|!5CjSEhIm48=uyT69sPZ};&Rj?3L+y2 z)Fudu?5v8s=;+dvqN~b`y2s8>7gz9grbZPsR$wZ4+)O_~*C3HkkQv;3i4rFX#I{ka z#-5tQry|v$AY8N=Qi8y~I4LxO1=OBlr41nhKVD>MG4tc%T6=|AO$2%`rI{h0+0Mm9_tFjR9!b%t+tm*DJU4t#nK zVG6s(OWwXM>>`LKXaINzb%2oOlKnEV<-yBkvzuyp0z;;*{(Jf|;Q)sQL&B*w3zxk? zip2?b#W{!&S{LWqW0D25vQ&6S%&f|i0weO?A#@AT0fulqUrB19u?A2QIm8m0T8J-5YZdaU8QAtd5FT9GBPAy>KyS3RW9jCa{mEJHqnx}^ zj5=LM+yfnKRU<@4N1pBtp5dv#-HXJuun&*Rn%>pX&#D4X+Nj0#NpGqC;Gt;}pkQv~ znNj_hQ>}Tn9~gnS`=`wU>gd3B;~C{apUnQ`K&L)^itVdX-)?A8&Cmf;hx@Y-ciwrR zq7AFwtOVbxCt}~#!&Hy3*3lyl8US`ivY1M|K$T0abQ?ZU+0!8M6U-@woAcchu)L%- zWR&O$D0P>33N#axv)%)6!m&eN@+1!HAp}?T1NH4|_Gn&BWeuivxD2Z29T!c)=mb+0 z7SoIM)W|hqltQpBVI)R{!eQ0Hagl8Kj4CwiSxjcvxRQchDaAsJjC8etE}S=w3|lj+ zMtOvQB&Q|)%3}$uUjh8y{$?-&NK-Td!MzPbVBsJBW^{vkXXZdc9<5e^TQz1>Cg}b9 zW)V$55njcjxO(1bg@dIUg#jn@&chKbx3!J5Art1_sD@K&MT^jAyFIsHEf_TVZI{Of zCzrO$18Uw}Gflbb$%%W(rEjrhRkjOaZ~nyt3tuw`qoe>JjD$Q1@Zi7vreg1ls7p#t zQ$-|J$?^^^go$V)rafK>x{E1$~E$|h0_a_?L5oPR8 zM923}q@w2LU_Vg`nEDgVR-Qi*1O4zPQn1&>RX>q|S^tUPDpG%Qi(mhyAPCjJ83@9m zZTL6$JlOvxoh#ViEOao3w*JjG&iQW+R`J^GZ(Ax%)T4EZ9;b z{>?x5{+n2)s{ZB`EndC*n^hFVf73b_{>{GK{+oPC5={L~B?z>C6Nwb`Z$hIAVZh&& z()I5`3CzFCrQLs*s(xUbX&F3C{qBOeizEK-l#Tse1zKxpp0}-9rz-Br$_eby4wR_1cmH~WX8 zX#LSq)jtHKdiM?0!Dio3j?JlWh)(G!N-LxAuxhzXRKu>DY5J<7f%rH*#LHsb+IEdm7BCDpp3+qM@z%U47<-UYd!! zyWotymZ9%YD)*BI5R^;L!zyT^djWHkDW5R7W~`eMdv&FZ_| z>~^s@g_p^Qc?;UA-`Qj@RA&))uZTC6UJ>8zW;s-Gs_x2TFIH>C?`*S~PMp%aSHvpT zw$gX93K%+QO5436Rju68S9PG{peHbjbPAR|>Adot6XrLMe7l0!0G=PtQY5?1b1|T=ZOiP+dnn`i@ zYa$_j%@_MMkE~zQ=WmWvnj9zS9HE zfb1Y%|7a0+KX4!Ukmh6WsWWx$RuOAGuoc(JW_cbuQ+n6N^J1%a;=8Ni3@x0hyR#h_ zt6Q&kw;5e$&eYz`5v$nRD${w*v`{%yc9%w!3t{Vir!~7m<4oCI8d07DTlYJy*%eAS zWy`4v?Kg1pDjPg|Rr3a`J);Y{Df5nj#l&FpFLM`~OPly-{_R-U*gq3zLuF0=GpDSv zu6aT?(U)ZT;Ooz%;z$PHpJ^l~qK5vNLiF1PlE#OY$8CqL)9I=ST$E{1h6R~1GAhWR&`<1PFxVKUpGkto{>(4??PrF#&espxyPqi)6MZ?r z8)CDc*%b!;p<4e;3xQKVlfqT|GbiK`zCh5sKhwdE|I7wn zz<%a}F8j|+kSWz={+R{~`aWq{0R;6*XRoC#EFGh~0g`vc3 zck#A>S?rC;DrOY)391RZ#62R32;A!mBKLqKs&hDU_c5VI%kxMiZ1+^&-(tD7>qzaX4Soa%nDV&k4c5sA5%h+sgD`w+K>4_tM@UTMCOmlVDEm+ z1(*u*-aaORy!c}tz>FGF{g?%YfPG8?L*9=$K*xSe0k8crorF|<%%)lYm`kmU*F@5{Tscm^a>pe(3L@T+kHI{O3Ka?(vc5dS|Yq zE$k6zhjY8(!3NLDX>v4of;t)dY6ph)f^*rm?7&jBqEpc!<%Xhl5;Lje%lBX;IgDJ1 zyh8Mw4hTNId(?M0cGz_`4tp-Yf!nxi%(=~N@eH|okD;S!Vcamgmf>V^D{k6OQH$9K zo55rfa9?nU`R!kRs1g55X@}~+go6D`4R7ziXx>b9Zn_Z#xRJD5}+SuAk-_2$+RK^tC{g+4Ae_8ZnY$7t0nRaPe z2#rz_((#OOQ4z)B2?JiY!;Gj8U1V+);8X{bcUDnW$Lu^38j9k`zc@y}1aAynILyJh2}>c-WoL zkpoBA+zlHwOt`hp08^8Zc2?qrixwnUjHy5|;)ID3Un9DI7x7;IKI?CP{~#j%yA((K zdxyLFcW4dvcMT!lzjMXdziYkr-?6-^{%)n~f6t(`{{2Eu|J}mu^mht){`U#hyT3;O zA^#l$9Qk)Aj{lv3Z1#5rAKfQf7pbGf+0CD~ICh64QmuBtX zk+gb$KZ?$O_j{td8yo77Szo@DIG2N@4tYC53FUg7_zKzpX!fHYYLLI>9y#(`=F#zQ zd8cZpt8kZt6LP(I+g#VwgIn1Aj4h}&Ml0qHjJ0G{$*u6+w_GA4x#qn;uy)|~TjOdi zM~honrO?4G88|wXAa%lm-rPf@3ODs#PSo_${ZZ-!g#(uy1+5!uu_wu-_7@g8eO@ECb;B zw*(MdzvU86f6F8aPT%q<&%b36ortPyA9^#Z6D;LIGo=K{8q#*W86zy>iq}E0AT1#M z&+Z4pA-pHn!gwCo+3DzW9K^}tT-~&Bt{F_z0F9Y4V;G33f?4ooL6@2ftz|09)Rou@ zOhti|-Ksy)_9b9)tyX`f60l!MMezPgB-mf6XaC9~QhEBX6k`3AH~lMt9B}%T)BIQV zxHBOC${mrvvJU^1bY{QOj)H$>9PDb+s!^#2~xZgh4$EDNf^4Rasz1yokH^+?q+&I1d+}d*Lb78z> zpUcAPKX(lN``i>zzCL#=Z~R;<81ZwTa`kg5+(5MU7LR(!YuJO}(qV%Mmd;$%bM;9J9I;+OL&bu007uE;`bLblpzW z1p)GNsHjIVk8F6YGrwu)B+7Z??1b@K_01rsYJTHaHaK*f%?qz-aIB!Ixceu~z*xG> zY!+xtq#dRXgaYcK1HM~wEic%g{6lntv%FRv*H-KbfOy>sI;hPs+v6J#jM}tvA2vsrr*N=Kacs>s{CI zSX<+1_I;KI2AuEspDfdBxCNe9W)W9m`%lt$Qs8J39PfXU1pM`i*k?QO zpY*!5@%2xFfTfcia>Oh4PeNtAKdIr$MMq0p{gYR=75yy403-g%s@=l%{*x7I`cG2L zdHcGNo_~_bw*E<_`Rz|45kmjuD}Q~- zPnd}A;+ij=%WyE|U3I zW;V1;54bSL@4NYq3|!mA`Ip?GV@%a9hZkyZ#C08awV}=NF9~OZiE)z)tJN>bM$ZVN zmSeAXVCuMAjWM4EzF)G%7Zs8wW)X7q+5zX_#Yr1kEu^9Mm)rnrc%faU?(W?6Vsoyl z{Ux^m!M>!{j#VS-fM3$;e%qm6@>%`+l2lxr@(HswmmnEItNoG=Vze*0V2S^d25wlN zzhnU|@t1s>Bkuur{UrnZ$zRe*FZ_~CwBDD@^7bW_=JPu3%UB-TCskrCkPk7V%LJJ^q0peHp_^&_W@ zygyRGzQy%we&av#$-aN&fVnO*|40E<>yK=L?{2dn$z(%`Ox0Z)alZb@C3yNF6%&mN zx^8tdt(@1V>bD;j(W52&ka^&`4{1n*>O<10HtvP;96L|9hrk&Ef5p3Hx?UK6>iA2LtKk1C=T`yqJ%sS9#r3V3Hf zq>Yz`J>&KtQVkc>tENt{j5mgs?L(Ty)(`0dPwGRK-Su_GV;?WA&pFKEz4tnw@wmrZ z>vJxzcyGPd&iL4E_#su~R32}ve@GN?uHzq442T$ff5@=6-sd|LcjSiz%L_kb3EBRT zBkZO=&{SAH(S!OD5vH?+A96pyT?EBjB%CL@mVur47HM2DthiyLPA=7p$dgY2nk| z*2?wNwTolf&+llJAAZLtOx3SdJ-P~(Wmt$&VNNPjfbs80rL}iD#)K>PJ4$%7-!TF; zMvQocfJ2azen$tnrq=1K{^@cWgBuaYqAei%jtZ_bS^|0B5nQeKoz#t`GXrM^U_{wb zQL^A|*9Blq$=&Y=6%*Lm=IeKSiuJzZ05cu>V(L2zh?ClPZQ*xxs#@_ov+oF?CcMgK zPT!G4_1AsJB>U|Kb5Zpjk!GszcvMByV!xx&UFXm;c;3IGhYNH3{_`v+YO%R@ zXFxJcGRs1guvMR=p)4e;h<0QhDd+vh$9r*wZV#db)wK<1489`DfA(8j(|+I%^~h?T zJ1PwAyoh-n`R+<5#Z+M-+*o62>wFi>d7&s^ZRBr^Q@v^lWjL?dZ*)^*$(F_1z-;t2 zu$nhCX0&W{nG<93F>X&Mrf4xS7`w0vsP`KK={OoxKe~IUM8_OmNzDKN0L%aY002M$ zgQyw~Bv~3WMMIh(0E7@CF|&mbiZKicA_M>c$^ZZu005W~01%J>;zGES3QBg_#UyUv z?04vbVA_5DbykJ&7JF6QYRhJXV$!?Rv??$bER?ELETBTG5;?_upTMp%tU?OKP-_*s zq6p#LN1w>Z?p=UZe76ot73&`hOr}BFf!CZ9c)RR(nb`u8k=fmJC`GGKs3N4=R55jh z8byaIJppl5>);(QHer%_8UgJsWe#+s-0@1Vw_PJWum5!px9avo_NjGh|j4uDxDlm&_JPhM29)mSLzkX*VV*-HIu{ z=1dfoky+;qgW04?7G&6cnBSdD`(mgy77pL88$x#hlchG)TI+c?<~wMUEmu3z%m!N& z^Y{iCnCjAN&g-BwRAYP_m$Syq{t+1y^z zwtYbiwfmX`X;m#9gCdNh;{JqSCKS9&#Ofq3~FN6KxE>Pb6c|gHW6Jw@3Z0bns`f^`UNrKjS7g! zmLWn|Rj0Q6Ix^px z4P#6YZ)Jm9?6d`hEl$RkhI7kZ4NwRveA>FpaP~>tOVud8jY<}kRe{)=4!z=gsYt7| z!$xIb+lP&2w;_YWma`vrPhw6mA@&+|RBQyW%Xd7aWg7kpa^1C}sshr5_z>pPUITU# zAGUEvLil2DAZf<*hKf{f!K`_gl;P?YwDX{aQuFlLCn2=)QcO|GbOA$p9D=r{V1pB^ zRkhqO*)rbyiyn(TswE)R^4kRR^z2zv&3Hugr8ido1u`6$@1-xB3(-xApz{U)% zk5zVDgA7wzzYMqeLnQS0i9qW_@mJ>1wjYY^g;eiUy<1YK%G(9ze;AT~rht)^T3Knt zrsS20HX*sv3feqZ-3+64LvY(hYXBR9>@xlmf2!)L%EVr48v;Ft&V2Lb-J8iR(U|kRAY) zdu1Dn&8%Q}n49DN$#ju~oAZib)N9pv{Owqzb=jZhP4OTfZkctL!Q+B5Y}_yXZ+p4}wnuX>{mqF>S*vDo0g^TIRtNv*0YSheDi9MidNzCZKONh}FIMX;fWMz2m0QYi$pKSU3txU<|!MH_M z%Az**1hLXYH}&u=c$tZ_jfh)-Fv@#%Kj%kSb}>HagHLKWE_xxfT=+DWia@T73lULl zUNx(=nQ)3)=}jc7z_t0BdB_YaOt(YXxkwUfT30Ljj|DYUt8@8+iTt5 z&37?=8d&V}2EfT`zZ$7LJgLY9o*vLq9L$KEkhUx_r;0tOI&Kx1UrglOslsZjM`$@6 zD3D!1=#@1^cz_nRrc=t4`2o1kOe)jlYzkfJ#P4mBUlT8>`U6wPT`WSklXiz%B-Bak zaORl~&koonOJlRH6cZ>RwkZyH%#xka`pnBLxNqQFr<7M34THEj{zGADf_=R4jGSpQ z$Uoua9k3%vHqZ27+%gmKpc#F1(ijG6UB_8=&Ex%3+d;K+-Mw?5GXiSQByNIV$lLPy z^oIs!Td<=z9#~FX@zpEp*#gj7P|rUH9n_xK;$2K9};+nK-u{!0c2lLTAl# zzsnhY%VYvTTz;TBBazsDGBU$!971y^wiR>n*zdlT&S_0BAS@G%8G-a!arGHOifPO; zqi@5{t<`{P#R)c%j~I5Q9&b1eP1BLR|iNWI_ zw=wu$O=^>R9D^4e$_YNDnv>B8-q0We|KJ-OXK6zBGj0{DZ1^$|%is@*Z8`kq81F_s z{mY0sFayT%KQplAaGJ~GY$kfY-Zg@Nt_*!iXYDi6EF-#8@G1Bx>5`%q6GLn?_MA=H zWaTIZIwYLc8Hl5Elk;+z;wTu^gUNN2b(no}<15A~XHFlTudgZR6EUMswHX34AW!+E zY*vmUSR=5(6(NQ=3FneBOd7Qe?j;U=w5eCfls#A5D0IOio`6;doQr%0FDLvGU0WB< zQZE~(m%&_I4q|8Rwz{Ahy;0QU38+P7J04o|VL!x%=hh^d_T82ve5|?X!<$FNvzZf+2jHUEo$=2dGzwZN(5f04;Xo!F zaFEVnSU*@L#4Bw$fMMU9vR@!@k;4G$2>O;%M%b55*#d}3!@2Gi?-IN-Eb%}2n}-<@=26~TyCWwfe>^{ zIu|hqIwMod;7`U{C%C6G1(D4x1#XF-crDEz9B+9-_cLx3OEz;6sAc`fwIu#B6pIev zc%Z#bQ5X&v9e~k<@A}4BXDoyTb8bD{sSOe;s44JRhgV;CWAI-zY!8CcTHq_D$P8K6dE5 zf8=1`W%Mt)1e@f)jtoO=q$byL!A(*4Wt1$#4OGwI%aha>MrEC9o99-($K|jxSJwTev$TxGb6($Vv~|xZ9Xl?6}MW)Ovv^9(y>Gql9AF z{pc(^(PoH6`(DXH^xr}hviV=YBiJht8f$%e>4bxs{%`|EVK-JET#MT4~s+PG&r32{;S$3z6=4vN8%q5ka28 zBJ*TTx0rVtA8!cgt3)#Q$<&Iw$&hYZGNZ&6XxW(Wth2WaHEZF4{GbZv13YGv-|JTl z(bgoSwfvpf&+-aAMoYC``%3lrQ^pZE{%xiO@@7?}AzTrG5HB(Fh&XnlFr_D{lE${aBk;JdWQ`9k9To8#mO;h@G%&^Nb}SfwTN~z$is0s(pNyeDaQBrL&CPIrvtH^~1AfW??QduF_az@`akNRBq9? zg&)G5={2&seI?OK>j?yJ9_vQX@Pqx!$-Dn_!OC&i@iHsKkT&>&JN6nX9obg@E?=O4hOgF zGIU@5PsDA(aK|6b(iK*dUCgx|L)(X9Zf0z8f&GQ5Z5A^t5n&%wVakfVLUD7ws8b3nZF{Z*Mll8;=Ly8fTiyQ6`k`L%lG$C6qrysZ) z_pJ9uk3NS}Oru|Bi}(U_3XrScJlkDocW8f1$4kW{3HPV}9l3Ry8!zR+PGLNy1f4ab z{;hU`S#Bp`8&B>1nGVi~Sl0hp94~r6Jf+{giG@mEUuJe|OO!l(>*lo#$6Vop#-0;G zY*r(_Ma|*zI*PJy`X45f*ghW3>7aIDE1Jf$z8Omxao4(6LTuKC(_RRs=Zalpgh_@I zyW!S2`22G)E>@4T!A|7PU2eOm{rM6$eK0uQZ{)IYYv!rp@A!(d9M;-M&c0BhQ!|*h zWBcat;_7H2H619j@(tH6q3ki5xiT31+eVQb4}()gd?Sl9VLVKd43>EJq?A@iZI=Z8 zRCUG;j;_Hh41PN$=&a4o%D9aKLBDlrPw%T3AlB%v5P@6Jg->=obL;jyoK!x_Hq4mH z%M|i_@R}T0Q`XmCny`$o-}g;TxM8Y@vrmoNJl$Q zwCqH9BVhsAq;WI81h#A}igAQz)v22JMYm{XGdbu9(l8isCbSUdmNO)F!EVRd(F=p? z*4FNnIa3?ZquN{DSm`j0hGY?rvES0I459I+7(*WMcFGEh<*6fH|FQz7JhH8hGC2Gzvd0{k(+F=`L_hFMqXgW0;NCHdZ$l^KqSY#!={y#74)Lv#Hu4Hz7cyAzmNd zxv9E1=U`6UXQhoV;!WU7CgM@o`JQEGV*?--ZGKT6(J&5z{+R!y{m$0@Wn>TBtlmz5 ztF58NTaAg;o)F*ad93pg&i(8*3B<&0f-<*m2ZZed;&|9Q>i{o4?Y0m24cZ$_0tGgPykR@Ln_HRuoSFD6WOu{sXQ6>JzKuVle%ra#=7e=8 ze|M#@zb+?sAjn;NeRhmMSpyQ_`vRNKouogTHfV7he`Gf^2-p+MYx{Et zu861AsH{PJY`m7*gte{V{5J;w`^FbeBluq_wl*m;zN=iQ#{j>&ZDbTG6t7t27H~lR@STlFS2kJu)1vB5F2t3GS+dW% z*;2D-zbWUrw}DhEgANZNTcpxI1k?kNwm-+Y>6dCX-|0H0Gu30`#y9&5Wn3D*^t>pGeu}L|>oes*BGBKE#n{fuFTv*rORH_5x}yr@<`U zt=_|M=kZ`j+Lf8*mKJWk0V$;^f*mnb;EeZot_Ov7W}Y{KdB(uFr9x!_1`0XV5bLUeqUQf)Vhxk7hTv z;!4{5e0lF1KAMNtI$F4ev(5Ew5d=lBwv*3ZIbeI!d;*oGDyqq&7@~?%Fxdnaxgi!( ztRiT9TJjXTDG)z^o(FznWa7Q@aU-^t;c&8G#8Go@gCia6!Ff?nBm%=4yxjm8y>h>X zf`9n1{RPIZM}jE);Msnbv>Jv*Sd3k>J<$c==<$dD3swiG;@F5u3pHNhV0auL#s;?= zL)YXUXf;prqyeLrwd$7zR_L>RMmwxU86Ony5OAqX&7Khsu0xQ|+zL_Y_psE=#yH06 z3&fJ8?ICYUpGFQd^K_NI!Qb172j2)o=JLd5Dy*jA-qVpq!hMFaE`3A40$74Ks}tIZ zk50RZHo4FKiBE&pfI8B?X+c?L86tWk)&~5KX>jv*;GLP+ejj~1{j?*P>_d0U!4GMJ z7{SkfMw5X39*Fl6>&j;#8QHY`8fwL?vaq$XCdWxT(GP{21_ysZL$8-TZ|5MrLPfX= z+)RTH9Dn2W^eOPXpO}?B2{eZaaqN?xG)t2?Mi_)zQ8zEouJ;}ei`X))&Q8Bx=MC6< zR=VS@`Wfm5y2IivTd}r+JGxP!rW^-uO*iHk9RdFkG16HCjpx%5qxnwq z=Q8hho~0$7=R{)Iv>N3N`x`Pl^LC%x-j7K|r|6GhR)<0N*`slDS=?oJ!V`cQJEiM` zaQ0d=l!b2m3<(94#K4$ii7;Yp z?&0FA89dmx84Hh0HxjkGU3Nsi1FAF<@K>t!8Q1W>(g@R-GKqp5KD(@p@Xwy5lkaW8 zi}rA4bet(!Ez%Yg!VRvJGGkMVsomY}C+^xF#~R7gTT+9n9iRIK z&ynGpl7c!4)^1s`abnjbw?85F_%0Z~&T3p|E2kTGia3ApGxpl88_te#fY&$m zZo7JHPeU;0HHD8K{u2*g*{he@p(1AWf0k02)i~^vF0|8&zOwr}rh3!Y@&F5Gnr4&@ z3z6OEa^G}7DXo@$ik!t zR?S2+)-r9CvPYy^YNFAV$WvF#FeAER!m}ZU)5Y&>jTq)ZKmIh{U^lKZ3vM6jeUdQY zocICV9RcUDf{gqaAU+GgSTmBl`x#)&>vZgjzqlcUzP=vY7q#eE!_4ALo_A+Gq?n_?jO{yc?{pM?fy3VLsvrd}y^?6Sx7| zv3>8Wt|N^2gek@rZXZ-?_xx!0v1s8@f9vg=W5Db(KGO%+@#gQh(q2!K1Dst(0o~M} z@yMyHa8y%lcpPja+8stO@?x17Y|~+V``H7<6t`|R#xJLftSDH?33g&?n?NW=3E7`; zSDsu}&12uhcK~-q?WO_5yMZ4OYc^>jrzQfk%wA*aK4)5@Z8yAdR|idpVH##t8vvu=c90Imn4(7rEzC}ALhm7066DA6n(KyP*X1&Cy=G$nWAcHryyRe)R#8qS zoSh{tB2R99Rm@H5+Q8BzoXuL={sv34ZUZVLksZYgZrU%&rz zlD|V8q3!YrCpVe?~v8Go5r9v*enqV+&+6hcN`Y+RN0DbsBOUWkx#B1`!!j1zj zZo0L(lPUr3pv;~v6$LTH*#2GBY2gS%x}qTOB&8P+0a>CL~ra2*qLZbT=K2T zTec@(;v>5-?gL(u?ihm}&#u?|DH4a)>YUo3Ej9?nva4aL-sSqHr*ulYG0Z@XPQTxvBDQJ5D|S+yT6n}f z&7LT2t9fgv>s5CT80>8B`98-kWZ`;f5Q<(MBu$zr<>+a-;C_K?iLa zP!lns5W9x8SCSex_ezIwvEn`y-2=OR za|-lkhn849muF6xUH%|;>E@oT4P4P_WVWRhn+n;`u2dSNhqfp4Hb+}hC<|vIvsN0a z<1^wd-@1XT#ENsa*aI@yH4?7ltRuQ;pMF~rD2?F@OlF^e6>t}ayZKQ+baN@zbh zPgbADLcQ=u`@|AqE*QLm2VjApNct?xFo7y=d-7Oy0M!vWfU*Q%1^`9Q$x`x}1;+x% zF5d}Nb|Z7ULhZVtK(M~>Ny~%^at5@MoSnRg@)&KR%ud3bqJe$Ci=CwR2)O-s;tq2I zk_;8#Bt3$D(kc-$Tf^`8nOT46OOplZP)aa`N>-VxL9=j8s2sB%(F6H^ zMw@UI0_XU_8JIQbUlMU~0)?FG8ywtWv!*Z*9}x6@=nA&X0Q#f%Xm>I(o{`z`znNy) zXmEQ#i}H4skc`gwqiK3-Ms8~FS`{?8-6R_Zt2ZU!VE0*5IisDJ zsoKnW-m2&3!{{A;bhOhmM0mI6W~X1t6V+fB$kyhy8G1!dS|@~~M7aI!i=Er5HRMIS zbrma&pqA!bg9EtW#)||!0ETIb3h3ANf%*j&b%uZ1Cw@N@v9cFeyT|I0;mzNI_*p@% zJ8hgBICE03!b7&ziC)obTzBw>2=XpFPIujH?RNCctYcwE2iBSI=4k+QMb9*piTBU} z2}RQToBhQ~gUE}xw{BU5I>C=N>6|$-Jkyd;!}*Zz7gf!=xf&CPKQ|I9O|V@iRJ-&9 zm*$Ed!5>zcq33&78yRu>?^G{u?I%{QApeS=0LMu~K)sd0`)|VX9xY)v+-xheXU&*y z!h7PLf@&!(CLy+dFx&R7eeZU)WwGgBho*_9XEfA#c+2Ep!)W^!xQL*7D*|77sLu9{ z69RzrwAgxF&vMO#tsA(WuwF-5TsSo9yk3vs4A7aaj&}-cF0LFeII=>Cr(ZDBdoa&j zDtFG^H!8LO1ql>^bOrvWA(Z$PY z)W3GS6#*&J31@;fbFnC8@L5Tb~Cp-Q)|j4twHW#H2l`Yo~R5MEa@@kLpCu7H=# zy*%wPF?CgOCq}q`#nrO9a0Ep~{Q}j+;)$dS_a3ogHEkD!P&L`>JQuo=AywhzzPu9QgfrqB^5OrMXhcKbK%(u6Ln0qu25s& zUCl$|3fY`jqwIq!XK5eLxHDTWvYKwA()-7831}39FF@xmw7weJHnPp=_2n=)k7n5N z+n+|YJi0Vg>#a%XD~=+M6oVVO#_c&|CceID>M|fNkXq)L7a!-17h34D@x@i~~h5Sdb50w)l(x{)FaLAbMt+e5D%s?Wk9Z6U4; zSEc#G`@!}4n+Z*|#WZ3)CLSv*b-b_(YdK@RUoIkBAQvBarxQQN15uft(*FnvZvRC_3mO2?@8U;7Me3bg=A2JwL}hyX zq?%-0GZvOE9xe2qaz<$AF;D276_&N(aU`rLv~Qm+$e~#?K&%Qq(PN9PgNwjzuh-x! zXCi{S7f9^L5ZZgJI6u-iV_2a5>z(nUmF-mm$RB-97zq96?EKy{JX97IW$T>%yABB) zlI=2qX3AqPeP$xV(k9M&W87_N3Xn>eRm}pY2P6-Y(VHvGGmtGsHiTU9y=xu!uGNEr zTapX}6Hjf(AXYdb{ek5?{Yuf#4X=@3?b1(;3Xg`Y!M0dMN!&22aeCHvTS}Cl@kfLz)NNNscgjBB_ZV(8#8>;J(t=*QoSm37SnUv-}Jl?_Zw3yjqv)eyo3KNa^i zF2;W@8*<5m^>>o~bhn@l3d^-Ia=Fv3K%{nU)2(&vcU~eL|L7XBx#<#KG0~4u0*sJ= z99^2avK64PSGvcyXz9Q0g{I-dL(KrVud3MGiZE8A3$sQ)8&9v?p+_0G7PrlpifS_A zSYsOtl@NI%J zQLucLkRmH%dH#*AgfW|VPJte&b*PY#GF=IXFW?0Xw3eK`ey_TnFqm|e@z=X0uf{OW zvdK~n53QKy2!Ci0c}2Ld)p`g%g4BIOar&{OW-p2tr;EwhiGLPKRW@EP_=Zat7kIeR z^9iteOgEOgBZJZfh@{bFA$_4eYyexo*IQwJUA$dGB_8hh8Hec~R>No#n>?8uwepW&1y-$uoi^!pq~N;|r62DB+&~s=-wIa{mPnVS zPlK>mzAY(y@H(JaoQB=hW;Hu!H1+r~YS?FKW+N|4_d^M>%2|3yQT}Gu2T!Yyy|b0^ zB=mNsm(nR4!w4NKF21dqmOl@ym2^F1QwM?*+YO3h5u%0jW$di$a^=-Fws)=-D5kPR zY3mR-$cp_%WOk&%h6Gz9#U_Z~F-n6CIqY_hU1F|bl*bli*yC1D0~yn8*e%eBVZ$|= zqT0ikgsEa-Da>UQY?@qhtWqfm&|P4Oru6LtwF?jdWfI2_m=3$V&H#}}LsZsbIjhLM zk*ZiM28KlR%>^$gc=Oo76k)gA)krtu0Yo2$F;Mc-^~zw5u)8=FEHuBpvqi!fwUKy+ zVLn=0wF$g4*?k>Dw#kxlap(#0iQ^Bv*0)4=uXgM%3PQ`U& z=RgM2T_%W<^(wgvcdgr)NF#9$bw+qTsvH^&;IZ|xbF;5VU+!t^WWVRUBR=2CCA|3OTMc!IV|7Sp@PZc z*p^zDLgtx1+BzDhlG{>f<lR@MNgJRsMW;$*r8piG+9a2kJ?=b*w?}d~U^&Tbo-R&WYDi z?mbkrv&Ppvdf`wTlit0T=`CJFQ?mb{o@*wZk5?Qy%xx5G?V=(vn>MFizcg3lW;SMF z`Ic_e?nD^QH{LiF*_{S>uyQ}u?drf))Qm6{;cA^LDtR{iiPnGa%Q+J)sC|xvLA}VB920_)#AaI@}{q)V6fpdWf_uRJ)y8$?0*FU%TZV{pqNrV_;hgbE6kF4W1f>DT?IgT@OKXAwd zWz$UEA%Myng+*BIUAT#u-&A^61_FD}*71C-VaUW8ZbSMB)F!ciw~ckMM3fCh zu#d>=3gQNh&w|Ag)^0KYBQ$#(==eNTiYlQVk>3Y^7L%F`zS52JF!kpb9$WbynUW== zD6%vc^}&udxCyMUr-$Rv;EOG}FR8{Ad)e++RM6-|tAnMXon2c}9Q_>!yBOobFny9e z;l%gB9vMr|h;yoC=B9Ecs$OnhG_o#HlSYg3%#7q@pWAqHzkE3Jv;JQ-D}OUE;YG}q z=(Igy-~J{)?8-rk_fca{nG!JjDl!*{kkA(14Q%AdXxoz&*zi^}bCiuAlW0WGk&{pI zaARS>7e42y`4~Sg@nSO^oP!;#dsnBM=9aod*S)*_I@;rHu4WoX;yh?mm_esR68%{l z4*bdcMC}*m#HmuycUE_?SEY#jEM^OZ-djpoS5DCxNNokxPB}FB)Z#1)$R|I#LB@0 zK$C}+MVkC*^)jCVvNQymwjro8rH^*Tr#@OGTu1H`iwy+^7cce9X4jQE>)zAd-2naP zAz#a(%6}g1%PUJC+PW=h57i{}K<*F+RAkK%49sFtQT!s5+_+7}!$dIFxr4Cc)-MU2 zGm6j;P`qFSQA!(ci&gCo)yxq)i8*!bR5$d56>}qF(oIgkj&L-R)9jZ9J_z* zf!irCGOQ=@DhY1gP@eFhrqP6n7%w`IQ$T_IG^aXR$YvM&`iAz`Rq85=cV_}v&Xm4< zYw0g?r}{Q7vc!6+zt}3Ph?|=0%^;I^9vRlkBBAwCKOV;^P*WPu!z8w|))S242;TDC z%$3HOH}J^2NQFfth=bGOcHoJ3=1Q$JlAScvkz=1KQN{pQ8EC3{=Mn1FuR*VK)?Vzc zm!A)8p8z5LDiTIcfQKgjy&3mKj`D3Os4i=j%*pSg3j6j7wocL$-$B#WT#(B+Zxl`i!sC`PSx zzpP}5+xUG8)H%=4fra42x;^$6fMjkif#{U4#m?-N(K%zVRnWycj+~-Na=ZwMiusNc z`q%jC>IprlB^^iu0Z1=|Ba*pd~#x+JH%^W!Ad%1K`HfW)gBE1d zU!btQsffbk6dqdX;>i-$fy?I=Fhm5|#^9$_s@QssEr>iOvM}i45!r z*nuTV_;@LTc{`XMtUVan48qdr(JaHc5FN5Rz;)2!rgD>uyk6S0pp?)XN+TaZWNy-d zR=DbctCS4<5kA&YiKxPYILcPj<1ZY?15t({e_ZL-AXtEW7X#a60;NK61sA3FO5N4+ zEkGY>Di1jLu#o_BF|~BjjI8cdAP*`z2tr0#A!0&{FNmD|tP5az2A7qWuyfZN-KXd| zBp;xa!SJcBppOvEaB>6KL5PT|O~>=XQ?@DGAF$khX*tQEFHfFh(3p6N=$UkkG3fvg zTx7GSTXZpXLL#NJEis*ZKhtf(rS}y^4wdmiW4jRRlA7eD2ci6by5xA;wJvEA1YGL( z4c9PEvJzZ)kGzvkE|qGQcO{42>_$CDM%Vp_n!LZA10dpmojF`gPSbP?)tg=hOdReP zil)_Y!Gu-m)^aZ0`m)5=iQY!9hKDZX=3E4$rPFfyIo;D`I%iW|(8J60_qDk+g;r5N zNc+hQ6<5%u;s^Gem}o{fnZRZUoaF8f3YX{yFpV6p&h!C>1|;an2qeOQ{7FUcq3i2n zQU{djvI}WR2E~y!ZlFNC-`0yU-YcyAu0mtnxH#BpJ6{!+lnrh@5pJ1ubqC;qpwsk7m;2rVr^T&WnL||BN)(N(bY0D zk94SEHt}Z|AH@_D-(eg_+4aFZ{)GqP=`$-5=a~m39fqHy=5CaK^>{-Jn+3h@HiIMc z1hM&Td<8Qzob(g)YT7&v1b*$x+5XIX*_dU?%*=z7fSG>=EP-eK8HxlC3Mp1lAcvp* zfsOtE!Eare9g3fp8&B_28{sz01tU^|3!(x=k6coLxurx7$nd=wbc4Sizqpapxt!gl z6M0LAzqHs_bGi{pCxOQfW*!S8EI%U>{Dy&E1j35+7a=IUv>|F1LFnOQ1N|ZdrI(M* z^zo6K{uBr6EQ099XBc$jGo0J&*yy3XT%$fUFc02coni*Za*L7V!1)|#XD0dCq2K0b~a%~_i_02W$xk}h%X7Ejw*%VuK8WG- zSPlG4(NARUoy2;BIqdma0X-ia!XHfZH@D5t-O}@?lK1(Sep=t?SrdLnrk^M`^Kdid zP5fpuZpLrC`NkUs^LazN?*YJXn)2;?P{Mc{1HGkC?$1H;e*TT^RPPrrc^fp`X+@B=7o%m7-pn878&^^1m9nWug3 zM=E6c2@BNh%ykelhmbPJ%zL#t8^k}9;30GcZQVmOcUnj3e6rc`=r&FCDudTrK)MH{ zjPB+>h2N;wZgt&Zammhis=I@TR4b3_x$J=28ExSm#@N6%BN{vi>A#5(57wBQARD;F z{5PpcX>`cfY@?VIx-jZ3n7=&+OMcWECw|vj zb@5Fu@C~Q|GSLiq5UO}CFV)9EEpg@qNlcf;hx4!q3i-4bKBWuLhRRv!es?*#aU#}T2O8d&Uaa`Qs%mN5WOLH@G>+3Wh7I=KhjSDiRRMN=40 zfeSB3@Ph4ieb|PEng`;u7lKS5GE3Ke!#|I*m*Em@_CkFh76yr;#H{8hLRvYxVw7Ue zk5ta!7qvzJ!hYlsxB-&0DV@zapLc1i9Eb`qBGc8yYT-W!tcCwR#C`q=Aouw{^R@N3 zfnLQRhhUG)ZM~F9A67Y8hRfDz_?W``|D{GVH zx^h9*!t_gH5G()%nECB6&A`}vhs%bg)mg!R##{%`ZOK=ra0uv(Sv5!yJ4oHkP0Rx9 zHPbYFH=@sc|0gZ)G(?Hdw#l()gS^C|M7g8zBeU+e!wj3Ewb$VAG39#;XvAj%IIC@W z;hY$Idd5r>Jo9)L`w)q@eB01a?wV`6I*)@%2B&k`{{XJO#@l`)+9AzKaE|fk0(*Sw zA2gIcudja$`xgoNuZoP9!!8ykLfe3Kamw2+_a@PPFkwbOW$!NF90dJpUo;qoi3*8t z+4W%VaHAfBdzfLR@H*5?%1=;_bjln?XX>p;ODk=t;eEE78s})c+1Gwt!m>Zki^CRZ zP)DvYJw-ZVb*A7KYM!{P=;yHi>A~LY+}qoF8|#>$){_t`W*c|23zXE;@CSNCoqRuv zR1LeCT%?0QnI819gUq;0qt4p{ilQc-;sMg1bfvy7Y0;*1BeWm&`@c&N94()2GHb&EB>LEOOH88|E`^Cn+N@J)(MbzP;omLPW}bZ8F~o^m zfH4U@rMlzpEpu)V5Oq~w0Pwp;6X*dW$AWO7z z-Of^Ew7-MXbkOA=n>an>9U6&u4J3h#Mxx0waa1;Y6D_XPUk!j}! z?vlHU2orW#hnW&BR5d4n$f(ActD)P{2WAcjumhR973KvLm0ZiPtpm5580Sn`i*~L) z4yNoOb5E<-5UMnC-rQ8kx+_rjZ(mpv(89%JXKO}3{=0Nm0nlh>OcN2OFryQd;xw}R z4S3+MBS!1btt=(Gh zc7~i)GZF){M2%J*5F+NmE@^qBLdPJ@#>)oK^b*KqHY*OUX$m2x&e*Cxq}AV#vrNHI z{<(7cBT$^hYrIe0%@MUIjh_9V;CT0lx+EXSZyOKkta^cD?SvjY{N_b@4p?@t!JZ~S z7tN;0`+(Bo2$(y_v&zdxJvj?KSLB3WO4>E>`r|9-*&hoBpZyV7kLy1bdG}Om#jHen z9ON&!4LyGy1e5iG_9g%s1=&`R_&vxYJ3OI&7VWGp7f7A`2|v-xkOoWgfc2XX!yWL( z<?CUZ2F*4TOwb zd~*PU;_1vZ7^h53zV@r!Ui(d$sUdW2kj zZcvp?Da)8GkZz^IzYw6_lN-{20^mNoOee==8JgJLu-*kg2Pg3_Epyy?EzF%kv8*q< zx!W6Bkh48$$c@!pBu=Ob(Z3r40ZtoXo&-8SU_^h<&G_`fMis$8lyId$z|C0Z33U38 zW!mgIh-Gvj{~ve%`eqYX8Vc8GrdC_bW5vb_55h)5rY_!~%^9rALArAcwmj|3 zmIPx8kELz7vi?n|Fz`@3&{38h@WsQo58HNy01HA2vlsgPGc8nN8DI&b){{dOtr(!I zjAOY#=K69-SpN?oCdd%}a*MzB8w`*ZXtgc1V$A$d*#1L%C(?TR z26ZJD0|}*q6|A5<{D=SS&zD?PW+w<&JwTDcNROF4kQ-I;enZJ?Koh^?`ZzF+L}@67 z>5W3c_pueh6Zbxk5-7f_p3H-+X0o`7XnXXDZ-c zBsjU)MQj1vj5-)J_ba#dZKCj$9dL_Rul`}Tdl%)EeHZU_tl@uLztvm~;j)xnRBVOI z-~!}my^2e1N_nS#@`w?9R@BVHs^ zGqQKkHeR6`k?~~m&+XYd8gOP&QFeJgCuztWZ-g_6K7l70{1#eq;cpKAowj%}gRygr z1iwLp;A5`^K4yG5feas&0Qb_xG`MV!%?Gr9U z7t6Cqf;`263m!2*$?h|Tt4eGhydZZ`>Ajoa@>n8S2S0HP0*YXdmS$WadB4E!VWQsb zaRIRBY&-<_F6te?w$Mc~+k9cpxwOC-4&5xm8;XCw=w!`gQH(Ten2T|88}}!*jfzT( zXFvJ(uAoIHUS!y%gYYqfzGtRYjG!9xZafM`@6b9{**`J*?p)90$Y!WXubX1e;Eui^XS;_2(oP*}_-3Z8-=iPH2JcvR2;Ed#Zf2P+YL8)}KbSzGqsA1eZ}IbbJN zfh7xkV3Ah{oImN=%^>pxpIn@o`d{a6;3b;m#Z(V63M4ecS45lRv$DgN1V$dM(rCRN zcF@G*e(xcZ(oiiDcF|&6-2$FLo59^#GAm&h_FF6L{rQBu+ze1eifLT6{LF(aqt#Ov zI2fqQ>`87CV^2%wmTHPSVOZk)c2Q?qd}7}TJ+E`z4f+;QpcGa8t8IG@(4ne9L^*i7R4)&8$mjAS#OJf zO|&d5+$$_sMB%aHd98%#YpERn3z{3kiMWZ&$J*V&pZdX!mM!eaj2iT2u59+Ph=}D5 zK~Otnn(&KUw3`qoxrOA)hubW`YFMJj!CV8lY?ehr-(p%UyWHRHV$KEDn41bOx^Rr% zt)nqD0<(}7*!1-d7oAgnS@E`L@&e&wNUm!XEU(3YZf1z?Gk%>F0wBZ5_au`*{$^4| zAxzPmpy&*TA_c*@C5iUz_Y`t?$99tNuLutV{Sf$@kk2Mc)Y(SF7fRY}2lQU4 zKU0OZDUAoU2h0Z~^wCLeE^l@1Y+YU#Ylbew!kwZt0 z3pyi@JYNX9{He5&FmKxPSwi8v!x`c^8$o$aOLPv4LH=j!(ICiK1%pyVtfE-52Ez2$ z9YXv;tNJF!Z1t|)OY=ZA3tcMod2ITS`4AWfRsxB>l^r+}x>@dB*f4BvxC0RUWU@;@ z2XI<7L8q@-Z1Z-Cj_=KE><2SA8pZ--Kv?lLDN6urz?fUI3DBS&5=hktSgp4gRUE^! zi>w-D274~9o$85|kwOulc(4s@d1=G>1NR3F9^(vIzAS4VwV$wZiu8xV;LgK!vIlL= z87tPj%hsZSt9_M5lTV;hN8WC*{8bfmU;EikM#JKopRN-&|3Q1lpYKX73(UTQgWNPb-7FS+ngK;nYTV;Tg;%3PVWWXMe6r(T8%Q7{hh;rmGaYeH0R&d zp@Q1W;{+~WF!%AZyTH`xi5#mh0afT@-6e?PB^+_cY3MO|>!N^V1UO zR&*_$!BH-$1I~2Wy(QLFXG~nr+dWXD&E^_fYQ&(#wN(jKI4~VS_QEy) zt`Ukm-h8#(rN9eo@iLqySrt}aC3Ml+qc~D_QE6*VRW(*GEmzqHwBQr7>C$fs|2>L7Z|(1dqs0>| z)%Md)Rx;@d&eJ-8<*!w*hpaeD5p78PhTk{ z?mWDfVeRh}aVwU1`6n4DZ6b8^Z1rPEOX^C#Kz+T3ur7#6tWoB(Z|;ILDpq3i@3Nq> zBh2^ateHJP4OUJIc==S}bAKA*Pnp*WDI$Q(DMtiVk${)y+1wiK2N{5C^-G&cBygzr zZW#q2X7QaOvZ`bvb2~9*UK(pw9Vx@6F+z_+--lp6f*vQ8{lm&>(9a2Fy9;kxWg{)o z*~W?;xLNW|+mfEGUQ$?+hs(-GL?1C~-J1+3^ z%|PZ+`$Yk4oJwzyQS)Q`gv%X<3YTm71>Pz^bPkJ1en*I=jV01UR?=Kj2juBdNiN=7 zNL*v~x1EeOn}fJHXzd8|)p^W@qGT|jK|Rc-Fc#pU_Cu&+6!!K^Hyns;Y>7@~@yS=I zwwL~~%G8ollS^Pu$KAKMR;|WzS^hq{d(xWo?Z%+5qsxbB&7-ytcn8+>_nS4VgSZ>< zrL1gq&L2Ot_2?cenKYIJx^x|0cPy@6qB0r4^{(BE#+qBM3tAstJ}o)cTxHKryl@Vz zX`d4;z5EmjOkKi%zu`JrM{D8~4y95D_a&nl0p>vKCC zZ8m4X>Nl(|75X2e6|fc%^O;@4u<8H$RH2e(LAJYaN~>JAOK0)tqqZj`VcBy51H)}c2F*_+a>O_vO7ubux5%e?gVGs6(esEKNi_5!`g24u zY$&8dFyKS1>GP2xnO{gH4Dq&hUxlxLl)doemJrTqEUJLx$Cw#pwEYPr=%tZ@k}p=t zRZ2|)n>q^rZTvHg>uMkt6OgPAz5vX0c=zH+irl&-P1qqf+AX+V$gg||-J9=%w_eMt zEd#jlmYQ_SEE!i&<8k@TeuF&4ur14>EJ|=gR7tK1alXE4Ktb|zfzLtH1%+Lv<#Rq@Hks|XObopO^Z zs-$#wsQGZpQmS^+hPm|eM_430TaAXTDAlUYD~%?Rz@JVBcgHpS#?`Fj2&MOkw|e`< z29<6%`e{c_@LP4HV#dx^&!)gG^%-xPn^v=FjEO4xbbM}CQ)aP*@22ADq^Kx08dxmOGxR7gy=gRoMj015i3gtq9w<($(p<8a0aLD2ssTDO8V@uNaBg~20O#xa9&gLpym~67-zD5PGW_~4l(YuG(_j) zRG$zWZ4MJB2&?_^gGyfBs_TM|upXN}Vs3|L$F`TALraU$a#D*+ zerVItvsIm!)L5KlyvsIRX-g}jl$V@S1BMW_{g}!(SS$Yr5?eFleM{99%z(fwOAj zNAv=S)mBfnXP$0C+|}JNuN$xBC`+l=gU*NP^qFG9HmnEBy=ufQq1I@OiP~a{LhIuW zE?>?j^K2a?#c&R_)L5LAuv9MPblTESKa#dHqoB{63F9kgT6k|9QKZ;J0;_a>eMDA!nHr}6sU1{12f2#59nU5xXTyP_HQ=y(0$SE5ym)_b z$mJ2)!w0~C;W%sedF7Z20Qk_r=h*`)06vfSJSyQ)36Eguo}j;{*GG3tS`jK2p>FY& z=D8*F$bdg4UEaI#=;S+&+B-<+qkrvR{?3}uY&$g^>!fn8*C}GzM(-}SXmws1j>G4d z-my7IA4dIjcxF0Y-y6^_1>`*2-`OmNfaFt8QJgvp7p>mZ$1GkvX!=q!CTR1daW*rw zs7gG@{CQ2?Klk3jB&6U=UB-Z)kD$I{~Wg^pt3P|p+O?JiHiz# z>ICN-!Oe8MNqxsJ+2(=^Ba#8>Tplk#0)N|-mj&x}@y)lu@iWR&()%K)Y zaOIcONXxI;9L*^+l7b-~J7U>-QWQsoM}stzL6kyxxdSocs0vc7eZh}h>`ri~U2;>Q z?kox4gtc7)H;1n}AImmQlVb<2#~o1ZP%}_CU@L7mU}zP$t2Uljp9y=531z(Y_(l`; z1I(h(%o^dFZs1U}A}GyM$b5JJnF|y-{R5VS6D+_u8>X4WlMHF)Cmo|< zfpQ2DVT}lJC`TzB;3#+ailTjhV6i3JDx*S;@l<)Dp)g1+Gu1s-o_b1Cbj}ngl{?LBn%w%_#3S!)<()^ zZ!v;yy7r{@WGmuPr>Gw(woJ-P>*)pyMPzxLk)VKs-NA#%%Q$wHHIpjSl4;_dyx=Gk zCTZK3Sd=@Q-WI$UuwHV2(W#zpyscMLD#e0HnQ6;3k#XWbc&VRmz@Bcro^ZIHaI~Iq zu%2)bxwv%P2b_Y!Jq3k$#}pJ=IEANB%M>lj??jQ1LOoG`@>#LSqIyp}Xn=y`f3{eU z7DOnz`XS<%Dw9FrPe<>Tp^*(Jwv#8vt9nDp%%K{=pGqBPbdC0aYKDSy0J*M6m-WK( z8kj+AL~!)I@|b-B44cxZ{g=;c!cZvNXShseVM1GT#;)RX#n1L-%!`JtRMgU@A4610 zA|_rSOFz-NOE{X~#YJecs!oE+EV1@Iel&MaTI>f@9uQC~2R+0;H% z)%23gUt@UwgtGmHPg^pdb^}}`R}q6JALWNbO;0hdg3?(Mcf$)*>UjzG?blWR9FtYT zI(hZGNh^&y@9BVb<9d&hRK7oN+Dq6t4f;P}Zs+#lelWuq|{^&sK})w?VXLhYlV5(aARb?*FdLA@-<)#gwI^g5Bo z;+YQWBqpd-yp)PejV7{I0dr_Xg|^SmB-eW5G~`x|WU4#?P+?l30f0?PfFX94-s{{^ zfl^LrK>P?(CD-8fwBt$vEf|2plnsPQHmo2C*f@L>7Ii44!}YZ11s|Jw5=V;!J3yrB zCmgV+S`ggDLIn_3%IOD{GevgNA)npCh5eEW^oNDgdg74^k$SOX!PBKG4nU}YGk|ft z_96$aoh72enU=DE1aW66@dKW+l-7XPIl@)^L)3h{lI4!LScwAPP6fQGj&5*}8{j{_ zE3i-@98JfId7?Y|V?{vd=S_=i1#HyfPmh`afYhz}ahB}?x5KKB+hbQf& z-=7YBSg7Doqx~4fT>>C!Db3YLiS#QbtwgEqGb9|XhFf%{Ay>3p`~2udn>5Lh6PR|? zt2R;<8?k&zLcRMLl;Ni{gbe@DiQH*dwaPaPOx$MAZwC83c@)`lMYda4W%isKC~2Vv zbXiNpd$~k5)RGo@k9zdX%(m@ z-^keX&-3Ufx1-aB&wKB&U_}I>*mBlbH*4@1g?;3pxg*Q_By*iwbxt%nXBYyGheO3j zxD!MIv%wJFsGut0u-DISg8X~aZD{f@2ep430kSA!QwPW$rbJ22d&P^fozp0xXj(ut zuN`)>jd-)&t6&9_Q6_I;j#MSpjt;@IY-6Y~Bor>@&4U%e40SL@yrpDOg1*dF^cUC^ z&I#Qvyj^aD%gv_OL^#+LDR(%%pR^d6d(=n&RIm(fa?RGLMXLA;krrm1Vo5qT6UOi= z6wEPblRitruOTlZRAM@hAr;6ltqFpngu`W<5lY2UN<|9JhjSVeL}>vlv8X7l22cL` zj`?6Iz+lK~Zj)kt?GPqSVQzcwIoJl4EN^*7iqs905+SQOZ(Z<81ygUDfnL@#(_#fqlRS_DJyd3rPIus*G)Li|80w*hQw@7CkJnDe8-9=4 zaZBmLKn#kTO8ttEDQ9pF7RzmJ%!y# zop?Ul9`ivD4>{s|3o8PP+L5W}<3e2Esg$K1R+ooG^YoIT!88yglYilB9&33Z`N-h_x$ zyB|&4qC+fOUm9Z&EI@!71A>1m-fgidO@2TM?+s@_V-Ph)(Wp^9ey80mBKa8Cz|a%fBe{U=XT zq4PBH8I?ov@HF7sTY%uv`Ak^W0G5P1t(*p@phIJ&TH^$d@9RNSrgCcf0icGuK+BmH zFqgyHo_cjI!zmS+CoLo4U{&WVQ#)QF!>hy=K|KZYRd+K`lNp%Ns`=H$-@_clQeX*< z2_91x5J`Orvw(YB0kcZsaR zK^Gi*6*W+DdJgHyFlEPyj2R}fC-kaLO@dA(PGDfKZS!&H1J!)SHRS@FfIpt1!(4YAg;>`MJ$&)0f6ykdbQFJ#(; zD0KAzULUExWj?fZ@ND|>O;8E{Ja?F75w#()ep4WstEK%ck9Lm7?paWMb|`oAaiuk9 zm&=3Jjxe8}H}4a*WuSpi3wP$xk{YQ(yJrhQ(Arl%Ec}<1ZP1x3%6ON}xYB!Av@Vh z;KolFR}jx~8AKXyPT|6!#rGKXA#*)H8wQjkJS~?+jLFVyjuka;=TX@vP{4Uu)8AJL zgL@8_$q2M~RwrtQluM|~dv|=o<)MBsPbkL(bqC8Lk$`2~fEja5!6`slgo(%;m5byQ zv-b#0z{9D|p9x<(QH4L{J0)7D0iOQM+v&h!nm%cT6Au=GI3oT_I2&vrgeE5(hgGS(Vptp+i zZ)U|-%jHJfBfj>Ty<;axTTwQKs{?aZTyWJ^09f(`Ms?&ZBF0r?%)ZsL!W3&~sLv`K znp1!sJ2IzNwViJG5Wr2C+o2(V7XQ8IDjrT#M&=h~aYeZ>1~Q0y3>ULplPX{ox_D_V zTr7}&%-X4FLAR7s6s`V5&SoNk5-ygGH-Lpb;#C#FD-!U`-#C8iIo)W8`UbJ0{qP^1 zVtT7WW~oz@tcM{FDXOgDX}CWKu1zeZD{q;91SNP!H!@? zu>E{hXW$i`&lpU^FZ7&>qKRr|2}C3gkuXGp1(weu#8P2(QaJt-sY8mROlKRFi0acLtMtlH-L-gmh3HeGfy*_pp;h$$KYr@ z0ai_#VQT-&aJO^mF1e}h*>8#2vV?$l7IO)Ua^Z@O&jnyt=~eY#kxDSffrzCLow?DM ztnmbS-;^t>YMU&Nwx+J+Dc7RVBtMWw#Q`;N#L1mClSGI+&Rf~0Sx8MPg9(4UG#}Ab z52VlIx6^^6bHt`MT0I0*8@+^U44E(;PlL6xD4PLdbw;chAcD)PN;$bz>mK(kUR5`?``(vfa(i0R*KgrO@f8HL+Hy+OLGV?RwaO z&SacodiFc0Y*ZcKOEczF$KznM|G!GfRg_fABmH7XOJ`K&JM)2t`iAD(M#SSYsxPu6 z%P@n+&;!1p#LKX3+nl4uoo7$=eND(t=o16ly)7q3whp zHUY*w>i9mCY~!-Jhgu||mFtPccyP`;KOY>H9po*7q_)m`9Kv)tQd!7@!XW~KP23Fu zkzD(2y=qxryK!;|8{D2W=o5P+zs#Ta2Y(Qf3%`jafxW#=bY|0%uDJ=-5NT;@SfQ!? z9&cBM2AT|O%0aCcGqiLl?NjJ+Mkr$Nmrn4h)yB3`Wj}oM?Kh) zlG)~MwDOBouw@`tW8f8EsO5^3u?w#gQPekmvP9m6QfPhLkx)!m4w3~?p(reYfQI-D zPEOFde{M-XvYk(IE}G#83oj~+3HjyT2%AQ)0_~WSvt)qea#+&LoBj9}AD8Z26SXVV759k|J3CaUqw5o|90mscf&+RP;#@#*b*!Wo*}ezKux#oIQW^l2(29(< z!3Qf1o<0@V4)=zZVw^s~6lLw9#B3ON06S?io3wZv&{jgMI-%C6#U^YH7SwqKZek)t zr;wZPN9*pZ36JSYy zm_h&b$?tHREB#JMxg88p4Lcv%GbBWul9eF8ya;<>%M@ zy<76m{ZLC`Egv>w!-`56H+K^ZZ9n@3FHVtb6@ZqwC7HBo#rl0iErrgv2kN0E&QKbJzj^!BNgZDd8Ek4uBv8gU~1x1_#5yzzA?C z2n>URz0c!vv0pZ~KK`K}SKp}^LRDd?}&Zw!u$EnMFo{vv@)a5weZ+|rMF_0=zub_j%D~g}@CXdK7nLl{lZ}yO^yBC6NP^==ym{1K(oKqhq?4_2=3%V@{5l1JdDJA=bv3Y>v0^p z8}}gy#)(|i!2C6TRJbwv6Yu16d||kZ@oMw9sL{X4YcJtC{Wp(-DKhWqDU}a-=YV*VXxmM5aeJeijq@K3@uj!JeS6z; z#$KJ^i~H08+5h-69{EGSZsI@v%$K}cy~_BGXY;b-v3uwOA^0i1 z=o?2Mq6Pz#=`TJcJl`+&?my`vo_G4~=*n{__V+*Z!~D<~9KY_9U3AjDvBwjCvWI&i z$8%rjBraJduD#S1Bm;f~lp)I}ej-jd3?RYn6Efc)tPr^-T$5ZTz6p5f!Vi$@CA9d% z>@>0jD2XBn6 z%N-5pGkoMB{|?J%-^RlfH9TJ3(|dySeZSaWKcu0h{23koibFo6a}o#X_2_oN#MfaL z-o&0e`pVze2|Kv?-G_cmvTNWEVnmv|@bA3#A(qYLQ_j~N$T_3WqoJf5WcM+dX#}-cC zbn?gW`UMHhHF0uxT&!K63KG+``Va1)RKG)yB0sOWasT!C*NA#p517&;($BcJGx~ln zYA+5S!q}n<3EWLmyX5UJHRO=FpX7BPU}tn*#52i40riU8Uy}dhuGW!#7(YNVu zSHk*Lo$?1WANj{z(lL&G9ax1M)^F&Thm{|$7rU`Rx+m%=nf>?kQK9Mfd3y7Qb0NlN zFXzydDa?`&u=z^=rwe-q1Hqo+FM3+}vffob_KhFIAfgNXmT&0Dyvk8suV;sHgc)XdHJEoDMj9_463L?N6_$phPkO0QAKEP1FXkM4 z$svzp@;h8@tqSr$y+`{MF3%wy)IPY=;b=!4)Fr_%$9^>x=hzz!JXZ80k`GSVukRbe zEvfw+`a~^MAP+{j*S^2i-WI}R&=>h7wV6mPe(O` z=fV2E%6QChR$k`IoR5zN$`jAz=Wx*QSes3)e`+tvYn{jGw@=yU!xsi0>FiMTroH9~ zac6LqJ`elLu7@A1@F34ejPKgZrTVLA&|_OPN;ui)o^rq+3ZTwf{mJfx`rr2T;R*W5 z=7jpG9fcSux=R*=M67Ky_Xk?}DV?eTREL)Tw|PQ)=)_<4C&-ThB#-1b@gA)_8Ag&^ zjm}!@gxkLW!6P(`#L0+Bp=*aWELuxIMm?-gx-d6$S24b>zEwg$Yeq!}{lvnGkJi{U z)QxsP!k7e;+i>$SsL_H9v32WX&uBU>A2P8y_x12@cQeBovHUM(BkLrmJRJe!8n81s z0cbKk8~+91YY}QTdc*~}JWiSi`r){mn-@DOfJVv4GaQ34InAc6!kY*oP+zqEQK#WfZ$dPu1 zrsXQe@RA=3l(JaN5jTHB8saqPXHn3bGK9Ujoo({Xs9Jq6x#3tT!Y;g92}3r6$G45| zjJ?)-U>~~*)dF|jLPbSC2>9P8)Tb7S>U^k4;F_?lV{n`8%i<10Q{NGD1naSYZ3%2@ z0MvER?w+nFdJxWzvM%~H5h7Pxvw!Gl$+OQTBx{1Y#2pan?@zfxFOc!JT853Gr4HAX z(aA4$)oc_YuRu7K^?RsmELvGo7NoZ_I8B4j6=GKU?^^^wug8{d;VBKA*=9tA9HK=B zj>nuuEb>k3LMf#JI`u?d$WRL9u31dNUb`$Z%e(R0k1;0ZpsOp9 zNZYSEQU4^f8oo}y`ycDZJBP<_<0UI@Aq&RrF}`zT1Sru|?!@$vs@n*H_*IAqGJ%@e5z-65Y`-^HuZChFAOHZ zaWDkks&R8xj%lOVQ4Iwcu}bC1LaBJ_T^5oUh7N{$6e7X_jR@TE$}F2)1e<5|o_h?Z9+-K4NTVYhSPg>~ z>BqEzfr-#QB&UN7X`Fdjt?png z4@~gm#D4PcjDkBPXYLX#eY%^gqDT_!3synTO-vQUSED{dB#!mt0Nw+x;0m56dcmy_ zDU3RhB^lz+bj_QGE8m|tscF&mU6oo1IhGW(!I+XV7&;ntYx&b~=wos)-c3!YF{*(a z(eFmYFKVLmty}`TI7uy*wF!{3712CaaSs|rIG*!05`Ds6>pU=9l2V;hpF`&$J1n1G}ncHR(WVL(PZ47tHf6PVqh=)huAjzmu@)r{5K@DlZC z0-Fc0)qnpWuo{*js$8y>I|iprdu%BV$X_gW{SC|$zij0TI3a_gca6S`=mACuV#t46 zhT0W2!_S8Cs)?EG%%acO#fie3W0}^O*`V+@muM{{x>O8#dIK;m3`_%G&XL404%J|B;?bhm ztdlLtEpIkqlg#ynY`fkEZ3OL<#8!N!LAh+1aEZ*Z}U-X0kx2 z0P&QL^&-OCsqq)u!d=m5ASBoh#dm9wvw2Po9-uDNNYfwwfouXKnItx+o(i>(qu!aE zJ5No8g&w(!BD1)k^L0$FRT8=t#tkPwHVMFHe1m45F@xB(4e02#+xpS$r{H7;?h67X z3zzCwposH=dmp}#{++IhDI@k-8>J!NSKp0`pV@uofKKEW+KZ#B5DggS0-Yl@7NXH; z$uP&&r2Mw5h;b~%z|olSV{54x&?Pj*PX=-zxPXQxW*`a!_#Ih$G^I)EIq03v&#Vlh zAsHLgKQT_&DLlvOSLHoOehiMR(nSG0Qk0d8mrlC}7>h83h2{qy(dviVK%EZ9LDf|H+jKI!-=w@qfj zz1T%B?1se-kWIe6vFrw?@4PRKA%RJGjJND{c}@-?$JMs-cxbONj+aNt36^~{lLjFL zsC9-`NDCbBc1h7s>H5L4|I^;V!EY}DLz>vyct8Pmk?Kv+&^y_N!u~=w1zrA)LK!ky z^0@G*D1d$fmtqcL(^||qcfIs3s98;sU?+;b`SQl^jHney#ytxPDBoD4B5jEM3{C(v z=Jh3IBjfMGG{ZM{8+rO0WGWufhBMz3aOpzZi)8XZP95XM?)Rb{cu#`y)GiUsjoxT5 zcopc}-%|ZJI(CG)V!KgKIv^)G{gg!C9gVIwl9bxOTv&%RGnC;g8=pEb$ zr*9W-FS@hA8XSg!?kB@$0jqF1!>^Sc;4yTFT&G+d3@lO}F<8Ti-poKswDwR9+kD1# zk?OerXSAO=UA#H*%4O>rohl8|S6jdbYXw83JpvC+kY^AtFw)3eY@E+TM%HgFtV_gj znya@yF&ubH)~G!za|L3IykE1<*rDos~v zubfx?cR=GN-EeaC97|WDeZ4TC zXq!nAbJ6D3Za~hbQY5v~oF#o=Y_e1WTC|Ul01r(t;^1+dK-3ZfMGnN6*QKp!zue;N zb=8qBHTIdNX|zY<4UCb3Wq1}jupEjiKv)mckZ0MfDTGaz`-=@W_((dAg0>Jbm^E7; zx<12wt&~?M-rB#xP%;KZZPTLJsZa^K=X4gaRN_S%524Ys5&V$S- zx2A{MV6Cj#w)e3O=7!nh1@3PRvmZI*Vg~ zvQ(d&{vjx z4Qm`&3jqrX-VKNf9@qDZLEW;q0{!_Zl&aIF<9~xK0_oUpqvje;1gr(%vmx6uxB6%* z@f7ODf6fOMv~`S@?xM)k%iFlkWsT1hR7AE!Z*0k!ZDv#t2Ea=Y;PKGlqu-~2vBwV` zV7uO6Qf4YlfPgiAO=X*D3>>#H^hCoDyw21I+`npZ&w_ZTx;X67$A{Q+<;nlOHfwbd zzSe2(+O>NTp`)3TaX~26qOhZ9r8&?RD`w);dq=sm~>VIvnLU{a-LmzY?sMdDs zLnrSzDb;vffU3i);5=C;;mYQ#XBdqtj9 zrm8xj6Abuf-W-?--Cme^?-@Af0V|4BI zHyRhRQP;p0tBr(xb1IAmK|pj^^gnLKJPX)&~LTugZuOMWfN%K&Y=Kf364tT>-1+%>#XAxdRYZkms}X)tD10 zP{H=?A!yj_AFD(N5JjH{b#@uoG0s-O7(vw)dwx2}^@cO7->!@~@oFrZ%s#51xmZ9uN63RAN^ro8uT23h~p>2dRP2C;B4!;sEmk)*Ns7Z76+ z_bapNAKexfYGg+M{kbtscpi(F6t^t2;4NbF!_5Gr4~IAg0J!@wPb|8eXv=39DK^Lq z3v&w^3>d9wA)fm+3w0zqWPYvE2JO=&>XmfbolnW5XZ7gt6A}S3|i*W%20&dX_`%yG4H1lbIMWh z8hkj0LfEkujdQ%W#qY?%R#K;puHuk-tSO6QBi=No8T6M6JXn9LP-XBaFiJ7(welXJ z{Y<$Ohn`q=U^Ly#jR*qGMhP-fO-@4oLP2C{+`!6e0~ZH1JBk{FMHPs%`;yaCMcs7k zU-bXc^z5mJa$)QuINY#!)5VkCfbXe0)fp1>F{a?C*8$$>1F_3$*ZQUsHEv+JW4jP9EH<*!_)PoM2O6UR~@-uJo zdlQN)xbCocHV{}X77|&sNy&ZaQxS<-=`ODcO?P3U5^ET&r7hY^%f>-9cwR?Q$;SXT zc@kAM0BY_#j;kyhu?P${{800{$ebMbGy`T3Rv@mr40mRlmEz&5}L?QY9Nb$8PU9`**IGgBRG z9r?&qVGevO)wkk?An{;p^z8*YAZe$SWJmmRcpn@$E%@VbqeiEgEiEIc5H00O)`q?& zNV8HA$hxEXC_X2)3jRIQ#t`J>2IT7LdWf*mNnKiXm%|1wdF=>Zo8fG;x6YV1+L@AO zS>u@robN8msqu&koaijxCUN4_R0a0>Hh-ER-zsY`Lv4y+@)f`(D(6C#@rWo&~F$Ru<=cZEL<@T4dvVPLkhRh?~3 zY|4uRP-IX1zg$JWon43<7m70ypM}*4CUFqh^PXp&qQ{X+9m+ud{y_)_)Z%NbUzsB! zNXQbq37pS#XCz!~lKSGK$tIx3OR>3y3ji$m?MM0Bz)NZz2NJKDc#>h$)r5Fvmei`Q zshP%&BEw^EU`cj&seAP8^6ee7m`%Z40kapUQ`!(R5&gONPkzP|)Vj1F<# zW?3whNwW9H1|A8yJAQDN8|O}a7$LGk0Da%s1npNMnL6*dBu1w{b&38+?BECzb(!MD zo?Z)rQRqZI=}%O84Td>&xD)J#D<2K$@*UNIOSwmYKYQ*@gJA^zRfCN!TR#zjY>N)A)_NM>K$sjGJtw%d>s?8%S#3mVt zjoSXi5j@dJ0Oc0cJSVX|=uIf|HqCV3!Y^Oc0mX)p4r#%+L?hd(8C zo1Vyx9zVGww6XPNLx6Tg(lM}=D9+RO+07G@<%`+YQ3hz{t}4Yqc5zhMrvfp16P`>~ z!{BbyvO;r@RQ^d1tkw18OGvsdVr(Dapb+Zr66OI=jY6lnw9rd%&rE`^K&CP9QU_Bo zlMl$2?OY>50oAJ<1Drc9!0gil7?3FQ%Rp~x1By)eCJjaJaU5l-`QB~MBoW@O1N#@0 z?_ppe?F-B4MW&L69W1ycOFL{hAO20+`UN{`!+v5kI>Gp-Rh6o>b&a(vLByr=Zcb12 zQ1%dFbs53C9IpB$;#V2SupUMUk;!9MC?S$67Bb~6~$q0H$J z_%)FHDioyl>~$!1Yh10or)P=$h_(Fc;^OAaNJEUkoIYvY!zKm-GH`dZl3lK42R76Q zqvGAxP3%Z6oz9rJ`HEH1QT%Cj%t)h|(FT4AH!AH)IJU)_y3uxZwC1j&wk9m3s_PGn zPau5rlCv9(NyFRMTOxIiPc~$WQpa&01b_2-1~h=8BN?mVUKGsW7{RQ>2l_pzqM|d4`7{ZBx|*?U#j!xtNOwHZi*$VLXw(rz1k4tvtO+JLNoX}K;M;Z# z7{l9vM@Rc?Q#gx3Yu4GEq#42c3fWE6Ex(U85Eyu@^?Ni}*gHv*qb5au7M4^>+3>># zY)o-+r>v=jG=Y|4Bt8YwXKxjIn?OjQY7R!tq52`&cyZ(oce5-ni9ky98(vl(X<)k! zi4!<)VTWomZkr9_;ElENq0WQd6DT>2neD2#Pz%`jBGZneQZ#8X20~;%hnc`Un-ZW% zQt{Bl$R?BGlQTR&nDK^$X6k~qod%0Nw=w~PG%2iJfQzfUWVxWx*8GoaZMP(As>J~r zc?r^%d7!U7GVVHQv5KxhYRJGE{agmiL3cy;Y00LGu-c}l^ia3rL55rno{#~|ZDVQ}O5kgL;2!~~*d z0wrLkr1{d9O<-6+=Shr%H(?s8U>mdRX~SE?%#<*#1h-h%HNg;ne^d6(WR}wtpI_g@ zrg_Ck&fbe(4aeserU-izAavSs8v?CG1Qj|HqZ5xbMtwN>`!X|XT72&0+-~;CnI{y4 z;+>qC0z$c`C59H55H*xOB+2(hXW7}8j$!lt>jMXpb4O&@Ydv2e`KYz>2yg&p^JnQ= z`f~DZoyOfLaAd20?Tp#+oe<_aCNb55#gQuyhg<>>oddcD!LU-<7*SJ_jC(DTT_{P5 zpAu*34rpsV&78)ROf>JZN&ro0Sa3%VB(5<8T+6w*Y)K=rLprtzXTZWpB=Bh!#+1?? zNOEZp>Dd9>@qPKS!CG+9ad3%g9)#U*<7jJ=_SHbVkykn4;F36px;c1rMRFtDGz}oK z?W}FsX1E$Q{Qkv7YhXPrI$VNw7Gk=mxvm=u)h@~8ggwQAq#Fs@UI%7{VIKl)8e_XS z1xem4SXjH+j;RcDqe4BVZwdj;ye)Znd6Vc*5%TQBqKlhfufj7 z%S??G6LuP6B7wywE)ObpKMw!zOOFs%7`?rOF(4W;lVKyp+CzGUttrAvGN!$vVG|?o za939acnf?|JKyE=5Xu&;9L{xqgkTuAQeSDK+oe!d%19cKb|x#7#0;6?n# zb2Cmc)ga_UA_07kKvZeiA_!%!MNfLxnsqeFDk_jLQZxY%IEc(2$P*rh0^FX3kkT+r zu*Vn}4DlEl{At-h*NoH{qY4p*Tm{%M_>9@wB3PfGfw9~~S)_`Y+>zA*i=7|v$ns*^ zwAp~BE(*XXYe@&{)F3E0BCdITO0}@N0fiVHkmzX3^3(NkIBGdGTn?l1;b36_W%3wmdgxsoOfG%H&!QnCBKtJ3lbR;g z-2nhD3>;}7uK5xB3_KjYoQxm97ujSDm+V+&ht}tCwB60{d})YxvPQBp?Yx(KFSW;) zYh+8K23Z@>5+My`Gf-y-GR(f`(+x0Zli7%B;pF1%{BmFnP|5>MXw#F7Mr&=1P~+z= z7r~W#elgY55P>r#S6bW~sZPg0-LifVJG7L28&gc-PeX8`mhJk{$QPP~9A3=Q9x{Sn zZh`{1E7`SfbWANn5`!gyv1v|A0t`yh5;C$15)Dx}IAWe4P$DS9Su&)GO=Vs%_#7wA zm+B)(F;5ymI+_3Hh*?gG=Fd(vD=5ew;d2x^{GkJn(kPM|;&kq0Py|q20rjLErit!G zer>hsALzP`2inD2-m?vS;LuS`=pQ}<1I0sPNlgM}#7z1j4j{P(+A+bNl!|gFw(CIRB0o3Zszmc{wY5*QWpf#e+PN##aG1{)8#@jj)s zd}16*+LHjohZSZ7(Z)41O}d7spu!NA3N_)oT<{^bxebg6cpWg(jPC?D!3F^`@1T3E zjOOWTAwcEu0Nle`5wh^&;LQsKALNyxw6RAfiJOFeopyO`54#I}g?7VQIKHr@6d^_2 zKQ?^XbZZAJp#%kRoun758(BTa#Z5{q1weW7gBotVivKnIct%L9nlK3_6MrJWL!|_C z3j=OqgwGE_5GXHcIC5rOId2G$heyeCq1<>jn46(_aQSN1N4-LTAVeSn#jF9pFnF{e z)a)x5kPog0AY%4CUfNuF-w4@KrUemT4`mNOF1&})eDUars-ThGy{n(HEDWu;vYkdK zxmSpG9Zb`5zqIJ3N_iyGaW+F^*(n+!wX|t##{!kH1E9a7@uS2J^J92LV<(`CK892z z78~+yFA>cwk6Bh)L5fGQP1;&*+G0x?)S6Poju?KBoiRT&B$aE-3=W&y*dhw86gN*Q z#Jc`sBjrPb^J80^x|xxq>QF7Q#d>{Fzee=7U1O$hV-$>F5V@v`UtGc|k3L1PdjC5H zUeMgSChT$H!4>wSuP?M^uyD+(C2Fl=NfFkThnJW(EKW4c@DXVODF2Vp@|9 zMRUUE)cg`FP;4tq08eWwh^9ku$~WW9Ds|CN=(uFqr5LNAWg`?oEzyh`qr}uK&}^zV zMqQ(_wM~`KYzZ&a(#Ep=AWPRexiE3|^2Qsqc&}-M(#ARfL+VtF%v@K$DW;2NPZU_a z>6Sazb!KQ{usLXAOz>~7YDWU?OAah>kq4WemztMZ6cKNlnOD_o>~uoBX+;6p5=_&= z;X%-mRYc~Z0ZngeH6pTl9j8R7l%mSyKox=(lbNU8AzS;2 zt$N+$E1@Iaav!fUU-&h^rLo=E0e4FcJ}lcBH@BKCO}MVt?9r9Kh0rp~ZeT-J=RwC8ML#qipmk#&UIx?9xDHys$o5f2y$ zC5wuuv<#*l1Nn+ohzw!n>rG?Y>YnTOgzj46iS5bb>97a@VQoxpYfMOv?a+)$1gj?% z(qE4fC$}bL@uXq~hOkjh`Hy0wRiAulFQHY)6I@`}Hm0Y?w%C@ZSpA~HBYAZxMk`j0-#ygflCw1JY+L?T1<-6;~C} zE%5>j=c}L+Ty=uCW(o=1x~Zm)3tEH^JoT;(Snyg~po>q+D}lYR#Wg9Q-;Fy_uy@tc)if2@ zt^Hk_K+P*k-O;xgT0=e)K~T*LgFqNiDY|a#fuJhd zm2iIb;l1%Gvu_qO+mWV0>X{v+AlDBmlQxN%oz%8hZM!a#>UeB%zG|vt4^%<{b(Jj} zXSEHYEppj0U??W&SEDhtE@pLM2h&`-Dhkk2A(77dpjs^e9$DWgHI3X+dst+Xk6I4U&GrhpjTUxXd*O^pr ziIx6z@g44Yt8s&62<1}n>9J~F@k|MKz^%Z$PSD1p4%!;FrSf0kp4S%`9CuOe=|<;Q z!SY7lNZ}30z;-pAOi)VV$6lw@feM0+E&i@MV) zY-?UbxbE^^FBEQbh7)%YMknS-qUcvxX3Q!mXPDOIC&y)$1wtm8C|E?wCjnmoe^s=; zw#A{PfP*t^wgo{W1fZpI02C-*A^0Mzv{pcCIS|2{*PW6&*cKm1MB#v;pAkF1F=%jb ze^e@Nd}5?jYGCLJfl$MIsiY_MqNB~Ot4kNeuL`KJS*9}C2e@eEwH{VsJ0r|nY5`U{ zQRw%tDEu`W&gu!hJp4=B%j(VG;RZ)mDFvKv`y*y-MsTJ=1eQ=*CHi;$78r-FwY8*s z9vGUuEG4pY0^*{I!2+)K{9^PW@bZA0(bqE&X!%BsR^e1iYIUjUwLFmI4ke%lkocBG z60KsWk6VrBBhWxCEDDL~N{Qd69@flUrNS9k9U58$ZL%!z~sSDZtk>rur?)8{zbu3QH z0W!MRAvhRC`@7mWj{O4$aBN=9tzk>pL5(g6#1a8vB?#CLf`1Hjmya*G3XbnxT%cvf zE?PQP)6q{J5BM3rP{RQM7uK2r?}4li1KR6>Md<=mC9K994;OgofEQi#3J8)Qj3!GI zw)Js&{epLDy76C3sT8ml85ei4X`rCmV-#F;OR$1cv#~ADC#PvU!-&Md>9I{YEw-oE z)Bvrott~Ju#-~3EYn)59IJLTpmp!6n4wLnT+|3) zpsCZ&z_(}jX`7Z>8x$*Bdq9ilB=2P<99ZYq*IF@3=?K+WFpvb#J=Lm3fVwPkwyc1< zbdk2qakfm-R2Y4>9Mfq_v9l#dX{pN=Y0DdD%PDnv;%kYbZ7H_46iZtcu!6cYJ6qD| z8FN&kgWctVh!^5m+!`GpS!>8uDgcZD%$iFS>;aCipKXT-A}IH^KBTe-Ra8Ywy+Esv z*>T2E3*cK~FHWW0u3gVbI_{n%AQPaOkhM9KtqUzN1SAlX@!$^MXsOL?sU^n7XiU*m zRI_^5IxF1LL0a|2q^&4ZIwcCS8XeaPKxWL~O-nuN7;T7Fh5@aN7)Lx9S{IbgR5TDn z>qmQLr*+Yd+B4qcwN?gM1}&KYM>lwy%92`Yi7~XP3>6npjfsbago1#}w}xMvhA>a) z_LMDISyO3kkiBt~TB?e%ZWN@?`aO$rB8E|{NwhAQo?2@2X=TiqVzn|jtYt!E4JAN} zrlx%Xsik2IBTLaXWU#a)6W~ZBO;fwsQcH}@n95Kw0rhBImN>#K#g5hGm~n9_W=vcP zU_4w}p)nQ`@yl@S8+>8of}0NGk^-FBlPT52F~!7qG;ut10`5&)7<9`vwy`HppWY?G z5_f_X5sKRkWF{vqtOR~?50qK9#HPY2ADJnsWQ|6Hy*X3tGJ)h8e4@8UcwkJdhTDOm?TK#N5@ZTARqTd}6BtmD*<}f&-gQZatXqm9txFq7xMhba z$SS+XL`S07r!5Q94#=wyGmeP{(2tH6S{G+_NmgdgwX4f&B+~42xaTKVr`9HoGxEX- z_K8|yX{%KmFm7*ldy8t%B2PZ;M+>3i7FXedP3wy;>KJ1boFZ|$1vh6L;~VU#L?zjd7f`v2}qi%@R|8&!eggCz3Mm5g6mGUGx&lJ27Y?r+UMy^I1P81~EE@%3Y&RnYX@VbJZ)WpU5dFanKZOX5P-1| z%i~UK$vq)GsRjTDONmlS)ptV&Nq&ft`2H?nc$Bqsq^Bc-1V-2C)}m|In+O9J(G?NO z&^5477P}neC#QiRTQ>zNoECa@{kg#HBZ$aHD{xO6R*#=to+jI1+SE?AtBwUO9V()n zYhav2ESxYoKr36C!fB7Tt~NZ}v_!QJIZSCuPF0)cxC zL~^+!Y10Q>t5%?qs$AhzTEqcY8klFUZqQEu&mvuyei^woG`vD7k+wGuP%$nna7Y$A zgzF8iP7SUp71F>n$f9D9wZZBERe%&?u>hgUJ%cnAjy@Pbv*_Cw2Cesl0e34A(T7)H zk2Y*IE0@TIf!Fkcwyr@77H|_0d3Xg@(1xWTE0@SNf!EZntqTvEn}#SsGtduQ5EKx?QOqaM)U`wN>Ep!dcBi~zkc4k2V5;6|Yr2FM2X z1P(E>a(xv62A^5ME3z1DQu*`~O zphcJ*0*P!%+NKe(Xin4Ir~teWC9R+aI#5ByR!Y$(=Ok-myM)3zjXGiNnlwhkWisK1 zC{`HQiP#d&FfTSrB&bucwh;zM{R%}qgcgXfuQUMKJ`~`gE!x(h%E7uJ%cdweMf7@C zq6RcqF#{D55{9_@oAAu~$twt2Q>l>0Z~= znLDjIA_LjLAyi>lysX@ssj~@^@|rS7g>}7G_dQ~tgS0?DY#AsmIWo>Fo0r0AT~h#R zQ!7wS5Zi;9Cg-G(P0TWED)?mW5_H`rq7yYxX~hc4H8t6i)M=frDKj@i6)^y6pc>P$ zS-CVeWOM4*1;agRAqoaou|_YsLN@F4MwiqJH-i_VR$vp`UM`WXa4OhU=4KJEfmUo) zu8l2is-f$px`=^TIkst+3l}jEE5|mCqIPwf`+Ri1ze`OXmRLk7`5{iC!dq-ZgEV~~ zX$3lRdt)RhP2^HkRK+3^sv%nOGz2$Ts8DV!(E)>0L^a6v2~_t6C`Ff_wLv~q9(%~P z7TwUJ6?iBO50#EPD4v3ce{%%c0#Cefu6=-TYKS)4w7G;W{@nJ|RMGt4jAyLaJ~1;g z*GhbPczaxg$xiVEu*aw9#m_DqHnv3&5lcvig@jb^(9kT;v`V6!Sss{_N)~ZS)9yNA z8bz=Y6ff)(E1CgNcw7w;RY)V8tlVk&tXz{RGy9fYe-(>O%)&lVk}Op z5}ey!5J5H|Ut2$_eR>emu_3B@O)r2m@+j=9;7i8@AG#zsG~5wphrpqZI7IXXK-`^cuCFN z3~ot-Sp^6y9&5gX+;SxLjS~M5$1p$c{a{8&N9N(tE*@!#`4PYI z4edrV7C0zr@bw%BRVazqNH~*P!6$z>TQq)riJ1^JTly2=Bxgz_Wx?AZOooj`n)z;o z!sKcdj@@wIHM4ndY2vy%EKV7)8>XEI?*>A;e60k$s{yiU(a(2D!MktVnA|s?!9tk_;689VrOKTmCQx7zqiv2*+I4 zQeh=G0-3rXtBvEf39^0rH8dV>J;|2ycW5WvfXPPko9Hs{JugrB!)$P0LZU&9aoK;Q z!b5(X6s5xnjRRxAf&;g;*AKO`bwh_Q>6ngru^Gu*2vk%AtpT$A`~!55x7I37#Mrl0 zoc!bg?{(cf(ea(+&OrUwtp@oI9O&(y6X&_nN0Q_GFxm6?qUlc!zd*BksM0~82 zJZd}X%Z^#zBbj62 zQ4kwX(1zMLZzNraTS?tD`t8OzCzf=hnj|awxyJ(BQfdWm%mbC-&u}ju!9ZFgZ|gwa zSxvez1j!nY;FU7Kfio1QjV5lS1Iosdx22YoIK8n`lBBYdQVuKWB$aGf*_Tv$Vda&i z@{W~Dl1jP1<1nRR%7e6FTnsSBPDTMDd~N2=3DA96`I`ZXBaun{n6Ji|sXNu!4r5*w=|TQj5HjbfC2)^}_ilk616GERo`a^7D;jg5&& z18!^tHT|a%{9T5XOkLo_m$(f-d2?yG&ZXoQ;wQs)2mLyn81YkKJ1zQCB&Czzmq@Cd z*iVz2KM8_rI+0A|CqkW6v}lCHPls((B(rS7#9zKdb1Z-nc(ZB$pjs`87|oA{j%PB* zN&(`7@vZNUtiDa;N5S?}ZJ-=UI7b~b$6F+|xvw$0I-u!l{NWo}W(_*Ok%d{~$kT*8 zM-L{AMKlJCS)hQxA436moFfsl0PAxgVxm=vBf#!!ZyXTN_Bez44Mb4`I06)44O0NS z-)O1qj&a0cmRYYhXGNv+Q(atQ9DUy8oC@R}gz*Y&pnz?tWW^a6n8YgM>D z2vQQ2^EEtXlr`YM=W17=95nFx4LVQ_U3`wC5VWg;7-)sQKoj^pM;+*dK1LDZe2oY+ z0+vpz?m3`TfG()yUIj;o$$23w>Ua2`m2U32+kn|Av4ngM;`|mJ@`3)dY zBa^>f#KQaTlyDPy0X)wE9TK+oF-`MKIb*umnQkZtPQgkwj{7!Mk9=C$zY!m-hii=;#S$Tj^L79Y=T3n@&CN5e{M*a{BbD_vN0a>7nke)4LO)ii)@0{YsJMK-WP$h7vLl-I|c5E{{&eA zXCSTte`3LPnAz~P$=09725uv+1Sn%5Q*kvn>;x>paL$D;pZPBcJJWHaryBGG#F)wt zCdEB&JOK|EIL~p2aR;dy$Kj!ijqJBN;{z&ac!)7>!2N=@v08>Fi-2Zeux1v|wU`80 z&ToR_-f7+)|Bg!%U@!tNiJ!y=8O&9e1sU7fz*3~V3B!ns#tSeHacfj{X<2#TFbQ5v zf{IE^#LHX_zlH}I3b$4FedH39otH?7_(hOaahVgulTqxDO3T0;#DxF_0E?FZK^z=F@*DlR^I-zH;iV5w6J1=nyxK#IZL_gZ1#FXz(&8QXA0K-i)p1G@~D!`%nY zbXNoX1H@4At585HMvJv`oCFhpI-tdIxMBg+&?@mK7AT&>Ekkhy+z>9NZ-B-03%Fr1 z0C<{v;lFSRhZ{2;DH|6!MDxl3Uci0f0AIO%@SBAW+`^@BcY+C?;R2AA0h;^ z)y?35AH<+@pRzFAInt}+OsGlYr@>oTZYqLi+TSM$oZq|xocZ1n=O_xC<-7x&`(Cg+ zK!BaN=OS8D+K4NL30Pq7)f!WMZ;MWR(S@6p1_xcn|uzE5D zw}~MJL*S~&+Q4BIk}Fz1Y+T~Dbl$Gn(SZMip2Ce~EfM??T#GS)u`xe6dz&`+;Z z!@?=AwQ39q?ww4(+p#{%A{2(Sr`#$YX);+08JM82_iC;lO=M7f$?n${7_8wpY*CKHX}afrqcw1P?YxOLMD08?NAopyYo`2mWy z8Iop&ou$W!7f~V)PQ7pcJ9nB*nJB#lfZ+j1gI$f*8HNkWQTg zWgrMcyYR-qmvrluXhjmn|`7iP_4(TD|s z1-uMngu!SShlenjB}$Ei*yIC9)U0eZv(~k2gs`O;3jhX^O%EQ2Xoeg>)RT%G>L?&T z3Y<-iVr|UAFgESL@mv%X9JCr>TGuAFiFnB*(*(ZI+EicyBNG6tiYcw>N_f%%~H%7-PdcI6if;HHhUKYaA^K+cCi#XJ|;l5{=A0(E;;Z zdWEz#^45Ax_{mN#l!jkXqROaT_PrG7Tj8eC&m#6!170U@U+ZCj9WwR)m& zRI@8qp!PbZ_J9EgIuhHuOwra#O*V)9XGLz{hem143k{Ep+2ITY*>qfkv>3H+i?Pk9 z*orY2FQx_%-$Wjdfq>Zaeut!b2%OC*p@M-9W2dl6Em8vlyma&lWOq2$SGaW@6FjyM zT#}_gav|KK4r)t$f$5oXuO%%N?+GIEjg>IYv2*JUVTtV{j*PD`Ks7uF!}vHa&1>x| zm$k3a3nG@Bd7+JXD$$YHQPQM}*CRTt%oNtWri$tSUTAaLww8rj;n|~DU=;Bdl0bkk zqhFJeDK-!>w#Bgtm9Q1ms-|@_t|8!}jL$Et3?T5V2oL)RovclaPS!BJ4Sn3uxOja1 z$j}7jq*AhLF>DGb#ZU+U8=Q2>yf!a^jmwzmoHHg`oqZf20-{~4L5%eQShs1H)BSqW zL~?mS2Mxg9rGuIuEM0mC>I0$=K>EXxOB*#kWH2Nuq@#5Hwhn+;I;1=JxinH$ha{Iu zdg=hi0q{~vFNeLKp=@CC5mo1gAYNHmN~FE6d<0yThB>DOLJd`x&UJfSfkI|e*VQH35#yJTmZ_@hn5GElk)zVBr{x+l%mU3xil9Sj{b-Z&De^N&?$0Qfa z@){XT3+G~lDzs9LU-;;U1Y|{spN4H^cq}4qmHi>8GQ&?oT~+2-bgHNnsqpxD*i=(K zC54}ddg|_2b*iKQT`JCRK}yQ8@H9!){hWOdkCj34EqsOW6R}?)#{yL4fDP0meky7x zM|U>jXJR`Oj}@rOnLSpd*J<}ln}yE`;-D$#=QB(r&w_I`R=2>T| zl98S@_$D<-cDd_AUXw^Z*UFQ1l+$%o^7CI?ho6^I@gGfPT9?~uT7H3N) zUy@-i;eMwct&lJKn7z1oH8kc!90Px>Q+53EH(~Sn@ecDH_$Q;LGpsc1roKd`KvoiJ zCOCH*v;pbp=OM>KtUT=F;opE!5-Sh2G18Tis*HShG9q;g?c$xNyshEST3XDV_&B@D z&w(@URQRH>!490Su#z(*DE`4fx9RsE*3*nrZluG!F-cz;$lEvO4kR7b3YQ5s6@&}K z!>A%%5OU$=E~NZfE`A(_4`d5VzgG)6Z_)Qxz#&`|A@y4kO7s7HGl|m$hjVj4lS)Vu}t!NtGCv!(bvM)}+Lu!)WrB;ByjTP9hHs z(qTM7f+d3W9V`o2k;8z31cMuq!AHE2+Tk)dEfqYByH~p8mm$Iomj$+nG7mw9%jR?l zzQd4G1wztcP>}+m0f;e&k@teg`#TSS>OW}s;CC2SkRQnW(GNi${a79d4}%Zs!Oow- z1KvF(`6YJ)*Qy7)CLP1e%$QH z>$QkZhU*1T;>=*=@45?-xD4AD9=$Bl@GF-N$D~x$rq${q(Hm>T= zLncIej4$m3#hV2>O%Q{XK!nS(En&zb@ZmBq9bwO3Sg9gd4}j1X15EpX%+2OFX<0gy zkjwTOn&(+zI;+ZGV5zYDAn;WDb3ErBLrnXOyP2TVm7H7YaT#A*Rrz@f)gqUXX(~v6 z0Z2uq1%au*{{bmGk1?i|qH{AlPEtsI&U+Ja8DYPO{;onHf`Z!fBj8Nrvc7gI`U^uU zClmyldp{25oX05BGUMEAFlssJXF*SOkMU#q6!$Y8CoqozWa(rD&SMCnYVz{8gN|~z zEQ3DA`T2}-j?4PAk;w1XCgHL_-5z-iI?L`t)k=N|ILc!rYPNffLnktknW`LzT*Ao2 zM$#R5DeA{F=O0-?KB%1F~xt0r^0S^`9fXC0{jpgpMWEA9M zpf=9=*IGh+)Sz3#9~(urS&j_ywoLvCt?0-r?>mEc;1W{f8>W%WjeL+sy&LyP-|G1j z#F{E8T&6)+-TkbDDvrwrH5J^;6r-l#{6(D9)ZSlQUn!|61^mUDcE&&BUwq=my$N?- zfeqAzG(QJ!J$eO5@3#USE1AWhcMMgWbh+uSo>PI$qmY_Q%l{PQ%F3f}`YNwUmE5Co zx+)HhRGdfUwA7owo4naa?ex2)&bfr6gYBfd2QbNIp(4yZkLGEno+$1ZjuN&j<{rdA zxz!@dMvoS1W#XF#y-9;72_IeTWS+mx9;^I__cIY=lY3CoH!?ZbVb0p1yL`dY-K9%5 z%cVQJ<*%T*eA(;f(&fxmZ#le#-m>ODptTf^>DKbc&Q)u1^1o;-;F)f0o1c4h7B*|T zv#fdZHF|cI9&%ER1<|n-xkmd+27g=Yv2o&Ty**d9-d|fObnUh>=;tk6MND3I6)<|J zIuG$JMzN~%?%=(hC&b!RB2nq{bCRC&X3CbIM@#V{g~=a5U#DD!{0{Wpl3#TcN*!fO z9%M(+`@b4WA{0P}qJ|LJQ2GufPSTInc6~BHwq2f|L)+omCHY%7T^9)0T{mVCRo4yq z&zeaWIo(XSy!DbSORgAswvs|us#?jMZZd7ATFKncmO61Tk;9C^2)z+k%k#w>T~VWv4-=1>%8|Ni8x-m_LANY2KcOCBzB zehSRRiXD=A zoCVQ;0B3=7)0`#9UKC@A^QNdQn2L`nem>>LlpcanETxSUDgO++3DRXWRQz^GX+5ECH;shNo3iEI%>G7-JU zDQfUzaa<4sx}Lu^z$1Bi3H?Pk0%HD zQpe;Vcz=|EB!Zb@AkD`=q`c!Sa`F%B*VxDPkAQn*;U3mw@F=b^aCGGggDbzliq{tu zu^`Enw%`blCR>^ZllK`$R2A%jlTg9lqbguRLH0{iu;mTt2Q@*WyA8@|H#-vOvC|UZ z+2Kb|@8C0qYDbbW5+YD^3la4F#y1D}-hqT%2e3brij5(C+J=xjR5jM56$;d8gH9s@ zLQRA4jVAF)BZ&|ujklkN0dU-45VZk8{saoJdjs-mfi~we9^E;^@V_DB(i==-%dqtK z$|&=*DL?w`IzS#=4?snLEORZu6+EgKfyzjT(f6nrcYjul9zU8@`a_thdAAW`!K@C3 zB0NVJhG3Zayp<3AAzzj++GxQS(j6nAZaR{i#jgtV#!+|+3Ob8 zx8J2Fi#bb}EO<=UjOl5b0N%UaihUqD;(TBEiI!N12cl%X^1GY%wZZu1f5Am|u_% ztANBBB26L<*c)quxuFvUCO2YFNssVy=@us~#lF)RsuGc?S|wue&k-Wg`^}pWA-;eB z1d-;a0&&HP1VQDGel0ruf`bJ4_4l>p%Lo8@cMSj)ys8g@{<9B5@cM(0HxECqw1*yP zo>4S}RnaQHg$|Y8Y938>81z4R&jG}=f$j@<-Q{JN^cJ(FGc5YR0O?I*Q0(%=;N^dS z;mCWgDJ-GW6zIOV698R8 zn>sDw4~~=sAU`*WfOw}P9E#B85Hdm*2#ydT2qGdOz=2Q);mH4d@aX-g2>D>q&*6cY zGd&3Nw}r6iaErmySaRNMs#(tsh(LJuA#zoxNMF%Wtm0$sDmSV?NSX=|oh4O}Kc@&u zIaQUQV@^K)9!zeTbC7((l&6PvCb&!8 zVX4Ba2vbhzB8DKN~?!sgVlA&qzoq zK7R|Txj!qtQId{j1S(2{C?AYPhkPsjXz%q{P2N}TSXd|rkQ^vstS(3gMxfptE6fW8 z=2&l_pzfS!7;6sF$=76btUGVh&#?$WHQg`?F%}{uvyj>3Scxwa$g_SxEf+0|a26bL z3HOxdS#$4`mSW2QJOT7REK1NcwNwR%jytp%O+60QD`GE?FBSvXbs?H7FI@W zkrqH(is}ig*p)<9>IXvbLt%%+4bRZLpvC1SAq)Z)n)Ym~s!Cb^X7>E^HCc$8(sXjr zFHK%~)0$3N`H>s&6>iegY~@XarWE)Uco&2CUHfs{r2EWUELL6pYw#VnPnw~;?R(XJ zwNGFVQ_j_unJPQClFO>v zJ7X2cWGb}BSmaiQn2bXH_6ggq>{Kw3L5PaFt4MQ|!qV?df%p}2S1IcJyoh2Ct8mgN z^jyW2M#1IhHDidZqOQjdT}77X7?eK(6M9#%X3E5oABNbO93}Mpod{Ma1=!th1qS3R z#2`m}cw?gU6>(Nffqvtgw(cv&AX_BwATN0Dui__P;e~mYJKHg1|MMZEj~}f>wTW(I z)V72Ej>ArVj044RSq!BK5i8wvlc9fsWF=Oz>ExuJ_n6vTnWxY6cP{q86eukNu0f^K z2!9o6MmX(Ar_J3lfXtQwOMZ5PMu!jR(r9x28w4D3jl?E^(9b<)4B{GgdWHtC@u+89 z`5DpK8K$A9&-!iy%yWQ6Kl>2?$<@|O#h~;z78rG|W~5=z`DeU%^czp6Ui|sn$`swk zB2-zQpBK4E#5B;f3q(xguU%ky+LL1oz|-h+WWh(Ka;I^}omT%QqT%ilCcL?f=D*CG;s02?b2P<{>sQRg|BSb-4pGu2dh#8g31 zg*+%KSicy?#m99eK_SpjMd8hHATlYC5i;Qm)0oo}x;$-3PYCj}l`TL_<4te*c?~_! zt-0TT2wYxc(o}@HpXngH{ehVWcz>Yer$Flo8FcWkf|fZBMocL7=ew-AAK*8I1?k6u zWxX1m^Jz>%h4>qivZ&_#DX4-R2a@E}27eQd3DR*K!eZLD))}7#U;}e(>&6QLdeHFSHwp|-6H-t zDXRT)WRbVM`zti0BfGqBK}I1=TdoY`WP)<&_~ptn7mjd^t^~Z$Zrm^*=HvFwWi0jz zG@&2vJ!85F`TT6xdeCqaI_cJ9=1=D7IfdF(^_)4s6J4*VgNWH{viwL!-ACq~rwFq9 z_I_pqX2+#SQ#%gddU`bN5b`Fxn~EUO-&BXqjyq4Ksj~sO8w+787FtC1aU&QDXaCuo zv|WxgblbeYyXZI*6L;-jyH%DKgK&AbL3=N1E`Ot;B;1`4G0!CFPC#trMl~P=_yst# zP2@Kwv%{NrSOlSim3LqSfdiU%a0Fq);5$5m;AQ9?B06!iuC9e=#`O2vp}t^JgNm+h2~K%P%1r-c7aYUdh`o)O31G~&Kfa8(7aSn_d{GCDL z-4)|@-JgTI+%4pu^WNdgZ$Bcs$+#pS=Z#AYxKWI|JZ9k^KT@(FQpgrDrSY%1c)5 z^-evk+RdGQSh1oz0kL8wGM)~7sQ$wm3Lf_SL!T)RY93W{0OTk{pB#X^sp#7~yd3~M z6gc=f0E(tKwE4NZq0PUdP}p$yFELXa;C>rkRsK~7>Luh~k)RsD9E1>PhQfnj0?k0= zAgn+!ggFQ?(5^rS;Rf0zcMy7@APPY(2s(&JPz!TETLmc(A%p_gq=&dpacS@nY?xew z6a+m49tsr7JcObt3V0Whgh@fk1S%Ing@S}i7tuE*VbDbcVoJ!fB!b^XFmfa8{aomQ z9O#2BKUM3`!6La@c9uwkP=G4A^lmC^gG>LIS&O8D6tMDKnrI3O%|{?%Vr8FGC_I^* zMBdc1`g8TF`VnU+SnW9pJX2O`{uNb=4+8=XQv$7edsrTnip#^mK&LWz7#rvmkcZ)c zN@X852paYX8WrRvfI#0aFQEkLpwCO>K^=gBLV0-!Hc+P@s1xob20@!&Ug8my`R8Il zpv)l`QvzM?{l+fJ9~aAWniy$JB+e>?EcYUOLNM~P9W68W^25~H0`2>T zAW!J^8;CHo68#TgQTm3xCl;V@81uxs`-U^jr{UG3Zz%M<+Vc&F%&RJY16E?rLCMpK z$+N1-v+Bu{3d)n}?l~ppIYs3umG_jg@{GFjjLPzSwLD)gPX}F|4!%60z&xRzoP(IB zlg~Mfc{-o`DVlfAp-flP$~lnLNd1VBlG^C#OmS64FlV|x8TICL28^WCO~{95+M~fkhP>^X-n=PNvMJ5aQIb^N zR4JK!a;6?{+8~LP^mCJA;g!|ok?`j=MkQC`NgC(=30k^4ZArFre_5BgQ#RROegc^A zPF|pFv_6n}Pex)M+2qc#JHYhtd$@bIymKZOsAZa;mpo-TvkTNyldO}WGrvGN>ACXD zn{rTBO1TH5;hB&)kG#`Rob>L#K{+iU)70l~5U8ePmAinTl5}*>6J;(ZH%wd(b#;Es zos%XUlgzb24kctl7ZyHg$ZW&BGPN}MX`*R1X;xX{VT$r7J15iJprhVjNLALlKWm&J&AJJ^mnau2fo@)OX6NAf|o9Xo#> zCAoZ@OnHcoWbT5wa5S={CEZnXfe)$3$uo^?^y5Ivani4mac@F{;V5R#h=r4C+Nk$8 z(2n8cU$6;bc8cMCxMWKBUBs0 zmEVX3>k>bZ(^!`NB;*Hn`kChs5~-fnwyW#ULads6D^Y8;yKpPl&E@TrDR%TfU^{QSyyr8A zz#Do`i-?Vvx;51H;A4;OOFvqpy3LPxZ+rPA;4(k*MOlcDHwzQqtrne3Nq#;&X1SFe zuH%onhIA`HTs>#bE7V}PvzsOiehk)Hy|;tiVq%4xNe&Cr^GJfz$3ldk*k&ooV~!yjDsWm&S?im{z}3C)#nt%uV6b1-^9c3U^nkP3J?ZnB6A79bYBkP zH-laZc~l?_Pk8?f7Y@ID+6BCm8Gh}wQ<=Yss+5NQE|OB-QC|7W=v69tve1)x_$BNl z;9o~oOpyLQl42@k3iCJ8%QWRj#UC}`_fH@3{H0WN{PCzGQpQBT1>>4WS$U0Ie%{jd zcvK|kJMrv?8PQ6Xhg0ZjvOz2;uy6`IjY3b#2_bv}2oV#L_=KM}vG|{vxUz{dZ6b;h zF(YguOpDDq33J3H06UCP*c^vZ=`bQcHvwzJB+@ik;?GD%{9&*!J)+OACSBwaMOq3e zQA7|HLD(YRhJc{NA*u~R($9mw=r}}Ne<6|bff0u=(jW1`%bj$n`}qe4B@7};b4c)(i;U^s-Aet!8WxEk{l zg~F_icBHIu2p}z$_cN3zI0iwbqk=p{oT?Y_BK$bLX8tY$#pTjDDkvs@15Uk%WnU-V z-$aK=Ofy}8WWyo)8oB1@>TwN+NYlqO593oFkGw`nf17d0P58A@$Vm7-xi6Q+LxG|EjcO03hiR>qP3XZ{l2RYVZ7*pa6jX)~LL((4Y5>!y z8484P&PfPe4TS)tEr5iY5{Y48C>RcwM52%oL_rJ!0|6io37j&30jN3x0unU3-{}R;Z=WjO7v;uVl_g7|Q>Gr>Nu&>h> zRf*kLw$eW9R{qtNS3hEQdh%dR0uTC^iu^BnZzbU1&SdIfB%j9U;q%2{p0J_F{gy4C z#t$F+G8o?HQSpF(%7ToL@o%hg$HDSWAQ8Y}{cyp>8~K_s_C2L=%4m)ZG$Ph5aI6sJ z${fP#PwG6rR4H^yAp+18_r;rzsxFQOPLbRL>vZ1sk1FmHrYF zmY28}L#9tmO!_dAIiu(Nno-Y@evAmkiarB7yC$-K7T~c6wcYx~pt>Km&lA*l@q`!> zMR-LrI$Q8Htpgovo;{WIx}6RsIZ4W<17KNm)cj5im~o62X@BgI5DJ<;uYH4 zQi569QIz`;FB{&3q35{C99Zh(D{qSz{E&F)aDX>B)H8{xnlH}ir858RDNIa6uIoGS z)fo^hfUvt|`I~D^EHt0EF}oal`CA2>NR4WQ%Kc;F{P=g#5dR{SgTZ67hre5#n(_tW#{fkZzN@gR z#a_4#O79g?+7uG(6>H{uvA@QRava?6Uxb+w^2tBs34C+CWSKwviJk!(4hOe9NbgC+ z@2z(Z zRA!;6IrtGv14>sX<^vnb{|-^g#z4YVbvENh3+!%jtB6S1Q*Rg>!kRf$PESB4We#nq?Fuza^IWCrl9e*aJo=jr?IiP#kB13 z-cAa0lf!2%<4a=?b;b!_ad$AB+pihX(!xFPF8DL#~ zEEh<-(*mHX_V)@De{=8qNdpcGy87!NefOl@1D6N=+HsyoOmdCM>8w3RU1yrLjfs8! ziJ0_&3$pX;l}qQ6rqR&;{>i{cR2_80&k5j!K);1VOsa`Bvb-(z-#}3E>fJ%(!M`_ z=_t!U8|19p*|)FqhuHa4yL*1HuZzacrDLp8`?@HVko&5Z+hnuL9-nr7RO-}=^5(BKgf!(EG9vFWpNf*kQd z(L_WvL}#4CY@9^9%oTv>%;RKPjdZaQ>wk_zJ$;cw3zH`#4L`A@ZxO_r3`zN-P$0-U z6ps%T`PkeRk_9;EmPNF*akH(ux1a+^^*HZB|9J9c)1cdw zDB!{S&Md3P?6{Uz9p5AH_EIvD3xSczwh&SBbn2qLEAwc2N<-DIze8`TgjhqN^e$*U zi5_Q0$77Hz(>1Xu`MaB6c9u7e534I&c{=Vvm?+XRIRDo}z?e0<`DZBY5yO|l^(|#p zIO#CiSBG=Nk)LvFy-?ypDauYh(nI~{mfehwg?H|J38Ugu$_*kjUowG!lj?3=Gz`9Q zwBL$$6#A*reU$koBRdG_b z@`h3p=R=-}U(hzy&jHMru_A@c5o?e-9m(&BzJou5FzoO+_4D*yity1sitXW;QzAQd z@Zh~nDLZ7W3C4FyE8UZJoD@RW)vf-7FH`A5I<$$9QU{@a9a!Ec-Z@RCTXNfmNy-wx zW!3Fm%!7%|*$m*xx9Psd!e@uK&VImu*-2%g;lpxH>o|ff05ZmZ9Gj=~j){|U>Us!i zx2^N}zbPTp;_%=~37P1G^6q=#xW`#bnTCvSgsa+G|O>P=tAc@k9^ zlYs}M!K>+^x|5#+k70-k{q_ec(#gwHP^%~yDBlnpO1$N)I>aq#e{5QQDp}WascpgT z_D5jL3`#K%I-lkM>B!aj+SUCo+HQ!IW$>=g_9^xl*As-ucaEOEx?FFZ!T>MHIB_~5 zw5u5vtTs#hcT$nTCEJNI&B~UvSlanf6Qy^wgIoM62mkh{r}|<;+-A!3BKy@fM&Lqs zMRS3lP|m0yuU&!{k_~o>q2C&DeeP#8GrSA$zX5-4!_5Jvo8?MJ*p^?cefKSJejy*_ zjTzmvRx==W44pO)e9QgX+mWNeZ4Evz**8tNfv1+dsKTld6&;I88tfPF>c!4}RNxl$ zi(eVq99Cmt6F!MqeBT+yE_a6}3ccMv*otofwgO0_?&yIL_(<=S&jv72z*Pa4f8wAP z*`JU3JkB^O{(3Ggm;ory2036Leo=4-{&b2q@`UQ)|86{I;;@{@zyg{Dk=sqIm%N9y zh^mNO8&$6&<7I@TF2xCnhVWDE>hBxp#`Xf9Hct=4>WnETuoKfPVagXwU!o~QJ2=pG zbZGS0?_7(AmRcZp8dw*1W<%M~fLFC4T!R*ot-yM%o6w=NUqZIZtI&$be?*w})c6%CIui*HfR9DXbM{NnD>T}wbXm_DoeeRXz_y}wK8~524 zV2I7a84W?KT)0PJ+I3o#f$$ki&NxVwe<+FsF7`KwhR2S(EXMwpn=1c+euDT|qjP}O zahxt_+e_Op6N5jVEtjB$hwTeFm1Xe#UdPj>M+lXr$h(fB7Y1^Q))fYxI7Ec?8BcXR zONdq&wFo{PAe3B(okHt_GqZ38{TYg<7!c2lgc8^Rl4*zO&ap(Y%R+2o8*3@K_!{iEAU0D-O{egg_%-o#l7Y{gY{}z;s9P4QSGiPqo z*KdcMWS0tnrbzEv^{O#4kR@Y4{N`9s(0af9s`%yU9nOwLfu5}Rlw@+=R3c~M8k|Z@zWORw^vv?!|;UTb6sU6?uTO*#Op5SF}@5$m%wE}V{|!uqOGy) z)8MFnOwp!Fr+fN#YtPXzx}(l#KMRjKxr5S7Gm-hGX+Cy|o+O@n=sI^|Faus9%n!$o zUJtvau7MG&>^Bho+aq-jIXxuI7WlY8)#n))uIbCHE_p>Ik7N| zZWv^QQK2cF4ht#XD42HTg5WV$)Fm9&UxFa*c+<#5Oggb3&3n;U8p^2NFq{?LMbRUp z^MsEUt&gQN9Vfx?lbR0Wd;pb|CEn;9MKp_|mObMJI%mNqxI3o&*^iGVdePeuMOz;j zd?~WY>;u=yV-tic)`@&*rSxT6<0~-yl`PmnAXUN1jiV0j9)}r6F~N4zX{E8D0mm!w zlr+NVnouPc$;j{9AtFC&mXGn^0KZ(;@$1rV!kKY~@>M6l>wn^L=7>qni>VSwT&Onx zk&D-U1gR1Fxm2l^aVWyeX@T~{Yav6|OwzRJRU}v)Gu^DAZu=xvG4XR(_S=2-{hnTL7S!gx&CAS=u_55^gXdDg<{)?vKm zFz)75pHT4K5X9fg+Yl_c-Xf`VaBLZ0Cl+2>)M&Z(gpC0*T3fygg(7c-4nGV~vP>*P zL5k8XXgiJc!4IrV1GKz7-GtbP;e3PY6Q31``X;GwI0;CoJpPrFwk?Jj91`asyb}D0 zjrFjG!r1;P?#TwUC5B^zk_l8u67&@E4Ks723QwqKz&`jzgb6stIP?6_ zh4`oG?7kQt^=CT8&EQxYu*7Ke5furHJ{1+_3DPTK8GG@*fBf+bhOb@w zgvaKBj|h_t6ubF0*XfD|e>p%AdD$xk|e@@Bu|Ap%wS3)SQ`xDo9T(&2( z{tsUFIIKoq_s?F}f6$~Ywf-Gl_j=(#z_R-o%GF+TkkW+LwREz@ovHo(=Te0%cC@ag zh0@}DTyfj8wh||U#$E0xbMN;TM8{KH)dbK79uA?m-4?3!^Rmf)II=WjjQ3=1|IQVl z#1e;#*QU({a-47R$q)L-_A#&w8{jFB3?7UFJN@bgkP+i@u)jnjq29Tc$I z`?RaY13|GgubXzQyz*GXI@xNMp~nEJsTy3OKtZRx`n&Y zO_A9W8B3=KWucYFR)-9D_H_yh#%Z5Ew)95RejQPTTWMO(O0s)P zeSptmxdqTtb~e?JpW+Lso4?sVbJ#-=Yxjf4_*waj3p^&>8s*lR8Y0WFHlF6ZafV-C zgc+XRkmzQd(HP&RwZ%spiL^1+sH;u?jI4EP>rL*MLRuFD6uah>&4mO$f_qraRGmaJ%&t-lgipuly?%-c|E9$3>4S0et_A<;Gx7)|)ZB%Sx}#DAkW&nGq!e zk_k4P@{Ni#`DT1TX9hKflYI+%<;{sjc5J>I_3RDjd>cJrS^TraPnU6PzKrF}DW5c8 zZSW>$9V?l(WpHD5gv}xA!5tGTpRNTX%KeKmVyk0*}3Qv5}rZ{Ec7}j0yIX;tbT0ZM6`5-82@ph4djJx6y8P#1hoe|K^%gqNSD^xHe zuHdR{c#KwOpD>LLzYXvS5-nkejpFvE^=9M|GDA19Aq%O@&530uI0Saq`mkOpymi(O zT2`D@ZLOv2St}g>>@D_99O2sr!k}{54qkD*iT!1V@&R7P_ii?ZK%OI=51;0G%SG8Gy9n7L=MLGMu8$_#S{MvmF zU40v8BH*>BIoSfr%)t36*{1I#f>~qHB0$D3h7edA-nDu)hD~%$UaTG^?I_I#$<2FG z81u*C%ui>IYc*ue0XOT@XJDhf6vpEgA_>)Q`Yl07#0X%dsd&JvU6carBhI{a;v$ZB z@TVX6!$%reOG)U%Ie~Y*>lQYu*ub17P)Yuxqa!|8aM8+-q(E+q7G8TdV{YQ{K*07w zD$SQBiG$}G8G?Jj4?#|#vbM3pStcR9^;7BOz8l<~$7r#;O=WKW+F!!+OZ2CVFDpdk@Byz^7_|0Zg4^34~>E}^Hgm9jb8G<=0hMV zL6VC-NHWt5ItN@%8Ac9|SxWgJaN6vh({o+#+lO~-J3F@BMmx!lZQHh;#G zV>eD3wCUTE-~aF)d=J*Fvo+7$a~-UC?$3O#s;(P8X4%1U1L*I6bJF4_Z8xH_wF{Y# z61#2YBRcH|mvKs8Su1xGEP%2j;glSNtco1N(PD*3LSTTQ%i0R;T zFPe-{(O>^yWwv-Cet7O{nbzu!&BqmSqqYSy(I}uU@zRagK*7 zRO*)(xa#15!m~}7!+@+_7XC=&26`iXlm2iYi1eQ%)t z8;4;(5;RQqPck_s{oDh;I7U$F<14Da*F_@fFlhN&+?4AJ(QdR& zzv-E`5?_tDOxP1>NnW$_EJfbyG|Z99>r{3%K&k=BtbD*QT2BtJ6BAj=Qi(*W44jTv zSFoO6M!Rd(3XIV@ew0TR@mp)yRbePP8c-sPQd;c0uDy2I5i}9t<7Yo9jjg_S)awPB z&xxZiJEGko7fPWkV6@I}m94hNmE!&>5kin8!fb)O`ulMEMCgmv-g<6xCZwp$5%qKF zZ(y>X-XpS^g7GsI1z%%g`OUofR+8tAX86QFGS9BCMZ;TG4zGsd7+(4$cf#*$^rcvZ z56ASzh$HcFN_a+ohq>L6XPigw0Q*|Q2rc@$*ZQmeSW<_VvwWPB`&trEi&Z39QTw0( zBJuKQlC5q$n*|jk~4{YQhGL}jGyp!6LB!_5OW>Tq&MJP^W<^me}^PQe*WH@6+ z>jBqX_0g?l_L(B*`)WvEX|=$~^u8)f5D`-1qfPTC6dxqbuJIv{ z)izpd5aDLu2$xB&`tT4IbjH}03@kT}=e7C4M!Cwcs3fVV_o>}4e`wa50fLR}4FUlJ zLG%`~T~MPbbX7ST2fh-Ji9nb{ppa9HlPKLt=kl&H=_kJ1zE)72sq+aSeJi}3tePGw zCv!Go{2oWjp_dSZnq7kvCu*K~gfW7~FBFMp^RC`Km86Dz}GJmhB70;tmA%d=#$QS+SSWfq~&g; z<)MhqQq1?!AyTA|$$e2du9N=!<~!lUM+V`|$)J`(a*Z#GP#!3?Ha~voWm8&<4Jw`j zXJX83$j!e-oh8^H6iF;P-}eNP!5!kA>wT&}1rsk4@bnk$bez?=icH8sR`ql&jP|){ zQPSO4Lads$=)(#HSsnYhjGfCgEkobr#fIL=bOYyrhRiZG@t z6E4D@nQ$<;z|a1IkfL^LGY#N0zzHzt>(Fa%2Cy|r{dpYva9o`?k}4O<0!1pl;MfOzGyM6oq0N%GdIk3fERiBhqX9j^>iCydF}KO89E zX32DNcm$F#XC86$Y_IQqA7Ce0Q!%cL(9@$3++Km3^oYAK)5QwsO5-X_iw2gbTk)}5 zf8?AAw`Vxj1Vca>N(jQG{)v5Ca!oe323EtKqEogc1F(_=f60Oq_aXv^nWr_%kq;#) zXJ<1Q>j=d)T$nCUdY`YDb61h$BcRXQ~hCe7jeWr26o zdasKF!4PExU`GYHJE8t7SN$eBnRWd|D$UbA!Iik?`}F+myyN%n>G_IL)zALhk3N2~ zx4*A{KYGsoUb~|F@iV=K`S??8Hcf-nS6!RBP za}N2O|6aW2Bn}#7jisek9=9&U#-r=!@@`y)lFV-j=6V{-ZNjX(1_tH?gpGEcV?+7}b;%#ZtV?f+81E3)g z7aqtEPuYmc8o%O`CEgHv5g0im1bTq&VP)?|j*7l(8e2#-kMVpP|4JlBWIU5h`91mN z)5;?j*j6Dw<^#1_md_wNVfYBO=_>3eVZoYwRM;2cXjxu_uCnf$7uE5a@)ds4{~J<9 z$uvxkrR$sA3(xfI3CGwQQ_dv8G3TRSc$Pyo0j%!FkH?=L5dWL?|MxdhD_{#l8!U^C zUVecKg+;Ac$jx`-KN|z>M}R$1h;UdpX)s{4PQSnX$W5vDaf6%`#f^ZU*ka@lOvGKcL~U<$=7im?K>j;1 zR?+FAd=t8pYU6J{_s?b`6S4ZLX^eU0_)%;d3R-BXyZRH^H-e>G993=*pWRg(i_(f1$=L?HDs@_#N7k;#gX;mI zlA8Yt=0{4e;!0iRNp!PWMmjY>uE#bOyI7}L8@N3*B=sF@J>9N{mlVX|;*7{uJ;Yy~ zUN9S-tl?BO`5g8finXm0t!@~v(vHSZNIA&4OyF;j7{g0m$qUd$tb(&Q)HF&q${9~W zXHp49>Mb~;?Ru1Ysh^&g3_=T~X-#l1%{GzSbYqL*Kvp3ODv9YuT(H?-x-KzjGHW|3 zM3OxmkIbIEd_%B2y})D<_XirmJKO|5P!-x9#76>w+oLTbFEmkDuzUi6028%AV$qn& zUo@~LTeq3NWE?^57lk8kR^g~_U#zZOM4}TKQ$I!474;FFC};>jS#|5lQI!_*l7)1z zWCPjQ?^MbKN8H9n)KX5ziRQ*-@%A3MzVaQA+7h2^R7i!pR(eRxi2dnYP--9` zPX{cQLS|sZeL4nsFVn+tQr*#W^gMK?AX?i9nVW}?-F(!;8QbxaIK-XP-{zZ7ts27V6_iDKI`tU3pz%2m#oaGdm`aUHQ=xo;9=v=QpR#y{ry z;Jk5ZM>4%R_nFt&YW-$Hza_gC){9&SNzU*>Ik6o-WDB`GCYYX?Z)`DRhi-y2j@(m9 zX0ycGN1;!9u?|1n&7&4n(DvTvR%Oa*wzg}I7K>> zt5>s5tbewaC~QdAPC4hsk|2n?qx{?X9A6mxul)1Cuz&Gw6uz`nA??!@`ZSP^DfXDy z=;iRIZn9{Kr_mvw9~pNxBrBA? z%}d1=7ky;SoqN4?-0unv<*K!Kw(klh%5>YFCTMqxiitRjaK+Gj-zQU0fdjy;nl{p6jTvFG>m*%E!T z_xNpRpZoR-l32&VcA^aCE!2=N07V=3h9(s_OTY`~9V(OGpw>R~j#%DI5c>>d%@|@_ zIXz{!ZFU3u?^s>aLJPenC~N6~#n`6Dtg}>`ljgrhr=05!G$91PA@bnev!K&?vZ$*^ z+oITIz6Z{hx!$V!I3d5sPjWbTExFTVb~8)4h{X%SI5aTc8Kq_ulVL^R4hMzA9m^!m z=J=k$$HHL$FV>D=1Q=RmuOhE{qk`_VUlVVG&#QLD{nFZd=#XPBQPcot!4fz_Ji zNyFNQ0;$|M<}0y*OZh71R6*Z@%2E^mtzSz*m9{+DR+KuEEs%A}HK9p9+jsSl&A#gW=!rt%TnG|H=Z!)#>xg>^T@l{e*axRNC%i>KnILPDsfk8)5gzjWh=knj+;3V`5_^10jEf`31rfT5th%_Cc9owoKB=#@j%Z^2)r| zL0CI2iitIX-e*Q!_^Z1nA`@3R-Mr|ek=PK0>xAdxr)9^Pus^lnmfHbnyf|q~RFa)R8U*3MU%W48TIX|E$0=_N{MVt6 zHwE=XFnfZ48_cE!+g8TAan)nr`PHD|3&!{zugZ{wS+*mj-UM6W1N=JkNzYsmP6;TsFN+b<4lTfu9N*B2XpR-e!Z9C?ue?4TZ#1r zxr1FrsGlK4XXyNO$YW7Zv#IT}M(CXEb^RI+OmAx@=XK0K^LU}%c;PR^fhP~8U3CyL zXNd@7_SdRu0-6=PVm&?iR)r;o6D+#W)5Z$o*>b{AtWP9d_Y}hlWI?+tRwRAl0yyM_ zE0_vfjG8|IhxN^km${DC#ppr{i9F;rF2Q}{dpRqJ8 z??#d-*;t&yY;iQYcq!Brm+_#tW1F(?Q%|N`3#vXAN`v8c}lJ_neELMMjNE- zv@QawOeBg!obpXMahn%LD>qfS8X?nVU2ddGy>gM3mDL8E?0)VW7D5HI_?$-4Yj9U( z#xPC;eQWk0tfoJ)~n$eOQ63zge4LoHG7wshnlzWdpxAeYP0OZ$Tj_vF4p zsZYbvdf%9s#=SGs>5*424TFX}R8xXBxXhP>!UxK9DF1>jE@3J#X<- zhGmv@8oVJUGAFnr^2DmaB~6I-0_u|nP&{kp>80zI)v`W z`B^eyM>m|ShwJ;Ds>BRov?`EM{gI!5g(7I#l57F@fvb+lw-FI1+e zZOFacrW>9OTS`v5ruLLRo9S5?BbqI7)y?pw0ikX+PQ@{Fy@>{bY`0~T%wueHpeO|JN=amvEhWw=a;<}aeRuMhTIOiH~H5 z=CZmoZzlot3jN?Khgr+)W++j|+=zL2;b#_CC^R)4ttvi*nV0_I(nom3y4A~wBYMJ` z=mh-5;)DZSV=Iv~dkA&Ck*cBkalPBdSwvn~OYBoBN81i9iA{2;~Y>cS2G7~=c7>2oaherbz7^$*h;Kq7aIqss<+>2nn3RPt-b>7%EPYby_ z`%;wc^^+4S8fIY18FBf7ZBjIylXUfMOu7H(;A+lL9*%#p>}^?9>2Q>DtVs7f(NCFN z8^KeQp%wzy4a0|z_1B)iAAR{W`{%pAhYigQ3&wB%oP9g6CzK*RGYnvM+3PSI{rhQ` z@ZAmep+-?C`|s;*!~H7H)sMbU1CDe<|BqF_k4H}LH(S5o?hSsg9sTNhrd&dAy2j?; zze*ROJxTn@x?6EPLA$7Bg+?B~x*crs|1C!{I(_@gpXiv41+<;>YZ?S;cZ2p|)^K<< z{%u$`$l3pc5&uD(=dR-I+dJbu{Hlfjhk&2ccf^w8^~i+x*HJ;ABo!A+dp*l_IuQeT;TB*?NNFKgfvv1G0*S)S_4X% z6O84)chtAI6%?o(ILp%R$^EQF{&da1{tkLDt{1H*`g@`cN};_M?A$Y$gkf3_t$4&C z`Rukd9t13B+`pgsXG(t17d%V#TTkD;F}yOP>E1mGd{7-f8+tP%y4Cg2s4)I?t^@2{ z{);B~eEXJUsCsg*#^#;&FQ%kbBl!2Qi0=*OyI@|#_c@b&@jzqJS=sLk^M}T@Esp)a zsd^tbe?8#(2@?C5#~YTt)qgXb=PwHMZ)`wp`Ht0ZJ8e&HQ~U6m;$?%U)BPOi_&wUQ zYes{}z;RkL%j*lX$CISmc!RJv=1PK%_usp9&~K*#E(qN|pNrdu*SUG2;E4X;{Q1KT zioZM#<(PdS4gRvm22D7))a{U$zbS@Wcwtf zHg!2Ul9q5ALd%6ar=^a(+imjw<=}{~SLZ=LvbTigVEVP~Qh)GQdPn|J${d-&B8l;1 zX6oav8~)KCfpLbKI}{*hg3O|WlDBX<(gDwdI$u@dxK1o?#a#hk)Pfgr!Hr=AwE+4Y zy)$w{Fk=uAm>~+Ye{eYkjso{gQ1 zp%(}JIGv{Bm~kPB_6Q#evXC*$(ru=J--=_0@(a`2Y{Nmo`>A1CnYkubU05u3ZnB7S zV)U0bxiFj}QPi?>j|E-~ZffCig$_)2reA9z+sZ?xG7cr^y7CQcX9s=a#Z=I_7b0@n zvRV_u{nPD=eUY|!tCKbE3HAfFE|5qvVHX;^O~OEmCj$`O(zK=NAXu)2;-lDrPLl*` z=UVH#MD`IQi}lYS7gY%CiuP(}GeF4i&hd@lskT2u>O-FHl0z!sDc#uUGy{;guI~SP2J)VJid;`k-O2Q+y^iCI0#cusZbpp+sERnDa0g|EpzAwq|HXM zY(%1B1IY+^H;=>;Swk3}{CvuBUA6q*`$Pu9z+ZvdW8rjITm;2al>(I&Ro6rHgLVn2UD*5BM+6@5*%tBK=GU3#VD%;?9y ziBvc`Q~mULT5DL{EG$WlzuaXSl`>V!qg-9nIm#bNobS z4FPa%)RJw4I_RLRWd`w)3(NgzR|jFlR&)V@oF~XShIgZy0`gdg!VerGS*-#7WXd;& zCQUIz5c*p0w{+!idoMAtKfL`ulqnOoQX9(_Zyl1?H!=EJGFYd}q*;Z$$cmcMMyQmawQ%HEXNcHA^2NyUe zSe1KvUF0HTzu0Di!!jaaLK##z^biT+6anD~55Y{9O(YuthwU&ytOZe2*lOBJgx&zQ z)5*DZQBLV%%=tkYPgfLYU{7eA-JN_Yv@EGJ2C@bFtyvvKFzNfY`sts3N$l)NLrs{> z4rou(d;hE6nmC3G17@-F&Why+1nq&>WyHoTNSQmha-<0Hw95$zv>{A0YWXc(?0EP0 zTaiwliYcnHKJ#D@dlIfo8%AtS0}AW60T4F`X#`(35WiAVll2GHz$@QCWC)H32~Y&{ z7|zqUt%V=7(I3v*@>o!Lj0W$p!>eRF>BkDCkafkdJQfK{*26}V6~$JQ5diVsGNW>kIuN&6r3O1L}W5hs`*eHdxKMNBCns>2^$WgJ=_1RLm%+MhHyni zL~jHIqq_%~@d;Z;3D=}Tcb~Y))6bSx zMalp#B3Y+0d+u5A!}DzO;uQizuh0Ssnsv@CAJzOySE=`sYB05-3|a2Ig=lk4&>VBVd%9P{_D#YlJQS*wLQcCyaN< z;SOrs)9=;5Z1j#TY8A(>TQ{T8=sbr{kHq|!^`n9~0sX9!S)*Tk001?Pgx;U{qCwj+{-UD#9m_V zTobnzS89&Ek2QcD;zh$P9Y&Z7-Lv3Ox*l73(D=_yGm;2*QJw^0fT8ZEDF%Zyq<_RE zt=G#v?+L^|r@4^k(oQz`9!5^46F+6iOF2J#&_Vgc86!45igPhz-jO*d8Jag8>9yZl zz%o7JZ^0$Mj!t;&8cBM)8Fs)(Z~e70Cekpb037TU=I4?X6}IBE>WZps7G zIqfm7P5wbY`+;Uz-j@SStc~lUzrZgnjXOdn?(IlCKC`+K*v`kLDr{G5@Up~9dp4Y5 z*Xaj-&?Qy@Uy)BkUk6P(yZF+HK=*uW4jRyyv9klAZ=(Ffd$s~ve`%r8!<#q9J0Bo! z76eE~@b$}zu;ijj>`jv=0MEY^VQ}mbq$NYU@p2Ia?J8#swmrE}HXzl^{A|J3;u=2y zpD^oy=IWgcLE(?CnYTQwYgVyO<{BY%R#nuG(NMBKVJQr&#D^oYHpGeAUPAS1M-F*K z^k5x~0M{50=IUO*Ho_Ha8rTuDT7;DtblSb;%+I9al5QLdbHEg?@r?mM3BVfRecDTC zW3wNo(<(iTK^26hnrL!z<-}KZTX{|3XL2~k4eeU+CqUeDW?Gd5MI9ltrz)*oaK(os z=G^hc+uFq>r)Wm4pP*4r8N+BTma`j3CEFgx7=2zQiK$%z6Hu<4o>0C&cE6OY!Z@5- z)QuJj5g2o#&X1WQER~hC#}PoirX5SREM;pm);Q$O4)2t-O}qykzAfs-#^!yChP253 z@PJJoYXtX(XgnqXRh9Orz{=*dg9Mfdqz2kR`IfyhtSci})%By|V4e-BGYHw}dSNq@ z`G{BB9*h&m9Z`}tii5(mgtA9B`DWGfz^v{a)aGjK_Q%;|Nb1;2V?#M=^wM zb!(8cC*q`wpl)cJfX~=dk;sk-4Igr(E4f*z&qxw8LbR|kyHD4sHGFRzjdC1tLBdDPhy?Siz@P;-Cv4KxU&J0ZMTZ2C(m76ZLjT$5+ zVuAFe*p3*W3))WlMR-ql7%p5rR5OX$Po zt%8SKTrv>1?Kdxiq)FUtonpXs#yXFZOJG9C$3XGDfx?fnr(MYo^(Q^yw-K2; z-A!*G`rQ^Rz|CmhzG|M!$dm=mu|jldKgz_5u+m8ZrQa3jVMU<m zlbpX_Tq>g-?FYrkdD&TfLSnwNRmfiF8ksEf>rEp7u5Ce*q)pg+XcBY9H=Rr$(a7J6 zMmV;c-5o1c7{Tl3#(8x)eXbT|K+VC@J*6h+6G|!JnludJ5l~w$0jn~yFdW%Tgu4wa zLxQ+KxIN>Ljex9#m4v+sVZ#-Srj+K}Jq~BJ=v66{YjYvNH~mL@KkJjNs{G~bS&utB zDUSl0Q^?6+az0J(s}P`fdS0>9t8bz_L%2Y63LJ#I!%^s>4J&CNMmK=tK8q3}>KHnB z4atK%)O(B=LVxvisw`idfM~cfuE5b{-G2o|L*V7%A1@~wjfQr67;=uU4{{u-m?bGl z`1k#80r}i{68z}R=lxaz|HGs~JG5*o!i%>j9-nyl@b&PP)~DP=WH66_&sVVRc-Mp7 zR$0fAueTSx3_7bKJVE4%^h2HF4hLRC=-CodBrIt@Fq=FqV!G`Pkafa;+0Jhay*lU_ zW!Vii*m7gl2HB%}tS2iEl~h}SGBuJxCh(OaR%ae- zEV<)=d{$Q(8gY)Qf~g(3D&hhA;rHTA?IzF&=a5Y*q`RW3IAmb{)4JmGS%Q5H$BM>Q z5uP{5Ds|XqaBv(XL_PX&u~`3gCf|`E3oDF)T~H-Vdm9F%BG<`KEc|IkL@%(qobqpK z2m$lQG;SsPIAeOt`zm~1E#T5 z6z@j%U=e)(lFX$&m0@J-RF!-dwsg->gg)4T5)~!|qch9*C`RIoIGsOiQOZqRzxUej z>Zx`{$}bYp1Z`*D5r9Z%;-~TT=)Wgno7uz6Sei?0g4w>!WK(B$YQXW_CMhTco?Ik0 z&}Q;gxj`@YlmO3go^|%)WQHS4S@3J7l2pqyj!oYA7AIG!48oowNg-oZj?ilkMF=Bc z;D>f`L<5X5zcBReYiMKM1R~CE0cq5*D(5RF3W>P_NA`O}`_lto?2*p{Yj{=; zWYBhK-%pcz%hE&?jx7C${JRWXG2@zH4TtEML1l|%m;+3?i9)DzSj1gwAZ~NI&m3kW z$|@i~axOPC5DghiKR6LZdDIKg9qy1=Q?5y&>W4Q^ zk;#i?^A5(;#M3WPaV+ks<-u{zSf38NEqs$3H}xAOP(K7e9i$IAeJOTQP^FqmLL4JF z!43qsnk1+9(`A#1@o_%UPo|@sC!+ zkeYBpu(&L5iI4A?C~nNvt{EYhyCNbeG@W8w5O&ccNYdWYF(7#fa(XOyBwR>^hW%5` zOUN_(jat~bT;YZ|+lFP7XD+9c9FpLeYz$vXAx3j_M_XPV$B__B!y%F;?N}7NMv4_K z(BoraB%pyh%{6q04ODX3%upJ35!+(}M*xs;vabuumvWO^rvrk)5cR{rI zQrY0CYE>byHCg%{Y*f+)x7w4&G9$7(w|J7X+SGYW`%HEHL%vh7rjyxF>adb`H<1B# zv$L_QB8I*dfDSEED;;|4qfPWxE`A!X=9QE&% zD7kvsOF8*8dm;&P*M=#g%2iY5@WeQhSo%7a0*%t3IyV+XJp&FWG;{C~U9LHuIHL5I zMp1^AI{~j*<3L*^^)j)3xs9&{q!m!I%v^96xz1clG!KUaAsIt5ivD8k0~uM>Uipt( z%Zv0i+NE-cU7+&HPMNXhAgAOvnh_~#-p|pfFvz9N&g(a~F ze0Lgvz-cR6eY&*6NwM(BRmr_dR2~V-D#oliRndvmOl@_}9cDKw$96AK_A44S#oZbZ z?@%b_sq0t3UrbHVD$}S}pMBtM%b(WUM@-YjDnlt;tD_4AxyD+eTIXpxGvezqMkrDk zIvJ$Iq*W)7aKf*bK1oB-z;LEF^sFwR?6n2LRd$P6=P;;ZvH@5znxGCksZ-iaY{T_T z)nP`9jS%4Eha^Q=c;q#+t|%Ibd*Te_V*PrK%r+vUsvMVrV=6 zr5v(-vb5vSIBEZ2#{k@G`NS>Q9i@WJARRZM5vqjMN}ffaz&C(ZP**feQ&~wY8Z#DI z7E`DALr91!r5S%EOJ}hDdsC%mdY=|BhaI9u5A4bpfv2&%jXKg9)ODNqr zq|W_f9h)kr&RvT9%wi-VKe_u7{99Fxn^izDM`_Y9ipK1d0>zZ_TuefOb^LDK5w$2C z`|@kdI*#`sd$@2f7X5KBEVlYmWm|a0GSq_B(~|MT$hw*Zn~u9pJ>}fNSJ%7&Ql&E2 z;%Rm_HCTG6z1ks)37!<2=~6r*)N`Ga_rMw@z)+%p5uuU*4J7r^axF0C_3&%NIt43> z@hKAvVS_sbu2M4>)2cXir4sv~^oxp^%!tL^c8ob@FO?rx;SFw4Z8I_f2=2BfQ#5FMlm^R5n+&nn40U9YzS*1C+D}n;!Fvsll z8LTgr1qk9CN{{L-gQg>MfD8HE$Y`R`4p~R64$K_L5fO5wrjrWIECtxG{fa?1^WHdf zSQm=28qLk1R7s3`i7_B`;I~2vz0EqJ@J9zSK>E6?s)q{K4ADorh*@=oV%b$id_Aye zY>z=P9uU{u|Gc9}p$W~c5{NK6fH$`*b9o5P+)wWIj4i&9NAQZFD@GM0OMNmGu`l~l zyQ;ddho&1$FfA@*@9Z_YU`3%V7V@;K;<-e%!EjkN3&+fAup?l=3mgHNqUNCa=uQp^sL`3=7*xGqgZfg#hY>sY?rhYq(TRdbI3#L; z9V|oAJ_Lcn4KN?qQN%488G(f7NwZtR#HhBVpdY;Pz-kn)o7NZH=x;Xz6wb-SI;1Mq zA&kR}F&4HWROja;)#g885m;of&caCxoY)x0@Ypg1M9gH(F550K)+zBv=I$Z+TJ51t zs*&to#YFfi^-9k1FgOr`kgjUf{{5LBM~uJ%VR*G1 zgus?QtJ)%?WN0kN*+6*aMAlS7psWx&6|N7gsaRMD^aakapl);BjXoBe7|~PaWwGDE zAzcS&M+@UJUdX_(%o8cir|WX2=ljKn>v4b^V3}#|s60>=EdnzKci;^MO*kLrvm;7u zH*n8QXrZk1U$3D}k?5*Q0~=@s&DoxlGs4`q;=RqMYG<^$Nvd?|+asWrs_a{2aC7aZ zq(Ud+#V}#Msxs5{eVKtQNlHpVCgk}%kV%lRzQ+Az*N&yin#@yTf^VN4t@!Jim%3O)d;t&H)8Vh{_}djEAL#j^>e>0 zl%ZoNrHZN{2Ql7HDky@b%3`Of=R9mA9=q~**1s6O)aYV{Gh!&=^7ZCUM$JPc$@owU z(Lgj~Wi?qEGZR6q5^~?(G_&XH$o@9lGOjud-#1-2bfb>JZtPvmGwpzBNOhB(0re^zkXK+z6(V1BMHX2Ro- znmuSFMjkre2J>roN|LUwZYx1G=DF=+!;)nLYhw8J*@apTKl(6)PTZif@{3wQ$j>IV z2Z;sF5Ycars@D+>|Bl>UiEIP8w`pWJrk)-(j`2!xgipHeD@;)7 z)iwyfD_jKQL=iWeltO7nxeyI2w+1imhqL6^`L!Ju!rH@Da}*XKRU=sp&^X8HNJJC? z&np_B$i0PSsqwlbBrl&TKz7-6Trl)3$YDm#F|_5~W;RokN@4YcstsM~?-QXpL)@hk zyQ-m$NFz_9;NwOszYG2gafuBaSnosG!E_%sCxY=kl@O-EoGKz}JN-hRWZaOXOc+-n zB}JH0^`EC9>|c>0v7IOf?bz7KHGSX#S%p%^1er*5OBt%jJp!FS13kh5i8i~~NA`AT zU-8;?J}yvOMP?4fozLSQby@v)jBJaliGW7lKPt&Rmei66jD&b9F>as`CILOtSrjAi zo(Y(}WI&0u92~DWcvaz!P-B(GIx-U44HpE?ps}F@-54WbebJ%%vUNnti7mDh5%^A$ zSGEwVc9F~#b+St8I|FiJC>-npIfk{GnV7#7L$JO(DgHKD#MOpE^%wc zX_eLHgzALE5)M?X{XJI4(48@~SR8f$1>^UzLt*4O!=+|Nj?HU{_^%5w(nR(`J>=m_ z5k;mw3>uDYJwIrZ+UH?7vX+$yC{-MDK_ux0R3DyjfbkU-1maXPMEXS}Pz204RA27j zpr*;4c))n;pCWjzfG7BZiF=EaqvM|7cY z&K?oit^TgSaxJ_RS1pVWdMNd~!@CH2r(arcPPhO==y;Lw!K)0}c2zYf@mfUIT3Vys z(0zvx>hW`jQ7>i}6C#lXvHJYf^mBPKluVmIGnp{Cmg4wQ*^6JIEb#v4fjMJ{h}8Pz zfB?UJ_?K8Qn^y&&ss)Wj^COU`h-Q7wc$}T*MdIMsUlh$>7x7JKH_ROq)Bb5zrnltH zO=GlR!i^{B*5()t3gh~Cw2WyYFGc)H@Rl)_+VA2JZ@UOfCp2{T<7~9^Yb4RcBKr>g zO!CCwut%GnLOXH%u!5N~7>Lk!A&IS}){z;-cM`d+IZlsDK7z>QkJb|ekeLYGf@3($HGr}wA2IM`fvdFr2+ZL{!uszv1+DM4yr z;zpD8Sx#dx&BT=lzLozOFls$Qmd2eChhtnaNNwwqrAc(#)q-2y*TlWaPR_Y#ki=O} zwC((9WXlLLmxKZ%F%UP-?8RVcbTBvM!-Ryn86@R$5r`AA7S*;hEboVRk7y(9 z8LaK*g_~L2JYtVSsswf#=6qIY@;EB#6AQIh3(?eO*yY`iM#$dEqf9d*>xk32G`Qa) z+k4hP*bq)|o%0;^o1O!7Z1T!#e4)XR9hIKVTMzT~sf0>%ux?PZl;=7OzBrMqQ%Jf+ zw*?9E9a0bNh2Po4ho4@C@o%MQk=+sh_%qb5Qiq}%4P%^+<_N{kr{Ulh9(y7?o?_N@ z-nQa9d{Z1Z@aIwH2J)ZLjfL%T3q}VK!*m|7Klz1-wVS5*e%w|Fn+{8pc ztB=cy9u4h`r1OBmaxHX*)h(mB%TitYFF$je|M%nMm{@~#nD3bRrngdA0gY1>zC?= zHnBmS^uSpJvZHxVtRE(P;*1XH9dI>jn)Aw14`GPq&~w&j`-1M9a?-;sGp9T5I{aF9 z(;?&*2)Bu2;JQ4Bz3Lu0sw$P0!_d*c&I2}}Kjxd_PACu6Lz=WFUpF4&G=gd0DQhi8r81 z=4Bk_tqsyZbQ#w>xrAV-5CA_biH;uVj&goE>}DleLN(AG#4|61;?aVdi;zzi|2#K+ z%x-3H8zuTdM>zXOUhnSo^>69#e;Pi2G9DgmWwVBAq!z&i_;qgupv{9S!uIQiP_(ZqxtiZh;FGs9Wq!gRTG zZ68@MZ4z^tVqn+v{^}sO-|xq7K(oZ@gr*Mn5MN^7q00zg)H<>=@J~4)QNI`8uNGrJ5r{UevT9Gu3+uk2cqDeMsX+rdPZZS>EsW@63dTZ$bIaP_x zb-bqEZGUGT)?x{m5_*R^kFPC>zdC%iUmi9>COklbNN;b|LPoR?rn;(IOA6 zW&}CYL$agq3zU93{)4;#W~9`F%j%{Sg0v^Gj2T_b}7RsV} zw;;&Kc!RHka^4ywbjJ=AN64A`>6}*T1Dz~us>nuZa1=pp@7Yhphy7NFzgn(Zw2ls7 zT#-2HYK{V$7VXJh6gLPX+h?K8aGVC1{9w$IvLov8^DU~w)aa2k196@t=+6TYd(4JB zFpSC&19>6Ce-FlN%NtwjdbLTw1dp4X6Al7f;OG>UWV;f(dnOco!)%;6EXjNNz zT67g&i*wUuutJXsgs4n-+JV*MxfTMVfnBJsFD|AG1a(%|Vgp zbuEQo@x9o258z#&Gv=!BzVkJ%p^e5@p=Zn#^65=ejgsT-QD1qUd2+wgVWs)g%;hCc zWGWTDJMtEoA$3WO@Ko!{qM8Oh>sZtI6SV;5{{THe!oMKpxOVh1#E0b2dr0;avQ~|+ zv{0lnRyGv^5Hh zfM*)RAy-A16e4TGSP&Z#C{w#huyS0Xhi?uq9&U&YsTGp9jw7j(RVVFHlrr{=rvQNLUWO zd?qKlqxf zN^@&%9kG;!RLEF4Utv^IZspw_ppEVab2y8tcY>=gWV4)fb(^xf9I=Lj3YsgmM=Z2= zg_Wwr+Q|U{xd%+mAtm=Zav@^ zuqf6y{I=Yq&kqJ#Dn5pIBe#c17o|FAi1|WkCC9$^<>S zXRx9y#7<0)Bvd1?u-k?ZnI>Y@i|Hl8K&sh4)sZI;WI#sXU&J}!&( zsO7{S5vzsRKOgOtD)U-l2irGF8WigU6%NP4Lr^9)JbYZDJHuF(?G7QK_bXp2tjdOv&S>-c3zOOk|1R%PdY#|8o3A!vyK<}T|y;jv6LQ+$%*2UwtV1#u* ztHjq1ZKEpN2URNQ3Bm@nvN9^UR;3&Ph^`K+H=re>>K_cE#T3aVdHBi|gjZ$zJQmGi ztNf#5$T-LGUN6pT=?7=mhAG}1Ec&wF^k(qgJ3(%k+Z>*dKamEI&DY_akHqIJG`hg{q)B(PUI+>{vIJ`6UaAfMm`z9(6HhXJT%%+oq2I_RS zP;tZxdI{JWK_1HkmJ>ZQvkDHkK7gT1#GJkBs@fRXV% zR5gB75XLcJxHUHhpzG2RNZtprV6C3(N#2FghTBT88q7(OEUmhs$7*9GFYFT7UJYbWRd?AB*r zK>6;A*JDH7wu(@`Mm!YT=)H=j3eCmfv}wNcLd&ktizCl1bzLxi`^0N^cA2L!G&ZK*mWVL*M(JX4>yZjO0$h> zLzvKaX4T}l$P(is>p`@7eDZA}YArX@No_IdCAc1xl*QYkfFDch#&HHCu$sogTj`_E z)^=P!Up;n;{nn|;BC}$=wETkzYz{^~mBk>84Olfl!zs+vojFcfWop!p`jw!zf+Q6m z-EHB!SR?8tRPCID(&+tObQZvhm=<%@O2&1uIEF0`&&9fhR8=<_nxcsTn`Rhc$S!$} zn%nfcNCs)|v{}5DQb6BE-wolqb)L)h+Rn;vyCna>*6~{2cQ1XGi2c|ydMuHz5MFW| z16vH{0LJYCQ-!?vvS3oxLZ@0ao{)FbDRx-&c?#S-a543M@DyT=!Fg9q9Yt;o_drt! zU#dw-A)uJmqYZP<_=(ym9N$fItne}BRCGTaT%Jhx<3C5JHh;I`w2y(iH-pq5A zG25Kf6bV=<0wOj=)y;@?@1P`Rd$`hV231`q&7|RE!15K zG9z0yj)4RP7nea%=NG=AzUYZgr>!8YESN2P;%Wk(bY&EB`*eL$VS!iFyLK_s3Na@r z_!K7^ctJ|RR*xfz^%_)H&i2rZ2_NdE?(8C46HbzWS&HMfBrIWODS!*8vh+G`3t?>u z9YMwfo3c1e#6Al}MX)7iax5|C5NfUXr$}5OQ6(BZ3MCW;A#I+CU`i;k%uNZ{wr>$Z z;3XlOl*E-kh+X2iSo=`*DudV1W0i!A=o)^DbqOP#A)zGfP^=yA<IzjLorepY@27|C~=8p@2FqWYViiJN%mBaqXy$joj4bFql>29b5}Nd9~D`SLq(F` z(7j`stwf&Djc?T{Dvlju+S^$PEi1uVnYM;yV)E*D$UMTdw#pmHDAo<)-xtnm=xtI9 zmM!y`T60ZN_3j#bdd06us78FI3_+H7NgbOMf!+$|m3o;8DU_^e9&fg1yg@8f_zFeh zskl=g(uBR-APlj0=4JDzVfGZtoiGJij&EElrxh5Hii8j!64at#;dQRn3_f_^v$0io zVCPH}031at&Bi>^IflTgRDx_`+HL1MK;*ztbY9)9U zYgt`etFJ7t;3QMx)z9xHDS|rL>QH6H9kPeYRzhkxC)g!1rI#4fWh3fb_+ ziA7DW5|wFe<46U~>=PM?Wg!wXUkl25NLYD9fn7U}(VZfZ19D-wg?ncT3(W0^ExqW* zkxMV7TVOe;WkyL%EVg*Gl51%dUR$lNnFPotS)Ec##VEKbgzZA`Nh6MQ61znKXdAtr zcspmJC5vz}t{7*@;?P$2&O}OLlBm3!#z|^{XxsbeTP~IsKx`asbB~w^39O-Yk;bF} zK)Xj zL&eL>HFc}QH79w=>dCc7FNiA9=z+_|iz|=WNJEvP71RtoYCv?!yW@6_cH|=k2tI#A`sVk*XL3B#yO6Vxq-AV1|^5sY0H?v3CV9}WTZBGyw+ zvo-9Z_JUm8a8QP^MXnjS=(Ov@F!o|_2~M#au-ril+c&-|=}oYN?rM*|T(^$1_$DzH zv>xnXE}1}F(T1r#Xqv?o2rFQ|KSA$IG8g0#s$0cs!7D~V-I@io3 zWHR`8cZzx{(VB3tnr$%*iNtp|?hB8IonRddOH!KsH17@9+BqpBD&K~>#|YRU?)_6s z-3wa29W|{H$7-;ME`)jaj&UtrYg^V#NnZ~>@<>=u#amSJ8w>sSzA zTu|HIFm0V>D@++Sjgbao-aqS9h>aV^wnt2BXjuwl20#St9@_+=tErhEYG=rR53qU; zz{6dh$svcrUU0Qn{PHNahEE)Q`-CzBZwODP^*Uqh!jIDvRS&=v&a2 z)3t952l~nh=(9EX&sU87e04a3_w2(1!ODDe-*^wM5$n0-U>@5C2rPxic8_x0vAvWH zJGUk5)xmY395fuFA?culyG!Z<+!x+q0qz7#ReJ^g8HK17Ka1Ksm-%VoY|o& zk-&*R*GlK_t3ZsjK%)E*2PrItO@h7x#q{n zEN}7c46(pka4rKVugIP;&)pv;nd@hkHVm{p3r8!kl(QnfLI?ckquOol3ATF(+Gfej{ww8 z(TFVzi`>FF1V?)^NNyTKVd+MCrSW5zgLiz;DsZYt$43BdHPz$$LOgIOXh-YsZ{7Quy)!3+VJAevbD1Yn^pNocT@^8piQC# zeNI#lZkl*x5Exm9*Nb#)acBW-pA_gG*b+`0T05GV;QK^3x+ZK>+a?4sHcPJA9is!b zKjexX^b7;M2$Y$@t*KgO_KIYV;h0=H51^^hy7e9Pi>?w=WxCXgaEmQhEjI^-#Dc3u zE4ebPqFccNc4?rb!kfl6r1TCk%7nr`E-?py-D8tjOqs}{Fl)BWHImTKD5(aLT2PPJ z>hQbmlL)Q>ErsOH5s2;*uXYo);^lfqRgZxpspbO7>ubY3VDZc&cE(CPWZ`JXY!b<+ zgVuJ8Icm|2!)9j4QMa7Ffjh%Ca_JPMTYyS6c12Btw}@?=(QBv~%aZYx`H=^U#V}%F z_(`^cU(94uuHlJxjcRaFD`_X&u3FrZxx1#qOM$cnU~)h7`S`V%mt8 zzK1>mYo-&i1cJ0A%jpucH6$Ym+B?TUqBh1#O18a5+)^qDw}X*#$s9t5K-D02srUmg z3)}FaSAsn}K!7`Z$Cv}G4{@=7K9Y&)($TCP*PwyciE1>e9bpW%YBIWQ8R-IU7jL;X zTtWBF6n0^%Jb}0Oj77ajEa4B1@MWL~Ffc+UiscjpSsEgmt&@yHv@cr6FjV_S4sI#c zAooy0yJZUMdHJ#Sy&|C47y6l{peGD!U7+N18>*h%Nb&4$&`xgx>wH|Q(uuXA1+y-^ zwwO~Zr<~Xp*a>>m_$HT#5!7mM7CR=JUW}@mTq_=sruKzsV&^>5(<0>pxuVKyji^BE zp$PPvDJGXC$S`4QIsGyXx!l$ngJIE%CHIY1WRIw|izorK48%Z6@5+!+Y`6I2Yr`hE zc`}Jv!BUCt90QoO^a$?=_k6W%4$&EaWRNcyuV{1VBezegRbl{~tz#azP88yf-V&0M zh2R`FEhXXL6=N^fhi%vfy2h@6Fhjxa@rN^Nr&z}93de|*pco$kO@8Vv;}^R?^pquU)p9%{UG*I556Zf)Y~QpI{~t4kSj()w?51gR2yiZ8Iv&o#O^VJ?-cp;vQW=1 zoOp6ep0snD#*~q@k*4i>w#>3DAjfk0BdnvpdD1G;GRR&#=DqZ;3hTl-mjueVqQ0fH zEeLVVQP{1rPhO8YRlYG`+gjyrS^(gY+q>Q zR?aH8B2N~Odqyg{L6ov9C=?!%Fx`04n@1&8RFWGKzyNT;2*524jo9)@ zRiq|F%OSON3{q<;R;{8xYSr{n3vwh?trt^2@~Xw%V~^TB^T+|Y5|7?d?}$AjsoF#7 z$d#3&hvj1&u~yWLs%_yLxp218yK<6^*fOqB`@>MVfuhm-@#Pt@c(hbT?GwkSEuk2- zY=Wv;0T7H@FM3gX!!By`+@j{=$~-vL#&J`v60@jH^om-pR@ADBq@tFKQ`FiJQ!So! zT&hu7`9$rgPShgNQZ1rO)S8(@Z3-(AwOOQ88^b(|sI{P^+H1;4wW1DDTf`u04gH~3 z)`zJ-@=%M#iw+%XVTi*l1#gJ$@uUr3Gt$ue!$!M+#*ovaOGdYL1i*z_C*EjBxWcTO zDai6L@`TtfE`qfo3Ew*vEmh^0sP~N^*iMS*YiI|!3havEK~)3YObN}Zu*T~q27qdJ zEa_)4_POQZ9@q@x$=R``9oah4*|pRHS`qG{pf}ApH&R4S5X-5X-A3EgS`dP-jwsjU zrqO}fA;Lk^ODF?3I>a;+yGPkBrV7-eaLl(&F}XRE3^NPr8!x>&lJX+t{X+cQffx62SMqci9;9P8$#}CJEdaR(Mz#-GI4X`N=m(Q zj5N!{N04$AS=o@ocg-7YZ5ZjOmy0ye)=-9BS{P((Q0YSM8gH<)mwAcz-pi3jlIkTb0;U(e(wS~U%jwN7q~?$<0_b1EPAnJ^g@HnEd^sXGM>y*YsM?IKQv$# zP%YUQT@nyW>J-=}PDS}D8uoSI0Y2V$lP?!D`8qo5YiE*A46TuT-MGh*@1(yCJ)~EG zgYd$j8f!PxKXg^-BR7InI8a%w{$96Xyoc=$=TVEnc+ft@wqur#>yTyQ9I+vc1D0!w zYSae?k>B`ox{Yt6MSU$;jqi&nr}0hW8DAlm@f{S8F+MN07UQeOpuSNI#`lE1_|A6m zc}jAN@28|VeRFu#vFXcaO|~wuJVh@YU!q0gCU!ko3E46!<+!ja30Bh)gt&EKNXJ=+ z+7<)+h}Vp1m<3`ObZc9Pbpmq=xTUH>SoDSBM6xE_LG5fpI8I9Tvm3^G<{_O}KjYA} z@bZZ^x21MqH;T`EQ#gUyH-outYEsLt8LNDS*hG}sLROXpxE=En+U~WISSb!*6h5*$ z`@>}sKq9qY6e5dz1;|&=KX_PN*+(uMQ`uHp;iEcxPgkQS>a_hWbYVDhS<>;AiRzEGQXI0@1ll#TDT>Hy5eoyXoPSa{+37Lf z%fos5e1{3kbw@py(s2zX!s!-80>8T`uqwby%ns&Xr*nGTF#iDDuAX~G_C-)#HL-;mN+47tOKvkmbiLOPl-5ku^TDu)j_YwXerU< ziU_5i5!i=da8g0& z0H^VU^;Bs#CB=8KN@C7cY04^6IrR|-2@&e{-r+#aoE{QcQ=CpB=S!*_Tgh0JR4cHe zXdA?9T_`4w-XZ_|rr?f1GoK@>T;i-Ru_Lf9h!PuKb^!~;a~|SsY;;dWcoeY)^cp4D zUUa>6y=d>EkzgafC9pnFHv4j+7Xm@0JW_6=2*F4_-O zhu9!@l8+t)tq95*5PaP%3E~S4Qj=$b^y6KzhNC1exGGTX5J0Y>A3~Z8Xe!H+-8eu7 zJp{_m2dy)RK+W2L^+2bqs2WoQSBYyBpxZ;$5K_J|{Gh;Uw*&!RcO|)GDV6~$Q5x;R zNFzIm@mlTS$_fan+&HLaGns>Sjcd;G!muWhFDv#?#}1sUsR9M}#~au7FH700%%5NUR1*OM zdG-LRGl-6!Ky(Ue5Qxs7K!fzq;ULf;K80dkw!Gpg?~7)Dg4gP8vFQ`VgvPhszc^ZXW29W>B6zbO_anZSf+e%a$%& zxWu+_+1lc=)g=s=FI%>7@C8h4ix)9m!h8V(<_j1vTmGT5#f_R79WHJdVBpRMf&S1T zRH#p#L51iHs>A0F9XeZE*6ab)XO}NtZi#sT^CcZTbSR*c&=v+ZV8GCzKzs5Os&i*h z9zc2afSCXd1$5q-^4+Def3<`v&%a(%%<)QN@Pa#5v z2o)3Ca%}9526^z%=`*O#26O-g>Qkr>9zcQa+~TFroj!j86{@p^PV5bxH?s{GVBpW6 z3DU%3u^5;w8-!UP&!9ks2+_flr>l;iJcH=eYIp4P@k56W7cN`qJV1xenlcMOum%ks zE?YLZ!-at^Yqrp#)1{D`2PmL(YnWep*@a6NF~P*ReCe`9%oi?Z%%EAT-N~ZCpLeos zDKzNLL4^qMA(Z7GLxi#{1Srp+KY{M}$&wHuJ6RIyvq3|31`Vo1CyyUHbqdibRLgUx zD-WGJclKm?5FS2s^8BeYNDm!8d9tiis1BY$gR<0ELn)*wn(nWe9R%Q_%e#5D_DV_XrNG4dUflaa6$Xyx2lN( zmQX?M94*PgS>o-pCpNcM*HI1h$li8PSA>!Bd@9lB3u9)z!EHI!;em~z`Bu<7VV~o=JY0U0V=RKY=dj|gi)l(X7GY2JV#vD zUE;SgG$3uFV=vNHjYuwUNLJ|A8v`snrKqH`q&#N z?CzdbGo|xeX`EDZ+kDH_$3@A6kXo#JsivFa=mVPkWtYW?9is}85ad~LWFhE+pVA#A23 zq^b+TZ?2(JAtm&p8LVo1CoF9Rsm3Y6FINaol}&S4Ss!4sh6zimmQ{NT_~nJA>gkeK zYGl=1tgts3rczxLkKe9yoLc+FXVX}fs~BOmdP)^`)9=@cQ(vxPI#f%m@=^+`OGK)b z`tS=W4yWSQu}(OKat-2lD-Wl}-teystGHZcA#A9NQsqtbyL;%=Of?wNKda*A z32S>ns$Jpy^4aE8S~Zt7v+7m^!e;f7>KDsz%LSZDDwKP=WYt|GVRM0`3JC_P-$wH| z^|p>{-&mE;G{SP_r7G*iZ!D)%wO%oH71OHNmcsHLk*cSWelz{yR9zj8OG6(UZQ-sa zyf)EscJS6gtHxq*3xQA<_!ogxTCRFIwKq$xIYv{nddkIJfw+}Lmd-4Bv7{3BLe(j0 zKg9xj#3*@hpmo)p{a0Yt`xM0o70v+OD)0-X0ge0yFw1}$2y0dOK-BMo$xG?EG`uaCwR$eQ<}Zu!0PjBd z@$DO@?P3_PPQ2HLVCJH5+d#t!rYxDi1w=&TC)_!zd5grnxE^3|$SvhuQYGt{M}|tk zJ@{(Xz2guqTs4;U6v^62k7YC%7kYLGP6Xbk6(SfbvMJP{3U8lJ6mZ+X3#Q5< zSyFqVbzb?tF#ceb zI7aG3;0xU{a~Tmc3|b+MQ-+{=LHLKkZ|g_(Fgyl}P+c-M$t){6A}jeB3HZdDX%kPm zln#;McQ&Mhho*`mdlr-|AyIq`)jaiS7SRj@bGOPUP;f$q>;j_&;}h5(9^iy`tB)qT zAVUhED@LuJfJ70CNe+kwFRHkTroD5^64+G&vu;0xI6@Mh)tw!*`GB(lB(bUscGmW*9)8I^%cE{q0l(Vb&#mxo$-C0Ik29w@6b%zdJ>ZK+YP%#O?u3?i>JchrX3 z#N0*+*%9;NffpEb(7Ff{i??TFGlz@|8eVKh(K_6_>3WMo}SWpg#hQAp)2SWGj5s+_yQTaU@Tz_nH5c1z~kK| zL5x`yB%Bk*Y#6x!Rm;L8=BPN6h)>T^&KI~pyr{U)Wt!HhHpP!;Xkn8=i8p;CO?_F! zWTzf1X0doJ(xe+gP*&`sP+*FMOtv$GLWOJwp5}?58lql*6niC`Z zqsujsMj%Ywl8E$5;fNh2HkL4nX9OO_NWuxxhDuQ0HX;!OtPQ(>!2RIn^+cWzV@~12 zca3a%(DiV`i;WI<7@`e__gKOl4pR@f0fwX1(-w<=9(_S5ySu?hK#piD^`VB`qdsGp zVOLL3je0gTSw{xkL18i29BCbaQSYZEwAJ9G1uwvEny7^v4JE8|yA@*=b#IGc;S3D) zVTD;ba;dNp5HG4lJsGMjMyK*97%}jnUN< zp+mBF;$Z0ZLe^a}7a-Wf2D}ysEkT3ZO;J&WW+C{85RZjdAhlfzNM0di@GX+Egg&(r zfE1#K1_BnUzv_&V#T)UBUV)#|gCGwX@qoH_gky#_jEe4FTEhadeIBsaRVAFaNK{lN z2anbuqqTE`?-w?=DnztK7tl;krO|1?=0p9ZhqRCiPu<|x3+@&|(+(9}q1P0ZJ-(m< zp$DxA!Q=rWWWg;{xtTrVg=g-bgYbwATHpkC?WpGtS}*P}SI|Fp$hrxDESZDqPPxFE zAgpCb!D=nL0pkmRXBOuG0bgW5xkiT4@F_)aogrTW#B1a+ZOY z86^3wwWC(8pDH1M)F);Y@a>`2T@=1%YSoCKK%AAc(ucv4V(#jeX`8_hiCQcx<#c_1 zY+)`J&7{>K0b@5f(rCJgGfe`Wi6UkmSqqN-;%-o&;Mj67^ zj`!kq??XK-Y(j-M%`5`0Qc0U0A_2|S2{H_>R#ZuId&qSItp+8L zI+_k}cLAiaxeH_wIht9(#amqkScYkvW5d{496G5XwrdGA;3#;Li5Yl<7$$BB=QNU~ z;3q>&&X8!tAe+VO1w(8Mvo?xzXq?$9($+BxqgW{(h+y`vFiPD)wW!3I08S%bIKh>H zT)0V~sT(r}u&WinH#bFmG6by&-TbLVTRT3eV9Gu*j1cqiDYWypP1rcC8rd2qh}kCf zhC~>un2=WX>Lu>vfFD@XJDK3lV_bvuv5On;dX!)kxMQw%CzT^0d$~6-JKTH1ed> zb~?tB+9iUj@(``iqSl6&9M~-i*K#mZZ=R_sXj<9?!$g*ZOk~BP*rt@ovOAK>03TJD zkgUqoW>OzScgEVKpa^Od$kbI%i2Bw971bC$OIZk@sf9lF_)Rr6RTVpyX+d%Ronbg{5YTT*)f3pd&`C%Iok_~9 zpPurTfNSlOwQRmcF(9D0m45SWV3S)3*i9TLRx>Co!x7|aWzrK2$fUBdPhJpiGkbER zlU+wWYjoF7+W@rp_Bxq0iy_!bL_c9p6!?K#EIL`~5PO=!bxoRN6Dvd~YvM$qpELmk zcsGbllB&XLvIg3x7L%zRXcUG5)ZJj-5;!r~tHw06hrXpVq%1S{%+yn^*gu)1DS=?0 zw`7cF4KArQ&IY)WAdpYmEHaSkolKGnfPsB#_4JuWGq|Mg1M`q<$tS6pHbVnI&OT+? zc!69HGU;iZNgXk>&#PQ4)3whfaYokU(^K9u*+L1(rvu+USPkC#Fqx}aLJ2E^RROMM ztep|5O+dHQBYV+Ur`AM|xeaNO&)D1uG-)_#j!QzyMc74)nAOu2A`s>(1ixKZL?#e{SG?2H4?Tlf zbdO8ck}+$n5Wg?5B#cszv|MVkG9Z$btd5-0c8%XSJ3Z3OCVGkWp%*@Hzw}T5=Hj`R z&0*Y{WTpem>e5HmZQp1lpkE}CHq$IFw?~A63H?%W$|9-=4m$hk zO!bVC)08ZsD6~|Ray5cblJUZF5R_UZM#)OGObzO08n(3u1Pi^3pLFR#C!w;T4p1o% zK?k+PV^&f}c*V(Ag5OM~0I0wbZaTtvaBbqL6QLv_4Z)nHUFi-2j;llguIzXqpS@&c z66Xfv6hn$h6S8tuxCBxi-<8okI<)ecDHD~%=9o2M@1>L2e7B6@&nAwKJ=y4gB^RkjXWpgluvomW_s9^#W~VQ8;$xdSioi z?`WtkqF*=es;g*`tv0S2N-7G8bg@BX*R3ubk`t9=QhN=ptwHEsI(|{EZrU}ch6D@I z>czcKb!G+OQ;mhj(hxKdNbR_!Q5(W=hDOz)W^hu$+!Bg2ULCmVYQ$Jq^BiWzma%Hg zW16_RuVU|@x=1JcMi;JBrJR#&fR<)@FH@zLl6v#hel zAaae5t4(B66~sTYWV*9V)^b^O;~_}`?^Mu++L0KXqOplV$;Xcp zhkFlw<&6{egf5IEKatC6Je!!s04Ur`3@3Kyd}agBXo3gI%2PlknZ{l`))5kohAh?Y zmLt|nM6{QOud*l6)X!e+Jl+M)_d#9DfXkY4nKyJG#pTM@J`XjSp>j``xl`@+a;iMVr|yY*t) zDAKNsv)nq6RujV@XjR@>g; zW6_}9CGJXOq_B{}kj7;Z1fZhEg`ee!HJn2gGwY6vCF@#!&GD*HoS`P!>uFp{)6Vd0 z2g}+y$7F_WA?4f_Rb!ZqX|0%7QaQdZtlPmjbT0^tOXMp}EIz8Y%Gwgz0crw(7l43> z#5z$;K~QB&M=IJ-FW3T1$$qg-?`~bIuS`kJ)nO7hZaugITsps9U_)O55|GCUNE^Cj zMdct?Qx4`v3S|RZ7xpx`_4E2s$hLtgD(19^(u^QlJ=Rc{7lm3Z6jQvjJS6f*cG03> zCpc`=mk91O%59>mX_<+ZEfy%~9O*iuvNOYM)hP`Au35+|SM37$Qp0dHj7d%6EVqVl zc&#EDcE~*$nbCnoN@bDd)1zp&N5$xn><&IceZYG`A}@hKhDDdEcboi|Z5tLpu3cl= z-4#6II34|F2+#6)%{6n4edY=z%aVG`Pj9`nmp~lb!dG^!mCjQ(Ff5jvXhO1|q~`O} zc6706+i`6l44W5VE2H005Lg03b8~000mm0|o#9zybgW073u&fB*n4{9{55 z9IkxeoF9hw)TA1Dl3Sjn>GS%XBJq;{<$p-{6DLA{USf_s0`D)AlxI2SB@2BX^a%yX zW-z#a_(yO*lY#R%e~|a{t9X+1QErmgr)-m-k~hLHO9mi1QQKefP1S z{k-}Yw0_L4`mA0*T>GHW^KsOFU-#dCKkNN8q_2KSBHhhOUGm9X>hxzomm`~;_b2Z+ z+6T1v&9s}IDrdKBUpsncK`g*C1A+b-&%g_b&Xt-1zqt@%hiKU;IB-Kcbho z^F5FEEa~O2R@omRo<0!Cetgc?F@p8l&al3w863t>6WI-L*-B1K0lHW`At==TaUy)kP?rEp zl36|!*YT$z$Zqe5n*fmk-?SmO_ybE6C8O>ynhPl%zfWLnJ7zmuFIp0ffM5e3IbY_8 zi)+P6lQ_W1IUOd|9)}lcJ7jSN?uNI_KLS-(*m4@_U1oatMt}C1!S-Z-tLEvSj9{g* z|14k=x9q5V39*C()^`ctk|@5oKO#EM;eE@gl-ybst01c017IA*X_hUh_kvS>6K2nz zqG}`jw?km(MPr)1gYY2;(gG0ILpNam*aBR4|6e$nc`hrr3IQ|X?l6G*adPB z7X&~+@KLkh(Bs;9u5Ch8j+!B@ku!&7RFkFV#>2Ra>f;&*Tsa(^lJazmndXxaS$rcu z+NJlontAhBec$+jn?+9dqOts(4F&2H}L)%WK1H<>c3zz?({8<4tixOK1guUJpotgX{B#BRz z3h0ZLpxFzC5>dd@L;FlgaoLEB-dKzQRjL%l!U1a}dJ_eCV+Bxa)QjHe>cY@9y}UrqsNnVwBMGDk_4N`cB53jp@j)>Q^Ayt zuALQqP|l3_Gq-cnwL9wY>3voAy^~C4XHKe1MHvI}WKUFJHtJJFWHoTUrOR_2&+9%O zSSJ%0IfnqZJ5z<{`w#l*2d~1Kc!!(-2#w_~{7GUOV~g8!4yMeUEN zbK(qmog4({H63WEF!vN$z@0vtCeR8jp$t$VGKajaV)}1zzyN zufR8M!70SXf9c$Cn(0@i=M!OMu#}K)Of+VqI!B?>Io7aWx2eL)NvN?cvpnQHNQBNZ z?T@K}8cK+Pb;Sq3x9gt49?AgkNq&ab6_-Qz&LSp3Z%^Wb53sbb9u1|S#~Hx;5VyCe zG^B+eV*bB->5O4nJt6Q+R7yTW15ZZMxUH*+IHbZaa@i7cUs<=cNhrvs?JSI>f2xz} zHX))>5HSj6P2PiTV)M&F?8x^&J#qB(Rj6l36^T`dKdIz%5{|~;0?RldT~5`K^6igV ziddz4@-NVnP$dZXGyJS8w-(`k*yS#ZeCn&5{^GDz4Z&8eFaABI)M53*T!zkK2%_AU zrs()iohUDDi(_6E?tupl4+LaFSEiO{nQ7b9_aVG7ItWj`5%S>PKU}(fF`Om2rBJPZ z$?nQRW__r(lStJi4n%V^#r zX{3*M`p)shibU$VCZ?Vl0oxq8St-th?G&I)u-jDQ^q8LACyR%^_-8$p7x8ZU#I)z% z?eE17=3TB#)QA=j(S)(;vVBg`m^auNnMp|FV1zgV8F3V<5RXAGKVM4~YQ`KV8 z?OX9XLHDt755lnXOH_Y#E45%EvSJ{rI=B?tHF zM=XnwZ3++*sy$@+ja=5@BJTQ1-;Pt7Fm(g)X9opKx$SE@&Pv%$uzbzd)7BAGpA7aC z5F)LOPk2D?X@qyU&;Vl}tI9$`@ODf67 zQoTmvl8KBEZibdFZeZ$>;i(8<=>_=JA$7LYX=}|&c^60f!sblGY1j2wh@?kETqzYv zauKy|J53VDwox~CDA!e6=383BN6Tm3NMw2nhh0TB&uDvJ_0_1Up@0^I#md6ry5M6X zKiI8I$W@ndm91{_Ph zAF&ruPApVut>DV>(H8|rj4`!Z0@b3HL1y7e7MOTpJJwznvXo7xX~$7g53==}48BHy z%wZ+5M*dq9(9Z^eU}u@%J`kw}IF4OAGcri=wemF{J`D!Dk-x{1k4OaTq;;H1%@PLQ z41I1T(6;Ry0VbtYvp6qpddTgUfBGllseQDo)ky51*K$(2$fS*YL>WjYaVc?IDzQMR zIhpfk#DRbzi3Cf#UJcJkroZRDmQJ9)DjT2F(q)SPFzBCKqRF&D5RQ(j0WJzNiKR3R zx;2A!ciJ2cMa|$6hVWz`!IMW+(lfGg^-(0H^DN=ig~Sur;=F@(h$j%$frS#FxujN0 zVxUS|Xwg^T)4;t|<7`^@Hk4NZGD2%9814OOO!)xCtQ-WYh2nB|;l&su6p*=7R@iC* zD?T2fsl9ZHFHNumaI;3eVQ=N7aRS*CeN(hE2I&oSK!MrO?r`$&7YHJT;K>(@RY)to zlKIouIEhhDb9Ij51ro-9>!+Q**@1jv$md@VMi=7l1J9Xs^?0WI*hi@gU<=l=q3nJp zr!LlE7!B=>NBr-3LonR})7RRh6-QPg#V;G$L4Z0nX5thhC`y>yo zfXzW#yaWO*v^SdnrZ49pNuvnn!?5lUP+{&CMi~IBjmtSB_CRD-Os8#V6>bZb0W@>z zv88Z}C#*843S|V8;CYh?gi!^Q_ZM%MMyUovT4vJSX`w=61ynBzq=^`G!Oa}DS+m94 zK7y#T1MLTuN1$4Q?P%I2P|Yw>Gh`00@wHIM;+?n+!XmU9TL`lNkGql?x}nwj zdGS;)HqE^@SbZN_iC{(*`Fe>Z!A+3WH-Z*Z1+{|zne(`UFijBmmA;YAsJjrvI4!!E z3)XV?pk*;&NpPhHWDb^FKm)7+wSWdZExHR)5Y>X3bAyWU-2gLGl_{C365hb`e#jMx zOhTjSS|)y`uA(leu2)z@F~ZS^5<9)&hK40+P_$pbP=ftU1tf%nV6!VPBk^8~* zG&;kM)UAhAyY6bMRL@|{igvKfrisOlH+~>%?A)H4ZwzwX$_+juo~vq2$twMjDS@o= zS-a=te8R@So`!6UEzn-}o}u)l`vjy12_T+durse?K5@U-6(Syf9?mBr5%0Xou$5u9@wh ze&B~+G5u^atB4EOL+JUx6chpw^wLqKgc-|d&GoKGlwDVJPq|Aj}E}-Rj3X zUeS_2z#G5M%SW%Y#ZWFE_U;3;+#r4A_E`A{6tLO)7Zed{2Q!n2eswy2w=~}XpFm*0 zuu83zc!ILQO7P-&8_Eh-C2wVrGAigWYRv*b5^c9`Y)@C`JOo{bbw#qvPnLHu6v>jh zr<_2me|9@Yg9J4*1EfX1GMNj)pB0b2IHwJbQpA5#5{Rnd9!(Wl$1|6UGnD`h9~z64 zNFWz;X==G3W+`M)4 z5gYTRJk=71H@~FEa+q{NunKcpwIjF{IAh--d7h~ro6`}qV)*QVC~ir(=N~Pq1`{TL z>-~XO+Ut>_4(5g6sA80RyYh>4ACxt9bK)Qe-GT7O&L*8<@e(8QI@OdA70W=TXw|(Rrz)Y1EM2973nHJWczRdK2P#+pNdJ}0Vh^47_-((d1;OKM`&?cy> z$G48H)ZRrP$Js}Ihj?)Rotd<~1Uh)O2jP;QKQ_0&INd`zI%MDwp*b}TI1dpv5B9vp zF70sXbW@V?T82X?IsQI*&#*^22GctwWfQv0Czn*(K>zQJQ^e|dO#_${+|PUFZv4mG z`!c05ZHN{NlR#jL)g2j}{fBw|8fIY9KaD{-dKy{pC%;2hw8PcC&5CNW&BRAZtwKV8 z55Y!JkU>_gwzqY^so~P# zld;b8z>2XD1iyFW*}_>Ipc&Q-jj_FKaeUXEpX!onEN zunIS>L7}GSv|Zt%FqYU8K0yFI{$MlSoMlmQ!ozG>Nb%P2!$?R+OvM1sUU7>tzQ?Va z;A1M&&4^o}*s6<)#d;EiBP+>A@~Nu4e9YvepjBgtOGp416Z*6lIWr7A37|i!uNL{4*G``JSgS^*N4R&AA~ctE?}q z{hQG16_-vK`l0E%tuX9;=~_Qu9~Z93Y2Af0>^5xxZ&jb|ZBb^tu|#i`|je zw9)%dE@G4ZKyky_=n~t3sUxTCdBR4%lMm^o4G8xxDFmXFBIFQK>`ub?25*X*qsY;J zEdfgG-M01mBYt!0Tv6GNvViPHAT_eLmQnXmnR(QsG)Ib$c>UxN2*IzMhO~vzCD+H{Yj}fRceW$_$^u z5}pi+sAGk3XkGYW7M5Y+GunWl0|oldH+}QbC40h&@RgHH)w*)xWLdEA|Gq8>W=qAO zp_vewID?L54^8qr%0`xuxp{c|y@fWpl>%;UJ4b>o6t{?mTA1~||EM}e9UmuWH;V=9 z*oa=w@tEFCh(6n2oFw=JkfLfxC_KO2|Ijg87t=844J4!ME`M5 z)-1CLAH}5nDBrZ^Gz^7o7bVIQP|{rkg1GaxI~ax>ZWEoxZoMSz^6Z}mb_->f!}RRn zlq{+Y57Iy;xRRrGk<}6n=MON}Z-saFYHgNGq;$Cj@OR0A2~C+fK&{`3Z1R6HpcjoW z3aQE$z*xsT<%??XC-rXWejoN0+e%g6#iW2Voc8N2Uj-&Zplz&%d14M8tu~b`MNW@A z1UhR$RvS(SxMBDf*+bvT(IYFppp7)w8Z&5G6^`W452*MeSl-z+PBd?Y!%uNijyP6MNCk8gZsdl0vA&dE&?jX zbvo!kj3e#I)*el%dw*ZD1Q@fYqc`DD=FS)FOgNY$FX1>5N=jFV>#$uTC%JjE)P_|C zPsHIr7P;)ZDvxiB1wbukv-)y~#%~pktuYXRiyI;@SnWf~wi^==k$js7l23?6f5zF2 zw<&#ql*gI#1j=OmA^O9zAu?)PnNVUnwd5U{gJ769V>?gx5&?J?F)<9#eKgGiW0Y+IA)HKpO+0*Ds%a@gLMsLR@|sQPx%6t_~1+6Zl!7oQG$ctXfKeG!_3Ekq^`}&lv9qb&>y& zUdjvA0-T!f7^S|KV16Y8VY<30s4~211O)?=VKovbU7`zO&nE9}B%P&dI~F10+XuU5 zkW{#015A3!Mm}9@Wj^FXMAoGZ0CCly0|=iJ(V&TtQlHVul2j;RPtm#N;l_g7i<1br z4gKL!D>)YiS&p8Ot4S1iW=45I20Qy$WLL!$k>S2kT5t63YI(o0U9czll(?!HP*&XA zuBR~umJmCVOXuROtmOY1`U%wDVPhu7OZx!o4!kJl6^83V%p?|Jxpw#`k+|n^H(+EQ zj!DIoXFFo`*KygqS6hnx5nt+6G-vQDu;KzNdnEljtG_5U*}QDiXfVv=n09a zR^w#Tw4rU1xB6)W{41QxcLNS1X&C|nj1hVt=A#L0BI!DaE-JNon5%@R#I$v&Mbf!q zATUHg=LIZHizEBvR!|)V4t@;I z2hxDSEf76B*COHR6|=ZZ>pph#Z8v zCXuXowy1Bh)}_|%6F~#E59&8>5rBo$1&AsFT&(Vy9T(2%_}fU(+m&IAYCo$0nG5pL zFRtYbKWfUX8t+#~hy)tEDqp?oKD!F1? z#MKoS%65^SEY&&C6l{J{UE`^mxr zGrM6vptyaB=Xjj+gYVr&*kq|FMv+S(WkTUf`C|@ybHRWr zD1x0j>R{t}RWJ9=Z;_S7{N$&+a2sT{Tzl5soEtxazW<6HJHi0q1hZ#A(A6Pb#*Iya`@j z#ydBfEZ>{-=7n9o&3K=5_yG2tNdw-7&p4TTauVvqCb9XH8_>Kz^QSk?)XsduP0d$U z7Pti<8*_PbVPVwl)a*WTeULEOsX9uznR&;Kca^Aou`I+hCUl2MNGN+X$29HG^ToH8JDcH8 zcCuu6+s;O%quyd+Z$uMng7z$?PH?>q218-P4b8{v4gI7Gn<_|AZJb$t9K>H*8Tc0^ zAngR9$#8Oym8ot*<}BKN>AV`}HI_cE~RCOvP%gMYF*Iv$s4|mWg)Y#_DZ<%Unm9M+uBCxQBdwwAHRk#&lyuHNd zUH80N=NE1bn3X@5ez*>V2HtGPj0xNt+UMZ#AE z!8=Vzf1}N2S7{j*nZ;V!+ry@*P;S#!UJ6JC&Im?b^N-mAU?fs?-nnyk1aMYXjaT53 z@7!}fBy2Nj_WxK7_>FqQnFM@ zh^MVM*BI-xF1x+*pJ+)-F>Nw4RZcqa^m-9<(%#i6SpjI|S*omcCu2+!{KiguLOz=z z-8b8cr&r4STV~z;F<9u@F3zXNOqdil8!_c(P19~=l6R}akqb7<<#cAdaQEK+X*cf|)AD1c}J z96UKg_`@fB&?lcE4nmzLFscK$ z3v|!hqgPx7WS{_JPy`@MHXF6R6!azgZ?xM2*m-gDpE*hJ`a(YoEkeg5ev&inAD9p= z(xT`(A*j~vhE9`&pDyM{r4|a0g`cnTEmXY$`g(yvEAT{wh#r3hB{U46DLRbE6G~Rr z1Ci!IeH0vkH}rO*RkRgX%fS=bL^heC90VH#0tDTmiSGMOn$o1{(zW_=90-@P<0Lm@ zr{mqga4)}H=Z0!*J9Hy$9ZHkx)Ez}NVc_+lnMoXyNP-h6Ng9F&e=Kx41og`w_LT-e zZNs5TlMCUTG(?F5-G=Bw(%nyU`@`{M>ytDD_oVc1OMaFfPDcS{Yy&C!E7rOE9{znebVLUmI{+SbGu(rxV~U64m=RZ0fR9awt;438btfXgxsIJXNlj)U02&eQtq=9N9>AuW!A01ID*FkO$7`js%NxvBS3za=r zX#h7av;*N@C%hv9km6dMU@!E*8PWO12K_$VI$+%HRM*%u=I#;YxX*sMGC+lieP=X%6+hvU}*G0 z&VB9Hvn3J5m2y>hD4;IngeW?sKuFiOW~zg{-h4NVFj!jQ#55I! zn(O?`_?d83C;uaxVgo+=Eg zEYz6=Gz@IO;8jjDH#1k<4j!I}L>J#33sO)}7-2d)c-2p>^Z~d@E9X5c7sDa*y_Q z=sq_`4~8V#UUAf6AX1tGx)2Te1r$4S)6%zoE%gLyNrL#1;5{U0{|MGIf=(S10=N21 z9Wk;{PzY-=e{;;$a}Cm+}@f4hVHUG(z%PvPvD62sS_nJTO_SD{!bgQF!v8@+izJ3!5g_S5F07F& z-j_>wz-V*QU(`d#9l93B_Ub)sY$bOlMwi(cjoGi8^LB~ByLW`_m$T$KXcU0?d>o9j zg)x`vmN{3VW6srp;yx0$sPDlkf?^6@nf-|^>Qw3!to-D=xV+VJguwFIQ znz|h?k@DicZ=^RveG(&YFeIvbKujP+c*%PbbCu{^Yq!xDQzUEUx}{zdl7FoW6nj9p z_q#wTAF1(T-1qUo+W{fu*a6YrgLLmw!E>%l5u|9XFOM;et%O($x_3AKx8ofxPc60d zwOGMPnYa&j+o_Ngav@2TQ7!#+(WZ-6*OQ=Gk!ZL}$l2;_l^Kp{5C<=k@^DoV2HV zdk;)p-w-t1t$w70;Q<)#6SfkBbCR)S8=`wN*HDFM!tf*zru?DWr&CR7LTLhdNE*^1 zz3YAG+&&eew(|ti?0PvtatpwT%{sBrr8N1S@aA%=JH1)jiQ0+dXxh0=_;feJ)PyGv z*Frc+Z~;lbT-$`9fK8vC>!V3Dw+v0~lqSiO`R%#s)XA6c21t6?n>K6+mm+N;seyFA z9FiV(!n?zTlC8VdP@?GV&BKl$`a05Jr{6~eX==ZgCiXtK=lY=(f?k_`9}u26SlzeowL*{X4f>%EJ$i0qaf6dMVCU|r!D--pN}!21yYs}s;=S+g zJlV{nd(#j(-0eI#xQTMd4D_f`!aIIo>ySh`O89N))W9iCx}+UxZ;0EP9i2!I&euAL z4i6Cs1OidpE4SV$<$ z=7z1f7!y9%*m^wK3KNb7>v%6vhoZ`d4;|DPbn&&f-aqN0d(JuLmQzkP*j{5SH`6pt z(=@r(n03IP9GQkvoa&zo8QuNxEVXP-rbg>ENk0G3Kx6tU~znKj=GfT*0uJ0?cZLv)HJmLl9@GO z+w{MY&ivUL>JIm#r{;!A${7Q%kG(m%+uf}@znkLet%uH218=`MQmeU^7JzN6&r=@{ z2t&Iz+z0myY4`R*c-;-X5Y9Kk5smCti-Fjz9lbkx>vrfisy3WHT!sm{^1(Y&_O_dG zZyhrfy4GR{!bEVi|Nnn#=>%cNJQnlF*8xZW`&#H`X7X$G1L^uJB+8X}Y-(*)DoYP! z9-A`ELp{OVv@(xP_k}R?=tln5SvT}TS}q`s^TU2XRa&+fOG8F{vw}s68pihYGa z5o=LZa54JrL7cmxLSap;QMu5DP(Sgr*mDnwARrn_!$lypJ$2jd8e56BZ_avmNH=c% zoQeW~Dd;EY>N+p?VRvoVvjVJZz1xDBQ{~Luw?Rjafuzl*>7jTNB)vtKhWxg`UtGz( z_Oyi()PIEk?%V&rj8DB&uO7-Mql_}f2%~yWA}7M2LD!mdtTDIRyKjkXuu0|`+}Z&< zOxpR-KzAGL%5S4z{wunr=vr)}IiUZDMggW`j8Mdt27nWotHc8lKG)cK*!q_dKG)cKML{Su0TPG=*VuaXGQ#H?Tc1F<#@4Hs z5kA-0dPTrBwqCuA@VUm;s|45Bdi65G=NenD5L{#H)yoKNNYhm*d=K*7y}%lDn`hBM(BTmLe`=Nel- zD#M`lbU;KQyEX6Pd|G?7;Fk&a9R1jT^aPz!`2F&Rr#pG+TjC-g;! zNk6pX=O(pROV{N*v2;2TCc<1W5EKaq9{&1YYpt~wi-iS6Q4~c{6h%=KMNt%GVPRpx zDvF{gilSIWQ4~c{tTLAY3DRJhj)j3Jz)Uy*4QOJ)D%7EnFo+8a3k#1I8U_q33>J!+ zFp!Ca0}V%mnbXON3DODp3#ud>Fwihi17?DPfu+FF5MVKYT{6%ZW})B*7zR!J+#DoK zr@_!%NJ5Gn27%0l8Zb-&OZ+GP9kVeTqoJT`tFiSMTz)Yocf~@Z;5~leaJSL#Bfd%) zAhbCE&H)R=n+XEU1B&UUV^M%;KxTpfvpMDf2Ron?99Wq0nu0=M2ONt72o2GoZc$h) z7A27&fTbNEW@ADm76B}@z28)EUU3VpkQIKK%ii;6vYCekf4B#|NsC0wJ;Qo-O^wn6ch++&bYp< ze=hS-9~T$Of*p8@n+c1?7zPrJsZbPzV*mkjQP5@rZ*MdD0?dL1qQEThOI?fqDckGN zeI9qo7uuJ>{ff#x?5$r9pRR?<0#5>wPr<^$p2$?t;1V;Zg0UEh2IEq%ebG1?P%MU$ zvC}Su7wtlts>oL=zKStQ2_uv*I_V;lExu$?#*b1IX%uMaLMR7gd#^bLTZ3&i$QV=& zuE?NbP{CzcmW8*MZz-tcQwqxXqI~hm2jgq#tlAWkD5D&*K43#1h001BWBZUZ1SY$4jDO!|b zS^yN`!-N+ChJ=Fxf(-zI0|bc)!a`B-6b2YV!Eh)j1PKSB97gOA<^y1U+hLePt-8$K zIm+$F>MZ-k&s=r;?q`Pj<`VNpao;e9n$7-MvpFATXi6TTl7K3rD}6=yeGmzcLZHYc zI2(~dg3eAD9VhgiBtleREqi2q;x7#31^a6Eg$7B_ijwH#kwn2 zwB}ukXhrQdUXB3AD%#n5eA~#Q?x*j=riudkuDH-9RMS)q#&?K%#W`G;;3ONtiewMb zNkA1*M@`|qP$`~{D8MVpw*yupk(@6ziB&D52#e!&L=`26_d?}(DzX5tB>xIniA3_g z^dw%Dj3PXat0Jl>IlLDt#nBN3SY`QEfLavGds4G_mHb%MqxdS~3L3?GQBr&jn1naF zc*4xi`6TrtRTj#J?*Wxyt-uk%ju>_T5nxOXLU&-jZVSS=f3V*!OX8J4BHk%|9Z*HZ zabIvbmX4s&a=03xmt>h}xSnTyaqzL_4=u668Y>(y+l5BBOXcRRQ5Zk|lPkxxTeRC^ zMs4oJ2v^v4$1P%qB(Gh0_2qV=o?6B>*QRjGP)F@EqXkHLyQePrxnHpnFI;cZ0DPLj z5p!jlrb<2V_Kn=|Puj)_2i&l+aVx!HOz1-}m%b&I^Q7mns`fI#Hms0(OB$Yzkul1nLG&kU1P{#B1?1!~=l8*AqOYWgCrRKr@e~tW&MI>|mVG<2G5%?5q=yJy1--QTyptu6Ofa5>w!x#&HcYL{}>=m#uBGq4g2z!x%!5^N;;+ z^V+Kajo4cOyIrHvCJq$uLxEZh5{Oh+nx-q%{S|+O-%-PFnCS99Rf4_0mY;wJG+EPr z`zYTkFhEu8-9AcVsO$kVWH1^PS3ui^UnWdjYsD=fRAriB5#ZWaMYoTj-q@#&cphH{ z`25J6oz8B%Cp6pGy5!=A43m63e-sC1K!ZON^&2TdW|aAWFsU7;${_3vg^W?O#lwtI z#Wt1F3@Ct^Y(F%AV9|snJJI^v5HM~MS0J0`N|BT2!B#nEq0{L>Xe<6lWa1>!TUNKN zLS;J5?%(PGLN(DZ=6(u4+7%{RY%z!6IWGr+i3p$Bv*cd8GMSmlW6HiS?Lyh(1B_fX zM}A)l>1v2L8Do_4q(;j!24L(_O-5!0b;_0$a|wi!HIY>ME(gtyAA~b13n3V2H&B}7 zMcNq%()q5v9xuGCTlRNDL)V3$X4LHEmXGKLF|^)X&a{RKGNW|jMzLLL5CoyThh=2_ zwn>m5CM-Tp<|(M?R*PSf$?56BJEBwPb#z+k=Vvxv{%lyC+d<8eQ6~#rytfBqrlbL1w4{?QF7q1>mz||S%q$FiTdQ`OE>6BFSTN1?3SNoQPH-A3v^-vV2sEku z5dn5G$VH^lm0Y~O0Zom`@HjA)ift92K0T(34C1C^iPl zgZfPcNuyKCgtL=IU5n*tCe)n)HJTCfADdnC3CAc*v^}x#^50e~q|mc9Cm)H17Q#}J z9y@}@p$Ae-6Dr69#mmk?<@7MNUtlo;tJO2O@kay3;B!O;P0wLKodo}CLu5*{2UmVv&`WuR<51ULNm z)e^=!9dU9WiPe-u5G@pj$n+$`O!3@k*&bnV-0*AW^(}1|A;wFX7t;YgRlDL$izGSk zMNu-(jmyI2jt!$DQqrHH^Z}fS3)sAg5(5Gw9D4*S;{?)bAHfpl3#6;J+1^5KOfaUS zx#9U{R$9=GrbQu)!Fqn}n3#&s)F}ltq8dF8cq7JYf6{2tAPWXbU*w!ufqkSM9_nhG z*H)+%SJteBEVAnwtOrB=#WL8{wz>cEOiXmE`XsCUX59$nPL`sBzATTnSBM9X?{EN8 zIK;V%eLOR(Ae**$>Yao%h59%=1v#-v+fRSHZzLfeZ}%b)U9%`7wC1e&+3&(gP^}nv z*AvdEu?qY|zo#cgte;H51}Q?{>$u{95{>z}&!H0)*{|6_HrAq_>mGa6dc8@Y3uwTv zonaj+nu!F+6aAkv8vY|vT%54TfM+s>Jp3VQpMfQ;Cc#^CL5(C zCzkeGN8h&nc5RufU<=*FGny@~Dh$+UEiaLOfl}>ez)H<{r6Q9 z*pT6XkJ){dTWEN?~wptxLtqUPl1#=L8UV}w7R_hCv-`wSj?Kvowf&hKYIp~4$iaUVKW_Yxzu z%qTz)zb+&~Eunr46~ zoYUsks92zP^wM!;AbJS}e~Y|6e2SeVe809E1^GkP>LHMQCgtK{X;tm1B+SrJ zU#N|vSvpfhJj*~!WHTW;zNAH%W$^i9e?ZCL2?kbFKZU2zHRTvTO}Bw7{a;_Rh6S#&o=&JVw)uCjH_R`t&)+o5JNv; z6JIb_*0oCt1GF`$^b|NfTDD*$cf`|lx(WTKvErbUF3!oNMZ;U^(^!6ssd6?H;6p{F zF1&fW*$qyf++>x6)0dWqEkixO7)>m0jqJ{Urp+QBaUFOq6z?U$q5=#G2*as?lXbt$ zz=1E9QU#nzllAPBE^>tgpE?4%>O$+wmFg}(wB!tnC|HfWSLVR+f!Rk}~e%lFu6kUEVPn>|AYbLNm;QS>a zO+>=JD|HJDnOJIcGbm*+mnLG^=wIMib#9B$@mL=F7<{>70K=ICk@_R_;vzdCO~Y?B zA%ydoPJqe2z?qNi${XBQ5;ZHBKX*dMAWjbZU7b_fWGnGRoJ~9BIK#zm;q&v|aRf}k zyS7aS&lRrYoT$j_CY;&35C-=qHrh>As*4Cv3_(! zdQzPFvfEzRpOf)w)%E}kkLEDyZz6bI?V&yKZmePhuu2bwXTWt-v=?OlRrl2wFYW@f z9P2eyYNQ&;fRX~ao)k5w06$)dhdIYdp_*1;dA<4THEM-xkcj?#(snNlU5F?gw3mXt zhA-W7YL!=C)5A+%GIroBCPvjiY~3fuNV|q_|H!ed=qe+i`LN{G5tK3mro)5V-h0wCup|->tk$2Q`fn zW2K0kjT_aRB6dqN1n6TXT_jrnl;2vF>|FgL%y||aN7wKFIp>Cgm!aKs#qMJM5C88v z>;7QDf#!f6)PTob`O;_kRUna|5p?Hw;K^M+t;{@csPQsdsu($Bpr*V@yRsQ+)10#t zdEMaW}*M3os z#loR|5#s+LWf6(Jx#o_|7fr<7Cg<1|3|ylon~VJ5UMbh4!u(*xq+MPDsRr4bw|ux< zU-=JK$a0j4=l@R=oIVu)alM)N@kCb%cnp0YE!R=75!EEW4!CiLq#?`Z@4xKA;)zNq zI4Q7GNVPP?0+PiN9_1yF7r$Zg(V@N6am@-db=ppeeefuQDdT?7r}bW{|AL;>(`)FItC90ZTGT>puCKh=%0h~~C7Tlfd+wy_y+4)s8Zahw7= z+8Oi+T4)Mb>lbI9jX03Z8DkY)wsPXFkOOlLl1w9o27DvGJqrEI*GrF-=l$PB*y<^! z0o`{s=3v7ztvhFyW39mY+r`W}aa-4Jj?JAAcz7_4Ww|5WQ5CKsr$#FVh+P@&U(cJ8HDXT;gHGE(yjd8QGl*~kMk;&;= z|BI0XxwVok(*I3%-LQO{Q~AGIeZa(qkpdnnJ)@#S%>?=rhARnTK&&|$$_C%QJiXX( zGm|xqnbdmw%UG~0WsDqWwufaVKo^(>8&Yk#j)qcoDcg1akev$Ar)SnreJT@#ipF~Z7wZ`Mldp;x?@0PMSA2PeA?Ae{oV8@U>I#!o@h zhBK5K6yJ0?_+frwt{+=IoeV|$rUt@UPP> zJtR4lZByT5#oP4%DC0;4F&4U%0Fo$S&>7Q^SB9(_5?2)|agts=?Y#4BDK>YOCQYek zS$etF<}<~r)U+1HUUC$jBN!S=vJS5BQb=+t8CRR#+e~_P@aAX|uD%u21JcAu|Go1C z7v8%wZU|TTlzz(@G>94nj=KW-TwrN{Ny!xr0d+P1R9lj2RXO|`j!dP-T5?#L<~VAO zWIhFZTN`z`%OP$4&$MO>_U2G6ZeN|VRHv1!uGeLI^oZF2IUiiz zLNp;5OwF=Ef9v1C5O{xT8Kdd4 z)>hrv>z^|U{%E=xl=Y~LN!FS)Y;-z8KFCi!zo{wDO)#d2?9f5 z{U;qrdx_bnSrWxM>4Ou-g&XSPbrPtukUDIlg($?uOi_9hF+X(~M)_gsaLD3sPnqKo z|J_v~=%#;5WQ25~)#nGPra!7wnt7B|s?8`w8f=lNa*}=EYlr9=#Dd|F418UJW;y5- zokCRpqZ1V%gdFqTeTJevccLOr#?BXiW_7g$77d2}*_}C3Fqgio3=Ops= z%qSVa*vyJSyBDd-&CZb4ElVDw#onR0`M+A^AH+QJ}l0Tc?S&RnTw6Q;#QKQUd? zr5L>g+f;KS3(xQJx*!-MySR)ydkI{-9LZ~C0qte1Y$V|gtTF|=8uLiIbSNPO@)~ZMv z(wG~shPG_8jyj$Mzk(v-`y!}2rlUG(dNvx7)RW1NcJ4Sem4^Unf~*uG>kl&mno8+7 zHG&twIHV|MqmWYgayp6bd__8If1T^*}pW~1l2^o1`jme4wke)US?$l(Ftk5QR_s%m_4JI72!1RwGUI3}wD zD9=?bpAJsuC_J4<*=jivYb?>t_!B-sM>f+j&-PS*&VE6lSq-Nm7Be%Rrt%EuL1?UW%aTT^ zj+5|r3l?lY1=pNQajI#qe8H2r{HrYuJ0N#r($iu`KM*(4lJ$kPwqgMG)J&n1Fw_{@ zlFx37ncAGyM5AG2Y$&mt5!*H{F>CSObAQ)N&@VR3{T7U^g#_m|F2%TejBD*&ZEIPa z*i%>I=j#&=43ZXqZ|N9yfAQ;Z#s8;?7vZfhij>=^6z2t>!}Cqd!nw8BBFgYv;AIR^ zqIwu~0Y4aRT=KV~7r`}v|2#KPpfnw_pj{kl_{~#KGMQXMDc`lRg0cy6!s1{N1BU`< zFlZ{P`+i$OSq~>EH0L_u|KyI`L(4`b4-7MdE^-|(xX~ti;D?X5+P;9)HqPkk&fF?o zM5mzv@20R*Pc2T2GQO>DgKe$S z$0nceDM62@tI$-VAPINXHHi$nEW~T6-1i8fLc~CrVPOGKKCi2bZ)>dhoUbOr>oniY zEg2~Uqy?5tt<9h!lz}S0lE4R55#aYinBg8)e20sJTQkCpv;uq%*saQ2jV|hn-K;{4 z)60IN1{yGa@1BF_N=(LKK`cT`dXvxgQoOQg&yR!npC+aH;z;Kxgyy&m=dMODn8>{9 zVqE)e0g(@ILmRX*wgYf7U??=7jXCPVQ?*_=Q;?2@?7*pFwl5j!t=cfMrR0c!GQ8H`MRqlbZOj=|e zf1;&tK{0-D5I^Ol5d$ZvpPnwkM1bWzN1O{pr9lunI7moDH6C=Xd9a_bU}%bL*BBTx zRZVAAKhcm#D$#0{^eOInl0X0&YsBQ|8q32(w1{tlT}?`vZ@kC z0Bm*pc10SFFd&$~5K&TpE^!uXI3t114C?{07|XD#M%zpNabpWUUP?7sxh>nyOXHa+ zMKwLK)>tpXquTCk4RNxpl&-_Zx_g*aawLJDcQ!HNRXQ zLnuDoG~1#Vj*Ev#w7K`0XnFt9LycP)AL*0xi~_G8tkH7JIV#Z5Z>RqLxUD#V8IFOhPn@l&bnr1 z@;h*iVafWNiqS1Y^@B&;H~>GP)!wMmg<&+JTbUDISo@@k%z_{cI+krK?!lPzsXS=5 zeE}G3W?f!diVdFp-Cb~Um`N_)<9Pqc?e|!%7;G}PO1Mp|ESX!r2oajr^3DqH?d#|@ zJ6L_P8=gmO}!AfUBPoq0irGxO`nFT_m!x zLPtAA8XtjfXsc2yZ*Jg6$IIJbl^}@hPQnHJ2?_n-eE@H?3i{UdpD034+FAYmEaIl_ zE(g`+OI~&o7xUyWpA7Hmdc+?sY>x=L3jr#ohcBn!8lAjG27riS77h9Rz5PavLQ}Gk@5+_sj-~YJLdN{#otLzU^Z!2cp{ZtPZ6N zBW07>-E25aeRFgtO}BMy+s?$vFSc!ak_jiaHL-2m=ESyb+qU!N-uHRl`~6eht8mUf z)vIf*u0FN52mOuc@+T62VAbj@Fye2oX$`j0kws-05-aIBl%6s~bY0`R{0h+huTi+( z3u!Ft9VM<~G73;Izx==b$va{9h(y$>j2- zKnPyWUYr}wJU$DM-HjqE4Ph&f%vOJ7x&C5Cbgm=n4GuIe*fHbw6iB;!<82x2fq#~B zZ6VqG-sFx?2v&}N7m#qiEk+aJ48S8>2Klgz4^XiTkP_9~)Hh4&ns3c&a0AkabSy-k z?@;Y_%`|4bp`(jXS}G}ONXbBQGJ1?)tT2hKxpGa3i^pIn)?&h;rC6IEP@jVn&*Zn} zgmp(zIE77|w)$Bn%1X5mbIq0nd!Hd3L+bDU3+zYhJ(_`0kur}W_bjdSPzC-N45328 z&u&d#b^_z)cpt4rQJ3}M-mgl4L>}q5z!!kU@#c81?Cz1_3qFEh!0Qrd$vTFTS1pOX z9}SkY5kc|pV@^ZusNtM~N`(^QU{R9ye6@)Kn&!ftrJ6M{#)CIO;tBuvhWwHSy;|RV zOT^|w2;2P_=SOmCSYN4o&gz@+1k$UwS{)H4R|VXN`#y@$4bHNjSZD-MOd4*Pk)1Qc z@A8D46rwwOfLe9LtTHE^w=R!zU9RB(*J~L)*0+-Ay9h;P8qnPp@$lNKzy|`4}I~tzghKP4`l#KfU=#Is52P^*`OMGW)D0it@tJ0%l zmnzen0J?tEIQ-6!XNvq~! ztR#^y7ZfpSa&+$oLDoY;?~sT}e`fY!e5+snY?`LCrKsF)W@hW4RCTXnj6`5Z+!uTRc}dMN zzJ?hvkQ&2_-Ul^g;-v?Q^PM@P!vHm6JuE_XH%hFMJK)@OUzHas9K<2)Iph@%s5sq9 z9^kkUR+J74Cl1IJBYM>o_E#BGR&@>X^n-(8Sw@l?qH*9Q(lt%|Ne9L2xrA}S%L&1X zF!xhZ%E6g6Yfgbe7=gpg)1D2WOwdKkadQ5VzPH0<80i3;Y_EW?F-##>QUK`>zHHol@r-Q9@T6>G3^o* z!C)`n5P@l2uT=17i4`65EdEoM1MQ+XOnn7mG7rXbgcL(zADYrnYoxZ~)kk1aHfIyB zEq5eXLf?K?F1$`S%&%k`KCZ9BUwln5U!PSG5M&warC?nn;9vNg(1$uZRe;?E71H$) zimAhafC69Tk{9baq>4Od3huh>DqfeIEH+R_e<{1W4UuBfl?eU01g1L@G4hW>OC^*2 zEwUzhQj9WK2^!>kCvEnQ_m{(MW_%kwT$+051ck5mqEW9*!1!?^d)!-yJombtuNg5` zod$ZVzEB0yDYteevE?dpdtIRpVp2CXgOt=j1>&cl;Nu6ETL(&eXi=r08#gsfksD?^ z{k}a4y$9L42+wsyf*cWbx31mdCjxdNcmhqZBwp<+a_IW~monLUT!ur}#iZ8}NV>u; z*ohDat*4s*99xQo(}{g)y5`wsF4v4jKoQhi5TJ#VwA+!+~@vf$tOqy zUh1V+MYjg23k`z8qnI3l^4`DS?Bb<~DMn#HLjE)ewR07e9)FblSKZJz1Rip@EGlGh<4N4f z%-9kIZ44ez=QI}*)VP@^7hA5*f_Cc5e5NjMRLVb69anO9YetE%UVpI)fd#S^SxHg;x$ zb`r+k0F2#gvFXr&sNW~pTFUu=Q7WA(Uu3UxPQmy;0CJ662el>D1h?-cPJ_58zb8s2 zDCt{u7xr@G4^a3uf^4ZCYx_f@zV&#x(&`b!I;u6AyysgzA$q^^jyc(>qJUQjZovIE zbyLD!$RMM57|O~GuY)6AiKgaBHfSs2CA5f~WNh9(Y3oEC>DNF|(^-zN^jeActwFle z)GhEIvfF0=43PB)F;n0MzL%5>J&WmW>MIp+=F&O6y%a@ra2A)VU9mxCXAG|alc{cA z7BJ9$nqB`N$u6d&Ta9oqyBb3q*TLc{U@C$}^hC!ANP%js$3|E_M->IpOYq4k=N>7G z(pZVBf^SWFXDo`ejZvg@Mtr%_HNSQ@UZqo?OAnmstFRQ{sqRjRgHAc4IF ze%~opU0&w@juiQ~D*WGp!T)-?(v$tS5jE%LG`srd5(zN^snF|W!_38fxz^?1{KL}qJ|22*j@_(pf06yyf>%8;kKfRm&3Fs9R z9OUjlRm}g)L_PSwUJxb7P(npWV*j}aX#B^8yED)~Q_{u5)TAd%%ibJ5Z3qdt`d1_7SbLk_6{15+`a*PZh&AVyT~ z$5Uq>j&{=d=pmd$!V=}68O2NoFd}Q&&CA2s0LRxS31Xpu&{6|uVv>XaOO5vX9jm4w zaZDc~Ynil6TdQeM-~T&w0wrCP+BI}y_doaKY|@rV#{b)7_dlINqxsnw*(xyho4MQ^ zYeVhxoFAlrCN+!b7^ryt+^y?hd~EN>+H$C3J=|#SC#P3TZtfpI(KG35kra>40CZFQP6geiK zL`dtihuS_RPP-K9soAaKrbCIdMiXBlMbbb5r6(d)42$fT*^W!%a~D9g;|zkhcZC7D zlaBLugQJxIS`_lE6lBp^beN+lXX8E7oMToSPOIQr>{I=%R(+NwU|n)HiGT=5J8rEPUUZVr=~Y-md{Bx(W%WX@ z%n^zq$v4?)$;VbwD~F}f5|EUF#+oaoA9FkAF5UO5pH@#MeE=ori1>jW)t5&N?LAWJ zk_)Q9uY}&`%QB5g*7{=wl1M_43@Oxq(T5g=B-#-C_=dt30~&o#5``l?fZDfSqT~?# z=x=uomX+*ep8?F|KF^{tr(!*kxw%QKN=!1r51A()CZJy6{ANOeR(`iH2k)!NkBbej zt(A|Dv#jQ?OJrwM<&V4@QP9q@Sd2)cSRX-5&y2DeIBLJx2$`4!0oFJu^BUnL59rq$ z=91t9C;}Qmo<;68NHpGcEZ-_!v!4@4EJct$$ov556dd{?#uwXf6^B>xfTA|48B)3> z)7ZiNR(Hx_LLmSY@rXoY9rWqd3VP5he0u}YNDmUe#=_o6*aX$Q?L3< zYkq}q%~~T0jQMj|1e#;YCac`U6&6Zp zV4_qk5uQb)fxNPA0UBE1`U2Fgr)+Np1nT6ZnRv&=A_%le7WO2?r`9(7KC*Vw$`~xQCpyQu`u#;!Ih+%@vgu z$7XQw*-mh=-bg;ZL|`fykAFB+w}>9uGHvHhNzi=D!U?NO{%DjlJmOwN!Xlz6$_N=< z3w%u0>Mt2|DHhCqbS6Fkrsu=RYR`&T`QW%c{&#JZL*QwR`F*v?JrC~G2AY2rxSp+t z43P^t>-%KP*->Mf`06bqQtX!jDI6!Hx-qQ;7L`G5#U2rsHZf_f{>1CHuF1~B4NXjk zFlI;lb9xSaK}(QK5?PT&3&C?CC#Wj%fCH8m-ZT!;L~9+l(4WMeR=QQ#@0dzKLnNw! z%YEOkoi>cB*@zZO{y+voc@U%FS|FuY*EMlj_DbCH)?WC`#0S<`r|cmauqe zgn^KOz%&{TxRWIX!RFil7G+Iov{>KW*MJgbRfDrx(W)|xQDu@EAm^|Qq60}H0kYb%T^zChAeCYp2kZ}h%+5u3I%4RuC zwgmV61C9C{mz;=44fs>O9b+D391bWM>!H9rncyUll9r`^Gm8TN84t5e?OP*DdNnWCW_yrH|QjVPldE_5sWSbBJ8M_h`0+&W9u5M^c zFRu-yWE%!0BhAiLr}eANL7@G8Q*N~@CK`E0&j<<=&y|R7eAV2DNZ;M;tZC+gPbCP- z48H5;rTihGB^kHr9j3DrX0I`_gZhJ7YBwJhUs@|hSlpT{f>!|q{bLls|6C0@V5>on z8`pysucBor0`#L-0t%+^tx_whA*?|I#mJx#*i50SsOlqq=ZgSKVurPZZ9%t$ewhSL zT$deD_)9$jMuT8JLD`>`1Urt5uorn(Dhw(=hOAIDx_2oErf@Yzpv3X&F(Y9D3MdB( zXs;g#4k2;8zzmCAvWOB9O%N;)Ubt5X)K3sx5V#k(w^z{5w+C8q8Ve1~zaL0|5)LY$ zZ#MW8erFx{N_v2rgXa!5$7q|i;W@*>$M*iGtbPWikS<4#B3HWTda%&QZnfl&$J)VQ zxHI0~2`-AAQ~;zxuC}~SFiXG*$5m9DQM669nV4PlqDEoHI* z@e=X9k!X{`gs%1&`cG_EwroWAPTV>XVF``CEa;T%b4%ik*7T~lfpn0^^LTESij{F| zlRc0TZpCrz!gwH$J#8XxJVR}nU^UE#8Y9y`KKPdGBZlxMoY|)xpMN|96)W()gxW*v z?)n~f#Ud&!G(BNHOzx_{F~1c%;42|rDpPy3aPuee%I}+CzuJ{t#Pkk3P1XI$_WWbG zC<`!+!@ak64kp{|n4HQ8k2dI5)5(8HWK85qXPX2`(|OZJSBK28&D)M5R4jD*1n3k^ z(>Wf=&bDLI+xD)$4nqdMcLPnjfw+zK5v89v@N1<1I@W$$VGxcz<}mGz>vz28OrJ?( zSNGgrkI^cKwXty2>vWBPmcNq0b`-O637M0Y2%_&=pp$3@9Z4j!0PbW18NS#DOmT^u z7gJN#?x-_Au3!gDqMuELi|a`BFt#)3PSJewd=oD_x=p;)1oA32j!M(YT_TAA(S!tE zxT#>PPMG1{+cbHsH%l}3u)d0YWY=;rU?={Bua2ctvl0m#z#UK_tqP2Q-a<+lz$O!l zfD52kUe2Ofc*n?!u~jviuL~RPCZ}f?teNk##J*FstT_H_Wk?O~`S!c`$75>ya1Y!e zp(%F^#+`UWvoim8PE*vmFhUfAKh>NH2XUhC>u3jD0^&H@eqka&Y__1q_v%k4uO{Nr z_>Et_Sh3#pJcgIs%A)7}gX;#?u&~s_!OQRjh0LKctr_1#Ef?mh;h0^irsV>yv_$Uc zi$57fOh+&18HjPt?bK(-9g80lEjPV&I{#o^ss%~JS*o|V#&7d!=a@!21yAfv{e^ox ze?hVOnCQtO8U2Z*k%rduBgSK z8W-hYkmg#Kha<8fvQh`k-y0S%!dO@$6UtEPXV>|$OSgDI#fk>Q@;C`&e3Ykor>?f~sVeTQTY<3AMJ5lDUZdT&z2w#Bk!GHe0lCy5)N#0;EG1Sp1OpHB^qvaa9k~tKsV~ z4AliHlo7UKxi>=^O@+?C5T_&&2i3O=r*4Up z|6sXI9}-`a-_ZoRv6LU}m8q!W)u&;>^?$Ga=HvmM&IZh+=&|_&h>ik~lS+O=&ec_m z%#*T^z9rgf?+Q#kULaP0em+<*pWA;~p6&cC_KtIWS<>%byBdsW3B5v%=fw#~^I_~4 zNz|1lW8cX+>&0Zn$?6b`PefzD3FC$ekvL4piS%q$Ij3cnU3%6qWK4u zIhG7+RDqTLPSRu5Vg668ur^4zI1d+H-YsJHgyKl}8f)MM z7hCr)S>@6Rd*&TO8uCF^MqceQQ+vcKn1P76tQnsS3Gai(i70UfB3ds6=2V zYyk=@x1F^DnNOu2(McdTP{oFrPD1p&)D7rDef-=d#;2afpi;Vx_x#gNIe@&Q<)>Oe zN*|htYZJqcBi>k5)dr6~Na4n}9OKS*-utBjB~mnexw1o_*>Q2zrS>Nm%dh0jKxpbK zuVU21{7)BL5GE~MCa6Os zRFm7{Ohib7uD{ z?XGlpsGbRwIdai&x)#HRsju^8n~RlW2(ZEpZM`GX87r4g?%$&mL@Lk6#06^&VV-(L z6Iek#Z&nd7Nue2&k|ZpnHrK`F`6)hQf8{{kDPeYHSyz(*32Y%d;gM&0RuWX|ag*gS zjPqAwobPD}t9XH0u*=iCnW^ZnMRK|Rw8oAC1wWS!LQCB;%w$?E=bKB6NSTpxGlQPh z7!GL386DHumWRM&P7syC80BrMC8N8a<*Nrd<6$s+)6>qA_68s)1quNp1P)_{#A4{2 zjpY+gt1c6K-IWVy*nFqL3gFLTrQ#Q55YR;7lz6tOhj63;3+=~@`!msKsWLD|gFPryZF@AON}WBQrBDSZ|(#N%?s zI?4J5(8cLW72}Tk-Bmh+u*1q82TVc*Sv2OqDm`? zR%*B7ghFJk-kYq{IyTo=P)0wnjIl;TALVLdu;1#3nZl`0cJt3L=21B)_UaWC>xz=8 zRKwwf6yI0%L>TO?z0b}?Z9 z8#$!Z;J~T3OQZc8=}T}gY5+t#l8E>jczhRa#;;5RA2of5L$d1`ATgz3(IIX7vZguU=(s zayq|)rO(fFZ;yhxN*Fxep;J9~reUF?#aXx3&|Jj9PrDW_muX~-JDY1S2rM)hN@c8R zt+d6MOjN*r{yu_epM^*K*1~^U0K`JZ5oB;B5iOJ}qZoL`m_O3fW`4L&K61PQJ7Rc# z0#5c(zm04m;Y@fQ355)$?q|aw)Svb0oZ+JHKU}j{P>^eo!U01-Ba#IHdzJe2J@3&k zmB~Z?3DpV7FPEUEH15HFrX=}{%FQTTCuDkDq?tUZtd)^h=53S&6CWB)hc ziQ|bR77b%C+r(yyHGf13DiF5OUy>dO70Xd^^V%m`PLEnhmARj!+L>GXWg*mK{oGgj z+8&jdc;Pbv)yJi$Q}4sYQb*H?R;)!G+C1>izXG#u*n}KX4zeAez1S&fF136k_Rv2K z$8K6mjYCxhZsw!Ttx_|-=b|!liSlvOEkev9R%n6L3cF61VwJr6b?1W--Ms7$`3@2p zXb*nw5ockt;7giq{8#D+J!NxU)`q23RtJN~Yc;0w2Z(rrr_*n~UHy?;i{oq``Weep zfmjR+#!raEx@3Ls>UB zLLlgrY3K3&Tz+@!K<6{lyK`=OJ4Xc`FZyksx#pPX)g!)U=)TBVutwL~Wrhoc6;#6A zQ=thE0)Ml3ER<~BNo`K&gY__KY%5agik8yd-(bNPGVeVY#@#rF(nqAi`*}=fcnYu^#C&<`_YPJge4iq@B zW>3Qo?p;VJYXJqsgm zlAN9|Bv;_Cbb*Ouu_+3hO4?vp(AnzrA!Zo8yqOJqx##TQ@ctEYUQ@-}AKkm3!&+N* z6g_v^47R&U%BNMQn+(WKq8NM3m4-A?7)x*vQYf+H8?sNN>1O3z<=rMD_&eW#H*g;jxW){5LhrLM{%c zT~#EpVMM1$0r*r$ui{ncmU}>kB&_&lH7c}s3K$WNY{Mg?#BgmHSuI7P_q0pYR7v^L zsu|XANbMVi`WrICCMy?yUqB_9N%*Ki!>l0a54pgZu_=})54o-Hm&K8P6Tf@A3@oCu z@Q@ugo?p{_WzI#<5-MjWx$Z=Hn&vr{ayK!!A5;vmq511uJDVtF4O#9b>)o!QF=z>b^?VNDPc;- z9|=QZ>!60}g44739tZJY-7zK5&rl$j4ULfNx^7c+!PqIzH}!aLp`Vbkl2dyrVz>843jYQDQWjwA3c`Q zjrDeYaK_J_x&wnxwSXz`T(|z>;oUjD_L=m#J53cozVht5GZ>2%fPT4xJo2;{4mK6U@hdMw$uYJ#?89zV}($I7m6koE^YDi@5bT+7i< z;_YMg6~h)F;zc7$?2ZfGQMoK|lL=I*WCX4R(dvHJekFXvZv~j;Zb9({iMl@GpjdYL z=pulmjB|w7B{q2#*aXZp&S^T)Zkt>6ZIvFmCum35T+}w{#c2)VX*+@a8u`l2_U?h4 z#n5$6nH0@}gLJfgbcn9$pv=rsml(`98{ek~a<&sV>yfHthqPvK@%d)1Z`wijYcSmM zcLQoC`-*KmwX{cp=?Qa9*w%#uq%US;201Z%Sq_Z|yb&ysaf>R`Ocwv3tNplS(c_^- zfCk9!BQkeOV8+(>JO5yl;?E@Uc1OtKhMLxcBH8(tsD-gkpX}}v6pD?-lthFI z(J1;&;Tj*Zh~DpaXfOz=jQ@LmGG5YqI`~Mvyy#4NI?_5dmuVvNde=sst4L_N`z86! z0M}f|q6h3Tb0!DAQb_kX+qmc1f@Z6@185PpL&hvqD5p3uDg#8|52d|bN0D5lqut&F z^rG9~3YMs2Jjiy%?KGGqJ^rn@xQn|;WjuAE;|V#(!Z4lLIGlyr>jz$qg0`CztcT5J zK+H;N_SSx}`ILe&PX@*mkZw1HXE*aZP*$RTHZBkCxK_>!ZU;Ok{SD=>BQRHGG|@AV z=>53AgLfJ~jX4q+l)P6R@xcsLE(VxoYDkfL9EmcC_Io zIdI6O#VJGAJ2UEb^SOqAc`$p5XU6uL>x!GLy~vF0%Gx%v;mzlhU8zO7qTyzL&;H-O zmlPOvFFHTzjq;%lSW?glKh%kE<|?O~xac@G`r)>jf5C%4^kj=alFl0EO#0}uSF|)D zsI_SpKqoswi%Vv2JD<|R-g}I&jSntu4$RKht?6fB@r--wddWX2nK0}e&Rsn-w+2tp zN#j4fO;SwzL(F1-AWR)zG?*9e5*%45+W!^{xuoBrX>KPwoLir1X8k4e^*~YoWbUF@ zR{WDlzRDol774$P1_f&h`|#vQUwpCvInr$kGpk%*u66NIZ*)`?CrmtOzP^*_fC6YlW6)Q!7Fg&vqG z-A~6lb}{q_!;JrCB$lT%L26&$8Cy~PR$R%#OMF4Y(HC1S2@T}38F9-#5ms*Te4Jb( zoiZibneytwPm3e_Bz)sStFj?Ax>e?f>&(!FGMWGTq+_R2x&7bkUly~6XFRd^AaB&; zFQWuHCVx#>OrHm@S_ycgF`kKPlWErWtEAj+q#&LrNyJb>@i@qYDXzTW78lhTeS@rMJ*$i9hw15A&I%2UvxpzD-m~ecMEFt;2&TB)uV?ktswGIK2roLY^<1yF zdrdTT%`o%@vbvR+f=XD|IE+7}U#Z$4XGCD@US0}+gsY_q01_$oD56lEjM%X?KYEZP z3H*+@eVStWR6**-(Vg+O@#e)h^}TqI-R+=n3(?errnW2H=lX8oKn_A56Eg4}?1u=k zxNAt*(b5J}i9VSWIz>?}DuK|-&eB&pgbbivp6!st^^Ynuw_Rp|RVT3qSDWFtT2F$GmqeDAMX!1zH?cAA^K5c{w)zf3cqATesf&z4pTvYn?@)dJejhegv6ws9mPj8#j&yPS% z$j#&5T<&vf!Qp=TbxqZlpdiQ4WhO1+&9MlDirV_8XGRsXo$+U_w}rwySPIZAZlPL0 zHx;5#qo3mRSl9MPC?b~lBXlmW=adbRs6c+DkS)u+>^nP3%(^s4n5)jgi-se=M({df zQq+aji&T|uBGlX3q6v_;oRK!B=ebIgV1Vv`1*L^-oKbZJ>d{U4Po6QtB^y|cT_dOK zp#38T%$KeSeUS(pBcNQ0C1*(=v!8=sPP;l6ZswL&Ewdf#MeD(NH#@k76!%FdYD^$3snTudjqkO^TqbNZ ze__a58&C@`wNpD@A>sTp*P4;yPr=BXO0TzwqT|3za=btBb8u;}gg0|yaNg;SSmaA> zK)3+?J;CM%Bi{-IHILm`_~$6%>o8)kO>cVkG+HOc^7hjPc(3T(1$1nltb~-gL->+e(hM z`mEZ8c7LyvFkMvIN|3l--X>C0e~c4Fah}#YqpDblha1oyIQQbaYXNEX1Oux>tD4o< zc-c}Wt&V>4O^5=LS3&1aWu=$eBc#d$iT~EyjH~+7@?A4;Up6s{o0tj8w+c(U;tN( z07qdZ9QVQ~zK;n>0{iOG6QRiIgX}qmH;KcfI2r6!O`pDdr@G-0ZUG5gA4a-cqRH?S zR^;-^0Hm495V_xj=J&|{9@Nd_;1MC{i^-=A-iYDH^XWjrtBoVnksRwfsPW44rH)6& zeVYlLz;d$Q?wt}J=w4KTHizAL@;jy$`kUp;y4r)TM$uQQj69VJH#5(5c+YL*#=Ih$8_4TKW-atywh2EV!XXU=8mSH6A7FF`q<8Om| zTJbiu`*{R;OFh|j=t2Zu$#cE_DD`+M?P1qr2py^yCQApLRZL|kS|*C6eU%>NdAZi62&-~;R}HY-m@3WIiWp-38&xmyquM0T z_&t9GBWu7Gx`_*IJ-fjUjF#gCj&-WfFavkK{W3kX+8nTI<59YSD`Z_Nh{|m})=5URXX@pZBee84H{sg&O>v`sP`xx^8)Ub zxR?!MX>c>hsXA?01^OTKX0v;+6ccD_G2=XWM#Jy4GX)k3mC&nZZZmI78bS!C3j2kDt z7X&xC2x~yi!gL1i_QGXIAcT?hUDLJ<#QRL-|dz=0de#mo^hoyBC@zI)az>n z2x#i22*ASQQ#U6~%Oe%VwJ;baL2({Q>$S$laX(b}d~3!kgy_W=a&o$&c7<0vfw!<6 zOhbtlG^L|x5j1}zmp48`QVdSwmfT8i2>=WNfC+K$6?U+Hk1Ndd?f<1Mgr$_RtrY{t zf)(iQ&vG*#jPcK2F$2P9`B`fx2oJ`P(@VunuCXaFBF_cn>jUa}|4f7sFa#h78f4?D zHZj`(+KKcd6+*%i1mZiCRb~o6dmk_2rR>)0^To768V827_yEgIg|O~iL?wcI&)pe7 z$F^XEevgQ}aidD1+KgA**b$QtTKjtuOYz$Z$9ww}p|XRNs$e`hejTzb zud2oC^HIiPtvcONi$L)&_Y2n=22H1wdUJaK((fbRFmMxjNZ{j=jnb9TE+`su$hv?R z+nnBZO?CV!hg#i=c9&*@ej4Suhfg7TDu&uYA)4o2~(+oiH-6BpW# z79am&-3Pz6hL_;}UFsO{JQ;)em2VPiLc;Az}4`n#qtS9P=J5;lW?HyQe4&$?4N^e14 zU7XD;+K+^sHsY3T9{RQ~U#>tO))#d?k|rw`p9nQgIeHZ3j2~=5co|7W`FZ7q0%~u_ zXnj*^qc+%STcoOF^OJqfX9a}J{LzPE;sC-Ei$_2tE{xaLz> zvH7y&RE%*NJfj#e2-Hs} z@lVf(&2@e30t1;R0{9qEm|_7UFF>&jRDc@*kdP#kv6JW%)^7+Jvpd-yqcE6{DAZJ-k%Cb%p1+N#9mp=S z`O?pTCWtgO^xP7vuv2No{V7mEJ}<`%YEhI&jw^vn2GQ@Vme&H+E3mQM6?ZD9t)K*Gr+4_p7dZ>D+2;p0TPD z4B;Ii<4=YIarptFcEtz&I5KOr{05$@RY~_>s#bDdnbD^i#PH+^d-=z*>WA)>LWmE* z7{`H{&Fkj+iJmS=2j{aV5igF168E>>n^nTuK$ znWl>EI8XBMA9a;UicDdvs~i=+SrAe`B}$9ipN2WBN7y5mY}!&oH)5J~})2c0V+O4ZC`7xJqTw8meo?%kx zhOM^AuD(OrMGRTM)p;Jq$l{+V>Xyo_sZy~K5O<{lH}$4Js@Ogs&Z&+@e&RdIK3+B+ zuNG2}mf%nkOStd8%bgaa?S3g{ z&*@?BicUM6{ZE3h*VZ#T@G|Lg}bVl7ocHWtU zNymor)~rJ}x`&Mq<9i0l1&y$dHsJ(5JrtJj6vu?=7KSIC`-0tyBJ$ddi|kt$ht$u4 zBSmNO`>`ZJ9PG10%SomcCC}nn9>!K7CJ8%lJ#x~A?!Wf6?ljmMGr*vxrZs}ZL2wwX zdbA1v$(>!%r5c5qT<{LTo$r+tj)Q4gm}s{L0u)6+LopCtLoQ@mZx9*^1O>?!;Nu$! z0$BzG^tkwWwfCjC>&MMh-iGqhhBNnJcr~`T{p9@BwdC~W`u6LF>5BlOM<$8$J(}(h z%wen>PjL9{qqXJLg3ZI%7pm9N-DP9K5b4`{N_YF+UMOHwOYNj)5c~Sdgw=HBHj@(b znj!N;c8|`*QhNB~YG~Y6l3-7!oE|;~p15KQF+y13L3nButxzK4JjBz9|;u%K@TX%5DNkn0AU!L#{F#LuMdh9 zh9c)MH8GO2_H{joB@cy5(!=(Ocxu$Rg4E=UXbb7Q)Ik7$i?vQ(rfymp%adx=ZGVwZ z{1j>D$y)w40-?u2Az-1M^d+a0T;m2eCP+5x}=a~B1-K*vYItd9s zjB9C4h~v#P3Veof6=+feB@2f=IgtC%>9oN{;6EsdQ!qAtQ`(>sLxi0BOZPRgCuobG?mq1e+kT+L6)M!WRE8`Puiku`ImkC3 zPp4cytBI1$I7tlWUiY8RVGt2L?rPw0(1579pmwe#r+Pd!07rOp@w1sczN_{=OsYELVJd#C&=mOthAu)PHTA+(uAZj(G;4^Hsjf*eWVh(Y7}>e(>vIL@)_1vif^ zMubwAcuMes>rYMuQ)g{TG6;uYal1TOGOGvtkx1`GVXeHv!JdZ0^6>yz+qj{MyHYzy zP~~Fcx{Jt^raaV;k*5ECIYn`icH6Un7c|LNBw;f`LG5$Vw4Lv z0QVSpVZ2I=wT2w2z+z9D#j`s|*GT(Y54P zGU$strySo^R32{t0)9~`FA$H^T+5%FDVJbU-%Gtw9>{?m2{mKyT?WYxLYb12nDbG9 zO@v0Hy8{Otg?c*)5Vch5UX78fbclNU6=goa=z+5aEkG*+(D6syVf|E zYe!X;hk!U9+(_RP-W*wnFj(*Jtr}9&jC9&VtPu)XgpG!Y%DC`-#=5FS)LHwAbU3uT z-e5=H8d-{Hb|HmVj^M@<1cjmRW7Q7{pA6y5SN!2PexE(q>haN{>cVak*I@_rl|o?@ zlXCu~sgfvl)XDpT8^gu(%&>TeYawut>wt^J$km@~8z<_1oT;h9aP0n$2IlddW=u>s z5Ct!xlFXd`w3Lga#zE7RCj$CG-@Y7&UX z$=2^h5Py8d_n;x-y>6;_D3@7ct|&e5p@RcO@^89hZ*t0tiLj0zwbjfdbCh;YaC23b z=DnAIM$Z@@SE*jP0=ze-d^79nMj(#snQ+I`d7m>cerxkR2WZwec<#bm;if(2FjSOA z@%bla8W7^$i&8sBmdQJTSNDeGJuuY*fQPFni}(=#K)|^<_BRY6MO4?7dUZ3NpSt^Z zMa08cq49VmMA!`rAg;LMeEurH3$-g2D0WB%QpTW+m6RwF9;$fyQW!wqv2SK#mVlap z23N*n$U0n+BEzTPPKZyuUHsdF_V=cUH|q35Lq}e(C1g2hZR*WDN=W6a0)l5<9@G%yFU1rmmjF3JOmk+$To%5Xp}8e0I8$XKupU>9^{B`P*numtQ$ zq3D7dfB_Qj9fh$n^ww@yI)~i%zzRx`k~WaB4eRAZ~pboOE)vibv*cYjM?X&eGz z_Wl!=!DTR{>40X-P>ED%0q;0KV5mMqFjePyauM9s#1yky_UtzgL%)?QmWX&)ZN?Vq zW&c|@MO5oh(fT7+Sw2>8TF*(I)cDXpOAeK!g{=`tIt0rDa@Czru@*H393<5iG)j~d z=1}~rH+piGlqI0@t21PhlN3py=&NtYl(y(@S(1rH+;`b5I$ zy&MGun7_~f8np5o!=QM{wHwt0J6B+RR*y3wBps~Y{z{EAp-DQd-uOxzXF^Civ!L~r z8fQXFy4bz>l{Vgll$?=*^rr}DU@l2Tg+S_4C})~UML~J;Q#jW&lZp(1^rv9%G?R*e z^3>=Uxvpp(uCh6B!ZD ziPnZxwoqU&+8Mfl&*G#>f~^p!xpUl*W$s}>&-y$L$Hc&9!H~+Y$syaIm%xn7c2GPL zRGr5ne<-QK+ASij9_U<2wxbUK<>FvMj#EnXCZYbKtZ*{h7sB8-2`xUt3}@2VI&=1A8xU^o~k?6>}Xf^X-{MGqDW zO{%Uq7$p?wsGtb=KWv&10k68BS6AOrw3fAat>#snjIg)|Xlr2aaRw=!{a*lG5=_Z1 zUz)TJ61!>t$Gcy2dFPTZ~7(J?Tp zq04&#dfSC3AK~KiV}HdHaxgtr`ILjby%H+nXW1$LBg8NZss`Iwwzh$umF38H2n|5* zyw8|*4`uUlUU!j5P)Eh3&1gXg5RT_eq8*isROp`|I!q6jHZw`u=3Z%=os$2YK`U;- zKELh0BFBcGDJnQQB75*mVCXZ@Qd4COuv(n<_WofN;F01DXhB2moSvN(m)&&wToook z?J(Pr#^PTA@1qq&COiFRV$&gzTM?&|F}_e&_%p@&)6N-tn3(ZE`HSf+Hi<*;ERD1_pd z;Hkt2>xP2dH3RR2e*=vkk$COXYgG`~-yTw=PCy05Vm!8w2{>JN9HIR}=vJAaddk;r zl2R0M4X62A<0}|sjreyChclAMJL(>I`PoS}N!4e-!4!36v zQV1aN*O^-)>_hEqhjg9@V^YJSk3|N_%_h@UN&C5tDMps8Vi|rD5F4x z-s!%g_>h^)tIUvI@WO@@(6;|12SH!_3RP}n=@H~uk9o$KY6g=T8bC;WB^8O+BpX1p z7?Pk8KMd7M)RPfH<-iZ%t#I&)tOANdvB9CAsL7+~`fBRHj)PxJVib?rGDJ)(7w%Yr zF~X@@09aYnOyp$gq=uCfPvXBEN4F|-J7cU`|Gilo05D7+szUU!qf|hP4;j7S8(8!v z6@mUu&Vu)46p9;wn399L>cvuDa2##lry>0`UW_OZnFAG&UW@WFmbbQ7_#KtI{?z^M zgsL;%N0Sesst)2wlhyy9TV_FyHmIR*%xpkzo7KL*ELE*>K1n+}OG{`<;PaQl2@_Yn zl_OZQTyNt^uy6q@q`53u1XA=0j|;>kP)vdOfN^(iB-I9wIlED!zj-=B^s_S4pxYVc zQXo^FXtBUwQ?$>I=KBLO$jb$`nw#~KX-ohxPTU7pc zt+>3HP@xwMU|b;zaGQLwpJ2~I70U4S<|4Id_u0?bFFX`ZMKMmsdHCS2j36_@#3|#a zWykaipt0|7&x`yDk;CpHy%&Nu(`Oj^e@JO8!D#`Ru?EQQGyX_Cde@coRE=mqR(H1d zJO?=dvlH9SSc&~09n&RzZm9yar1N%iOC)nBlz5vqVt}9nD28x~VbDDuZ=sxgEiIIP zYk=gZckwB(Iei<$h98SdSv(_N)SF#TSH$k)^gS~GH|1^hjs z_rkd!{5xGx=spBMf>b~er2I@eJobnm`_{1Evd3u-JDSZo+iGzQsEP!)LPLkfC(h3T zI{gymQcE2tydo8Nj~W{;@4$Pwzhk-JpU5SA79jez%y}z_V$jfGn;w~;$YcYH>k7#! zYh)6IHGvh_!@`wVn<^2IwU6+}Ri=dGt}u63tkq-IH~Wj-AM+5IS>n8gjwBBGXVHuQ zuCxscm%eXL{Hy6gxzS1qF_ji!2xV`5Gc=K*wBOwFCClF%1DqGk2~kj;MtD~zMf@O4llqLea|+=7k|fr|lDa53RSHyhf* zg0hW)5tD>D&Cc@Ktp`k#P}=t8dpk>902Ar=vqO+!K=;ILwvu$GT-xqX;32d zR2dN6&}qq_fKq)b85#71c4bnj%JYG$u}S$J!)T`E!nuvRdWF-7|4y9Z@Od35qHI5p zqrCZzFLbn>FXUs&d#pQwCNL@$H2*~-7xa~fRLH!YPuqvI2lt=&aDk=#8C2lPV_5KE zuE7v8_Y)GS8`8o|5cb7Eae(yA*n78pf_r2Yv;{*@=n2i>f9nSJE?=z0kO_nxlggHo zTwl*|5W}iyL_}QA+Co+BCbW)=6p3y##6x7)$7o#FX?Ki7t zJusOfDH^EEUt4~xWFHZNKatdq^sMy!c_>6<4^+W-wwy zQ|LimE~AOb!kJVh=?vNFsIzt&B@}+Spn*wmTrT4%N?2}FU?9Vqx>~A!B;Mnf@x0T6 zHRysjXgS!Qgn}iLNls8YbcNd>qR-K~Lwv`3Sr0KlhNezqAJ7LSwDwn4M*vII(=~Ij zs-5YZ)LiLj^b!XM!9=jGVAb_M;$c4@(Y0(6>(Jd>KCQVsHG#yjT)J%Bi;*Y7M z99c~te(og{uTqb+o%0t~&ezt%L779N-M6UqN#Tsd0{NU3wS1IRI$r1Z80NSB2C)61 zfDRsI(GqYT4Z=OPSqYaUWY0jCzW)kJ0R*+i!B;(pVJCqsm|GZhk_*)sJS14WefVHH z^Z||CH$N_4YhH|to^PPX7ef>9V9Q@?Rz>2d>`g7yJK(*-!Sho}vdIZ(3J(12cjD!T c^?(A|nXVIQMou8jK)}ft&yFEwA17G*KjbP^TG%c)|7VZo3Xno-Ara6s}pLyxRXTbod@v5YfRbPdH4fr?Sv z3+AV4nxtC>J_aZTb*%NiN_;P>WL5%)Q<_{AEtQD1oCGeS)Qv5^L8dL5Gb|{Af7eyF zm}p(TN<=hCtz{>XiGY*9B9XRN<^w&gP!1=g2~~bK2uX5toveJR*a9~gQV>E)f?^4Z zV2k9Xi#OH8-jQ|Dfi67;jKyUH87j5aln@h%h!da+6fHT4O2WBrK%k911tmRiP?a z>v)V8TpiDl(1w}cPpen^@+!xyqX<|&#^G7@crax(e@PS;Ds38$QxtML=w2w?beuGC z_&AtiEYH6wtl>Jn_NK#4?|P4+IGUsdq;LwJV}d{)K?$Ju5oao^q2Mcet}RxOZ8kH;OPejb)CN$lNu!rxc-Pfd9{ERVy4R7i=tY{bhf|ciNQ8^6R+JWbgoucUh=_=&NPMbo2K2sN zMR-4D5%#6i!^Q7n4oa^IddR)^7K`*=FlKb|x|e%o=V1QYzc9S$T4fW#M6{4d{Qg~2 z69<=xXyai1+P^Ql-mp_7*hET4*GZXQ@6F3365*+Q5Op3(X)ie1;*^yM-9bS?K|!zA z><7)l{QF6_W){x;wUX&4=ObhDEKj?HF5%0s62wwK<%~T+k5{W zK)s-C>R{q8Z;ykM;F|8sndPTgBqeznc#8xCo)8uII#bR6o^_0+)mvh&cmF~?D zbGb+|KMD;3M3QWo*&`@pm|Lwdp$Ep_BYVSyK3@n_`h`K}^U*XFTbzV6JH$TrOcslcP^U4#l2|OpIgzpoA}NrZyIdt)frOIUj>9NxJ52Y1bDg0J^nZUO#^EkklHrv)pdO5v;0%t*u2LxeO|n4R<3my#0@Df!1nh`nV% zb^P~>)5OM7`KUW@q5nrF?R@1z?L3?@3x6UHP|I&bX^lKoYAy5!qvbD-eo0hXG{18) z?u1BGRAa#1T2R^$-gPs zdQ0bJe%@#0YQn^3sdM?KDglkow_uTMFfnxRun_+63J|spGoeW6;{%EmA3bJ}GJDda z$qYYQh+&2!C{UtExk1VgBq%LJdEtl!8-5_b1{OFDF_7@%h8Jd#@`4RNUU&jU_G8s* zO-)U$_6wpZAK<9LhOU|%jo^ry4$9XZ-4_xlZ~WB_9*_%huRtO>)eduHd$0E1FZKnS zhR$|vGlSaP=H4nOdvD>}2iQ3q1anFdI&%m~tT+gVcWewe){{VaPR*9jLqjd^zwWcP z?!2ETs+0EqjuqjVzcb6$kve(aab24_SUNloNX=M(?+pMO z3yhg=KK(}O;h4)=k#ng?wHA|PqJ5bURSW?3tkG;Hy2Rd`fTfyHQ&6Q z_gL<`us|Ly&MZ<|oVQRE$=ywW!-=<{wR>+HHr8%KtF<{<5XSE<_t97`PSv1PQ&3R< zr{gMG_QYC-xA?jpChh7LXxS5M6UcAiH#}E|LyEbgw0v_7U5kx_kqp z;~3L4O<;BcE3Yw>(lYYnZdjpKxa#q6h!S@}#g2zYTCU>#c*v{0czmE_f|?Du?git= z1i!-P45e(-=>hJSS8p;3SK+4VCs99+sXX~yE(;&HytkVHY^zMBHc2_R0huJ(0?!B| zBmoi_D;S%ml|=nGF2Iw|5#jRQZgl``t4zkFNy@VTnIst}1fKCln8AzHi%rud*ik=@ zN058+xhj&lytmsHZL93XZ<2DZh5$e&Im9z=7g&txe6L(=dJ8u{wgL#Bb8@R-jSL4j zg1oI(Y=~By&Z7UAhF2}A;G|KVpaRabkWQ#nVI0+_SNO3QpF463SD7pZ2r1_>noN?k zzyV`Um=hx9Y?>DH;}`=zmuvIhZaJ(nS(%h`oJo>5+Eg)uAsA8sZkm?i$1w#Q@VQ(C zv-fu6`J%&PlgVP3Dd#+sB&SBGy>2!G%4;uPS-u1kTXvulr3HHX!WIbvi6V_9F+m6j zBx3e}XpwbZt17M@k>uE_y4I9x>qGIWaiPp=OekH)_YT7;D=-&|42?~Zf2pk3IHE(> zcEku{?54G*8s*Molu5I()xwH_v%ENpMy&K zieeW2=o~=p>qlw%a!{%LXmIp*eEa7BN)v;)+D#Sgl)W{QQ=IIiY-VU!p$=N18@gAl zO8ZKZfmW!-tBDzCo0`^CPT|x|)f7$3R9vA3^K~2qOR|Vj{^`v8&WmUjQN-S|h2BMk zSCn4!752yf8qccb!C?W`mMuFiIWF%O+z;*!T5h%#2JHqdPWB5fXwjnN3j5l>&XIse zTqJ0rQC{KwXd#IpVkRPr2q!QSkI9B8w>ZQ|_jrEQ)s2xZjuU^4+c7TJS2R_HaD^=) z$lA+4hjhcGrHKa7qJ2Sx@(cT0Oojx6DULvtzIdkL)qQ0y9{XXe_YdNn>#>`vD{qlL zxO~|1ulo&`Q%yAOf%Jtvv_9-*oDAuPj^zT(1uxN$Ius#&uzbVhLb}$W~awMoZ}ZY+gd|jnC=j z%4JNrc3%}m<(-yr+O(f=daY2e5R+5N+)c*G6+&8t7>ub~*S@anDvNQ~C<7|3bMFn6 zHL*ENrYnRyQ3cw26=D@$cTLSvg>CeWywS^qtHbQMOqgq(z9u?;*(z+<=r^TCzDYEC zjgZoq%c$j>JB|rbA5%HD8o9ibMy>C2nao{GCVi=9f?Il-An~SNG7*dFBDn}Ia*Na= zGz0108|5F6rVJ-|2E@`c5!Ip^1EVa%Yms|_vPgx05n5Cf(sAy#WQkh=29$15SOJr+ z<2Q#cxgoKa$S43W;S@-hkW01|>)gM8*VG(S*g4YVwSY)4T_2b{9&^u)U-s*JM7jRd zO~H(SnZgKxI)xpZLohWeQl#E-NHJHe<(rK#B4qFFGJ87&leagxJurJap;?-wiPYCv zH=@LSBsUgwfEjbW0U%x5=@wMkW6o;D&46|;vO-~u75YZ4kdTm2JOqQOdioC9QvdA5 zpQgVNRR()XEgl+jYpj_CDc=WWT<+5|)eEC(D)kD;b6;i~5r6}!&_UJnw+w5K3~1-L zEA*LVKH|J>8HD8zV`~7}Id66~fNc258JKnkYKWzv&841=XCu$@3bWx~BK4h1yKU#g+-agtXf4Cy&1`ay|>xP-oQm`?!ux^>feHNhCMy>%=64|iPjw4WjIddt4lehuV~Xd2rCS$p%HsUCDx4NtsTO+z~!70J(a+#B9!_oYN(AGVo`sxADBaJmv7V< za6;=GRoWGx6M>XJAiF+$-p2#5R}(!zJs9C0YMS@?v>yWU>@41;Aw`$t2R2p~sLlSP zuIuy1f1!Fx9hQx;rgM}f?ZG>P1&S;YC89^44I%-1AZi`#0Yb_2WA#btZ2dmi&|Gt7 zSrZ4@)#Vx=A#J8}R>vTTRin)dsejf;V*U2sF)5#nB)Sca9cR+a$<8~LP@Q<+0FM7t zA9Wn0oueJNIaR#5Ehqb~t9zTdIltmwoGZfcFB7+Qc6-+zBa#bu8HtmH)u$S+yRs|e z*E=#hPgQ@TWdFIq0Pp-RhCwI`LSYA>b0A(K)~uwafJQ8X(XxMEB1oJ=aB zx;jRJEyoER3qy96w3qXZy0`M*k;=kJ2M?^hS-&Zom01>|^Cv5Rsa1kXVq3OOQu=Z7 zK0*0U{D)RaDh9ALu=vC zSkcG8#g;q&R$A`JZ?xb;h}lej%ctdE4QuPr#vj}C5z6$n%pE+I<(=Axj?Z~EcT@`6 zU+;Q}&Oy=y+x?2dNTc%X2<&6S&f`r(jWOp0_Q}c5xL55>6T=SxukyQji%N11vRba^I5PvmwRYt z3Hc4AV*R)D*BIDXZfYL9Hyp8ZSIfh36vOzSaNwLh80ZKyFetQBeCHa-T?)?0MxCur z6s;C@vMVu9qwIf(E6`V9To4QY=a7yDQXwmIU}L$UYf{))D!TTk&Q_j+u_5g%Ye;RN z>T!DuQe@aLKIH(`F2%`yCaEps?W!eyydF<$Iy6D261+i-lnm90)Nu}W8)V!%PQ%#p z(`1M-QWBC_+sE>s|7rOjN@pD~C`6blLxP+SJ5iK}KEgU1VtYu2{ zaLkxFd-E*9kS;0~WK`Z5(F$~h#pwo%_yVCJ(0DU-Pi*VD#vqCulSIMTsJFL)wLBLJ zI5v0klK((TFL^Jn?048QX3QA+)uI0H-reZS-CshVMlb7XUF}O9tSdp_eX83|s26t$ zU8<#!qKgjJp}Y5KJOg_frGT}cj0(d#P!l4S>Lm|k?tpK%AxgC6Ai zX{v|Jz)OA!g@XD%^`#EgmAdVOLh-KJ=ujOj=IhYi`!r7N5O<^hy8WdLT4r~8Cgzh- zyL>tb(o&r+c_UURJ4RkfFXkO1iut~L8pXI2XptkFB4I{SjLm-mxhICZuiH+j4wgHB z-wslq`vmiNF(W){`=II zI#`G5O5Jusc{w@Yp5xnLuw(3Nf9ViI3CjmcP3aQ)WwqIM?{4&8%bCGDc-99gQDd|yJ*u;sJ-YrjSPvmOClVg1^t!S=m%yd&)@jJ`20i6l;5 z51e`Wc0mgCxFtzAToQ5;IGQHk)ZGffohHvSJ@-(jvrm)1uj!V9YD#yOQrl`f{|5TE z3<|h$oJ5srnFgBYPt#l`VD=B%u(5E?7S74$+z>aMq%y~bhg&Yr_5IyJbFk2CLv`o~ zwX?Yn=W=QcslL(dN(4%!4*`_RH^P4bVO+WKlEm6yXtggVn_F|UIezOH_8t~z zEKN565q<#$523T11sYJ@g zdZPpDXMvq)CpfK76&Cb=9q1qaqfb2Xd+#s}_uqT(XcEe5A*J3i`}6E$*5bU?H?ySI z&`9N5kE*V;771xxSK8U?bSH0~XLL<=V$tLn7qjTL(z+fc>t_E(|NKDh9`m~ z%5r!Mv(!4fdmm_Dtpm$9B%~e+!!R`-Ck$C$h5`;!!Da&|9>V^P(=_N~B(ZjAkglK> zQlrM&so?$f|Mb7@Fl!tt!dsaTq+$iD@HtemhFNGduq<^Cv>Hh7L@C+Eas!GW&cH&4 zaJS+2dI=b3IvwR%j(KeE)FL&*F5E+k3J2MB7>#%Qd}mJ;fGaG~h1y>`ke6XW9;XfE z88hwa*@RMeAv&hDS>!3|DgOIp1q+sw_i3uHYSS6bZNmGov37j5`ZiOgX_AWQcIy#a zD&Ff66EL&>$3}!a6T9oau(J2m&U<{aj$Anf)HPh6MQS1_wX1z8#l+wWC{^S2P!Esd z3W=>3&1|DNd36$M+jH5a)HFGm45&ma7`IwP0tf&A1OZc*5D*ND#?m+u6x9bL#iHWn zWTJvaVk#UM1BBsFhzvy`002P{Q~&@F0H6?HOjctf07AOsPVbY>otW3rIlVdf(HZG@ zJmqpT;wERS&dep@Ha)-mt@Na`Wx$h8+>-%y*Nwcr-sw0UTr(53baalhRGpUG`)Ee9 z6*cdKqVc`-75k$2UJUJZUa41ZjF0A3hQK_5j>fdLZ&P&G$vablzgDW=$Q*QBgwY** zKZ;9Zqn%73{G2m6ta4t|IBx1OR|W zru1P8%l~Qljt;gWoWmO`#Td@@JoH;1m1=}A6TZ43*jIf-n!~l`C0P`0774GjPb=Xf zBgDIRpsLCs*|?B#hC9sr_^np3h+8aZLe@zanG|h5m@D`1;{f|*r4cs zP4ga^Hdfk(KDHuLFq#u#s^?S{ElNHH;Ahkxb)Ly{S$e2(cXV&)YX3ZC&Y;9H31{*C zn#tf>>?+brvT<8mEVFF1$*mOCRL$H+8~5yYICChik@;lG&mg=b7gm>J5kIl~wFsfM zA(&4$a+XjTxR=p1_Tj#%s$qeWMT~4|Yz{XR$r{`co$~L;9i%73_BJc%6n3K!K(tgq zMEqQB;iImI>sL4^d}yOx@>9Uf)`3p|PSf-o2HM0Ac7ZD(y%h3#yhuhH;!cOBJi&Uk zS^jk4BWjHqSsPDrIEZ_@-~bO1yv(e4IZv?YHDv-4%t6);jWyQ@dONnThF91Q7JQMI za?CYLW)K{dR4IzqAC8-S#Oe2$A(Y?`vt2wd9V&tA`oJWDN zuP9l*%K$XS-w#*t4WdIeZe?M9`TV1|^Eg@6R6~n-$Uwmxa;azjj7`hnq^$wBiZz1K zFn={uODCVZQ6G)|$En9`3_X4}_=!cOt$aNL7~X4nM%0K`1>Esc`r9U~_;sB|1W44y z-p~eQ_GT2?G-o@dC+vN8LXw0Cmi{GCRf!oDD*D)?liGa?y((6;@K8D6dnSd^FQ?x7SQ2!ti7s-X&Bm_s-7 zq2z9B)E?nM@perv*=ULqEU=tme3QI~mlF^{DaNokl=2cDOSj4ZY5X@5dFb|~;g)~b zf(|db8zYPMm+FP|tmg`@w>TtZuapD=?%o-fdRuf*J#c;#|1@Kh^O#$%aKCmmQ`(qv zH*ojlZ=!x^v3+j-Da&j*KW)GFLjAR@iEzsRpTb(!TD4ar2Ji`TduzXcL6}V2@Hstf zs`e=Ge@kHjj;r&`$yvLFD-0Z;Y8_gH?YTRJ;AKtlwa7H!al>w8n_D^H=C41rEc%RS zF}G;=(HM1;g)VmxPY7B?ulOE~46IL?SpZ0#(Tezo>zb7!BnY9hpo2dr@H|)Ry&Fqk zjJX=vSzO)0IS?VVDzvMQe5YY}fIX@;k4Z%b>@s^U%{0EtMpO7k%D6}WvG`XXaixDb zjRI7UO6NTKpn`7ubYZRPj%JS~t_gN42RwLe5$IZE*tJo}2YvXeoyIm^Ni=B%P)-`Ke17BX<5gPRm0@Od|c@4XUXpE|y&PspTe+g6EU1t%v@&JxiycP8YZ z#;MrNTl%lSBKes*W)HNZU|TuQIz%>fZV$L_!tYVAjm_cx;4Jk-tOT4hprsk3#92nb zKJ9X69-V!s^CZ?RH_Y;$5d2P_3}gMdlM>Io>cy;cPV2wFG+Tb|{J|3^Tu*6`wZ`4f zNGO9ys{zo%qidc>O=|FLeVW}uubD|(UxZdf;yQGAp2gtvS+I8Vp14}&A5peaN z#pjS>_%Rn0(Z0RL_)6vZ1}JPihQ-{u4zSDX_(GUY)AKRDK##;bvge`_LoQ(gzsLrKZ#-#*#eaFZHNd$-DY0N=V$`EhSd4`H;%0W|~^&*c= z8^qq7%tndf;HQ%~l??&ISD~NmmQYA%lpVHXMnzz%q?Y)eUe&n&wskwEN~+FvPHqSY z_ImX&+ce9)`(+fG%LDb)i;K))$^_!7+h=^V3{7;0`J4RyY34FJS|y#y50^%QBKh6< z3qkuv&Y3f$xW5#|GTQOYSgpeiv0d0emf2pqWq|CXTy|0o z_{^yFhAaBiuTM;BE8`iT(UiK=+YPK&ycRUtnsPkBHwjP19K45dnWpV!4*~*P=NTl< zcn3V7(Li%ySf7+13osiWBb+h+=&ci!WeaAUlqt;e*h5ymCNpWcBR`uq#VREsgAXcu z5Xz4{<*Dr4nN|Wk1x`THYa_2s+s6}yS{fx?!klS7)qD5V_9w!CXZ0iWN<#Vfp5nDW zaC`I6E_yU;pQ~7T-Z!r?Yw9pijdL|e+Xq!K5&u&*6dhHG-6zR(DhZEo&_p74m>&Fb zh`8D=WsDN-_j@2)oi0AN~L9Qcexpw6z~C-csSt$6D{LyXbG4* zMLtkkwP80Q&Abpp*9gkc2t-A0PW5Z?xs|(Fb#IG+H*A66e3bl<+U;GPnQZXBT6*!= zUITb!|Aifb?s9_kW&LOpHb15|PY1;-(nhS{#vGk@Hfd;Z8P?fDSC@UC>?uo0lZxBzy6G8Msdb3V z&K9TwwTBypo{b&&kC9mj7r-^yx5zUIADl;CZ+!>IXm`j!C96&~b&AE8DsB6jAv z@nBs2%(%9hNd;6QRR4<9yG{i_?P*t*3 zz^7wY)D1|kB&DY)wo|E*QDw5zc_0ogu`v%IUNwi3UvXHo*RE;^jsbb2uUQ z9uo3aMtUkS3k(Z;kuj5bfphMqpB-;d{b&>f+YBWauI`EB2#J9R8T#N>%e9xNx8xW*s-S@=dW#{u{ zT`0N)^OMTmQ#N@rxJ=n@KaQs?dS|VwBS-?iOwov#UBo(`lY}y!&Ii%Vh7Y;F1s(4Q zriw-LkW)W#fGxsT-QKuWVN6>lVKC# zVc?Qo1(ej`=$Ca%E#_Cj

q@G$YyO@(2yJh+X1j4T^Sf)DAEM$1M5mh=R+>+=}P> z-*{K~!)kEcfYSWE873aOgBFfEU8&=(+^-R{?2$#b@$5cnI z7yrx39zv(UM59d!ztFDfWTzQ!f?(z(f(#WqBceLu;PHym1aRW*3$FpN-e^Fc!PJa;9V<*y{w8$)hLB>6v!3UI^=NIn=LLQzX z38y;e(Id@*RnAsQ?Mlb(`q!YcI6tJ=zzjgb^N{K;cT|N-1um4NPqOY-z1cz7ov5M=7l1BHTpKN`*HlQV7s$Uy@S8R-Elr)ALh79wVfBm zg|V(GquA85FnL*(ow6x6tq-A#7(^*$*Xo55rqdb^5BMV}=Fbs(Cow=6PnFF>&TVtD zBcmqzzY%V+Y)uSkodFeo^JySyi9B{Kjd*FmC|M^yq-5 z=mq)`OQr~n0HxiV<_oLqp%_Ce$2#pKC`C{V&LH6`oDh(Klg=Aj76lcabOE1Cps98p|h+hemft%ij?|4qq>5p*S!Y4iXINizHcZ? z{sGx^Y55)~${T{{r!E@^1-ewzZKNPB`-A&JDnc+Kx?HBz_ZN08D9-(kw5Q^BU!y zklKO#Q0e27F}DZ^s#zp15da_xDtXf)hb1J>E*fknHiWSPV5>?k1)0WAN_z*m6N_Qum;@uLkMFe1{S-zDN6sDCfQl zq1yz>9#Entd5yKf`whihR4<=jz3Z7>Ae(8iPlz-`#t1QrzMXAMAEQd2N)%`2qI->o zW55yZt1gekCY{?@1?E&EgAJo_13YCV{+paSr1xQFZ;BaH6eTAlfPAtk7~VYbLAJaQjRNf4<9IV+0L5`i_nLK_C0Gy7cf3kg37yNQBN< z;&K3jd6H<*b5?#V*T3gpedUj8NS`Dz#GBNrEcUPMpH~JJ)RYa_UvC(>+B}z^R!9Mc zAyM(K>5c?;EHj=qN*v>;XCtEP3p>`69~~uglYict5jSz3r)I3-=f(M($(-doVppeM z(33yw>_wDvtUFGb6D8SA7)@`3XMI>I6OQ1ToNJPXD`b5#A&m8`^JFvdh{ZL;Nl)ac zo7t*v{{_Oe*X(Uh(9mf8LR@7-uVpjAdQ7^5TAo$?_D@iz!tm#LEW;n3CtfaNvPu6j z*Z!pVeSg4*7LxFyW5Ix@gE-I2pFW2EnRF1QL~{SFQd2UP3FhfoMXo-zjUDWB_oPPj zVde}esRUq-WaJ%ipwSf_O!>6*6nQ1j6h}kJ1EUQ4q`fhe-4t17Bdvb%a~fO7ou|j4 z{N#cU2Ou?)hAQ|hFDZZIu81xtI=47skf9U z_RP@vpGw35t-&R1<@nzBBc1#}=KW#3!+nL*jC(QO%!_uFZ}m%x<}arh0IG9}oU?xl zv0=Kh)bf*XKn;dIH1lQ_o^tCLzZNrIDO@|6u@7moGbTY>smG_N%@An1Ur~5P7{Q}> z3r{K{XK{Oqg`2oUZkT^#XaYTd@XJX|-y4r}T|YULjUUE|3n2Hq?tz{~@@L@j_7kxd z;C{Jkm;$c9C7zEZz|GA;-T6@x9vc=ARP*+L3$FT zn+)oCm@)0d53fNnsG<_(5jK)<<|{hjFM}a8_fQeZaW@`BjiV}30+3W?2piZXI^zU1 zHKnknLof_KbTkP_r=uN{6cE;cA@=Ja@23&@Y?pl(^%+hWtBot?OCwe7K1{6Uh&%7I zp+0y2;cySev1xUFD>E8v^a+j1E{8@D!@&i2QBZ!<>$ev<{hv#(4`RS1qrxiA&K;~JE<%q8m?K?w+VA|PIL`Wg(Fe6WD0V`J>rDq{ z&6yAf&9OtU;h>C@Va0f__tN(>@0?hy1XE$-p`!&swhLx@0MxrO9qJJR)F))Mc}>JQ zokeMv55xYGvy|hz)!iQcW{xsW%xcD0cbskG%r_d$UEf@e2hTiJ{mIzW_*DQBbjH@o z{9?^s2NPpH3P9;{8dIAkWkM|f!1^}16(q346107Ap_OTZx(8>L%MlO+h(JF_hX7Fd z!6hD*|FbnlE%)uUU?K>I!e{D<)C{>Z6wref4Z2vKowsqD4K!(_j^@DEiE(2NiZsx} zvDAr=cv0hu;;s@0=Wx2>M9s5_yPksq(01XCAgS%twq_T7H;l~>l7HnXDKiZJ@N)7a zL(U@tn@t`a6^1|6TX3kUSQ#faf{g^kvTQjwTDG4xhU$2sA{l` z#@&B+24}?-BVk31&Nd=ppE&}u8?*Y5I13bpZJlhw%->{yy3xHZ zj@$MkecvhjIfBnaqlLkU%;1f{F(qg&(2C4}HOCXsg-uVUIePvmp3*nOQtXM2?05_~e{$W`NMxo4jS-lQM zfEoDYl&X`7XZtaQ6mGC3#b@vg1Y!0kYXYnRxU>U`@qrOv&Sv%C8RU|Q7j1#+?zlr=+Du#J>nng21F3hS;#Zv zcbb;L0CU7~aFu>-t}YCpB8C14SgT}PF$Rh&)CGpi72<@sW1(WH!XGqi$JT!O4%4O! zve8P(V%v~SNIO$eOlZ5{CW7pY+-i|eTGnojH>EUE?RugCQTdXqqWjLnOuQ9+Egw=8 zavkJTU1&~hvH=UjfN^haC(KDmWibpF1Kd>J%W5#TaB<@tGaXhySfT^BJRxw^*dUg= z=>Zv&0*jzZ$!EXdsYgCk@$-GHqy4>#|29lF$vvOym zJUeL=N<1TU#Gs?};7NJ{(?h}%RaCfb>BMIFQE?_xCbLGxm9n8oX1pIl);9zD{Hw#cTOq|A#jyhZOEm+xJ;B+4Z}%P_M) z9MY8obQ6)KIu612KJMV+G6?GLO;-COo% zCln*&Q}BCXDniO0@Nwbks-nsFAlUQ6SG8TQ#xF_uO3s9pyhtUB9D&mVE!UNtUNeXTUh$xU4$O#n4N|c& z(xC>o)99D5Y|;YJDJJ$NVYPg~A75$}AU8vU>`EVH1jGDa&o=w!TR{*LSR8?`aiWa| z{+?Nq6&NO}XOGjkQOBbZc{d}wu}zJ!m%Rbe*$|LZD4!gx&q6x#W75%gs z-&?g0wzqWr3TV1-M$@^gBh!n2d6J3HvI*qiz$Cw4`0FvAe@n{&>eoRBBNO@kgK&U# zlx*hDv7s~@+At5GK!}JFLG8+}ak}xXdr&3+dDqA|Du*?v6%d~gr&O>Rsz&<)x-nDl zq<&a)`KQ5~72=v$! zj|TT1_O8SyiASUn+wZ~)N%9_npwFj}Y?urt|7@)MKEB1AEG(k+Gi= z0DGLqK@BO|boW|JvA%vrBQX|LV_Y5FQG4_1=by4UmWrn*#l^eOHN7l%LAeixm4z8p zrXL;tOrNViHVFB1?}ni^q_d3c4+oIYr7 zB*U%@)pSlP9sVf$oyyQoFX*hOD9p$4nZWgpfrk}N7C+of>J zvkhQ8Fcc500{$xhfy1Oi0F*v>JR?I_AF|rVdY`>PL^|deUDO#T<15w3eqLuFbPUIq zyRuxuERWW|Ah}U?p2A*{sPqI#_y80-byfly)nU@gz~>IsByu;81vNKwLIa$$ZV)q2 zgGPq!=ttxLO5-(?(y^v%<)m=7Q9IZe)Hqg@D3i0rqIRTrArf3Q%&U*TWWecvA?&opE8cv z!oh$ko%j$M)iwn=aeCF^b;l0QiJc{gcNCiyq%iMHb6=KY3wheEGzjZitVbrklSXtf zKSz#G&__(cc$5cL$Ca4krndQ@*du$u0ZOrs!yZnu#Ij5@JUth)I18?Vs%h^`S+E_J zd;&|Xm3W($e*Z27GVLS>%dl$~X9Te}z@AlO=Q$>?u-aYDRevjk3CP!@)>n&{fkCQ7#FCD;XRFmxv#u zoS!hL+PD}KkbZCcs@DnD5REcrhr8hRY61SVgl_>cfnr2<-rEoq0_-Rx_`;KZJr?i5u4Jk=1bwU=&Z zPoF*Vw(*~Q@KBboP|m1jDut?V`JzG6vDB?o3Tm6kGnv-;3)Y09g)(h$5kXFNN>y(Y zgmfDh=H7>JbHR$-?yN3x=5#P9yvrVFT#W~STsPIfx~?PGK)N>~t%$MI-6v()JmQme=_Fa& zsutBXEWOarP-WH9hmO84Z$lM_ycQ_26%zLGmqZ+lEEuW+dBY3ni$Yge8aio9>tE2% zu2t_AENd&`V(61ZafH?=<;ca+GxPAKSQdcyc#y&OO+G2GJqS{4GeDp|g2m)*nAaZl zMs=?_fn;VC03=1t^%X8K+pS!`&`8Bf=$btn&L{Ss{(KwUb+hKKW3JSU#BauVfHfvM zPtFT$bTDLOYMb6+d%WAz>TG4Hr71liVtRr^F0AKWXjZM*2rPfz;*tm`O-=zlY66Y$ zEYx1#KfJhd<*yiF@nsq~olQr4v_DfY>o?6~VFZd(txG2lx5gQ)@SztMn%ROh|IK&r zB6r4_2!6bl0|MtU$id9B?4&PE1lvjYn%PW%xjaBSw4qDH(eO*u52kdJsXCjB&96kz zTpVV{vf}ljqS*>o>+VzUyvB<2gn|eYbrlRYSEfLJnEHc_c)PHQXQ7Uf07C#S~o-wJ*0Yg>fP}j6^D+7umgZQggpL#p&jI!D5Ka7-6%B zjo_qbEs_D2r{AhYQ=@9x-2kgo!efvJy0@0>sP=w%RZ%+Mx%%dcmAhL~sJ6*CrDye< zRPuK@l69sy;FhV(n4jMI zqP|+Xu1IZsM9_f-xmCpwP!>$Tf`kXeXXtIg=FvQZ#wj#{{AS7qFJ$q=@~qY&&$;Zs zfVI3a?=Vr3@>{Sl)(5LV0wC?>YB2%9h)w8(@7S5lh}-$h#*FakPo25qZ>xLDf|CcZ z8GN9_*fW>^L|)T*MwT6@LGqmh;tnk#3+3wFCZa_p*x~G@#@b*)d+_A&C#t0G{cbA+tNrzp@8}V`fZYv2^GCw(A9Er(pz^< z{7ngYECHM*M+&5T0|~kEq9VAxMu!|u(#vu~9Pu20n2#-!rDAh9!W1}JOZvhj_aJ82 zf!(aJ6!X-xzGq`cTidaoo{!wm?+%vk<+Kv~7IfJl?Dyih#g^Wl#sp%RmKXM!F)i0SRG#5cAGPTw8QNzFDY0-@wJC3J@7Hq|@sB=c8Uxc^Go`@zZ$xexWZ4qi7Kv}4U?ysKHE;8+ zCER$urR;CZSeQ2Dn|}qqjcMF9@@p<4)-s(ROq{0y)_AqE)nmZc>Dzh8^FuuiHInN& zLl+nHTa-=`krz=(4wE#!YI*#ypeKTlHgMc+n4TZbvVgtuq|W9sG^ztl&(+RZ-G-I+ zb2hZN<)h}Kv75{CNXcgPWEY~DoC-i+EYD%~B6Gn#=j;}_nF$ElqI=Zv|BOZi1P$K| z6Y_@X?7qx+f&mYY?%Wfm_Q!04BlA>}4y5xZhK#)ZVcBHW;!L5!r>Gt?4_4zDy!y4b ztOvV|UwiSH%bx*QhcU_@OxY4%z+KPJoWui6~-&5rRIO zz0QJLv=q8)Z^#?X5Jn&+wPl5fmg*Cp#FWobBUMgp=o$ca`Yf+nLJ{3f&K1qt{dcRAcMPN;u7cV=Ys=F;U#ou?|< zS61OuF>CaYvx$1RjHt#Nfq=@hcZIGJZF$2WIU8|p1GF&?}TLm+nA1D z#_^D;2QqPVzov8oRl;mjrm_4<0)OEOF8i;JRrTxEtEPRU4oD7bq(v&EB5qj%`4GF8 z+l2Nx1KGJO_aA@q!_YRFI{^TK&OK!OjqyC-K2E{1@wl%0!Pt>C*~e!J^Z4Q~9)zc9 zMZ;Hpxm@ut<6XDtE zo#W$7hi5}}`x^v#e)MVV^YxekSE-t%ht%dx0oOg`w|fhs9$eI4FBv!SIy$-`V@s03 z2fMJ1#V*gZ|0#2aJi(g}AI)1)3{TP+p>+{^Ad$HafjXIY2`Vl!jBTqu!0KE7kTx1C zoXZa}GQz^3Jp3o{5o@sjerm4#)$)H(#Z-CSJ7pymt6DAGXMVCj#>Y3dS`0d#fu)Fp z9snakjY-D?kQC{#CtwMv7<7CFmLeVW0(=P#gBmX&S+v7mfGeP3kn;s3MLOsWawT*O zdc1(OXa_w3Q$WE;&IeE_;-DvF3aA+Lcm<|K9rOZh0UeVb4`5Q%!CuH8&@ia+1}a4y z^aMN+Dw7y5AX3y}55N@AFo^L9Ocd3iSHMc>F$nPB1azPeiVG`@*r?^Gzz*~QQDKD{9W{;!=%9WmDy%W$qb}}w z^e<{oz$grBZ$%XZpX2D0N{P_|&=ZiUHkuY2zp8U?+>w7(X7P>GF0jVe4|c;)GzE}pvWO;TIwBGZ$djO9kBeN*G=z# zqbIKZ24u|-_G2PGq4%F3(330rAqoF3;Dw4bx&3gQUiyb--u&G>#cs_n%yIr6wl1*E zo2#Cztzb$5Z8|EBJGYD(Jde)~1n3=Wem#n(K@OD+Dwvx9MqElaKG{VOOAUbCpYmNSB3miIWDlw<1=gX$mSK$ z23QNQ-n-qy38154Xpi;Ig&_lk`xXsqNnhDZ8@O=sUVb;jPHLZlrSW|MAD7Ps#8mtS zqsKsUK%bc>c&`lR#>acn@8h*s#NCSfyg@g0t4z4KS2Y)xK8d*Mv*6zLyRY-!w(nj~ z*UD=AMsoMs33~Ut4hbiS_b6yl~HmZ87hrW1G`ONm9D;HO~w97fvoZ69${ zhhqh8Um}0=&Ihr!c=^I3?e1YYTMN=Ey3SM}8oTT4cV(!iIV>z01)ks1{%+{*=!Em` zE3D5A;qM~tAAWl=btjZF&)298!#Mnrdwun5DKLg-qtuRR8;?Edo@$++b2Jg2=^ z+J&gfSiGy+Rl!lJPsKj{_@i;nLHV@Cym)GVL6uUMWK;H3soF8>t*xh`3V;n*nlx#S zKUW3t|2lhF5_Ugp)s#0p;v~d=re@J~B&;LYyL)qkyZZ6<_NGXQu$l^A4-07^+Kv#j zQf=A<(>D1&<;b>~b%`q}61zI3ouZa-P?d5q<9c@~SW%Aj-(j^yU(^lSGA{o|y!?Bq zrtRu+!ZzwBO9g*ODgC=;#=^a>_x|iAO@2U~kE&z!!#{6b8 z!agYihWY1v2yqDZR8vrHcd0}TZI7a_8YO;-f9FNm`LCw8UGFwKM-dW_+wf%-(po__49W`aNIo>nG9CiDhF+tV88*6(-d z0`y&cbUzMl(Ir?W1Z%LGs&~{^S4NhDD!P>I&ZkwFF&N3G4oSO-j_rt^tlCQJJph2_StI z#JL6Pk{TT*k(RLN6eN&651NyOwRnT<=2P)Y=JDA!Fj)o!nyY>XK26{*>T$ z>f&`qy4s%Is-S{3-cKi1iIr|E*}cHFPDdr5g5j*k9+gVhBsm4@-pZf17EF9P(1KaH=+oV~$cpLiD*a!Ces^~Xf3@DW%9+GOoYH^5 zCFe8zkR|oC0|eQ&du!8L7(~h49^OC-o9gOeS$$S&4@;z~WHj zAiB8ZI$%#)c--zlNy9zlEoG*dI0Ci(c=Ajkis&YR@(M~NdPSGI`ucp~j;y2o(;KK4Rx-QRb_JZyNT zV;lNYs)1F@0d(il+OYfjJJubg4qF1**9TKuOPxy*RkB((C(T4ckjb;rPIk&M+R)bM z`AFt~zvG~@b}QFKZW(yM{_5 zE~<-mMe2(4iLJ782JhURGgcXM(kzo9Lq-glOeT}bkRc;Rj2K8)3E7ihpfMM+8R`;k zyT-V)3+`+rlG;hq@^sToH(=XJ40lz=eB#vb*Hg7l?csQfVG&feR@^OiUPnO+r0);e z_b&VvK&f}R!1C&bV2Ts5|2Ee5odz9ANA5T7I#30rY9FKT$=%FP73Ip-P>D(;K13$K z`c+2!D*|jW{WmZnU=7O`xN!6#%j9zD+(TONF1WD zi6{IC)}JSE{N6opXhrV0&yPQ6V-sy`|GqcHV=`hzI~G!v*X}k-tbY%J{54w7F`hy@ zKV+pYbK{B9wqmL$#TEMIVNg0PEJ+{=g+wFz7B)eFw+cjeu?NIn3^Pj*O)!3`JtPLz z-oEkUofHNa)1+HW!(3nz2Ic{_JFw;5KSLZ2a+yl|m$4aRKSTk)Z5X$Q z5#&SSak!fT6n>dzacW5Xca!<2PP3+gX!b+bx55{*S*70Hy*j5bw$qm?-DVu4K+~`7 zg=EPxM1RAh11qk@z0z_#y0y18Xm2J@Xl$nw)^MUTWIn2bkkC~Ww6<%Vsc8Fi9LPSY z>ilKf00@Ku1RB|w(hHE2t@CdU4{12o1w{Yy6J`s@1w5`3J%+`%X#Mf{lgH}YvJ2>~Q#O7?n}{~#b@x?9x_&Thq4a;tLIHgbO@d2eIeJc6JpT+ z&CZ6vqe%31S5{R3$65F)_rh0nsu;kG!QS>~O;d*N7D5Pkh+Aj~_v+5ISNDwz0S}SG zU7bKDX4{4uyDcRsvC1wRvKMevDLA*pbu5dR1UMeqo&A~Itkhi!g0GmEnp{}piNpKj zYHlDCuY3W559kCgAfYPE0ab!jfWn;e*$Lp^w`ALQn=?q;)`7H`dU{Q;#e)%f^* z-^U}~@^GP0I2@KTjVdCMSl2EJ9p84DeAop3pWivpR87#JYhnXxpn({}&;{WNG%%Jb zyXw-1x(-8@rTKb~qNu8xTtY+J%x!x%oAK85G$H7O!Te0M8q3~px20M;Ye#S@#@x(! zGZ#BI==<&>84B(R`rg zI@utv9ORu>{bZ$lG1k@$!oKpnzBg7WB3l+!DcxQbOsg&cI*Z>>jt%0X?|3EJnyxhc zl1hupB{5wbW-1t5U;&MZ%PEO2_cFCNwgy~T$8is9Ez9jZS z2F=Wg1k-)qS4k(a)_7X{P7DUi-uZd5jxT0&NpGWn0f)9&e?Kry6gHyg~h0GbciRJ9R4$=PC`t$MqRS9@x zKhj3$bpe}wONE&&*_c{t+s=Ijf=yX&B@n~OMz-~Wh^Y#Bqx5mAY|TowNN4E#xoTPi z$gPCqw;C0RV#;R&S+*Z+sWh8r==0pRlCc*8mzq@s(U^cXRIO}J! z54AM|O}uqSh=qQqhz^a;r_Bs$U3r#VsEoF=hrJHn5ov>M1Gh2Ul7)%UtDCN)Dd*T) zUP)}d4JgfLV$_IKRhgBRrrLht?itk^DegKmyi!)C%a+mCBI=q0U(Gq=lQqk8T75jf?^*j|6PDF@aQJ;u_fc^ zPaS*?Vn2> zT`j4Py*OaWdQueHi6X|fai8;kxM{q1JWMQ>bJ?xR11;0>Z8dR1MA#I4DT$L3B_23w0zy3HcY_tM2Nr~IXy{J=;R3CY zED^Gxfe1teq;Np`?lo+Kp%OyofUHLBj6I3v&ZAR!_RJ(k^92~p6HF0c+?j#<1_R5v zubFHF9Py-4X7Wp1cu5JW(&Ya?$2e8eGxy!ewZxkK_N;abt?r7T{SCZqe5^orkpDA5 zcZ@J%Nlctj$A@x3&1gx3tF8(?kwS$U0QR;J$0b_hrXmOgilCzl(D%IrA07Fk$Tukr zlVA+(tVTCs=T`#)i?kEs5FWd1Wx^}66Kl>KrvQM!V)~-!!E|9Pks|0HSfx6GEbQtF zANpbmhc`}Sb4f72Hu>!_zhaCsiz8>w+&C0(RQ|^@AAi&I>&P+AX52n{2?{}T^ep%s zjf-H~mUKu!Z?KOz!nS8ISOPH+4$#a&qo9Ene%&BEhwL+k*~PrT9Lf?y48%GNcu{g8 zmMsY1(#(k>t$K!6jCp4ZWDmI7}M;cp~>Mp#5$(JYjp&2OjB`eY;%&ZNVPRU9TUi2_2)!`RZ}i^dX!uC->W{Mu|_q*cAwBLFQ{BLzy}Ei|9QWh z!p9CZv!7XtH#DBiYBOvz1gttRW3z1u+*rjV@bp5LA}bprBCkk)pWWyC=Se#sPh&Ol8nDad5VDROdMnU5e5Fd!|^I+_Xd35^tIDD=0da-isbu`p^!!oCa5Gj6>PdS-le; zmd=KujszP@^NPM@uIvB9n&&MiQIN^)M}N0}*aj$~c|?HD9X~fz!T{ zstSY&u_7vx*NzIH9g!X2F?T94yATi92S#YobFM(q!;XtT2G0kBQ)drSXQ!6Cr4NrY zHOIi(QpA@kCGjBa&#<=4@L~y}mUXc3G;r&?x`J3!2xB`#FW`V}29^3HQ=RJL?}Dp1ok0yR}}YTHKOjZ{DM-GuFzqp*|X+q1r|eBKq^3G~(KO|*D5MaO(y zE+D!`^eBry9RBDg0<%_c5rV!RU9?yKe&K@dW0mg6eKZdCl3C@KlHhy1Kp+S>5;Uk% zPf^Ww`RJFUNZVwp%roqTi3?&~ZdTR69GeN%8$NpLyY{vi z(!xrM7zoV4=E2r}9cwL}e&4LkN`t09`ILi$E0t9l>`?!N%G1f`=jxusQ3y)vm1nF=MVW=K8K`!~#FndIwww zWKOPUD#G+4W<(L+BxHN3+K3L+;el~%3Jj{^3yg0XO0A7~HY`py@O%XI2%`AvprdwD zY?RmOl2-zNO1(QPWN*{*_~0hPtZjEu?ct_K?XX2P7i--V1L}BnM9mb}f0E{NCG+Abz<<#F3{$gt)vc*LN1KgSR*Feut) zv_+w05iuyU(z0!FgeUH|774d3THImcPA-19<{Nk{$Uwib0S~$YVoDu6kRmj1;g~TS z$QZ$k&&FPSStlQCnU5c^K*vRZaSt*br_l_ttmul@3?jl>8Tt!=*yoT)RZ2&u_#%-e zuIG*o9I)o4mgOcoa zTU%zJe?I-XhUW`arp*q8z1*BbLIcml5P%~AKwP%KS-apU6B^}?vAKrDPg@KZ{m6nF zN(EAw0f9|nVf3jMxo@`Mm#6SCb~Z9*l1p81vpvO^)e(oiU~qoGNwQdb^|X=-=^rn6 zmH{Yz-bboW{0lzdEW*qnhC_m&v6jS>ozt2rUk6Xa)5a$l7R^Dt_=5c8uoeQ=@9&(? z!ce@;MjYr&Tn(}^dAHJ6_H}-_G8Ay=7*pU>GRs`-8zZPW;s1!^5oLfkklk~*EoygE z^i>x$6KgH?_EUB&xgXv64d>J*;BI%benGp5_n#5ICVbzVIc;ns#vd|&?Ewxq4fLkQvxKK1H5nzB;hN~Eu7 z$>L{fl}u*Smz0+>2Ga0Mw{2{vA8p%aKrbt0fNf0LF)=l}>h^p8^;p9r*on#+smbOs zVn;=fl}*eYzPuLJm5tTr2mG>axF7bza+A+%;%c%sCJq5P_a>Lc4cp5wWVwJDlp$!J zTVg>703k%es!OU^TV~hxA+ypJKU784c4h`>HOjdXWrJ-J_&H(ax2}7cJML8$_$rAj zwOV_m^=v!j$0fs~-)>s!@u6Oe#yiu+-ncZ$r7v3=qb?S_YEjr2;l6BJI5||fH&k|H zCN?I{2Pk1wxH?fLvdGt$qx_fHp+%|w=qt_@@gmB>_>yrG7-5^s5Pr(mPWrm~l&9CQK_oc`dTf${R=_BWG%r3YqO#ImOvMx;UO~vRDXSje zD<=8=7-6h+6;bj~<&IDXe)y$B_V{p=a7>EXJ~$_&wLLx*N=D4+c7Ev%S!woRl9A{a z=tsR@T4W>(9#Kz3&G6Gu5J@bK5tpWS0}}Ep0}@qE`Iw>}V4{6;1dlug2|@seN$#ja zT4O&E=0-*?>GI2EgbVvIBYbLaCeRyV&dF3oFKTJQll?T=B z`YNJ~lz2F2Z+fOFixSM8u!ZYUnz61@$tNUAiD*d5H!}xNbBXOU;oF{!PM2noA-nC+Cb>7MJugFA{PKM}gOw zL&gd9j)sD-i}?)#1z9HPG%UXXFIGd&!Q zHp4(9XB@MD#aCy?3tf?15{kkmi7tz43Um%$Mjsx0 z?|XVRYRw`0a&g4E1>~gwcz$MLL8lsIl+LN8yS0j@gYQjyN=3b05vA9uh!MX#hxG^} zGru}fJoNaIx~$Yrx+%?to|@l#bHKkTyv$eYT}#L>-o;#pMXX?Q56n2BDK?NkoDOKl zsZx-3#rLa+N(sVc13nxpo9r4Ue)Xa zl1qBzTpRh-f_uTCV0^fwsIMQ+jf(Sw*Exxe{i~!`Dg}v&eA!$KqS_eYx@4S?;vRX- zm^S)QZnSA9#9o|_Zrft&3H>b6hj@9~3G8XUCDML7}PSjuk6e`qFzPvz(L6|xYCLc2C z9s>;&e$21clCMGtI#mjONq!Q*Dy5P8ay(PA%$LKs)$Mp~OvhW|uwLMN|M~!C%n3Re zUcEZzehWWWcfgXDQQ4qg1JJMN7&5^?Ra!zw7As-T+FdXeKiWRr@Bz<%aIbv$0gnqT zGEG3pkQuHos^CC!PEHPoKM+PT^SFi&sOIb@T1#3RfkrE-8OOk%m3k7)D?^ygew(^( z|Eza>gx2uA+u16QCoH3y3xV_Vo{rcs+>z!X*~5V!(7uOK9z7Z78Z5)y5qZ4+%F zU+Po+XaZNy7>UyX$|!CJ0%bVg|7QH(HGB0|u?)l@)|TN>`03mQ5>Kx*aCRi<$5{$r z4J!tY9~_S_euOYwz+r2ll4#HP`4AEURtc9s8}4e(RZw+Bbl0rytervdMYK&E+J^At z$F&BQYoT?vzOyben2N9ZqPhjd7_CPz==eFMntmkG=q<9V{efU71AW$OJqUeC$pBr@ z2^q%;tS%EKW`rjj+M=64__FzoB}0QH#sHvL(4xW*QfVp8q5}n`9jLU;6AR2~-aSYW!7{f4%5X}I95GX}O#Q+fj z>&RcR$yV+hEHGOB@eM`tLF4Ee_)0teA2X*apXy9gZype^vk5*#z)6PX2e=( zbiPzno%l^8p?<3}J3MmXy6k2&sTlwprVC=wY^Aapjd_`76{kd}x zy9UpLrPZ69Tr(ZD86!p~UyOJ&!Om;Dp=) zBQ2;%VU1jSo#FBSH;X@3hPqnqHDiFk^gHGnrn}OslWUupo}#h_wW2JxY3HZrVN6q! zuod>*?}sguEa0+5Vbq4;RFhfZcYKn#M~Xa4Uacko7pi(B{qnf6V{~QHIBK zfz0XrfTF|-(c}!^G-voR;(o_*+Ns#Ay{M4ATep!?Cz0%v3ZWR~gm>yamQH(}dg{z# zeg7G=^{vTeC(8m?#$6eerqFeDAUGwSc)59&C@sJVXgu+AZU%r`1L-~2s_=Av!T#j%#mV6+w4P)#hg@g5j0@H9e8 ztow=Hp&vPuryE1qRe%be4MmXhf6(UvVq~$^)Le<9GQXeOfT6h*h8Bo?zSxI}nF<$G zv7(=_hY&Rg`fC)k_nJunV!ryDveto$qwGDE;e zYzwF{OP%`T#&|Xk-fAVoz_a*{N_qv<(n43p0!o|PTYmfdE>N#0az7lsUi}by#9KEU zX_WIUJ-RIJXuX>$TEpKR!EAP^==z!ydJUIc`4*rMNVCxlHpI|p34dTyr2X`pmdL>Z zAn$^ufu0yXJeaY*$anoE@TaH6>VLhkUNzY*HE$lOFBp&9_v)t8g~OEuos|iMWO}TA zbF4`t06%8ZKfoM;n;XMzF2W!2Wb|evVDa~@UEJ&kqbjMqURUh%zVBRL*R=)L0vE-V z%lxEkbk48mT4ij9yC9IW@q!V^i$K%leP>$3f!UP00x#nbdJ{zNT9#O9%b`q@TJUH| zu{Ueh_n^QxaJ$L!;jhNF~Y^oTJAFU`4jkLLf=*fbp~8 zcyaS|l^;WNPt+4(2?%CCow5nM0?QG(lSOSSJK~6Tq{ryZJCJmgenhh{b`L`W$QCgV z7AuZ8Ob@u@q1&+{lf&;8n{cr6A9k$XsOI1D%iS4M0|u&<;xid1$*z?-#6Ne$7UeVvGJ1FOn&v8Q-OLcVEK(3xDniq>ssi7IHXyMiIG+v=3u7v~Gbq`8_^gFU z#SpWKTB1)Lp1g>j^CfY5G2fDD&ZF(Z*R^xTS{>@-M>UmJmu9chl3QDVA5YzvH+x!&#ZbCKUn{(EG zXc1h8`xF>FVnm&O?PIU_58_fkX*?{xAD5avsbl#Gth#pfbJV^Srt9H7n6m?KMbn99 zh7(lF8>|SI)9O8@DQ&Ljj~06RenSB~Ib2)%yGxxxy`;xZ%_i75br~KpUA|Fpzwb=O z8K1{LrNvB}DTMOaAu?Sb>GDt^eLSvy=PDU&ps77?YT&)DnGX7DA}Ce!8irW4F%*#< zVLpS(Yh!agGYqf$ z;|R;Ss|j;75ooJk(!c_q#m6kYX!uR`BgDYzj5wUWm`+sBUXD4k*qTlCq zW8gJ86BIufdgCrVB&-)Y4J;<)HO%1KY+rYcFR*0IwRAGEW5`*5^}E&`5bd^{8a_4J zHC1PqylMfdv6Av8M z5!m!fTd|FNK7QWRBr@18V6c-aCxu%7JV)o3OgK`ws%E;Hn!bLjd5)HE%Ohm^_JuRt zRtL9D>egmXtc5Ghjb2(!Mk5dhv(l;I8e8(9=Hb7B%lyv~`s`edl??n?CaSL&&x|gY zX{Wv*t@a86oD$F68|f|rK-zP}@ZMn(tDZ8Mg_@TR6?#|*tG*o_9Qs{eFVx|9k}6Qb z+UX$nGikf}?0)_m>!?fGm``?Buur?uLp3&2v}pHmWb+ikLRqN7oPqZH9vtcp2Ngx* z0cO>y?)mfPmAW4zbEsnrH*VQCSW><016jb$bv*^?<2* zC-&2=`JP$Oym;SmdtW+Qofn*t9LUsd*v4Lud@kNr_&o|0Nyr0+<*u#ofL0~?(7gcb z&)29;Be=@Q$QV@&eT?dY`QtB&*1RXYMwd6vv8#U(E4$q75okEHp*`|%o zz`eg47U>A?PTdH54^InnwkrT(iF-G}jI7(2g~z>JaofIot&d+7*RkL|5isLZdZ!Fs z-c7lwe4Bg84L_Er9w9v*?Q0eBRuq%fX|iWO8PMUewxdnv}B>(Njr)nj<-A>3a}0On_IkQPgp%fiV&MAEh=5Y8xd( zMvu@G8frD?*l|!nL0x7~4sR6n4dqzEJ1SMDTh~r&IwsM!k2OrP2Ya@P zU>dn(9^x4f&v)<`B?1P|<&TMtE3bVapgd}=XF}Qh^zz*Xjy$RJ1k$s~qG&J8FNZOp zbNSCfVN|i=-N9jy57MQOs0Dkc^#UG_RDE}n2rG$`JOz$m!SwefFN84MB(&5sBWAD+ zYH8$FbD)8BgspC(f&ds%&&LkuhhP;}>Uo~0a!5fhdq2P;r^S*K41>WCq5HC29_#cv ztQAQtycqh=SZtDccBnXE+&^%{_hmWb=n7I(|9JY-y$-C=hP^Hl^Eyur%qW4B{|3O0 zZxq|Y`fv$VX3|f2H)!JVT3?n(rQm0UC86Ep;QzW6 z*8WsDxXXnYyz!rcvE(Cf=nn1-!sH!Nzwk9_u0Js5Q>lwy-3pTYZqNqTP&NKiCwU`r zNC+7C&qr($EW)&6GC!IOn++ewnqVV)E6g_B6_g~^mz}A!=>d!cB{A8E3M@J2Bm-eL zJ&iP29G%$27(O41cd6ObdfsvzuIDNm0gF=lt*RA&dw}!A0!Y*jPdV|BPzkBfi3xrN zuicFF;?_|`EB`m8p9x!`rQ%va>^Wp46vBvQN(5d2ZgUW|A8=hgl!ux?H1lZLV_NF- zQj~x1X`A1C39rl`3RHd4&`@|5qK?h*ZRnjea+NU?1dhO&I;|LVPU@?q@6%rGQA|>- zRy${d`ujnVG7LZ(C)@JB4Kmu^dypc7dOS3j_427QTT4G+b|k}VEU-5^#`p5r$+4NN zWXs6)P3akX5#Vn%fTNDpkHgAa8p%O2U9%+$`qOuS(M^5#XTLGzTR&6<`w&Pyk-(H3B((inW^=&!%54NC zk8kQeK7r~H8+3m9*uZok%+X-oo*tVncWS#I-aHiZNd7b>al#gvf!tv76Oxd0CoEFu zS4I&U=6DA7$r5mY;72$r+iF-xqfU$4gX}d4tc@x>%U|W=(1qy70IoPl`^uh;;v-gB zDsTfv($^x3lB-l>SFpG8`-F_wW*RpIsAdv&Y6`2TOpPmNkT*d2fO0Op?rC&Nl(_Gl zt&l1NS~V}ud?FUe1`!kaHHY_cqY8~>G)ab~5D~&?22sFpJN3MyKtGiiSX>wTyI9j% zgBGk5xu7h2m?Dw)AH+ud@K7gYN(M7=o3GD}l263jX|PrU$YEKBbBq{#Pq+yn*PLYQ zKMf}l@$el=Fcob;;5*>Eg=~Nq(fPh_%`3FS*ArS_@(xr|;AtJgOwI46y%!%IJO`JE zQvzC|K`m9_0kauKG0kQk*byESo4E<@VtaJ->{kM}xGGoofI_6NS z$Y+}vOq@INpauHj{<$Gf2%DG!SLP#<@tmRjeDaJSj7}o&{(r3{n_#od)HV1b#u_zl zXiT&!57f}$hMxGCy3?K3L{16+un9Bs8wiN`&CtEZjKR5c8kRZjQAtgtGqSL@gzJ5*FdOAsMD|VF4C8TXWg92m>V8c( zlUfA@$eojr7B(ph28kKd`n}rT5R@IvF{^x`kpqmI7+94|KM_fb`8-WwBxDR60IQ{V zs@mDZH-Q;d%1SiX>u|!hcG@DfNQU-2fth=vXq}>TCU~no2LvjZFb># zD^*v!zVwklC6N3 zW`}2{9TFmrc97;oXL6c#T%gNa128W6o=*8K6<1Ur>W-ccQ!qN)jsZ$TD-+Raty0Y~ zr>5iOyK}H*7N%kp78GzA1d2|h)bTl}-HH`wOr=_xtK@ErIc$05uKjuNt)x?%VYhyc ziU4%D-(IG>R1&o=HwFs5a#%V|geN6t0Ta&rtM~&7ivje?o^rl0qRSZTZ4*rN6YL8v z_Gtq!C;``*NaGh=-1zQ5L)Hqq0Z|wtAxIMPCDP`ZQm$QvJ;x;=)04sv+r}0KoFb+} z`r(!rxgeg+WLAouQ=$1OZBn|olfb;h#sboeXz^Id2ybIy?QZx=z~Xu`K?)6#3qSWf zZM$v7W!;J!<%Sy!{@cRzxXsPPJhv%eMXM(8zVsx%ol+L>8aMYP6P1_Znqx3(L)K!P zp4pvM1Ql${99n!dxc;tIWhg%Q6Ev5{ej{;&HLooZPYc4~)R{}&bA7pl(P1Yp2SuxN z{l8k8V)_j8H@|Lp-kuZTcMq=&l4_)~*2Wd^{uJmkU^ro=Fgso|W8zH+UgUtO5-j|pd}lUcG?xHT zKzpaO#a#yfYh`q6Klbd}SoH+==0)TqUo$`-p<6J+}a?8qG8)cEm=6>o+sJN99nhY_$^)p@dC=N~?y<(ZKC*$N&B3)9Gl|ny^gPq76edslHa31D#Y*9(Xrz*q zGN`38h)OJN3`>P!RT6=QyDA4>I^@RbQw}UrV~Zr7sF>_)x8phNt?zE-w3y&ro<*Aa zhCxkhR5AawC3n0_GbTzcM$26}#sQf&fTuP3uqnK(0Oky=*MIUhNHkjL7AfH-X;dbh z_FBN!4f30skuQ?W@EfY#!;V|m;WUnK)xWDV@j;dv*AB;0#$O#?dCnbVXY&EjXrVEz|MVL`$xZOW5J9(9iv5RG0?>qG4T`j|34t!fJU zm4_^762gP;Tdul#T?Omkt{jfEyRXNG<%Uy@UYV-{(rj5d5z#TN{)hDp45T1w5E zztYdU%1FdfA0k)@HlUV1dgC8y#jfDJ%}r<+2nz?EN>bqt^?fl}$W*)+fV_wurldS3 zBV#;3Dl6g+C0A#039CWi-v3XVMs80GnD-MQ<5YTXfSK1ji^ixvP-qBQ5Z6C`fr9Kh zY%_u2$e?U(S4IEby(Uv~5{#y8n2)ahmf*0a5MCvBWSk$b*isLSlPFv#gwVX#V&^s1 zOO56aL@&0)y=$d}aQf^+8Ciq&?OMPxvqL-iv`L;0E81psJ*&g6MZxUn?jiNU~o&=SC6iWXFi3s`rQa(_=MU zp-{_%hL35mOzXL-Vg<3HvSX6;pywRI@Cyw z&5-b6m-kp!cPDod2yp>_yDI`yC-mJRv&IXjmb+k1(P6tlf24~Lg%cCTV37n+p33la zb^(`$gDjCg`H0T907F2$zdEF4Glq%PS3m%i(p1k84pH4`zsAUY)F?FhAMZt4z11Lt zIhgsjY)MwJo&qf_jLM($3V}J8Zxfh?s)~WW?JCLtVWiD_D4RkucB#~&4a;O zH00gy*|YiuqT90nnGw)1+eyG8G(3&v4rz&moW&PQDWY+x`t#%}r+tcP&dXroL6b76 zJ1$cOHpG>`kp3$SU&y~f7x+DyK8r^71M+KT-uz4Finhmo#%|~2@3f9AC0@W%TxS3> z&A*H$Z~w8ygiiU=DqbE^MuHZGpjsJEY9+G7w|d7K=vf-BK7#3D&NJSzsa21<6$&6V zIZ51dQL;_YpoJXx_Xm&OHIFieNM?^7%Z;)^zoHs>^>lkxX^E}Sr z(Amn2Eu+mmm=Eu6%U9X_pNsJJyCbuVB^vAiq2g4#|AKdxo=k(kfFN$bXo~^PvS;c$ z{+o7VEXDL&_5~h$gNHH1z&;LW#%zE{X7nGTNM9{o0rp7UVK!UY1TD|-tGnTN7S$iC zm`>CBlTrHZ$_W&J85;?roL+F(g!ZTdJO*+uzcU9qtP9EJks(K?u~fBP%nz2k@)?on z4xi0(QEn@&3hy)k;@-!2#s`et8li7Kr~LIgP&}1tB<8^Be7iS0@e9aMVf@;JD}JbZ zWIKn^#p$8=I+d9#x@Hjs8u?<(d}Z}>I}F}z*N_jmjL1V6ZI93E*5Cs=KNLlC*7lyc z&W27DenF<{;=`Dmt47$>>7wXMgZG#{Mu#Pm7<{`@dQ1F(a7*Y?5V+jOL>*lTqaonn zcNGJhlTNhPo*@+b$y#X^xm25}UUvID?4crp9|fau&0&EODBX?bYmf0 zwgZUWX(-wy7agxHtjIu!iBVqAHOS+mz&)d&vk{jWLKZu1uL2W24e5c6;(wDvEXGkj zi#`EJG&sdLepNLr@s~{=aCtL8 zzIcwBk{!4qP8J_d3djgH6m5Ci$(Hmr%x4reJnIDj0wITt54H@=QbhuARf$*?L8!Uk zf(>&=`5_vc9KID@9l~)2c5#yu}WsJr8l~{-ZXmhK{@fR~yNwR@HMMeI^ z5{b8^449ah{yEgu&lUJfd+iuBBE%3XP#7^{P!4sl2_CVSL!Tmp1!%7V~Tjv)gF(B2#zamhPAz$p+-enGsZaR;v`wU{=D?u3Zd5^`fvEwXVVx>; zl$RWxzI?|il}1f>Wni^im*v6oPLUUR_$HITMH2~E(8}`ZNc$LA=yF1h4>3K1)R?hp zjjWy)1b)*PaV18k0|p@WAm2&3)wrI z4(3&DJ7cGf0wp%FFh{SpaVe{KypuyAZ@Fk{M!Ww-!~v6s=dSBxx}t(= zFLnT{eQ~M*w0P)`r7Wp`Y=7HEz_(caSBW3g)CgEvfwSwV!SL7H>xcDeF(Wpn3>VXf zkF#v0)<45;)(5OXX6@7V{F8mwRoG`gMsAN23jkow0kv~mm!uB>7@>*CpnqRUmC-mF za9%137NE?MsSFj}o7zMy>38nb|tpEqUWu z8nZ9LP*!2|Yzs&%pw71OY>}Gdztj6fReAbNEWM~%LyjGYA9<7UO8CbGu^!+&J50zu zMD^OF7P%S`>P+aQ0AJFpJtsn^K0L0ZLc6D88!Ukzm7ygF=EyuvH-elMrjRuSH!qMvNZ9M4LhfM;o<+5&tOwnC114)KxF^ zbK5EyV-*Qpc6vcC+@+~Z?)8!(c_I2RqD?#eP4EfKNoqs;i}6F|`iYaJje?h@wKxc7R9jxfZnyuB>Z#$`Dk zNOT>wnt6A~6o$T34Yi+&lon;JU!_7zIg5-rMqM3tF?T9Fc+}!E=HC z2+V|D4+!EfhROgUEpg|TfQVCTm#}mipNJ8^sq7CfG0!sX1&XI~5HM7yMRrvjMI+^( ziI1GA2N!WPHiCt0QbqY`ARPi~&6j{B6rU1tG7pF1v^O9+0Ey!vi3FMO13qj+qGJ*f z8qLEhiuo-R?vJxsxu?ksOFdrVSey76K&8Mol3yt9fq!?bCeQ7WI@m3-8-V*LM-cG( z4vh<<;;r}^!FM1eR2q4??O$->L~5Cwxe638 zByj}pvXv;8fhR!o8U^A8&^dZhKdy4VNlvPP@+Ii8u$ncb~L+S z{dYw2!0H}-Zhn(zmg_78h$fAnC(Tcqe%XGDWdUI9@VbGum-Ny^~b z8szB0m@mp_Qou%!FBu3z4LqYV9sjEGiI=wMN$l1hWACRWlGijBARONN2h?6`=YThFsP~9(Z1=J%?8I_^w9+*K{pG4cxAGfNk)%CpQbu{!@rHf~BxXEH@e+EEXd)u}0)3r(U13D(nX zvYtNa63Xcy<7kS)Os1b@aKq+s)~~Yvs>?iXU;H|@^#l}uC@c{eq-8)B(NX#J+MEh2 zz4EMsb9p1{g!IQOJpPwwYFtutu;W^Vh3bwhPX2#;NGz&uBFB^)7^=vv`7sl^R+}|KbSim_?BbvC}LJB1eI4nb6d*cQ*bA z19;S{Cmy#X@J={Gwi(y{0h}My4k0MNhgq0Zd53j@{|-emiZOlJt~uy<8wP?SZMXq4 zk1ldQ3hXA60#9kIa`;A`icp(nNs-UA60I~`Q2B+{{L!8nidrQX%aJ9`Nyy{p{W;Oz*dXN1{FvW)m_}?8-q}Z> z7|WUu_b8n*lX>5yPr$zxXnHfnak2Uy$i0q`{20Gz4(G6a9Ve`8U@|CnQTWr$=B(+d z`VqLJz@BZ@P#cx+eZ-@-_vtO>Q#R*h63(z2K5~i_t!lICNbCPv?E8(t1hge^Nx?U7JfccTWf@w!)=@%p8gQ2;s}al&ZFicncM~kI0%Kh z6C_bac$Jr_?aexO#ne{&G<9p(yGVI!hbO{f3W9C!r%3Z!jQfZ24l*Ox;i4i-=__J4 z1#a5WAH}c(BPH5p1{y$eWUGh;5AS%u$c=(-#>2f;Ak-|`KMW=tig|^SXxA`STaN5@ ztyvh&ICk_0V(dg~3;`#dYrOFV^XO5r4>;cf?BpM7f!ehM>{!d+RH+!{l!+L8JbD%I7+JVU1K@AY~?jyT=8o5cXh@fcmPQiV{Hz(N5Htl_6Q5%2v&kB8qhyyOX=Efu?bM>)9IM+vM>^;$rBKqI1qKh|b@IiB7~2vS=o zypRtS*hkOH82q0t9mc8%r(jlx)PJ#r157Bpe|en@6HN&45075g5&LLA0oKY zaGmo^8qE4ldhu=bLaa`oh{5G@GgcJ_{Y^p68hh@Mg^P`ZLwFJ#LV=~y{A?_Vh!6{YD2p!l+$u*P0ITajAzLxu$=tculT)`$5j_5w0ALqTo z1ppTWwXWRSx5=u7RS^q=xczu5X5FV{Qb(T@MzN16|F&!VH6{tdH}>iuNeLYs@hQ4~_V+ z*lcb@^cF5hLyu{oUf`3@l8iYts-=k{5MfPNJ&iZ!YRyK-rb+Q`1!@1NjE0o*7u=#E zT)jV*H0R;r2I6K5N>?m^n$U)KjR8LjUt7JK01aj6O`4W0$BpZ0$BIjeQV^SjKEb$$ zFk&!bRXZ}$dkW6hP>JLopkz+~SibWoF{vfcHT~wdc{f|TbLd{&*zo}u55(H1nZ)F( z-`UPV^SCtXQ>o=JHam1^+5r~^acr=!cv zp?{!;Y<&ZoCTc~ZemY#L?aE9DE@rhq^H2*-$exm{I5ZkWR(u zz`l7G=VI6W`sEB87)8s9H+&L?^!F@P0)q<)9Cm;aCrI_PNgYXKEyk*SgZ#DaVJ`6SyPU)mq?kmAszv4#fvNt(^ z!U|vRaw2+)#?*?~DI#6i`&MkT-!v?5SQ|Y0(aVbnT!8Eez(K8mphO$&=~2Z{_rvo+ zbOV_=*y_BHzlOk&@+f}mL`Yor>d`K5Hq**W@DH5WLKhGikw=mS+DzhYgH12K$DjlyIt2Dg>Z^&$Df1i*Hx zRnbcs$lUL~G1XX2sY!f6@CS@Y+~qxc>x;37=kyy$i9LY|RXsgOgNH@2Cg7+7hfFI9e#-ynmGAfnz(BN2dkZj~Ak z$R|)>E2lgzNH%nEz)(0D=8Wh1Mq$cf0y;&~0~p}q5kiW3u%7`cWJ4s7Sx~75u!yh|Q3!*rBxp=T3)(%y+F^ zOmZiM;_j)O4)M;(Ccj_3{tyE}TjDhhl2HgjH=u>kj7V&|A6I>wSjG=7`x^-H_|xlEcNSSJQv!11cH!6?k}fG>`?S0+E7Q_GMLd z+ctK@1OGlTp?j9QPlnG=soUTW*RiS4^!Ya{=8WGRYhyU(*u%whKRrZSvmPeF(VA~m`rI1hn*PUU*4;?<$xBmI6l?N<;TdZmI=Tbn zWMRdITO3{P@^gN*S4ee&=7IK=L;h5;J*js$N4$n#NBlhDlhWDz z;+jsc3$J(jDbvF+^#xphMIHE7uvoLU~%SXZY)uo zfCB{XS-=%F04ZaW$3zRG&R}sVKw4KR1 zN_GlR!S2^Votp;mFc*s4-|UIAjwtxjc=;zcDeI-S@&N$N(no9x3=B}cvQNW`dl`)&?$s2ln+#>sf#uCdjY9*t?i9!hbDQQtQQ|@&HX|(i^@W2NU;XaL-dG`99 zyC5Z-D5{dYJkn0qtt`#BeyNj|W(!zgt~tI`O186_Bx4qs%NYU5X42yC_Pf3YUq19% zjHCkBnZVUy7fN{Qs9%brJcj@``sH$o|2;_3DDHv32Omutsk&DFq9q%qv1rKXN_O}6 zY=q-cLmMDNoHgymRBxW?-Lb|@Jy_}S97V2rDk=8Gm>rh*{N0e8ZDmXMjT0l8Cv9Y8L7gwo*p8!ll`g&~4q-e9PCmmSxWs^M$XxqmX@ zPY||5frIauE4EX0U?SxM^bgz?jj3oP5Us=~=~C&(oPZqEL<~w*)Qf+4+ z+k<2#&0E-oABkv_*iSbeH>RdRku)Rh$gnM!1;ktV#AR-pCT7~i#uIMVFE1iKnPONP z0S#y4EO#O&Iwp{ruY{7W$Rc0v-{`#aqS)YFQU*7z`ebQN;#ly&;70|sH1l`;9#!cz zX4nCCbMyxc6!on$C@te>0n#(~{5nac*^aN=1A^e_pXE3! zlsJvcv15BqKafC6EbD{Li`m!UW7b(9sEK19isjY!Ydo}7IG_$Gxb`AVYel)GAHtzN z<&<6v44@*~vtwZ766Lv$Y9~9YKFAg;`6weKTm^=2Ci;%?b)vt2;$e~;-3LUQJZaki zwh_C85zhG$;5(Y!!0XK1yifx^23<qw(^Zte7kl1KUb-(#Ay2FBsrvQU7mKPr51^9PCve*!4OBIY+Ue&EC zV^GB#hu?sGaKp35(e&eFd-4DID*QWjc{8&c;Mg~YX`=R?62pkrn9Xr6m~wWD^JL#; zxF6(W*6Jm)+t>t>!LcBN|0s#oW=i(PF$o5xK3n%BmRUSxn?3Kf*9u#@8{vev@FO4} zDi7)at>3aP@eg`@Ga3hnQxJ=@>S)c)2jr8;=93qxyt8?7sb~>4=!1;B8?*dG>0k(3 z>V)Ds)VAs{dX+hQ499QfkYjLW$RPQe;R&uXGO&J4WdhVVQJ1qqMB?;w@lTk)SoRo9 z1fxjDSn42<*d4l=*ob~XfWq&v`90kl7?~}R(;|eapk93H*%)Sue2_S=$T(SKi9dLe z=pg03Y$(}&+?cMR`-qTdzjliLWnV~P+MOig{#ku>0k$eE28;rvnFQOqwws@GDH7w> zJbo@-c#NaP%zCukL-38R-vmC+F@eEb$m~n@=BNw2@jy4uu(M{rd4+xF#l$yq94-1s z)a1hicA9=6j%?1{u*hvlVFhRsfbh#Hf%e`>cbdatPcPi6V*M25g1=>L<$m8hz&0S| zkT6zBPD->|fqm%N3@PmR-li&~1{^pbfJjk|oo-Biae3S73xf-!T8jf)`GF=Ug=1izTT~A@C?L_H~Jo`C^8!ME_+!{@S zd2h5{;3|u(^V;CA)hYaBXc&usd}ZWm)c~acrs&kMjFPmJWV`tR{52!$u|JiV+6p+XI@xymQ1IDjcy7oEt_Rrmqazu#Dz!S8zlHtI;Id+IxYTAucj$;1 z9gPd3@Ivu?Jg@2R;{ohU=Gk2=#{H7oA#%;8wIY2OErq4DO{}X~?09%lxrz_89m5<; zaz!uQj7tt4Pd5&|M3?vLz984a8VzT#F2w;;udXy=+ zhfORS&;<-|vV>ml*FG{2ov1?SA=3}YY6d}j+4s2H{Ai^PJzK|p#GE(iaHI-m&w}KZ zNZonc#h#w0kE~Ra_?3U^6a)O<(fqK`hg)e#M+o|F!0qlnn*OeqETt8R~K0g~% zazvv29g0PYArhw?gI2J#$c|mrzFJJHH+Jx1kUc|e%@hJ;B;s8KXE6&~=5T4-!}@5!eIItqhVp_kk%E0dqF~1`KlH6T2QSE;Miz7%VKb=Y&;>SlnrDFKG6kM(ZwQlGemWA> zyDAA78K};VH1DZCP!#agp)f<)I*uC-My@Hd)s^E`T*`NYEo;a|G(r@{Asxgd&39dw zq)sUrtfG_*nQ~q4pr{MA`R1&+*XuDz^gs&PQp!1O2ubOC$p6vcS?IY?N++W)I(^2e z^44UdY#<40yBWiAHUte_3_NP?o{KwZvZ5e@6X)ifm3&00T++z-zghw8)eCln}#oN z&+LtAODae~SOQ8p>f-%=2BL-OYeU;9;$lmGCkx}L(~VeOKA;@S8sI*0!KBIei}(k= za;bPnzJ3l5jzE{Tlji(0-2yH$Cz~{#-ax44%g@#|D=2UnxXY%JpLIkI32Zm3>|el6 z2x?}X6EpdL0(R$A;J}c#vS#e8k3Y?^aNM5v^XN*DK5KT*uN{YrN&Cy^&MyXoBYK?r zb-jiYK!VLY*do_W?`coy`83HXw_NyP_bt>IOw8Z>Kl`HN(cIS2v->e>OHLK-(OY`n zD?gtUH5mYRy~S(&LnZ8gN6e#TLz!(8&R63h$p3t%=@`!JJKvzQK+WCY1P>*q^WIfH z91L6Uhr~iCzrol088-X~8vXL0QDtKoIr+@td zw+>&d)$kzLeim*W5TLIyay4QM)t8D)F4Y{cL9qwJ|m)z?S;4U34(WrjGX`n=BHe!-R`}7?Kcq8lm?C zg*fI1oZ>WvA7&q1SK;zXe6F3rq00{yn9Nk|gO~8%;lb;FnNK_1<+Ev$4kpbGPJIWN~VsOagJBCHtngVZlQm9jPP9Wzry-TqI zXEs{1cVwREiyMaQ+nP)kI&m6HtLUuZ%`#xG%~c|Lo$L8BGuknRI3z$NJ%Kv z&Z&|8+9c3NuFSEEs~ck-+hAdwzxchI3%XTj08Bik|Ns7*yu_9-#uQA)Sy@0`i{ud>? zkd!{Hbm)PgvBC0wSC%{z6z=jkSZ3&T*L4SfL!s*MY6Ln_%&Uc#A=>#O;vx zj$xvayG6SZA4D=vBVItQw;B`Xxao}mcjc^6OpHSSwh>T`gT;Ob z5O*da^W%o&;QoOD1B?>1F)&91Iq}njQGedxZwk4r;APMe!xAyHPg{@z<6zCXHPqBLHM!M^ z?NBweF~_MrSd5&3;&OB1FMevfK+NmW^>yJbzdgx3-L60LM*eAbUF8+U?qIarkkbzD z&>f*q5i0JT);%bg*;fAu);mjL9qsR_`#V`Oi4V*z!?pmXYvIGwYpofZpAwwpipM|W zFQs@8>Fx+wahMpH$SeMtVaj|YqscmMM4UJQ0iceC&2%q05(Zg^Ur6UpL5xBgiG1n> zYipE2Nh3|EMjjT-ZyuRi0-l^F4CI?frH*)BRr;2$CwBXNz2@QZJRXl;B^Axj=`!9;HJ z%^CI#J(^+vffeLz^@d4JAEclEFSbByKf$NS#9D|}lOoOyvc@M4>-)2@7RBF_W5`kR zvdk`C9wyp9vVJpf32o-sRA_0dAfkJE9XHCA!C4(#j3X7Kf1*=7z9b3zMj-!((TpJY zG9u4+f?kc&(&g7zk@@%WyX_UM^w0$Q_55bHfr>}k$NYef&wH0b*&^op#F)M--N9$YxTHsiPv2R6s&R@y&zm;Anpe7B?gFn=e*B6A{C(s{LfkZO zSodRSx5F6^o@XR%+Fp3d5^fJr8N`_MTHvfl&1Szc>ghIEg(EZH*p9Vc93h=fNG>>| zV*-~ln}PA?_EXg2 znXx;8UDuez@t;4;rwh8vI+`v)7IIK^eyy%{q-d0YtPII5T@Ngw49ik|ol^pA_0$~+ znWI^qR>nB?Bafk4j6^}Tl(IUnW*k<}svF<#fa7?6VWLfWnyObHUBQGMg3#9(>ZOe=Xky8?B zM(-W8U@y?Oy}gYPy7J|$2`hMVA2Rn3@F9c-P?mpo$&$O5KW+-|G+VTlzA;vtw7^2b zm6fllCoNe|`d7qpLpfxH*2xgz)aJ(7Qm15tWyjpV-$QY(N!7e(%tn%W7~J}(mwCQT zzPxmAmWFrp-drd+3l<_LfHJi5d^#wy`>L~F%x_5LM4UbHbq-`c@o5oH!9c~ngUQLC z$iBu~lSUe#)7UMKvwS?XxPoBi<3O2^-dmEylP9IfgnuEK-)O)1x4$ZyMs(|We$#4! z6nD?orRBGGhXIYDZBTf;$NAIU+pgHSp=7$7nE9(i&Fe8Kgy|xpA%!zqm_9UwOyWQA z{|Cr-q5b~`=#Y@u)lzOS-F8$b3992zA0a`0WC7%O%ahnj>hm`<_uF{!3mTx|u3mKV15NWG4K!R8P zRpDe7OW~g?y-YuU$lzhGxT!YA zFsHA;W9RrK!ut&8@A#lzs>2PKMbe6aH&H6EqmS7_MegJiU6}5#c9+RdO@H@t68Gdl z;#h>yT?qIxS}{Gyv^U*}*#g|&{wQw*K7yGF`9SMa8QxG1?$-3x9mvn<1i1l1k9Ut z1`dJGOz%EBn`uKZqQD7i{;`iC1@SK!W^unR%Y5>4sZs6wP5X$)CBh!wdwb5VEp1eV zG#0`ymgw%E`LIjCcGi!g6x#_L9$u4Cc8B?oI;Ozt&tdJ!#9e5KJmcxtQrMWlEiKV$ zbVg$Or(g)Tl=YbH&iQyAQ9JJ$xUqepy+fWA5T0{;jb5Nh$P=->T9XUhl(6{m0d{ox zaDg-R=-8Z&uw9R4&Ju2-%9-icB)%Ck)0ucFvlQutq$_IH@6<-%c#lH$V|s2th(BGR zWco!oZjewbjhIo-k@&OzW=?0WkK+C^Mo`EWGCJdsa*!t>@A)E^ zq;1y`kBU&5|qb z>bz_LZ#-U(xdZYg<{>j*I)lNw+0Y25Q~QTxqfz>KfK+;W*ccsZp>PtY012g_jI8I3UCJ&@s6N%DIo!Xy6L{-Gb|O525cd zPX7L{aBP6%{s%wnkkINc3WH*A(DUzi59mhBjlFfiC`E#4nv3N4n{P|_!Gw8GXz*v% zW3ktX3w&bW4vWWO!_a)D3f%t!41nUyNPC4Es{PLj=O~AwG{*;A@$WdfhMh-K>!;r6 zO2v4xhtg!2?qdF)n6$(jEHsen-8euA_fTi)u^6e~Hb=NomX4+0pw==41AXq$nGmgu zxH%hOz!`k`J{k$^mNuF@qOJ92@S!6(y!u6$`693~iXzyHB|`LL(u#Q)K5(hya5Wa1 z*PJgkN>hEsnGyH()*Zr0ZtE#=Hc#rio9Wjc1{~;Li=uyDI}PMM){@xNO0g+T+dW^9 z$_Y)hOI42sA&zYTb?XT)8iyi$PfpJCMLcgXk)TQTN+!`KK(!szG#H3e{?Tm`&w$;^ z@)?$+;GM^v$>=~Va`)h6ynJXO;(0EML7fG}&G4mOi5IH%dvyS`4Ga-+M|?P;4krA5 z6^MCvwnhC*hL?D_Om?oe#)n?XDL4!ToPoeyFneENh(^(fef_5#M+j7tO(*e3?TmG0 ztZf&K@EmS5$oDOScC1FFR$iu7YXkAv0yVRVgNOzl`KVJ+Gsi<57(h#JrVGDsboBAQ z>j!YtVdXG`c&|@VH8K^K8Srunb3d2>4dZD}UCK>c!*TDq`!wZaGp7L`T9r@C(-)v6e3~^x4T6qi) z7-yqqMyj6SMR7v54)rne6RQm;8)yt$y|>nqxg?A-n>OZt?xJH+M2FzMe#1J)S|Nrp zhn}t%r)}yoGf7W~C@~_F_4IRgLKy{>+=A=B-!bUWsvS&x#~s!v0Q9sD)SX}hEnaXQ z(^)0z07nvlRvR?mZ60##LL`^(LrO8w-1rP}^Ge~X28n!snmYOy2#iYD(ExT~)`ZYP zJ`!K2G_|p;&h~$-`SC64i3>t6IQk&>`w1-*CilqzyTm?q2;wtaO^c)Go!l83v#1l? zh)Rm$x6{Q(v|uJZqkkxjygk%_|7M4MDodevdt8Ze`Ic3r)c0zXa5)% ze;e(~rP!k>?sDQpr>J_(pGbM)gp`C32R46GQ~LkE-n>t(fb|fE9IVY$(a7oS#xq`4t60JVD6fX*o!h zh>@>b_JlgsshymTPJUp;KDJBKDbmG|^m|pR839cG1-{{g91>L!C`Ms7r&$zEe+ZXf z!Eg%Bhh?#dTUGc?ml#JN#tGbhf_Q}>0C}^YKGg)LkqM`VOfY1C2|{Klvem=_P4UfS zn(dE-b<@cM3C@Np8naEsT4~%Q^$`IQ;SplkV4Uf5^;W+0Z9aemD*zO1nf-Ty-L8Bp1y2bUG>gvXAnzBy)#x21JE zzw4m_8C5tYoGokclu(Phmb1C@)AUX;)oruF%>-6jN{M~nd1I)sM+t-maO`2|ufO$E zs~Y?7(i9Vyt+F%YV&CP;si?*Xqehf0bghe2*!MlR`{}3Ta6U8LA(g6QFHF@D%YS;H znl$(NnGoPx(m|}L%HzB2!yZ^bEbsd9ZoYqDSciZ|Y*z+Q$sE7}?g~8dx@g}s|8mGR z_lrn>GbYolFtzEEFzO9pPT(IXk#1$<$&@GP3iEW@gt60s+?Cw3$j!C8BgYf84@;Sn zIv6NBjtIAtn0LXD{(Xlk?LJqVUl=SV1xq!zn2!{Lqa(!_kyi39R4eyqr}a}+=9`#* zNvw3h)x;|mwSGGw_PgY#HF`Wn_84o*<+*mnX!3stK)^hiMy?~{mHJ!fSG-H?v z>;eaI^p6Ui_Fw;V_to*leJbxVW<|8RQ*Y@nzHe%TUm)INBO-{RPb zkP61Aoz$Mh&v4nPXd^cWCTt)KsUy!A!PYe^D*ydDHWJt>;(2#@%5g(P>9kq7PVOCC zj##9Aot_7cg8gL&66s=3daa?=E0|ZrRUNN9twnac19j#PwYpp7$88@Lf&y!yyJDRF%%jjy=pM)~PC>B)%RE!0jNT*eUaqN^S<=daZE(Rr8b6 z5ehKUs~FugR`-8_J?h`f!^u<`n=XeXNUwpJR8(?`F}2bjN9PDqDo`2h9wb$Dpu*CU zv$;C?I4XVhJ5uC(5`JxoJn>&BIIbBSH}^rBvHjHO=ik-Er5`_565+>QI8L9Si{$SM z9Rr{IjFOg&pte^Mp^m$@+y`)Y&i$5t&|IXn^uMeSW)u2E{eFGdLle4a%H^_M8(FaQ zdtD3X+?dUaja@CFIkIz^cRt@JtC| z^6ZtB$^<2V@V(a>+kRJNB1+S&{tuc>K|XhaAFE;cvDnrL-@{!xj%#c%8FBjK4KkcD zDMsjJ#@ORakVU7x-N(U6dEowSS>fOYYl#2Ib+40en)ELtsOp2NB+=r^l znfn|B+k54(1#*|sxBb{j{Ne?LKe&qXBcRHRzAE&=qT1(JqTh_IY81=OKAV<|4J<&F z<`^V(xrJhpBNsgdWmfXBJW3IF!k~`Faw;F*8O!p%+81~9{x3@ZmXLNnsKg?XnAs!= z_+dCk>Rv5m9)lD>0RQb2eRvP}F6l4kwart|L(a6(OGkbheb7ejW%wSj2lJ?A`hi45 zJ*Z1U1(WWU`CRZJ^9|bYw&x)KjCv?ARAxzco7g=C8gbvP;j86eKgN+PFO49&GK0QH z{@obz!5c%+CH)9A7u}()7_x6jU8ZY`q;Z!Ytnrh-qM!8D_;3q=58Fj3D2WI#>0*D$ z{5gPyHB-z{BUTRvdi3W!kx*mO!>q#o^J8$#iGcM02D+0708~J$zqPV5k`ap_)Hpgs zPHdGmefQxiW~Zndnaq;a&5)x-yAV)4ft|oOhV>8+hm}2CvBe`O{7bSxM{c87!0eM? z5E}LtfRKwvLvZk@wgB(?#oBKGV@L5r3f$`p#h5CxMVBc1(HfY%w_o@m({06xVdWh} z9Eoaqx2~`ID2z7l*NqW$Ab7w*{PhC6{qES?-7w=if$dJm2EhA8OnAEi@aiI#DG5u! zwr*((s$qcWG>SA{87q%=1MPAGiDK z6z657&zza{d!CW)fB${UmB{6$Sh)^>dAcQ}(5}swr%S^}dKsX*z}|B!c*u#H>ve!S z;&}SyxhL+M1>fD-5Qf8cd3tEop6phZ53?*3>qf6QRcu%B=bC;59%iN*F(CF~E~N?5 zw1^KNq{UWJ7E%ysP?l1bA4B#PC$>ve>F1H&tI}XZAGMDk=xGiGwaVC5$UHaNNlg2m zZ9`X?mhW?)DZT^yq<7wfR4@z3`!(MdsI{q`JaIXd{+JU7xYafr$(-hy`98iT|3?(8fzx}9X@Gy7n6PD2Q%0*x#QJ1-rxj1pm2OR z@z1rBP*6KLJiPzHTRvw0D}v{ zzJjnj0dolZ5-=8aVUHn`DUrb+5{~a#sn3-YEBn(qXMwPD?nU4)<})G^x?xtDYI>G~ zW(ugT{QfT3ewTBCF12TlzK%ilCa|d9guxBYm8O=4Chd!_>3zs&%NYmL;#@wvtV!c4 zi((d~jH~+dV(|Djbm@5lfN;iIOT{v)Ms(=yY-rj7D`+Cf)|eLVKpEk?>>UyQHmP;<2=# zk)4G-&CJloq-IVtqW1R_;pu4rG^G!U5mA5z1eU;!aNsm+mBOE8X2I439ceREL}BR( zL9M``RyR1*szU*6pvmr(ri2qx#icSK5a2e@xI>L_%^OcFsB*cL)5$?AC8~oBdRWD> zJQc{Z!F9AYC-mlM6rdS5KZVsY!dEwOBat#G- zcQv{}h#Q9s$bXn?*uIMu;Zu}0T1pDGkO|J*=Jv7dWYM8h0nY>sSxd0J5H4_UL^>6t z4H2-_ldT(2_OJD+?AhAj_F&n&mT+!MO4Rfx|8W+8%~h@3 zXRZ|0LF!2!;&y4E$%z$2!HBbxpB`|Bt^Uo)#M3y#r2FTpBg;!!B28d1sZi)RGo(DA z2(+ydF*-v9-i8@H4Vp+7vy(0T3P<-gqX!-PitcNSFb3Ej^i-8XrO5@t3ft;@Zoi;}Q1 z60X9cq)jR7fT=>u!PIoR)RfZo1WP+Z>k3N2x}-@-l4ORIXIh%FFf$)l+SCkeOBvdf zGAL$BqRr;f>6}KRQZcdLw5+UyvNUK?9&GdGf)26>yge%GAcV6;H)iH4K1$sUD?hdT zk2WJH@H0ig{%f3Sk3MwR=}lofJc@u2Q+8k(DIa}<=H5rgM5W86))m5{XfcaQIWj}s z1ooOMv9j#DHd?6c(|-ixsnWS?Cs|;A{n*Aj7hnSX!Vs@jyXG+Cq&e^*fc z6^eW?935Hy8D*1Cxu)l06TW`S>%USy@`ir508~+o9-6yg<~1W+&C#JIUL$f@`5A~a zpdn-OUAb5Cm3tOKwm-pR7d2rqD>BOD)yQwKk#^=h)?peUX2zJR$h*PJC&*CNvOn49 z0lISmT}-TgbNtta*q8ujT^sFE9f^Um2(fYZv^`xAc%B8EL$uK&WS=(L!*Ia80H_Cg zlWQcS!JWhh@G0|He&o9$Rwix^6Zc3AwUbCjZ2K<=LGmRsg$}kv2IDp>Zt=fkLbr<* zvDJ06QiuJQN*UKLlnG9u=gVgX9Zl33)L$o_2q?o7zUiMh*Ha$d`D8OFx&GJ;Vq9WD z9Zi>xU~ej7SO0q>$k}pB5iU$SelTX0oK906EK!?ON4$Q~XAzAJvzW|mM);XSSEo0$ z`OBCD%i*U|M=uBz`X4a(v7MK~Fm6_TWt}>_D(h?SX!$s3{*POcN))+3U>HMWU zg600}NIyEUy3$2&`dXpO0xEd`Uo0NL4A3MnuSwRx(x#^FG$$uuETxDJFkaEofL+jm zL1sEUDpo)t89I>2?1t4^m0-0;5Wc2%S~lXo)5fHMnQ1|D65AirEhOBmM&My-AQX!o zuo_TF;6{fDnN@0OK9FR2wX`T^_!h9T2W>sX!iCP(#S(w=w8WPM* z1g8p!bgVM8GhAF;X?eA>r&(B;Py}k0=PCnBlbSuv*j2{@bDZ4(dzjtms%y z_6f|VQX0!?Ni1K&0ur4)(~^>M9Pp5uks=D~3>P#d;Jb?GAc+~;E!|RvhBME=8UlNq z6`OJtM-O~u=vYS})tS=_hBIca#=uGJm3U&~niPDGMd+z4HOh$!O`U;PZ&;ADAeVJX&3#) z3Wj0@!vIpz?Ggt=6(lH;I56)itcA|z-oV^aK1_vDzl{Ei=&^jym4jEtruJi_ixEy> zk%13chgNo~rPvZmyI6EKaKk>a;UPRYYYnNc?R91<+C~efW7nu-shQyn*((U<+0Qsd zR_s6pc+T!ef2>Qw8l7+%Fmw4O@V0C9Kc~xr)X{t%m(g<(pX+K=7vVhM3+4UTaOWAN zUD6*F+G0jrWyG>OY={V0A=1_Xe9Ny=up5f0Lpgp8w>5$&H)BjqQo^CaBqPknDpWnj zia~n92IFM~yAZO$mQX(2<;T(W4xF2wRiUKpX7;+@`CeTbuU)# zKLkv#2OFf-Ay7hARrv0tPa!(cCA+m0m%;7>W-mUqTkZj%szi8t0xxTf|9Amgc6_$_ zFCW={7@pQxvF{Jh2EspBAcgZryG`~BrfJ!8awX;0=b^dT8(K8XfmGDksWAC`&7ym| z_Ndw|_lwD|GEn~mlwAPxFpl0a2f=@Aw%qpwvKc6w>$K%7*uv&QxxhwtBLCv(=hwHA zvyH%|Pc~JW?Z_T-bmdP;qGXGKNC(Ez(mVqyi#7&`iGh`1mYSb6Jy=>aD%LcmVdFS? zgoHRwk9QidO73Cggi*Bx*91$e@wA0%?I}mfq)WL}&3sr>YST0fM}~eP&#Q7-P~Hyb zN@N)uPx=Jr2bJTbvH0+}2^CudXvb*&>q3*xiev$v6V#9_@T4h=N=FR2!+u@h*+w1k z4{H9qft1({<6Xq;O%DXMhO;(uzoC^7h{A1LA|zDm$TC*~VD1#V(y(ISp^hfDhV zqvl6{?&lU5JXVezL1$jM8)9Ci^z^?b<}zk4gp^oAe=IIS0c<%BU?eT61;-ij$0hV` z)W5#CvAlPIXEDKP28B99W<_G@n0lry0e38|Q<_lVMIiH;loSI9)U|cM9XJ*+gCI~N zd?iIfWZ$sC;t(qHU(88vGkew4pUi&O&b)-1z*(dZ!v)0!?3vdy543>uG zd;Y)}k)L=t}$LK3p|@ z5MNQ8M@;b`H)8~xIPwNccO&qe%No%GmR|+Gn>Kt=${HID+7Vo z)gwx1J;R#+#(-0aiouE1nVbZqGQMH+mm^NB&d6@YH*Nj^@4`ZrdCINauN4`~ICv73 z@19w`c=qdLKz9iTjS&s?Bmanb%6WnFZ(B9CoN6}(dd$bLqA!Z@z|`p9EKFdlns1!@BW z!B1g=*@W(j<}1(gKeeZgFT!Iv0KrHn(MFFE@yw0z+C~e|@?V&;%_hq>0RW`y>dFW& zQbb47Ls_w_J%`!DPb{~Pb+p~+xR`Ue<;+xYaU^)ndK5#>$MBaOXU9n2fzydF(x*mX z5|rHiYx5Ezdu?TN(ryPTL843`%CpQfnnsP7*IfOgqkx5(b#>t6nwDYtAV!dC`3^%Z z|D@96G2HTEt6N2(KZS1$H54pHI-A0lEjk%iI3bML88UDZsbQ`tx+2RVvmil~KW?xz zB_mLktgyQZQ&@fvb5p6n+G!?*A;<)fAYMjzI(C7UpCl+~Ufrs~ShD39D>2u9XEH_@ z7J>su*BiK9a6tkN6yRR#hTQL_NKkg)n}Gt5R4^mmXaUGMCo=gmPK~m=_^`=%!*f#- z(w63W1Qw|haRr1!S>5NG?D_j?`tNRhflB70H}A#ZP1u2=pJxkbn;*V+m)8KThb zBtuN%iSpq(A_ffsRFlz4kiaSEfa}Ok%P-QOc?Nz$KK7(|)Hhz59tM_PAA=j~2v8~3 z6lOpcfVY`EZ9O%a;XhD0ZuFM7#ggnFl)M9OgF@A22wMfkokA& zLOmBSba2f9WQk+M3k;{pvb#Y+Z#<#rlTU`#|zFdSL1W%|uaWgPm_BD=% zA(zO3lrY%k;3cY05z;5y+W3CS#?Jd@UXopnG~|Ou{u3wnL~07keh+9fA1(N4Lgl2P z^cTWZa+kT28Z&A@2ttX1ELm{Igz%XUSAW>hKArlQ1lHH~~9 z7Ive1s?ncW#eP&+%kaHa*QJC7{6T}U!Yp>tG9Sn%uYzMMr`^Q z@G+d5E>A1G=9d(WHhOpCJ)g|3*rNbwxii_4+u%w^B`&YASA;-Wy%)hB8 zPSumXkv=1k>OFCgW2+mY?MW@N->|>lSkf(+B3pK`!u8#rRRGYj$<|hCXT__R{tu}a zRS9f7fUD|cyn#FC%l6a9j)&hIwNr>taZjekS%}*ZjpO#OP%~WzX=wTJg z{9YI`ndJ|T5o-CwC$t+KHyV+k3IojE;!-P+m>rUJn?>RB(4h<0&+#=Z!1+E1EaNnFv{8FyfV&T_A zs~<_B;Vw+cJgs-21-D(R&qdScW^7q-UPi<1TNB=p8>6wZ{92`1D{QWpkJMuJvo#kt z*=+R6zx*faKKNZd{u8**KSP`E@$bGrZZ2~eV-iXZBO$62u0T(gEQPvd@aub+zviB}q2Rg`7-fkWA$9#HlXY;yNjp1(y==ui`a zP1i|;Aq9h^|_1dXX}Xj%TrFyJE8VjW5sJgPD6Pt+$+>cOiDni1F$F1 zEX4DQd?hYB*LN;;@Zrh}cIO&nZTZ53(AJYi^VP5^uI!eo_OM!}ju$Gi_S3Z4nH3OxAslVornj@spsQMA#W z4QEW*p?1aAvOo5D$cSge;P+GW7bTL#f2ZKMUN~fYw6KvO{<_d%e?z_2<^RCAQELqD z4m<~ka%4&3mnA6#7Pj1J8I%8Ys7lr_5WWKc-T3g0x@?9bgrO_!{5i=S_V3gd6PBKM z2xQ1`4*rqjjImDoU#U@ln_-xeSG*5|2ue`!w5qUy7rqmB2?>RjkgFeo$McC9ADbW9 zUIN*Ub!fgH3l@()tknBrJrJ&AJ@FPJ%z7}wI+g>;@-!6nq#7Yyl&WLagF3!IZDsn` zZ2z-S1!aR*_}^9PdALt^JdOGp7T@+}uza{$b*iDm#8**LRZD|WDmb^i%aftA0L>|L zt1cb78>vnTJO|Ee?sO{>vr2~sP^ZVF>Ua>6%Gnu6b2IW>nnOYTA(UN!Q-DiVn^l$C zT1BJBbn4u==&6u%M*7!Y%pHSyWTk|}(MetG4kw;t>uYJmaX_)bse4)p@!e-S>0PY^ zEUj34F^4Ig#HWoP@|bZ9==qrhlUB9ppK(8Z*M=#!Ye%J>#MalnU0E?3xa7R7v~&pb zVc?UPD@C1&8sodRq=zu))?ZF)Um((V;%K%n z8pqw^rgoTf4IrXjD=C~JI2q#AlP+^kSMIMgK&W<~z-^o)iy<-nLA1LD6nasYBEO$4 zxqO!kj_z_Xx>Y``<=0Mt9;*DefQ zLC7q5bB>O~Qp~?~%{_xpL4LVXQD{cEUjb63>IfB9`O-C_3=5dOiPT{p%z=>(MRzu8 z++7@E50_#dSHz{D>(SkeF{x&2xMj#t%p(&9xn6}eA3Ti|7o+bH!aERM8rzqD6|jb* z*KV8zi}^`uaJ`rPh^BH|`pv)Ink&}yO1syu$Jojen$^8wH(@fy!F2Nrm`D~}RW4Z$ zSz^r71~)^ca}IN)FW1K;ghY$j9dM5nt#X}0H|hoYVdxL@-8Ex7l5eI#-}hY%XxqvhT|kEwfHpI{f!QjS$Z}vAsG{VBOkftK}=qk zKRpf9uN=v_=KM(cC_n)Un6XBTjy*wW@s_Mz2%^B?)XUDQeXlq!I&3xbb{9-}g^dCI z?a4wHGrrCx*fIe;6*{M$NIe-fCdYjE2JYrrk(vRo-*x6|?Y_Ajpm;9S zeXgtR?=^V<9hfJaM4`7?nXPY+nM=uab9t8G2)CT20Wr5IRta%du0n#uXK=I39!)@Q z_P;i86_S!O0OmX&qvT$*#`tRaSvcTYz=+k4B;qsNS6528B|RO}QvD#WZ|<5KB1+Ae zEHST{*Cbdm%G~G{e5QM2uiVA^|5yh`g#Oo~t!}VPh_&DS&5ZeS4P<6)4Za<|lI$>= z5O(j?NvVS(JxmD41neWJ2;=0kyI7B38{{ySCuC;Vo-0=B4(07XTZ zypJPiDfsXK#|eOm>|IrEE`;f_fL0yz+))QcHvuZY+IjkuR;u7&B8OmA?o;T3eYZ;$ z-_6+CJ`JHfFVo>JIz|0{#Kci z&l^3C8sVH64X;xn{KJv$?7;jp_IBX_B46f|NsWE~C8YAJc(wKe0>M=8@)hI8pnU1zo&T4qSoo79kT9f>;irl*fymiwkgZ^&9=q~{2oI(Bpg z;sU{o>5e&@G2i1GoQZqoAEm%X=2`eClaC6+mh`Y6*8x6=qoYExuM~aLKt+vQxeK;t z?L6gFX(x~U3gh4kGG^a#;pj06Tt-;u_JqlV@Y|07Z5&N;G#A;Dhx6Kx>>+_XwVU?T zWsF(;m(1#tvEo{}Ku3}RAz9S#l^>I_;a1!x8$dxZCc~0AOw8DvIZ)9{3dRvmTB*w2 z1nyH{OE5AgGd8bl0%v(LrXEsRz7?95vl&KzwQYo*FYdX(=9y<9&@ zM$WxW(Qa}>R2O4X>?hx#xHvM|(h8K5hJD}d5^{mCA?>f1=s<$Q2%Vn|B633D_^`fS z&kYD02Y5WY4>}JkFb8u7$ir-t%x*40$GAPhi0WyhgT7ADrSly!JmNeKZ#jGjgm)m;Y&yl1Eb&->>yYQS!+APzIzh;eyT{G*dm*X1 znz@m*4rJht>Y+eMgAVQ-cL+r(1l%kh!)=6HVA)aVFV6PWcF`w-)Hd!hWtN>q1i_@- z|7Xr2NIoMT;XiX4V-ktaxwK&U;ydOL<|GIxup~)mHv2&j3Bj0Go2D^NNK~t9Zf%*; za#f%XPT5&EqaV$Qc$`#p;m2@5U>%G3YEpoY(>Y4MB1j!;;Fj{XWoiiw$_eg*M~o-m z)Cqb0>8wL)*-sio1v*g@0c86xc>IC|(B*HCYvAsjFYBWQOG;*v#9*&SG-B&ei58oU zSKCmE5ygO)0by8+@e}xp3h5Is9}N~U^|0tuEQ#ePY#S3zo1e5PXRwr}dz?CHiq8G4 zB@JieQwTig?#Y#azogs^4(joffGykr$T{)Honlr|1Fyy+8{-}xCh(*r4Qj81JmJN- zQ2Sck__*UCIT#ckp8E&kI`i(i_C)iQCJh_g+S?d6p^hgU6GVi>HGK*k?nlvKdnPzA zn5bDnh<-oxew}IHeH%z6eCSp*T%GJ>6ryjVOBjEE^Nu(?bi|c=%nLQD0dB1d2IWC* zTy?=PVlTBV8}{+*rJ$yHkoy7(3E|cihwPj`E|QsX zF^F8Ef4E5~drt*rer$UaReTQ^>No;(`=ROKDio?3#|xBK7btW!M&xm>U#}bqn~7oe zi#JNM{M9fn^O4k_Bm?)w2QT7uI-Ot6G5=ouO*Hzvfdhbdl7XisI*$zWTEZ(28w~ew zudzD>K<&NCkP*UhKhE>@h4+Z8i!j_{v(MMIER^`iIy!F{6#5Q|(1)QyyDl`E|DKR{ zUu$s+m zk5R`kSax_cg0>ZZ*q$xOnun@mf73#ROEA2~)g==_l#&3Dv_?BQO>NP=?|n@_NyD1l zBCMs%UW~q$mBvz?UxUc|E<(RXj2Z?}!&gl_@=i_on*AprTa2*J$4`P0CfTMcYEL)- z%MONzhKlB8W1BKddGb_SDqCe5t#SqAiArwDyCd(y&_2uq-zM}rPdRT)Qs~nl+uyks zRCZD8V@;}=r$BKuzw#h=Ej=0vx|bP!kk3b*)S|od_8qNM;Rkh`rN_x>1Rswd4<&yD zb%((=hz-|JK}dIxZrmK*98sPgkO- zer4(Ro&>(;MC%iTjGv?W|87X=HT%UOC#fIJwqX zhRwh-bad*tDy5;hB5JOvy(zjW%B}H=v_fE|#|jU(1m-g@Uc7km;>C*>S5GK(of-{P zr35TCp|8?L6WKK)sQoU8&g|z#9YGC8?|cC`D0B|Wo`Zv@`~QgWHP8Z$rVwVB!F8k7 zET%Gl_rs&UseeN1+?Ak)`-!)%;fwk?(ZjAmMHihIfk*J<%i$be{~8_p$BXtgd~1U2 z8$dv6zd|l!gx9QDv&PI?f%d~>gfYB>mk`-D(%4`F;J*fvp9-ql#suUsvVG!();OVp zXWQ5zPjR3CDMXi45xL;mZqiH5>;>efDLfK+`yk2#)+D)RXm$a(h1yUGRosl zh_4SHoj?VLW;PGLPrjm%jDv>E4HWJ|T{m#-@mA)H0%*#N+UlE93n*Soo~vElJ{ zJDqMNQZbL~kZMUM5)m!wYeWG&_2R1JD>G+8_W6^I=F>fHe~ju^3&=;XuDuuPK7B^@ z(2sk(FV_KcT(5U?V`IbP?RGldYJ8dRD&sZsn6C_8PR!?Mj>CL&!jxcJeGDBNUgO^L zj4=l9Cu8vHUPY39NxrBUyW92-MwDKF1t|?vgV=6Ew{r+zYjbO(qhQM)8-GespJM#6 zQ6HOJKHT=-pC5l^Unon#_pHxGy-TvZF9*!fUhn3{#)ik+?R2XyW*)6Ku}+71baV8< zQ?E+HWjrw7s+bbh6)y7Fo`{o}SKl);yBUi*KQ8LDN3!p^R>hdb=y^N6ZR3{Lk`b$X z3@qWc59eGzt}^3ZJ-Bx-pnOmMOBjERec%rT|BCU4f_hiSK+{G0(n@Z&DK}{g1)YEEQx&&1pz8_f^hR+OrPFJL>lb`fz5Sr zooIR$_*a-MCNLJJDh~CJ!5YZBBpqdJSA?2LU2Ya_$1c9{GFfc(6SPUSQb-uFiI?Ov zue#$Jk0MWinahud^>jt!*&a;J-Jns?O=D2b=~D|7l@>Y=4IkmhuE78(-ccTn6RLH5 zUHx$r-tummDzsvtAhhdzdkohf$@vTL1n>*^80J>yh2d4^w=tQ7Jg2^pZ&U=a>9WSv zr24}j@O*8JxRt-rFq)JPw>Ma*fcv~P{D3*S*6)kv=U49Ms7T^8>^hPFsEJ zvx5cev!hP_@HpvrBhYb2|8Cip9YpQqT5}R#%uQ5Qui^wUbTYP1yUEP02YFqq`nm=! zO|_f@Rt^R_lK}9>oHS^Oz%jB_0TgF(usANzr%P3)4Zxo-OkM^)1`72b<}oKeh!y`7 z?Xo$W!+?g_#D`ifcWTMyjv3SU`4}uJnwHM~;$t>51Hh42J1(F^SL|+Do4P)_;MK}-0 zM=pB;YPha_njRLm34y{wF+g`ocwy3=PC{mu$c^Spm&6VO97ATGr$Ox&jpY7S1;*+M zo0`u`)o%>g*GlQHA~KH~%M7*bI$UdHY+xw#sw?{{NTz@QJ1V^r6IrwJ9{@5ED#pqK zyw6_CUNvH|)jx*w9@VUn46$DhV*iy^>pHGqYE?_RGkw1dxze&d4NJ2Y?U#RpnC=Cy(If+qs`ci@E#R9XOHX@ee=}8%v+0RCLU}#Mt*C%p+Y0E z`oEnyj1?BPub(q>|4_2A?(1bLR$t#O))?}@TOBE!ChFUYR)i&fb#)I=K$R{sw0yfZ*YXFb7F7K0mJ+_%URoJO4*vS zn^zoJWW+7AAD4X}SAWc2Db~C*KOXbr{=3Bk%1_`o_sXa8-&Ysr>3$h$@MzL+Rr<`^ z-vU%=vaJ!wJD#$&6+#m-OmS}u(>>xt%kALI%|I;^by|ZYVVULIVmCmnU@f<6+2(`e zk$?vY>hj=_@mVK?&d&%MwDDPl0I z*YjT8qWB9yE{CjfaQ1)Tk%KW0G-L+?=bMpu6dtrqyTjoe|fqoOvDE`k`_HN5$ec_A~Ui!Osa=VEZ)4 z@82}|IV4o5%dBI91q{+XDgJI?pzHWt)`tx{AbX{oT1wLek1=%6s_(wVIL~0|RyxX4*`qdKEQiPJze52(K2gK^_`?y0&Kqj$Jx6GmqD!qTifQ z`p3qA85r>lkH<5r-+)~3EWHcuCL|+vIe$!n4Rf_a+04eko-rO!Q34ostM&AuC=%bp zQ61dqwjI*1AnL}AhUVgKer4RARKxrfT8yO_~ag=^-p z+yxuC*M)w;*D&Tn56Z?9eft?Xj99E~a|IhVtDzly~2pC>8Ca<2aa zMTNd_b6IxQ`Qe)^=+D7ri0JilKyY(|!^Vc`0gu;!AM$P&0|9h8Dl8L+0?)PehTW{v zMV-Nv%<9K`%$p@$SS3<_1#)EMXpt-TJrFuedJnG&#T+dPJ1prKQ0Ftnqs{8cY%1Gs&FNZWJM-6k;X7syGdhcJhqv>VbTA@N4YO1B z$s*MYTPB}tG7JbNV}rwf@=1hy9hW!Zs;u>Y>39-=jD+GU^!&8-vWhd@ZnWswV2#ZQ zLgY8z50(pXJ0z4TaZg(3L)nKpGP$)RV7XtBYy{k6-&bQ4k0w?Y(6ysmq>{7aB0GO( z1}`8^;5Q$@H;D|Ol5NH8fMG2{AWPFf|5a6zaBbeWem&Z-2j8Otkrs!Jos46!v!^8- zLpeH3q|yc5{mD$7y7_<*+CL*O(njhpCC`R;p2dg={3LaDA@J5@Cyy_b5iPN;(g#18 z+p!BSB>7?TP57v2 z1R*?sr{t!7 ztCf68XvCD3d`?bAa6b3-&EQjV0{h-ra8hd9 z_6gj!Q#)j6!Mz>!k71@0(v=Gon?66fadUKY#CpKj+G3ESBwWnVxPW9k^!FUfz3fv63zFP)%(F>9sGna&Zqb<~N5a*c{j#E&YC;xG7ixekAnn}1y ztBGfXlK`Z@CvZ`E{D8+4i4zYbKk6zeizyJ4m>`r*ff+i5@ZqOQgqCHq0Jq?qF8}BB zMT{3gtm&tMJ(Q-nH+UEjAv|!# z94Bp{fwO(@0w1b?zbLg_Ojrx@DH1L@jsq-UAOz0gCoGzvf*m*z=Yg}puSnrB@E^DY z!xT;Gx8EoMi3YydWUAW=Z@CBalT#JUkU7%izi_lzF2**8LoY8RCCTON0Qnm&7)cL@ z6{aT~U6=taPEg?tFz5;O2iWSoUtXS~`A!h$QUc~N=b>tOLN*JQ3-0M)=|xRBL3Sck zHGy%&te(eX->7E6S=@|pSPqXdsmk(LQrZeGtCL{KsoK7RWHeFo^%pR7H{VY;(pT`sXR2n?{gqaKUtEMAM zYIg=855xg}HV_#8h>AaNbAh%Ay^FSJHo>P=y7oW^a!94hw(uk#@YeUshSdquo2Ww1 zwnYz`dejn}P92SNsW*N3=uOYnlPTATt`a0fOds&B(5nPhK70dCLd6lc8REcqa0+lA z-hmPn`iee+CW@A4i&?f;pU$%hTM zzTn$0=(i@KY_!2C6wB`yW`%!OO-2^_vt%LB;swHyp1k;=Si~p388BMrD|t{*85>1V zR+xr=)%3ypH8+f+#V z{Ur59x{h&S$nXLZBrru-EEbE!VzKCS9)R8XbrLF!t5P>dS(jPLQje@od$eP=kGyq1 zD4-yceCF_(WORjxE|Kmu#yV~m=4!Rt*5>B6X3g6h99&#n-ph5blbAM!LiaRO!NGjP za-Y{|`W@Ny&<6k>2S^~!6+(#_Jr!ZxZ~Jh@4kunPJ2F6sFzEqRA@zF(>c7kT0jYZh zffy7LTKf{ZR_GpWp(kM+8;I^$j8{!gA{REFN7?QMv+s+3kWNSN=mc6cZHdv80sPC1 zfm;<9c~}+0@nI#p19+B_T#83=yx5bLO08~m8kz=KMOzhGmDmI}4l!2*j&tjLP{(6V z$&bkq6gpP~Ra(nQuSiS!5nKWI7}VC0inyxdiKiT~4LsejaAco7-89{;8}=%N6H`~7 z^cnqd3A`t*0mcM~q>Uc_cMZaO>LXKNpdk5a9O64fJR0tpKQ(qTS~m3M$lL>=#*wtQIk zQ=}Vj6RsJd`}3oIZ!o);@JEEYJz_=p(;zEC$SkE(a$d2xgR4-cYit9hsJXt;Fqj|A zo@Irzuq8M6dlgP=zgyW6c>6<`6vj4To>k_xHHJ~cNE$)BR`21yO}@UqA9Y^Mr_dc3 z^!?OmqlKb-*Ay%)Xi)a6p9N86gz(g;(*Ptw4aXAj>RrMM%|e71nhTeolzm-ZJeXq9 zNHwl;+Bbrut>jVMN-k!0Byj?_(Zu@^jxI>RFFjpVy`=e-gDP+|9LG{7$N_`~3+2oC zcwhMc@$p>?ZhUw{PTwtZ+&49>1Z2T?vt+TLc5mvW5Zf(^T8C(Mg9zlbOAS)y_h8ZF zE`ersyL)x@@$d!Dm7(*(ZDnzri*rS*4t0IoUc@8+FO~m#7dU2wS+3sAjg1YDx7+D- zYb)=_Ld@fi(6Y!p8vO(|JVs^pAKVUZUwl_CrgzTF##L4L{*UCr?(V}mIa@&oca!WE-`BNL)UCL?I{Cw9L5Nz5G+bp3U4}vJ#=IatfAm{5#S#sn7|0&oXs4;{+>X{z5F>i5T_{KHn# zj#&1qi`xEJ5A9EgjU=u+%?jthSjkz~h`b*Q@#-WI&xW)7A=$^Z_JWKhuJ{rW8QX*~ zmXECdA`nIx$Njdq3)wcZfI3It{V>;Y>*FKE0Co3`>3?-vH9vl@Ca{1AmX@X%EdlCC zKmibFu;gAbx-O82Ns0S@Bn$hPkS~!)A+(7SWS(Svr1WGjBMbQSyYCVcvYuQVPI$|3 z#bXSjAXrATMhyE>jBbt90~`6{qelL`B{+Zl>%zcBmM{BZWUe2#LNbmZgybY8g5^`M8`w(VNn zwq%x5&igm#f~IIMQcfa_pCBIfh^U?*2@YURS}ck=n!_pY5DqLm4-R4s;X#t}fBc~R z1~23=at%C0i!=g-5)zIaUfQyShtyA|3E?C&V4kp=7ade)^+`cQHgO8H-6axg`0EP@ zrh<^aoDy*3j39jio2{M)4gu6~&I+dNIXNf{SWYSu-Cj^S;z)?2asft$k>_=!ALH7r zrw3$^$%sp4Fya7kGDjqibOMb8&p}T^K_%24YG1>~1_|06zMO*~lgBwg-5BIV8ji;? zKb|uPYI8F*@K!Y(F?5PDBMyw5=C`a&BpUh)OM`Mg> zEXg&Nc_j*V(SFJvokCu}?bW&YjA%o{6P_X1?Hq<%7X-|fP&FKOiR&64YBw(xvTJ~;#n?FIDC#iQ;L(@+ z%Yi>6k4L#XoBbrqBLgYfkHCyEvL}xAN!9L?rMr|OO9i+DP(#0-jU?D=NCuYm?Or)i z2HBwj(C|MRcm*6ZZQwfG31^bPc~E!;cm$N5!Ccde>0Wn`tVu%v5BJ^7i5^J6iEb;P zOS;#p)JpV-t6(K>;;V4nB{;1rZX39g9A1TDzIkH%w1nV~rxTnt}Hu!CyUI)#w)`$ZIs5bBr> zfNx7FCOYbVzEb2lmmd@l)KGRaD-34s$A;B>xb}Gw#%c2IUyb}Mv&!19)%hG7|NKqOba2?2#ZH1tAz z@--nMs%=am!a~GCCL$W4L6BUTm&`JWg2K_9hK!S6o`<<2;#`#}VmAjYspRla5d!Wl z@|o|AJTgG^Ep~;Hf(#HK+$2s!LJ%eXv;e(oz)U79zACiV3zl>b_!S>5FJ=vuGFN?* z;l|;5dbcw^dcxWq%TeX#L?LiIG}szuEn3lh6NsZRq%-v|yi9r}S3yFRcb=0`vg}b8 zhT@wgAs-I5PghSta3`oHR8d|==y!6TSWm=o9KiWlb}k`rjqr2v^7J|QQf=g3*Og~U z&-1uAIJmdBHEZ15+S;mBHnz1jHEPnNsi6imXwICWQq7ntQ-%x~8fd`rF=Os~Iu#=( zOc*d=zI^fGrArqzn;cBFHAfctHnyqRtRe6wlO&ln{sCFSvc_dv%N#D@nI%YgCW#TA zIpW7Ne?)kuh!CC`!pAdxe4gp+@gTedp2vUi9{i4PefJ$a2e0Ed_#BVpS>N+F-p2F% z&g=Z@*%j)eKnEK&gG{B^^CHv0VMjP}J+-(mm%P9C`hL|ax@n1Yn>gAvLjo4|U{@vy zM)lAR7|yk~=~}WX(sE~%J!v&##BJorn=ZIgZK16|mN|J4k z$0XlNa^x_ijayOJIXP8L`EYVzr(2OAQIezw5*;22H^E?W=s^&JE8UHb*ZNv0De+k1 zp%kS_M+!Zy-jG|%^*P6kmHZl)t_oOQUhZB(NUUn!z@C-9%%%Gx;O2|Lxj2CJ{L^24wDq!tt4e3r( zPUs#o)CdD(pw63$B_$LU;;OEgS5>(RRBMtIi3lDk6?he>(qV8F=GBAj%!9aZ>{GuN zAy{iSjbAm zrrsvZ&13nrG15-aU@XR1Xkp=f$Uhb=fcOR2D@vSAB{1v`X8^*mq>trCa$-fKS!H5R z;21p-fPlaOAs!eXUU(qx4BH2~iw-R~1nIEYup&o@6J%BNQrw`h0rF1lOz41CW-iIQ zs^;z-vS{r<*`>zV>levYb3j<64+fug#9pcEG$^%FWpi*Pn(I2XR3op5qhEl*6EJ(& zk-t>nK4%__ki&{d8#vLt9_1cNu1Ybl&~kxH!>uXXML;A(K4VOg zW3qZXgCCm&5XFc90wEYLh{Fe5v+#d@$|9GJIP~G0_pqU%rljnmG^MeN? zriUFP=1yzGY`YP&cQ9gh;9$h$pku_;*;?uoEEsc;*JevviAFqqC+3GS~3Xnj~bsCOJ$x zk_kF-6t@hd7RvsEe2fSn5Q6c7IDEiGiy#&&gh3T4PykPu0NQe^)u8NcV88m3SoRh7 zj%*~#<*SqE(?hz97--p}0z?W2Q1AdhobX^`2Pm~As5GpzD5_Ypnt=d-00Tn+AQFuS zL=ve`lto!LbgGNyq@gq{NMjs{F=Gq@009627ytnQAOS!CfR7&=el7^akz^24>M>^V z)3=1_qONXqBqM?s#yN8+_VjM82P6skGPKLRKtHWKuB5Xe80YnejV5cS&+-NzMJNkE z(Q5mQO9<(jTn7wUtEN6~M(AsdyLy?YT8EPr)*(kz5?uge#Tkn78*C)pPRebvq3fSy z7t>D`tu8YOQNr$-E_mXUwv)%t^eapTXru+4#vP%Hy^Z~a*s>2!Zkjl$2x32H0;h>y z9RZ>ZvRV<6!Cfy;dsPWaVJ-n`kXM4>g8Yodo#Hf)76(+J|$Qs&Xe}?tcsshQYD=wI=o1TYxx$+(-klAoq%qc3)B21v>rxDrU zUnQ|k3rOnWR<(YDBAUMc#;tq4xEHC4IGD%|ZrTr4SlAGx3if%Q*giU~8=-TSV9IE2 zTTqpn`?%sDZiltvBq7wuge}^Adt7MvZN5{T8oG05J^=D*<^EB63ZqUnGAs&91;?#B zNL#0Cy(6z&ze8)8OiHkGelVOkbuSzX@+Er8&-FxMkXCwF*4XDKE9COIaH@G&=)lA7 z8Y@%3d+$8X#kCxupe;6_xk3q615!*F$Uh?oQGVKTMT7p?{GAR)ADjXz!M2uQ?1L3S zSk8hsI4@t+uEI6ww3p(8{4a3RAoSYX=>-yy)n-8c0>)+6z-@Z%@1ZI=eSIhm260}= zm27iQ8mSQeYmIUON<5kmjx{srS-=D9JZoRF7+%iLejs4Zo!CVe{~kE&)^v)98gd`Vc()4d z_hN2qsyBI*5<4#&{eX|)(NSj`bZwwYgopl)zzmCn(SO<6zTa^`X|f-)ie{hrIT)kI z2oPEWeffLI;Q2(Z5r ziaN?!dKH7C#uXq68{t)fwn6M#W_ZEnxLZVpnWUbc4X5dYdlm5_b68qj|0Bebn3Er3E#CqrF%`B` z)mr&!jbtw%)u|T(8k1D@;mBvV(WS}glB#GBEp#g0 zO4^v}{*vTVnL+T#;amRP5UJv_a`ii7Am&P4FzXD5)5kS}l^Y#wF5k*4JDKng-A2|l zJaWu@^U_uTWPGJ-r)UdpPHUEEZ6QM;=z(i1=$JSbiVdZ|wu0&?eu3z0vib@xQsm>l zF^F@YHuig1$$e1a*zlf5POP?ptD@WwPy5)({l@#)%F_4~Y|Iu);o6((?R#*=L)PjO zlEQ0y#PM<-{qj2H>vX@^gDiWJh2Wn)2$duS^qLHN*)cYE4?qG-Y(?!$X^gd2*N;}VmP+GeobHM#wZZ=6U^NY? zI#AQVCvQ9_&nmV-85XNV1rw6Xf{kd1>*FQ8szSjhLM5}RP)=OmQk8|2Xj+rPW?Hg} z6k)Q8$Es(>|8b}Ms$X(q^wG&L*p7%aDhg#B3GwHMD`8`WCK)ufQv4Y*deBamb1ph|uu_(ll}b~6 z1}&g_+*!h|4cmD(jC?{U%ICFAh5&Uwzu^F&;#&M_jzfOY@pjp(equ~Gcf1l&EPqFk zOStU{?_v|3F5IGn{%*Zhk)Kw}CInfU(;$Lb0Th2&P2dJ&!`@Q(6O*8JZ&DK-5^%EL7TE|=)R}P7 zZw&!YnT+YizIFovKliOPCS9pt_spTkQj=txFbJY@hyNRW4%BCS;>a+KnWLGdpx+>J z?7YXi)C~P&(9A!g7D*r?!?KRG2T&x?g~MUI5o6fLh@DfMG}0WBY=8-K7>$naCKqJJ z1G^+zPfJA^+K7sEgg!1KzY22y_MOIQBs*`Z!`4vJ_hOx?I%<563z%l)5>gtC1My+S z*ush)5OOSu(gF7BT;Px?1Dy=!(^M^LtYurYewJx&9bjWx)VAzq@rTPOIb*~9UK`LDf5_{kQVAr95 z$Vh{sS75{9UqCa4vnd}?czJr+TsBQ>6wUnJW5M}2VH)EbI}%ttLBcHqU8mJHx>2l+ zrkQwO;=bIRw*^e~=daBaP8`r>yU_8hSN4x*(qq3=T%+anpObhQh*lZ zK%fmpB)KOJxli6J*7d-wQ_|WR*1AYiF&NT&E&l0zZ}w{lp)&=mm&yY%a&Ova11X<5 z%w14$sqP_@Wrf~n;U-;n^4|<~IW?&ev||%bTSHH@@EuXj9n-YD2tUGjf_v=af8(bV za~IGL{#|$DB_(xeEsv9A98Ry8U6@kem;?NnNrcyq8^|^xK0jK7^+pS)g&&LCQmmPI z0X`f(Bdgn2F^dSSxCBLhFb8rv+T}mURV%WsaWZ%obt8FxQQG9Dh(}{7|KIj|D#ZVG zVB9J~r(Pb1kgWD~297mW^I_<7HC?OaFBN8kZ;)Nev}`H5I+j(V{h-xpagD8 zG{t0h?-7#)ji3MdT2RPldWla7JI{9;5nR6`d={xk0!?*&cGSLY$pqnW$`Dt5itcB{ zT=sK03^58Vnns0f+Ittt5Y+ji2@vzxag3o+n3J%tXR`_GnP~o?3`s*B@JH?+c=N&) zEarq4Afuy4pvwkU69Gh!a>M(k$^%IYpv~Ayxs1pr3}~5~wKGMrI;(9s zI5Lr?U0`K-82s!kj`j_nX<07T;=sEa|91T(L=FmT@B-}K%Y+Y|;?}4-3g9@qQ6Xg5d=QYFT5k>85S5W^u zUvcy>U}R@tTawGsfWuUN$fZ%hGPK3)!T=Xg2b=!j%<*k}ca|N?HuRW32Gx1eEXt~M zq(BLGzzqq){-Qhv*hr9RXhu`YBAa%hq;bfFJF!@mvsk{q)-L8<=kq~+QsUs9Kd3g~ zfb>%CxMBq2^`gzT89(OE)puVJ)J9~@MtAEGQ|n^sXvz0lI8Gr5UoOxcV) zQIrU{iEzTPR~i``UY8?95ppi_=X8P^yI67VR@BwW@`wiK_!SRG6tVC(y^e?>X`Q2 z$mJqZ^fqNV!rpm06t1`CU)U_#{q}u zKd}WL>SvyR1|mu*I6C7&+T%^7slQSl>=^QDpu-O&_#jKxNJNgZ;=_L0VFy%cK{!YU zRh5O4YkSp3y!_}MldSq|@#h?ZVMYgrnnUDP4`rK(ZcGv5%M-X?Dzr@?96s@F$?yj+ zOLM8YJ~+9c-dIR{13{XVh1YoH@StDyq0ai_&q#K0EG?A;=HnAb; zNfRDMZ~wO~A;{dTsydj>a+V0iN-1!1NH$sc-|H@R0=X1DBGiwEqec!(%AA9(A(D+O z!$8PlUO`6bmm!KzmF%I;>bi>M6akq#HEe2fqP67YBgH%67b0wwMp2fSJEeQR#ZK9n ziHa1;!V|}k*`oV|(ih{9nwig=?jq$^LoJ8eUT$3i8Z94Xy_Y1cYAf5OP?aUuln*Ia zwX_hOHzo5iadd}Dd$6>61$UF3a7(B^-i`RC>BzV@RL^$1e9X*uZ@^0`NCNv+CyeYF zwUGop$)If~Fg>I93>_j(jPpjC0f>1bFK;x&9lTES-6|QMRLSoy#WJ7D;Ly|3=0-Zp zU4~|aSz+Sq=tBWlx+G?OYnr^IilQ=VLPuO8btx&a5PK`$On3Cff(w3o?_kKk_hmPx|B={y3TdHTXr z3kKJrexPR&q{f4g7|G4hCLk6)AeSMC>I6<5X@Nv5_Fy2;O-DpA3vtBW<5#461|R%K z(-C`cL1U;Qb}$Emt5C7JE{?`WsrRrU+d3aPyf>}ke@~2N*p66x10j=cUX6|0vp6ds z>HLHu1wwlKIM0*PEL9y!$T@{`aVZfrA7Nq!fB#5kHI;-StjYCwH$)#A$lV)S7m1kz z&{44ihTGw??(vx9b`HKC;F>CLov(592)30b7*MpyaIn@vRJk1=)NDdid>MXdzR0kK z2fidR12Ru?50DsT^{&8-TB?^|^j2gME=Nh10eZ+zF34YJLFk{Jf|PimnmM>cAb4Kp-8BbXwJ$o&h+O zjIzX)*Yc`dF*G;J)%HAJXX<@~5(Rzc7$~UKoMD}hAo63t0PtRb7_La9NMj&K*5=m~7MU(<(T z;nN+5an3EanfKuZW=K)jvHVE4ITN_N*+pZslS%*FvhMd2@$5}n2Nj!?`UEyO!8(Yd zTaWhsryy#2LC~r|^{U2Dmf>-w@(6!sX|@l(3PpHI<|Yc+>n6IkVH9#b=SYuGAcXI9 zUQ!|~Ggd8aFUHgZT0XqaxQ=P2XNu3FR54!Uc%6C8b`9LkMgO%g#9+D4ERqlEU8uy! zL=LeKtbf@fp-i-j^pRpRk`He+Yt}k%4q19153u(|>duja8LbD&Sh1)z#`IZU%ZVEN zg%S!=SLoO#6ky}TOzV}gNaTDA15}KB5Y5z5nV%jac-tjsd6c={4w_FmpVWFl_Q4#g z4zHc)8%%1Bnj2t}tA^xwQ2T1}9^T8y;}hg2Z+IElHf>SnQE)u41gtvHM%Pa~M^6NU zSANf;<<1E6b%4};X(8GvV%_H{JKQ--qvfVn#43Pcz~xzEZU!X3|3r9A^^oep%SadD z(DA60FjC^t%uvze8X@}nfgE6*K!?y$<{&8Kj(2G6CPM=ZToXcul!Sr*O7jZV*z(k_ zB@WYW4|B}IN;CB^lYmml)Qm_mivSmByn-?NRQDojn)-ifx)6v}mT$W1DWbtrv!G99 z^MmvvNLgzigi+~gnz0Tbh6FA8@INE-q{slRi3P)6__Re*=l1V$w}V6#tAm&VL=E5| zF#5a64oID9l51qt8ukU3@BeDU{&`Ff$f$1>-4 zhfMCFCwG2NvYGB0#&v?OW@$d63EG!d*w7|WUWA>Louq&D1Xa(LvVg6*nC>XV4l|r( ziasSiG^H zJtK$0}dX+$&kWX$om_^9#@lAV2P+M8XqC;m%qI`qOa@pN1QV!wiU zRMu@`@(D@A>^P_F_GomoR9)S9f{-IoE2mVc|8G(8q4L$asAwBuQ`?At{d+ppNiA2yp z05uzMLv4}@qHX{i%gcdWi?kHv0o1fDw^u*tHlMJ)dTRv;pFXn7M9Kw6OB*Ge=Cx&4 zv$O5RH@x2BSxC8719^++k_8ai!8wj#$~%ts&fwEP*LSNjgV6XHwG6b*=_?TtupZ&~ zq3S(|rPnYkMaBCWjFV2i95%8?0zo#fhW5q{0l-%tVR%>NDm|HcE$&8z%>&I@KsUu#n2KF?v6ii8Q@B@duFXjAE@Bw=I&oI@Vi3 z-p$oYaF~VK#-Ohk#IOF5qxl*YgC09|%{mqBD5P4vPa7^mqf!biyB~du?NtQ(S4@u} zQXdgVnoCOsEzwC)Z0R6Bf&FS78O1`&2tAh`m{7OM&Cm(#Cq(_u5jdYz9|?B#Insar zrikLVg1YU{6SpYr*H$Ah>4p;kiBC+h-QSOwfg1FF>F)o&fXcxWHFOXzaeM-BMdM*TZ0{o%cYze0a+~E1*!lEu}A|on435mT3?V zD07+5Pj<)_xDl!j=Wqc`Ziu`VWp>yQ3?#W0fxVzcjDB5*FU^u%c=M_6PnFB9-S6x~ zWC#`(fT9HJhh&O#Q3*F2W~D&BdwGpaP&qW~dsE=?SsyLM#YUW>c>0$?Wk zlkAYHB%ts8Wc3ODeNDg(tLo`%iU8CYfY1*d+Fe04RngTBgecXQZd!0fw2x*oQ!@s{ zpK~-7!4?8a`l_vACa`{Q5)8r#z0cA(=d_cL(K1Gvyumjd;s9&U-~JVB9?1Xd(3;Ru#E~aD z;b}9p>+?9!_LQrJP=jq_t%WcvP_PxEpgU-ABC=@M^Nlj>^p&lx;~G$;kZ6g<>5fK# z2Ejuv`}+w~l!3BD@JJqYFzbnd$0rl{+6fg;z%F%QwmF^;x;7XqZC@Y!Rlx>>1=wWyq-&6EnW{7FTj= z_!;f3{7!Oz#Egg?UBKVL6d>wgTEy21)m$XY<#UM!o2qFhP$4~n{1D)vHkq#xEezu^ zwZDFkeWOdN$V306hVzOw%{_wXr43T>q1a(5Q6@%Gyh9cD+^QTQp>uJU{?QDS`IgX@ zEY>U@UAi{G(;r6-8t|67T(oNz@H~gty1$6?h2lcm#DpGzpDxo5TKBmmG_+xaQ09aG zol$+tzKVLkNAEF)xH9(TC@pP7bPvIYIgwP~Cy27h(M<2Dc;iGemYaR28^IZmmVHHM z&e~hvZAQ2J^E}L8-G&y1Is2lsNO?s5ArjLNQUM)2XI|42B0(?mDKIk)T{u8Y>E$Ry z#x{R?NegeC+0&!`q=OQGm=+Pa2bM zgt+)zMX5?7<7%mr?fuRTKWIq^F%@nFS>^TmoAV~Rqld+GdjCLXF?5)#>%pKfrhD>Q zVQ*D0-O*HKEW5=lp%KpsvwDVdZ442gu$8eqG*5>h5f4stU?wR)P%)BW(&8v{qre1W z3Wl$_3*ReSbh-i$uc&dLp#^vJw@PVnzHM+Dk>cfacp~0aPm#x#cyvQ!ZN(RZlp6W` zfrveQh9j&?Db{%70@eIM8{d48V_bJYW3DeHIoE}$q{G9^@v~J`lc?f1 z90m}UXT2-F%A4#V8i9;i=3$g-EPK$>z{p1|clWX@$9^hF_?4ci`9|suCY!PEr~{Lo zpQ0-oT%9}N(lZ8xlweY*8G*vGSt1;LPP2u>eaCp^WBwH~!6PH1l4<72oSibsuZ+@L zhWsy6c+6O4WoD}J z+aTQSp+@E%Phlt214gYxNDNx<>6`OT%I8H)OCe)iArb)(+IB(m;-;|%c*$`G0UlsS z13+oOGTTi#8Yp%pl<%cCcO;B_Su#!ydAy^HI|rRVl9aEAW^dsPGw zsdxb#e=1rt5~2m)lR3u?xZ8b%f3f*@naXDO|5TCfl*A0*W6R@`E^BG{Kq;vq{Ez)V zi@H(E;o%KQj_@%yzhA~}TH*{|r`S;aFAns6>af6^Y&JRRId=b9)I}|w{}Cqb75Z&? z=tfC~@=n0=7Z?RIrP@(^E6Ak40g41su)~AL>z;EOpY7A#W@UD)p-lBYg5;rPPW8;VkwaN2LY>qS;bGZkxd zome1fh2i53;sgRyFbkZIH?SnRGRF8D24b(#cj2qD&!ZJJO6oE*5%{%h@&yiHfw~e_ z1_Uxn!4C|A$IN4Lg)C#lZ%b?iDN@87;5IgDuOz&9VE~z z?{RrNnhr_=^bTz@X}dXr7K0|G%>o04yfbFAd}rv7 zaJtfXwz4klr*LWCo&mR3ymJaPjUp{23&&9q5l^StyFQE8#T-Npcfj8PnAxE$rC`@P z2$jY(hy(YL@J%L|JJOR=60oBSMGx&Q6SihcRv}}99m~_OOD!xkUa)kpYr>SaxL}`c zh|8_MtW10^urr@;5)$jdGKlp99oq6?B^MEopz*XMGBYHH@^iG7Fm&RAm96X!(>8JXkuG{rac!=1 zsOaA+*_ps5Rk_*?;E`)VAD8hUF0Ub6?h{-m$G5snZ*|VyYMk6^IkwetXsdC~R^x=N z&T*}V(^?H@wK@lCHBQs&oYLw!qSZM)vrm0UnMdVDUYb0cl8{1Vgl%#PWbiQ;)ZY|4npoI z<%q)qR?iHJyDMfMnSYmYc|Qo$yci$aN4-y*bwtCC2?hRhWt&@nysYC{%F+?k+o}?+)OZ{!>qtStDTd|& zbaL^|B2roxuzA!5Rk{CdAURXSGMjZW%K3ol0o2c-C-dk8fich&W6)1<9<(ibbezxs zjJ$xQ(GXeP`b(Of*d;k^U3SUQqED*`~B_39n=9j~VD6$MBNcN;0C4AkjxvJ*8JqaG*Hi+H5p%6f6U?<~+b%n6y$8Z`3e zg=x7xlE2?~n%=SP3*4*Mn`2(S<770apdit2UYe63EsEzbLYZV|GYJJ`zq9=!Rd2^;Wv6 z(t))?h@m_5sOe*>?2p5!C}9pE=5}^?r|_G#9kjL99K}MEAZ^~=P}Xau;(*|5gPGfH z4ZZ8fVMbr}5Nw&cy1!l2hjY^fVc&JJ%+kQ?Ss@whq)#=sT8>rQK@PcPi5Tu&=Fn3c zNu(Opuq1JZU1F_cHV54s@SAwXDUEUCGk_MAL+=UvNSyryMHJ|R*F`7AeN&}J0Iinr zp>oUC0p2B+H!p~h9|(#-b2Dcm!akBrx{?4#BluVM(yaw=F3WqOT`Q|$?_(CK$EMdi33YnWf~?`C&ixE!>-L3XMq<3i$5yE?+f2FH^I5|BcT{;&|R zx#Wi;lNws^e-fz1!R8MVK6Mtlat_#!Z~V{V`-y4ZteqjTMw;OM<*Y`46_2UaK+yM} zA$6zo($gV3#)DFpP9FIgZ5pF)+~EOPHo9QcYt>6Yojc)vjg|a$Hf?sMkE}pv`7bqw zDvl^l_J)h3#Y1eq(H@c!(c@!Wv$8yZ{Mh%iJk3GQQghuQ+)xQA-xOLyDG?VsLAH;d z8oCy(<~eSbMx&*enw(KLbw$hi-@to;>3^SZ6bg*#S00xpS`*W0g_cTAnz8$v7_@Li z1Jy4Px9L;H8`Q@XUC#glJMUny> zKc)c1?coC&pd1COIC#NjzB3Ex+EpQT4u2t-@J@Y%bwY6K3V=O^zat)gBVA(|F6I%2 z@8cm`r#*@6niMhU%Rz0DUs3O`1CGxQ)Q7=*WjL~Nj^LJQLpFM*D(#}FDb$}>i!9$d z`KEkOW?EIg{XnD7$LVzba6v9N(TMRRma-0HGWLO0<988>V(ouWBH5AtkTZVwK@YrB z4_H)wUl(GezCq!XAkxDu@gTDFdx~YO*!eeR6zH}CIpIgom>Ly7a*Nq*JV09QW1y|z zhQGGVzBNdAj2;QI2~#1GoKTFR@4!73(nNGO*5I?9UNGLp#EL_Z)@@gN&*4dWVP3oI zW8jq~elJ(dA7Qz%am8E9g5V!&@FiMkh(xZUx6k#>YU?a{|jb z1DijrpwgJ~+YN4WN1)nd8X}}wKEP0?w2}@G&B#(G#~IB}3Wf!!5m~1KDfDb}-BB9? znS?buBK;(7e*vgEsE5B&R;^zKNMW>0^U>fATtLA|C3FtNdp3+WY=MxyCB-jwpxLFs zv{f^j?v=|c%&*EqnRT9_f384=97Q6nqr3~+4kWf%0oN?F=LDh+#9|7XHHEsN`lBxs zwej-1XSde6P<6HB;YMl+=T=*3y!>irSpPl2^Qj47Aflmr*{MRALI??r4P}6gV)nkx zbiE7|qvez-RZcZ^4YN{K#j$_P`HSv$l&cQhr^*gQX^BB;tCiA2C}kQ92RfA;;^XM% z!g>%MjK9n%evI^?;9H&;C&zgPBs9apG;Hn@F3FclZ zr|c^X8Q;uE(b)#4vG%lr?M0r4&K49=ap@tQwx9abzy|7AlNUaj>0rE+xFoNw1FsN&pdrtH? zWuGw94-J-5rcG!MQwAS~pk5RQaIH$d37n;U5r{}NwBu%AKBf)Pj>uK`c7KJkhq<24 z4xi)=!gG4%`zU`x&KgU5j;c6Ku0mReX@BB^LtUoOVznzQ|9N35e~&2&aE`*o4TGvP zuy`nb7_oma)Z60%I_&oET`S_I2Rs}k=0sq*rr?qJH%pfZDN4r?zQ=^fM#^130u7}* z9l=WtiaS@v+Ak(TwPC;pz+Jt_yu_1J&-(}D`v$iFaeXLc+5vAqTK>Z<|Mui;C;xuu zF?9aGl6SHe^l#-%RNqd(P?<%3;ik; z<{7yF6r9_r8Rc_xWMwg0=Vb$h$JyJ(&k_i?wq|~$>)qU+TZRl+4a(qP`xmGQ#sb6zR6y?WhW#s@6F?O1AD0M0{_OCY*$?gk}jR8w0r!{$o#G2{)tF zbu7Q@1f7fm_X82L^7Zd{6{t^^@uT-FtbPk)e_>3NIOD@jOJ=Wy$Yq)Y!=AH_)(m|!aq9Ag+TI*Q`b(* zrRbv7K#rXcGrEWHr-BCZ)Y)6R)UcrWNtrPU?4dbbj54!&eN-y&5c_w-TZu_gK_3Q> z3N+6@@x|{NFtw17fE*tPzga){9K-NhW|3`7vtbi8ddP~zF$rpkIGGb5sq%@PFwjvm z&&n(wM!AF}d+ zXR+*swgdqjKFrF1-E(dRbu7~UjH!_SzxzTeZ~1WSVXk5nEv);6ysUU5U=>+P8&Ba$P})ib`Oa@$SLnzbjvc*}>Jil9D#WkjfBNkgx)bf#~B-)RE`2 za`&H$y8t z7IB&bknoj0j2S)hL*7i}H%0&Znf9(`2pjsA`>dH3ASV@NjeeB%Km*zC_ zp^{M$a_MxSqWLkkl5Y&c9VkL6!7;t)f*R%)&l&n>z9lxx=qX=?xvV~AB2+uT3zswET=tJAjf;uMEi{pjO(YTr zyd6y7))4(}?W720{oaV>Ib>OsdX;-kg{ZF^Sg}*gFgk{Xgh7*GbY#Rw10YoP2TY?2 zXaerzgwrQWUjHrk>%gLoeqT~EhS6*OrdL1^WF9U!=*_rnTS9eC;Vy1=JmKg*0a2*} zssRD#>!e6wF~nbnHqr`QHyVUUVda9fc z^^rP#+O8P-d#kjBB1K{#jjBWWo+;uC`yuMJ7_TxC;`3ErKxlm{q!R&7_MW!d%_%S& zox$6YUc`E)M$B-?x`|?ZsbLMex760%BZaS4Y9J*ER|X#Pc@UA<(CwaiV!mk06#=5)cel8zfH@2mYnO$fWmcz(a~+{O2V%Aq}2b zffVh4zmmFkVX3*J=Ejlfgmh7(Qjf7}-2`isfC&Az#}x!w@k;*g3R-9vLEA@2gC199 z)u`+~)tP-X&y^JV{(&Ivi2Md`V=sp?k=-EbOwX5?*L;b``vq0`EO05lo{#``JK6oF{; zd<#XN%Fj1h^$u!?ZVKqoQGd0%ez>X-E6Y2@t}Op|4eSWs-(4k*~4P8!KJFXfvI zcOh^GG}yd|YWUhBKwsvgbCc?3Kc>EJyJ@_ZA{($ryf!F0i zogrwIDdPGH!%4;)gNprbfJ~BU#Yi988J<{ZH>P*U8B8&I4%) z7!ZjGu~~!z@{Z@96#G0opUQ`8)9J1FM80ur38gD zOm3|Om)?6feV{f%u+?7GgzcS5cp*QQDd6z!g!%{bM?G}!$aqZN6?zcm5NxGCg~-IyIZ1OB7BhOZ9+V;|Hfzo6|Nw)AwAqXrzA2KHxy7`KQcFfU-b0Xt$b1E94doo z+A|=LtTBD=qp_a|Y`){ar~b64x;&XwX=@NBeg6&s_2FT>;-V9 z%af|j*|6J=%sPBDD2cl<_9yUIY3-H|-&4hWuSIRSz))@bWT_+f!=o!e(4e6eao+!> zV1DVHg=nxGVH@rp^Vd!sV03a!0*cabG*x!&t^D-sJX3a%Q7`VuxjY;0aL*$UclT72 zH6RmiS3yMf=I}In>G(1Dx*FmWcAHjT1C!a1ab@I}V%{7~E_{`fNP|ELYaHuA(EXxZ zr1fh|K7ma@H2x+nivb3Ude^vrcveM-Il-C1WETLeJ<_ASbu9vE!YOL(;wV~aI-7MY z%lUt8m#aWA`Od$o_#ad!e54JV><=d$-ZnulBhr^G{$;F|OF`eL^(#6gzJ6=QTfFUh zSa*})VBmLdMzP;R22N@|HM%{Bn0ynA<~1Wi2s7N@<_Li)Di?%^?t1<{s)~j?DUCS- z>I`3j0x};4?bFG;up-#?nHCM^M8}Vh%yHKg%Mtgq?sZ5y9NF`@9oHa&Z4|kuPsIaN ztkgcZKBu0rs9^fzw5ZDKncMipiDL_$Ez^QEdo zF2Rb~UyPf??@;P*uyIff10kTX{9_iDvrXboVYwnz*%eMX)ZolhN}yoSC*{R7qAa z#KQ;y0)~P|PnP&26sgqSelL)DmgSq2g#X^TC2r?TaO~5|mia`>I3+p)m4B{$7f^Iy zhygFd!3zOf7y!?uF@6y|qHdC}Sc|XU zQJ{|Lu-mguu$BweXigvanC#uCXW}VXq1t#-x36cU1o4f-*bkZC{r$_Z@W76iVu7e2 z&@w;{FZ@M#-RJ;x4CEhF9qj#GIo@sh6Py9Ql~KFOKTM;vk}q?p#_`G#^9*MX8W-1b zhf1x$`syr5`U2(!ybbg18#r8{3a&3VHcGePiT5YA@aAC19Qml+8UauhqhyOG0baGK zgj(92kVLh$s(85AEY8%Alb5bOx52?Pn1DMYsualVr|SYk1>s1fuSqJi-GCzP$s*P zXamxz%_LCG7vW|)UD)Z@W1MpFs86{1gRgi6A}(D=c-gNOS3Z{}?+Oex;KeQ8dqSIt zg?GF)57;1cWUPpqY}^6#vv8#se8#exX8mTPMaODDdTm5Xq&B*Vswb|uch|%~ok z6)D=0IsFNehI@>>=!tPPHjct#KuuA?k~A%)Ys7;nxUsHL>=}+IQ{OPq`mcS3ZnQ2$ z5a0AdYt*Ok0k8VJE&y3TroRs-pUBZGn4=Eai+ax8zx(P*Nx_^sz*;oaU86=X&VP-l zwN^{QbnVe+Gf3SJ>nr1mGkxi5BK$*bk7ANKP%Ng1sEe#|Ss#%msMLyqzc%z*u)U() znI5EY)wMj*Y)aj=T-R$Eh8vp%q}qM%Y`OJ-n+T31r#c9o%ne}zgo2b@-(^pSIo2dh zju2ML<`C)kXqx5~Iz$7EO?rT1;($1+M2>omxY0+X0O5>SH&*RG#_UDo7>>Y^eA9ElwkzJ}AR8#fD_ z0ZxMAema#TBz1Yc zj0T|*9=&`(EqSgQ-qm`?8e%hSDsJwCZwlE>Mam$ukMx|%)(GS5kmP+5Z()ZC?W{mS z&@x)75-M>cnhWkPi`wy2oO?*!ajDFyc*bQr(zNbW|9F;r6wpuU_zoWjQSLe65vn9> z-be{iRphJet9MPCVQy{FU8P8hhYVnQHK~J<$HOVLsnHGz+-Uh2&2o2?V_3If2Kaan zHoY%PU^X4XV2Bay!1U{f{T^E#G6D+$0IP>6CRws1)bMXCNfxkR4U>nXAN0V^zsuFE zQB8{Hd!vcBZ_I3;&h^|&ty8C!yk5Gh@R{K$muuNPCE)u4X);DMrl+gYqlqEvJw zyEkzVkIyjZivcbmh$9e2(Bj|5Ig+7$MTI)3=_9Z*XE{b&U_FzdLo1d`RMTi~;|rBa zPUR+s(4vG~Mw*EsHvq`$&TDf4?}pQE*S!g?)6rz=>X#ax5cwsfjOwu~K1s(DP&4~- zE{*$B0x4@zdKWUa4bhc2YPCnx@4g~*y(c69&)9BxE2(|sTw!ag?gJ8PgA+YWg(fZ( z>@;x#+J@Eas}dEAlD2pRA;oGz(g|3MR5riPGtPz4hcuD)q?mJhUoW z2YlkeT1_J^&Oo4%5ttTMyFuO> z2=wUMEy!2sVP*|QRE9*EYe-VyoMs=sXXu_^P_KKbnYwAFWu*)PF?&<<$M%{)_3 ze4O2`XkdJveBtKdcfpT=c@5me59s7mZ<*S~tHjjt;md1!>T;HfUBGYhX}lkg@j^#6 z==6{!OdMeV-mJEG(9D}KAQ&Cd-Rcs-?H-p8!UkIP{rh0SM=|iThjc+}L+gQ3tOUW> zRdyPsY^1J{T}M>CmjZEl;NLKTS>Qkl0XNGBcx`w85%5(TB>xpS+0sp&w)9G@q7AuGCXU1t%)|C!Q*b-;L`I5AYNRO8dqzSg;9qbS?XD<$7K) z?PtbwPBMYWmKeMuu8DVrPt}9e%19-Uv~RIyFvt|?QB^0NGSy^UD@!Zzs{;8Lw0($$ z1`d}lz1tJW4U_r8m7a&T9~~=-*MIiC^LNgk$zvV5vjAc+ zy%8@kq@@n{4~1H-KTC{7jIM1NNn><6I5#W)R@-VdZ#JW!@|aDq=vVm2znSan&{Uu- zVE?Dh5iW|T=8uo1-g~vzZi~rY0pkuV%GR+#5OdhH$BFt{*J&9)tzHH zIwCy(14(?hS#PxZau&s>ooW1O*Q0Z|mp;$Ui#xfN663%{8O^aW%s;0sOXRTpQUPm3 z+8@F~IKf8Z*{a2?zmF*v_EvV+)YRv^F zn%haeS>5WJiGcBr5x7X-@Sr{)=Sfo_W49($)Z|;foP^ZhNNF4)c@f`|GCN-FYb{ub zmOwSN7barYf%^ESBBC;mecPfdW`EQJ2w(POuwE_HY|fE~;D=5)k_CjQwvbu9@Z%eD zg?sEx#=1!`Dw#KR1`^XqH~sK%_-DP8)~hr$E5Zdon@NTh<@Tg@VM;SVIHM9mh*UTv zxRA$n$a5a+SDY7?HDx`+=9C)Lw_9p9xLA)WZfzvBPKjA5pxsQk;rJKckuY>NC zRB-e3S-r@ybNakqK`Pxyy98M7 z0gxt^@0pt86*Z(71_xL-vqqoOlbyaLMhzN{pwSBro|;hu&Vl$NA+d#s6iw&hvM`0% z>=bj{{&&Ow_M)5?sFbo5-H9FMv2qpo=NKJ+YoV>gXcGbEqg&dkg3$8}|v|%gDfp4P+vS zMt0Ux-~$SrgsEl)P{-4Rqd@Z2xZa8ZY?&>=8JtMuG9sNsGkd(m8HX9Y_Cxd!kd^kN zxc!f`V$g~mhzOSa}A%piG&RGCwEctCzL1&Lw*ohZLw+L z@woEqidJTgQ(A#gX|H_@q<~1%Sw6~4|5+Cj>j=6^)zoby6I zw-mEl`Gzua5&hlWP?L!2853>jWT+5D7_m_^`0MezbrB(=d9dr3AsK&vK6Wj>E@pWa z(iYUST1RwYLdNKng9^@AgyX|5s~AZpS*lo+P2|ucW;X7F6ZG`CK{%aKvk3C#9vJlw z4YvCsl|xKU785VM4^SF7eh^5>3IK}BWR2DYELn&LaEZsf7^LZUzP7w@>X!Ot&a+qm zXxA;j0_r#*Jx#~26KE%F#^`QK;g|Hc!ehU(tQKcr{)*T)+!$jjMyw0Qd99fGp^o7~ zuj~OH<`*@Aus_cFLUfS<@NNC9R>mEXKR0Iu^9OHCjsxp8Vx*jcT$jwjw$AC*fxoEG z*$z%hPhf7sx~D>#Ssm4GlV+_a8By<3GFV1Kv+;}pSANJ zNc90i<72s!nyM-d_2KUG3uj2+Il}&N_+!tPYHfixB;X4uqbcN!frPk$51=0M2+kBxMi*4=p z$&9BO5YS9lf4WgE{6nSZwIX8DX|4Kt+%B#1uxQM}kP@be7CQ|6j~1o9MlB-5)tW?Km*#YO8f}uCsWFwlC4Aj1mJ+I}=vaiwN!r9Db_>|}-)lBqd0_5> z6%D}J=YR(6Pqf|E6(?^dLj_4>%2NJ;z^1bjqdJRRYj4)hj)0RwXw__4>1qWg5HTTQ zM;T4jlbaZ6d{{f5X?G^c8uF6I?VD$Q@N*djn&N|QD9ivYb|LAwHuzIdWaL1ijL#{l zBR7Nk^g&{5Fz={lVAYY+DfmXw;jGAGA~tEHK+kG~Fa!j2Wq@AiR&d+!MMU(L6WKdx zJ!yB`#Gw~^uVb@_Vs$iL&+W$-na>0E7B-MbOfP}+aIf`3=_1M~)ze~wXw@+=3~D|K zNZf2G?tM#`txiWuK`CYeyxpk-HGljP9EQ1Mxy8b=4CL{f;Q}Z0OSnl(i`7O06^hZQ zg}LlSDsf*YvQv`%JIH1ow`(Mna(8;Q-IAFZ_OZ2?rmYMLWf1&+y`+{rHsa9-cTvb;4@}f6PBEX3v0!0Bz1?%h z6wlBO!2D7WB1^OfYb?t3`HU>_nGbCm`UokzKh_K1_$bVd)(=OX{7>C2 z2d7yX9loXQ{j6A1U^PYe$n+$5g02@KGl4ZgadDC3280^{pG#i5o;$106*`2Wn-BM; zO9Dq2K6ZG9{04apNpsMf_*b43Fb@k1PG&m^vdR~j)I%6AGAqQe-Xr8(rw)sRP&#rx zbk%GCcBueuNUYMV)n>~vj$DOlIn%AcVaLFngQ9Rn3vERPad<;L@0f8nI%XC+1fs8C zU@cflZJod|0vBB~abc-NMFmx0Ke8L}&3b_YuQyGYww%Y-;=I#r{JK2}kQ?mTgTS)S zlT71TN=8lG-68?&nV>BoavUP6hWNQoJ4BAF9@{Tf_%kM>$`a7ajev%d z^Qo!OZ-n1dxhu& zR4q&K%<*jF%J%0`&%0lov?*s=kVwV4q1djmdqgFiyEMFBS(d9yYIb(Vh5xp%s8w5V zzTpPvSkd8S3Yd-MldHX1X6CR`o77B7`9dk!oy?FB7vu(jyiXhJYvE?jft6a?xUjw+ z9|Xh=2*N^%EuiA8qo>>I;kofCy%8o;myOKVO~aF=6pmjG)Q$sa4_TbHOS69+k&aja z1M?;563pAUl=qxlwvInqGLo`xawRQ{7fk0z%nKcVRpvaAPC173BUA6MhG$v)P@oR^ zX8c!YK)s2+rMWz#XiQeoze{?J1Nbtsn6FjzY)6?v{{J-so7xt*g;*$KashCK<)E$F z*YhqhA@Yb<+($?mP`Dc3mM&?o5>LHH=9o&#;F3fMjHxd*dJrY9hyU778qJ@_?u8TYqiuIrggB4(m*0Btl-AZR0j{$Wu=Gd8wuQ6 zxwHc3U_;RT12k@j@9h}V=pa&Q#sIWuZB>t#O!bJG-Qv!}8>n-DLXd8HqPmfi#irOV za94+=+rL@X(8i^fa3#{T1nAhGC@v{X+&kes?4?zvY$Xw4+-S&@e|)WEP*ETcCnhqZ z-s8{$@lwXN`l`cQq%f(@qre18XhsW6C7pR-?B;$M{1$yp^;qCG>fyzZ7EH+$0HDvp zP!bNyd)HeCIAGEtREZs}+qh&!S2n^MpAZrLkM3}La4Rup2tH1ROAwd?u996eeE=BK z>?X-@q__OU@%^4179L1nMuIu>tq4az$$Wu&K>rWk_0O+6&h6umOzAWiapfC#@ezrr ze^bQYKU1e!WFW>s0Am1P*Ad9B&Y`risc1x)@dH%n-9XV>9Dtb^I-}Oz3KW;KzokEw zBaD`VLiTD@m;d+?arZ@mrEZJ-ET}c{ma29C5tb}ur9JxT5m%wu^w&fmZnNa0RO|CP z^h_^oiZ;E~{qpnk)Rp1PX_*_wv!8bJ(PbPL@EoDS=k=a-D;g7)_D!s>4h){;gwP`? zej*>S`Hrv@KmHkVgM8seUJ~Onu0U$)5(amyYu6fM*RPf0bxZsECjobD`AR@vw`%rH zwlkW&E|44h1aM-T9&3l!!6gmrz;0My06(5m#3k~kMO)(|Z?#Ss;?#!oxgiM9#WZg0 z6-&Yc zX5q8B;eP5Fo`(iSo~<7=2f;|tGxBxS`@C<%6m4UlC30m{X$(hY6;_9?JTqT?RADg zc|Ag|NK;;dM}|vAa8I}nRC<$#&uq}Wv1TcpYolTn+F6-*ix?R#($;*S(uRd`gAf29 z(V7f-ORL3U9u;vg}ux0^z7?7fW-j&MVozDoZP9; ztgdxNuEwHai`BO6SeB^gcgeV-I}B(?tL79qteG0)OZ@iDMq5~C#A*eSavL+BBgA~u zq(D1my3rSnygb1OcJQBp4oMtt+=O*1T%Rflq4m)c3d;*&A6^skdKw756n1fEP=NqRIw z%GGH?VXux{2Gv{|^6e{4ymn~CFV*n*)U}&<%+v)%QZkYanJOuUriYnRv0U^fkTj)O zl5(!`^lTEKk!?G3u_cNE4qgLrE}M=?P8_X2Ck%vxfAuq2FTH6aZ@cjG1wiip{M{gC}7q(U{wk1<^eO~N((XkeDI=^KJF`VQ%w zetBp@P=)hJlmM=aof^d2K`jAtd91QtPssJu>$-2+w*2u|Q~OQPTunwFHp(U9wT-Wk z4g4pmG!oWJfL7m(Neg&7f}BvQ`Cfudq)9rEy@FubD*HruAEGn(b|M6eD`W8B{_YHB zTrm;dnp2o{$9k4hW=P~P+sQAm@9PxB?Y#}WxUw_M->|I7p1fLyJ8A{t+g`$}iPw{IT-zx_g1<%%_7mp~g z&`e@8T0`{V32~iPzt#K3a~lf4+{?I|SImd?vjJ^--B>9wI62T-_;?mxP?J9E-k}wBKJa zjWH zl%M3w?!`SSQYgpRbI-k}_J!h8lYn@IX-&=l%GiH{A1WXt1dPJu9uXN z2`R2Z=)#83%f3S2wgm;maM6&IR%zY~aok%3+H2O=6(IT)CQr1Fs@<`Q6uBg!PafA4nPg@P$5r-*ifhjgq8&~?wI(s)iP*Jcmq zp8AGfsM2nXgCRe7#%%r-X{{(v8+F(93?;W-I8Y!o5OsOg)L05S0;q}>+I?T(f>q_& z>nl+?&TvI1x%D1jmLb7*o9&O(O%44fUniwYjtqPlz#H`o5^9Pt1tU)hoNzHy%p$vQ zW*(8q!)DgiBDFBUVYNtCH@QSkY;H>?Af{{E?Lbo{lYT#JVA6C_ZnofS@{*cCtnZH( zJhUk)B*oYtGc`=9UkO&lLDu%A@zBQo zcoS{JVb zSy?c6>4S;_=D^80F9MzJ@9vp8Nq2(WepOjc+eP)Jg#$bxm>7XQkUUl_i$zdgxOauS zmF`csoohk5UWykeMdB(9*@8_h2V=3fWp@j~zG^qjvdPCF!`|=@-985q7%4{N;z!gE zq#0+R#LE`gcOnS&_({{MEqc$_Oe^H{eb@hPGb-jvT3%+ZTI_G3I{?KQ?2*+?Cj8-H zzn*|_Y`UCFqR|e-UeV_>+}JGWRby+0*}dU&p^uX6yH5e#Jc4XwY`cNuA@|Fd&Qiq^ zGn7samN7AI0bsYlvIap~sZu%DH+D)8gV*Jy`@?$k+;XA_?}$>81-nQ?tWL4*%E1kh zEHoJ9aM(QF6#ICylQ|8zDfAB-Y7%v{=o*A{fGEc;q!ZYP&m`=w;hi}xbP{ym45 z^BY#V%`hBU0pw0~8rVbDa*>4WHJLc6)P>x4d=7tVG9G?cE(z(#(5W~57S%kl2g_L}ZWb2$DN)BaMyE0m^MI#Q`>NXA>J6yUP~Kc&c_eCUo}a}iH$oI}nHKud z@0Am|TxvymH6fM=4@Wg^j%Qy>d4d+O{^#;xm!@`-lATfJ*gfyZDvgrP)K&JeY*8dg zVa==JIxk;p*QBq-g4it2^Ieqgl&QZI{>?k7?Z>HHhRJTpDDSj!*W+FpP{?wQ%RdQ3 zoEb{i#k*YWx~T&@b`(B%jULL3ZXByr`%Ic(gT?-JIc2XQppSrOSC$cE%z_HuyM`rM z5^cjC)Iy_XRNp8|Y^LajdWgn^^wYwi8K?`-1J?N^TPCJE;CqOCd<%f*PI$UxCccts zGudYBD*#TAwl2Qhu5IhK8yBJhsx7$QST2bJm(ocDEy&A96-u((W@E+0qJxsraaagL zR?YvTp`XYnADtc3{&OrFu5t|=Ao$AtvsUSjgQ`>LzPe*jjV9j;D43a(<3|CH^l{*q z1%mC*L;gAc%Qf#(0Eg2xb7IN<=OHLK`N7pID~Brh``f_)VfbNK<&wP@q%EmH57r3( zMRNg_gwEz<5f9I}Ws#-HSAbTMRNksieNe>U1dRe(+Nj)!yWI)&1MM`;V zvafi9k;QAm1}(Z;IdfJF%4@e|?#hkC)nGhM?r^2-zfUo(sTM`0br;Yk-PMN(d^SR@ z9-45*bc%s&pB=!qBoji@X`5|b77c~pcLXs?WD$W?lRH6O$1d6)qE=ZLgc1?Xu73Ve_A`*D<_yxB-;D_M>2>L0gb|kw$V~4rmcYfA;`% zUch~M3t)31U%CBNhrDPxeIdP)zHA|DQRQ#2`Kirx%q(X58^70;xGV6j`cW*#MAEt| zwYgXJ&mf`k0zRyPGoQWMb#DYbQ5zI z4SZPTnU6*o>LzFjL%vE!N{{TqmfAr0J3_I7SP6+yc%`Uo>8KJp8o@V)Vc6LKbmB;*^4hY4iBM1jsrQsdHkquYG7it1O{A zH0Tf#v1g7UeAeI+{qt-;V>ENoc7iuodRELR=w&k&fZ((82&Q99#Ux7G%yT*s>LWP- z55+{%r6UON11|uH@{TP?623+s#-VE=L6}X;UB)ocB6FgX- z>HA-lgGwk8g?Ew{$rykjA}{4|z`2B@N_$(n5M>=LXZa_#Lg2JIsJpqlEX9?dP+cav zW8TBDDe>9;41`C0AW36MA7p3?LaD=RPqxM_(H0G@%eb4RRfKA1?kD!|bq0{2NY5av zAQEB;CZ>IBQ;S(J;~ij~vnxZ`+)@SG{oIL9{S91B8}Oh9be-_0oXy`%R52lI44WMp zk=MZd5wPG&YC-SfZxM}>GOs9^M`%!9%R1B)@7rnNMS_oC$4dSl(y! z90d_8Hp5|lBtL3LNQ$^qsu5eJ-!C?p1_NbLP#CQ>ul`_Rh#;Xj+|IDAvVQjy3Ux%Z zMz2Xe3_7({E9t|ZcBYk}t(QP8ehd1QA#TRq9BqPQeWxZ_8)2Q#97fr_Ky$!=cvIs{w@wDq+?e4{zCje6%~@lON@! ztJ-FTQ>%aMkyG^8py#ieK_NX)_7FpXJPeiS!4$;d*y&8lwVdjH6<)jQ04PWg-b6Aq z$--EwI3}TM60f4jYel`F5wBJ(czvWG5Qy1S2e~wCYbnXN9nf(APA%IyjBB_t#WUTU6%*E0&7YW zm|LnMOp@O&GQGz&EC@-TOBcosL(HdrJ!4E%^UNKGu*@$5o3B|T>U=b$)c`iMMGu2r zg@Ow&i!Cu_sN7T;BlVW?ZS+59RQhJ}htjYsPuFZ3?s`ySjkBbv7^`&UQ>o;j)$ItF z&iPj#R{mtIdLqSSD1r$KAPMIbMAK|v`L*8~hOhVve2EY~#`N&nN)W< zG`GYm>gnwZ;*5nHZ&;Peo8VDgiQ2s5n3ZyxbY1Ht+U~rj#)JOhWHCrMcTOQBqtjl( z_={A^_Z&%+HJP!-;FP>9scM!04A+}6=D82{I?c~enR3yAdlQB%<;;8cc zVz!Q-V~V6B6uWWl#d!3Iit+bcCTa1oc?qo+Y{vvLY%RU($asROKsj$8{hPobmRT{= z8`nhKu1wcL%&1AP^#xd`ve0k6a2o^cX9Ei!Mx0GXHfmVS1l}HyDO^E*u7$2K3xtRQ z3!A_lKrlmli|25_@Y!+>RWvNa6YWjaCB61aVGK=!HChX)=M)eJOEid?_6Y&LBw_5Q z*Kj|rFC|s^Acj)!Q?qQ?h^y8S`^2_53FHy+7wpq|jQW~?E54n}`yEsRyV6N#t1e6G z=s1ap7uzTLGKKTfU$+#TxNRFdYq;*Hi-hid^3G_N%ciO&SPxsWe!@IL|Da-N7gR`Q{#Ygpkm8 zd;=r!*gh&nuqlSoj}Xek9^J3hRbN^p+FvVWEG_1kW4RwvDk&O+@&qQ8BU{JlYtTZK z+AF0(f=8uIM}e&Ibbn?w`(%T%GW>kO-wMu{kg#F5{mzvC#W2n=sG=Q(+s`zZpOR7y zX^aVvZ)E#($R85-j`Fl z#6-`MzpfyqISau&ia^;zTP$D-D=Ad^h0&(GEsY=scvZxpLk>8awPQh!SX_77SY}dB zLy0APKXv`@2@NgnmWrV&ZxdDb^Tv|$SyVrT;*GmIciI2-!IM>$fV@#@x0#o=1dg7; z{@667sIcu@J4XgS;c;ch4AK)$%!3cZ`v#VmWUW=_kNRRujhSLqWsoFIKmK>Qz1jnQ zF#X~kxFWBHhodJ&o#Yx=uFzI|^p(p7dji(sSh1lMGO<`I{IUCHzou&@{`lZN5}O0i zTGng6bO#@RT86;g{~FHw4)JV2o;e0rHKQN_g$)AUoglW$A)_YiRJmTi-~}Y(YbL2T z=Yz;2UrN8;uj1#Rq|m+DJ<%me4b<^SwCtVEZ0Ad$*!WG2LQG?sFJfgqS=Z^C$N-g4 z#*Dr#U25RRUuaEuW-#}9@7-EHYzSz*fM~Z3&6r(LCQ*jQTSEbE{azFU{;vS!{6Wlh zqf~*pn3$(<_O`jK86{T(pZ$u>;?pbVXDlr;mx>UBAsWLhMZ0hD`>T`40}yvMJcKg? zGK8E;VLl@U4)6)&Dp~3#Gaz1l!Sw3<__*_Dr{^cGjV;f~)+MO}KIH<>zv9{^IA_wP zb=eOH!$4pYzYeJE>s)`cbYc0(BCw9rn&i4U+Z}%4O*1lh0~`-F{B-chQI5_a4mc{w z%{FnZiXgkRK6q>{M?&2>i-@$4$7IDf75<0Et)LEP%LgU^1uQmeSqb6;0y(G#b4ltn z5st~|&uXnW5iv)xCns}(Kh8^R4`q?m&kgcQ-?EtMDq(AfS^o*jsE&Ot?B$twoAQ2a zNRKTibSeBTu_B@QTg6LaxVx3LeEm8Fe!6;(o(;Kg(QV~S3pB9Z_zjfjso(`8Dd9tSyql< znnL0;M!nsgawnBI2`!hCrw8L(+ZI{$oB^ANXH-2KPE+kTcx7Apnb#=G-? zAde#l&ChU}_wL6{b$WkYE%ul1Gf~)_e*1basJ;DH8_hXNb|RpV);=o=nrE}-kl7is z5$Ina?$*|#{LN>xsB%j6)FzDS2bTc&$72S_MDD}ANV6$Ihax@6ubxFt4eZq{Tlc;x z^Cc_Dp|}_eH2Az=EUV=#!a3>!6JXR>cnV|Nqem@xXT;Lj*L#LAdw5Ifv7#D&=It;- z2q~J6I-tU}hLWs2-WujOK1Y2&*j5iJ1RBShkSK--es-E6<75d+nxqS;Z|cR62sXFJ z8ZeY2w6XDugJ(rMy(yOfWTmBxPx`bn(Y`#k_#R;OKM}T~T{-W0RcCB?+0nf`k&Ov| zqeQt}5!<9t0mW}9Ry#CFa~d21J1m#ZOL(wVvSo3TDDa@n#6dWeFVO#5nuJ4aB|Ee4 z#6j9QAw!kvitf5yyb@BA{_xTNB%SD1ZOp+b``p@_*Ld-@isG+~(Uhks{ghf`A|x_p zIW~;q!WoXb|1&~`=6L1xdu(tk^FN)_rB;33rMTEk1b`B4(fq^ii&}tFnuIkH9xYFW zfT0+rGl9q>m^0m*5Zg(;Un!vyy!Sy5hLi}z* zcWc5dv_f<%K3{TZ>64J_CP{t<S=w3M5;O{vm76B&Coz{tQ>o}C1_Ji;C2f4a|!0I+`iutV|;Zmb9iNnq*IW@QGi zZu}PqD##Q2hcOgZ1UzywFf3woG*%g!V zZboRxp)H99660xM_Aj7Zx)13`TBkKnxqqvyemvK`M5D$ic_rz`oG664>PFtCyTmF8 zT!cGwViDgX*5L>EaQty~d=Ao_6XQVi!yf%SqufcT?iV1)RNudL(lJlNeAq_h%g=Yu z<;}?%)zrHKZra%liWPX0>w>c=?yTRMNGn4?*M-cO>(iGbgeV}Zd>Q)!>HwG%qGw}4 zRjKre^rNr!W zeY&2Z3N*}HhGX0)_An1gh)8nj4rhWg$+G)UDj2^7K=ax7-9beRBX_r6U&hl<0uG}q z>G*y??jp@K20iGN|DRX?<@}kp0W7bbKKY4HfSbBq z!qUBZr=WjDnAchz5F1dyxyeGZWi3wE|3)$o{50lhHXHed8nck9Yxm(idYQSs5@NE3 zeY4mSpbnM2=-w{9=})K}AZLvvEFZs(9xBc_VE6(D+ceHRUVkmWqT-jeiE3IS7o)GNlXxbrFcg<3~+7SLaJ? z7_iDl_go)`!lMwVYwyQss7LnXX$@(oGqnI0yNiAvyioQ(IRo&zQpZX1Xhs7Qdw$k{ zP;aZi|6l3+IXPcoXj}NU5#xiYDHQ(^FB*^qFmY8&!a2vlc3xv%DDSg8CH6MJpF+ow z#sOZCEf!BmkJp=4zQJ>thq)+=(AZ?gBRS+2R|Kx=Yyc2(k13^4wl(kbVHCV+tmowxsKl0cm?` z?Jbu*yDWd6kNs*IEUDk5k$ulHaTYlL_Wcb71@5&$*ow^w6H@eLT8tBrt^B+YZUAQN zj;}ZUot0ctY)Cai%xN!~W{yew6tcr9w{Qnd-v4OQGc*$gn~#6ZN7lMDK__%N+3zB> z{w$V^e5zq)u(WhD&^)<3kKdlWG#1Ddj#ry1K%8BL+Q2`U5q;&;mkuZ3&0Wn^E~C!h zN-LO-!>#bMZaeU80&=R80dL6dCre5}XE?&Ae+W#Da)U2oo)FPKN^CHUpKrD4>FVng zO5`aLDHObdli^YgCh99=+DYpVwfcDuy`zG4uFFBck@G8=4D`Qn*XQHZb4dA;1v^SW zxQ?q(Oo)FEqDA{I+Mc>l=!x>k*7{tj-5V14`)Pk}y*l;t#N@1k6wR%?G#U9{IY6Kq zm%^+xfcPI)X>a!NK7Z3mN6+{`q*z>NGO3`62`AMxDfVNA3r3rm`too^Qh~0VRUb`A zYAv)kI!u=Me$gg~4r;x^%Uk30FFHipnNE7{UjS`p%CitKPXel3nkyY?0uAu4+eff zH;Eq;)f_-g1Ar68s5v0)vmaIlcvdt+2iMDc60wjru>cDKUv^R{Vh_DoCIWy!Wzgj* z_h|>Ln}l`M*WNVG$A~PTCoqE?%7zhuir%H0h0TabEDPF$BLGpJ7zxH9Uv%)4^Y$d| z*S1E&*nYMEv~^!er@eEaP5TFYByFl3H~7UI5#t0jN5_>I%Odg=E>PgR>e_Zk zW0064iB%>T&9oK@5EjY1kY*k3IE?1hWyayg;`ch}ZGKhr9hLHAN@kcmvb&6~2g!Y2 zc9cIG^=skbGtO^3dsqy5(KGOWe`7-%6v_)tko2yMOc2syhc%g3@u5er?M?|h#>6P| zIRA!6I*|25;%^~9Nb-K03Jq)zHUDTlbi85K7saT2T%aP8R$h~$QX7TM+k-IyTg=(C zd9SzUu4IN+-563xt$IzJo3TKh9OvOyoitu>S1wXTvz;>EUw+4PCxSeGx8LE{)|8iWh}4D+CMbO)S^qpM}%wy_kv06t^t1 ztUMl%r`_VNa3fmu-a+n~q}v-}10vrm7ws0mv2jV~+hyzjNBHU&pTNe(*fjAHc;y@gT194ytbN1^d zvbZ^}h zH;!XKlK-2s;XoXS192b@#DO>v2lC+OQ0EH|0PYG)uh-4(?ahptGiTu7;^MwvAkT#( zHJC4<=g{l>zd~&?8pFvmEMqqT$ABY0ONIjH zTED%& z{lc@jUQg&=6Uu8-@otO5oXBBgXQ%_kyrT+Ix{#vw148VhNz%aEBC>tb!Y44!M7MWrM0;EQlOdyE%DHfcRrAW`7t ze&IjdPSHqYr+6Gg3-W_R1e*4_{J+9Sopl698xA;YBethmgeeeYjM}faq3zdDLi0I6 zHsQ!)C{E)sW$a4F({^+?zGy~(>q1j)L?ROFX>oBULZ#>0cDmx6dXSM2U2jv(Gu2^E z6vgpGLV6F&PXzVg3?_F+?CQ6e<%U^meTrT#r;XC=#wSJy8oTX@Z-3|&a6m<`W%rdc z1MA~P27Lp4E@y@iDPvJYuwq402voOi+r(0Z4%;Z0smpTj$qiWdA6aTo`({-1mLompY+NMo zQc|hhLABK#2&Q@hxF}`JcjLz1*B|vJ`lP-^-^9fRgJe)Z(b_7##|vLYi|HC0yE0;r zA%H;P6kXUM?c~(-3H6jttx!~}mMoh+^P$aRtvLI%JAv=)$^_XO#;#0bXSTH^*^hUg z_l8;DpLaQZfXo^9m41h?x^LUW3H{iWZTM_V&zv#Zjk2(mjf|3l=hF>3h1U~nJiTvN zzl5nESwYur$G2sy$o+6(o51E{73zqKUH;}gpA z?i$mT%B$dUO$pShmvB;qW(PSV&70+N#4_n#Dgn@RU^(X)aWc?L0OJ8A&DD(vm=iL- zaaOunjuRf1pwwOHub(57OG$!I>a?FLbA#swTQzA6A*B)b5hU_;+(3v@Dbp0eGpEtR z`u5y>4asD25zXE^QIyiJ-|ro&^*1T67q0{Pa?`p-5CMmwqoP=75UfT~G3nCAG~8T#d#Pfy7P1oa|P1}Vwfj(v)y7c{2;oB(#X zCPp|IkmA<(B97N{R=i_>rV`68MzLot8X@t-(blSMk^gAf^YAHz1+%Syss6#WK%Y!2 z`l`SBsc88Cc|eB0%Y_uYr`GPnJrBFMBxMEp-aVx<>&pO^kjCxH2&k9kbt9&+EE^lU z`*TzJnpYexYH0(Z4>O_Tc6livG%(LyR(@?n5U{W8kW`n);(M6bFV6gKeW2;hPoeB@ zh*Pt6gkM>45dXK|8AuPRRrLDP&<53_XHY(8@Rq((XeaJs@Km8UE^vU>g`L6&e*Y|UU2`T&}x!SoL6e!IFi6SE;d4bnwI5R?$ z7otT;pn86FfF!-+@qweUXBuTR?p#n?SfgNj$3xtpt*W;q1&6p5s6q(`@gKzTElEE@ z9iiTU61MHy`?GcE`V=c9;3!Ncv)ODmQy{U+-e)KHrVJqGuDaGTw`uGUOZ-~aFDlC% zEdJNfmc@@y2l0AT_v({@7VQvXjV1}bPAia7kee6Ks)F4F)rD2iY74pW=QMy^>eD(3 z$zBN~dajPLNdI72L^UEVM6=m^KA%q-QX0?aQ!158Z5(Y#rP8OTCl*o%vQeM@B1EVD z4*fFlzS3_T$OiO>LJ8wUoIf}Z?tp(k8s_!b#mtgbvyrE#r|EP$yd$8g4u%he}+4UKED* zDEFAD%oNv8N{Va(O|!9aS?@Q0=slfYPqb*R()#w8dQFnOqhrr#?-h;rZh!d3dpe{@ z5Be*ei_XRfbK8HQBONLksy^WS@M*EQt?vI7@}WFH)*Dv zF7C9^kv^hzaB#d}uaU>VgFzhs{q7s5hq5i?^Vv47l*H>Tb|0LQbWgMxWyc5e?)dUh z6#8RbZh)&ZyBMyBv4IZTL>Df6T%}7yplJ11cQ~3W`dlQhms# zkSJ4I{YC%(rue#LUuCOwxT#s?W$N!fBQ#aG$}_E|{j7YE5v6Ur_`pW9lCwCIXPh3*AX)oRsh zwf=s;`@U}wqG&p}yEHqp)gnzA5bol{%2ceg^#ru>-M;cQg;yFXALYH<1^Y3hRT#$c zIGA36(@4zZ0(=pb4x&T}ttlA!KY_wakLT6TYMW#a{mfRI`I>bi#|m6PDP`3=dTnbp z$3Tl6K#)F^XFL+g_=&DUoXCrg;)<%|mDOsMfreNtR>}{H#b&eFY&V-RmsT6 zv|6o}K60GWT5W9~O55gCm&s&~z-v0m7e(w*|7xQ>uS+@?8+ef?Ovo3=Lqy~N5eprB z7e){e23YCwm!fg-xUH^4jF@H1a8r*v0@*`A#-$6$=t$Y42wD{4;968so|k6#GeGz7 z2x9L%tKC%xB0o?bt)|my7u&~taz0I+HF2g=8zrPt0@zy4=ks}%Ombu0Mlp$aovFJ( zl@SeboccobP+2bP>nHITC-G`KQ8Fj7{I!J z=nkVWM!p7DbWmrOYp9M*hLq00y_l@scAQCIeh*Q}@l`(FLt2Oa_JC@P&0 zu5H`CF-yLPqs-RbNF>fXx_L%6k2mK!o{l$xp0z|pf?%5BfM5c`DTzGdFtKr*lE|YC zqIiQa0)gWk+4YTMWY;zhPM+@|cAPL^6z+0|E5^Z-1ErWT(Bdd}9V442J?0=2%n-9<)xVgmqmjQv;X615QzLyqR7@lz(2_&~$Qeadg=d&!N*{??CKu^ym z2^)t^jr>4BPjEZLd~_W|Usgdf$CKOAn9~DYI)E^wffbX+jwiTUBEN~~*wG>fJR5|? zD!#M6LtlqD_IIzNR{^94_RBtagiGYPG*I9kO}R)aH%K2se^qh<%w>fq@fKJKvoJq! z90wzb-!doykpv33OgP{=adqZq7%sJV>ZbvBjHI;yEm}adXh+pp_DXNM>Qzu(hPHT@ zAzFl$p{q>^W(8N1Q!QNEij_1=AmhST)2aSke3kyqJiv=~y8 zrqZ`kQN2hAB{8^fLrrmvAnfnM&WuTFMy!gaQ_(5>zOLV|AGKHMyJ}VeI^DzN zIUd_|R|kAChT$dN#cwT&Ext;Z(O#&DISHbUGMQsZ%!JQ$@!O8!NZm*p?n1N(grA6y z1c@-F;!t4g8D1YFBF@LuLHeQA=sWPC)NiBKDpc4L3?^>IIqrb2L2VF4qjV%>wTHlxZS; z749~P76D{aSuw5*9TQiHPD@9|=I-?zb&J^%L>QMRq_+Fg(J(#JKhlZH-V(2HYSue2odanETr~fbYJZ)0Y6^dyU?x zztJ1}3o__)-0YCPNN=QXHYpjwi5?+_8K|(VuomvNroI8{aZ%{-0(S-~tga|ou^P0< zT&~VIjFFzibk~yA?J(GGpxYh4I_txzTV(3@2n|c1Ngr#dH^n$&RPn?PiI-I37j_Rhw;U zYHDgq>c%g`bs~|?%GKQweT%%BR(g*eiAuLK2oh-~lgT7ckBPxl!=lF{@QY>TUqDnUhWAE|pG^aw-qp znj@P<=Gq;(F5H3E_L05s8Hb5*74mpRt>RHUaw$EZ`mtNtRQe9QD*xc#k=mn=IjO@+ z#jQP>Sz8+bX|n^W6lps3K$=X-Igi^Wdqu|b4;xVv%Ztm6%W0i19&lL^G`qLN%~-r} zXErKkY%NJ|PgXiZC`(u(i97b6poZ&536Khr(R(EX&qaBlFJNB}e zygMh6R;_GS){5s>Gh=aW-ZS6ab|NN+Ma&J|F-?9De&eR(sMc+S3yJN~=*|k!|euO`bfAH}HM1iy6Qf~BOk#Y&lzQOfe{mABoPC}UK>yts@C2;^tn(`xzLpI6j z$L>UgIKFLgxv3-Hscr7xPSS(vmfHc$DZ@3@bB{w)O>+=YqoS$4Y4WTx^w5*H$GZ(= zUDO=qq;pYHTaHrUj-yz}YKzL@g;8j_TbAZ6SSIA;glc-MvKMNh)>n&WctQ?TDCkVy zf)&P7Fm;U54pyj%1Ws^&JH5KIeA2RUNYjPH~kS$-W?pHbl~>~adxNvIzWdMNkh*; z$%Z60AKe$MEMCPNFU?mH{g42;PlTJh;iZ;wPfPjJ_hkE71SbL*N?L;D{B=V=hhm0b zRKB8+8MEzcqzSFBn^YsOU1F5XaFKD_YQqZS)dEu%cN46MM71VfmMp2lM2nM>(^#C0 zi!;$P+131zd3@-R{MAEbc5ZsWfR7d^e$+#`yJNp|b_ektfZ6(i9p}k?&LXW+xSUJ* zbnsmPuDUH*^_&u=lHyY+NXboat*PaNFjjK(grU}judqDy=wO&?l>vgK)#e54X`;~R zwm9Ex;*QNG&bClClY)t{m!?psW))UJYYKB=tU@Y0G2YVbvr+hAeAX0x@kCy4?Xtu* zO;WEq$o8fzB|rki!@2Kl7s=VZAbsWIR)DQ?Uf@zPtQ%;pNiLEm3db$j3%T6Y&sZX8 zQ<#^&+%*J=T{3Y-yClqQv4mdUr;q2K;|f12acW>+OV+0df)_W@HGT?kj1VkwR~O_! z{5M{qgnmp&m9O*5Tr7PHrjx}*SaynJMJztWpqyw?id9IPPcGb{VHuTgO9Pnsp*6mH zI0aC3ZL3;j)=Hg9-JVJ69A%?%(sUCQ8exnFAu{XJ^29L0uMp(egYNVAnD_MX?VJ^ae0F8VAXI|(G(1;hZznmq^Q70Jm zG}0JlMb^4CNv&q9CM&?D^h(;i?zkP)rJ>G7q)1lDUY2tzmESoWRP6Z-0rF8BJ~v9m zy&%}W@q9lf^QJXBr8cFtp24X&zAG2bLaSO>>iC)^~3PSDFdQKNLBjr zckp4NL;_Nt3a!8C2(dSpX&x(sS3)z*d6zrCj zs``ZL1ggoD$&-_G$&(365vDTP14+m6$Y`_||1bv%UgJ_It8^O)B}(~qt2EWGhGd?A zn=2S!9J6GjI8ZZ^=+!%zwLOn1-r;C1DJUgwe{ zOpbi34@=!ZBO5~Y&{fRqy1^_3Z<4tZj-4wz(|}tIk?3}$JwXX?=62W~>e6nnz}z=A zj;kU|m^g9q^To7x`;9ZkuvMt1W|N6z{6Y8+ff)w4;hs#F6c(Cq^Ti6Ez4me$5z4rwe}mGH7b58`mi61#_N8-_EXz&t9{+qX z?cI`Lt1++;12JJF$0>#DG5l*{Ak>NjQa#0GOy33;S*#sF4Qd6T9uMA zL3%cs$)s;|=Ry3(0Bk~!%-h{+&#GHeD%A8Tg=CSBbTsZYekJs1;oE1^CDdraRLQbf zYt~bfr1aTj4%v^Ke%~n%;!Z7SryH#k?Coy9SfxBwsZi4dFq!rw($RPU4z#6zx6dZP zhwT`vmMn|?nmS=VNuSLlMjiP6^I!xv2|3s;O#2^u6_O||N$&iF0>5@LF2CdFtu9NKEIr$aY%ah&wDz&4KF&Oh;4;3Eg z5$ek6(Mf!5MO)GWiOxb-;}ppqg=8j=FuH_!*JkE@XG=Ld2zqXE4^h5jR*)l#{s90a zRr!wS9A3xFNuwo3tfjba2&!6}Y|OBFg1*8LUl25hv<_e;nwCcfptbrpG-)t%7X()c zS6KZKBsc`E{*WApiTm9n^v>05VzopQ>7n@MLsp3DO@v!OFWTXlBV&9U4 z1O2Q(A>Fiqi5X40#*tfbPufKz8*ErVrHbr3&*BT#2eW$7^&{0I1Nw(i57 z4?^I_mXX6pK?sPtVz@;Lp%AHWEyXl!1M+j=ji(@oNp5ivB~em`4Yo2B4NYc6n;-H* zVx%$v1@&Gzz8kwo&oC5$0f-Mm!}z5bIwUd1e-H$QAwk@H^btw+o71Ydkkm0!!f-wz z|D$@}h{S~Pe1fWC$&kRf0i|acaROPwJ=7+u5};8k+{CF0?hTcAi`sqv3|~~G_vrdQ zsPAXj zC$S@A<__k;yhdpY4QEG5n$3hckaKA+xMlbC)OjEypl3;2zqxOvZJw{evO7rs9wW5QMwwr~`t^hm?&t4U!tv$gXo<(Z z7oCLiCSnKUDsAIID`h4@C4{S0ZkDM&vY9Zt040NO?l35Q6ziD-44P%n-Xp&INUnktvxig{h1O-S^c`CQ2gjUMR)X!xVR=&^kKmKysJM>H7 z^}-WJut>%`u4lN)2-kWdY(%tmxUH!0(iSfibC0-((l3Xt)y@b>jbw!o2@Fj-&|*** zr<{hB#t*SQ{5OFY(ok}BG)Zln@FVP=IZcS(uvlVyXfBotw@wM)HA6|P2}sCh7mI3B z`Jos{p`bwBeVa(D&6|Q68Z0N+p@esbqlB;e7Edu%|g#aUg()c*aA@vZL>Zb6-0uA(D00999 z!fm3RT9{*tfP{pEgmgR}k4K}?XfzV-`@Zk@ec!jw=kxilbm{Te^Rx2(|NlSbUynrJ zl33M$+qP|6tjZ1&Era`L`Ub~w9RK}(KV1ypwL6b&)ff=qq}IKWm4rll3G2)m5O zV0|kw((P%oIk+s{;ScVdm@aTbAlgrmMIWqax^of56QgJum@ku`7E|wORzP5x>;;-N zz4%$fDJtlh{?jV3Ax?mGKyO*Mzq>e{stxcB*Hjf!I9CPv*Kf& z`QVB^1kELDyO7NU7(6?yPWh=vuY13XXx7U|TxE*0_kz;1LKIqhUxx?N=)AF+aQ++T z-#ZXMWvF6DlGa=T+Crl^Fo3TH#V|?83v7WOz`o;2BXOl*vkQ%?8@#k|OaM)~N0ndf!12_s3F?;~0ZflD7CgIJwh$J6mQ zIphFi84$mT-u}FaNPN2MRk((BM`;_JvIsK<@6a0>PR1=t0_g!^7=#grC1`sBHbMZ7+_;_>6Lv!hsyTk>6rv%J3Pa=<;+6zGFQaauEP|X&X@6APEVD&oaefbeQk%b z;JK<{-`&BI?vGbu>jf_sdE9*q6vB$3ZmBS@jopv#!}od^`xzSSnv(~nB)27gA-=Q) ziRZve9ES!xGrjkSi&K0BIa9q-3Z#(vj~vNWOxt7?TM=!lf~w2ad+c1v zD5$L&9qn}2aZ;TdslR80z!g0ruI4WL#{_@5Zxef%C``+?N@zTmXlPSPvt4Ok&yw!Q zAdfp82}J{jz9Oi*Kzl`j5(wBs8i@Y=U)AW0+C>H8BEVg4F2LOf-%O1aND%>d-8lko zyO~nFs|K{xb`juh>|yXJ{&woT5t>!JI$4etJ>W`CsL0zwGg}KslNZ(<-{@>KpRdG8epUd|0**y)Fa*ozZjlZEvuQTE2d zsc^+~c0NE1%Yi5?cE{5&s5JJ)9=8vZR-Y|;HFdV#`FWyjfZ%w0fz5dlLpwyI$+@Dq zHgB@Dm^;NWy;s#AY!0Xxr}t$*y_>jDF|vG(kEG@A6nxq0j9uYBS_F%qx`<;slI4QH z0&8%E1`@>oPhy}b&uWyz;SZGXi%p)CfG|6(PxPZ%>o2Tu$Gwjoo$l%__T~3xLYtVx zgGIsPQ_`Wc13Bqy`Q6kg2t8?0r)eORM8O5t>Azb&nR5z;|CcI<$ElIKrzkRo z4ZWwi;}9mrXkNd%eLmDIaT*_NU^E2(3rB#%B1V86^XN>`gZt5or+JcZRX%wkP>K1m zn43j{Udw0T$Gvm-4$QxKT1NlTCgJZq^)W zqV@EC5jUtJIr>7Rc*q<(a~FW$;O=qf-Ge|n0NA{LQw9=uWG?X7b!{e-!z!YhzCtdT z3d~^A6~|dCLh{Q}GQ{VjF<7jz<7F^DvHb`#?+XTTS)MbR?n*2aX6iMl zhk|ZWT8mVmEQ_5jbOAs!=i3ct8SEC8L|PB@sXwy{p@yH{9N)_-YOlQM`gK)`wonKP zZh40I$Y8p+2Ow@SP>%Is&sM~XSNcWvn*lkN4UCwouw)D`j<8=bHQcvK_Y^aGV3ge+ z#E>;zD-#K4kjkJTuxkRLndT@hb*xvM_&cmG7OxETLJp*9HM6KAz*>fl=Y=BoE;Xuq zD#R-DwS1Gt=|r4!bsU(T4wm;7(niI~w7Hu63&%HBtrZwf1VkhXio-h@XU3EUBU8%x ze>^d$B%xHzlSNFT<4aGlPuuruiP<7WHIdeOOX={*X}VU}lK_1wp8!{p)&Iu6hrPiuHH~YAS+EDD+Pvc&PLbr08B9ylbgXd(SD6(-qFKx z(hB+FAUOeyjr#&M?}iR*v2HA9aaQyQ=LOzrW_e0Dck{hH&@{y>{&y?jnZX7&bSBdd zryNnQ?O^p%*}CBG`;i`><~aT6(6is8`ic|z29C_bCYC&wl{(Vb%Qf;YR|>8(Dg|9- zbn}><3gtJG^{HaY8IvD|GLoOW;~2jwj7|T*V<7NR2ao*JadX#7=Wl{H2@eqUS|=!{ z8(lxr@0mp^SYV@8MxN4tIei()I`|os`z}$x8LH3}(pMb%DsCRol<`314ZrERy zEq=eHb-2>^b=C`fft$6;DKiAJAklh^$Ab8VYLLhe26xTrVn6nft_kW7;)u4zFvGz( zU2@=SX_Z_Ph2VVZp`~<4nONeyKn|Ee>Wp?M^`kUntv<2bs>KUerSU>8PhUm@r#NGc zdB2CHGSAVFJq~r`k(;eTtsKP57aeT8qdIa5*aCwh2u`U zL$u~jPLL3e@Sy#k+Bi!k=+|#S&7y_`MB5RrJ47!1@8(LW&zz#um4c{0*-XMz z0**+Cpk}8@B0ZXw-sY$&E5ME=VD{0+)G$7c97|=J693Q?(ugq&_JVjkBXDWd5Jshb z6^F0%AAGa=22K}@uCzQ|F3P@8B)A+}1;yEzJldPtp#7LFDp@o0FmCl5`6d0rA!*!d zX1Ri-wpZ>%Zf)H`aa_lYzJp$pJU~2-9ZYUhQdb>tscb9lGP&U-g?WWmPZfBEdTsbe zH#*HtTM1jdF;$)b%Xdn)tyQ&o462Rf!_V1Fwft2MZBlO?bTx^VXR;eBVA>^@Jn?d;g`PZ z%YZXnbW>C!KM8#DJtKjt6~i}&5wI3!V`c`=UZA;SB6Em5t45j-@5`$zi6s?Qj8Hyb zfQt3L1t}Map;Q(59W{uVH~y@qan zLGCoVPR`m!=z$rlntO0;n2;=?iRp?lA2|=P9VueNsCv$U1@1v77zkyLX!4vxqXY+d zMpB25YN%X>VS3~hKQ?DjOD-LWCHVH+0l8PlrsI0+W-3~FX&eI0n8gjx5px!9fQGsf zxl{XSJ2Ur`2n;7a;oU+E5GrKeAeGft`V?x(bnmgEi!hgc&GBls)lr_i%CMm=Q0>4u zmU26Hc!P^qZ$)XhHXuqDc23Gj-f+pqEnNVMQoo2UzMTtNO2!byl=4tNF}lu! z0o}7x2;3GAk($SEG$#vUJ|l%Thjewp*Bt-EQb$*1DoCN5k-u8D(fi|I|F3qGGH9iT zQKBqr0orECOONk$M zM6ANvL}Y%Zz*ko^m-5nMxKc9j4(_43A#mrtR|#CdAfTz^Y)VjQS*YV<{lCU%adV?h zy@vH;xoC_Rf|&6;A7^z3HI~=$a+Xvas2~Ox8h<3 z(^046pkS;KXH+hf2V%-O!^AC? z3*NhKiC3KzPq+~XmDm2rnP-!S-_|FGf&z?krCv+pfiegb?C~|WZ0~7whxR)zCbX(Q zb$18Y(GNmJo(3>2(HFek>dwRTxV4fWnAScWk@RHqC?u8M&B)G3oyO6cmW-Pea%s8^%qj z9~1m|Wm>im(aG{lWtecbL`BnBT1C$<(ZKg5fpIy~Ma)?BS`YDofe;pSHZXIfg>QM- zN<~E4;BgFe`sBTiwVjW>o*UI+x!AIX8&C!@@pDF-k43n18F!BWsa%OkOkW>5K*0x= zlX+p_QJIK5iD+#|&^Y$7U2Kt22-9b(g#*?f ziDT?)TQribdg(m%t<~?7aYO&)^uI{DE>R{Ky5_KYVKJ!JU##H|g+ri#_wF+otPl^h zIE=~!&NgFgj^){6>jTx`F#(N&DTNNjEyNW!3N7PQ3Rr2_2iE{C03l8?{TCSiA4G7` zEkEZwxRE45R?y~XBMxh|ABp^UNuu$!CdI({ zxQ67|I%ySA8)I4!sQDVMwD^FF#2LIw@FQVqhprc&bbhj@mxthK{R_F#(ma`hU z_eYo;0k?`xyt_%!I0R6!TRmO<#4;F>&Uru8rav!~%|wgaWrCGl4i}zvMj+*EX7EWX zw{UZpvjPs0=X74~tWB0Cbo)q#GtZd8MzXzKr0NX?bgbyFkJJEJP$-OmznVPC)N4`SBBA%`*lG zg(id#IhAFq9c+J5>?}EmFi!phbuV-*cv$gm1V#IocNZMCj@h4vN)=(m?45Ig&J(p# zh#td);}n`EF^vnB={inRq3f3bU>N2%1$l(pNh=@_iJElRhH*Qpr2oxrc>3Wm3(RTn zk*g4`9l6Fr4@8|8xi_PjL~+@~5}bNElw>a27Hm0O0|Gy>HHj))nh6)087=$mdTWp? zV?MUHR?h<#RbY;Z*1_DH?}@Rx&Rd6zSShcu)gX<548~1TGEN-PDob21d@Pp zO8n?jfZ&xS#Q)yGrxm?ky^=qY&~m8UD|hM!rFCHKBj3Oxz@{Nr?w&U)BO}}YnzdmIPiOSORWskb{=3zQM_AceufA?NfoA1lxUAVY|KX= zQqum!sISZqVdOSQ5~+3aVzR~JkbLJ`Ofm{q(nc_F(643`eG~&=MS=kNQx-%2LWmJg z**JYHU;(aiLVw#Il>Y<2w+NeV=QM@;z zzH{u=(E`WRL)iKAYi^g}J_g_DJmkA|T^SAXLcwKJD`i%&#n|f?3utJa#E}~{%H7(< zW|(oz=FUf2a~*Q1>EkkIvaJ$;JD*71n2kxgbLp8wWJ=fIvh3gyyG?bW{%izFA1=3$a|5JgjGPxU7yKUOnhWBR*)6N7aq0KR# zN+n&TRku~j_!!jJ)m)wqv_0@H@S5Bh_C8?H{zyVXW}Rjgk8r(C34LgFHCtnV=IEi(GrhvC2LyQt~tAA}h@50R(G_2MDmb zMHx6or@(u$8GtHG;)C;TDW3I<1!3rcm`l9lLc8Z_O0J2_dOc@O@X?j{9GqR^^FU?_ zEI-ai&^piU0MAbmOs-Xxqu98R$wqr~w7&yrXO{0 zqU<`ZJj4_LjdkK=av1VQ6R?HZq`EKTaAvLj3h0^K78|xK3J@@@Q_bygZ}w2P{&2-{k0V2&|t+#viY z+eYg7Oy<*E6VhW?h0FmA9Mr2Z8D!&C%e2x^E*-i1X*jDp4Br*xWYht6yy5GHnT{bQpEsxCZ47~BwT zIv(S|qGOjx(GWuuUsF%}N5%hR`s`F?wWGwDrY%oDN<5fW-!y|4{{(hX++Jp5V=WjF zqLb5*zs;rvb+JAz7eN-&v^lN=i+hK=R<;JCE|`HKoJWH5wIe6^pK9svHgKKuvgu(J zNTeSQ=+y$ z(w5HDzwt>dfjD|NN;!|uvPXbCeg0Flv&??tW%}|tf3<_r6By*i)OdrQtx_DR6JZdr+*sUk0VSU&vDbCqUN=P_lF`a~0;h~7TWmgV!L1_bYgbEJr zO9>^|%^^F^{KI9c6UQ`UxArh-Lo1`@!Oy0UWJf%}wUS3=nCXpQDLsSA^Tr^2qZ*9%F|wUzWgT3h2SF5Nq+61v_!uxP z_BSDgaLTppN}Y+ zY$5H0!*)Z_+NLqyF!-=8ar}&?0oi5{$pEi*vaq~)?X|=*bw>y*e@aNGtboWEh_s{4 zb_Z7AU=B7jB8&WjbYvx@9NYrsge{5(?9Z%ur$?SkM9LqmRHqBCOl(RGziUS=Ct8J~ zlPC~gcbgf&ud;oUbr(_@417eXYiIqW!gJw4C4^zY15_>YoI?l@O{B}8ffsc*Mat>^ z3keXvUr3P{V5P95J}hPNoPMRB!06#I;7pIH(&-emC|oL(NnC1l!|^2|<#G#%XZ|It zlZT}efHr0GTSAtG`giQ_xn2CF2IZ~H6tltWjZQ+Vf-Te^mjxG6R3LGRGL@ru|8To? z#d5(SM-GGM;Pr72(BQ|MrK2=^G=D1vhl|LBRc8@aZifN6KVxbfR%?n| zxtz|*fVFZ~A=rpqv`(%| zz({53My@H{Tvx$S=^~Q)2dlA!=Us2u<2vrifg#ahepKMcUU}E?&$Op-H2F5@i_S@( zQL+dG!g?xDTkp>01Wt7djFbc}TpjMW3B)7?EE#Q@^CG75t2$MhKsfr}h)53y_*Yzp znQ7RCFIO_&9sw*T0w`vHxF$xL0B*a`?EU)QH_)vvkEI2jG@5iLMs87%s(f;M_%vwC zB|KuEWQ1sl3p|jotjfg$yzFrH&vY|AjuGL>yOtHXEAfI)wI^!Rt}ZXoz0cDuYmWrB zm~b?^62m}Yw`a$&E#?&*gt{G9c~#*ziysKkD^Cj&HvHAeBI-8t71|KQ2)!<&*$4R< zg=`E1Z*thn7i4FMf;WW8entplDDNs!Ew`E>v%%#Mt6ViZ$fP`&hhF5_-04G{MV_AMR6nzlziG4(nhTfv$+Y896 zX(=rd`Ns*AOnD*^t_y*HMX|Bqbp9E?SfUOXewGS*I(t+Q^=-7m1_%SXV&YYaGb?QE z1VBFUAO6WoV)QZZdeD;a3)9Lhcxhyj=hPF8Sf2{P1%uV0C{rHK;5j8VM3Exz_l#cU zgEcN6d2WcT_{PlGATPlcFH~QXO?32DIviFBE&=&Ld%0P}%emjW!IaPv1Uo-QZwWf5 z0qD_uJ{A(MO108gH3cz>lvbDoidBSJ;K;12eo(Ex5(p3u5d%U_O}au(BJLUyCy&e! zE>#>@jK=~`3Mm*f`wl}6IYKQiQZ+x^>r>=jnZ?G7FUVULQtf`+=d*~u%*Os6K0#@@ zfV%mG>o%uNv{gbzG(ZfHjwIy@3>`h_q;i)>qnCYGC2A0l^wNQN3`3N%MeB~(C^W}H zKd~5bJOYHsAnA1%QsPylm3_QmaU+epPD(Nk`~pT9lEiO@Ipni0689SkHB2t3V9Fi2 zh%TzT3fUnuk!;UDr4AlY1?z24KI|8bR$>9|A*=ZuOLh#p1n~f z|AKhiRnwKdR{?#8-YGCV`1!Mav)CgWD$hf%L=54IKoP%ocsRBw#L4zI1Uk?vD;!D= z(}w_xT3w)SIJcT2qtaeUFUx}$iH(bdEeS3Dv{9V~(JZF=>0N3a`;|l7anEoLEIkZ% zma{M^g6!q!NTC?o!=PS#zX^p@LcRjjC|F+RObAD&OU3l3{#MyX1P=7M$8%T!mV0-@ z$p?K{`jyZbiPys7Jck_wW8@iFvcsZis}j+WLO5OI>TeA&Q+7^vuEFEuNH@;>>)~1| zc_%+o!O??sTY}<577i&8eII1JcJ$-Tm=f!9IYEb1Ap^5-44c3YAQ5OY+bA$@yZ7Hjt3x) zl0G7P{fOvVCBMsRrEI0&g5(#vr1KZqV%F>|(|Des*O!ew=xq{Zt<&d(K^TH{>`a@G zi6teo8h0gzfwI0BCa~MAm6=3daCA+UygEP%rC~zdjDxW==`Pgv$^Ib6l41gDGZmUS zLo5pUbR_<{)}lyEd*WDtDyFSS(=s zh**xE;ieQya{&nm0QLv#HpA@1kJsj&gff&hBuSnj9a(mT4(!O|cZ5d04^AGQI;lq2 zP->$JMSL5r9n{r?{IU<}!IpMNE=vr=Jg(4hCc%15#EcpqjvTyTUWO36*Y^Mz6es^T zVxwqWA~ToPfJDKajcWvJiNH`jBK0Dt}N0$SPz_iI_h z%JFVG7+f|1?eBSnEWXhBDu*!ap)}X6`R;hSO?6ynSvZm|HL4xGZd-0Q9f0NIo`-HJ zYgE6VrVQ?&3aX=1lz_L@>$uDY6*FbrFV1~ooPHnvek^4I)Z2h{fXj%k^*HBJlvJx; zP%{TzA7ob3h#+plw(Izun7$my-Jyn`LBMqDrXtBE)BsOFu)nM%091qq#zNKF1U#z^j%3rF?0O)~cjS71X}M{uHS))6!fwCi=t;WG#`ZnOvkm z&W2cM+1n>YM$1-XICaa@9{~g-W*fDvsz$R;cym1XfZjY_W*zHN@8^GMAiqRahjI1b zF7xXGUKk$QCB=FCOZoB?jJu?ba-+r1hjh3Zzfc0Z=LK=!M=!9!pEUy`av_6509 zUUTlciKkxt^J$de_rLIg{KM82Rw-ZP{H~qQwSl%vFUJ7GF_07m+af}FBQJzL956vB-+{r2Ol^m|x2 z(+wr~Sv8?EVoFIn+X8ZK!FH7L%ZeL;y(dsHk*{$4;W?|oWYw4R#uobcRN=9LCH{#R@( zF0w#jwRkn@h-_rcW6XChwq+{_PZO)h;$njitE*+XF$*U!I&gi~x8*GiQp`=@%1(c5 zy35-7-h$}pDq{s7JW^06!}|C~3bC>wWegTO@;zo*?AUdAb?Z|KH6WfhiN;wS#RSo(9+e-QH(ToagyH#C6+m`FjkO2q+itK(tc1MDeT7+ILH^N$z zeaPT>7``{Bc3I;^M94{%9J{@mG1vN5a;Gm-*vUrzA03zbuvQ*jVEbtKBZ{yqhn3qFO+GZ+(BN;q?o zVxzEx#+#|8dTDta{${=};Ap`95#?~tH}4*Fw&&waKO4M%gnY}gTNx0eNTZ8m9hxQe z9GVXG>R7ay3*%4K=s&GB^(lUUez@N(U#L(VY2)Ymr6gFRDrhQ&h9^HeswIrYSia=F zo05wk?9OHUnyR5+4=nb0ClP*+=;MyCJvci`j~dr^qg#--4Pq={f|(;z@`afbs4W$@ zUqhm>9RcYm9T?pwDEm4?pE^DmAGHC1CMfQDD=5;yud~zF9bF(;)9+zT@QR zCd6y(GbN~`cqFyHc4I1Hi33k2vef%**8cXfZd}+x$D^qhRwCByE9BHsKjrn7K zwJADRixmnVJko4ab*or{wP#tE3?6X83%=>MIj_F-_HUiCoWB2_s>cC0{=ZCW=IqUa zauV68et-3`0b}jr#CA_@$xjf&HK#A)6FaANL1iLEUtLJc;#*n`NP)&EMPF|6VPFo$ z3UJc|*^9S4Hh={X^dQL)98XWoVOPQm<2b;^sMz>ExXyY^@_6BB?8quH+j&_0&w zZKP+xFjbCUi9)8KmZyEiVTs z<&633L6lL2=F8OSx8{yx7vMa#HfMnj*sd%oO(d}8o8TDTu?po_=Clx2)nX{nZz6Xq z-EcuO?TMTva(y*6q-G6(VIeE4#Nz6oU_ww6cn)oC%2zuCYZ0e!2Odo}0)@G}=}@M^m8u0Vj}(I%U=TDKS?F_eQu9S2udki2 zo5Fu4ogbbGl|{s1u@96@^h!FB>x2&k02uLPvWecZToT@IK^pVJ!}q$7KDuO)qKku{UZHf>Y=${pG<2=|Um$U{U$g&V`R1sbn8<@6I2el^ zJqq{S40VYofKwLolh+}L;X1@Q{U?fzjrzmT8Jjd6_@N!Vop8cI);b8OW)b+@qKh`p zM3c&aKo*b7l#)FoqG}|SW6(>xi4CQ1K$5GbqG|p^%iTDN4xu+f5Zn(k>F$coL$mdG z1mo8jnhJH#=x@H^cJ<2dEM9g|>kNT0!se&>U@IBAc<=mLYH}^+!`R@pLty{1tO79L z&^AA6pfz))ta4pXKT6xPQ|QVKxBH~q8BFZLhgKY!>}yoslc~Bex>cx$7~OP@*6Fep zFO}yXNsRV@DFV4inJ&J!$Ejy`^b(pyjWs!rg z)~Prp7_A&fQ=`yju*kn-bjs=3w^py?gM?k>%8RqlYL#mnC%#|b!HNIVFi!VX^wa%= zUKWpO{}I{ajbqdfF)L*uM^%wq2acdQF7No0%7aXLJAF{swaAI9^uSQP-N+Fu4L&LS zO9SOnwA?`CF z?kHcg$Hn0uyThoQB|!vdbM_Bs;tNMKonG*11W2o&E4?oZF@82bF&YP-QG7!v;9Cb<*QVF=lF8tqt=@JnE3 zeD9q`-D!w$?)6wv2nnR8gN-|)EO>Tez7S_dVzT;~eCjWIpcF3Y+6wYIk@`y z6#iv4V>LcT*F$efs1l2aHSg5hyeFr=uFbFPOQcK@l+^5;7N*;sI;5GLYWm>@3=6`V6)m!h}HW6X!_10wXQgC z!Bq%=_M~JrA{`cfWiKd}>~Uzzmse(yfb+JfICcO}$e=a`==*>LT%c2mNdt(*Vdv$X zARB-8yCgeYr$yMj(gi+vG1*|pA0iIg>B04SjC>BgNl8Bg+#5CTE&}_ElCuQ?Ii9JB zvS6RWW>kR@Y;yXy)n>u#j_ohxpCdQ|lnd>&6@$`@a&LnO064DA=aS zj{6H@4xDdP|8nAq*l%tvQ?{+xPOK>U#;xzM#p`PHY2PP)Cz!nxu!Ea}q8eVbfa)xmdx@H~V zRd_Kw(6=kY&STYp^!>FUcvBhWSQpIcsSLD`L5|U%_K{r!P*RB%ii$k-p?7agG$7H}q%(a6ue=#Tsj8`j6<{4v+Vwil7<=Eo9m{kSLwdZ_`y4V{Y_OlP#T zDaM&D)?m$DzKwNY0$UB*M7AHh{4^*}BTtD4RL!^@z7!WB`)gQS&^6?b@y=_QvSw%q z)!F>>eT6WL)T&I1+FA%D4e8y72WEAXh8y4>MjSN~nuT>w|5=e}7y<@-cg&R*Q^uK! z8}p<*Zlj`Q$_zp}FiB;xQXHjtI4S%d$kUD$B|(U>XECY~gl8sTQ}R(kW3_Zt5Sq4} z^QmgGA4|DwR#lkGWC5p^=~M+01C~c!e&nEd! zx?F5$pBmcF<8h`s<)2#u-JS*PheR+vTww%f#5AQyt*0`j#z7>^`e}ArBNmq=YW>U1 z(cz~suuPuR2+jSurOFDMp3>jR3J(uq{(MYGR**Umv}&!#j7yxR)L-WjfX%3VR6C5< zi&n@kpRWtN+<{&{#;(t~zj7Mau<>pbRU0u3wg3UJbP8ljt)u&WKNrjGiu0~7`TjpB zhnd1N5G};{c(@+JS{Xuw#rTm&h)5My;PmHp8qeWp5+AlQ+XR|YW0?SKAc;bmWFjW~ z1igl-NrB?Ie64OM^|?(mYvH|=9a!PO&?bt?TZYGrI^_hex$0xoCFHG2(HJ}-2nJSE z5-!ZhG-2T9T*SC_CNqWlfDnPSV-R+Hnl)hpgSN`b$e?d8(Feg;Eo!$cD-0 zhY5`8vEkGRFzrG!F?60;+|VH|Ke9K>HX013vDT)T$d^?ndO2c&U)s1$ELOEP@$`Cl zNhnfoQ0d4eQ1jBE{ryO8r0Hl4-&`1#WWH7Pmkw%`{N@&*3)->(wQa}-6UHv zSM0m_p_2{;b?3PXvJVEuenT}Co74cT@qDlt3BH88b<)Lyr=XVOtvO9j0CKQKy2+-NeuEhtZSUgj$?JgQ0t>Zz-g6TVMz(7-2)sr zE|gR?rvpkeP3qc;YjSQJ03(*_H+%heZc=@12HdVl9{ne8EmRuK60BP?D5i}~<9O_@ z(5&HJUk|9!Tv}026KpNv!;Q38q>(qWF2!IcZCedo1C#)IMZ)HHcv5+^^A(z(2}s3S zS|iP>0#nuIZ$dVm&jCUJcNLe#us{ba6J(Qys+e1)xN4sVvN(0tWK4m25`bSd>|Z09 zfphe?V?X3(jN8F7HBN&A>9d$+ z=2uICW5dleH($-fP4dhG!r+es6A5wGyEpjDydAOsXwX@qgoyDNv0gN@_<&yA*=#;7 z3sn=Y?A5U35d414w3_<{oC@P>zyT(eS@82tso`k0Xz#Hma{~4Z?d=WdK!ua@ON~F1 zLaHc%FH&}M!^QhXD|{Cvnk&CN6LDV(5B-y>&zc06cHU#DgV1b@J&<8lJ>^Z@i`ia+ zknX-c4rrz-Cm4V+_X2(s_4R^K#0?!BLqc!PX|1<12a_<>_M;{2A0!fr(uk5^#CLyO zqh43xNMJoHn^u>>R5+Py1e}tpAKl?r4%h4u}Xl$X?kg6S%4<<0ZakuKV@> zK`Oab0^y^Xya*iSL)~`nO@D1F8i6$Yzcu!0FevD_Lon1|FV$$#gNuJOEjEX=mX5Wy zVNK(8=cy;=5AqEDr~zaJ5JSBs#wpUr7n8m-`U!G0;E-(@XxDqbYLg7ogLY)TR1Khc z3<3kR9N>c?REQAoxix8sy?`l;klO4uqn((TGzd^85Lcfyk8g+0TIuFMC$xikVCn+v z>YDw^5TqZQ;P9J&u*zlBk%s)NW?+4JJk|nf;x&@enHdLp8Fe{_sl^ATH`zJ62tS4pX6H*^-6QvI!=X@+6aR zPQcy^68mje)==J1O<9-?5Ms`|aEi>v=A2N0zB*70I0YP^ba(Q_)opUeKMwWwo&|+5 zT^GroB1(!Hh&S=zg_ikK5f^I^`4bd*C>x)>9HB7p1rHCDVHN>;+Ay+&?wzr!Hatno zBr$@mztL?qzp6cdPa>$2Ut?;~QksdS4jq_Do5yOfp5pk7csBN?M!(Na%`EoD+>GTw6jt&Nf?fG=_Qe6#XCZ{LMh)?010kk_T;ZC&6^wRv>L?089e6Kl$iH^qSm59 zPfrH}atiDDWKeaC856{BX4~%G98EA?smlxxx|}^(ajmaIy0XC+6rK>YgwX zefGoV$+F60xFC-KPb2wORRabM_24q^RA5Q=JZ|lBR}k3qmw9Q{Vkk-dzFEa(dtsJF zk&OS{DrXoTuMdnPh5@V{Da>~_?d(zdE{BiZ=f1QVBN()!^lCNS;uw>HCt$wRVs%pX zkUkY~ux6V2yQw1WJ1IBA_naq+T6Q6*7 zGgir*UNHwV8*#!r9x{pAaI8)z zYdgu&R)R+%o!?)%TZd$8^YA`4Q&es_><@VDLsGc@b!zh{Q2n?Tc+3JTg1VXECH)eL zlxeB3a2s6JbRxuTiO<3lO~V}}l36Z5xc^naEeUsB79-Cwi=vC0VCO_WJQt{#KIaaO zaQ6=Jh5w<)2!c85*C`_lVGe2_2TR~%EJgpW(zN!Q9~5Yei&AxIO)2 zCRMya$g`q1U8;BapJ5mOe)?b~*aU@5y}Nge^=-6t6DJY|j{?E#ihb$5`6Ij*c@$@3 zC_F$*aur@^Q+u{P6@n$67+M$t3OsP{#0ca;kyzeTw$~9Uko*H8j*p)xwVXvon7=8$ z%~QrV zb~HmEI&X}P_R6o#GA5TJALB<85|g_l_CMnj=Wo?{3att56phGVAil4-i8z-L1Y9VO z+~qm{n!7RDBYPkzu8J)SAz96qqnkwV2Ck8Sxg*jQ$&n#NJc0x#Ri<)m!8Xmq^9LS@ zjY#j7IHGi7_>k*W?IObsL>i6UkxHhWmV zW^KdE$+|xEg(QDj=c~b=Yg?60-`yZuTwh1k%aLs)i1-Y~k9~p(|JVn2+Z`6bxFE=U zz>kb$*Y;lM&NIOS;?-~R}J4HIhUWa zrPuL(Sc1<98dkN+5RU{!bSCVEjn~Erk$KJF1IJ1jd!o|2?LEv^A8Ps9?eS~510WnNyqdEZ% z!xb9YE5CkS%ZkUWx}x>Mxzw8+YxXq_itqBg<7kj#+mSYU^j-u?DOguB2uTK>Uw}EP zG~Seh#h5IMGu1fEdIFDVRu-8#f%u@=1pwbJ>7+>`j@0gSrI@uCbhw6GT%pX2ZlYEo zws|^)yNSXj8hRi?pKEw?V~W$N8>*+NnCPAc&cePrByhtL)p!?WYgHTz8sw?cXSq@# zV&{HoIK_*@k;VnIHi`m9d8_HdHBZp^%I$KOU?2mryM`y$^i|3`z08a zQBy7#C!4(&8HfC~^dHz=lc$1Ns~7q3UedN3Eh5ykQ0uTpxyt z_n&s?C)^~_dHiMsJ#vekPU(!Ix`BYEht9mAdv5%uy2e0D5^^=+*K%oS^Dz@e&~>I? z$u9rajNrHgZy-KnSRu_6MvgO4GUsH7lyVJzvO*ijO3K8dAGI2>z1M^rn-Pdo6A@zD zMO!(IV8=lsR{tIqSK*k}NQC?)=_lP z_>^%q!~&yC7H;vN3BFneNGH)qei`WA{z}f`bx#>k@DQ)eo-f(74x)}uvFRcMyqXne zPR1G;^1Vp`f4r&K4#i6gjqjy^4}h4&u?h1BlQPg(PA5WubXQ+QA8%+sIz@Vk|dK1KJUdQlpGqk#BRfFR# z!n-M+N=zDjhSZ=xM6EzX^0@PAsNYCNf9IZ%S`7RdiHze0VkL;v%gqR4fAVI%w=Evi zl<4A#5LeTwb=lO|{rqgMP@r4Ap|n-qiD+-A#z|Yrsc43oXZYUSuawR;x?NoYwk{>e zG($U7&EFAp9JM=lSX+% zkiOnp`Y`U~s8|@`PdzpnYTo!e(7MO4}e8^)q}s;OC_I48Q)@ibcZ? z|A>PfP(fFO_beEiu&7K(*m@-!GI5hCb0`fmfrUa2fqeIw&JOy!!IWS-r8|SKOYZ-Q zl_v-R^)hle#1J-E|nXuJNZ$y9b~&xYMZ+(%gB`ZWp*G<19YC! zzSyO%fkkbWy_=>%V?Mmj`j^9Ig!0T8Yy(d6lu($C6}I~w%t)Gw9*g96t^gNJx#+vE z>@Yl7oEVOy2vbC|Haj^{wzZ0HG<+I(HTi6209+|~IFwQ|`;NrjM@8)6PqCpvJ0c8G zm@{U>aW>Y{f_n9G@S?po^pEE8XB^+auh=qK!q{M1_k3KLz5UMPft^65GLWG(Cem}nnK{`CWZ=z=4lbf&7jC_oVlrP ziOWs<&G2VlvU|}@KWg{{yku_PKeX>|LyFQ~;IFhps*fWep9-cO2Z{e^r=k~QkHJ^; zJcu(SQ}oyQ^o1~e)@VfRS`AcZ{+m%rwXhulV*-d|rj_YiZ*&Cbqxm%rAb zUFer&X|sO_IDD8{%cg6)8BbFaG~gMO;+!b(8?z3)+5*$iqnY#N{~C`;U=oh{^BZ6& z%^dC5Ow`9W2PqZSBP|rEoSo!XvbJ7PUmo4H<$+38gat5RkiwCg?Y zI@a}fe~9O)@)Ovw=bwNaRBNCi&2sI$b|ld~5dQk*hg#Q~(VOY`2kHg%dU!3pp=}SO zHyIv)SC{1zVe+%H3y&3m9Kg`3K?YcLqD#)lf~ZO#S+g3mxj{)aHZ%o>>4RsChCO8a ztTj*waljid8kRMrKex_&IiOncE0OjufD$KAba>GGA9XVhT7IV-V5mYaDAaEQx_ye3QVtz=8L(DNcuLd`4S z=ky0sTg^T)rUT2Gke|WiAAGcCe_T%g|4ln!2}cPu33GisqopcKCK6SCy*$yF8)4yWc=g;7}NL^k|Ds(iy7<2NLJbk(TRap;|7m#w%;|B>W=r?rO zO5Py4&_&lg)Qz*&)Rb3KjnA}~^h&XU-O7u@TgHF+zrTIEs#VLxzN)BZC;EsFi7wT! z`vZC+{WGf5hERfa%G>vJS-s+nIt4-`=L&?DLrnS?P^1rzt_xNseFgo`$w-zwY87K; z(F>ojIOmxPN)^wV+N!5j;i@Oswo@C5HWZm>KJ+@ypQZVF!L(NTc?Vsr%vRY7RWUEM z18QHy@+&`F&(^eWTY8>0tB9p;Ho)~mwo(SmYXj!XSwk90E|#!TnI(pUF{r>3)R;^* ze^6mm>UN-Z77O?G=C*ddo=HI8m$9m;rKO>vkH(<-0W-g0EnRf(Nm>!v9}5>&=2`if1n1;$g!tq0Rsgxn?2N5-nZOFc6NecU+gM&%s(JKV%oMbasVMbZBg9e!p812Z z7b{u#nymh0V%Y`(^6;TR4<2I;^hre_ZIt~3>)8JyFZlea!8IQ1^99#m+;J(VnPz&*RZ zmmr!8v|@o`)0xCQU8v}=NOyZqf6aQj!zjXv-6B6QRad*z$u)8XiV2*KNS`l zj-}!QN=7D1$_N}(;hX@7;hbM;RIC~=H=IeEIP%CCnCO3c9{rr_TPvQNg;mTaPN~sXzDIWB zkt-j`v6YZZNfupx!B|@pq+KLth#@kQc3+Mi$K0dmY6kk0!{P1ob}N6wAD&BytaqTC zi)aU$YkT5Als_cC<4b*oFe;X5+(~{%)WIQ-hP=rNj=)aiM!F9{NU^Lg0-H6hDEWSj z(truVhT0K_d!ZiK_XYGrJx}!W+Mo@3i$xt8 z*UNa;a7=;nA3iDe!z6v)e1`Sc?)sowI-$DxoZ>zuk=S#k#C5v34~KYN*L7V#Ri&tZ z4#@IUA90~3WbO2;@w(@G33t%NKuPgn->p2eZ%@hTYZXIMo0ZbaiVRfKgIy^FS}NK0 zUCFhpX#`EF>{5Y%y@qskbv47))$!^I31r89L?(G2pMWHrq)s|E$m0=(u!fK66uZJ( zPm}U=I=px6!eNr95Wj09ADy94=n}aziYUB%%l8avAw>YGD(|f3?FacrqVEjcvCBNs ziDfGz#bpJNbl?qL4Shq$`bgj~Z3q5S?}PaAUMb48Y(|1%wu+{P1)7I6V*=0^zm_o= zc`;<-MIAQ&!j9Jq2({eM6a{yDYiVVKMh#{)2h@yIddi_xw3Xk2sjDtf<;fCAA-gW) zU6qxU)jFhxJ@SFNJ|Tu$ilbzP$bxKbvuAD6^dfMAeM$HdIRZsK)@NR5%Y;IrcHX+#Pq}D!{lS?Vd7yj z!89|KU?RaZf@z0I1d|R^4wK9jGlgIR!PH~IVY*?0nO>$b*0UFFz#X#xlZvNcK1&~t z89UH^Z6YykgAu*`yW==6nYlmHi(K3rf{Hplj-n41`v!U?6N43f+ksUB>#oP3hkFWo zeXoPe?Qd06)l{iOd2BigWuF%-bW3cR#TNe?Uo4ZfXO=7>5{2OS3#SY4v9dPdnto=< z5+ZTPMG)d{6Iq%WBBP_33C{C8r_Jpb4|Grnm=(bz|BMEM!LVQjMVekgxS)IAmBB9A zs%9`4bU)6CHKZ*#5(jc)KjI}IaU93KLOzi8SB$8D1@;gwuu}CYAC7K&QARS&YSc3Q z_3hT6`^EvWl%Fx&Q&E+MH+CT!oSXYT!nt01S6p}OT4qpC+F8UyB#)MUhqN@ksOQ1J z2rcyGF<&H8Q&X)~38l?Ykp2Z_Ak)(8h7nXGk|fm3vhphnlgbiRV?5=N{W{|>k{r*? zD)>yBWwYP-scmvIhtEy$x2!Jb6&tKnp)$pqQiGHN&@jW53^Bm)f(tEJv9N*)DV$Jc zf&fY&VFVEZKn21FQ9AenfDQI1I&?|{DXn6ZGk@Ojt6$R6q%d+RYbPe5Zy*y>yK3=Q zRnlCUJk~;5&b8O77=KkI&6UYxEu>|)y;jBet14-(O#U&vR&6va5)K7{v~S*#d#~=d zYTnRX6QEXulmgH&!<7s%!0>_#EfBzJ1Q7y26{UkG&?qMv2!~Q9xx^f%tjqc3hW~#J zq$9hwK|`xJ!c&;47qT(2E?l-4KuZ|dmseL7EL>Y(sM9N}Dk>>7Zz`XX$Rl14g+Y3j zUlQ84t6H^8?2DgXS*1`#0#y|020Aofq9jQM7$_-t3gR>Y5D6lHAZK8^Cyi>aAwv^+ z$WYJNURa>bCb?~6H*rR_!YER#hofu z1RAwj}hQr~| zYB;=J)wS9b$E*DDSoVcPiY3L8$*-rUr>C-~Ctj&kDwR`Xv)OC{m(}J~0a__xw2D?T z6uo@=q2DS8qlCGl6j2CJ`wLR6L&b_WAfaz_S5laK)D1IE>jujG@Hj$1jA9BV`d(+W zrn=*!I=q2+$n7(5mCTdO1Y-2xzz84hnL7f5IYz(Ph`Asgl&2d}V=;4aPj_p_2x@L|zY4SB)PrTQc`4t{=L8Sx7X%HLH61YjG`ZS)lmpx$wrpO30PM88zgOeK$gZ9 zR@?MIOi85>?1~}@g&g#>{eE;ro7s)SEveIi)4KTUETAD


G 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 z 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

<( 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%0DKN(@qz%{GY^Shjp3_PZ$+#2c}f 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∨<0Pe_} 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 Wj+W{VDGz96Y9|vU2HFN(7s=$^Hb!Lt diff --git a/waterbox/ares64/BizInterface.cpp b/waterbox/ares64/BizInterface.cpp index dd7074429c..9ff179d9b4 100644 --- a/waterbox/ares64/BizInterface.cpp +++ b/waterbox/ares64/BizInterface.cpp @@ -31,19 +31,13 @@ typedef enum START = 1 << 13, } Buttons_t; -static u64 biztime = 0; - -static u64 GetBizTime() -{ - return biztime; -} - struct BizPlatform : ares::Platform { auto attach(ares::Node::Object) -> void override; auto pak(ares::Node::Object) -> ares::VFS::Pak override; auto audio(ares::Node::Audio::Stream) -> void override; auto input(ares::Node::Input::Input) -> void override; + auto time() -> n64 override; ares::VFS::Pak bizpak = nullptr; u16* soundbuf = alloc_invisible(1024 * 2); @@ -51,6 +45,7 @@ struct BizPlatform : ares::Platform bool hack = false; void (*inputcb)() = nullptr; bool lagged = true; + u64 biztime = 0; }; auto BizPlatform::attach(ares::Node::Object node) -> void @@ -88,7 +83,12 @@ auto BizPlatform::input(ares::Node::Input::Input node) -> void if (inputcb) inputcb(); } } -}; +} + +auto BizPlatform::time() -> n64 +{ + return biztime; +} static ares::Node::System root = nullptr; static BizPlatform* platform = nullptr; @@ -98,6 +98,7 @@ static array_view* romData = nullptr; static array_view* diskData = nullptr; static array_view* diskErrorData = nullptr; static array_view* saveData = nullptr; +static array_view* rtcData = nullptr; static array_view* gbRomData[4] = { nullptr, nullptr, nullptr, nullptr, }; typedef enum @@ -311,7 +312,8 @@ static inline SaveType DetectSaveType(u8* rom) if (id == "NW4") ret = FLASH128KB; if (id == "NDP") ret = FLASH128KB; - if(id[1] == 'E' && id[2] == 'D') { + if (id[1] == 'E' && id[2] == 'D') + { n8 config = revision; if (config.bit(4,7) == 1) ret = EEPROM512; else if (config.bit(4,7) == 2) ret = EEPROM2KB; @@ -324,6 +326,26 @@ static inline SaveType DetectSaveType(u8* rom) return ret; } +static inline bool DetectRtc(u8* rom) +{ + string id; + id.append((char)rom[0x3B]); + id.append((char)rom[0x3C]); + id.append((char)rom[0x3D]); + + u8 revision = rom[0x3f]; + + if (id == "NAF") return true; + + if (id[1] == 'E' && id[2] == 'D') + { + n8 config = revision; + return config.bit(0) == 1; + } + + return false; +} + namespace ares::Nintendo64 { extern bool BobDeinterlace; @@ -351,16 +373,6 @@ typedef struct GbRom GbRoms[4]; } LoadData; -#define SET_RTC_CALLBACK(NUM) do { \ - if (auto pad = dynamic_cast(ares::Nintendo64::controllerPort##NUM.device.data())) \ - { \ - if (auto mbc3 = dynamic_cast(pad->transferPak.mbc.data())) \ - { \ - mbc3->rtcCallback = GetBizTime; \ - } \ - } \ -} while (0) - static bool LoadRom(LoadData* loadData, bool isPal) { u8* data; @@ -406,6 +418,15 @@ static bool LoadRom(LoadData* loadData, bool isPal) platform->bizpak->append(name, *saveData); } + if (DetectRtc(data)) + { + len = 32, name = "save.rtc"; + data = new u8[len]; + memset(data, 0xFF, len); + rtcData = new array_view(data, len); + platform->bizpak->append(name, *rtcData); + } + if (auto port = root->find("Cartridge Slot")) { port->allocate(); @@ -464,8 +485,7 @@ ECL_EXPORT bool Init(LoadData* loadData, ControllerType* controllers, bool isPal platform->bizpak = new vfs::directory; ares::platform = platform; - biztime = initTime; - ares::Nintendo64::dd.rtcCallback = GetBizTime; + platform->biztime = initTime; angrylion::OutFrameBuffer = NULL; angrylion::OutHeight = isPal ? 576 : 480; @@ -579,11 +599,6 @@ ECL_EXPORT bool Init(LoadData* loadData, ControllerType* controllers, bool isPal } } - SET_RTC_CALLBACK(1); - SET_RTC_CALLBACK(2); - SET_RTC_CALLBACK(3); - SET_RTC_CALLBACK(4); - root->power(false); root->run(); // HACK, first frame dirties a ton of memory, so we emulate it then seal (this should be investigated, not sure why 60MBish of memory would be dirtied in a single frame?) return true; @@ -682,15 +697,17 @@ static u8 PeekFunc(u64 address) } } - return ares::Nintendo64::bus.read(addr); + u32 unused = 0; + return ares::Nintendo64::bus.read(addr, unused); } static void SysBusAccess(u8* buffer, u64 address, u64 count, bool write) { if (write) { + u32 unused = 0; while (count--) - ares::Nintendo64::bus.write(address++, *buffer++); + ares::Nintendo64::bus.write(address++, *buffer++, unused); } else { @@ -791,7 +808,7 @@ ECL_EXPORT void FrameAdvance(MyFrameInfo* f) angrylion::OutFrameBuffer = f->SkipDraw ? NULL : f->VideoBuffer; - biztime = f->Time; + platform->biztime = f->Time; if (f->Power) { @@ -828,7 +845,10 @@ ECL_EXPORT void SetInputCallback(void (*callback)()) ECL_EXPORT void PostLoadState() { + ares::Nintendo64::cpu.recompiler.allocator.release(bump_allocator::zero_fill); ares::Nintendo64::cpu.recompiler.reset(); + ares::Nintendo64::rsp.recompiler.allocator.release(bump_allocator::zero_fill); + ares::Nintendo64::rsp.recompiler.reset(); } ECL_EXPORT void GetDisassembly(u32 address, u32 instruction, char* buf) diff --git a/waterbox/ares64/Makefile b/waterbox/ares64/Makefile index 4cfd2cd859..19696ec6a1 100644 --- a/waterbox/ares64/Makefile +++ b/waterbox/ares64/Makefile @@ -1,10 +1,13 @@ NEED_LIBCO := 1 ARES_PATH = $(ROOT_DIR)/ares/ares +NALL_PATH = $(ROOT_DIR)/ares/nall THIRDPARTY_PATH = $(ROOT_DIR)/ares/thirdparty ANGRYLION_PATH = $(THIRDPARTY_PATH)/angrylion-rdp/mylittle-nocomment SLJIT_PATH = $(THIRDPARTY_PATH)/sljit/sljit_src +CCFLAGS := -march=x86-64-v2 -I.$(THIRDPARTY_PATH) -DSLJIT_HAVE_CONFIG_PRE=1 -DSLJIT_HAVE_CONFIG_POST=1 + CXXFLAGS := -std=gnu++17 -march=x86-64-v2 \ -I../libco -I.$(ROOT_DIR)/ares -I.$(ARES_PATH) -I.$(THIRDPARTY_PATH) -I.$(ANGRYLION_PATH) \ -Werror=int-to-pointer-cast -Wno-unused-but-set-variable -Wno-format-security \ @@ -12,11 +15,14 @@ CXXFLAGS := -std=gnu++17 -march=x86-64-v2 \ -Wno-sign-compare -Wno-switch -Wno-unused-local-typedefs -Wno-bool-operation \ -Wno-mismatched-tags -Wno-missing-braces -Wno-overloaded-virtual \ -Wno-unused-private-field -Wno-sometimes-uninitialized \ - -fno-strict-aliasing -fwrapv -fno-operator-names \ + -fno-strict-aliasing -fwrapv \ -DSLJIT_HAVE_CONFIG_PRE=1 -DSLJIT_HAVE_CONFIG_POST=1 TARGET = ares64.wbx +SRCS_NALL = \ + $(NALL_PATH)/nall.cpp + SRCS_PROCESSORS = \ $(ARES_PATH)/component/processor/sm5k/sm5k.cpp @@ -28,6 +34,7 @@ SRCS_N64 = \ $(ARES_PATH)/n64/memory/memory.cpp \ $(ARES_PATH)/n64/system/system.cpp \ $(ARES_PATH)/n64/cartridge/cartridge.cpp \ + $(ARES_PATH)/n64/cic/cic.cpp \ $(ARES_PATH)/n64/controller/controller.cpp \ $(ARES_PATH)/n64/dd/dd.cpp \ $(ARES_PATH)/n64/mi/mi.cpp \ @@ -50,6 +57,6 @@ SRCS_SLJIT = \ $(SLJIT_PATH)/sljitLir.c \ $(THIRDPARTY_PATH)/sljitAllocator.cpp -SRCS = $(SRCS_PROCESSORS) $(SRCS_ARES) $(SRCS_N64) $(SRCS_ANGRYLION) $(SRCS_SLJIT) BizInterface.cpp +SRCS = $(SRCS_NALL) $(SRCS_PROCESSORS) $(SRCS_ARES) $(SRCS_N64) $(SRCS_ANGRYLION) $(SRCS_SLJIT) BizInterface.cpp include ../common.mak diff --git a/waterbox/ares64/ares/ares/ares/ares.hpp b/waterbox/ares64/ares/ares/ares/ares.hpp index f406d455f5..0bba0202c0 100644 --- a/waterbox/ares64/ares/ares/ares/ares.hpp +++ b/waterbox/ares64/ares/ares/ares/ares.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -38,10 +39,11 @@ #include #include using namespace nall; +using namespace nall::primitives; namespace ares { static const string Name = "ares"; - static const string Version = "130.1"; + static const string Version = "132"; static const string Copyright = "ares team, Near"; static const string License = "ISC"; static const string LicenseURI = "https://opensource.org/licenses/ISC"; @@ -50,7 +52,6 @@ namespace ares { //incremented only when serialization format changes static const u32 SerializerSignature = 0x31545342; //"BST1" (little-endian) - static const string SerializerVersion = "130.3"; namespace VFS { using Pak = shared_pointer; diff --git a/waterbox/ares64/ares/ares/ares/memory/fixed-allocator.cpp b/waterbox/ares64/ares/ares/ares/memory/fixed-allocator.cpp index db5c2ff7b8..ee92ac771e 100644 --- a/waterbox/ares64/ares/ares/ares/memory/fixed-allocator.cpp +++ b/waterbox/ares64/ares/ares/ares/memory/fixed-allocator.cpp @@ -7,7 +7,7 @@ namespace ares::Memory { FixedAllocator::FixedAllocator() { } #else -alignas(4096) u8 fixedBuffer[8_MiB]; +alignas(4096) u8 fixedBuffer[128_MiB] ECL_INVISIBLE; FixedAllocator::FixedAllocator() { _allocator.resize(sizeof(fixedBuffer), 0, fixedBuffer); diff --git a/waterbox/ares64/ares/ares/ares/node/audio/stream.hpp b/waterbox/ares64/ares/ares/ares/node/audio/stream.hpp index 13c3007751..a928c1d5dd 100644 --- a/waterbox/ares64/ares/ares/ares/node/audio/stream.hpp +++ b/waterbox/ares64/ares/ares/ares/node/audio/stream.hpp @@ -25,7 +25,7 @@ struct Stream : Audio { template auto frame(P&&... p) -> void { if(runAhead()) return; - f64 samples[sizeof...(p)] = {std::forward

(p)...}; + f64 samples[sizeof...(p)] = {f64(std::forward

(p))...}; write(samples); } diff --git a/waterbox/ares64/ares/ares/ares/node/debugger/tracer/instruction.hpp b/waterbox/ares64/ares/ares/ares/node/debugger/tracer/instruction.hpp index 19b9545d37..0c354c3b2a 100644 --- a/waterbox/ares64/ares/ares/ares/node/debugger/tracer/instruction.hpp +++ b/waterbox/ares64/ares/ares/ares/node/debugger/tracer/instruction.hpp @@ -31,7 +31,7 @@ struct Instruction : Tracer { auto address(u64 address) -> bool { address &= ~0ull >> (64 - _addressBits); //mask upper bits of address _address = address; - /*address >>= _addressMask; //clip unneeded alignment bits (to reduce _masks size) + address >>= _addressMask; //clip unneeded alignment bits (to reduce _masks size) if(_mask) { auto mask = _masks.find(address); @@ -50,7 +50,7 @@ struct Instruction : Tracer { _history[index] = _history[index + 1]; } _history.last() = _address; - }*/ + } return true; } @@ -58,13 +58,13 @@ struct Instruction : Tracer { //mark an already-executed address as not executed yet for trace masking. //call when writing to executable RAM to support self-modifying code. auto invalidate(u64 address) -> void { - /*if(unlikely(_mask)) { + if(unlikely(_mask)) { address &= ~0ull >> (64 - _addressBits); address >>= _addressMask; auto mask = _masks.find(address); if(mask) mask->unvisit(address); - }*/ + } } auto notify(const string& instruction, const string& context, const string& extra = {}) -> void { diff --git a/waterbox/ares64/ares/ares/ares/platform.hpp b/waterbox/ares64/ares/ares/ares/platform.hpp index 5dd0c693b8..c2e670f4ac 100644 --- a/waterbox/ares64/ares/ares/ares/platform.hpp +++ b/waterbox/ares64/ares/ares/ares/platform.hpp @@ -20,6 +20,7 @@ struct Platform { virtual auto video(Node::Video::Screen, const u32* data, u32 pitch, u32 width, u32 height) -> void {} virtual auto audio(Node::Audio::Stream) -> void {} virtual auto input(Node::Input::Input) -> void {} + virtual auto time() -> n64 { return ::time(0); } }; extern Platform* platform; diff --git a/waterbox/ares64/ares/ares/component/processor/sm5k/disassembler.cpp b/waterbox/ares64/ares/ares/component/processor/sm5k/disassembler.cpp index 5c84321eb3..c305ea8f97 100644 --- a/waterbox/ares64/ares/ares/component/processor/sm5k/disassembler.cpp +++ b/waterbox/ares64/ares/ares/component/processor/sm5k/disassembler.cpp @@ -12,54 +12,54 @@ auto SM5K::disassembleInstruction() -> string { string pc = {"0x", hex(n4(opcode) << 8 | operand, 3L)}; switch(opcode) { - case 0x00 ... 0x0f: s = {"adx ", p4}; break; - case 0x10 ... 0x1f: s = {"lax ", p4}; break; - case 0x20 ... 0x2f: s = {"lblx ", p4}; break; - case 0x30 ... 0x3f: s = {"lbmx ", p4}; break; - case 0x40 ... 0x43: s = {"rm ", p2}; break; - case 0x44 ... 0x47: s = {"sm ", p2}; break; - case 0x48 ... 0x4b: s = {"tm ", p2}; break; - case 0x4c ... 0x4f: s = {"tpb ", p2}; break; - case 0x50 ... 0x53: s = {"lda ", p2}; break; - case 0x54 ... 0x57: s = {"exc ", p2}; break; - case 0x58 ... 0x5b: s = {"exci ", p2}; break; - case 0x5c ... 0x5f: s = {"excd ", p2}; break; - case 0x60: s = {"rc " }; break; - case 0x61: s = {"sc " }; break; - case 0x62: s = {"id " }; break; - case 0x63: s = {"ie " }; break; - case 0x64: s = {"exax " }; break; - case 0x65: s = {"atx " }; break; - case 0x66: s = {"exbm " }; break; - case 0x67: s = {"exbl " }; break; - case 0x68: s = {"ex " }; break; - case 0x69: s = {"dta ", p8}; break; - case 0x6a: s = {"pat ", p8}; break; - case 0x6b: s = {"tabl " }; break; - case 0x6c: s = {"ta " }; break; - case 0x6d: s = {"tb " }; break; - case 0x6e: s = {"tc " }; break; - case 0x6f: s = {"tam " }; break; - case 0x70: s = {"inl " }; break; - case 0x71: s = {"outl " }; break; - case 0x72: s = {"anp " }; break; - case 0x73: s = {"orp " }; break; - case 0x74: s = {"in " }; break; - case 0x75: s = {"out " }; break; - case 0x76: s = {"stop " }; break; - case 0x77: s = {"halt " }; break; - case 0x78: s = {"incb " }; break; - case 0x79: s = {"coma " }; break; - case 0x7a: s = {"add " }; break; - case 0x7b: s = {"adc " }; break; - case 0x7c: s = {"decb " }; break; - case 0x7d: s = {"rtn " }; break; - case 0x7e: s = {"rtns " }; break; - case 0x7f: s = {"rtni " }; break; - case 0x80 ... 0xbf: s = {"tr ", p6}; break; - case 0xc0 ... 0xdf: s = {"trs ", p5}; break; - case 0xe0 ... 0xef: s = {"tl ", pc}; break; - case 0xf0 ... 0xff: s = {"call ", pc}; break; + case range16(0x00, 0x0f): s = {"adx ", p4}; break; + case range16(0x10, 0x1f): s = {"lax ", p4}; break; + case range16(0x20, 0x2f): s = {"lblx ", p4}; break; + case range16(0x30, 0x3f): s = {"lbmx ", p4}; break; + case range4 (0x40, 0x43): s = {"rm ", p2}; break; + case range4 (0x44, 0x47): s = {"sm ", p2}; break; + case range4 (0x48, 0x4b): s = {"tm ", p2}; break; + case range4 (0x4c, 0x4f): s = {"tpb ", p2}; break; + case range4 (0x50, 0x53): s = {"lda ", p2}; break; + case range4 (0x54, 0x57): s = {"exc ", p2}; break; + case range4 (0x58, 0x5b): s = {"exci ", p2}; break; + case range4 (0x5c, 0x5f): s = {"excd ", p2}; break; + case 0x60: s = {"rc " }; break; + case 0x61: s = {"sc " }; break; + case 0x62: s = {"id " }; break; + case 0x63: s = {"ie " }; break; + case 0x64: s = {"exax " }; break; + case 0x65: s = {"atx " }; break; + case 0x66: s = {"exbm " }; break; + case 0x67: s = {"exbl " }; break; + case 0x68: s = {"ex " }; break; + case 0x69: s = {"dta ", p8}; break; + case 0x6a: s = {"pat ", p8}; break; + case 0x6b: s = {"tabl " }; break; + case 0x6c: s = {"ta " }; break; + case 0x6d: s = {"tb " }; break; + case 0x6e: s = {"tc " }; break; + case 0x6f: s = {"tam " }; break; + case 0x70: s = {"inl " }; break; + case 0x71: s = {"outl " }; break; + case 0x72: s = {"anp " }; break; + case 0x73: s = {"orp " }; break; + case 0x74: s = {"in " }; break; + case 0x75: s = {"out " }; break; + case 0x76: s = {"stop " }; break; + case 0x77: s = {"halt " }; break; + case 0x78: s = {"incb " }; break; + case 0x79: s = {"coma " }; break; + case 0x7a: s = {"add " }; break; + case 0x7b: s = {"adc " }; break; + case 0x7c: s = {"decb " }; break; + case 0x7d: s = {"rtn " }; break; + case 0x7e: s = {"rtns " }; break; + case 0x7f: s = {"rtni " }; break; + case range64(0x80, 0xbf): s = {"tr ", p6}; break; + case range32(0xc0, 0xdf): s = {"trs ", p5}; break; + case range16(0xe0, 0xef): s = {"tl ", pc}; break; + case range16(0xf0, 0xff): s = {"call ", pc}; break; } while(s.size() < 10) s.append(" "); diff --git a/waterbox/ares64/ares/ares/component/processor/sm5k/instruction.cpp b/waterbox/ares64/ares/ares/component/processor/sm5k/instruction.cpp index dc38b50f3d..b992f1f4fe 100644 --- a/waterbox/ares64/ares/ares/component/processor/sm5k/instruction.cpp +++ b/waterbox/ares64/ares/ares/component/processor/sm5k/instruction.cpp @@ -20,54 +20,54 @@ auto SM5K::instruction() -> void { n8 opcode = fetch(); switch(opcode) { - op(0x00 ... 0x0f, ADX, n4(opcode)); - op(0x10 ... 0x1f, LAX, n4(opcode)); - op(0x20 ... 0x2f, LBLX, n4(opcode)); - op(0x30 ... 0x3f, LBMX, n4(opcode)); - op(0x40 ... 0x43, RM, n2(opcode)); - op(0x44 ... 0x47, SM, n2(opcode)); - op(0x48 ... 0x4b, TM, n2(opcode)); - op(0x4c ... 0x4f, TPB, n2(opcode)); - op(0x50 ... 0x53, LDA, n2(opcode)); - op(0x54 ... 0x57, EXC, n2(opcode)); - op(0x58 ... 0x5b, EXCI, n2(opcode)); - op(0x5c ... 0x5f, EXCD, n2(opcode)); - op(0x60, RC ); - op(0x61, SC ); - op(0x62, ID ); - op(0x63, IE ); - op(0x64, EXAX ); - op(0x65, ATX ); - op(0x66, EXBM ); - op(0x67, EXBL ); - op(0x68, EX ); - op(0x69, DTA, fetch()); - op(0x6a, PAT, fetch()); - op(0x6b, TABL ); - op(0x6c, TA ); - op(0x6d, TB ); - op(0x6e, TC ); - op(0x6f, TAM ); - op(0x70, INL ); - op(0x71, OUTL ); - op(0x72, ANP ); - op(0x73, ORP ); - op(0x74, IN ); - op(0x75, OUT ); - op(0x76, STOP ); - op(0x77, HALT ); - op(0x78, INCB ); - op(0x79, COMA ); - op(0x7a, ADD ); - op(0x7b, ADC ); - op(0x7c, DECB ); - op(0x7d, RTN ); - op(0x7e, RTNS ); - op(0x7f, RTNI ); - op(0x80 ... 0xbf, TR, n6(opcode)); - op(0xc0 ... 0xdf, TRS, n5(opcode)); - op(0xe0 ... 0xef, TL, n4(opcode) << 8 | fetch()); - op(0xf0 ... 0xff, CALL, n4(opcode) << 8 | fetch()); + op(range16(0x00, 0x0f), ADX, n4(opcode)); + op(range16(0x10, 0x1f), LAX, n4(opcode)); + op(range16(0x20, 0x2f), LBLX, n4(opcode)); + op(range16(0x30, 0x3f), LBMX, n4(opcode)); + op(range4 (0x40, 0x43), RM, n2(opcode)); + op(range4 (0x44, 0x47), SM, n2(opcode)); + op(range4 (0x48, 0x4b), TM, n2(opcode)); + op(range4 (0x4c, 0x4f), TPB, n2(opcode)); + op(range4 (0x50, 0x53), LDA, n2(opcode)); + op(range4 (0x54, 0x57), EXC, n2(opcode)); + op(range4 (0x58, 0x5b), EXCI, n2(opcode)); + op(range4 (0x5c, 0x5f), EXCD, n2(opcode)); + op(0x60, RC ); + op(0x61, SC ); + op(0x62, ID ); + op(0x63, IE ); + op(0x64, EXAX ); + op(0x65, ATX ); + op(0x66, EXBM ); + op(0x67, EXBL ); + op(0x68, EX ); + op(0x69, DTA, fetch()); + op(0x6a, PAT, fetch()); + op(0x6b, TABL ); + op(0x6c, TA ); + op(0x6d, TB ); + op(0x6e, TC ); + op(0x6f, TAM ); + op(0x70, INL ); + op(0x71, OUTL ); + op(0x72, ANP ); + op(0x73, ORP ); + op(0x74, IN ); + op(0x75, OUT ); + op(0x76, STOP ); + op(0x77, HALT ); + op(0x78, INCB ); + op(0x79, COMA ); + op(0x7a, ADD ); + op(0x7b, ADC ); + op(0x7c, DECB ); + op(0x7d, RTN ); + op(0x7e, RTNS ); + op(0x7f, RTNI ); + op(range64(0x80, 0xbf), TR, n6(opcode)); + op(range32(0xc0, 0xdf), TRS, n5(opcode)); + op(range16(0xe0, 0xef), TL, n4(opcode) << 8 | fetch()); + op(range16(0xf0, 0xff), CALL, n4(opcode) << 8 | fetch()); } } diff --git a/waterbox/ares64/ares/ares/n64/accuracy.hpp b/waterbox/ares64/ares/ares/n64/accuracy.hpp index 76875d61b0..007ecd4641 100644 --- a/waterbox/ares64/ares/ares/n64/accuracy.hpp +++ b/waterbox/ares64/ares/ares/n64/accuracy.hpp @@ -3,7 +3,7 @@ struct Accuracy { static constexpr bool Reference = 0; struct CPU { - static constexpr bool Interpreter = 0 | Reference; + static constexpr bool Interpreter = 0 | Reference | !recompiler::generic::supported; static constexpr bool Recompiler = !Interpreter; //exceptions when the CPU accesses unaligned memory addresses @@ -11,7 +11,7 @@ struct Accuracy { }; struct RSP { - static constexpr bool Interpreter = 0 | Reference; + static constexpr bool Interpreter = 0 | Reference | !recompiler::generic::supported; static constexpr bool Recompiler = !Interpreter; //VU instructions @@ -22,4 +22,9 @@ struct Accuracy { struct RDRAM { static constexpr bool Broadcasting = 0; }; + + struct PIF { + // Emulate a region-locked console + static constexpr bool RegionLock = false; + }; }; diff --git a/waterbox/ares64/ares/ares/n64/ai/ai.hpp b/waterbox/ares64/ares/ares/n64/ai/ai.hpp index 5f3dee5313..a3b5a13f33 100644 --- a/waterbox/ares64/ares/ares/n64/ai/ai.hpp +++ b/waterbox/ares64/ares/ares/n64/ai/ai.hpp @@ -1,6 +1,6 @@ //Audio Interface -struct AI : Thread, Memory::IO { +struct AI : Thread, Memory::RCP { Node::Object node; Node::Audio::Stream stream; @@ -23,8 +23,8 @@ struct AI : Thread, Memory::IO { auto power(bool reset) -> void; //io.cpp - auto readWord(u32 address) -> u32; - auto writeWord(u32 address, u32 data) -> void; + auto readWord(u32 address, u32& cycles) -> u32; + auto writeWord(u32 address, u32 data, u32& cycles) -> void; //serialization.cpp auto serialize(serializer&) -> void; diff --git a/waterbox/ares64/ares/ares/n64/ai/io.cpp b/waterbox/ares64/ares/ares/n64/ai/io.cpp index 3f293a7e78..011d203033 100644 --- a/waterbox/ares64/ares/ares/n64/ai/io.cpp +++ b/waterbox/ares64/ares/ares/n64/ai/io.cpp @@ -1,4 +1,4 @@ -auto AI::readWord(u32 address) -> u32 { +auto AI::readWord(u32 address, u32& cycles) -> u32 { address = (address & 0xfffff) >> 2; n32 data; @@ -21,7 +21,7 @@ auto AI::readWord(u32 address) -> u32 { return data; } -auto AI::writeWord(u32 address, u32 data_) -> void { +auto AI::writeWord(u32 address, u32 data_, u32& cycles) -> void { address = (address & 0xfffff) >> 2; n32 data = data_; diff --git a/waterbox/ares64/ares/ares/n64/cartridge/cartridge.cpp b/waterbox/ares64/ares/ares/n64/cartridge/cartridge.cpp index de58f54f1f..9826499ec4 100644 --- a/waterbox/ares64/ares/ares/n64/cartridge/cartridge.cpp +++ b/waterbox/ares64/ares/ares/n64/cartridge/cartridge.cpp @@ -5,6 +5,8 @@ namespace ares::Nintendo64 { Cartridge& cartridge = cartridgeSlot.cartridge; #include "slot.cpp" #include "flash.cpp" +#include "rtc.cpp" +#include "joybus.cpp" #include "isviewer.cpp" #include "debugger.cpp" #include "serialization.cpp" @@ -43,6 +45,8 @@ auto Cartridge::connect() -> void { flash.load(fp); } + rtc.load(); + isviewer.ram.allocate(64_KiB); debugger.load(node); @@ -77,6 +81,8 @@ auto Cartridge::save() -> void { if(auto fp = pak->write("save.flash")) { flash.save(fp); } + + rtc.save(); } auto Cartridge::power(bool reset) -> void { @@ -85,6 +91,7 @@ auto Cartridge::power(bool reset) -> void { flash.source = 0; flash.offset = 0; isviewer.ram.fill(0); + rtc.power(reset); } } diff --git a/waterbox/ares64/ares/ares/n64/cartridge/cartridge.hpp b/waterbox/ares64/ares/ares/n64/cartridge/cartridge.hpp index 190a9526b3..22825ba5e3 100644 --- a/waterbox/ares64/ares/ares/n64/cartridge/cartridge.hpp +++ b/waterbox/ares64/ares/ares/n64/cartridge/cartridge.hpp @@ -38,14 +38,38 @@ struct Cartridge { u32 source = 0; u32 offset = 0; } flash; - struct ISViewer : Memory::IO { + struct ISViewer : Memory::PI { Memory::Writable ram; //unserialized //isviewer.cpp + auto readHalf(u32 address) -> u16; + auto writeHalf(u32 address, u16 data) -> void; auto readWord(u32 address) -> u32; auto writeWord(u32 address, u32 data) -> void; } isviewer; + struct RTC { + Cartridge& self; + RTC(Cartridge &self) : self(self) {} + + Memory::Writable ram; + n1 present; + n8 status; + n3 writeLock; + + // rtc.cpp + auto power(bool reset) -> void; + auto run(bool run) -> void; + auto running() -> bool; + auto load() -> void; + auto save() -> void; + auto tick(int nsec=1) -> void; + auto advance(int nsec) -> void; + auto serialize(serializer& s) -> void; + auto read(u2 block, n8 *data) -> void; + auto write(u2 block, n8 *data) -> void; + } rtc{*this}; + struct Debugger { //debugger.cpp auto load(Node::Object) -> void; @@ -67,10 +91,12 @@ struct Cartridge { auto allocate(Node::Port) -> Node::Peripheral; auto connect() -> void; auto disconnect() -> void; - auto save() -> void; auto power(bool reset) -> void; + //joybus.cpp + auto joybusComm(n8 send, n8 recv, n8 input[], n8 output[]) -> n2; + //serialization.cpp auto serialize(serializer&) -> void; diff --git a/waterbox/ares64/ares/ares/n64/cartridge/isviewer.cpp b/waterbox/ares64/ares/ares/n64/cartridge/isviewer.cpp index 496ad4d00a..f7df89abfa 100644 --- a/waterbox/ares64/ares/ares/n64/cartridge/isviewer.cpp +++ b/waterbox/ares64/ares/ares/n64/cartridge/isviewer.cpp @@ -1,22 +1,39 @@ -auto Cartridge::ISViewer::readWord(u32 address) -> u32 { - u32 data = ram.read(address); - address = (address & 0xffff) >> 2; - - if(address == 0) { - data = 0x49533634; //'IS64' - } - - return data; +auto Cartridge::ISViewer::readHalf(u32 address) -> u16 { + address = (address & 0xffff); + return ram.read(address); } -auto Cartridge::ISViewer::writeWord(u32 address, u32 data) -> void { - ram.write(address, data); - address = (address & 0xffff) >> 2; +auto Cartridge::ISViewer::readWord(u32 address) -> u32 { + address = (address & 0xffff); + return ram.read(address); +} - if(address == 5) { - for(auto address : range(u16(data))) { +auto Cartridge::ISViewer::writeHalf(u32 address, u16 data) -> void { + address = (address & 0xffff); + + if(address == 0x16) { + // HACK: allow printf output to work for both libultra and libdragon + // Libultra expects a real IS-Viewer device and treats this address as a + // pointer to the end of the buffer, reading the current value, writing N + // bytes, then updating the buffer pointer. + // libdragon instead treats this as a "number of bytes" register, only + // writing an "output byte count" + // In order to satisfy both libraries, we assume it behaves as libdragon + // expects, and by forcing the write to never hit ram, libultra remains + // functional. + for(auto address : range(data)) { char c = ram.read(0x20 + address); fputc(c, stdout); } + return; } + + ram.write(address, data); } + +auto Cartridge::ISViewer::writeWord(u32 address, u32 data) -> void { + address = (address & 0xffff); + writeHalf(address+0, data >> 16); + writeHalf(address+2, data & 0xffff); +} + diff --git a/waterbox/ares64/ares/ares/n64/cartridge/joybus.cpp b/waterbox/ares64/ares/ares/n64/cartridge/joybus.cpp new file mode 100644 index 0000000000..a2461d6b65 --- /dev/null +++ b/waterbox/ares64/ares/ares/n64/cartridge/joybus.cpp @@ -0,0 +1,75 @@ + +auto Cartridge::joybusComm(n8 send, n8 recv, n8 input[], n8 output[]) -> n2 { + n1 valid = 0, over = 0; + + //status + if(input[0] == 0x00 || input[0] == 0xff) { + //cartridge EEPROM (4kbit) + if(cartridge.eeprom.size == 512) { + output[0] = 0x00; + output[1] = 0x80; + output[2] = 0x00; + valid = 1; + } + + //cartridge EEPROM (16kbit) + if(cartridge.eeprom.size == 2048) { + output[0] = 0x00; + output[1] = 0xc0; + output[2] = 0x00; + valid = 1; + } + } + + //read EEPROM + if(input[0] == 0x04 && send >= 2) { + u32 address = input[1] * 8; + for(u32 index : range(recv)) { + output[index] = cartridge.eeprom.read(address++); + } + valid = 1; + } + + //write EEPROM + if(input[0] == 0x05 && send >= 2 && recv >= 1) { + u32 address = input[1] * 8; + for(u32 index : range(send - 2)) { + cartridge.eeprom.write(address++, input[2 + index]); + } + output[0] = 0x00; + valid = 1; + } + + //RTC status + if(input[0] == 0x06 && send >= 1 && recv >= 3) { + if(cartridge.rtc.present) { + output[0] = 0x00; + output[1] = 0x10; + output[2] = rtc.status; + valid = 1; + } + } + + //RTC read + if(input[0] == 0x07 && send >= 2 && recv >= 9) { + if(cartridge.rtc.present) { + rtc.read(input[1], &output[0]); + output[8] = 0x00; + valid = 1; + } + } + + //RTC write + if(input[0] == 0x08 && send >= 10 && recv >= 1) { + if(cartridge.rtc.present) { + rtc.write(input[1], &input[2]); + output[0] = 0x00; + valid = 1; + } + } + + n2 status; + status.bit(0) = valid; + status.bit(1) = over; + return status; +} diff --git a/waterbox/ares64/ares/ares/n64/cartridge/rtc.cpp b/waterbox/ares64/ares/ares/n64/cartridge/rtc.cpp new file mode 100644 index 0000000000..66530fa593 --- /dev/null +++ b/waterbox/ares64/ares/ares/n64/cartridge/rtc.cpp @@ -0,0 +1,102 @@ + +auto Cartridge::RTC::power(bool reset) -> void { + if(present) run(!status.bit(7)); +} + +auto Cartridge::RTC::load() -> void { + if(auto fp = self.pak->read("save.rtc")) { + ram.allocate(fp->size()); + ram.load(fp); + + present = 1; + n64 timestamp = ram.read(24); + if(!~timestamp) { + ram.fill(0); + ram.write(21, 1); + } + + timestamp = platform->time() - timestamp; + advance(timestamp); + } +} + +auto Cartridge::RTC::save() -> void { +#if false + if(auto fp = self.pak->write("save.rtc")) { + ram.write(24, time(0)); + ram.save(fp); + } +#endif +} + +auto Cartridge::RTC::tick(int nsec) -> void { + advance(nsec); + run(true); +} + +auto Cartridge::RTC::run(bool run) -> void { + status.bit(7) = !run; + queue.remove(Queue::RTC_Tick); + if(run) queue.insert(Queue::RTC_Tick, 187'500'000); +} + +auto Cartridge::RTC::running() -> bool { + return !status.bit(7); +} + +auto Cartridge::RTC::advance(int nsec) -> void { + struct tm tmm = {}; + tmm.tm_sec = BCD::decode(ram.read(16)); + tmm.tm_min = BCD::decode(ram.read(17)); + tmm.tm_hour = BCD::decode(ram.read(18) & 0x7f); + tmm.tm_mday = BCD::decode(ram.read(19)); + tmm.tm_mon = BCD::decode(ram.read(21)) - 1; + tmm.tm_year = BCD::decode(ram.read(22)) + 100 * BCD::decode(ram.read(23)); + time_t t = mktime(&tmm); + + t += nsec; + + tmm = *localtime(&t); + ram.write(16, BCD::encode(tmm.tm_sec)); + ram.write(17, BCD::encode(tmm.tm_min)); + ram.write(18, BCD::encode(tmm.tm_hour) | 0x80); + ram.write(19, BCD::encode(tmm.tm_mday)); + ram.write(20, BCD::encode(tmm.tm_wday)); + ram.write(21, BCD::encode(tmm.tm_mon + 1)); + ram.write(22, BCD::encode(tmm.tm_year % 100)); + ram.write(23, BCD::encode(tmm.tm_year / 100)); +} + +auto Cartridge::RTC::read(u2 block, n8* data) -> void { + data[0] = ram.read(block*8 + 0); + data[1] = ram.read(block*8 + 1); + data[2] = ram.read(block*8 + 2); + data[3] = ram.read(block*8 + 3); + data[4] = ram.read(block*8 + 4); + data[5] = ram.read(block*8 + 5); + data[6] = ram.read(block*8 + 6); + data[7] = ram.read(block*8 + 7); +} + +auto Cartridge::RTC::write(u2 block, n8* data) -> void { + if (writeLock.bit(block)) return; + ram.write(block*8 + 0, data[0]); + ram.write(block*8 + 1, data[1]); + ram.write(block*8 + 2, data[2]); + ram.write(block*8 + 3, data[3]); + ram.write(block*8 + 4, data[4]); + ram.write(block*8 + 5, data[5]); + ram.write(block*8 + 6, data[6]); + ram.write(block*8 + 7, data[7]); + if(block == 0) { + n16 control = ram.read(0); + writeLock.bit(1,2) = control.bit(8,9); + run(!control.bit(2)); + } +} + +auto Cartridge::RTC::serialize(serializer& s) -> void { + s(ram); + s(status); + s(writeLock); +} diff --git a/waterbox/ares64/ares/ares/n64/cartridge/serialization.cpp b/waterbox/ares64/ares/ares/n64/cartridge/serialization.cpp index 49a70aac66..72c96f2d97 100644 --- a/waterbox/ares64/ares/ares/n64/cartridge/serialization.cpp +++ b/waterbox/ares64/ares/ares/n64/cartridge/serialization.cpp @@ -2,4 +2,5 @@ auto Cartridge::serialize(serializer& s) -> void { s(ram); s(eeprom); s(flash); + s(rtc); } diff --git a/waterbox/ares64/ares/ares/n64/cic/cic.cpp b/waterbox/ares64/ares/ares/n64/cic/cic.cpp new file mode 100644 index 0000000000..c0d85195de --- /dev/null +++ b/waterbox/ares64/ares/ares/n64/cic/cic.cpp @@ -0,0 +1,93 @@ +#include + +namespace ares::Nintendo64 { + +CIC cic; +#include "io.cpp" +#include "commands.cpp" +#include "serialization.cpp" + +auto CIC::power(bool reset) -> void { + model = cartridge.node ? cartridge.cic() : dd.cic(); + type = Cartridge; + challengeAlgo = DummyChallenge; + if(model == "CIC-NUS-6101") region = NTSC, seed = 0x3f, checksum = 0x45cc73ee317aull; + if(model == "CIC-NUS-6102") region = NTSC, seed = 0x3f, checksum = 0xa536c0f1d859ull; + if(model == "CIC-NUS-7101") region = PAL, seed = 0x3f, checksum = 0xa536c0f1d859ull; + if(model == "CIC-NUS-7102") region = PAL, seed = 0x3f, checksum = 0x44160ec5d9afull; + if(model == "CIC-NUS-6103") region = NTSC, seed = 0x78, checksum = 0x586fd4709867ull; + if(model == "CIC-NUS-7103") region = PAL, seed = 0x78, checksum = 0x586fd4709867ull; + if(model == "CIC-NUS-6105") region = NTSC, seed = 0x91, checksum = 0x8618a45bc2d3ull, challengeAlgo = RealChallenge; + if(model == "CIC-NUS-7105") region = PAL, seed = 0x91, checksum = 0x8618a45bc2d3ull, challengeAlgo = RealChallenge; + if(model == "CIC-NUS-6106") region = NTSC, seed = 0x85, checksum = 0x2bbad4e6eb74ull; + if(model == "CIC-NUS-7106") region = PAL, seed = 0x85, checksum = 0x2bbad4e6eb74ull; + if(model == "CIC-NUS-8303") region = NTSC, seed = 0xdd, checksum = 0x32b294e2ab90ull, type = DD64; + if(model == "CIC-NUS-8401") region = NTSC, seed = 0xdd, checksum = 0x6ee8d9e84970ull, type = DD64; + if(model == "CIC-NUS-5167") region = NTSC, seed = 0xdd, checksum = 0x083c6c77e0b1ull; + if(model == "CIC-NUS-DDUS") region = NTSC, seed = 0xde, checksum = 0x05ba2ef0a5f1ull, type = DD64; + state = BootRegion; + fifo.bits.resize(32*4); +} + +auto CIC::scramble(n4 *buf, int size) -> void { + for(int i : range(1,size)) buf[i] += buf[i-1] + 1; +} + +auto CIC::poll() -> void { + if(state == BootRegion) { + fifo.write(type); + fifo.write(region == PAL); + fifo.write(0); + fifo.write(1); + state = BootSeed; + return; + } + + if(state == BootSeed) { + n4 buf[6]; + buf[0] = 0xB; + buf[1] = 0x5; + buf[2] = seed.bit(4,7); + buf[3] = seed.bit(0,3); + buf[4] = seed.bit(4,7); + buf[5] = seed.bit(0,3); + for (auto i : range(2)) scramble(buf, 6); + for (auto i : range(6)) fifo.writeNibble(buf[i]); + state = BootChecksum; + return; + } + + if(state == BootChecksum) { + n4 buf[16]; + buf[0] = 0x4; //true random + buf[1] = 0x7; //true random + buf[2] = 0xA; //true random + buf[3] = 0x1; //true random + for (auto i : range(12)) buf[i+4] = checksum.bit(44-i*4,47-i*4); + for (auto i : range(4)) scramble(buf, 16); + for (auto i : range(16)) fifo.writeNibble(buf[i]); + state = Run; + return; + } + + if(state == Run && fifo.size() >= 2) { + n2 cmd; + cmd.bit(1) = fifo.read(); + cmd.bit(0) = fifo.read(); + if(cmd == 0b00) return cmdCompare(); + if(cmd == 0b01) return cmdDie(); + if(cmd == 0b10) return cmdChallenge(); + if(cmd == 0b11) return cmdReset(); + return; + } + + if(state == Challenge) { + return cmdChallenge(); + } + + if(state == Dead) { + return; + } +} + +} \ No newline at end of file diff --git a/waterbox/ares64/ares/ares/n64/cic/cic.hpp b/waterbox/ares64/ares/ares/n64/cic/cic.hpp new file mode 100644 index 0000000000..95b2e57f0c --- /dev/null +++ b/waterbox/ares64/ares/ares/n64/cic/cic.hpp @@ -0,0 +1,60 @@ + +struct CIC { + enum State : u32 { BootRegion, BootSeed, BootChecksum, Run, Challenge, Dead }; + enum Region : u32 { NTSC, PAL }; + enum ChallengeAlgo : bool { DummyChallenge, RealChallenge }; + enum Type : u32 { Cartridge, DD64 }; + + struct { + nall::queue bits; + + auto empty() -> bool { return bits.empty(); } + auto size() -> u32 { return bits.size(); } + auto write(n1 data) -> void { bits.write(data); } + auto read() -> n1 { return bits.read(); } + auto writeNibble(n4 data) -> void { + write(data.bit(3)); + write(data.bit(2)); + write(data.bit(1)); + write(data.bit(0)); + } + auto readNibble() -> n4 { + n4 data; + data.bit(3) = read(); + data.bit(2) = read(); + data.bit(1) = read(); + data.bit(0) = read(); + return data; + } + } fifo; + n8 seed; + n48 checksum; //ipl2 checksum + n1 type; + n1 region; + n1 challengeAlgo; + u32 state; + string model; + + //cic.cpp + auto power(bool reset) -> void; + auto poll() -> void; + auto scramble(n4 *buf, int size) -> void; + + //io.cpp + auto readBit() -> n1; + auto readNibble() -> n4; + auto writeBit(n1 cmd) -> void; + auto writeNibble(n4 cmd) -> void; + + //commands.cpp + auto cmdCompare() -> void; + auto cmdDie() -> void; + auto cmdChallenge() -> void; + auto cmdReset() -> void; + auto challenge(n4 data[30]) -> void; + + //serialization.cpp + auto serialize(serializer&) -> void; +}; + +extern CIC cic; diff --git a/waterbox/ares64/ares/ares/n64/cic/commands.cpp b/waterbox/ares64/ares/ares/n64/cic/commands.cpp new file mode 100644 index 0000000000..bb7fee96ea --- /dev/null +++ b/waterbox/ares64/ares/ares/n64/cic/commands.cpp @@ -0,0 +1,65 @@ + +auto CIC::cmdCompare() -> void { +} + +auto CIC::challenge(n4 mem[30]) -> void { + if(challengeAlgo == DummyChallenge) { + for(u32 address : range(30)) + mem[address] = ~mem[address]; + return; + } + + //CIC-NUS-6105 anti-piracy challenge + if(challengeAlgo == RealChallenge) { + static n4 lut[32] = { + 0x4, 0x7, 0xa, 0x7, 0xe, 0x5, 0xe, 0x1, + 0xc, 0xf, 0x8, 0xf, 0x6, 0x3, 0x6, 0x9, + 0x4, 0x1, 0xa, 0x7, 0xe, 0x5, 0xe, 0x1, + 0xc, 0x9, 0x8, 0x5, 0x6, 0x3, 0xc, 0x9, + }; + + n4 key = 0xb; + n1 sel = 0; + for(u32 address : range(30)) { + n4 data = key + 5 * mem[address]; + mem[address] = data; + key = lut[sel << 4 | data]; + n1 mod = data >> 3; + n3 mag = data >> 0; + if(mod) mag = ~mag; + if(mag % 3 != 1) mod = !mod; + if(sel) { + if(data == 0x1 || data == 0x9) mod = 1; + if(data == 0xb || data == 0xe) mod = 0; + } + sel = mod; + } + return; + } +} + +auto CIC::cmdChallenge() -> void { + if(state == Run) { + fifo.writeNibble(0xa); + fifo.writeNibble(0xa); + state = Challenge; + } + if(state == Challenge && fifo.size() == 30*4) { + n4 data[30]; + for (auto i : range(30)) data[i] = fifo.readNibble(); + challenge(data); + fifo.write(0); // write 0 bit + for (auto i : range(30)) fifo.writeNibble(data[i]); + state = Run; + printf("CIC challenge complete %d\n", fifo.size()); + } +} + +auto CIC::cmdDie() -> void { + debug(unusual, "[CIC::cmdDie] die command received by PIF"); + state = Dead; +} + +auto CIC::cmdReset() -> void { + debug(unimplemented, "[CIC::cmdReset]"); +} diff --git a/waterbox/ares64/ares/ares/n64/cic/io.cpp b/waterbox/ares64/ares/ares/n64/cic/io.cpp new file mode 100644 index 0000000000..78c2df701b --- /dev/null +++ b/waterbox/ares64/ares/ares/n64/cic/io.cpp @@ -0,0 +1,21 @@ + +auto CIC::writeBit(n1 data) -> void { + fifo.write(data); + poll(); +} + +auto CIC::writeNibble(n4 data) -> void { + fifo.writeNibble(data); + poll(); +} + +auto CIC::readBit() -> n1 { + if(fifo.empty()) cic.poll(); + return fifo.read(); +} + +auto CIC::readNibble() -> n4 { + if (fifo.empty()) cic.poll(); + return fifo.readNibble(); +} + diff --git a/waterbox/ares64/ares/ares/n64/cic/serialization.cpp b/waterbox/ares64/ares/ares/n64/cic/serialization.cpp new file mode 100644 index 0000000000..3f9b50877d --- /dev/null +++ b/waterbox/ares64/ares/ares/n64/cic/serialization.cpp @@ -0,0 +1,10 @@ + +auto CIC::serialize(serializer& s) -> void { + s(fifo.bits); + s(seed); + s(checksum); + s(type); + s(region); + s(challengeAlgo); + s(state); +} diff --git a/waterbox/ares64/ares/ares/n64/controller/controller.hpp b/waterbox/ares64/ares/ares/n64/controller/controller.hpp index 3dc1f706b6..64b9db84c7 100644 --- a/waterbox/ares64/ares/ares/n64/controller/controller.hpp +++ b/waterbox/ares64/ares/ares/n64/controller/controller.hpp @@ -4,6 +4,7 @@ struct Controller { virtual ~Controller() = default; virtual auto save() -> void {} virtual auto comm(n8 send, n8 recv, n8 input[], n8 output[]) -> n2 { return 1; } + virtual auto reset() -> void {} virtual auto read() -> n32 { return 0; } virtual auto serialize(serializer&) -> void {} }; diff --git a/waterbox/ares64/ares/ares/n64/controller/gamepad/gamepad.cpp b/waterbox/ares64/ares/ares/n64/controller/gamepad/gamepad.cpp index 98b203a2f9..25f2aeecda 100644 --- a/waterbox/ares64/ares/ares/n64/controller/gamepad/gamepad.cpp +++ b/waterbox/ares64/ares/ares/n64/controller/gamepad/gamepad.cpp @@ -33,7 +33,7 @@ Gamepad::~Gamepad() { } auto Gamepad::save() -> void { -/* +#if false if(!slot) return; if(slot->name() == "Controller Pak") { ram.save(pak->write("save.pak")); @@ -43,7 +43,7 @@ auto Gamepad::save() -> void { transferPak.ram.save(pak->write("gbram.pak")); } } -*/ +#endif } auto Gamepad::allocate(string name) -> Node::Peripheral { @@ -135,36 +135,41 @@ auto Gamepad::comm(n8 send, n8 recv, n8 input[], n8 output[]) -> n2 { if(input[0] == 0x02 && send >= 3 && recv >= 1) { //controller pak if(ram) { - u32 address = (input[1] << 8 | input[2] << 0) & ~31; + u16 address = (input[1] << 8 | input[2] << 0) & ~31; if(pif.addressCRC(address) == (n5)input[2]) { for(u32 index : range(recv - 1)) { - output[index] = ram.read(address++); + if(address <= 0x7FFF) output[index] = ram.read(address); + else output[index] = 0; + address++; } - output[recv - 1] = pif.dataCRC({&output[0], recv - 1}); + output[recv - 1] = pif.dataCRC({&output[0], recv - 1u}); valid = 1; } } //rumble pak if(motor) { - u32 address = (input[1] << 8 | input[2] << 0) & ~31; + u16 address = (input[1] << 8 | input[2] << 0) & ~31; if(pif.addressCRC(address) == (n5)input[2]) { for(u32 index : range(recv - 1)) { - output[index] = 0x80; + if(address <= 0x7FFF) output[index] = 0; + else if(address <= 0x8FFF) output[index] = 0x80; + else output[index] = motor->enable() ? 0xFF : 0x00; + address++; } - output[recv - 1] = pif.dataCRC({&output[0], recv - 1}); + output[recv - 1] = pif.dataCRC({&output[0], recv - 1u}); valid = 1; } } //transfer pak if(transferPak) { - u32 address = (input[1] << 8 | input[2] << 0) & ~31; + u16 address = (input[1] << 8 | input[2] << 0) & ~31; if(pif.addressCRC(address) == (n5)input[2]) { for(u32 index : range(recv - 1)) { output[index] = transferPak.read(address++); } - output[recv - 1] = pif.dataCRC({&output[0], recv - 1}); + output[recv - 1] = pif.dataCRC({&output[0], recv - 1u}); valid = 1; } } @@ -174,34 +179,35 @@ auto Gamepad::comm(n8 send, n8 recv, n8 input[], n8 output[]) -> n2 { if(input[0] == 0x03 && send >= 3 && recv >= 1) { //controller pak if(ram) { - u32 address = (input[1] << 8 | input[2] << 0) & ~31; + u16 address = (input[1] << 8 | input[2] << 0) & ~31; if(pif.addressCRC(address) == (n5)input[2]) { for(u32 index : range(send - 3)) { - ram.write(address++, input[3 + index]); + if(address <= 0x7FFF) ram.write(address, input[3 + index]); + address++; } - output[0] = pif.dataCRC({&input[3], send - 3}); + output[0] = pif.dataCRC({&input[3], send - 3u}); valid = 1; } } //rumble pak if(motor) { - u32 address = (input[1] << 8 | input[2] << 0) & ~31; + u16 address = (input[1] << 8 | input[2] << 0) & ~31; if(pif.addressCRC(address) == (n5)input[2]) { - output[0] = pif.dataCRC({&input[3], send - 3}); + output[0] = pif.dataCRC({&input[3], send - 3u}); valid = 1; - rumble(input[3] & 1); + if(address >= 0xC000) rumble(input[3] & 1); } } //transfer pak if(transferPak) { - u32 address = (input[1] << 8 | input[2] << 0) & ~31; + u16 address = (input[1] << 8 | input[2] << 0) & ~31; if(pif.addressCRC(address) == (n5)input[2]) { for(u32 index : range(send - 3)) { transferPak.write(address++, input[3 + index]); } - output[0] = pif.dataCRC({&input[3], send - 3}); + output[0] = pif.dataCRC({&input[3], send - 3u}); valid = 1; } } @@ -231,6 +237,47 @@ auto Gamepad::read() -> n32 { platform->input(z); platform->input(start); +#if false + //scale {-32768 ... +32767} to {-85 ... +85} + auto ax = x->value() * 85.0 / 32767.0; + auto ay = y->value() * 85.0 / 32767.0; + + //create inner axial dead-zone in range {-7 ... +7} and scale from it up to outer circular dead-zone of radius 85 + auto length = sqrt(ax * ax + ay * ay); + if(length <= 85.0) { + auto lengthAbsoluteX = abs(ax); + auto lengthAbsoluteY = abs(ay); + if(lengthAbsoluteX <= 7.0) { + lengthAbsoluteX = 0.0; + } else { + lengthAbsoluteX = (lengthAbsoluteX - 7.0) * 85.0 / (85.0 - 7.0) / lengthAbsoluteX; + } + ax *= lengthAbsoluteX; + if(lengthAbsoluteY <= 7.0) { + lengthAbsoluteY = 0.0; + } else { + lengthAbsoluteY = (lengthAbsoluteY - 7.0) * 85.0 / (85.0 - 7.0) / lengthAbsoluteY; + } + ay *= lengthAbsoluteY; + } else { + length = 85.0 / length; + ax *= length; + ay *= length; + } + + //bound diagonals to an octagonal range {-69 ... +69} + if(ax != 0.0 && ay != 0.0) { + auto slope = ay / ax; + auto edgex = copysign(85.0 / (abs(slope) + 16.0 / 69.0), ax); + auto edgey = copysign(min(abs(edgex * slope), 85.0 / (1.0 / abs(slope) + 16.0 / 69.0)), ay); + edgex = edgey / slope; + + auto scale = sqrt(edgex * edgex + edgey * edgey) / 85.0; + ax *= scale; + ay *= scale; + } +#endif + n32 data; data.byte(0) = y->value(); data.byte(1) = x->value(); diff --git a/waterbox/ares64/ares/ares/n64/controller/gamepad/mbc/mbc.hpp b/waterbox/ares64/ares/ares/n64/controller/gamepad/mbc/mbc.hpp index 6bcff0a22e..39863d9a74 100644 --- a/waterbox/ares64/ares/ares/n64/controller/gamepad/mbc/mbc.hpp +++ b/waterbox/ares64/ares/ares/n64/controller/gamepad/mbc/mbc.hpp @@ -10,6 +10,11 @@ protected: Memory::Writable& ram; }; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wgnu-case-range" + #include "mbc1.hpp" #include "mbc3.hpp" #include "mbc5.hpp" + +#pragma clang diagnostic pop diff --git a/waterbox/ares64/ares/ares/n64/controller/gamepad/mbc/mbc3.hpp b/waterbox/ares64/ares/ares/n64/controller/gamepad/mbc/mbc3.hpp index ca70a63a3b..36f0b2511d 100644 --- a/waterbox/ares64/ares/ares/n64/controller/gamepad/mbc/mbc3.hpp +++ b/waterbox/ares64/ares/ares/n64/controller/gamepad/mbc/mbc3.hpp @@ -2,7 +2,7 @@ struct Mbc3 : Mbc { explicit Mbc3(Memory::Readable& rom_, Memory::Writable& ram_, bool rtc) : Mbc(rom_, ram_), hasRtc(rtc) { reset(); } inline auto rtcUpdate() -> void { - u64 diff = rtcCallback() - lastTime; + u64 diff = platform->time() - lastTime; lastTime += diff; if(!rtcHalt) { s8 seconds = rtcSeconds; @@ -146,6 +146,4 @@ private: n8 rtcLatches[5] = {}; u64 lastTime = 0; -public: - std::function rtcCallback = []() { return 0; }; }; diff --git a/waterbox/ares64/ares/ares/n64/controller/port.cpp b/waterbox/ares64/ares/ares/n64/controller/port.cpp index 580a94f9b0..9cd9bc6ac4 100644 --- a/waterbox/ares64/ares/ares/n64/controller/port.cpp +++ b/waterbox/ares64/ares/ares/n64/controller/port.cpp @@ -12,6 +12,7 @@ auto ControllerPort::load(Node::Object parent) -> void { port->setType("Controller"); port->setHotSwappable(true); port->setAllocate([&](auto name) { return allocate(name); }); + port->setDisconnect([&] { device.reset(); }); port->setSupported({"Gamepad", "Mouse"}); } @@ -25,7 +26,6 @@ auto ControllerPort::save() -> void { } auto ControllerPort::allocate(string name) -> Node::Peripheral { - device = {}; if(name == "Gamepad") device = new Gamepad(port); if(name == "Mouse" ) device = new Mouse(port); if(device) return device->node; diff --git a/waterbox/ares64/ares/ares/n64/cpu/algorithms.cpp b/waterbox/ares64/ares/ares/n64/cpu/algorithms.cpp index 7eec4187a4..37a2ece7dd 100644 --- a/waterbox/ares64/ares/ares/n64/cpu/algorithms.cpp +++ b/waterbox/ares64/ares/ares/n64/cpu/algorithms.cpp @@ -2,7 +2,7 @@ template auto CPU::roundNearest(f32 f) -> T { #if defined(ARCHITECTURE_ARM64) return vrndns_f32(f); -#elif defined(ARCHITECTURE_AMD64) +#elif defined(ARCHITECTURE_AMD64) && ARCHITECTURE_SUPPORTS_SSE4_1 __m128 t = _mm_set_ss(f); t = _mm_round_ss(t, t, _MM_FROUND_TO_NEAREST_INT); return _mm_cvtss_f32(t); @@ -14,9 +14,9 @@ auto CPU::roundNearest(f32 f) -> T { template auto CPU::roundNearest(f64 f) -> T { #if defined(ARCHITECTURE_ARM64) - float64x1_t vf = {f}; - return vrndn_f64(vf)[0]; -#elif defined(ARCHITECTURE_AMD64) + float64x1_t vf = vdup_n_f64(f); + return vget_lane_f64(vrndn_f64(vf), 0); +#elif defined(ARCHITECTURE_AMD64) && ARCHITECTURE_SUPPORTS_SSE4_1 __m128d t = _mm_set_sd(f); t = _mm_round_sd(t, t, _MM_FROUND_TO_NEAREST_INT); return _mm_cvtsd_f64(t); @@ -27,7 +27,7 @@ auto CPU::roundNearest(f64 f) -> T { template auto CPU::roundCeil(f32 f) -> T { -#if defined(ARCHITECTURE_AMD64) +#if defined(ARCHITECTURE_AMD64) && ARCHITECTURE_SUPPORTS_SSE4_1 __m128 t = _mm_set_ss(f); t = _mm_round_ss(t, t, _MM_FROUND_TO_POS_INF); return _mm_cvtss_f32(t); @@ -38,7 +38,7 @@ auto CPU::roundCeil(f32 f) -> T { template auto CPU::roundCeil(f64 f) -> T { -#if defined(ARCHITECTURE_AMD64) +#if defined(ARCHITECTURE_AMD64) && ARCHITECTURE_SUPPORTS_SSE4_1 __m128d t = _mm_set_sd(f); t = _mm_round_sd(t, t, _MM_FROUND_TO_POS_INF); return _mm_cvtsd_f64(t); @@ -49,7 +49,7 @@ auto CPU::roundCeil(f64 f) -> T { template auto CPU::roundCurrent(f32 f) -> T { -#if defined(ARCHITECTURE_AMD64) +#if defined(ARCHITECTURE_AMD64) && ARCHITECTURE_SUPPORTS_SSE4_1 auto t = _mm_set_ss(f); t = _mm_round_ss(t, t, _MM_FROUND_CUR_DIRECTION); return _mm_cvtss_f32(t); @@ -60,7 +60,7 @@ auto CPU::roundCurrent(f32 f) -> T { template auto CPU::roundCurrent(f64 f) -> T { -#if defined(ARCHITECTURE_AMD64) +#if defined(ARCHITECTURE_AMD64) && ARCHITECTURE_SUPPORTS_SSE4_1 auto t = _mm_set_sd(f); t = _mm_round_sd(t, t, _MM_FROUND_CUR_DIRECTION); return _mm_cvtsd_f64(t); @@ -71,7 +71,7 @@ auto CPU::roundCurrent(f64 f) -> T { template auto CPU::roundFloor(f32 f) -> T { -#if defined(ARCHITECTURE_AMD64) +#if defined(ARCHITECTURE_AMD64) && ARCHITECTURE_SUPPORTS_SSE4_1 __m128 t = _mm_set_ss(f); t = _mm_round_ss(t, t, _MM_FROUND_TO_NEG_INF); return _mm_cvtss_f32(t); @@ -82,7 +82,7 @@ auto CPU::roundFloor(f32 f) -> T { template auto CPU::roundFloor(f64 f) -> T { -#if defined(ARCHITECTURE_AMD64) +#if defined(ARCHITECTURE_AMD64) && ARCHITECTURE_SUPPORTS_SSE4_1 __m128d t = _mm_set_sd(f); t = _mm_round_sd(t, t, _MM_FROUND_TO_NEG_INF); return _mm_cvtsd_f64(t); @@ -93,7 +93,7 @@ auto CPU::roundFloor(f64 f) -> T { template auto CPU::roundTrunc(f32 f) -> T { -#if defined(ARCHITECTURE_AMD64) +#if defined(ARCHITECTURE_AMD64) && ARCHITECTURE_SUPPORTS_SSE4_1 __m128 t = _mm_set_ss(f); t = _mm_round_ss(t, t, _MM_FROUND_TO_ZERO); return _mm_cvtss_f32(t); @@ -104,7 +104,7 @@ auto CPU::roundTrunc(f32 f) -> T { template auto CPU::roundTrunc(f64 f) -> T { -#if defined(ARCHITECTURE_AMD64) +#if defined(ARCHITECTURE_AMD64) && ARCHITECTURE_SUPPORTS_SSE4_1 __m128d t = _mm_set_sd(f); t = _mm_round_sd(t, t, _MM_FROUND_TO_ZERO); return _mm_cvtsd_f64(t); diff --git a/waterbox/ares64/ares/ares/n64/cpu/cpu.cpp b/waterbox/ares64/ares/ares/n64/cpu/cpu.cpp index bb7e9e1b4a..956c0ec479 100644 --- a/waterbox/ares64/ares/ares/n64/cpu/cpu.cpp +++ b/waterbox/ares64/ares/ares/n64/cpu/cpu.cpp @@ -46,10 +46,12 @@ auto CPU::synchronize() -> void { ai.clock -= clocks; rsp.clock -= clocks; rdp.clock -= clocks; + pif.clock -= clocks; while( vi.clock < 0) vi.main(); while( ai.clock < 0) ai.main(); while(rsp.clock < 0) rsp.main(); while(rdp.clock < 0) rdp.main(); + while(pif.clock < 0) pif.main(); queue.step(clocks, [](u32 event) { switch(event) { @@ -59,6 +61,8 @@ auto CPU::synchronize() -> void { case Queue::PI_BUS_Write: return pi.writeFinished(); case Queue::SI_DMA_Read: return si.dmaRead(); case Queue::SI_DMA_Write: return si.dmaWrite(); + case Queue::SI_BUS_Write: return si.writeFinished(); + case Queue::RTC_Tick: return cartridge.rtc.tick(); case Queue::DD_Clock_Tick: return dd.rtcTickClock(); case Queue::DD_MECHA_Response: return dd.mechaResponse(); case Queue::DD_BM_Request: return dd.bmRequest(); @@ -81,16 +85,24 @@ auto CPU::instruction() -> void { return exception.interrupt(); } } + if (scc.nmiPending) { + debugger.nmi(); + step(1); + return exception.nmi(); + } if constexpr(Accuracy::CPU::Recompiler) { - auto address = devirtualize(ipu.pc)(0); - auto& block = recompiler.block(address); - block.execute(*this); + if (auto address = devirtualize(ipu.pc)) { + auto block = recompiler.block(*address); + block->execute(*this); + } } if constexpr(Accuracy::CPU::Interpreter) { pipeline.address = ipu.pc; - pipeline.instruction = fetch(ipu.pc); + auto data = fetch(ipu.pc); + if (!data) return; + pipeline.instruction = *data; debugger.instruction(); decoderEXECUTE(); instructionEpilogue(); @@ -143,8 +155,8 @@ auto CPU::power(bool reset) -> void { context.setMode(); if constexpr(Accuracy::CPU::Recompiler) { - auto buffer = ares::Memory::FixedAllocator::get().tryAcquire(4_MiB); - recompiler.allocator.resize(4_MiB, bump_allocator::executable | bump_allocator::zero_fill, buffer); + auto buffer = ares::Memory::FixedAllocator::get().tryAcquire(64_MiB); + recompiler.allocator.resize(64_MiB, bump_allocator::executable | bump_allocator::zero_fill, buffer); recompiler.reset(); } } diff --git a/waterbox/ares64/ares/ares/n64/cpu/cpu.hpp b/waterbox/ares64/ares/ares/n64/cpu/cpu.hpp index 437c49c671..722c2af5f4 100644 --- a/waterbox/ares64/ares/ares/n64/cpu/cpu.hpp +++ b/waterbox/ares64/ares/ares/n64/cpu/cpu.hpp @@ -10,6 +10,7 @@ struct CPU : Thread { auto instruction() -> void; auto exception(u8 code) -> void; auto interrupt(u8 mask) -> void; + auto nmi() -> void; auto tlbWrite(u32 index) -> void; auto tlbModification(u64 address) -> void; auto tlbLoad(u64 address, u64 physical) -> void; @@ -83,7 +84,7 @@ struct CPU : Thread { enum Endian : bool { Little, Big }; enum Mode : u32 { Kernel, Supervisor, User }; - enum Segment : u32 { Unused, Mapped, Cached, Direct, Kernel64, Supervisor64, User64 }; + enum Segment : u32 { Unused, Mapped, Cached, Direct, Cached32, Direct32, Kernel64, Supervisor64, User64 }; auto littleEndian() const -> bool { return endian == Endian::Little; } auto bigEndian() const -> bool { return endian == Endian::Big; } @@ -147,26 +148,26 @@ struct CPU : Thread { cpu.step(48); valid = 1; tag = address & ~0x0000'0fff; - words[0] = bus.read(tag | index | 0x00); - words[1] = bus.read(tag | index | 0x04); - words[2] = bus.read(tag | index | 0x08); - words[3] = bus.read(tag | index | 0x0c); - words[4] = bus.read(tag | index | 0x10); - words[5] = bus.read(tag | index | 0x14); - words[6] = bus.read(tag | index | 0x18); - words[7] = bus.read(tag | index | 0x1c); + words[0] = cpu.busRead(tag | index | 0x00); + words[1] = cpu.busRead(tag | index | 0x04); + words[2] = cpu.busRead(tag | index | 0x08); + words[3] = cpu.busRead(tag | index | 0x0c); + words[4] = cpu.busRead(tag | index | 0x10); + words[5] = cpu.busRead(tag | index | 0x14); + words[6] = cpu.busRead(tag | index | 0x18); + words[7] = cpu.busRead(tag | index | 0x1c); } auto writeBack(CPU& cpu) -> void { cpu.step(48); - bus.write(tag | index | 0x00, words[0]); - bus.write(tag | index | 0x04, words[1]); - bus.write(tag | index | 0x08, words[2]); - bus.write(tag | index | 0x0c, words[3]); - bus.write(tag | index | 0x10, words[4]); - bus.write(tag | index | 0x14, words[5]); - bus.write(tag | index | 0x18, words[6]); - bus.write(tag | index | 0x1c, words[7]); + cpu.busWrite(tag | index | 0x00, words[0]); + cpu.busWrite(tag | index | 0x04, words[1]); + cpu.busWrite(tag | index | 0x08, words[2]); + cpu.busWrite(tag | index | 0x0c, words[3]); + cpu.busWrite(tag | index | 0x10, words[4]); + cpu.busWrite(tag | index | 0x14, words[5]); + cpu.busWrite(tag | index | 0x18, words[6]); + cpu.busWrite(tag | index | 0x1c, words[7]); } auto read(u32 address) const -> u32 { return words[address >> 2 & 7]; } @@ -259,9 +260,12 @@ struct CPU : Thread { auto segment(u64 vaddr) -> Context::Segment; auto devirtualize(u64 vaddr) -> maybe; - auto fetch(u64 vaddr) -> u32; + auto fetch(u64 vaddr) -> maybe; + template auto busWrite(u32 address, u64 data) -> void; + template auto busRead(u32 address) -> u64; template auto read(u64 vaddr) -> maybe; template auto write(u64 vaddr, u64 data) -> bool; + template auto vaddrAlignedError(u64 vaddr, bool write) -> bool; auto addressException(u64 vaddr) -> void; //serialization.cpp @@ -296,6 +300,7 @@ struct CPU : Thread { auto trap() -> void; auto floatingPoint() -> void; auto watchAddress() -> void; + auto nmi() -> void; } exception{*this}; enum Interrupt : u32 { @@ -317,8 +322,6 @@ struct CPU : Thread { struct { int64_t s64; }; struct { uint64_t u64; }; struct { float64_t f64; }; - auto s128() const -> int128_t { return (int128_t)s64; } - auto u128() const -> uint128_t { return (uint128_t)u64; } }; using cr64 = const r64; @@ -594,6 +597,7 @@ struct CPU : Thread { //other n64 latch; + n1 nmiPending; } scc; //interpreter-scc.cpp @@ -821,8 +825,7 @@ struct CPU : Thread { }; struct Pool { - Block blocks[1 << 6]; - bool dirty; + Block* blocks[1 << 6]; }; auto reset() -> void { @@ -842,14 +845,13 @@ struct CPU : Thread { auto pool = pools[address >> 8 & 0x1fffff]; if(!pool) return; memory::jitprotect(false); - pool->blocks[address >> 2 & 0x3f].code = nullptr; + pool->blocks[address >> 2 & 0x3f] = nullptr; memory::jitprotect(true); #endif } auto invalidatePool(u32 address) -> void { - auto pool = pools[address >> 8 & 0x1fffff]; - if(pool && pool->dirty) memory::fill(pool, sizeof(Pool)); + pools[address >> 8 & 0x1fffff] = nullptr; } auto invalidateRange(u32 address, u32 length) -> void { @@ -859,9 +861,9 @@ struct CPU : Thread { } auto pool(u32 address) -> Pool*; - auto block(u32 address) -> Block&; + auto block(u32 address) -> Block*; - auto emit(u32 address, Block& block) -> void; + auto emit(u32 address) -> Block*; auto emitEXECUTE(u32 instruction) -> bool; auto emitSPECIAL(u32 instruction) -> bool; auto emitREGIMM(u32 instruction) -> bool; diff --git a/waterbox/ares64/ares/ares/n64/cpu/dcache.cpp b/waterbox/ares64/ares/ares/n64/cpu/dcache.cpp index 4ec2409691..34d3d0ff71 100644 --- a/waterbox/ares64/ares/ares/n64/cpu/dcache.cpp +++ b/waterbox/ares64/ares/ares/n64/cpu/dcache.cpp @@ -11,21 +11,21 @@ template auto CPU::DataCache::Line::fill(u32 address, u64 data) -> voi switch(address & 8) { case 0: if constexpr(Size != Dual) { - words[0] = bus.read(tag | index | 0x0); - words[1] = bus.read(tag | index | 0x4); + words[0] = cpu.busRead(tag | index | 0x0); + words[1] = cpu.busRead(tag | index | 0x4); } write(address, data); - words[2] = bus.read(tag | index | 0x8); - words[3] = bus.read(tag | index | 0xc); + words[2] = cpu.busRead(tag | index | 0x8); + words[3] = cpu.busRead(tag | index | 0xc); break; case 8: if constexpr(Size != Dual) { - words[2] = bus.read(tag | index | 0x8); - words[3] = bus.read(tag | index | 0xc); + words[2] = cpu.busRead(tag | index | 0x8); + words[3] = cpu.busRead(tag | index | 0xc); } write(address, data); - words[0] = bus.read(tag | index | 0x0); - words[1] = bus.read(tag | index | 0x4); + words[0] = cpu.busRead(tag | index | 0x0); + words[1] = cpu.busRead(tag | index | 0x4); break; } } @@ -38,16 +38,16 @@ auto CPU::DataCache::Line::fill(u32 address) -> void { //read words according to critical doubleword first scheme switch(address & 8) { case 0: - words[0] = bus.read(tag | index | 0x0); - words[1] = bus.read(tag | index | 0x4); - words[2] = bus.read(tag | index | 0x8); - words[3] = bus.read(tag | index | 0xc); + words[0] = cpu.busRead(tag | index | 0x0); + words[1] = cpu.busRead(tag | index | 0x4); + words[2] = cpu.busRead(tag | index | 0x8); + words[3] = cpu.busRead(tag | index | 0xc); break; case 8: - words[2] = bus.read(tag | index | 0x8); - words[3] = bus.read(tag | index | 0xc); - words[0] = bus.read(tag | index | 0x0); - words[1] = bus.read(tag | index | 0x4); + words[2] = cpu.busRead(tag | index | 0x8); + words[3] = cpu.busRead(tag | index | 0xc); + words[0] = cpu.busRead(tag | index | 0x0); + words[1] = cpu.busRead(tag | index | 0x4); break; } } @@ -55,10 +55,10 @@ auto CPU::DataCache::Line::fill(u32 address) -> void { auto CPU::DataCache::Line::writeBack() -> void { cpu.step(40); dirty = 0; - bus.write(tag | index | 0x0, words[0]); - bus.write(tag | index | 0x4, words[1]); - bus.write(tag | index | 0x8, words[2]); - bus.write(tag | index | 0xc, words[3]); + cpu.busWrite(tag | index | 0x0, words[0]); + cpu.busWrite(tag | index | 0x4, words[1]); + cpu.busWrite(tag | index | 0x8, words[2]); + cpu.busWrite(tag | index | 0xc, words[3]); } auto CPU::DataCache::line(u32 address) -> Line& { diff --git a/waterbox/ares64/ares/ares/n64/cpu/debugger.cpp b/waterbox/ares64/ares/ares/n64/cpu/debugger.cpp index 40a0580bc6..dc284e5b15 100644 --- a/waterbox/ares64/ares/ares/n64/cpu/debugger.cpp +++ b/waterbox/ares64/ares/ares/n64/cpu/debugger.cpp @@ -69,6 +69,12 @@ auto CPU::Debugger::interrupt(u8 mask) -> void { } } +auto CPU::Debugger::nmi() -> void { + if(unlikely(tracer.exception->enabled())) { + tracer.exception->notify("NMI"); + } +} + auto CPU::Debugger::tlbWrite(u32 index) -> void { if(unlikely(tracer.tlb->enabled())) { auto entry = cpu.tlb.entry[index & 31]; diff --git a/waterbox/ares64/ares/ares/n64/cpu/disassembler.cpp b/waterbox/ares64/ares/ares/n64/cpu/disassembler.cpp index 4321bb62c9..e176191de2 100644 --- a/waterbox/ares64/ares/ares/n64/cpu/disassembler.cpp +++ b/waterbox/ares64/ares/ares/n64/cpu/disassembler.cpp @@ -476,6 +476,6 @@ auto CPU::Disassembler::ccrRegisterValue(u32 index) const -> string { template auto CPU::Disassembler::hint(P&&... p) const -> string { - if(showColors) return {"\e[0m\e[37m", std::forward

(p)..., "\e[0m"}; + if(showColors) return {terminal::csi, "0m", terminal::csi, "37m", std::forward

(p)..., terminal::csi, "0m"}; return {std::forward

(p)...}; } diff --git a/waterbox/ares64/ares/ares/n64/cpu/exceptions.cpp b/waterbox/ares64/ares/ares/n64/cpu/exceptions.cpp index 475f043c6d..310662f496 100644 --- a/waterbox/ares64/ares/ares/n64/cpu/exceptions.cpp +++ b/waterbox/ares64/ares/ares/n64/cpu/exceptions.cpp @@ -1,8 +1,7 @@ auto CPU::Exception::trigger(u32 code, u32 coprocessor, bool tlbMiss) -> void { self.debugger.exception(code); - u64 vectorBase = !self.scc.status.vectorLocation ? 0x8000'0000 : 0xbfc0'0200; - if(self.context.bits == 64) vectorBase = (s32)vectorBase; + u64 vectorBase = !self.scc.status.vectorLocation ? (s32)0x8000'0000 : (s32)0xbfc0'0200; u16 vectorOffset = 0x0180; if(tlbMiss) { @@ -51,3 +50,12 @@ auto CPU::Exception::arithmeticOverflow() -> void { trigger(12); } auto CPU::Exception::trap() -> void { trigger(13); } auto CPU::Exception::floatingPoint() -> void { trigger(15); } auto CPU::Exception::watchAddress() -> void { trigger(23); } + +auto CPU::Exception::nmi() -> void { + self.scc.status.vectorLocation = 1; + self.scc.status.tlbShutdown = 0; + self.scc.status.softReset = 0; + self.scc.status.errorLevel = 1; + self.scc.epcError = self.ipu.pc; + self.ipu.pc = 0xffff'ffff'bfc0'0000; +} diff --git a/waterbox/ares64/ares/ares/n64/cpu/interpreter-fpu.cpp b/waterbox/ares64/ares/ares/n64/cpu/interpreter-fpu.cpp index 5f15d295da..7283d816c1 100644 --- a/waterbox/ares64/ares/ares/n64/cpu/interpreter-fpu.cpp +++ b/waterbox/ares64/ares/ares/n64/cpu/interpreter-fpu.cpp @@ -208,15 +208,13 @@ auto CPU::checkFPUExceptions() -> bool { return raise; } -#define CHECK_FPE_IMPL(type, operation, convert) ({ \ +#define CHECK_FPE_IMPL(type, res, operation, convert) \ fenv.clearExcept(); \ - type res = [&]() noinline { return type(operation); }(); \ - if (checkFPUExceptions()) return; \ - (res); \ -}) + type res = [&]() noinline -> type { return operation; }(); \ + if (checkFPUExceptions()) return; -#define CHECK_FPE(type, operation) CHECK_FPE_IMPL(type, operation, false) -#define CHECK_FPE_CONV(type, operation) CHECK_FPE_IMPL(type, operation, true) +#define CHECK_FPE(type, res, operation) CHECK_FPE_IMPL(type, res, operation, false) +#define CHECK_FPE_CONV(type, res, operation) CHECK_FPE_IMPL(type, res, operation, true) auto f32repr(f32 f) -> n32 { uint32_t v; memcpy(&v, &f, 4); @@ -420,7 +418,7 @@ auto CPU::FADD_S(u8 fd, u8 fs, u8 ft) -> void { f32 ffs = FS(f32), fft = FT(f32); if(!fpuCheckInput(ffs)) return; if(!fpuCheckInput(fft)) return; - float ffd = CHECK_FPE(f32, FS(f32) + FT(f32)); + CHECK_FPE(f32, ffd, FS(f32) + FT(f32)); if(!fpuCheckOutput(ffd)) return; FD(f32) = ffd; } @@ -430,7 +428,7 @@ auto CPU::FADD_D(u8 fd, u8 fs, u8 ft) -> void { auto ffs = FS(f64), fft = FT(f64); if(!fpuCheckInput(ffs)) return; if(!fpuCheckInput(fft)) return; - auto ffd = CHECK_FPE(f64, ffs + fft); + CHECK_FPE(f64, ffd, ffs + fft); if(!fpuCheckOutput(ffd)) return; FD(f64) = ffd; } @@ -439,7 +437,7 @@ auto CPU::FCEIL_L_S(u8 fd, u8 fs) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f32); if(!fpuCheckInputConv(ffs)) return; - auto ffd = CHECK_FPE(s64, roundCeil(ffs)); + CHECK_FPE(s64, ffd, roundCeil(ffs)); FD(s64) = ffd; } @@ -447,7 +445,7 @@ auto CPU::FCEIL_L_D(u8 fd, u8 fs) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f64); if(!fpuCheckInputConv(ffs)) return; - auto ffd = CHECK_FPE(s64, roundCeil(ffs)); + CHECK_FPE(s64, ffd, roundCeil(ffs)); FD(s64) = ffd; } @@ -455,7 +453,7 @@ auto CPU::FCEIL_W_S(u8 fd, u8 fs) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f32); if(!fpuCheckInputConv(ffs)) return; - auto ffd = CHECK_FPE_CONV(s32, roundCeil(ffs)); + CHECK_FPE_CONV(s32, ffd, roundCeil(ffs)); FD(s32) = ffd; } @@ -463,7 +461,7 @@ auto CPU::FCEIL_W_D(u8 fd, u8 fs) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f64); if(!fpuCheckInputConv(ffs)) return; - auto ffd = CHECK_FPE_CONV(s32, roundCeil(ffs)); + CHECK_FPE_CONV(s32, ffd, roundCeil(ffs)); FD(s32) = ffd; } @@ -651,7 +649,7 @@ auto CPU::FCVT_S_D(u8 fd, u8 fs) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f64); if(!fpuCheckInput(ffs)) return; - auto ffd = CHECK_FPE(f32, (f32)ffs); + CHECK_FPE(f32, ffd, (f32)ffs); if(!fpuCheckOutput(ffd)) return; FD(f32) = ffd; } @@ -659,7 +657,7 @@ auto CPU::FCVT_S_D(u8 fd, u8 fs) -> void { auto CPU::FCVT_S_W(u8 fd, u8 fs) -> void { if(!fpuCheckStart()) return; auto ffs = FS(s32); - auto ffd = CHECK_FPE(f32, ffs); + CHECK_FPE(f32, ffd, ffs); if(!fpuCheckOutput(ffd)) return; FD(f32) = ffd; } @@ -671,7 +669,7 @@ auto CPU::FCVT_S_L(u8 fd, u8 fs) -> void { if (fpeUnimplemented()) return exception.floatingPoint(); return; } - auto ffd = CHECK_FPE(f32, (f32)ffs); + CHECK_FPE(f32, ffd, (f32)ffs); if(!fpuCheckOutput(ffd)) return; FD(f32) = ffd; } @@ -680,7 +678,7 @@ auto CPU::FCVT_D_S(u8 fd, u8 fs) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f32); if(!fpuCheckInput(ffs)) return; - auto ffd = CHECK_FPE(f64, ffs); + CHECK_FPE(f64, ffd, ffs); if(!fpuCheckOutput(ffd)) return; FD(f64) = ffd; } @@ -693,7 +691,7 @@ auto CPU::FCVT_D_D(u8 fd, u8 fs) -> void { auto CPU::FCVT_D_W(u8 fd, u8 fs) -> void { if(!fpuCheckStart()) return; auto ffs = FS(s32); - auto ffd = CHECK_FPE(f64, (f64)ffs); + CHECK_FPE(f64, ffd, (f64)ffs); if(!fpuCheckOutput(ffd)) return; FD(f64) = ffd; } @@ -705,7 +703,7 @@ auto CPU::FCVT_D_L(u8 fd, u8 fs) -> void { if (fpeUnimplemented()) return exception.floatingPoint(); return; } - auto ffd = CHECK_FPE(f64, (f64)ffs); + CHECK_FPE(f64, ffd, (f64)ffs); if(!fpuCheckOutput(ffd)) return; FD(f64) = ffs; } @@ -714,7 +712,7 @@ auto CPU::FCVT_L_S(u8 fd, u8 fs) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f32); if(!fpuCheckInputConv(ffs)) return; - auto ffd = CHECK_FPE(s64, roundCurrent(ffs)); + CHECK_FPE(s64, ffd, roundCurrent(ffs)); FD(s64) = ffd; } @@ -722,7 +720,7 @@ auto CPU::FCVT_L_D(u8 fd, u8 fs) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f64); if(!fpuCheckInputConv(ffs)) return; - auto ffd = CHECK_FPE(s64, roundCurrent(ffs)); + CHECK_FPE(s64, ffd, roundCurrent(ffs)); FD(s64) = ffd; } @@ -730,7 +728,7 @@ auto CPU::FCVT_W_S(u8 fd, u8 fs) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f32); if(!fpuCheckInputConv(ffs)) return; - auto ffd = CHECK_FPE_CONV(s32, roundCurrent(ffs)); + CHECK_FPE_CONV(s32, ffd, roundCurrent(ffs)); FD(s32) = ffd; } @@ -738,7 +736,7 @@ auto CPU::FCVT_W_D(u8 fd, u8 fs) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f64); if(!fpuCheckInputConv(ffs)) return; - auto ffd = CHECK_FPE_CONV(s32, roundCurrent(ffs)); + CHECK_FPE_CONV(s32, ffd, roundCurrent(ffs)); FD(s32) = ffd; } @@ -747,7 +745,7 @@ auto CPU::FDIV_S(u8 fd, u8 fs, u8 ft) -> void { auto ffs = FS(f32), fft = FT(f32); if(!fpuCheckInput(ffs)) return; if(!fpuCheckInput(fft)) return; - auto ffd = CHECK_FPE(f32, ffs / fft); + CHECK_FPE(f32, ffd, ffs / fft); if(!fpuCheckOutput(ffd)) return; FD(f32) = ffd; } @@ -757,7 +755,7 @@ auto CPU::FDIV_D(u8 fd, u8 fs, u8 ft) -> void { auto ffs = FS(f64), fft = FT(f64); if(!fpuCheckInput(ffs)) return; if(!fpuCheckInput(fft)) return; - auto ffd = CHECK_FPE(f64, ffs / fft); + CHECK_FPE(f64, ffd, ffs / fft); if(!fpuCheckOutput(ffd)) return; FD(f64) = ffd; } @@ -766,7 +764,7 @@ auto CPU::FFLOOR_L_S(u8 fd, u8 fs) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f32); if(!fpuCheckInputConv(ffs)) return; - auto ffd = CHECK_FPE(s64, roundFloor(ffs)); + CHECK_FPE(s64, ffd, roundFloor(ffs)); FD(s64) = ffd; } @@ -774,7 +772,7 @@ auto CPU::FFLOOR_L_D(u8 fd, u8 fs) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f64); if(!fpuCheckInputConv(ffs)) return; - auto ffd = CHECK_FPE(s64, roundFloor(ffs)); + CHECK_FPE(s64, ffd, roundFloor(ffs)); FD(s64) = ffd; } @@ -782,7 +780,7 @@ auto CPU::FFLOOR_W_S(u8 fd, u8 fs) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f32); if(!fpuCheckInputConv(ffs)) return; - auto ffd = CHECK_FPE_CONV(s32, roundFloor(ffs)); + CHECK_FPE_CONV(s32, ffd, roundFloor(ffs)); FD(s32) = ffd; } @@ -790,7 +788,7 @@ auto CPU::FFLOOR_W_D(u8 fd, u8 fs) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f64); if(!fpuCheckInputConv(ffs)) return; - auto ffd = CHECK_FPE_CONV(s32, roundFloor(ffs)); + CHECK_FPE_CONV(s32, ffd, roundFloor(ffs)); FD(s32) = ffd; } @@ -809,7 +807,7 @@ auto CPU::FMUL_S(u8 fd, u8 fs, u8 ft) -> void { auto ffs = FS(f32), fft = FT(f32); if(!fpuCheckInput(ffs)) return; if(!fpuCheckInput(fft)) return; - auto ffd = CHECK_FPE(f32, ffs * fft); + CHECK_FPE(f32, ffd, ffs * fft); if(!fpuCheckOutput(ffd)) return; FD(f32) = ffd; } @@ -819,7 +817,7 @@ auto CPU::FMUL_D(u8 fd, u8 fs, u8 ft) -> void { auto ffs = FS(f64), fft = FT(f64); if(!fpuCheckInput(ffs)) return; if(!fpuCheckInput(fft)) return; - auto ffd = CHECK_FPE(f64, ffs * fft); + CHECK_FPE(f64, ffd, ffs * fft); if(!fpuCheckOutput(ffd)) return; FD(f64) = ffd; } @@ -828,7 +826,7 @@ auto CPU::FNEG_S(u8 fd, u8 fs) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f32); if(!fpuCheckInput(ffs)) return; - auto ffd = CHECK_FPE(f32, -ffs); + CHECK_FPE(f32, ffd, -ffs); if(!fpuCheckOutput(ffd)) return; FD(f32) = ffd; } @@ -837,7 +835,7 @@ auto CPU::FNEG_D(u8 fd, u8 fs) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f64); if(!fpuCheckInput(ffs)) return; - auto ffd = CHECK_FPE(f64, -ffs); + CHECK_FPE(f64, ffd, -ffs); if(!fpuCheckOutput(ffd)) return; FD(f64) = ffd; } @@ -846,7 +844,7 @@ auto CPU::FROUND_L_S(u8 fd, u8 fs) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f32); if(!fpuCheckInputConv(ffs)) return; - auto ffd = CHECK_FPE(s64, roundNearest(ffs)); + CHECK_FPE(s64, ffd, roundNearest(ffs)); if(ffd != ffs && fpeInexact()) return exception.floatingPoint(); FD(s64) = ffd; } @@ -855,7 +853,7 @@ auto CPU::FROUND_L_D(u8 fd, u8 fs) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f64); if(!fpuCheckInputConv(ffs)) return; - auto ffd = CHECK_FPE(s64, roundNearest(ffs)); + CHECK_FPE(s64, ffd, roundNearest(ffs)); if(ffd != ffs && fpeInexact()) return exception.floatingPoint(); FD(s64) = ffd; } @@ -864,7 +862,7 @@ auto CPU::FROUND_W_S(u8 fd, u8 fs) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f32); if(!fpuCheckInputConv(ffs)) return; - auto ffd = CHECK_FPE_CONV(s32, roundNearest(ffs)); + CHECK_FPE_CONV(s32, ffd, roundNearest(ffs)); if(ffd != ffs && fpeInexact()) return exception.floatingPoint(); FD(s32) = ffd; } @@ -873,7 +871,7 @@ auto CPU::FROUND_W_D(u8 fd, u8 fs) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f64); if(!fpuCheckInputConv(ffs)) return; - auto ffd = CHECK_FPE_CONV(s32, roundNearest(ffs)); + CHECK_FPE_CONV(s32, ffd, roundNearest(ffs)); if(ffd != ffs && fpeInexact()) return exception.floatingPoint(); FD(s32) = ffd; } @@ -882,7 +880,7 @@ auto CPU::FSQRT_S(u8 fd, u8 fs) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f32); if(!fpuCheckInput(ffs)) return; - auto ffd = CHECK_FPE(f32, squareRoot(ffs)); + CHECK_FPE(f32, ffd, squareRoot(ffs)); if(!fpuCheckOutput(ffd)) return; FD(f32) = ffd; } @@ -891,7 +889,7 @@ auto CPU::FSQRT_D(u8 fd, u8 fs) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f64); if(!fpuCheckInput(ffs)) return; - auto ffd = CHECK_FPE(f64, squareRoot(ffs)); + CHECK_FPE(f64, ffd, squareRoot(ffs)); if(!fpuCheckOutput(ffd)) return; FD(f64) = ffd; } @@ -901,7 +899,7 @@ auto CPU::FSUB_S(u8 fd, u8 fs, u8 ft) -> void { auto ffs = FS(f32), fft = FT(f32); if(!fpuCheckInput(ffs)) return; if(!fpuCheckInput(fft)) return; - auto ffd = CHECK_FPE(f32, ffs - fft); + CHECK_FPE(f32, ffd, ffs - fft); if(!fpuCheckOutput(ffd)) return; FD(f32) = ffd; } @@ -911,7 +909,7 @@ auto CPU::FSUB_D(u8 fd, u8 fs, u8 ft) -> void { auto ffs = FS(f64), fft = FT(f64); if(!fpuCheckInput(ffs)) return; if(!fpuCheckInput(fft)) return; - auto ffd = CHECK_FPE(f64, ffs - fft); + CHECK_FPE(f64, ffd, ffs - fft); if(!fpuCheckOutput(ffd)) return; FD(f64) = ffd; } @@ -920,7 +918,7 @@ auto CPU::FTRUNC_L_S(u8 fd, u8 fs) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f32); if(!fpuCheckInputConv(ffs)) return; - auto ffd = CHECK_FPE(s64, roundTrunc(ffs)); + CHECK_FPE(s64, ffd, roundTrunc(ffs)); if((f32)ffd != ffs && fpeInexact()) return exception.floatingPoint(); FD(s64) = ffd; } @@ -929,7 +927,7 @@ auto CPU::FTRUNC_L_D(u8 fd, u8 fs) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f64); if(!fpuCheckInputConv(ffs)) return; - auto ffd = CHECK_FPE(s64, roundTrunc(ffs)); + CHECK_FPE(s64, ffd, roundTrunc(ffs)); if((f64)ffd != ffs && fpeInexact()) return exception.floatingPoint(); FD(s64) = ffd; } @@ -938,7 +936,7 @@ auto CPU::FTRUNC_W_S(u8 fd, u8 fs) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f32); if(!fpuCheckInputConv(ffs)) return; - auto ffd = CHECK_FPE_CONV(s32, roundTrunc(ffs)); + CHECK_FPE_CONV(s32, ffd, roundTrunc(ffs)); if((f32)ffd != ffs && fpeInexact()) return exception.floatingPoint(); FD(s32) = ffd; } @@ -947,7 +945,7 @@ auto CPU::FTRUNC_W_D(u8 fd, u8 fs) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f64); if(!fpuCheckInputConv(ffs)) return; - auto ffd = CHECK_FPE_CONV(s32, roundTrunc(ffs)); + CHECK_FPE_CONV(s32, ffd, roundTrunc(ffs)); if((f64)ffd != ffs && fpeInexact()) return exception.floatingPoint(); FD(s32) = ffd; } diff --git a/waterbox/ares64/ares/ares/n64/cpu/interpreter-ipu.cpp b/waterbox/ares64/ares/ares/n64/cpu/interpreter-ipu.cpp index 08cc7bedc3..c50c6c9fab 100644 --- a/waterbox/ares64/ares/ares/n64/cpu/interpreter-ipu.cpp +++ b/waterbox/ares64/ares/ares/n64/cpu/interpreter-ipu.cpp @@ -252,9 +252,19 @@ auto CPU::DADDU(r64& rd, cr64& rs, cr64& rt) -> void { auto CPU::DDIV(cr64& rs, cr64& rt) -> void { if(!context.kernelMode() && context.bits == 32) return exception.reservedInstruction(); if(rt.s64) { + #if defined(_MSC_VER) || !defined(__SIZEOF_INT128__) + if(rs.s64 != (-1LL << 63) || rt.s64 != -1LL) { + LO.u64 = rs.s64 / rt.s64; + HI.u64 = rs.s64 % rt.s64; + } else { + LO.u64 = rs.s64; + HI.u64 = 0; + } + #else //cast to i128 to prevent exception on INT64_MIN / -1 LO.u64 = s128(rs.s64) / s128(rt.s64); HI.u64 = s128(rs.s64) % s128(rt.s64); + #endif } else { LO.u64 = rs.s64 < 0 ? +1 : -1; HI.u64 = rs.s64; @@ -301,17 +311,41 @@ auto CPU::DIVU(cr64& rs, cr64& rt) -> void { auto CPU::DMULT(cr64& rs, cr64& rt) -> void { if(!context.kernelMode() && context.bits == 32) return exception.reservedInstruction(); - u128 result = rs.s128() * rt.s128(); +#if defined(COMPILER_MICROSOFT) && (defined(ARCHITECTURE_AMD64) || defined(ARCHITECTURE_ARM64)) + #if defined(ARCHITECTURE_AMD64) + LO.s64 = _mul128(rs.s64, rt.s64, &HI.s64); + #else + LO.s64 = rs.s64 * rt.s64; + HI.s64 = __mulh(rs.s64, rt.s64); + #endif +#else + #if defined(__SIZEOF_INT128__) + u128 result = s128(rs.s64) * s128(rt.s64); + #else + u128 result = u128(rs.u64) * u128(rt.u64); + if(rs.s64 < 0) result -= u128(rt.u64) << 64; + if(rt.s64 < 0) result -= u128(rs.u64) << 64; + #endif LO.u64 = result >> 0; HI.u64 = result >> 64; +#endif step(8); } auto CPU::DMULTU(cr64& rs, cr64& rt) -> void { if(!context.kernelMode() && context.bits == 32) return exception.reservedInstruction(); - u128 result = rs.u128() * rt.u128(); +#if defined(COMPILER_MICROSOFT) && (defined(ARCHITECTURE_AMD64) || defined(ARCHITECTURE_ARM64)) + #if defined(ARCHITECTURE_AMD64) + LO.u64 = _umul128(rs.u64, rt.u64, &HI.u64); + #else + LO.u64 = rs.u64 * rt.u64; + HI.u64 = __umulh(rs.u64, rt.u64); + #endif +#else + u128 result = u128(rs.u64) * u128(rt.u64); LO.u64 = result >> 0; HI.u64 = result >> 64; +#endif step(8); } diff --git a/waterbox/ares64/ares/ares/n64/cpu/memory.cpp b/waterbox/ares64/ares/ares/n64/cpu/memory.cpp index 9b139a6782..80ce9bb1eb 100644 --- a/waterbox/ares64/ares/ares/n64/cpu/memory.cpp +++ b/waterbox/ares64/ares/ares/n64/cpu/memory.cpp @@ -30,21 +30,21 @@ auto CPU::kernelSegment64(u64 vaddr) const -> Context::Segment { if(vaddr <= 0x3fff'ffff'ffff'ffffull) return Context::Segment::Unused; if(vaddr <= 0x4000'00ff'ffff'ffffull) return Context::Segment::Mapped; //xksseg if(vaddr <= 0x7fff'ffff'ffff'ffffull) return Context::Segment::Unused; - if(vaddr <= 0x8000'0000'ffff'ffffull) return Context::Segment::Cached; //xkphys* + if(vaddr <= 0x8000'0000'ffff'ffffull) return Context::Segment::Cached32; //xkphys* if(vaddr <= 0x87ff'ffff'ffff'ffffull) return Context::Segment::Unused; - if(vaddr <= 0x8800'0000'ffff'ffffull) return Context::Segment::Cached; //xkphys* + if(vaddr <= 0x8800'0000'ffff'ffffull) return Context::Segment::Cached32; //xkphys* if(vaddr <= 0x8fff'ffff'ffff'ffffull) return Context::Segment::Unused; - if(vaddr <= 0x9000'0000'ffff'ffffull) return Context::Segment::Direct; //xkphys* + if(vaddr <= 0x9000'0000'ffff'ffffull) return Context::Segment::Direct32; //xkphys* if(vaddr <= 0x97ff'ffff'ffff'ffffull) return Context::Segment::Unused; - if(vaddr <= 0x9800'0000'ffff'ffffull) return Context::Segment::Cached; //xkphys* + if(vaddr <= 0x9800'0000'ffff'ffffull) return Context::Segment::Cached32; //xkphys* if(vaddr <= 0x9fff'ffff'ffff'ffffull) return Context::Segment::Unused; - if(vaddr <= 0xa000'0000'ffff'ffffull) return Context::Segment::Cached; //xkphys* + if(vaddr <= 0xa000'0000'ffff'ffffull) return Context::Segment::Cached32; //xkphys* if(vaddr <= 0xa7ff'ffff'ffff'ffffull) return Context::Segment::Unused; - if(vaddr <= 0xa800'0000'ffff'ffffull) return Context::Segment::Cached; //xkphys* + if(vaddr <= 0xa800'0000'ffff'ffffull) return Context::Segment::Cached32; //xkphys* if(vaddr <= 0xafff'ffff'ffff'ffffull) return Context::Segment::Unused; - if(vaddr <= 0xb000'0000'ffff'ffffull) return Context::Segment::Cached; //xkphys* + if(vaddr <= 0xb000'0000'ffff'ffffull) return Context::Segment::Cached32; //xkphys* if(vaddr <= 0xb7ff'ffff'ffff'ffffull) return Context::Segment::Unused; - if(vaddr <= 0xb800'0000'ffff'ffffull) return Context::Segment::Cached; //xkphys* + if(vaddr <= 0xb800'0000'ffff'ffffull) return Context::Segment::Cached32; //xkphys* if(vaddr <= 0xbfff'ffff'ffff'ffffull) return Context::Segment::Unused; if(vaddr <= 0xc000'00ff'7fff'ffffull) return Context::Segment::Mapped; //xkseg if(vaddr <= 0xffff'ffff'7fff'ffffull) return Context::Segment::Unused; @@ -89,6 +89,7 @@ auto CPU::segment(u64 vaddr) -> Context::Segment { } auto CPU::devirtualize(u64 vaddr) -> maybe { + if(vaddrAlignedError(vaddr, false)) return nothing; switch(segment(vaddr)) { case Context::Segment::Unused: addressException(vaddr); @@ -100,32 +101,55 @@ auto CPU::devirtualize(u64 vaddr) -> maybe { return nothing; case Context::Segment::Cached: case Context::Segment::Direct: - return vaddr & context.physMask; + return vaddr & 0x1fff'ffff; + case Context::Segment::Cached32: + case Context::Segment::Direct32: + return vaddr & 0xffff'ffff; } unreachable; } -auto CPU::fetch(u64 vaddr) -> u32 { +template +inline auto CPU::busWrite(u32 address, u64 data) -> void { + u32 cycles = 0; + bus.write(address, data, cycles); + step(cycles); +} + +template +inline auto CPU::busRead(u32 address) -> u64 { + u32 cycles = 0; u64 data; + data = bus.read(address, cycles); + return step(cycles), data; +} + +auto CPU::fetch(u64 vaddr) -> maybe { + if(vaddrAlignedError(vaddr, false)) return nothing; switch(segment(vaddr)) { case Context::Segment::Unused: step(1); addressException(vaddr); exception.addressLoad(); - return 0; //nop + return nothing; case Context::Segment::Mapped: if(auto match = tlb.load(vaddr)) { if(match.cache) return icache.fetch(match.address & context.physMask, cpu); step(1); - return bus.read(match.address & context.physMask); + return busRead(match.address & context.physMask); } step(1); addressException(vaddr); - return 0; //nop + return nothing; case Context::Segment::Cached: - return icache.fetch(vaddr & context.physMask, cpu); + return icache.fetch(vaddr & 0x1fff'ffff, cpu); + case Context::Segment::Cached32: + return icache.fetch(vaddr & 0xffff'ffff, cpu); case Context::Segment::Direct: step(1); - return bus.read(vaddr & context.physMask); + return busRead(vaddr & 0x1fff'ffff); + case Context::Segment::Direct32: + step(1); + return busRead(vaddr & 0xffff'ffff); } unreachable; @@ -133,21 +157,7 @@ auto CPU::fetch(u64 vaddr) -> u32 { template auto CPU::read(u64 vaddr) -> maybe { - if constexpr(Accuracy::CPU::AddressErrors) { - if(unlikely(vaddr & Size - 1)) { - step(1); - addressException(vaddr); - exception.addressLoad(); - return nothing; - } - if (context.bits == 32 && unlikely((s32)vaddr != vaddr)) { - step(1); - addressException(vaddr); - exception.addressLoad(); - return nothing; - } - } - + if(vaddrAlignedError(vaddr, false)) return nothing; switch(segment(vaddr)) { case Context::Segment::Unused: step(1); @@ -158,16 +168,21 @@ auto CPU::read(u64 vaddr) -> maybe { if(auto match = tlb.load(vaddr)) { if(match.cache) return dcache.read(match.address & context.physMask); step(1); - return bus.read(match.address & context.physMask); + return busRead(match.address & context.physMask); } step(1); addressException(vaddr); return nothing; case Context::Segment::Cached: - return dcache.read(vaddr & context.physMask); + return dcache.read(vaddr & 0x1fff'ffff); + case Context::Segment::Cached32: + return dcache.read(vaddr & 0xffff'ffff); case Context::Segment::Direct: step(1); - return bus.read(vaddr & context.physMask); + return busRead(vaddr & 0x1fff'ffff); + case Context::Segment::Direct32: + step(1); + return busRead(vaddr & 0xffff'ffff); } unreachable; @@ -175,21 +190,7 @@ auto CPU::read(u64 vaddr) -> maybe { template auto CPU::write(u64 vaddr, u64 data) -> bool { - if constexpr(Accuracy::CPU::AddressErrors) { - if(unlikely(vaddr & Size - 1)) { - step(1); - addressException(vaddr); - exception.addressStore(); - return false; - } - if (context.bits == 32 && unlikely((s32)vaddr != vaddr)) { - step(1); - addressException(vaddr); - exception.addressStore(); - return false; - } - } - + if(vaddrAlignedError(vaddr, true)) return false; switch(segment(vaddr)) { case Context::Segment::Unused: step(1); @@ -200,21 +201,47 @@ auto CPU::write(u64 vaddr, u64 data) -> bool { if(auto match = tlb.store(vaddr)) { if(match.cache) return dcache.write(match.address & context.physMask, data), true; step(1); - return bus.write(match.address & context.physMask, data), true; + return busWrite(match.address & context.physMask, data), true; } step(1); addressException(vaddr); return false; case Context::Segment::Cached: - return dcache.write(vaddr & context.physMask, data), true; + return dcache.write(vaddr & 0x1fff'ffff, data), true; + case Context::Segment::Cached32: + return dcache.write(vaddr & 0xffff'ffff, data), true; case Context::Segment::Direct: step(1); - return bus.write(vaddr & context.physMask, data), true; + return busWrite(vaddr & 0x1fff'ffff, data), true; + case Context::Segment::Direct32: + step(1); + return busWrite(vaddr & 0xffff'ffff, data), true; } unreachable; } +template +auto CPU::vaddrAlignedError(u64 vaddr, bool write) -> bool { + if constexpr(Accuracy::CPU::AddressErrors) { + if(unlikely(vaddr & Size - 1)) { + step(1); + addressException(vaddr); + if(write) exception.addressStore(); + else exception.addressLoad(); + return true; + } + if (context.bits == 32 && unlikely((s32)vaddr != vaddr)) { + step(1); + addressException(vaddr); + if(write) exception.addressStore(); + else exception.addressLoad(); + return true; + } + } + return false; +} + auto CPU::addressException(u64 vaddr) -> void { scc.badVirtualAddress = vaddr; scc.tlb.virtualAddress.bit(13,39) = vaddr >> 13; diff --git a/waterbox/ares64/ares/ares/n64/cpu/recompiler.cpp b/waterbox/ares64/ares/ares/n64/cpu/recompiler.cpp index 3e660414d9..fb0fc61319 100644 --- a/waterbox/ares64/ares/ares/n64/cpu/recompiler.cpp +++ b/waterbox/ares64/ares/ares/n64/cpu/recompiler.cpp @@ -4,17 +4,15 @@ auto CPU::Recompiler::pool(u32 address) -> Pool* { return pool; } -auto CPU::Recompiler::block(u32 address) -> Block& { - auto pool = this->pool(address); - auto& block = pool->blocks[address >> 2 & 0x3f]; - if(block.code) return block; - emit(address, block); - pool->dirty = true; +auto CPU::Recompiler::block(u32 address) -> Block* { + if(auto block = pool(address)->blocks[address >> 2 & 0x3f]) return block; + auto block = emit(address); + pool(address)->blocks[address >> 2 & 0x3f] = block; memory::jitprotect(true); return block; } -auto CPU::Recompiler::emit(u32 address, Block& block) -> void { +auto CPU::Recompiler::emit(u32 address) -> Block* { if(unlikely(allocator.available() < 1_MiB)) { print("CPU allocator flush\n"); memory::jitprotect(false); @@ -23,11 +21,13 @@ auto CPU::Recompiler::emit(u32 address, Block& block) -> void { reset(); } + auto block = (Block*)allocator.acquire(sizeof(Block)); beginFunction(3); + u32 memCycles; bool hasBranched = 0; while(true) { - u32 instruction = bus.read(address); + u32 instruction = bus.read(address, memCycles); bool branched = emitEXECUTE(instruction); if(unlikely(instruction == 0x1000'ffff)) { //accelerate idle loops @@ -43,9 +43,10 @@ auto CPU::Recompiler::emit(u32 address, Block& block) -> void { jumpEpilog(); memory::jitprotect(false); - block.code = endFunction(); + block->code = endFunction(); //print(hex(PC, 8L), " ", instructions, " ", size(), "\n"); + return block; } #define Sa (instruction >> 6 & 31) @@ -284,7 +285,7 @@ auto CPU::Recompiler::emitEXECUTE(u32 instruction) -> bool { } //INVALID - case 0x1c ... 0x1f: { + case range4(0x1c, 0x1f): { call(&CPU::INVALID); return 1; } @@ -599,9 +600,7 @@ auto CPU::Recompiler::emitSPECIAL(u32 instruction) -> bool { //SLLV Rd,Rt,Rs case 0x04: { - mov32(reg(0), mem(Rt32)); - and32(reg(1), mem(Rs32), imm(31)); - shl32(reg(0), reg(0), reg(1)); + mshl32(reg(0), mem(Rt32), mem(Rs32)); mov64_s32(reg(0), reg(0)); mov64(mem(Rd), reg(0)); return 0; @@ -615,9 +614,7 @@ auto CPU::Recompiler::emitSPECIAL(u32 instruction) -> bool { //SRLV Rd,Rt,RS case 0x06: { - mov32(reg(0), mem(Rt32)); - and32(reg(1), mem(Rs32), imm(31)); - lshr32(reg(0), reg(0), reg(1)); + mlshr32(reg(0), mem(Rt32), mem(Rs32)); mov64_s32(reg(0), reg(0)); mov64(mem(Rd), reg(0)); return 0; @@ -625,7 +622,7 @@ auto CPU::Recompiler::emitSPECIAL(u32 instruction) -> bool { //SRAV Rd,Rt,Rs case 0x07: { - and32(reg(1), mem(Rs32), imm(31)); + and64(reg(1), mem(Rs), imm(31)); ashr64(reg(0), mem(Rt), reg(1)); mov64_s32(reg(0), reg(0)); mov64(mem(Rd), reg(0)); @@ -648,7 +645,7 @@ auto CPU::Recompiler::emitSPECIAL(u32 instruction) -> bool { } //INVALID - case 0x0a ... 0x0b: { + case range2(0x0a, 0x0b): { call(&CPU::INVALID); return 1; } @@ -853,13 +850,13 @@ auto CPU::Recompiler::emitSPECIAL(u32 instruction) -> bool { //NOR Rd,Rs,Rt case 0x27: { or64(reg(0), mem(Rs), mem(Rt)); - not64(reg(0), reg(0)); + xor64(reg(0), reg(0), imm(-1)); mov64(mem(Rd), reg(0)); return 0; } //INVALID - case 0x28 ... 0x29: { + case range2(0x28, 0x29): { call(&CPU::INVALID); return 1; } @@ -1081,7 +1078,7 @@ auto CPU::Recompiler::emitREGIMM(u32 instruction) -> bool { } //INVALID - case 0x04 ... 0x07: { + case range4(0x04, 0x07): { call(&CPU::INVALID); return 1; } @@ -1179,7 +1176,7 @@ auto CPU::Recompiler::emitREGIMM(u32 instruction) -> bool { } //INVALID - case 0x14 ... 0x1f: { + case range12(0x14, 0x1f): { call(&CPU::INVALID); return 1; } @@ -1209,7 +1206,7 @@ auto CPU::Recompiler::emitSCC(u32 instruction) -> bool { } //INVALID - case 0x02 ... 0x03: { + case range2(0x02, 0x03): { call(&CPU::INVALID); return 1; } @@ -1231,7 +1228,7 @@ auto CPU::Recompiler::emitSCC(u32 instruction) -> bool { } //INVALID - case 0x06 ... 0x0f: { + case range10(0x06, 0x0f): { call(&CPU::INVALID); return 1; } @@ -1348,7 +1345,7 @@ auto CPU::Recompiler::emitFPU(u32 instruction) -> bool { } //INVALID - case 0x09 ... 0x0f: { + case range7(0x09, 0x0f): { call(&CPU::INVALID); return 1; } @@ -1951,12 +1948,12 @@ auto CPU::Recompiler::emitFPU(u32 instruction) -> bool { if((instruction >> 21 & 31) == 20) switch(instruction & 0x3f) { - case 0x08 ... 0x0f: { + case range8(0x08, 0x0f): { call(&CPU::COP1UNIMPLEMENTED); return 1; } - case 0x24 ... 0x25: { + case range2(0x24, 0x25): { call(&CPU::COP1UNIMPLEMENTED); return 1; } @@ -1981,11 +1978,11 @@ auto CPU::Recompiler::emitFPU(u32 instruction) -> bool { if((instruction >> 21 & 31) == 21) switch(instruction & 0x3f) { - case 0x08 ... 0x0f: { + case range8(0x08, 0x0f): { call(&CPU::COP1UNIMPLEMENTED); return 1; } - case 0x24 ... 0x25: { + case range2(0x24, 0x25): { call(&CPU::COP1UNIMPLEMENTED); return 1; } @@ -2069,7 +2066,7 @@ auto CPU::Recompiler::emitCOP2(u32 instruction) -> bool { } //INVALID - case 0x07 ... 0x0f: { + case range9(0x07, 0x0f): { call(&CPU::COP2INVALID); return 1; } diff --git a/waterbox/ares64/ares/ares/n64/cpu/serialization.cpp b/waterbox/ares64/ares/ares/n64/cpu/serialization.cpp index 56442a6476..48f9d03cfd 100644 --- a/waterbox/ares64/ares/ares/n64/cpu/serialization.cpp +++ b/waterbox/ares64/ares/ares/n64/cpu/serialization.cpp @@ -116,6 +116,7 @@ auto CPU::serialize(serializer& s) -> void { s(scc.tagLo.physicalAddress); s(scc.epcError); s(scc.latch); + s(scc.nmiPending); for(auto& r : fpu.r) s(r.u64); s(fpu.csr.roundMode); diff --git a/waterbox/ares64/ares/ares/n64/dd/dd.cpp b/waterbox/ares64/ares/ares/n64/dd/dd.cpp index b291be4593..316e53903e 100644 --- a/waterbox/ares64/ares/ares/n64/dd/dd.cpp +++ b/waterbox/ares64/ares/ares/n64/dd/dd.cpp @@ -93,10 +93,12 @@ auto DD::disconnect() -> void { } auto DD::save() -> void { - /*if(disk) +#if false + if(disk) if(auto fp = pak->write("program.disk")) { disk.save(fp); - }*/ + } +#endif rtcSave(); } diff --git a/waterbox/ares64/ares/ares/n64/dd/dd.hpp b/waterbox/ares64/ares/ares/n64/dd/dd.hpp index a6abe053e2..d6b9f2a7e8 100644 --- a/waterbox/ares64/ares/ares/n64/dd/dd.hpp +++ b/waterbox/ares64/ares/ares/n64/dd/dd.hpp @@ -1,6 +1,8 @@ //Disk Drive -struct DD : Memory::IO

{ +#include + +struct DD : Memory::PI
{ Node::Object obj; Node::Port port; Node::Peripheral node; @@ -65,6 +67,8 @@ struct DD : Memory::IO
{ auto rtcTickSecond() -> void; //io.cpp + auto readHalf(u32 address) -> u16; + auto writeHalf(u32 address, u16 data) -> void; auto readWord(u32 address) -> u32; auto writeWord(u32 address, u32 data) -> void; @@ -76,13 +80,6 @@ struct DD : Memory::IO
{ string cic; } information; - struct BCD { - static auto encode(u8 value) -> u8 { return value / 10 << 4 | value % 10; } - static auto decode(u8 value) -> u8 { return (value >> 4) * 10 + (value & 15); } - }; - - std::function rtcCallback = []() { return 0; }; - private: struct Interrupt { b1 line = 0; diff --git a/waterbox/ares64/ares/ares/n64/dd/drive.cpp b/waterbox/ares64/ares/ares/n64/dd/drive.cpp index 7eef152641..33768765a7 100644 --- a/waterbox/ares64/ares/ares/n64/dd/drive.cpp +++ b/waterbox/ares64/ares/ares/n64/dd/drive.cpp @@ -20,7 +20,7 @@ auto DD::seekSector(n8 sector) -> u32 { n1 headCalc = io.currentTrack.bit(12); u32 startOffsetTable[16] = {0x0,0x5F15E0,0xB79D00,0x10801A0,0x1523720,0x1963D80,0x1D414C0,0x20BBCE0, - 0x23196E0,0x28A1E00,0x2DF5DC0,0x3299340,0x36D99A0,0x3AB70E0,0x3E31900,0x4149200}; + 0x23196E0,0x28A1E00,0x2DF5DC0,0x3299340,0x36D99A0,0x3AB70E0,0x3E31900,0x4149200}; u16 trackPhysicalTable[] = {0x000, 0x09E, 0x13C, 0x1D1, 0x266, 0x2FB, 0x390, 0x425}; u16 blockSizeTable[] = {0x4D08, 0x47B8, 0x4510, 0x3FC0, 0x3A70, 0x3520, 0x2FD0, 0x2A80, diff --git a/waterbox/ares64/ares/ares/n64/dd/io.cpp b/waterbox/ares64/ares/ares/n64/dd/io.cpp index 1ed95c4d19..a85269edd9 100644 --- a/waterbox/ares64/ares/ares/n64/dd/io.cpp +++ b/waterbox/ares64/ares/ares/n64/dd/io.cpp @@ -1,31 +1,31 @@ -auto DD::readWord(u32 address) -> u32 { - address = (address & 0x7f) >> 2; - n32 data; +auto DD::readHalf(u32 address) -> u16 { + address = (address & 0x7f) >> 1; + n16 data = 0; //ASIC_DATA if(address == 0) { - data.bit(16,31) = io.data; + data.bit(0,15) = io.data; } //ASIC_MISC_REG - if(address == 1) { + if(address == 2) { } //ASIC_STATUS - if(address == 2) { - data.bit(16) = io.status.diskChanged; - data.bit(17) = io.status.mechaError; - data.bit(18) = io.status.writeProtect; - data.bit(19) = io.status.headRetracted; - data.bit(20) = io.status.spindleMotorStopped; - data.bit(22) = io.status.resetState; - data.bit(23) = io.status.busyState; - data.bit(24) = (bool)disk; //disk present - data.bit(25) = irq.mecha.line; - data.bit(26) = irq.bm.line; - data.bit(27) = io.bm.error; - data.bit(28) = io.status.requestC2Sector; - data.bit(30) = io.status.requestUserSector; + if(address == 4) { + data.bit(0) = io.status.diskChanged; + data.bit(1) = io.status.mechaError; + data.bit(2) = io.status.writeProtect; + data.bit(3) = io.status.headRetracted; + data.bit(4) = io.status.spindleMotorStopped; + data.bit(6) = io.status.resetState; + data.bit(7) = io.status.busyState; + data.bit(8) = (bool)disk; //disk present + data.bit(9) = irq.mecha.line; + data.bit(10) = irq.bm.line; + data.bit(11) = io.bm.error; + data.bit(12) = io.status.requestC2Sector; + data.bit(14) = io.status.requestUserSector; //acknowledge bm interrupt (tested on real hardware) if(irq.bm.line) { @@ -36,133 +36,133 @@ auto DD::readWord(u32 address) -> u32 { } //ASIC_CUR_TK - if(address == 3) { - data.bit(16,31) = io.currentTrack; + if(address == 6) { + data.bit(0,15) = io.currentTrack; } //ASIC_BM_STATUS - if(address == 4) { - data.bit(16) = io.bm.c1Error; - data.bit(21) = io.bm.c1Single; - data.bit(22) = io.bm.c1Double; - data.bit(23) = io.bm.c1Correct; - data.bit(24) = io.bm.blockTransfer; - data.bit(25) = io.micro.error; - data.bit(26) = io.bm.error; - data.bit(31) = io.bm.start; + if(address == 8) { + data.bit(0) = io.bm.c1Error; + data.bit(5) = io.bm.c1Single; + data.bit(6) = io.bm.c1Double; + data.bit(7) = io.bm.c1Correct; + data.bit(8) = io.bm.blockTransfer; + data.bit(9) = io.micro.error; + data.bit(10) = io.bm.error; + data.bit(15) = io.bm.start; } //ASIC_ERR_SECTOR - if(address == 5) { - data.bit(16,23) = io.error.sector; - data.bit(24) = io.error.selfStop; - data.bit(25) = io.error.clockUnlock; - data.bit(26) = ~(bool)disk; //no disk - data.bit(27) = io.error.offTrack; - data.bit(28) = io.error.overrun; - data.bit(29) = io.error.spindle; - data.bit(30) = io.micro.error; - data.bit(31) = io.error.am; + if(address == 10) { + data.bit(0,7) = io.error.sector; + data.bit(8) = io.error.selfStop; + data.bit(9) = io.error.clockUnlock; + data.bit(10) = ~(bool)disk; //no disk + data.bit(11) = io.error.offTrack; + data.bit(12) = io.error.overrun; + data.bit(13) = io.error.spindle; + data.bit(14) = io.micro.error; + data.bit(15) = io.error.am; } //ASIC_SEQ_STATUS - if(address == 6) { + if(address == 12) { } //ASIC_CUR_SECTOR - if(address == 7) { - data.bit(24,31) = io.currentSector; - data.bit(16,23) = 0xc3; + if(address == 14) { + data.bit(8,15) = io.currentSector; + data.bit(0,7) = 0xc3; } //ASIC_HARD_RESET - if(address == 8) { + if(address == 16) { } //ASIC_C1_S0 - if(address == 9) { + if(address == 18) { } //ASIC_HOST_SECBYTE - if(address == 10) { - data.bit(16,23) = io.sectorSizeBuf; + if(address == 20) { + data.bit(0,7) = io.sectorSizeBuf; } //ASIC_C1_S2 - if(address == 11) { + if(address == 22) { } //ASIC_SEC_BYTE - if(address == 12) { - data.bit(16,23) = io.sectorSize; - data.bit(24,31) = io.sectorBlock; + if(address == 24) { + data.bit(0,7) = io.sectorSize; + data.bit(8,15) = io.sectorBlock; } //ASIC_C1_S4 - if(address == 13) { + if(address == 26) { } //ASIC_C1_S6 - if(address == 14) { + if(address == 28) { } //ASIC_CUR_ADDRESS - if(address == 15) { + if(address == 30) { } //ASIC_ID_REG - if(address == 16) { - data.bit(16,31) = io.id; + if(address == 32) { + data.bit(0,15) = io.id; } //ASIC_TEST_REG - if(address == 17) { + if(address == 34) { } //ASIC_TEST_PIN_SEL - if(address == 18) { + if(address == 36) { } debugger.io(Read, address, data); return data; } -auto DD::writeWord(u32 address, u32 data_) -> void { - address = (address & 0x7f) >> 2; - n32 data = data_; +auto DD::writeHalf(u32 address, u16 data_) -> void { + address = (address & 0x7f) >> 1; + n16 data = data_; //ASIC_DATA if(address == 0) { - io.data = data.bit(16,31); + io.data = data.bit(0,15); } //ASIC_MISC_REG - if(address == 1) { + if(address == 2) { } //ASIC_CMD - if(address == 2) { - command(data.bit(16,31)); + if(address == 4) { + command(data.bit(0,15)); } //ASIC_CUR_TK - if(address == 3) { + if(address == 6) { } //ASIC_BM_CTL - if(address == 4) { - io.bm.reset |= data.bit(28); - io.bm.readMode = data.bit(30); - //irq.bm.mask = ~data.bit(29); - io.bm.disableORcheck = data.bit(27); - io.bm.disableC1Correction = data.bit(26); - io.bm.blockTransfer = data.bit(25); - if (data.bit(24)) { + if(address == 8) { + io.bm.reset |= data.bit(12); + io.bm.readMode = data.bit(14); + //irq.bm.mask = ~data.bit(13); + io.bm.disableORcheck = data.bit(11); + io.bm.disableC1Correction = data.bit(10); + io.bm.blockTransfer = data.bit(9); + if (data.bit(8)) { //mecha int reset lower(IRQ::MECHA); } - io.currentSector = data.bit(16,23); - if (!data.bit(28) && io.bm.reset) { + io.currentSector = data.bit(0,7); + if (!data.bit(12) && io.bm.reset) { //BM reset io.bm.start = 0; io.bm.error = 0; @@ -172,76 +172,88 @@ auto DD::writeWord(u32 address, u32 data_) -> void { lower(IRQ::BM); } - if(data.bit(31) && disk) { + if(data.bit(15) && disk) { //start BM - io.bm.start |= data.bit(31); + io.bm.start |= data.bit(15); //TODO: proper research into seek and access times queue.insert(Queue::DD_BM_Request, 50'000 + (io.currentTrack.bit(0,11) / 15)); } } //ASIC_ERR_SECTOR - if(address == 5) { + if(address == 10) { } //ASIC_SEQ_CTL - if(address == 6) { - io.micro.enable = data.bit(30); + if(address == 12) { + io.micro.enable = data.bit(14); } //ASIC_CUR_SECTOR - if(address == 7) { + if(address == 14) { } //ASIC_HARD_RESET - if(address == 8) { + if(address == 16) { if((data >> 16) == 0xAAAA) { power(true); } } //ASIC_C1_S0 - if(address == 9) { + if(address == 18) { } //ASIC_HOST_SECBYTE - if(address == 10) { - io.sectorSizeBuf = data.bit(16,23); + if(address == 20) { + io.sectorSizeBuf = data.bit(0,7); } //ASIC_C1_S2 - if(address == 11) { - io.sectorSize = data.bit(16,23); - io.sectorBlock = data.bit(24,31); + if(address == 22) { + io.sectorSize = data.bit(0,7); + io.sectorBlock = data.bit(8,15); } //ASIC_SEC_BYTE - if(address == 12) { + if(address == 24) { } //ASIC_C1_S4 - if(address == 13) { + if(address == 26) { } //ASIC_C1_S6 - if(address == 14) { + if(address == 28) { } //ASIC_CUR_ADDRESS - if(address == 15) { + if(address == 30) { } //ASIC_ID_REG - if(address == 16) { + if(address == 32) { } //ASIC_TEST_REG - if(address == 17) { + if(address == 34) { } //ASIC_TEST_PIN_SEL - if(address == 18) { + if(address == 36) { } debugger.io(Write, address, data); } + +auto DD::readWord(u32 address) -> u32 { + n32 data; + data.bit(16,31) = readHalf(address + 0); + data.bit( 0,15) = readHalf(address + 2); + return (u32)data; +} + +auto DD::writeWord(u32 address, u32 data) -> void { + writeHalf(address + 0, data >> 16); + writeHalf(address + 2, data & 0xffff); +} diff --git a/waterbox/ares64/ares/ares/n64/dd/rtc.cpp b/waterbox/ares64/ares/ares/n64/dd/rtc.cpp index 8dae10a970..961a5a85ea 100644 --- a/waterbox/ares64/ares/ares/n64/dd/rtc.cpp +++ b/waterbox/ares64/ares/ares/n64/dd/rtc.cpp @@ -1,7 +1,9 @@ auto DD::rtcLoad() -> void { - /*if(auto fp = system.pak->read("time.rtc")) { +#if false + if(auto fp = system.pak->read("time.rtc")) { rtc.load(fp); - }*/ + } +#endif n64 check = 0; for(auto n : range(8)) check.byte(n) = rtc.read(n); @@ -11,17 +13,19 @@ auto DD::rtcLoad() -> void { for(auto n : range(8)) timestamp.byte(n) = rtc.read(8 + n); if(!~timestamp) return; //new save file - timestamp = rtcCallback() - timestamp; + timestamp = platform->time() - timestamp; while(timestamp--) rtcTickSecond(); } auto DD::rtcSave() -> void { - n64 timestamp = rtcCallback(); + n64 timestamp = platform->time(); for(auto n : range(8)) rtc.write(8 + n, timestamp.byte(n)); - /*if(auto fp = system.pak->write("time.rtc")) { +#if false + if(auto fp = system.pak->write("time.rtc")) { rtc.save(fp); - }*/ + } +#endif } auto DD::rtcTick(u32 offset) -> void { diff --git a/waterbox/ares64/ares/ares/n64/dd/serialization.cpp b/waterbox/ares64/ares/ares/n64/dd/serialization.cpp index a5c84e2439..f9047a15f6 100644 --- a/waterbox/ares64/ares/ares/n64/dd/serialization.cpp +++ b/waterbox/ares64/ares/ares/n64/dd/serialization.cpp @@ -1,66 +1,66 @@ auto DD::serialize(serializer& s) -> void { - s(irq.bm.line); - s(irq.bm.mask); - s(irq.mecha.line); - s(irq.mecha.mask); + s(irq.bm.line); + s(irq.bm.mask); + s(irq.mecha.line); + s(irq.mecha.mask); - s(ctl.diskType); - s(ctl.error.selfDiagnostic); - s(ctl.error.servoNG); - s(ctl.error.indexGapNG); - s(ctl.error.timeout); - s(ctl.error.undefinedCommand); - s(ctl.error.invalidParam); - s(ctl.error.unknown); - s(ctl.standbyDelayDisable); - s(ctl.standbyDelay); - s(ctl.sleepDelayDisable); - s(ctl.sleepDelay); - s(ctl.ledOnTime); - s(ctl.ledOffTime); + s(ctl.diskType); + s(ctl.error.selfDiagnostic); + s(ctl.error.servoNG); + s(ctl.error.indexGapNG); + s(ctl.error.timeout); + s(ctl.error.undefinedCommand); + s(ctl.error.invalidParam); + s(ctl.error.unknown); + s(ctl.standbyDelayDisable); + s(ctl.standbyDelay); + s(ctl.sleepDelayDisable); + s(ctl.sleepDelay); + s(ctl.ledOnTime); + s(ctl.ledOffTime); - s(io.data); + s(io.data); - s(io.status.requestUserSector); - s(io.status.requestC2Sector); - s(io.status.busyState); - s(io.status.resetState); - s(io.status.spindleMotorStopped); - s(io.status.headRetracted); - s(io.status.writeProtect); - s(io.status.mechaError); - s(io.status.diskChanged); + s(io.status.requestUserSector); + s(io.status.requestC2Sector); + s(io.status.busyState); + s(io.status.resetState); + s(io.status.spindleMotorStopped); + s(io.status.headRetracted); + s(io.status.writeProtect); + s(io.status.mechaError); + s(io.status.diskChanged); - s(io.currentTrack); - s(io.currentSector); + s(io.currentTrack); + s(io.currentSector); - s(io.sectorSizeBuf); - s(io.sectorSize); - s(io.sectorBlock); - s(io.id); + s(io.sectorSizeBuf); + s(io.sectorSize); + s(io.sectorBlock); + s(io.id); - s(io.bm.start); - s(io.bm.reset); - s(io.bm.error); - s(io.bm.blockTransfer); - s(io.bm.c1Correct); - s(io.bm.c1Double); - s(io.bm.c1Single); - s(io.bm.c1Error); - s(io.bm.readMode); - s(io.bm.disableORcheck); - s(io.bm.disableC1Correction); + s(io.bm.start); + s(io.bm.reset); + s(io.bm.error); + s(io.bm.blockTransfer); + s(io.bm.c1Correct); + s(io.bm.c1Double); + s(io.bm.c1Single); + s(io.bm.c1Error); + s(io.bm.readMode); + s(io.bm.disableORcheck); + s(io.bm.disableC1Correction); - s(io.error.am); - s(io.error.spindle); - s(io.error.overrun); - s(io.error.offTrack); - s(io.error.clockUnlock); - s(io.error.selfStop); - s(io.error.sector); + s(io.error.am); + s(io.error.spindle); + s(io.error.overrun); + s(io.error.offTrack); + s(io.error.clockUnlock); + s(io.error.selfStop); + s(io.error.sector); - s(io.micro.enable); - s(io.micro.error); + s(io.micro.enable); + s(io.micro.error); - s(state.seek); + s(state.seek); } diff --git a/waterbox/ares64/ares/ares/n64/memory/bus.hpp b/waterbox/ares64/ares/ares/n64/memory/bus.hpp index 904487dcbe..b7dcec5952 100644 --- a/waterbox/ares64/ares/ares/n64/memory/bus.hpp +++ b/waterbox/ares64/ares/ares/n64/memory/bus.hpp @@ -1,30 +1,30 @@ template -inline auto Bus::read(u32 address) -> u64 { +inline auto Bus::read(u32 address, u32& cycles) -> u64 { static constexpr u64 unmapped = 0; address &= 0x1fff'ffff - (Size - 1); if(address <= 0x007f'ffff) return rdram.ram.read(address); if(address <= 0x03ef'ffff) return unmapped; - if(address <= 0x03ff'ffff) return rdram.read(address); - if(address <= 0x0407'ffff) return rsp.read(address); - if(address <= 0x040f'ffff) return rsp.status.read(address); - if(address <= 0x041f'ffff) return rdp.read(address); - if(address <= 0x042f'ffff) return rdp.io.read(address); - if(address <= 0x043f'ffff) return mi.read(address); - if(address <= 0x044f'ffff) return vi.read(address); - if(address <= 0x045f'ffff) return ai.read(address); - if(address <= 0x046f'ffff) return pi.read(address); - if(address <= 0x047f'ffff) return ri.read(address); - if(address <= 0x048f'ffff) return si.read(address); + if(address <= 0x03ff'ffff) return rdram.read(address, cycles); + if(address <= 0x0407'ffff) return rsp.read(address, cycles); + if(address <= 0x040f'ffff) return rsp.status.read(address, cycles); + if(address <= 0x041f'ffff) return rdp.read(address, cycles); + if(address <= 0x042f'ffff) return rdp.io.read(address, cycles); + if(address <= 0x043f'ffff) return mi.read(address, cycles); + if(address <= 0x044f'ffff) return vi.read(address, cycles); + if(address <= 0x045f'ffff) return ai.read(address, cycles); + if(address <= 0x046f'ffff) return pi.read(address, cycles); + if(address <= 0x047f'ffff) return ri.read(address, cycles); + if(address <= 0x048f'ffff) return si.read(address, cycles); if(address <= 0x04ff'ffff) return unmapped; - if(address <= 0x1fbf'ffff) return pi.read(address); - if(address <= 0x1fcf'ffff) return pif.read(address); - if(address <= 0x7fff'ffff) return pi.read(address); + if(address <= 0x1fbf'ffff) return pi.read(address, cycles); + if(address <= 0x1fcf'ffff) return si.read(address, cycles); + if(address <= 0x7fff'ffff) return pi.read(address, cycles); return unmapped; } template -inline auto Bus::write(u32 address, u64 data) -> void { +inline auto Bus::write(u32 address, u64 data, u32& cycles) -> void { address &= 0x1fff'ffff - (Size - 1); if constexpr(Accuracy::CPU::Recompiler) { cpu.recompiler.invalidate(address + 0); if constexpr(Size == Dual) @@ -33,20 +33,20 @@ inline auto Bus::write(u32 address, u64 data) -> void { if(address <= 0x007f'ffff) return rdram.ram.write(address, data); if(address <= 0x03ef'ffff) return; - if(address <= 0x03ff'ffff) return rdram.write(address, data); - if(address <= 0x0407'ffff) return rsp.write(address, data); - if(address <= 0x040f'ffff) return rsp.status.write(address, data); - if(address <= 0x041f'ffff) return rdp.write(address, data); - if(address <= 0x042f'ffff) return rdp.io.write(address, data); - if(address <= 0x043f'ffff) return mi.write(address, data); - if(address <= 0x044f'ffff) return vi.write(address, data); - if(address <= 0x045f'ffff) return ai.write(address, data); - if(address <= 0x046f'ffff) return pi.write(address, data); - if(address <= 0x047f'ffff) return ri.write(address, data); - if(address <= 0x048f'ffff) return si.write(address, data); + if(address <= 0x03ff'ffff) return rdram.write(address, data, cycles); + if(address <= 0x0407'ffff) return rsp.write(address, data, cycles); + if(address <= 0x040f'ffff) return rsp.status.write(address, data, cycles); + if(address <= 0x041f'ffff) return rdp.write(address, data, cycles); + if(address <= 0x042f'ffff) return rdp.io.write(address, data, cycles); + if(address <= 0x043f'ffff) return mi.write(address, data, cycles); + if(address <= 0x044f'ffff) return vi.write(address, data, cycles); + if(address <= 0x045f'ffff) return ai.write(address, data, cycles); + if(address <= 0x046f'ffff) return pi.write(address, data, cycles); + if(address <= 0x047f'ffff) return ri.write(address, data, cycles); + if(address <= 0x048f'ffff) return si.write(address, data, cycles); if(address <= 0x04ff'ffff) return; - if(address <= 0x1fbf'ffff) return pi.write(address, data); - if(address <= 0x1fcf'ffff) return pif.write(address, data); - if(address <= 0x7fff'ffff) return pi.write(address, data); + if(address <= 0x1fbf'ffff) return pi.write(address, data, cycles); + if(address <= 0x1fcf'ffff) return si.write(address, data, cycles); + if(address <= 0x7fff'ffff) return pi.write(address, data, cycles); return; } diff --git a/waterbox/ares64/ares/ares/n64/memory/io.hpp b/waterbox/ares64/ares/ares/n64/memory/io.hpp index 8df9708a5c..aa8fd4b95f 100644 --- a/waterbox/ares64/ares/ares/n64/memory/io.hpp +++ b/waterbox/ares64/ares/ares/n64/memory/io.hpp @@ -1,9 +1,13 @@ template -struct IO { +struct RCP { //A device which is part of RCP + const u32 DefaultReadCycles = 20; + const u32 DefaultWriteCycles = 0; //not implemented until we implement the CPU write queue + template - auto read(u32 address) -> u64 { + auto read(u32 address, u32& cycles) -> u64 { + cycles = DefaultReadCycles; if constexpr(Size == Byte) { - auto data = ((T*)this)->readWord(address); + auto data = ((T*)this)->readWord(address, cycles); switch(address & 3) { case 0: return data >> 24; case 1: return data >> 16; @@ -12,43 +16,92 @@ struct IO { } } if constexpr(Size == Half) { - auto data = ((T*)this)->readWord(address); + auto data = ((T*)this)->readWord(address, cycles); switch(address & 2) { case 0: return data >> 16; case 2: return data >> 0; } } if constexpr(Size == Word) { - return ((T*)this)->readWord(address); + return ((T*)this)->readWord(address, cycles); } if constexpr(Size == Dual) { - u64 data = ((T*)this)->readWord(address); - return data << 32 | ((T*)this)->readWord(address + 4); + u64 data = ((T*)this)->readWord(address, cycles); + return data << 32 | ((T*)this)->readWord(address + 4, cycles); } unreachable; } template - auto write(u32 address, u64 data) -> void { + auto write(u32 address, u64 data, u32& cycles) -> void { + cycles = DefaultWriteCycles; if constexpr(Size == Byte) { switch(address & 3) { - case 0: return ((T*)this)->writeWord(address, data << 24); - case 1: return ((T*)this)->writeWord(address, data << 16); - case 2: return ((T*)this)->writeWord(address, data << 8); - case 3: return ((T*)this)->writeWord(address, data << 0); + case 0: return ((T*)this)->writeWord(address, data << 24, cycles); + case 1: return ((T*)this)->writeWord(address, data << 16, cycles); + case 2: return ((T*)this)->writeWord(address, data << 8, cycles); + case 3: return ((T*)this)->writeWord(address, data << 0, cycles); } } if constexpr(Size == Half) { switch(address & 2) { - case 0: return ((T*)this)->writeWord(address, data << 16); - case 2: return ((T*)this)->writeWord(address, data << 0); + case 0: return ((T*)this)->writeWord(address, data << 16, cycles); + case 2: return ((T*)this)->writeWord(address, data << 0, cycles); } } if constexpr(Size == Word) { - ((T*)this)->writeWord(address, data); + ((T*)this)->writeWord(address, data, cycles); } if constexpr(Size == Dual) { - ((T*)this)->writeWord(address, data >> 32); + ((T*)this)->writeWord(address, data >> 32, cycles); } } }; + +template +struct PI { //A device which is reachable only behind PI + template + auto read(u32 address) -> u64 { + static_assert(Size == Half || Size == Word); //PI bus will do 32-bit (CPU) or 16-bit (DMA) only + if constexpr(Size == Half) { + return ((T*)this)->readHalf(address); + } + if constexpr(Size == Word) { + return ((T*)this)->readWord(address); + } + unreachable; + } + + template + auto write(u32 address, u64 data) -> void { + static_assert(Size == Half || Size == Word); //PI bus will do 32-bit (CPU) or 16-bit (DMA) only + if constexpr(Size == Half) { + return ((T*)this)->writeHalf(address, data); + } + if constexpr(Size == Word) { + return ((T*)this)->writeWord(address, data); + } + unreachable; + } +}; + +template +struct SI { //A device which is reachable only behind SI + template + auto read(u32 address) -> u64 { + static_assert(Size == Word); //SI bus will do 32-bit (CPU/DMA) + if constexpr(Size == Word) { + return ((T*)this)->readWord(address); + } + unreachable; + } + + template + auto write(u32 address, u64 data) -> void { + static_assert(Size == Word); //PI bus will do 32-bit (CPU/DMA) + if constexpr(Size == Word) { + return ((T*)this)->writeWord(address, data); + } + unreachable; + } +}; diff --git a/waterbox/ares64/ares/ares/n64/memory/memory.hpp b/waterbox/ares64/ares/ares/n64/memory/memory.hpp index 20b24ebf66..b00614f4da 100644 --- a/waterbox/ares64/ares/ares/n64/memory/memory.hpp +++ b/waterbox/ares64/ares/ares/n64/memory/memory.hpp @@ -31,8 +31,8 @@ namespace Memory { struct Bus { //bus.hpp - template auto read(u32 address) -> u64; - template auto write(u32 address, u64 data) -> void; + template auto read(u32 address, u32& cycles) -> u64; + template auto write(u32 address, u64 data, u32& cycles) -> void; }; extern Bus bus; diff --git a/waterbox/ares64/ares/ares/n64/mi/io.cpp b/waterbox/ares64/ares/ares/n64/mi/io.cpp index aac5e31753..caaf82bcb6 100644 --- a/waterbox/ares64/ares/ares/n64/mi/io.cpp +++ b/waterbox/ares64/ares/ares/n64/mi/io.cpp @@ -1,4 +1,4 @@ -auto MI::readWord(u32 address) -> u32 { +auto MI::readWord(u32 address, u32& cycles) -> u32 { address = (address & 0xfffff) >> 2; n32 data; @@ -42,7 +42,7 @@ auto MI::readWord(u32 address) -> u32 { return data; } -auto MI::writeWord(u32 address, u32 data_) -> void { +auto MI::writeWord(u32 address, u32 data_, u32& cycles) -> void { address = (address & 0xfffff) >> 2; n32 data = data_; diff --git a/waterbox/ares64/ares/ares/n64/mi/mi.hpp b/waterbox/ares64/ares/ares/n64/mi/mi.hpp index 7402933874..e0df7dcfa6 100644 --- a/waterbox/ares64/ares/ares/n64/mi/mi.hpp +++ b/waterbox/ares64/ares/ares/n64/mi/mi.hpp @@ -1,6 +1,6 @@ //MIPS Interface -struct MI : Memory::IO { +struct MI : Memory::RCP { Node::Object node; struct Debugger { @@ -27,8 +27,8 @@ struct MI : Memory::IO { auto power(bool reset) -> void; //io.cpp - auto readWord(u32 address) -> u32; - auto writeWord(u32 address, u32 data) -> void; + auto readWord(u32 address, u32& cycles) -> u32; + auto writeWord(u32 address, u32 data, u32& cycles) -> void; //serialization.cpp auto serialize(serializer&) -> void; diff --git a/waterbox/ares64/ares/ares/n64/n64.hpp b/waterbox/ares64/ares/ares/n64/n64.hpp index 52fc35eece..52b756e396 100644 --- a/waterbox/ares64/ares/ares/n64/n64.hpp +++ b/waterbox/ares64/ares/ares/n64/n64.hpp @@ -7,21 +7,18 @@ #include #include #include +#include #include #include #if defined(ARCHITECTURE_AMD64) #include using v128 = __m128i; -#elif defined(ARCHITECTURE_ARM64) +#elif defined(ARCHITECTURE_ARM64) && !defined(COMPILER_MICROSOFT) #include using v128 = __m128i; #endif -#if defined(VULKAN) - #include -#endif - namespace ares::Nintendo64 { auto enumerate() -> vector; auto load(Node::System& node, string name) -> bool; @@ -57,6 +54,8 @@ namespace ares::Nintendo64 { PI_BUS_Write, SI_DMA_Read, SI_DMA_Write, + SI_BUS_Write, + RTC_Tick, DD_Clock_Tick, DD_MECHA_Response, DD_BM_Request, @@ -65,10 +64,16 @@ namespace ares::Nintendo64 { }; extern Queue queue; + struct BCD { + static auto encode(u8 value) -> u8 { return value / 10 << 4 | value % 10; } + static auto decode(u8 value) -> u8 { return (value >> 4) * 10 + (value & 15); } + }; + #include #include #include #include + #include #include #include #include diff --git a/waterbox/ares64/ares/ares/n64/pi/bus.hpp b/waterbox/ares64/ares/ares/n64/pi/bus.hpp index 839c39f96b..1ccd057970 100644 --- a/waterbox/ares64/ares/ares/n64/pi/bus.hpp +++ b/waterbox/ares64/ares/ares/n64/pi/bus.hpp @@ -1,10 +1,11 @@ -inline auto PI::readWord(u32 address) -> u32 { +inline auto PI::readWord(u32 address, u32& cycles) -> u32 { if(address <= 0x046f'ffff) return ioRead(address); if (unlikely(io.ioBusy)) { - writeForceFinish(); //technically, we should wait until Queue::PI_BUS_Write + cycles += writeForceFinish(); return io.busLatch; } + cycles += 250; return busRead(address); } @@ -50,7 +51,7 @@ inline auto PI::busRead(u32 address) -> u32 { return unmapped; //accesses here actually lock out the RCP } -inline auto PI::writeWord(u32 address, u32 data) -> void { +inline auto PI::writeWord(u32 address, u32 data, u32& cycles) -> void { if(address <= 0x046f'ffff) return ioWrite(address, data); if(io.ioBusy) return; @@ -106,7 +107,7 @@ inline auto PI::writeFinished() -> void { io.ioBusy = 0; } -inline auto PI::writeForceFinish() -> void { +inline auto PI::writeForceFinish() -> u32 { io.ioBusy = 0; - queue.remove(Queue::PI_BUS_Write); + return queue.remove(Queue::PI_BUS_Write); } diff --git a/waterbox/ares64/ares/ares/n64/pi/pi.hpp b/waterbox/ares64/ares/ares/n64/pi/pi.hpp index 3a1c4fc2e0..6c466604f2 100644 --- a/waterbox/ares64/ares/ares/n64/pi/pi.hpp +++ b/waterbox/ares64/ares/ares/n64/pi/pi.hpp @@ -1,6 +1,6 @@ //Peripheral Interface -struct PI : Memory::IO { +struct PI : Memory::RCP { Node::Object node; struct Debugger { @@ -28,10 +28,10 @@ struct PI : Memory::IO { auto ioWrite(u32 address, u32 data) -> void; //bus.hpp - auto readWord(u32 address) -> u32; - auto writeWord(u32 address, u32 data) -> void; + auto readWord(u32 address, u32& cycles) -> u32; + auto writeWord(u32 address, u32 data, u32& cycles) -> void; auto writeFinished() -> void; - auto writeForceFinish() -> void; + auto writeForceFinish() -> u32; template auto busRead(u32 address) -> u32; template diff --git a/waterbox/ares64/ares/ares/n64/pif/hle.cpp b/waterbox/ares64/ares/ares/n64/pif/hle.cpp new file mode 100644 index 0000000000..a35acf3a20 --- /dev/null +++ b/waterbox/ares64/ares/ares/n64/pif/hle.cpp @@ -0,0 +1,373 @@ + +auto PIF::addressCRC(u16 address) const -> n5 { + n5 crc = 0; + for(u32 i : range(16)) { + n5 xor_ = crc & 0x10 ? 0x15 : 0x00; + crc <<= 1; + if(address & 0x8000) crc |= 1; + address <<= 1; + crc ^= xor_; + } + return crc; +} + +auto PIF::dataCRC(array_view data) const -> n8 { + n8 crc = 0; + for(u32 i : range(33)) { + for(u32 j : reverse(range(8))) { + n8 xor_ = crc & 0x80 ? 0x85 : 0x00; + crc <<= 1; + if(i < 32) { + if(data[i] & 1 << j) crc |= 1; + } + crc ^= xor_; + } + } + return crc; +} + +auto PIF::descramble(n4 *buf, int size) -> void { + for(int i=size-1; i>0; i--) buf[i] -= buf[i-1] + 1; +} + +auto PIF::step(u32 clocks) -> void { + Thread::clock += clocks; + if(intram.bootTimeout > 0) intram.bootTimeout -= clocks; +} + +auto PIF::ramReadCommand() -> u8 { + return ram.read(0x3f); +} + +auto PIF::ramWriteCommand(u8 val) -> void { + return ram.write(0x3f, val); +} + +auto PIF::memSwap(u32 address, n8 &val) -> void { + n8 data = ram.read(address); + ram.write(address, (u8)val); + val = data; +} + +auto PIF::memSwapSecrets() -> void { + for (auto i: range(3)) memSwap(0x25+i, intram.osInfo[i]); + for (auto i: range(6)) memSwap(0x32+i, intram.cpuChecksum[i]); +} + +auto PIF::intA(bool dir, bool size) -> void { + if(dir == Read) { + if(size == Size64) { + if(ramReadCommand() & 0x02) { + challenge(); + return; + } + joyRun(); + return; + } + } + if(dir == Write) { + if(ramReadCommand() & 0x01) { + ramWriteCommand(ramReadCommand() & ~0x01); + joyInit(); + joyParse(); + return; + } + return; + } +} + +auto PIF::joyInit() -> void { + for(auto i : range(5)) { + intram.joyStatus[i].skip = 1; + intram.joyStatus[i].reset = 0; + } +} + +auto PIF::joyParse() -> void { + static constexpr bool Debug = 0; + + if constexpr(Debug) { + print("joyParse:\n{\n"); + for(u32 y : range(8)) { + print(" "); + for(u32 x : range(8)) { + print(hex(ram.read(y * 8 + x), 2L), " "); + } + print("\n"); + } + print("}\n"); + } + + u32 offset = 0; + n3 channel = 0; //0-5 + while(channel < 5 && offset < 64) { + n8 send = ram.read(offset++); + if(send == 0xfe) break; //end of packets + if(send == 0xff) continue; //alignment padding + if(send == 0x00) { channel++; continue; } // channel skip + if(send == 0xfd) { // channel reset + intram.joyStatus[channel++].reset = 1; + continue; + } + u32 sendOffset = offset-1; + n8 recv = ram.read(offset++); + send &= 0x3f; + recv &= 0x3f; + offset += send+recv; + if(offset < 64) { + intram.joyAddress[channel] = sendOffset; + intram.joyStatus[channel].skip = 0; + channel++; + } + } +} + +auto PIF::joyRun() -> void { + static constexpr bool Debug = 0; + + ControllerPort* controllers[4] = { + &controllerPort1, + &controllerPort2, + &controllerPort3, + &controllerPort4, + }; + + for (i32 channel=4; channel>=0; channel--) { + if (intram.joyStatus[channel].reset) { + if (channel < 4 && controllers[channel]->device) + controllers[channel]->device->reset(); + continue; + } + if (intram.joyStatus[channel].skip) continue; + + u32 offset = intram.joyAddress[channel]; + n8 send = ram.read(offset++); + if(send & 0x80) continue; // skip (another way to do it) + if(send & 0x40) { //reset (another way to do it) + if (channel < 4 && controllers[channel]->device) + controllers[channel]->device->reset(); + continue; + } + u32 recvOffset = offset; + n8 recv = ram.read(offset++); + send &= 0x3f; + recv &= 0x3f; + + n8 input[64]; + for(u32 index : range(send)) { + input[index] = ram.read(offset++); + } + n8 output[64]; + b1 valid = 0; + b1 over = 0; + + //controller port communication + if (channel < 4 && controllers[channel]->device) { + n2 status = controllers[channel]->device->comm(send, recv, input, output); + valid = status.bit(0); + over = status.bit(1); + } + //cartrige joybus communication + if (channel == 4) { + n2 status = cartridge.joybusComm(send, recv, input, output); + valid = status.bit(0); + over = status.bit(1); + } + + if(!valid) ram.write(recvOffset, 0x80 | recv); + if(over) ram.write(recvOffset, 0x40 | recv); + if (valid) { + for(u32 index : range(recv)) { + ram.write(offset++, output[index]); + } + } + } + + if constexpr(Debug) { + print("joyRun:\n[\n"); + for(u32 y : range(8)) { + print(" "); + for(u32 x : range(8)) { + print(hex(ram.read(y * 8 + x), 2L), " "); + } + print("\n"); + } + print("]\n"); + } +} + +auto PIF::estimateTiming() -> u32 { + ControllerPort* controllers[4] = { + &controllerPort1, + &controllerPort2, + &controllerPort3, + &controllerPort4, + }; + + u32 cycles = 13600; + u32 short_cmds = 0; + + u32 offset = 0; + u32 channel = 0; + while(offset < 64 && channel < 5) { + n8 send = ram.read(offset++); + if(send == 0xfe) { short_cmds++; break; } //end of packets + if(send == 0x00) { short_cmds++; channel++; continue; } + if(send == 0xfd) { short_cmds++; channel++; continue; } //channel reset + if(send == 0xff) { short_cmds++; continue; } //alignment padding + + n8 recv = ram.read(offset++); + + //clear flags from lengths + send &= 0x3f; + recv &= 0x3f; + n8 input[64]; + for(u32 index : range(send)) { + input[index] = ram.read(offset++); + } + offset += recv; + + if (channel < 4) { + if (controllers[channel]->device) { + cycles += 22000; + } else { + cycles += 18000; + } + } else { + //accessories(TBD) + cycles += 20000; + } + + channel++; + } + + cycles += 1420 * short_cmds; + return cycles; +} + +auto PIF::challenge() -> void { + cic.writeBit(1); cic.writeBit(0); //challenge command + cic.readNibble(); //ignore timeout value returned by CIC (we simulate instant response) + cic.readNibble(); //timeout high nibble + for(u32 address : range(15)) { + auto data = ram.read(0x30 + address); + cic.writeNibble(data >> 4 & 0xf); + cic.writeNibble(data >> 0 & 0xf); + } + cic.readBit(); //ignore start bit + for(u32 address : range(15)) { + u8 data = 0; + data |= cic.readNibble() << 4; + data |= cic.readNibble() << 0; + ram.write(0x30 + address, data); + } +} + +auto PIF::mainHLE() -> void { + step(10240*8); + + if(likely(state == Run)) { + //cicCompare() + return; + } + + if(state == Init) { + n4 hello = cic.readNibble(); + if (hello.bit(0,1) != 1) { + debug(unusual, "[PIF::main] invalid CIC hello message ", hex(hello, 4L)); + state = Error; + return; + } + if constexpr(Accuracy::PIF::RegionLock) { + if(hello.bit(2) != (u32)system.region()) { + const char *region[2] = { "NTSC", "PAL" }; + debug(unusual, "[PIF::main] CIC region mismatch: console is ", region[(u32)system.region()], " but cartridge is ", region[(int)hello.bit(4)]); + state = Error; + return; + } + } + n4 osinfo = 0; + osinfo.bit(2) = 1; //"version" bit (unknown, always set) + osinfo.bit(3) = hello.bit(3); //64dd + + n4 buf[6]; + for (auto i: range(6)) buf[i] = cic.readNibble(); + for (auto i: range(2)) descramble(buf, 6); + + intram.osInfo[0].bit(4,7) = buf[0]; + intram.osInfo[0].bit(0,3) = buf[1]; + intram.osInfo[1].bit(4,7) = buf[2]; + intram.osInfo[1].bit(0,3) = buf[3]; + intram.osInfo[2].bit(4,7) = buf[4]; + intram.osInfo[2].bit(0,3) = buf[5]; + + intram.osInfo[0].bit(0,3) = osinfo; + ramWriteCommand(0x00); + memSwapSecrets(); //show osinfo+seeds in external memory + state = WaitLockout; + return; + } + + if(state == WaitLockout && (ramReadCommand() & 0x10)) { + io.romLockout = 1; + joyInit(); + state = WaitGetChecksum; + return; + } + + if(state == WaitGetChecksum && (ramReadCommand() & 0x20)) { + memSwapSecrets(); //hide osinfo+seeds, copy+hide checksum to internal memory + ramWriteCommand(ramReadCommand() | 0x80); + state = WaitCheckChecksum; + return; + } + + if(state == WaitCheckChecksum && (ramReadCommand() & 0x40)) { + if (true) { // only on cold boot + n4 buf[16]; + for (auto i: range(16)) buf[i] = cic.readNibble(); + for (auto i: range(4)) descramble(buf, 16); + for (auto i: range(6)) { + intram.cicChecksum[i].bit(4,7) = buf[i*2+4]; + intram.cicChecksum[i].bit(0,3) = buf[i*2+5]; + } + intram.osInfo[0].bit(1) = 1; //warm boot (NMI) flag (ready in case a reset is made in the future) + } + + for (auto i: range(6)) { + u8 data = intram.cpuChecksum[i]; + if (intram.cicChecksum[i] != data) { + debug(unusual, "[PIF::main] invalid IPL2 checksum: ", cic.model, ":", + hex(intram.cicChecksum[0], 2L), hex(intram.cicChecksum[1], 2L), hex(intram.cicChecksum[2], 2L), + hex(intram.cicChecksum[3], 2L), hex(intram.cicChecksum[4], 2L), hex(intram.cicChecksum[5], 2L), + " != cpu:", + hex(intram.cpuChecksum[0], 2L), hex(intram.cpuChecksum[1], 2L), hex(intram.cpuChecksum[2], 2L), + hex(intram.cpuChecksum[3], 2L), hex(intram.cpuChecksum[4], 2L), hex(intram.cpuChecksum[5], 2L)); + state = Error; + return; + } + } + for (auto i: range(6)) intram.cpuChecksum[i] = 0; + state = WaitTerminateBoot; + intram.bootTimeout = 6 * 187500000; //6 seconds + return; + } + + if(state == WaitTerminateBoot && (ramReadCommand() & 0x08)) { + ramWriteCommand(0x00); + io.resetEnabled = 1; + state = Run; + return; + } + + if(state == WaitTerminateBoot && intram.bootTimeout <= 0) { + debug(unusual, "[PIF::main] boot timeout: CPU has not sent the boot termination command within 5 seconds. Halting the CPU"); + state = Error; + return; + } + + if(state == Error) { + cpu.scc.nmiPending = 1; + return; + } +} diff --git a/waterbox/ares64/ares/ares/n64/pif/io.cpp b/waterbox/ares64/ares/ares/n64/pif/io.cpp index 6e3f3b09a4..4d1ac5478f 100644 --- a/waterbox/ares64/ares/ares/n64/pif/io.cpp +++ b/waterbox/ares64/ares/ares/n64/pif/io.cpp @@ -1,4 +1,4 @@ -auto PIF::readWord(u32 address) -> u32 { +auto PIF::readInt(u32 address) -> u32 { address &= 0x7ff; if(address <= 0x7bf) { if(io.romLockout) return 0; @@ -7,7 +7,7 @@ auto PIF::readWord(u32 address) -> u32 { return ram.read(address); } -auto PIF::writeWord(u32 address, u32 data) -> void { +auto PIF::writeInt(u32 address, u32 data) -> void { address &= 0x7ff; if(address <= 0x7bf) { if(io.romLockout) return; @@ -15,3 +15,29 @@ auto PIF::writeWord(u32 address, u32 data) -> void { } return ram.write(address, data); } + +auto PIF::readWord(u32 address) -> u32 { + intA(Read, Size4); + return readInt(address); +} + +auto PIF::writeWord(u32 address, u32 data) -> void { + writeInt(address, data); + return intA(Write, Size4); +} + +auto PIF::dmaRead(u32 address, u32 ramAddress) -> void { + intA(Read, Size64); + for(u32 offset = 0; offset < 64; offset += 4) { + u32 data = readInt(address + offset); + rdram.ram.write(ramAddress + offset, data); + } +} + +auto PIF::dmaWrite(u32 address, u32 ramAddress) -> void { + for(u32 offset = 0; offset < 64; offset += 4) { + u32 data = rdram.ram.read(ramAddress + offset); + writeInt(address + offset, data); + } + intA(Write, Size64); +} diff --git a/waterbox/ares64/ares/ares/n64/pif/pif.cpp b/waterbox/ares64/ares/ares/n64/pif/pif.cpp index d7fa83a886..841d82414a 100644 --- a/waterbox/ares64/ares/ares/n64/pif/pif.cpp +++ b/waterbox/ares64/ares/ares/n64/pif/pif.cpp @@ -3,6 +3,7 @@ namespace ares::Nintendo64 { PIF pif; +#include "hle.cpp" #include "io.cpp" #include "debugger.cpp" #include "serialization.cpp" @@ -22,262 +23,13 @@ auto PIF::unload() -> void { node.reset(); } -auto PIF::addressCRC(u16 address) const -> n5 { - n5 crc = 0; - for(u32 i : range(16)) { - n5 xor = crc & 0x10 ? 0x15 : 0x00; - crc <<= 1; - if(address & 0x8000) crc |= 1; - address <<= 1; - crc ^= xor; - } - return crc; -} - -auto PIF::dataCRC(array_view data) const -> n8 { - n8 crc = 0; - for(u32 i : range(33)) { - for(u32 j : reverse(range(8))) { - n8 xor = crc & 0x80 ? 0x85 : 0x00; - crc <<= 1; - if(i < 32) { - if(data[i] & 1 << j) crc |= 1; - } - crc ^= xor; - } - } - return crc; -} - -auto PIF::run() -> void { - auto flags = ram.read(0x3f); - - //controller polling - if(flags & 0x01) { - //todo: this flag is supposed to be cleared, but doing so breaks inputs - //flags &= ~0x01; - scan(); - } - - //CIC-NUS-6105 challenge/response - if(flags & 0x02) { - flags &= ~0x02; - challenge(); - } - - //unknown purpose - if(flags & 0x04) { - flags &= ~0x04; - debug(unimplemented, "[SI::main] flags & 0x04"); - } - - //must be sent within 5s of the console booting, or SM5 will lock the N64 - if(flags & 0x08) { - flags &= ~0x08; - } - - //PIF ROM lockout - if(flags & 0x10) { - flags &= ~0x10; - io.romLockout = 1; - } - - //initialization - if(flags & 0x20) { - flags &= ~0x20; - flags |= 0x80; //set completion flag - } - - //clear PIF RAM - if(flags & 0x40) { - flags &= ~0x40; - ram.fill(); - } - - ram.write(0x3f, flags); -} - -auto PIF::scan() -> void { - ControllerPort* controllers[4] = { - &controllerPort1, - &controllerPort2, - &controllerPort3, - &controllerPort4, - }; - - static constexpr bool Debug = 0; - - if constexpr(Debug) { - print("{\n"); - for(u32 y : range(8)) { - print(" "); - for(u32 x : range(8)) { - print(hex(ram.read(y * 8 + x), 2L), " "); - } - print("\n"); - } - print("}\n"); - } - - n3 channel = 0; //0-5 - for(u32 offset = 0; offset < 64;) { - n8 send = ram.read(offset++); - if(send == 0x00) { channel++; continue; } - if(send == 0xfd) continue; //channel reset - if(send == 0xfe) break; //end of packets - if(send == 0xff) continue; //alignment padding - n8 recvOffset = offset; - n8 recv = ram.read(offset++); - if(recv == 0xfe) break; //end of packets - - //clear flags from lengths - send &= 0x3f; - recv &= 0x3f; - - n8 input[64]; - for(u32 index : range(send)) { - input[index] = ram.read(offset++); - } - n8 output[64]; - b1 valid = 0; - b1 over = 0; - - //controller port communication - if (channel < 4 && controllers[channel]->device) { - n2 status = controllers[channel]->device->comm(send, recv, input, output); - valid = status.bit(0); - over = status.bit(1); - } - - if (channel >= 4) { - //status - if(input[0] == 0x00 || input[0] == 0xff) { - //cartridge EEPROM (4kbit) - if(cartridge.eeprom.size == 512) { - output[0] = 0x00; - output[1] = 0x80; - output[2] = 0x00; - valid = 1; - } - - //cartridge EEPROM (16kbit) - if(cartridge.eeprom.size == 2048) { - output[0] = 0x00; - output[1] = 0xc0; - output[2] = 0x00; - valid = 1; - } - } - - //read EEPROM - if(input[0] == 0x04 && send >= 2) { - u32 address = input[1] * 8; - for(u32 index : range(recv)) { - output[index] = cartridge.eeprom.read(address++); - } - valid = 1; - } - - //write EEPROM - if(input[0] == 0x05 && send >= 2 && recv >= 1) { - u32 address = input[1] * 8; - for(u32 index : range(send - 2)) { - cartridge.eeprom.write(address++, input[2 + index]); - } - output[0] = 0x00; - valid = 1; - } - - //RTC status - if(input[0] == 0x06) { - debug(unimplemented, "[SI::main] RTC status"); - } - - //RTC read - if(input[0] == 0x07) { - debug(unimplemented, "[SI::main] RTC read"); - } - - //RTC write - if(input[0] == 0x08) { - debug(unimplemented, "[SI::main] RTC write"); - } - } - - if(!valid) { - ram.write(recvOffset, 0x80 | recv & 0x3f); - } - if(over) { - ram.write(recvOffset, 0x40 | recv & 0x3f); - } - - if (valid) { - for(u32 index : range(recv)) { - ram.write(offset++, output[index]); - } - } - channel++; - } - - if constexpr(Debug) { - print("[\n"); - for(u32 y : range(8)) { - print(" "); - for(u32 x : range(8)) { - print(hex(ram.read(y * 8 + x), 2L), " "); - } - print("\n"); - } - print("]\n"); - } -} - -//CIC-NUS-6105 anti-piracy challenge/response -auto PIF::challenge() -> void { - static n4 lut[32] = { - 0x4, 0x7, 0xa, 0x7, 0xe, 0x5, 0xe, 0x1, - 0xc, 0xf, 0x8, 0xf, 0x6, 0x3, 0x6, 0x9, - 0x4, 0x1, 0xa, 0x7, 0xe, 0x5, 0xe, 0x1, - 0xc, 0x9, 0x8, 0x5, 0x6, 0x3, 0xc, 0x9, - }; - - n4 challenge[30]; - n4 response[30]; - - //15 bytes -> 30 nibbles - for(u32 address : range(15)) { - auto data = ram.read(0x30 + address); - challenge[address << 1 | 0] = data >> 4; - challenge[address << 1 | 1] = data >> 0; - } - - n4 key = 0xb; - n1 sel = 0; - for(u32 address : range(30)) { - n4 data = key + 5 * challenge[address]; - response[address] = data; - key = lut[sel << 4 | data]; - n1 mod = data >> 3; - n3 mag = data >> 0; - if(mod) mag = ~mag; - if(mag % 3 != 1) mod = !mod; - if(sel) { - if(data == 0x1 || data == 0x9) mod = 1; - if(data == 0xb || data == 0xe) mod = 0; - } - sel = mod; - } - - //30 nibbles -> 15 bytes - for(u32 address : range(15)) { - n8 data = 0; - data |= response[address << 1 | 0] << 4; - data |= response[address << 1 | 1] << 0; - ram.write(0x30 + address, data); - } +auto PIF::main() -> void { + mainHLE(); } auto PIF::power(bool reset) -> void { + Thread::reset(); + string pifrom = Region::PAL() ? "pif.pal.rom" : "pif.ntsc.rom"; if(auto fp = system.pak->read(pifrom)) { rom.load(fp); @@ -285,27 +37,8 @@ auto PIF::power(bool reset) -> void { ram.fill(); io = {}; - - //write CIC seeds into PIF RAM so that cartridge checksum function passes - string cic = cartridge.node ? cartridge.cic() : dd.cic(); - n8 seed = 0x3f; - n1 version = 0; - n1 type = 0; - if(cic == "CIC-NUS-6101" || cic == "CIC-NUS-7102") seed = 0x3f, version = 1; - if(cic == "CIC-NUS-6102" || cic == "CIC-NUS-7101") seed = 0x3f; - if(cic == "CIC-NUS-6103" || cic == "CIC-NUS-7103") seed = 0x78; - if(cic == "CIC-NUS-6105" || cic == "CIC-NUS-7105") seed = 0x91; - if(cic == "CIC-NUS-6106" || cic == "CIC-NUS-7106") seed = 0x85; - if(cic == "CIC-NUS-8303" || cic == "CIC-NUS-8401") seed = 0xdd, type = 1; - if(cic == "CIC-NUS-DDUS") seed = 0xde, type = 1; - - n32 data; - data.bit(0, 7) = 0x3f; //CIC IPL2 seed - data.bit(8,15) = seed; //CIC IPL3 seed - data.bit(17) = reset; //osResetType (0 = power; 1 = reset (NMI)) - data.bit(18) = version; //osVersion - data.bit(19) = type; //osRomType (0 = Gamepak; 1 = 64DD) - ram.write(0x24, data); + intram = {}; + state = Init; } } diff --git a/waterbox/ares64/ares/ares/n64/pif/pif.hpp b/waterbox/ares64/ares/ares/n64/pif/pif.hpp index 0c532aa4fd..a93a3e2424 100644 --- a/waterbox/ares64/ares/ares/n64/pif/pif.hpp +++ b/waterbox/ares64/ares/ares/n64/pif/pif.hpp @@ -1,9 +1,14 @@ //PIF-NUS -struct PIF : Memory::IO { +struct PIF : Thread, Memory::SI { + enum State : u32 { Init, WaitLockout, WaitGetChecksum, WaitCheckChecksum, WaitTerminateBoot, Run, Error }; + enum IntADir : bool { Read, Write }; + enum IntASize : bool { Size4, Size64 }; + Node::Object node; Memory::Readable rom; Memory::Writable ram; + u32 state; struct Debugger { //debugger.cpp @@ -13,28 +18,59 @@ struct PIF : Memory::IO { struct Memory { Node::Debugger::Memory ram; } memory; - } debugger; + struct Intram { + n8 osInfo[3]; + n8 cpuChecksum[6]; + n8 cicChecksum[6]; + s32 bootTimeout; + n8 joyAddress[5]; + struct { + n1 skip; + n1 reset; + } joyStatus[5]; + + auto serialize(serializer& s) -> void; + } intram; + //pif.cpp + auto step(u32 clocks) -> void; auto load(Node::Object) -> void; auto unload() -> void; + auto main() -> void; + auto power(bool reset) -> void; + auto estimateTiming() -> u32; + + //hle.cpp + auto mainHLE() -> void; auto addressCRC(u16 address) const -> n5; auto dataCRC(array_view data) const -> n8; - auto run() -> void; - auto scan() -> void; + auto descramble(n4 *buf, int size) -> void; + auto ramReadCommand() -> u8; + auto ramWriteCommand(u8 val) -> void; + auto memSwap(u32 address, n8 &val) -> void; + auto memSwapSecrets() -> void; + auto joyInit() -> void; + auto joyParse() -> void; + auto joyRun() -> void; auto challenge() -> void; - auto power(bool reset) -> void; + auto intA(bool dir, bool size) -> void; //io.cpp + auto readInt(u32 address) -> u32; + auto writeInt(u32 address, u32 data) -> void; auto readWord(u32 address) -> u32; auto writeWord(u32 address, u32 data) -> void; + auto dmaRead(u32 address, u32 ramAddress) -> void; + auto dmaWrite(u32 address, u32 ramAddress) -> void; //serialization.cpp auto serialize(serializer&) -> void; struct IO { n1 romLockout; + n1 resetEnabled; } io; }; diff --git a/waterbox/ares64/ares/ares/n64/pif/serialization.cpp b/waterbox/ares64/ares/ares/n64/pif/serialization.cpp index d10a058372..51ec4ffb13 100644 --- a/waterbox/ares64/ares/ares/n64/pif/serialization.cpp +++ b/waterbox/ares64/ares/ares/n64/pif/serialization.cpp @@ -1,5 +1,16 @@ auto PIF::serialize(serializer& s) -> void { s(ram); - + s(state); + s(intram); s(io.romLockout); + s(io.resetEnabled); +} + +auto PIF::Intram::serialize(serializer& s) -> void { + s(osInfo); + s(cpuChecksum); + s(cicChecksum); + s(bootTimeout); + s(joyAddress); + for(auto i: range(5)) s(joyStatus[i].skip), s(joyStatus[i].reset); } diff --git a/waterbox/ares64/ares/ares/n64/rdp/io.cpp b/waterbox/ares64/ares/ares/n64/rdp/io.cpp index 5e7dd7437d..44c241ed64 100644 --- a/waterbox/ares64/ares/ares/n64/rdp/io.cpp +++ b/waterbox/ares64/ares/ares/n64/rdp/io.cpp @@ -1,4 +1,4 @@ -auto RDP::readWord(u32 address) -> u32 { +auto RDP::readWord(u32 address, u32& cycles) -> u32 { address = (address & 0xfffff) >> 2; n32 data; @@ -56,7 +56,7 @@ auto RDP::readWord(u32 address) -> u32 { return data; } -auto RDP::writeWord(u32 address, u32 data_) -> void { +auto RDP::writeWord(u32 address, u32 data_, u32& cycles) -> void { address = (address & 0xfffff) >> 2; n32 data = data_; @@ -113,7 +113,7 @@ auto RDP::writeWord(u32 address, u32 data_) -> void { debugger.ioDPC(Write, address, data); } -auto RDP::IO::readWord(u32 address) -> u32 { +auto RDP::IO::readWord(u32 address, u32& cycles) -> u32 { address = (address & 0xfffff) >> 2; n32 data; @@ -144,7 +144,7 @@ auto RDP::IO::readWord(u32 address) -> u32 { return data; } -auto RDP::IO::writeWord(u32 address, u32 data_) -> void { +auto RDP::IO::writeWord(u32 address, u32 data_, u32& cycles) -> void { address = (address & 0xfffff) >> 2; n32 data = data_; diff --git a/waterbox/ares64/ares/ares/n64/rdp/rdp.hpp b/waterbox/ares64/ares/ares/n64/rdp/rdp.hpp index 085e58292c..350cc7f3ab 100644 --- a/waterbox/ares64/ares/ares/n64/rdp/rdp.hpp +++ b/waterbox/ares64/ares/ares/n64/rdp/rdp.hpp @@ -1,6 +1,6 @@ //Reality Display Processor -struct RDP : Thread, Memory::IO { +struct RDP : Thread, Memory::RCP { Node::Object node; struct Debugger { @@ -66,8 +66,8 @@ struct RDP : Thread, Memory::IO { auto setColorImage() -> void; //io.cpp - auto readWord(u32 address) -> u32; - auto writeWord(u32 address, u32 data) -> void; + auto readWord(u32 address, u32& cycles) -> u32; + auto writeWord(u32 address, u32 data, u32& cycles) -> void; auto flushCommands() -> void; //serialization.cpp @@ -333,13 +333,13 @@ struct RDP : Thread, Memory::IO { } x, y; } fillRectangle_; - struct IO : Memory::IO { + struct IO : Memory::RCP { RDP& self; IO(RDP& self) : self(self) {} //io.cpp - auto readWord(u32 address) -> u32; - auto writeWord(u32 address, u32 data) -> void; + auto readWord(u32 address, u32& cycles) -> u32; + auto writeWord(u32 address, u32 data, u32& cycles) -> void; struct BIST { n1 check; diff --git a/waterbox/ares64/ares/ares/n64/rdram/io.cpp b/waterbox/ares64/ares/ares/n64/rdram/io.cpp index d5dd561629..3fd6f98e25 100644 --- a/waterbox/ares64/ares/ares/n64/rdram/io.cpp +++ b/waterbox/ares64/ares/ares/n64/rdram/io.cpp @@ -1,4 +1,4 @@ -auto RDRAM::readWord(u32 address) -> u32 { +auto RDRAM::readWord(u32 address, u32& cycles) -> u32 { u32 chipID = address >> 13 & 3; auto& chip = chips[chipID]; address = (address & 0x3ff) >> 2; @@ -63,7 +63,7 @@ auto RDRAM::readWord(u32 address) -> u32 { return data; } -auto RDRAM::writeWord(u32 address, u32 data) -> void { +auto RDRAM::writeWord(u32 address, u32 data, u32& cycles) -> void { u32 chipID = address >> 13 & 3; auto& chip = chips[chipID]; address = (address & 0x3ff) >> 2; diff --git a/waterbox/ares64/ares/ares/n64/rdram/rdram.hpp b/waterbox/ares64/ares/ares/n64/rdram/rdram.hpp index 57cb39ba09..40ee05ece6 100644 --- a/waterbox/ares64/ares/ares/n64/rdram/rdram.hpp +++ b/waterbox/ares64/ares/ares/n64/rdram/rdram.hpp @@ -1,6 +1,6 @@ //RAMBUS RAM -struct RDRAM : Memory::IO { +struct RDRAM : Memory::RCP { Node::Object node; Memory::Writable ram; @@ -24,8 +24,8 @@ struct RDRAM : Memory::IO { auto power(bool reset) -> void; //io.cpp - auto readWord(u32 address) -> u32; - auto writeWord(u32 address, u32 data) -> void; + auto readWord(u32 address, u32& cycles) -> u32; + auto writeWord(u32 address, u32 data, u32& cycles) -> void; //serialization.cpp auto serialize(serializer&) -> void; diff --git a/waterbox/ares64/ares/ares/n64/ri/io.cpp b/waterbox/ares64/ares/ares/n64/ri/io.cpp index 74cb89f8fd..473415b0e6 100644 --- a/waterbox/ares64/ares/ares/n64/ri/io.cpp +++ b/waterbox/ares64/ares/ares/n64/ri/io.cpp @@ -1,4 +1,4 @@ -auto RI::readWord(u32 address) -> u32 { +auto RI::readWord(u32 address, u32& cycles) -> u32 { address = (address & 0xfffff) >> 2; n32 data = 0; @@ -58,7 +58,7 @@ auto RI::readWord(u32 address) -> u32 { return data; } -auto RI::writeWord(u32 address, u32 data_) -> void { +auto RI::writeWord(u32 address, u32 data_, u32& cycles) -> void { address = (address & 0xfffff) >> 2; n32 data = data_; diff --git a/waterbox/ares64/ares/ares/n64/ri/ri.hpp b/waterbox/ares64/ares/ares/n64/ri/ri.hpp index 9c13617d0d..e8bfbd4c4e 100644 --- a/waterbox/ares64/ares/ares/n64/ri/ri.hpp +++ b/waterbox/ares64/ares/ares/n64/ri/ri.hpp @@ -1,6 +1,6 @@ //RDRAM Interface -struct RI : Memory::IO { +struct RI : Memory::RCP { Node::Object node; struct Debugger { @@ -19,8 +19,8 @@ struct RI : Memory::IO { auto power(bool reset) -> void; //io.cpp - auto readWord(u32 address) -> u32; - auto writeWord(u32 address, u32 data) -> void; + auto readWord(u32 address, u32& cycles) -> u32; + auto writeWord(u32 address, u32 data, u32& cycles) -> void; //serialization.cpp auto serialize(serializer&) -> void; diff --git a/waterbox/ares64/ares/ares/n64/rsp/disassembler.cpp b/waterbox/ares64/ares/ares/n64/rsp/disassembler.cpp index 0695e34217..c6b45276c6 100644 --- a/waterbox/ares64/ares/ares/n64/rsp/disassembler.cpp +++ b/waterbox/ares64/ares/ares/n64/rsp/disassembler.cpp @@ -490,10 +490,10 @@ auto RSP::Disassembler::sccRegisterName(u32 index) const -> string { } auto RSP::Disassembler::sccRegisterValue(u32 index) const -> string { - u32 value = 0; - if(index <= 6) value = rsp.readWord((index & 7) << 2); + u32 value = 0; u32 cycles; + if(index <= 6) value = rsp.readWord((index & 7) << 2, cycles); if(index == 7) value = self.status.semaphore; //rsp.readSCC(7) has side-effects - if(index >= 8) value = rdp.readWord((index & 7) << 2); + if(index >= 8) value = rdp.readWord((index & 7) << 2, cycles); if(showValues) return {sccRegisterName(index), hint("{$", hex(value, 8L), "}")}; return sccRegisterName(index); } @@ -525,6 +525,6 @@ auto RSP::Disassembler::ccrRegisterValue(u32 index) const -> string { template auto RSP::Disassembler::hint(P&&... p) const -> string { - if(showColors) return {"\e[0m\e[37m", std::forward

(p)..., "\e[0m"}; + if(showColors) return {terminal::csi, "0m", terminal::csi, "37m", std::forward

(p)..., terminal::csi, "0m"}; return {std::forward

(p)...}; } diff --git a/waterbox/ares64/ares/ares/n64/rsp/interpreter-scc.cpp b/waterbox/ares64/ares/ares/n64/rsp/interpreter-scc.cpp index 5cea79fdfd..8056d3e6fe 100644 --- a/waterbox/ares64/ares/ares/n64/rsp/interpreter-scc.cpp +++ b/waterbox/ares64/ares/ares/n64/rsp/interpreter-scc.cpp @@ -1,9 +1,13 @@ auto RSP::MFC0(r32& rt, u8 rd) -> void { + u32 cycles = 0; if((rd & 8) == 0) rt.u32 = Nintendo64::rsp.ioRead ((rd & 7) << 2); - if((rd & 8) != 0) rt.u32 = Nintendo64::rdp.readWord((rd & 7) << 2); + if((rd & 8) != 0) rt.u32 = Nintendo64::rdp.readWord((rd & 7) << 2, cycles); + step(cycles); } auto RSP::MTC0(cr32& rt, u8 rd) -> void { + u32 cycles = 0; if((rd & 8) == 0) Nintendo64::rsp.ioWrite ((rd & 7) << 2, rt.u32); - if((rd & 8) != 0) Nintendo64::rdp.writeWord((rd & 7) << 2, rt.u32); + if((rd & 8) != 0) Nintendo64::rdp.writeWord((rd & 7) << 2, rt.u32, cycles); + step(cycles); } diff --git a/waterbox/ares64/ares/ares/n64/rsp/interpreter-vpu.cpp b/waterbox/ares64/ares/ares/n64/rsp/interpreter-vpu.cpp index 80a2cdb7cb..24cdf0b2ca 100644 --- a/waterbox/ares64/ares/ares/n64/rsp/interpreter-vpu.cpp +++ b/waterbox/ares64/ares/ares/n64/rsp/interpreter-vpu.cpp @@ -11,6 +11,23 @@ #define DIVOUT vpu.divout #define DIVDP vpu.divdp +static auto countLeadingZeros(u32 value) -> u32 { + assert(value); +#if defined(COMPILER_MICROSOFT) + unsigned long index; + _BitScanReverse(&index, value); + return index ^ 31; +#elif __has_builtin(__builtin_clz) + return __builtin_clz(value); +#else + s32 index; + for(index = 31; index >= 0; --index) { + if(value >> index & 1) break; + } + return 31 - index; +#endif +} + auto RSP::r128::operator()(u32 index) const -> r128 { if constexpr(Accuracy::RSP::SISD) { r128 v{*this}; @@ -60,7 +77,9 @@ auto RSP::r128::operator()(u32 index) const -> r128 { _mm_set_epi8( 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0), //77777777 }; //todo: benchmark to see if testing for cases 0&1 to return value directly is faster - return {uint128_t(_mm_shuffle_epi8(v128, shuffle[index]))}; + r128 v; + v = _mm_shuffle_epi8(v128, shuffle[index]); + return v; #endif } } @@ -132,8 +151,8 @@ auto RSP::CTC2(cr32& rt, u8 rd) -> void { if constexpr(Accuracy::RSP::SIMD) { #if ARCHITECTURE_SUPPORTS_SSE4_1 static const v128 mask = _mm_set_epi16(0x0101, 0x0202, 0x0404, 0x0808, 0x1010, 0x2020, 0x4040, 0x8080); - lo->v128 = _mm_cmpeq_epi8(_mm_and_si128(_mm_shuffle_epi8(r128{~rt.u32 >> 0}, zero), mask), zero); - hi->v128 = _mm_cmpeq_epi8(_mm_and_si128(_mm_shuffle_epi8(r128{~rt.u32 >> 8}, zero), mask), zero); + lo->v128 = _mm_cmpeq_epi8(_mm_and_si128(_mm_set1_epi8(~rt.u32 >> 0), mask), zero); + hi->v128 = _mm_cmpeq_epi8(_mm_and_si128(_mm_set1_epi8(~rt.u32 >> 8), mask), zero); #endif } } @@ -1321,7 +1340,7 @@ auto RSP::VRCP(r128& vd, u8 de, cr128& vt) -> void { } else if(input == -32768) { result = 0xffff'0000; } else { - u32 shift = __builtin_clz(data); + u32 shift = countLeadingZeros(data); u32 index = (u64(data) << shift & 0x7fc0'0000) >> 22; result = reciprocals[index]; result = (0x10000 | result) << 14; @@ -1373,7 +1392,7 @@ auto RSP::VRSQ(r128& vd, u8 de, cr128& vt) -> void { } else if(input == -32768) { result = 0xffff'0000; } else { - u32 shift = __builtin_clz(data); + u32 shift = countLeadingZeros(data); u32 index = (u64(data) << shift & 0x7fc0'0000) >> 22; result = inverseSquareRoots[index & 0x1fe | shift & 1]; result = (0x10000 | result) << 14; diff --git a/waterbox/ares64/ares/ares/n64/rsp/interpreter.cpp b/waterbox/ares64/ares/ares/n64/rsp/interpreter.cpp index e766fb9e36..cb868882e0 100644 --- a/waterbox/ares64/ares/ares/n64/rsp/interpreter.cpp +++ b/waterbox/ares64/ares/ares/n64/rsp/interpreter.cpp @@ -27,7 +27,8 @@ case 0xd: return name<0xd>(__VA_ARGS__); \ case 0xe: return name<0xe>(__VA_ARGS__); \ case 0xf: return name<0xf>(__VA_ARGS__); \ - } + } \ + unreachable; #define SA (OP >> 6 & 31) #define RDn (OP >> 11 & 31) diff --git a/waterbox/ares64/ares/ares/n64/rsp/io.cpp b/waterbox/ares64/ares/ares/n64/rsp/io.cpp index d4c1cd05d5..4b48f9bb78 100644 --- a/waterbox/ares64/ares/ares/n64/rsp/io.cpp +++ b/waterbox/ares64/ares/ares/n64/rsp/io.cpp @@ -1,4 +1,4 @@ -auto RSP::readWord(u32 address) -> u32 { +auto RSP::readWord(u32 address, u32& cycles) -> u32 { if(address <= 0x0403'ffff) { if(address & 0x1000) return imem.read(address); else return dmem.read(address); @@ -67,7 +67,7 @@ auto RSP::ioRead(u32 address) -> u32 { return data; } -auto RSP::writeWord(u32 address, u32 data) -> void { +auto RSP::writeWord(u32 address, u32 data, u32& cycles) -> void { if(address <= 0x0403'ffff) { if(address & 0x1000) return recompiler.invalidate(address & 0xfff), imem.write(address, data); else return dmem.write(address, data); @@ -156,7 +156,7 @@ auto RSP::ioWrite(u32 address, u32 data_) -> void { debugger.ioSCC(Write, address, data); } -auto RSP::Status::readWord(u32 address) -> u32 { +auto RSP::Status::readWord(u32 address, u32& cycles) -> u32 { address = (address & 0x7ffff) >> 2; n32 data; @@ -177,7 +177,7 @@ auto RSP::Status::readWord(u32 address) -> u32 { return data; } -auto RSP::Status::writeWord(u32 address, u32 data_) -> void { +auto RSP::Status::writeWord(u32 address, u32 data_, u32& cycles) -> void { address = (address & 0x7ffff) >> 2; n32 data = data_; diff --git a/waterbox/ares64/ares/ares/n64/rsp/recompiler.cpp b/waterbox/ares64/ares/ares/n64/rsp/recompiler.cpp index 7f867792f8..e10a886f8a 100644 --- a/waterbox/ares64/ares/ares/n64/rsp/recompiler.cpp +++ b/waterbox/ares64/ares/ares/n64/rsp/recompiler.cpp @@ -188,7 +188,7 @@ auto RSP::Recompiler::emitEXECUTE(u32 instruction) -> bool { } //ADDIU Rt,Rs,i16 - case 0x08 ... 0x09: { + case range2(0x08, 0x09): { add32(mem(Rt), mem(Rs), imm(i16)); return 0; } @@ -247,7 +247,7 @@ auto RSP::Recompiler::emitEXECUTE(u32 instruction) -> bool { } //INVALID - case 0x13 ... 0x1f: { + case range13(0x13, 0x1f): { return 0; } @@ -348,7 +348,7 @@ auto RSP::Recompiler::emitEXECUTE(u32 instruction) -> bool { } //INVALID - case 0x2c ... 0x31: { + case range6(0x2c, 0x31): { return 0; } @@ -358,7 +358,7 @@ auto RSP::Recompiler::emitEXECUTE(u32 instruction) -> bool { } //INVALID - case 0x33 ... 0x39: { + case range7(0x33, 0x39): { return 0; } @@ -368,7 +368,7 @@ auto RSP::Recompiler::emitEXECUTE(u32 instruction) -> bool { } //INVALID - case 0x3b ... 0x3f: { + case range5(0x3b, 0x3f): { return 0; } @@ -405,8 +405,7 @@ auto RSP::Recompiler::emitSPECIAL(u32 instruction) -> bool { //SLLV Rd,Rt,Rs case 0x04: { - and32(reg(0), mem(Rs), imm(31)); - shl32(mem(Rd), mem(Rt), reg(0)); + mshl32(mem(Rd), mem(Rt), mem(Rs)); return 0; } @@ -417,15 +416,13 @@ auto RSP::Recompiler::emitSPECIAL(u32 instruction) -> bool { //SRLV Rd,Rt,Rs case 0x06: { - and32(reg(0), mem(Rs), imm(31)); - lshr32(mem(Rd), mem(Rt), reg(0)); + mlshr32(mem(Rd), mem(Rt), mem(Rs)); return 0; } //SRAV Rd,Rt,Rs case 0x07: { - and32(reg(0), mem(Rs), imm(31)); - ashr32(mem(Rd), mem(Rt), reg(0)); + mashr32(mem(Rd), mem(Rt), mem(Rs)); return 0; } @@ -445,7 +442,7 @@ auto RSP::Recompiler::emitSPECIAL(u32 instruction) -> bool { } //INVALID - case 0x0a ... 0x0c: { + case range3(0x0a, 0x0c): { return 0; } @@ -456,18 +453,18 @@ auto RSP::Recompiler::emitSPECIAL(u32 instruction) -> bool { } //INVALID - case 0x0e ... 0x1f: { + case range18(0x0e, 0x1f): { return 0; } //ADDU Rd,Rs,Rt - case 0x20 ... 0x21: { + case range2(0x20, 0x21): { add32(mem(Rd), mem(Rs), mem(Rt)); return 0; } //SUBU Rd,Rs,Rt - case 0x22 ... 0x23: { + case range2(0x22, 0x23): { sub32(mem(Rd), mem(Rs), mem(Rt)); return 0; } @@ -493,13 +490,13 @@ auto RSP::Recompiler::emitSPECIAL(u32 instruction) -> bool { //NOR Rd,Rs,Rt case 0x27: { or32(reg(0), mem(Rs), mem(Rt)); - not32(reg(0), reg(0)); + xor32(reg(0), reg(0), imm(-1)); mov32(mem(Rd), reg(0)); return 0; } //INVALID - case 0x28 ... 0x29: { + case range2(0x28, 0x29): { return 0; } @@ -518,7 +515,7 @@ auto RSP::Recompiler::emitSPECIAL(u32 instruction) -> bool { } //INVALID - case 0x2c ... 0x3f: { + case range20(0x2c, 0x3f): { return 0; } @@ -547,7 +544,7 @@ auto RSP::Recompiler::emitREGIMM(u32 instruction) -> bool { } //INVALID - case 0x02 ... 0x0f: { + case range14(0x02, 0x0f): { return 0; } @@ -568,7 +565,7 @@ auto RSP::Recompiler::emitREGIMM(u32 instruction) -> bool { } //INVALID - case 0x12 ... 0x1f: { + case range14(0x12, 0x1f): { return 0; } @@ -589,7 +586,7 @@ auto RSP::Recompiler::emitSCC(u32 instruction) -> bool { } //INVALID - case 0x01 ... 0x03: { + case range3(0x01, 0x03): { return 0; } @@ -602,7 +599,7 @@ auto RSP::Recompiler::emitSCC(u32 instruction) -> bool { } //INVALID - case 0x05 ... 0x1f: { + case range27(0x05, 0x1f): { return 0; } @@ -663,7 +660,7 @@ auto RSP::Recompiler::emitVU(u32 instruction) -> bool { } //INVALID - case 0x07 ... 0x0f: { + case range9(0x07, 0x0f): { return 0; } @@ -871,7 +868,7 @@ auto RSP::Recompiler::emitVU(u32 instruction) -> bool { } //Broken opcodes: VADDB, VSUBB, VACCB, VSUCB, VSAD, VSAC, VSUM - case 0x16 ... 0x1c: { + case range7(0x16, 0x1c): { lea(reg(1), Vd); lea(reg(2), Vs); lea(reg(3), Vt); @@ -888,7 +885,7 @@ auto RSP::Recompiler::emitVU(u32 instruction) -> bool { } //Invalid opcodes - case 0x1e ... 0x1f: { + case range2(0x1e, 0x1f): { lea(reg(1), Vd); lea(reg(2), Vs); lea(reg(3), Vt); @@ -1023,7 +1020,7 @@ auto RSP::Recompiler::emitVU(u32 instruction) -> bool { } //INVALID - case 0x2e ... 0x2f: { + case range2(0x2e, 0x2f): { lea(reg(1), Vd); lea(reg(2), Vs); lea(reg(3), Vt); @@ -1101,7 +1098,7 @@ auto RSP::Recompiler::emitVU(u32 instruction) -> bool { } //Broken opcodes: VEXTT, VEXTQ, VEXTN - case 0x38 ... 0x3a: { + case range3(0x38, 0x3a): { lea(reg(1), Vd); lea(reg(2), Vs); lea(reg(3), Vt); @@ -1119,7 +1116,7 @@ auto RSP::Recompiler::emitVU(u32 instruction) -> bool { } //Broken opcodes: VINST, VINSQ, VINSN - case 0x3c ... 0x3e: { + case range3(0x3c, 0x3e): { lea(reg(1), Vd); lea(reg(2), Vs); lea(reg(3), Vt); @@ -1250,7 +1247,7 @@ auto RSP::Recompiler::emitLWC2(u32 instruction) -> bool { } //INVALID - case 0x0c ... 0x1f: { + case range20(0x0c, 0x1f): { return 0; } @@ -1375,7 +1372,7 @@ auto RSP::Recompiler::emitSWC2(u32 instruction) -> bool { } //INVALID - case 0x0c ... 0x1f: { + case range20(0x0c, 0x1f): { return 0; } diff --git a/waterbox/ares64/ares/ares/n64/rsp/rsp.cpp b/waterbox/ares64/ares/ares/n64/rsp/rsp.cpp index 48753112c6..76598cf55d 100644 --- a/waterbox/ares64/ares/ares/n64/rsp/rsp.cpp +++ b/waterbox/ares64/ares/ares/n64/rsp/rsp.cpp @@ -86,15 +86,15 @@ auto RSP::power(bool reset) -> void { for(auto& r : ipu.r) r.u32 = 0; ipu.pc = 0; branch = {}; - for(auto& r : vpu.r) r.u128 = 0; - vpu.acch.u128 = 0; - vpu.accm.u128 = 0; - vpu.accl.u128 = 0; - vpu.vcoh.u128 = 0; - vpu.vcol.u128 = 0; - vpu.vcch.u128 = 0; - vpu.vccl.u128 = 0; - vpu.vce.u128 = 0; + for(auto& r : vpu.r) r = zero; + vpu.acch = zero; + vpu.accm = zero; + vpu.accl = zero; + vpu.vcoh = zero; + vpu.vcol = zero; + vpu.vcch = zero; + vpu.vccl = zero; + vpu.vce = zero; vpu.divin = 0; vpu.divout = 0; vpu.divdp = 0; @@ -115,8 +115,8 @@ auto RSP::power(bool reset) -> void { } if constexpr(Accuracy::RSP::Recompiler) { - auto buffer = ares::Memory::FixedAllocator::get().tryAcquire(4_MiB); - recompiler.allocator.resize(4_MiB, bump_allocator::executable | bump_allocator::zero_fill, buffer); + auto buffer = ares::Memory::FixedAllocator::get().tryAcquire(64_MiB); + recompiler.allocator.resize(64_MiB, bump_allocator::executable | bump_allocator::zero_fill, buffer); recompiler.reset(); } diff --git a/waterbox/ares64/ares/ares/n64/rsp/rsp.hpp b/waterbox/ares64/ares/ares/n64/rsp/rsp.hpp index 0e21ee255f..8cda7862a9 100644 --- a/waterbox/ares64/ares/ares/n64/rsp/rsp.hpp +++ b/waterbox/ares64/ares/ares/n64/rsp/rsp.hpp @@ -1,6 +1,6 @@ //Reality Signal Processor -struct RSP : Thread, Memory::IO { +struct RSP : Thread, Memory::RCP { Node::Object node; Memory::Writable dmem; Memory::Writable imem; @@ -47,8 +47,8 @@ struct RSP : Thread, Memory::IO { auto dmaTransferStep() -> void; //io.cpp - auto readWord(u32 address) -> u32; - auto writeWord(u32 address, u32 data) -> void; + auto readWord(u32 address, u32& cycles) -> u32; + auto writeWord(u32 address, u32 data, u32& cycles) -> void; auto ioRead(u32 address) -> u32; auto ioWrite(u32 address, u32 data) -> void; @@ -75,13 +75,13 @@ struct RSP : Thread, Memory::IO { } busy, full; } dma; - struct Status : Memory::IO { + struct Status : Memory::RCP { RSP& self; Status(RSP& self) : self(self) {} //io.cpp - auto readWord(u32 address) -> u32; - auto writeWord(u32 address, u32 data) -> void; + auto readWord(u32 address, u32& cycles) -> u32; + auto writeWord(u32 address, u32 data, u32& cycles) -> void; n1 semaphore; n1 halted = 1; @@ -174,7 +174,7 @@ struct RSP : Thread, Memory::IO { //vpu.cpp: Vector Processing Unit union r128 { - struct { uint128_t u128; }; + struct { u64 order_msb2(hi, lo); } u128; #if ARCHITECTURE_SUPPORTS_SSE4_1 struct { __m128i v128; }; @@ -203,6 +203,9 @@ struct RSP : Thread, Memory::IO { //vu-registers.cpp auto operator()(u32 index) const -> r128; + + //serialization.cpp + auto serialize(serializer&) -> void; }; using cr128 = const r128; @@ -217,8 +220,8 @@ struct RSP : Thread, Memory::IO { bool divdp; } vpu; - static constexpr r128 zero{0}; - static constexpr r128 invert{u128(0) - 1}; + static constexpr r128 zero{0ull, 0ull}; + static constexpr r128 invert{~0ull, ~0ull}; auto accumulatorGet(u32 index) const -> u64; auto accumulatorSet(u32 index, u64 value) -> void; diff --git a/waterbox/ares64/ares/ares/n64/rsp/serialization.cpp b/waterbox/ares64/ares/ares/n64/rsp/serialization.cpp index 8224a1513f..3da6b71fc7 100644 --- a/waterbox/ares64/ares/ares/n64/rsp/serialization.cpp +++ b/waterbox/ares64/ares/ares/n64/rsp/serialization.cpp @@ -27,15 +27,15 @@ auto RSP::serialize(serializer& s) -> void { s(branch.pc); s(branch.state); - for(auto& r : vpu.r) s(r.u128); - s(vpu.acch.u128); - s(vpu.accm.u128); - s(vpu.accl.u128); - s(vpu.vcoh.u128); - s(vpu.vcol.u128); - s(vpu.vcch.u128); - s(vpu.vccl.u128); - s(vpu.vce.u128); + for(auto& r : vpu.r) s(r); + s(vpu.acch); + s(vpu.accm); + s(vpu.accl); + s(vpu.vcoh); + s(vpu.vcol); + s(vpu.vcch); + s(vpu.vccl); + s(vpu.vce); s(vpu.divin); s(vpu.divout); s(vpu.divdp); @@ -53,3 +53,8 @@ auto RSP::DMA::Regs::serialize(serializer& s) -> void { s(skip); s(count); } + +auto RSP::r128::serialize(serializer& s) -> void { + s(u128.lo); + s(u128.hi); +} diff --git a/waterbox/ares64/ares/ares/n64/si/dma.cpp b/waterbox/ares64/ares/ares/n64/si/dma.cpp index 142adf176c..35f13aeb2a 100644 --- a/waterbox/ares64/ares/ares/n64/si/dma.cpp +++ b/waterbox/ares64/ares/ares/n64/si/dma.cpp @@ -1,21 +1,13 @@ auto SI::dmaRead() -> void { - pif.run(); - for(u32 offset = 0; offset < 64; offset += 4) { - u32 data = pif.readWord(io.readAddress + offset); - rdram.ram.write(io.dramAddress + offset, data); - } + pif.dmaRead(io.readAddress, io.dramAddress); io.dmaBusy = 0; io.interrupt = 1; mi.raise(MI::IRQ::SI); } auto SI::dmaWrite() -> void { - for(u32 offset = 0; offset < 64; offset += 4) { - u32 data = rdram.ram.read(io.dramAddress + offset); - pif.writeWord(io.writeAddress + offset, data); - } + pif.dmaWrite(io.writeAddress, io.dramAddress); io.dmaBusy = 0; io.interrupt = 1; mi.raise(MI::IRQ::SI); - pif.run(); } diff --git a/waterbox/ares64/ares/ares/n64/si/io.cpp b/waterbox/ares64/ares/ares/n64/si/io.cpp index 30174e8971..4079edad18 100644 --- a/waterbox/ares64/ares/ares/n64/si/io.cpp +++ b/waterbox/ares64/ares/ares/n64/si/io.cpp @@ -1,4 +1,14 @@ -auto SI::readWord(u32 address) -> u32 { +auto SI::readWord(u32 address, u32& cycles) -> u32 { + if(address <= 0x048f'ffff) return ioRead(address); + + if (unlikely(io.ioBusy)) { + writeForceFinish(); //technically, we should wait until Queue::SI_BUS_Write + return io.busLatch; + } + return pif.read(address); +} + +auto SI::ioRead(u32 address) -> u32 { address = (address & 0xfffff) >> 2; n32 data; @@ -44,7 +54,17 @@ auto SI::readWord(u32 address) -> u32 { return data; } -auto SI::writeWord(u32 address, u32 data_) -> void { +auto SI::writeWord(u32 address, u32 data, u32& cycles) -> void { + if(address <= 0x048f'ffff) return ioWrite(address, data); + + if(io.ioBusy) return; + io.ioBusy = 1; + io.busLatch = data; + queue.insert(Queue::SI_BUS_Write, 2150*3); + return pif.write(address, data); +} + +auto SI::ioWrite(u32 address, u32 data_) -> void { address = (address & 0xfffff) >> 2; n32 data = data_; @@ -57,7 +77,8 @@ auto SI::writeWord(u32 address, u32 data_) -> void { //SI_PIF_ADDRESS_READ64B io.readAddress = data.bit(0,31) & ~1; io.dmaBusy = 1; - queue.insert(Queue::SI_DMA_Read, 2304); + int cycles = pif.estimateTiming(); + queue.insert(Queue::SI_DMA_Read, cycles*3); } if(address == 2) { @@ -72,7 +93,7 @@ auto SI::writeWord(u32 address, u32 data_) -> void { //SI_PIF_ADDRESS_WRITE64B io.writeAddress = data.bit(0,31) & ~1; io.dmaBusy = 1; - queue.insert(Queue::SI_DMA_Write, 2304); + queue.insert(Queue::SI_DMA_Write, 4065*3); } if(address == 5) { @@ -87,3 +108,12 @@ auto SI::writeWord(u32 address, u32 data_) -> void { debugger.io(Write, address, data); } + +auto SI::writeFinished() -> void { + io.ioBusy = 0; +} + +auto SI::writeForceFinish() -> void { + io.ioBusy = 0; + queue.remove(Queue::SI_BUS_Write); +} diff --git a/waterbox/ares64/ares/ares/n64/si/serialization.cpp b/waterbox/ares64/ares/ares/n64/si/serialization.cpp index e692fece3d..531c92eb31 100644 --- a/waterbox/ares64/ares/ares/n64/si/serialization.cpp +++ b/waterbox/ares64/ares/ares/n64/si/serialization.cpp @@ -2,6 +2,7 @@ auto SI::serialize(serializer& s) -> void { s(io.dramAddress); s(io.readAddress); s(io.writeAddress); + s(io.busLatch); s(io.dmaBusy); s(io.ioBusy); s(io.readPending); diff --git a/waterbox/ares64/ares/ares/n64/si/si.cpp b/waterbox/ares64/ares/ares/n64/si/si.cpp index 01a3722787..0b02d855e9 100644 --- a/waterbox/ares64/ares/ares/n64/si/si.cpp +++ b/waterbox/ares64/ares/ares/n64/si/si.cpp @@ -11,14 +11,6 @@ SI si; auto SI::load(Node::Object parent) -> void { node = parent->append("SI"); debugger.load(node); - -/*if(auto fp = system.pak->read("pif.sm5.rom")) { - //load 1KB ROM and mirror it to 4KB - fp->read({SM5K::ROM, 1024}); - memory::copy(&SM5K::ROM[1024], &SM5K::ROM[0], 1024); - memory::copy(&SM5K::ROM[2048], &SM5K::ROM[0], 1024); - memory::copy(&SM5K::ROM[3072], &SM5K::ROM[0], 1024); - }*/ } auto SI::unload() -> void { diff --git a/waterbox/ares64/ares/ares/n64/si/si.hpp b/waterbox/ares64/ares/ares/n64/si/si.hpp index af4c28c532..de88dc404f 100644 --- a/waterbox/ares64/ares/ares/n64/si/si.hpp +++ b/waterbox/ares64/ares/ares/n64/si/si.hpp @@ -1,6 +1,6 @@ //Serial Interface -struct SI : Memory::IO { +struct SI : Memory::RCP { Node::Object node; struct Debugger { @@ -23,8 +23,12 @@ struct SI : Memory::IO { auto dmaWrite() -> void; //io.cpp - auto readWord(u32 address) -> u32; - auto writeWord(u32 address, u32 data) -> void; + auto ioRead(u32 address) -> u32; + auto ioWrite(u32 address, u32 data) -> void; + auto readWord(u32 address, u32& cycles) -> u32; + auto writeWord(u32 address, u32 data, u32& cycles) -> void; + auto writeFinished() -> void; + auto writeForceFinish() -> void; //serialization.cpp auto serialize(serializer&) -> void; @@ -33,6 +37,7 @@ struct SI : Memory::IO { n24 dramAddress; n32 readAddress; n32 writeAddress; + u32 busLatch; n1 dmaBusy; n1 ioBusy; n1 readPending; diff --git a/waterbox/ares64/ares/ares/n64/system/serialization.cpp b/waterbox/ares64/ares/ares/n64/system/serialization.cpp index 3965d18b5d..b199fca5a2 100644 --- a/waterbox/ares64/ares/ares/n64/system/serialization.cpp +++ b/waterbox/ares64/ares/ares/n64/system/serialization.cpp @@ -1,3 +1,5 @@ +static const string SerializerVersion = "v131"; + auto System::serialize(bool synchronize) -> serializer { serializer s; @@ -47,6 +49,7 @@ auto System::serialize(serializer& s, bool synchronize) -> void { s(ai); s(pi); s(pif); + s(cic); s(ri); s(si); s(cpu); diff --git a/waterbox/ares64/ares/ares/n64/system/system.cpp b/waterbox/ares64/ares/ares/n64/system/system.cpp index 1b24a5930c..bf249cc733 100644 --- a/waterbox/ares64/ares/ares/n64/system/system.cpp +++ b/waterbox/ares64/ares/ares/n64/system/system.cpp @@ -40,7 +40,6 @@ auto System::game() -> string { auto System::run() -> void { while(!vi.refreshed) cpu.main(); vi.refreshed = false; - if (!pif.io.romLockout) pif.run(); } auto System::load(Node::System& root, string name) -> bool { @@ -120,7 +119,7 @@ auto System::unload() -> void { } auto System::save() -> void { -/* +#if false if(!node) return; cartridge.save(); controllerPort1.save(); @@ -128,7 +127,7 @@ auto System::save() -> void { controllerPort3.save(); controllerPort4.save(); if(_DD()) dd.save(); -*/ +#endif } auto System::power(bool reset) -> void { @@ -146,6 +145,7 @@ auto System::power(bool reset) -> void { ai.power(reset); pi.power(reset); pif.power(reset); + cic.power(reset); ri.power(reset); si.power(reset); cpu.power(reset); diff --git a/waterbox/ares64/ares/ares/n64/vi/io.cpp b/waterbox/ares64/ares/ares/n64/vi/io.cpp index 3b84814051..3c875743d0 100644 --- a/waterbox/ares64/ares/ares/n64/vi/io.cpp +++ b/waterbox/ares64/ares/ares/n64/vi/io.cpp @@ -1,4 +1,4 @@ -auto VI::readWord(u32 address) -> u32 { +auto VI::readWord(u32 address, u32& cycles) -> u32 { address = (address & 0xfffff) >> 2; n32 data; @@ -96,7 +96,7 @@ auto VI::readWord(u32 address) -> u32 { return data; } -auto VI::writeWord(u32 address, u32 data_) -> void { +auto VI::writeWord(u32 address, u32 data_, u32& cycles) -> void { address = (address & 0xfffff) >> 2; n32 data = data_; diff --git a/waterbox/ares64/ares/ares/n64/vi/vi.hpp b/waterbox/ares64/ares/ares/n64/vi/vi.hpp index 2314f3cb6a..672e3967f9 100644 --- a/waterbox/ares64/ares/ares/n64/vi/vi.hpp +++ b/waterbox/ares64/ares/ares/n64/vi/vi.hpp @@ -1,6 +1,6 @@ //Video Interface -struct VI : Thread, Memory::IO { +struct VI : Thread, Memory::RCP { Node::Object node; Node::Video::Screen screen; @@ -24,8 +24,8 @@ struct VI : Thread, Memory::IO { auto power(bool reset) -> void; //io.cpp - auto readWord(u32 address) -> u32; - auto writeWord(u32 address, u32 data) -> void; + auto readWord(u32 address, u32& cycles) -> u32; + auto writeWord(u32 address, u32 data, u32& cycles) -> void; //serialization.cpp auto serialize(serializer&) -> void; diff --git a/waterbox/ares64/ares/nall/arguments.hpp b/waterbox/ares64/ares/nall/arguments.hpp index 7ecb536bff..1bf7043794 100644 --- a/waterbox/ares64/ares/nall/arguments.hpp +++ b/waterbox/ares64/ares/nall/arguments.hpp @@ -1,8 +1,10 @@ #pragma once +#include +#include +#include #include #include -#include #include namespace nall { diff --git a/waterbox/ares64/ares/nall/bcd.hpp b/waterbox/ares64/ares/nall/bcd.hpp new file mode 100644 index 0000000000..5d9a92a724 --- /dev/null +++ b/waterbox/ares64/ares/nall/bcd.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include + +namespace nall { + +struct BCD { + static auto encode(u8 value) -> u8 { return value / 10 << 4 | value % 10; } + static auto decode(u8 value) -> u8 { return (value >> 4) * 10 + (value & 15); } +}; + +} diff --git a/waterbox/ares64/ares/nall/case-range.hpp b/waterbox/ares64/ares/nall/case-range.hpp new file mode 100644 index 0000000000..6f345614f4 --- /dev/null +++ b/waterbox/ares64/ares/nall/case-range.hpp @@ -0,0 +1,279 @@ +#pragma once + +//GNU case range extension simulated with preprocessor macros +// +// usage expands to +// ------------------ ----------------------------------- +// caseN(X): => case X: +// case X + 1: +// ... +// case X + N - 1: +// +// case rangeN(X, Y): => case X: +// static_assert(Y - X + 1 == N); +// case X + 1: +// ... +// case Y: +// +//the range macro more closely resembles the GNU extension syntax at the cost of +//redundancy. it embeds a static assert between the first two case labels to +//ensure consistency between the chosen macro and the provided macro arguments. + +#define check_case_range(x, y, n) static_assert((y) - (x) + 1 == n, "range does not contain " #n " elements"); [[fallthrough]]; + +#define case1(x) case (x) +#define case2(x) case1(x): case1((x) + 1) +#define case3(x) case1(x): case2((x) + 1) +#define case4(x) case2(x): case2((x) + 2) +#define case5(x) case2(x): case3((x) + 2) +#define case6(x) case3(x): case3((x) + 3) +#define case7(x) case3(x): case4((x) + 3) +#define case8(x) case4(x): case4((x) + 4) +#define case9(x) case4(x): case5((x) + 4) +#define case10(x) case5(x): case5((x) + 5) +#define case11(x) case5(x): case6((x) + 5) +#define case12(x) case6(x): case6((x) + 6) +#define case13(x) case6(x): case7((x) + 6) +#define case14(x) case7(x): case7((x) + 7) +#define case15(x) case7(x): case8((x) + 7) +#define case16(x) case8(x): case8((x) + 8) +#define case17(x) case8(x): case9((x) + 8) +#define case18(x) case9(x): case9((x) + 9) +#define case19(x) case9(x): case10((x) + 9) +#define case20(x) case10(x): case10((x) + 10) +#define case21(x) case10(x): case11((x) + 10) +#define case22(x) case11(x): case11((x) + 11) +#define case23(x) case11(x): case12((x) + 11) +#define case24(x) case12(x): case12((x) + 12) +#define case25(x) case12(x): case13((x) + 12) +#define case26(x) case13(x): case13((x) + 13) +#define case27(x) case13(x): case14((x) + 13) +#define case28(x) case14(x): case14((x) + 14) +#define case29(x) case14(x): case15((x) + 14) +#define case30(x) case15(x): case15((x) + 15) +#define case31(x) case15(x): case16((x) + 15) +#define case32(x) case16(x): case16((x) + 16) +#define case33(x) case16(x): case17((x) + 16) +#define case34(x) case17(x): case17((x) + 17) +#define case35(x) case17(x): case18((x) + 17) +#define case36(x) case18(x): case18((x) + 18) +#define case37(x) case18(x): case19((x) + 18) +#define case38(x) case19(x): case19((x) + 19) +#define case39(x) case19(x): case20((x) + 19) +#define case40(x) case20(x): case20((x) + 20) +#define case41(x) case20(x): case21((x) + 20) +#define case42(x) case21(x): case21((x) + 21) +#define case43(x) case21(x): case22((x) + 21) +#define case44(x) case22(x): case22((x) + 22) +#define case45(x) case22(x): case23((x) + 22) +#define case46(x) case23(x): case23((x) + 23) +#define case47(x) case23(x): case24((x) + 23) +#define case48(x) case24(x): case24((x) + 24) +#define case49(x) case24(x): case25((x) + 24) +#define case50(x) case25(x): case25((x) + 25) +#define case51(x) case25(x): case26((x) + 25) +#define case52(x) case26(x): case26((x) + 26) +#define case53(x) case26(x): case27((x) + 26) +#define case54(x) case27(x): case27((x) + 27) +#define case55(x) case27(x): case28((x) + 27) +#define case56(x) case28(x): case28((x) + 28) +#define case57(x) case28(x): case29((x) + 28) +#define case58(x) case29(x): case29((x) + 29) +#define case59(x) case29(x): case30((x) + 29) +#define case60(x) case30(x): case30((x) + 30) +#define case61(x) case30(x): case31((x) + 30) +#define case62(x) case31(x): case31((x) + 31) +#define case63(x) case31(x): case32((x) + 31) +#define case64(x) case32(x): case32((x) + 32) +#define case65(x) case32(x): case33((x) + 32) +#define case66(x) case33(x): case33((x) + 33) +#define case67(x) case33(x): case34((x) + 33) +#define case68(x) case34(x): case34((x) + 34) +#define case69(x) case34(x): case35((x) + 34) +#define case70(x) case35(x): case35((x) + 35) +#define case71(x) case35(x): case36((x) + 35) +#define case72(x) case36(x): case36((x) + 36) +#define case73(x) case36(x): case37((x) + 36) +#define case74(x) case37(x): case37((x) + 37) +#define case75(x) case37(x): case38((x) + 37) +#define case76(x) case38(x): case38((x) + 38) +#define case77(x) case38(x): case39((x) + 38) +#define case78(x) case39(x): case39((x) + 39) +#define case79(x) case39(x): case40((x) + 39) +#define case80(x) case40(x): case40((x) + 40) +#define case81(x) case40(x): case41((x) + 40) +#define case82(x) case41(x): case41((x) + 41) +#define case83(x) case41(x): case42((x) + 41) +#define case84(x) case42(x): case42((x) + 42) +#define case85(x) case42(x): case43((x) + 42) +#define case86(x) case43(x): case43((x) + 43) +#define case87(x) case43(x): case44((x) + 43) +#define case88(x) case44(x): case44((x) + 44) +#define case89(x) case44(x): case45((x) + 44) +#define case90(x) case45(x): case45((x) + 45) +#define case91(x) case45(x): case46((x) + 45) +#define case92(x) case46(x): case46((x) + 46) +#define case93(x) case46(x): case47((x) + 46) +#define case94(x) case47(x): case47((x) + 47) +#define case95(x) case47(x): case48((x) + 47) +#define case96(x) case48(x): case48((x) + 48) +#define case97(x) case48(x): case49((x) + 48) +#define case98(x) case49(x): case49((x) + 49) +#define case99(x) case49(x): case50((x) + 49) +#define case100(x) case50(x): case50((x) + 50) +#define case101(x) case50(x): case51((x) + 50) +#define case102(x) case51(x): case51((x) + 51) +#define case103(x) case51(x): case52((x) + 51) +#define case104(x) case52(x): case52((x) + 52) +#define case105(x) case52(x): case53((x) + 52) +#define case106(x) case53(x): case53((x) + 53) +#define case107(x) case53(x): case54((x) + 53) +#define case108(x) case54(x): case54((x) + 54) +#define case109(x) case54(x): case55((x) + 54) +#define case110(x) case55(x): case55((x) + 55) +#define case111(x) case55(x): case56((x) + 55) +#define case112(x) case56(x): case56((x) + 56) +#define case113(x) case56(x): case57((x) + 56) +#define case114(x) case57(x): case57((x) + 57) +#define case115(x) case57(x): case58((x) + 57) +#define case116(x) case58(x): case58((x) + 58) +#define case117(x) case58(x): case59((x) + 58) +#define case118(x) case59(x): case59((x) + 59) +#define case119(x) case59(x): case60((x) + 59) +#define case120(x) case60(x): case60((x) + 60) +#define case121(x) case60(x): case61((x) + 60) +#define case122(x) case61(x): case61((x) + 61) +#define case123(x) case61(x): case62((x) + 61) +#define case124(x) case62(x): case62((x) + 62) +#define case125(x) case62(x): case63((x) + 62) +#define case126(x) case63(x): case63((x) + 63) +#define case127(x) case63(x): case64((x) + 63) +#define case128(x) case64(x): case64((x) + 64) + +#define range2(x, y) (x): check_case_range(x, y, 2) case1((x) + 1) +#define range3(x, y) (x): check_case_range(x, y, 3) case2((x) + 1) +#define range4(x, y) (x): check_case_range(x, y, 4) case3((x) + 1) +#define range5(x, y) (x): check_case_range(x, y, 5) case4((x) + 1) +#define range6(x, y) (x): check_case_range(x, y, 6) case5((x) + 1) +#define range7(x, y) (x): check_case_range(x, y, 7) case6((x) + 1) +#define range8(x, y) (x): check_case_range(x, y, 8) case7((x) + 1) +#define range9(x, y) (x): check_case_range(x, y, 9) case8((x) + 1) +#define range10(x, y) (x): check_case_range(x, y, 10) case9((x) + 1) +#define range11(x, y) (x): check_case_range(x, y, 11) case10((x) + 1) +#define range12(x, y) (x): check_case_range(x, y, 12) case11((x) + 1) +#define range13(x, y) (x): check_case_range(x, y, 13) case12((x) + 1) +#define range14(x, y) (x): check_case_range(x, y, 14) case13((x) + 1) +#define range15(x, y) (x): check_case_range(x, y, 15) case14((x) + 1) +#define range16(x, y) (x): check_case_range(x, y, 16) case15((x) + 1) +#define range17(x, y) (x): check_case_range(x, y, 17) case16((x) + 1) +#define range18(x, y) (x): check_case_range(x, y, 18) case17((x) + 1) +#define range19(x, y) (x): check_case_range(x, y, 19) case18((x) + 1) +#define range20(x, y) (x): check_case_range(x, y, 20) case19((x) + 1) +#define range21(x, y) (x): check_case_range(x, y, 21) case20((x) + 1) +#define range22(x, y) (x): check_case_range(x, y, 22) case21((x) + 1) +#define range23(x, y) (x): check_case_range(x, y, 23) case22((x) + 1) +#define range24(x, y) (x): check_case_range(x, y, 24) case23((x) + 1) +#define range25(x, y) (x): check_case_range(x, y, 25) case24((x) + 1) +#define range26(x, y) (x): check_case_range(x, y, 26) case25((x) + 1) +#define range27(x, y) (x): check_case_range(x, y, 27) case26((x) + 1) +#define range28(x, y) (x): check_case_range(x, y, 28) case27((x) + 1) +#define range29(x, y) (x): check_case_range(x, y, 29) case28((x) + 1) +#define range30(x, y) (x): check_case_range(x, y, 30) case29((x) + 1) +#define range31(x, y) (x): check_case_range(x, y, 31) case30((x) + 1) +#define range32(x, y) (x): check_case_range(x, y, 32) case31((x) + 1) +#define range33(x, y) (x): check_case_range(x, y, 33) case32((x) + 1) +#define range34(x, y) (x): check_case_range(x, y, 34) case33((x) + 1) +#define range35(x, y) (x): check_case_range(x, y, 35) case34((x) + 1) +#define range36(x, y) (x): check_case_range(x, y, 36) case35((x) + 1) +#define range37(x, y) (x): check_case_range(x, y, 37) case36((x) + 1) +#define range38(x, y) (x): check_case_range(x, y, 38) case37((x) + 1) +#define range39(x, y) (x): check_case_range(x, y, 39) case38((x) + 1) +#define range40(x, y) (x): check_case_range(x, y, 40) case39((x) + 1) +#define range41(x, y) (x): check_case_range(x, y, 41) case40((x) + 1) +#define range42(x, y) (x): check_case_range(x, y, 42) case41((x) + 1) +#define range43(x, y) (x): check_case_range(x, y, 43) case42((x) + 1) +#define range44(x, y) (x): check_case_range(x, y, 44) case43((x) + 1) +#define range45(x, y) (x): check_case_range(x, y, 45) case44((x) + 1) +#define range46(x, y) (x): check_case_range(x, y, 46) case45((x) + 1) +#define range47(x, y) (x): check_case_range(x, y, 47) case46((x) + 1) +#define range48(x, y) (x): check_case_range(x, y, 48) case47((x) + 1) +#define range49(x, y) (x): check_case_range(x, y, 49) case48((x) + 1) +#define range50(x, y) (x): check_case_range(x, y, 50) case49((x) + 1) +#define range51(x, y) (x): check_case_range(x, y, 51) case50((x) + 1) +#define range52(x, y) (x): check_case_range(x, y, 52) case51((x) + 1) +#define range53(x, y) (x): check_case_range(x, y, 53) case52((x) + 1) +#define range54(x, y) (x): check_case_range(x, y, 54) case53((x) + 1) +#define range55(x, y) (x): check_case_range(x, y, 55) case54((x) + 1) +#define range56(x, y) (x): check_case_range(x, y, 56) case55((x) + 1) +#define range57(x, y) (x): check_case_range(x, y, 57) case56((x) + 1) +#define range58(x, y) (x): check_case_range(x, y, 58) case57((x) + 1) +#define range59(x, y) (x): check_case_range(x, y, 59) case58((x) + 1) +#define range60(x, y) (x): check_case_range(x, y, 60) case59((x) + 1) +#define range61(x, y) (x): check_case_range(x, y, 61) case60((x) + 1) +#define range62(x, y) (x): check_case_range(x, y, 62) case61((x) + 1) +#define range63(x, y) (x): check_case_range(x, y, 63) case62((x) + 1) +#define range64(x, y) (x): check_case_range(x, y, 64) case63((x) + 1) +#define range65(x, y) (x): check_case_range(x, y, 65) case64((x) + 1) +#define range66(x, y) (x): check_case_range(x, y, 66) case65((x) + 1) +#define range67(x, y) (x): check_case_range(x, y, 67) case66((x) + 1) +#define range68(x, y) (x): check_case_range(x, y, 68) case67((x) + 1) +#define range69(x, y) (x): check_case_range(x, y, 69) case68((x) + 1) +#define range70(x, y) (x): check_case_range(x, y, 70) case69((x) + 1) +#define range71(x, y) (x): check_case_range(x, y, 71) case70((x) + 1) +#define range72(x, y) (x): check_case_range(x, y, 72) case71((x) + 1) +#define range73(x, y) (x): check_case_range(x, y, 73) case72((x) + 1) +#define range74(x, y) (x): check_case_range(x, y, 74) case73((x) + 1) +#define range75(x, y) (x): check_case_range(x, y, 75) case74((x) + 1) +#define range76(x, y) (x): check_case_range(x, y, 76) case75((x) + 1) +#define range77(x, y) (x): check_case_range(x, y, 77) case76((x) + 1) +#define range78(x, y) (x): check_case_range(x, y, 78) case77((x) + 1) +#define range79(x, y) (x): check_case_range(x, y, 79) case78((x) + 1) +#define range80(x, y) (x): check_case_range(x, y, 80) case79((x) + 1) +#define range81(x, y) (x): check_case_range(x, y, 81) case80((x) + 1) +#define range82(x, y) (x): check_case_range(x, y, 82) case81((x) + 1) +#define range83(x, y) (x): check_case_range(x, y, 83) case82((x) + 1) +#define range84(x, y) (x): check_case_range(x, y, 84) case83((x) + 1) +#define range85(x, y) (x): check_case_range(x, y, 85) case84((x) + 1) +#define range86(x, y) (x): check_case_range(x, y, 86) case85((x) + 1) +#define range87(x, y) (x): check_case_range(x, y, 87) case86((x) + 1) +#define range88(x, y) (x): check_case_range(x, y, 88) case87((x) + 1) +#define range89(x, y) (x): check_case_range(x, y, 89) case88((x) + 1) +#define range90(x, y) (x): check_case_range(x, y, 90) case89((x) + 1) +#define range91(x, y) (x): check_case_range(x, y, 91) case90((x) + 1) +#define range92(x, y) (x): check_case_range(x, y, 92) case91((x) + 1) +#define range93(x, y) (x): check_case_range(x, y, 93) case92((x) + 1) +#define range94(x, y) (x): check_case_range(x, y, 94) case93((x) + 1) +#define range95(x, y) (x): check_case_range(x, y, 95) case94((x) + 1) +#define range96(x, y) (x): check_case_range(x, y, 96) case95((x) + 1) +#define range97(x, y) (x): check_case_range(x, y, 97) case96((x) + 1) +#define range98(x, y) (x): check_case_range(x, y, 98) case97((x) + 1) +#define range99(x, y) (x): check_case_range(x, y, 99) case98((x) + 1) +#define range100(x, y) (x): check_case_range(x, y, 100) case99((x) + 1) +#define range101(x, y) (x): check_case_range(x, y, 101) case100((x) + 1) +#define range102(x, y) (x): check_case_range(x, y, 102) case101((x) + 1) +#define range103(x, y) (x): check_case_range(x, y, 103) case102((x) + 1) +#define range104(x, y) (x): check_case_range(x, y, 104) case103((x) + 1) +#define range105(x, y) (x): check_case_range(x, y, 105) case104((x) + 1) +#define range106(x, y) (x): check_case_range(x, y, 106) case105((x) + 1) +#define range107(x, y) (x): check_case_range(x, y, 107) case106((x) + 1) +#define range108(x, y) (x): check_case_range(x, y, 108) case107((x) + 1) +#define range109(x, y) (x): check_case_range(x, y, 109) case108((x) + 1) +#define range110(x, y) (x): check_case_range(x, y, 110) case109((x) + 1) +#define range111(x, y) (x): check_case_range(x, y, 111) case110((x) + 1) +#define range112(x, y) (x): check_case_range(x, y, 112) case111((x) + 1) +#define range113(x, y) (x): check_case_range(x, y, 113) case112((x) + 1) +#define range114(x, y) (x): check_case_range(x, y, 114) case113((x) + 1) +#define range115(x, y) (x): check_case_range(x, y, 115) case114((x) + 1) +#define range116(x, y) (x): check_case_range(x, y, 116) case115((x) + 1) +#define range117(x, y) (x): check_case_range(x, y, 117) case116((x) + 1) +#define range118(x, y) (x): check_case_range(x, y, 118) case117((x) + 1) +#define range119(x, y) (x): check_case_range(x, y, 119) case118((x) + 1) +#define range120(x, y) (x): check_case_range(x, y, 120) case119((x) + 1) +#define range121(x, y) (x): check_case_range(x, y, 121) case120((x) + 1) +#define range122(x, y) (x): check_case_range(x, y, 122) case121((x) + 1) +#define range123(x, y) (x): check_case_range(x, y, 123) case122((x) + 1) +#define range124(x, y) (x): check_case_range(x, y, 124) case123((x) + 1) +#define range125(x, y) (x): check_case_range(x, y, 125) case124((x) + 1) +#define range126(x, y) (x): check_case_range(x, y, 126) case125((x) + 1) +#define range127(x, y) (x): check_case_range(x, y, 127) case126((x) + 1) +#define range128(x, y) (x): check_case_range(x, y, 128) case127((x) + 1) diff --git a/waterbox/ares64/ares/nall/cd.hpp b/waterbox/ares64/ares/nall/cd.hpp index 9fca9abab7..55acbeec61 100644 --- a/waterbox/ares64/ares/nall/cd.hpp +++ b/waterbox/ares64/ares/nall/cd.hpp @@ -22,6 +22,7 @@ #include #include +#include #include #include #include diff --git a/waterbox/ares64/ares/nall/cd/session.hpp b/waterbox/ares64/ares/nall/cd/session.hpp index 26d359591c..f8b826c5e1 100644 --- a/waterbox/ares64/ares/nall/cd/session.hpp +++ b/waterbox/ares64/ares/nall/cd/session.hpp @@ -7,11 +7,6 @@ namespace nall::CD { enum : s32 { InvalidLBA = 100 * 60 * 75 }; -struct BCD { - static auto encode(u8 value) -> u8 { return value / 10 << 4 | value % 10; } - static auto decode(u8 value) -> u8 { return (value >> 4) * 10 + (value & 15); } -}; - struct MSF { u8 minute; //00-99 u8 second; //00-59 diff --git a/waterbox/ares64/ares/nall/chrono.hpp b/waterbox/ares64/ares/nall/chrono.hpp index 08b9e3e86a..dec25cbd8d 100644 --- a/waterbox/ares64/ares/nall/chrono.hpp +++ b/waterbox/ares64/ares/nall/chrono.hpp @@ -3,14 +3,15 @@ #include #include +#include + namespace nall::chrono { //passage of time functions (from unknown epoch) inline auto nanosecond() -> u64 { - timespec tv; - clock_gettime(CLOCK_MONOTONIC, &tv); - return tv.tv_sec * 1'000'000'000 + tv.tv_nsec; + auto now = std::chrono::steady_clock::now().time_since_epoch(); + return std::chrono::duration_cast(now).count(); } inline auto microsecond() -> u64 { return nanosecond() / 1'000; } diff --git a/waterbox/ares64/ares/nall/cipher/chacha20.hpp b/waterbox/ares64/ares/nall/cipher/chacha20.hpp index 4d0088056a..eec1042d59 100644 --- a/waterbox/ares64/ares/nall/cipher/chacha20.hpp +++ b/waterbox/ares64/ares/nall/cipher/chacha20.hpp @@ -102,7 +102,7 @@ struct HChaCha20 : protected ChaCha20 { //192-bit nonce; 64-bit x 64-byte (256GB) counter struct XChaCha20 : ChaCha20 { XChaCha20(u256 key, u192 nonce, u64 counter = 0): - ChaCha20(HChaCha20(key, nonce).key(), nonce >> 128, counter) { + ChaCha20(HChaCha20(key, u128(nonce)).key(), nonce >> 128, counter) { } }; diff --git a/waterbox/ares64/ares/nall/database/sqlite3.hpp b/waterbox/ares64/ares/nall/database/sqlite3.hpp index 8a8322c487..abc2af6468 100644 --- a/waterbox/ares64/ares/nall/database/sqlite3.hpp +++ b/waterbox/ares64/ares/nall/database/sqlite3.hpp @@ -116,9 +116,9 @@ struct SQLite3 { auto& bind(u32 column, u64 value) { sqlite3_bind_int64(_statement, 1 + column, value); return *this; } auto& bind(u32 column, intmax value) { sqlite3_bind_int64(_statement, 1 + column, value); return *this; } auto& bind(u32 column, uintmax value) { sqlite3_bind_int64(_statement, 1 + column, value); return *this; } - auto& bind(u32 column, nall::boolean value) { sqlite3_bind_int64(_statement, 1 + column, value); return *this; } - auto& bind(u32 column, nall::integer value) { sqlite3_bind_int64(_statement, 1 + column, value); return *this; } - auto& bind(u32 column, nall::natural value) { sqlite3_bind_int64(_statement, 1 + column, value); return *this; } + auto& bind(u32 column, nall::Boolean value) { sqlite3_bind_int64(_statement, 1 + column, value); return *this; } + auto& bind(u32 column, nall::Integer value) { sqlite3_bind_int64(_statement, 1 + column, value); return *this; } + auto& bind(u32 column, nall::Natural value) { sqlite3_bind_int64(_statement, 1 + column, value); return *this; } auto& bind(u32 column, f64 value) { sqlite3_bind_double(_statement, 1 + column, value); return *this; } auto& bind(u32 column, const nall::string& value) { sqlite3_bind_text(_statement, 1 + column, value.data(), value.size(), SQLITE_TRANSIENT); return *this; } auto& bind(u32 column, const vector& value) { sqlite3_bind_blob(_statement, 1 + column, value.data(), value.size(), SQLITE_TRANSIENT); return *this; } @@ -131,9 +131,9 @@ struct SQLite3 { auto& bind(u64 value) { return bind(_input++, value); } auto& bind(intmax value) { return bind(_input++, value); } auto& bind(uintmax value) { return bind(_input++, value); } - auto& bind(nall::boolean value) { return bind(_input++, value); } - auto& bind(nall::integer value) { return bind(_input++, value); } - auto& bind(nall::natural value) { return bind(_input++, value); } + auto& bind(nall::Boolean value) { return bind(_input++, value); } + auto& bind(nall::Integer value) { return bind(_input++, value); } + auto& bind(nall::Natural value) { return bind(_input++, value); } auto& bind(f64 value) { return bind(_input++, value); } auto& bind(const nall::string& value) { return bind(_input++, value); } auto& bind(const vector& value) { return bind(_input++, value); } diff --git a/waterbox/ares64/ares/nall/decode/chd.hpp b/waterbox/ares64/ares/nall/decode/chd.hpp index 8d48228a81..b150787f68 100644 --- a/waterbox/ares64/ares/nall/decode/chd.hpp +++ b/waterbox/ares64/ares/nall/decode/chd.hpp @@ -3,7 +3,9 @@ #include #include #include -//#include +#if false +#include +#endif namespace nall::Decode { @@ -35,7 +37,9 @@ struct CHD { vector tracks; private: file_buffer fp; - //chd_file* chd = nullptr; +#if false + chd_file* chd = nullptr; +#endif const int chd_sector_size = 2352 + 96; size_t chd_hunk_size; vector chd_hunk_buffer; @@ -43,9 +47,11 @@ private: }; inline CHD::~CHD() { - /*if (chd != nullptr) { +#if false + if (chd != nullptr) { chd_close(chd); - }*/ + } +#endif } inline auto CHD::load(const string& location) -> bool { @@ -56,8 +62,8 @@ inline auto CHD::load(const string& location) -> bool { } return false; - - /*chd_error err = chd_open_file(fp.handle(), CHD_OPEN_READ, nullptr, &chd); +#if false + chd_error err = chd_open_file(fp.handle(), CHD_OPEN_READ, nullptr, &chd); if (err != CHDERR_NONE) { print("CHD: Failed to open ", location, ": ", chd_error_string(err), "\n"); return false; @@ -112,7 +118,7 @@ inline auto CHD::load(const string& location) -> bool { // We currently only support RAW and audio tracks; log an error and exit if we see anything different auto typeStr = string{type}; - if (!(typeStr.find("_RAW") || typeStr.find("AUDIO"))) { + if (!(typeStr.find("_RAW") || typeStr.find("AUDIO") || typeStr.find("MODE1"))) { print("CHD: Unsupported track type: ", type, "\n"); return false; } @@ -180,18 +186,20 @@ inline auto CHD::load(const string& location) -> bool { tracks.append(track); } - return true;*/ + return true; +#endif } inline auto CHD::read(u32 sector) -> vector { // Convert LBA in CD-ROM to LBA in CHD - /*for(auto& track : tracks) { +#if false + for(auto& track : tracks) { for(auto& index : track.indices) { if (sector >= index.lba && sector <= index.end) { auto chd_lba = (sector - index.lba) + index.chd_lba; vector output; - output.resize(2352); + output.resize(track.type == "MODE1" ? 2048 : 2352); int hunk = (chd_lba * chd_sector_size) / chd_hunk_size; int offset = (chd_lba * chd_sector_size) % chd_hunk_size; @@ -215,7 +223,7 @@ inline auto CHD::read(u32 sector) -> vector { dst_ptr += sizeof(value); } } else { - std::copy(chd_hunk_buffer.data() + offset, chd_hunk_buffer.data() + offset + 2352, output.data()); + std::copy(chd_hunk_buffer.data() + offset, chd_hunk_buffer.data() + offset + output.size(), output.data()); } return output; @@ -223,7 +231,8 @@ inline auto CHD::read(u32 sector) -> vector { } } - print("CHD: Attempting to read from unmapped sector ", sector, "\n");*/ + print("CHD: Attempting to read from unmapped sector ", sector, "\n"); +#endif return {}; } diff --git a/waterbox/ares64/ares/nall/directory.cpp b/waterbox/ares64/ares/nall/directory.cpp new file mode 100644 index 0000000000..31eb783f85 --- /dev/null +++ b/waterbox/ares64/ares/nall/directory.cpp @@ -0,0 +1,86 @@ +#include + +namespace nall { + +#if defined(PLATFORM_WINDOWS) + +NALL_HEADER_INLINE auto directory::exists(const string& pathname) -> bool { + if(!pathname) return false; + string name = pathname; + name.trim("\"", "\""); + DWORD result = GetFileAttributes(utf16_t(name)); + if(result == INVALID_FILE_ATTRIBUTES) return false; + return (result & FILE_ATTRIBUTE_DIRECTORY); +} + +NALL_HEADER_INLINE auto directory::ufolders(const string& pathname, const string& pattern) -> vector { + if(!pathname) { + //special root pseudo-folder (return list of drives) + wchar_t drives[PATH_MAX] = {0}; + GetLogicalDriveStrings(PATH_MAX, drives); + wchar_t* p = drives; + while(*p || *(p + 1)) { + if(!*p) *p = ';'; + p++; + } + return string{(const char*)utf8_t(drives)}.replace("\\", "/").split(";"); + } + + vector list; + string path = pathname; + path.transform("/", "\\"); + if(!path.endsWith("\\")) path.append("\\"); + path.append("*"); + HANDLE handle; + WIN32_FIND_DATA data; + handle = FindFirstFile(utf16_t(path), &data); + if(handle != INVALID_HANDLE_VALUE) { + if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) { + if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + string name = (const char*)utf8_t(data.cFileName); + if(name.match(pattern)) list.append(name); + } + } + while(FindNextFile(handle, &data) != false) { + if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) { + if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + string name = (const char*)utf8_t(data.cFileName); + if(name.match(pattern)) list.append(name); + } + } + } + FindClose(handle); + } + return list; +} + +NALL_HEADER_INLINE auto directory::ufiles(const string& pathname, const string& pattern) -> vector { + if(!pathname) return {}; + + vector list; + string path = pathname; + path.transform("/", "\\"); + if(!path.endsWith("\\")) path.append("\\"); + path.append("*"); + HANDLE handle; + WIN32_FIND_DATA data; + handle = FindFirstFile(utf16_t(path), &data); + if(handle != INVALID_HANDLE_VALUE) { + if((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { + string name = (const char*)utf8_t(data.cFileName); + if(name.match(pattern)) list.append(name); + } + while(FindNextFile(handle, &data) != false) { + if((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { + string name = (const char*)utf8_t(data.cFileName); + if(name.match(pattern)) list.append(name); + } + } + FindClose(handle); + } + return list; +} + +#endif + +} diff --git a/waterbox/ares64/ares/nall/directory.hpp b/waterbox/ares64/ares/nall/directory.hpp index c3a2d3aa6f..86fd1ca480 100644 --- a/waterbox/ares64/ares/nall/directory.hpp +++ b/waterbox/ares64/ares/nall/directory.hpp @@ -192,83 +192,6 @@ inline auto directory::copy(const string& source, const string& target) -> bool } return _wrmdir(utf16_t(pathname)) == 0; } - - inline auto directory::exists(const string& pathname) -> bool { - if(!pathname) return false; - string name = pathname; - name.trim("\"", "\""); - DWORD result = GetFileAttributes(utf16_t(name)); - if(result == INVALID_FILE_ATTRIBUTES) return false; - return (result & FILE_ATTRIBUTE_DIRECTORY); - } - - inline auto directory::ufolders(const string& pathname, const string& pattern) -> vector { - if(!pathname) { - //special root pseudo-folder (return list of drives) - wchar_t drives[PATH_MAX] = {0}; - GetLogicalDriveStrings(PATH_MAX, drives); - wchar_t* p = drives; - while(*p || *(p + 1)) { - if(!*p) *p = ';'; - p++; - } - return string{(const char*)utf8_t(drives)}.replace("\\", "/").split(";"); - } - - vector list; - string path = pathname; - path.transform("/", "\\"); - if(!path.endsWith("\\")) path.append("\\"); - path.append("*"); - HANDLE handle; - WIN32_FIND_DATA data; - handle = FindFirstFile(utf16_t(path), &data); - if(handle != INVALID_HANDLE_VALUE) { - if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) { - if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - string name = (const char*)utf8_t(data.cFileName); - if(name.match(pattern)) list.append(name); - } - } - while(FindNextFile(handle, &data) != false) { - if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) { - if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - string name = (const char*)utf8_t(data.cFileName); - if(name.match(pattern)) list.append(name); - } - } - } - FindClose(handle); - } - return list; - } - - inline auto directory::ufiles(const string& pathname, const string& pattern) -> vector { - if(!pathname) return {}; - - vector list; - string path = pathname; - path.transform("/", "\\"); - if(!path.endsWith("\\")) path.append("\\"); - path.append("*"); - HANDLE handle; - WIN32_FIND_DATA data; - handle = FindFirstFile(utf16_t(path), &data); - if(handle != INVALID_HANDLE_VALUE) { - if((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { - string name = (const char*)utf8_t(data.cFileName); - if(name.match(pattern)) list.append(name); - } - while(FindNextFile(handle, &data) != false) { - if((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { - string name = (const char*)utf8_t(data.cFileName); - if(name.match(pattern)) list.append(name); - } - } - FindClose(handle); - } - return list; - } #else inline auto directoryIsFolder(DIR* dp, struct dirent* ep) -> bool { if(ep->d_type == DT_DIR) return true; @@ -353,3 +276,7 @@ inline auto directory::copy(const string& source, const string& target) -> bool #endif } + +#if defined(NALL_HEADER_ONLY) + #include +#endif diff --git a/waterbox/ares64/ares/nall/dl.cpp b/waterbox/ares64/ares/nall/dl.cpp new file mode 100644 index 0000000000..71c3ed50be --- /dev/null +++ b/waterbox/ares64/ares/nall/dl.cpp @@ -0,0 +1,39 @@ +#include + +namespace nall { + +#if defined(PLATFORM_WINDOWS) + +NALL_HEADER_INLINE auto library::open(const string& name, const string& path) -> bool { + if(handle) close(); + if(path) { + string filepath = {path, name, ".dll"}; + handle = (uintptr)LoadLibraryW(utf16_t(filepath)); + } + if(!handle) { + string filepath = {name, ".dll"}; + handle = (uintptr)LoadLibraryW(utf16_t(filepath)); + } + return handle; +} + +NALL_HEADER_INLINE auto library::openAbsolute(const string& name) -> bool { + if(handle) close(); + handle = (uintptr)LoadLibraryW(utf16_t(name)); + return handle; +} + +NALL_HEADER_INLINE auto library::sym(const string& name) -> void* { + if(!handle) return nullptr; + return (void*)GetProcAddress((HMODULE)handle, name); +} + +NALL_HEADER_INLINE auto library::close() -> void { + if(!handle) return; + FreeLibrary((HMODULE)handle); + handle = 0; +} + +#endif + +} diff --git a/waterbox/ares64/ares/nall/dl.hpp b/waterbox/ares64/ares/nall/dl.hpp index 8116d34921..942511b208 100644 --- a/waterbox/ares64/ares/nall/dl.hpp +++ b/waterbox/ares64/ares/nall/dl.hpp @@ -87,35 +87,7 @@ inline auto library::close() -> void { handle = 0; } #elif defined(PLATFORM_WINDOWS) -inline auto library::open(const string& name, const string& path) -> bool { - if(handle) close(); - if(path) { - string filepath = {path, name, ".dll"}; - handle = (uintptr)LoadLibraryW(utf16_t(filepath)); - } - if(!handle) { - string filepath = {name, ".dll"}; - handle = (uintptr)LoadLibraryW(utf16_t(filepath)); - } - return handle; -} - -inline auto library::openAbsolute(const string& name) -> bool { - if(handle) close(); - handle = (uintptr)LoadLibraryW(utf16_t(name)); - return handle; -} - -inline auto library::sym(const string& name) -> void* { - if(!handle) return nullptr; - return (void*)GetProcAddress((HMODULE)handle, name); -} - -inline auto library::close() -> void { - if(!handle) return; - FreeLibrary((HMODULE)handle); - handle = 0; -} +//defined in dl.cpp #else inline auto library::open(const string&, const string&) -> bool { return false; } inline auto library::openAbsolute(const string&) -> bool { return false; } @@ -124,3 +96,7 @@ inline auto library::close() -> void {} #endif } + +#if defined(NALL_HEADER_ONLY) + #include +#endif diff --git a/waterbox/ares64/ares/nall/file-map.cpp b/waterbox/ares64/ares/nall/file-map.cpp new file mode 100644 index 0000000000..c579f0c607 --- /dev/null +++ b/waterbox/ares64/ares/nall/file-map.cpp @@ -0,0 +1,80 @@ +#include + +namespace nall { + +#if defined(API_WINDOWS) + +NALL_HEADER_INLINE auto file_map::open(const string& filename, u32 mode_) -> bool { + close(); + if(file::exists(filename) && file::size(filename) == 0) return _open = true; + + s32 desiredAccess, creationDisposition, protection, mapAccess; + + switch(mode_) { + default: return false; + case mode::read: + desiredAccess = GENERIC_READ; + creationDisposition = OPEN_EXISTING; + protection = PAGE_READONLY; + mapAccess = FILE_MAP_READ; + break; + case mode::write: + //write access requires read access + desiredAccess = GENERIC_WRITE; + creationDisposition = CREATE_ALWAYS; + protection = PAGE_READWRITE; + mapAccess = FILE_MAP_ALL_ACCESS; + break; + case mode::modify: + desiredAccess = GENERIC_READ | GENERIC_WRITE; + creationDisposition = OPEN_EXISTING; + protection = PAGE_READWRITE; + mapAccess = FILE_MAP_ALL_ACCESS; + break; + case mode::append: + desiredAccess = GENERIC_READ | GENERIC_WRITE; + creationDisposition = CREATE_NEW; + protection = PAGE_READWRITE; + mapAccess = FILE_MAP_ALL_ACCESS; + break; + } + + _file = CreateFileW(utf16_t(filename), desiredAccess, FILE_SHARE_READ, nullptr, + creationDisposition, FILE_ATTRIBUTE_NORMAL, nullptr); + if(_file == INVALID_HANDLE_VALUE) return false; + + _size = GetFileSize(_file, nullptr); + + _map = CreateFileMapping(_file, nullptr, protection, 0, _size, nullptr); + if(_map == INVALID_HANDLE_VALUE) { + CloseHandle(_file); + _file = INVALID_HANDLE_VALUE; + return false; + } + + _data = (u8*)MapViewOfFile(_map, mapAccess, 0, 0, _size); + return _open = true; +} + +NALL_HEADER_INLINE auto file_map::close() -> void { + if(_data) { + UnmapViewOfFile(_data); + _data = nullptr; + } + + if(_map != INVALID_HANDLE_VALUE) { + CloseHandle(_map); + _map = INVALID_HANDLE_VALUE; + } + + if(_file != INVALID_HANDLE_VALUE) { + CloseHandle(_file); + _file = INVALID_HANDLE_VALUE; + } + + _open = false; +} + +#endif + +} diff --git a/waterbox/ares64/ares/nall/file-map.hpp b/waterbox/ares64/ares/nall/file-map.hpp index 2f7e506e55..0a7ec70094 100644 --- a/waterbox/ares64/ares/nall/file-map.hpp +++ b/waterbox/ares64/ares/nall/file-map.hpp @@ -73,76 +73,9 @@ public: return *this; } - auto open(const string& filename, u32 mode_) -> bool { - close(); - if(file::exists(filename) && file::size(filename) == 0) return _open = true; + auto open(const string& filename, u32 mode_) -> bool; - s32 desiredAccess, creationDisposition, protection, mapAccess; - - switch(mode_) { - default: return false; - case mode::read: - desiredAccess = GENERIC_READ; - creationDisposition = OPEN_EXISTING; - protection = PAGE_READONLY; - mapAccess = FILE_MAP_READ; - break; - case mode::write: - //write access requires read access - desiredAccess = GENERIC_WRITE; - creationDisposition = CREATE_ALWAYS; - protection = PAGE_READWRITE; - mapAccess = FILE_MAP_ALL_ACCESS; - break; - case mode::modify: - desiredAccess = GENERIC_READ | GENERIC_WRITE; - creationDisposition = OPEN_EXISTING; - protection = PAGE_READWRITE; - mapAccess = FILE_MAP_ALL_ACCESS; - break; - case mode::append: - desiredAccess = GENERIC_READ | GENERIC_WRITE; - creationDisposition = CREATE_NEW; - protection = PAGE_READWRITE; - mapAccess = FILE_MAP_ALL_ACCESS; - break; - } - - _file = CreateFileW(utf16_t(filename), desiredAccess, FILE_SHARE_READ, nullptr, - creationDisposition, FILE_ATTRIBUTE_NORMAL, nullptr); - if(_file == INVALID_HANDLE_VALUE) return false; - - _size = GetFileSize(_file, nullptr); - - _map = CreateFileMapping(_file, nullptr, protection, 0, _size, nullptr); - if(_map == INVALID_HANDLE_VALUE) { - CloseHandle(_file); - _file = INVALID_HANDLE_VALUE; - return false; - } - - _data = (u8*)MapViewOfFile(_map, mapAccess, 0, 0, _size); - return _open = true; - } - - auto close() -> void { - if(_data) { - UnmapViewOfFile(_data); - _data = nullptr; - } - - if(_map != INVALID_HANDLE_VALUE) { - CloseHandle(_map); - _map = INVALID_HANDLE_VALUE; - } - - if(_file != INVALID_HANDLE_VALUE) { - CloseHandle(_file); - _file = INVALID_HANDLE_VALUE; - } - - _open = false; - } + auto close() -> void; #else @@ -229,3 +162,7 @@ public: }; } + +#if defined(NALL_HEADER_ONLY) + #include +#endif diff --git a/waterbox/ares64/ares/nall/file.hpp b/waterbox/ares64/ares/nall/file.hpp index a4bec188ba..91be160ef7 100644 --- a/waterbox/ares64/ares/nall/file.hpp +++ b/waterbox/ares64/ares/nall/file.hpp @@ -68,7 +68,7 @@ struct file : inode { struct __stat64 data; _wstat64(utf16_t(filename), &data); #endif - return S_ISREG(data.st_mode) ? data.st_size : 0u; + return (data.st_mode & S_IFMT) == S_IFREG ? data.st_size : 0u; } static auto read(const string& filename) -> vector { diff --git a/waterbox/ares64/ares/nall/function.hpp b/waterbox/ares64/ares/nall/function.hpp index d28b809f1d..617330c4ad 100644 --- a/waterbox/ares64/ares/nall/function.hpp +++ b/waterbox/ares64/ares/nall/function.hpp @@ -22,7 +22,6 @@ template struct function R> { template function(auto (C::*function)(P...) -> R, C* object) { callback = new member(function, object); } template function(auto (C::*function)(P...) const -> R, C* object) { callback = new member((auto (C::*)(P...) -> R)function, object); } template::value>> function(const L& object) { callback = new lambda(object); } - explicit function(void* function) { if(function) callback = new global((auto (*)(P...) -> R)function); } ~function() { if(callback) delete callback; } explicit operator bool() const { return callback; } @@ -37,12 +36,6 @@ template struct function R> { return *this; } - auto operator=(void* source) -> function& { - if(callback) { delete callback; callback = nullptr; } - callback = new global((auto (*)(P...) -> R)source); - return *this; - } - private: struct container { virtual auto operator()(P... p) const -> R = 0; diff --git a/waterbox/ares64/ares/nall/http/client.cpp b/waterbox/ares64/ares/nall/http/client.cpp new file mode 100644 index 0000000000..9d5c98ff7f --- /dev/null +++ b/waterbox/ares64/ares/nall/http/client.cpp @@ -0,0 +1,36 @@ +#include + +#if defined(PLATFORM_WINDOWS) + #include +#endif + +namespace nall::HTTP { + +NALL_HEADER_INLINE auto Client::open(const string& hostname, u16 port) -> bool { + addrinfo hint = {}; + hint.ai_family = AF_UNSPEC; + hint.ai_socktype = SOCK_STREAM; + hint.ai_flags = AI_ADDRCONFIG; + + if(getaddrinfo(hostname, string{port}, &hint, &info) != 0) return close(), false; + + fd = socket(info->ai_family, info->ai_socktype, info->ai_protocol); + if(fd < 0) return close(), false; + + if(connect(fd, info->ai_addr, info->ai_addrlen) < 0) return close(), false; + return true; +} + +NALL_HEADER_INLINE auto Client::close() -> void { + if(fd) { + ::close(fd); + fd = -1; + } + + if(info) { + freeaddrinfo(info); + info = nullptr; + } +} + +} diff --git a/waterbox/ares64/ares/nall/http/client.hpp b/waterbox/ares64/ares/nall/http/client.hpp index 1fbf54a04b..8e96417920 100644 --- a/waterbox/ares64/ares/nall/http/client.hpp +++ b/waterbox/ares64/ares/nall/http/client.hpp @@ -2,6 +2,8 @@ #include +struct addrinfo; + namespace nall::HTTP { struct Client : Role { @@ -16,21 +18,6 @@ private: addrinfo* info = nullptr; }; -inline auto Client::open(const string& hostname, u16 port) -> bool { - addrinfo hint = {}; - hint.ai_family = AF_UNSPEC; - hint.ai_socktype = SOCK_STREAM; - hint.ai_flags = AI_ADDRCONFIG; - - if(getaddrinfo(hostname, string{port}, &hint, &info) != 0) return close(), false; - - fd = socket(info->ai_family, info->ai_socktype, info->ai_protocol); - if(fd < 0) return close(), false; - - if(connect(fd, info->ai_addr, info->ai_addrlen) < 0) return close(), false; - return true; -} - inline auto Client::upload(const Request& request) -> bool { return Role::upload(fd, request); } @@ -41,16 +28,8 @@ inline auto Client::download(const Request& request) -> Response { return response; } -inline auto Client::close() -> void { - if(fd) { - ::close(fd); - fd = -1; - } - - if(info) { - freeaddrinfo(info); - info = nullptr; - } } -} +#if defined(NALL_HEADER_ONLY) + #include +#endif diff --git a/waterbox/ares64/ares/nall/http/response.hpp b/waterbox/ares64/ares/nall/http/response.hpp index 93a3b7a7b5..bc5aa12061 100644 --- a/waterbox/ares64/ares/nall/http/response.hpp +++ b/waterbox/ares64/ares/nall/http/response.hpp @@ -1,5 +1,7 @@ #pragma once +#include +#include #include namespace nall::HTTP { diff --git a/waterbox/ares64/ares/nall/http/server.cpp b/waterbox/ares64/ares/nall/http/server.cpp new file mode 100644 index 0000000000..98f225b729 --- /dev/null +++ b/waterbox/ares64/ares/nall/http/server.cpp @@ -0,0 +1,185 @@ +#include +#include + +#if defined(PLATFORM_WINDOWS) + #include +#endif + +namespace nall::HTTP { + +NALL_HEADER_INLINE auto Server::open(u16 port, const string& serviceName, const string& command) -> bool { + if(serviceName) { + if(!service::command(serviceName, command)) return false; + } + + fd4 = socket(AF_INET, SOCK_STREAM, 0); + fd6 = socket(AF_INET6, SOCK_STREAM, 0); + if(!ipv4() && !ipv6()) return false; + + { + #if defined(SO_RCVTIMEO) + if(settings.timeoutReceive) { + struct timeval rcvtimeo; + rcvtimeo.tv_sec = settings.timeoutReceive / 1000; + rcvtimeo.tv_usec = settings.timeoutReceive % 1000 * 1000; + if(ipv4()) setsockopt(fd4, SOL_SOCKET, SO_RCVTIMEO, &rcvtimeo, sizeof(struct timeval)); + if(ipv6()) setsockopt(fd6, SOL_SOCKET, SO_RCVTIMEO, &rcvtimeo, sizeof(struct timeval)); + } + #endif + + #if defined(SO_SNDTIMEO) + if(settings.timeoutSend) { + struct timeval sndtimeo; + sndtimeo.tv_sec = settings.timeoutSend / 1000; + sndtimeo.tv_usec = settings.timeoutSend % 1000 * 1000; + if(ipv4()) setsockopt(fd4, SOL_SOCKET, SO_SNDTIMEO, &sndtimeo, sizeof(struct timeval)); + if(ipv6()) setsockopt(fd6, SOL_SOCKET, SO_SNDTIMEO, &sndtimeo, sizeof(struct timeval)); + } + #endif + + #if defined(SO_NOSIGPIPE) //BSD, OSX + s32 nosigpipe = 1; + if(ipv4()) setsockopt(fd4, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(s32)); + if(ipv6()) setsockopt(fd6, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(s32)); + #endif + + #if defined(SO_REUSEADDR) //BSD, Linux, OSX + s32 reuseaddr = 1; + if(ipv4()) setsockopt(fd4, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(s32)); + if(ipv6()) setsockopt(fd6, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(s32)); + #endif + + #if defined(SO_REUSEPORT) //BSD, OSX + s32 reuseport = 1; + if(ipv4()) setsockopt(fd4, SOL_SOCKET, SO_REUSEPORT, &reuseport, sizeof(s32)); + if(ipv6()) setsockopt(fd6, SOL_SOCKET, SO_REUSEPORT, &reuseport, sizeof(s32)); + #endif + } + + addrin4.sin_family = AF_INET; + addrin4.sin_addr.s_addr = htonl(INADDR_ANY); + addrin4.sin_port = htons(port); + + addrin6.sin6_family = AF_INET6; + addrin6.sin6_addr = in6addr_any; + addrin6.sin6_port = htons(port); + + if(bind(fd4, (struct sockaddr*)&addrin4, sizeof(addrin4)) < 0 || listen(fd4, SOMAXCONN) < 0) ipv4_close(); + if(bind(fd6, (struct sockaddr*)&addrin6, sizeof(addrin6)) < 0 || listen(fd6, SOMAXCONN) < 0) ipv6_close(); + return ipv4() || ipv6(); +} + +NALL_HEADER_INLINE auto Server::ipv4_scan() -> bool { + struct pollfd query = {0}; + query.fd = fd4; + query.events = POLLIN; + poll(&query, 1, 0); + + if(query.fd == fd4 && query.revents & POLLIN) { + ++connections; + + thread::create([&](uintptr) { + thread::detach(); + + s32 clientfd = -1; + struct sockaddr_in settings = {0}; + socklen_t socklen = sizeof(sockaddr_in); + + clientfd = accept(fd4, (struct sockaddr*)&settings, &socklen); + if(clientfd < 0) return; + + u32 ip = ntohl(settings.sin_addr.s_addr); + + Request request; + request._ipv6 = false; + request._ip = { + (u8)(ip >> 24), ".", + (u8)(ip >> 16), ".", + (u8)(ip >> 8), ".", + (u8)(ip >> 0) + }; + + if(download(clientfd, request) && callback) { + auto response = callback(request); + upload(clientfd, response); + } else { + upload(clientfd, Response()); //"501 Not Implemented" + } + + ::close(clientfd); + --connections; + }, 0, settings.threadStackSize); + + return true; + } + + return false; +} + +NALL_HEADER_INLINE auto Server::ipv6_scan() -> bool { + struct pollfd query = {0}; + query.fd = fd6; + query.events = POLLIN; + poll(&query, 1, 0); + + if(query.fd == fd6 && query.revents & POLLIN) { + ++connections; + + thread::create([&](uintptr) { + thread::detach(); + + s32 clientfd = -1; + struct sockaddr_in6 settings = {0}; + socklen_t socklen = sizeof(sockaddr_in6); + + clientfd = accept(fd6, (struct sockaddr*)&settings, &socklen); + if(clientfd < 0) return; + + u8* ip = settings.sin6_addr.s6_addr; + u16 ipSegment[8]; + for(auto n : range(8)) ipSegment[n] = ip[n * 2 + 0] * 256 + ip[n * 2 + 1]; + + Request request; + request._ipv6 = true; + //RFC5952 IPv6 encoding: the first longest 2+ consecutive zero-sequence is compressed to "::" + s32 zeroOffset = -1; + s32 zeroLength = 0; + s32 zeroCounter = 0; + for(auto n : range(8)) { + u16 value = ipSegment[n]; + if(value == 0) zeroCounter++; + if(zeroCounter > zeroLength) { + zeroLength = zeroCounter; + zeroOffset = 1 + n - zeroLength; + } + if(value != 0) zeroCounter = 0; + } + if(zeroLength == 1) zeroOffset = -1; + for(u32 n = 0; n < 8;) { + if(n == zeroOffset) { + request._ip.append(n == 0 ? "::" : ":"); + n += zeroLength; + } else { + u16 value = ipSegment[n]; + request._ip.append(hex(value), n++ != 7 ? ":" : ""); + } + } + + if(download(clientfd, request) && callback) { + auto response = callback(request); + upload(clientfd, response); + } else { + upload(clientfd, Response()); //"501 Not Implemented" + } + + ::close(clientfd); + --connections; + }, 0, settings.threadStackSize); + + return true; + } + + return false; +} + +} diff --git a/waterbox/ares64/ares/nall/http/server.hpp b/waterbox/ares64/ares/nall/http/server.hpp index 5560fec27e..94469ffba8 100644 --- a/waterbox/ares64/ares/nall/http/server.hpp +++ b/waterbox/ares64/ares/nall/http/server.hpp @@ -3,6 +3,9 @@ #include #include +struct sockaddr_in; +struct sockaddr_in6; + namespace nall::HTTP { struct Server : Role, service { @@ -18,8 +21,10 @@ private: s32 fd4 = -1; s32 fd6 = -1; - struct sockaddr_in addrin4 = {0}; - struct sockaddr_in6 addrin6 = {0}; + u64 addrin4_storage[16] = {0}; //sizeof(sockaddr_storage) = 128 + u64 addrin6_storage[16] = {0}; + sockaddr_in& addrin4 = (sockaddr_in&)addrin4_storage; + sockaddr_in6& addrin6 = (sockaddr_in6&)addrin6_storage; auto ipv4() const -> bool { return fd4 >= 0; } auto ipv6() const -> bool { return fd6 >= 0; } @@ -31,68 +36,6 @@ private: auto ipv6_scan() -> bool; }; -inline auto Server::open(u16 port, const string& serviceName, const string& command) -> bool { - if(serviceName) { - if(!service::command(serviceName, command)) return false; - } - - fd4 = socket(AF_INET, SOCK_STREAM, 0); - fd6 = socket(AF_INET6, SOCK_STREAM, 0); - if(!ipv4() && !ipv6()) return false; - - { - #if defined(SO_RCVTIMEO) - if(settings.timeoutReceive) { - struct timeval rcvtimeo; - rcvtimeo.tv_sec = settings.timeoutReceive / 1000; - rcvtimeo.tv_usec = settings.timeoutReceive % 1000 * 1000; - if(ipv4()) setsockopt(fd4, SOL_SOCKET, SO_RCVTIMEO, &rcvtimeo, sizeof(struct timeval)); - if(ipv6()) setsockopt(fd6, SOL_SOCKET, SO_RCVTIMEO, &rcvtimeo, sizeof(struct timeval)); - } - #endif - - #if defined(SO_SNDTIMEO) - if(settings.timeoutSend) { - struct timeval sndtimeo; - sndtimeo.tv_sec = settings.timeoutSend / 1000; - sndtimeo.tv_usec = settings.timeoutSend % 1000 * 1000; - if(ipv4()) setsockopt(fd4, SOL_SOCKET, SO_SNDTIMEO, &sndtimeo, sizeof(struct timeval)); - if(ipv6()) setsockopt(fd6, SOL_SOCKET, SO_SNDTIMEO, &sndtimeo, sizeof(struct timeval)); - } - #endif - - #if defined(SO_NOSIGPIPE) //BSD, OSX - s32 nosigpipe = 1; - if(ipv4()) setsockopt(fd4, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(s32)); - if(ipv6()) setsockopt(fd6, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(s32)); - #endif - - #if defined(SO_REUSEADDR) //BSD, Linux, OSX - s32 reuseaddr = 1; - if(ipv4()) setsockopt(fd4, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(s32)); - if(ipv6()) setsockopt(fd6, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(s32)); - #endif - - #if defined(SO_REUSEPORT) //BSD, OSX - s32 reuseport = 1; - if(ipv4()) setsockopt(fd4, SOL_SOCKET, SO_REUSEPORT, &reuseport, sizeof(s32)); - if(ipv6()) setsockopt(fd6, SOL_SOCKET, SO_REUSEPORT, &reuseport, sizeof(s32)); - #endif - } - - addrin4.sin_family = AF_INET; - addrin4.sin_addr.s_addr = htonl(INADDR_ANY); - addrin4.sin_port = htons(port); - - addrin6.sin6_family = AF_INET6; - addrin6.sin6_addr = in6addr_any; - addrin6.sin6_port = htons(port); - - if(bind(fd4, (struct sockaddr*)&addrin4, sizeof(addrin4)) < 0 || listen(fd4, SOMAXCONN) < 0) ipv4_close(); - if(bind(fd6, (struct sockaddr*)&addrin6, sizeof(addrin6)) < 0 || listen(fd6, SOMAXCONN) < 0) ipv6_close(); - return ipv4() || ipv6(); -} - inline auto Server::main(const function& function) -> void { callback = function; } @@ -105,122 +48,13 @@ inline auto Server::scan() -> string { return "idle"; } -inline auto Server::ipv4_scan() -> bool { - struct pollfd query = {0}; - query.fd = fd4; - query.events = POLLIN; - poll(&query, 1, 0); - - if(query.fd == fd4 && query.revents & POLLIN) { - ++connections; - - thread::create([&](uintptr) { - thread::detach(); - - s32 clientfd = -1; - struct sockaddr_in settings = {0}; - socklen_t socklen = sizeof(sockaddr_in); - - clientfd = accept(fd4, (struct sockaddr*)&settings, &socklen); - if(clientfd < 0) return; - - u32 ip = ntohl(settings.sin_addr.s_addr); - - Request request; - request._ipv6 = false; - request._ip = { - (u8)(ip >> 24), ".", - (u8)(ip >> 16), ".", - (u8)(ip >> 8), ".", - (u8)(ip >> 0) - }; - - if(download(clientfd, request) && callback) { - auto response = callback(request); - upload(clientfd, response); - } else { - upload(clientfd, Response()); //"501 Not Implemented" - } - - ::close(clientfd); - --connections; - }, 0, settings.threadStackSize); - - return true; - } - - return false; -} - -inline auto Server::ipv6_scan() -> bool { - struct pollfd query = {0}; - query.fd = fd6; - query.events = POLLIN; - poll(&query, 1, 0); - - if(query.fd == fd6 && query.revents & POLLIN) { - ++connections; - - thread::create([&](uintptr) { - thread::detach(); - - s32 clientfd = -1; - struct sockaddr_in6 settings = {0}; - socklen_t socklen = sizeof(sockaddr_in6); - - clientfd = accept(fd6, (struct sockaddr*)&settings, &socklen); - if(clientfd < 0) return; - - u8* ip = settings.sin6_addr.s6_addr; - u16 ipSegment[8]; - for(auto n : range(8)) ipSegment[n] = ip[n * 2 + 0] * 256 + ip[n * 2 + 1]; - - Request request; - request._ipv6 = true; - //RFC5952 IPv6 encoding: the first longest 2+ consecutive zero-sequence is compressed to "::" - s32 zeroOffset = -1; - s32 zeroLength = 0; - s32 zeroCounter = 0; - for(auto n : range(8)) { - u16 value = ipSegment[n]; - if(value == 0) zeroCounter++; - if(zeroCounter > zeroLength) { - zeroLength = zeroCounter; - zeroOffset = 1 + n - zeroLength; - } - if(value != 0) zeroCounter = 0; - } - if(zeroLength == 1) zeroOffset = -1; - for(u32 n = 0; n < 8;) { - if(n == zeroOffset) { - request._ip.append(n == 0 ? "::" : ":"); - n += zeroLength; - } else { - u16 value = ipSegment[n]; - request._ip.append(hex(value), n++ != 7 ? ":" : ""); - } - } - - if(download(clientfd, request) && callback) { - auto response = callback(request); - upload(clientfd, response); - } else { - upload(clientfd, Response()); //"501 Not Implemented" - } - - ::close(clientfd); - --connections; - }, 0, settings.threadStackSize); - - return true; - } - - return false; -} - inline auto Server::close() -> void { ipv4_close(); ipv6_close(); } } + +#if defined(NALL_HEADER_ONLY) + #include +#endif diff --git a/waterbox/ares64/ares/nall/inode.cpp b/waterbox/ares64/ares/nall/inode.cpp new file mode 100644 index 0000000000..48bef1876a --- /dev/null +++ b/waterbox/ares64/ares/nall/inode.cpp @@ -0,0 +1,15 @@ +#include + +namespace nall { + +NALL_HEADER_INLINE auto inode::hidden(const string& name) -> bool { + #if defined(PLATFORM_WINDOWS) + auto attributes = GetFileAttributes(utf16_t(name)); + return attributes & FILE_ATTRIBUTE_HIDDEN; + #else + //todo: is this really the best way to do this? stat doesn't have S_ISHIDDEN ... + return name.split("/").last().beginsWith("."); + #endif +} + +} diff --git a/waterbox/ares64/ares/nall/inode.hpp b/waterbox/ares64/ares/nall/inode.hpp index 491fdd1612..11d3fa2c89 100644 --- a/waterbox/ares64/ares/nall/inode.hpp +++ b/waterbox/ares64/ares/nall/inode.hpp @@ -6,6 +6,22 @@ #include #include +#if !defined(F_OK) + #define F_OK 0 +#endif + +#if !defined(X_OK) + #define X_OK 1 +#endif + +#if !defined(W_OK) + #define W_OK 2 +#endif + +#if !defined(R_OK) + #define R_OK 4 +#endif + namespace nall { struct inode { @@ -31,15 +47,7 @@ struct inode { return access(name, X_OK) == 0; } - static auto hidden(const string& name) -> bool { - #if defined(PLATFORM_WINDOWS) - auto attributes = GetFileAttributes(utf16_t(name)); - return attributes & FILE_ATTRIBUTE_HIDDEN; - #else - //todo: is this really the best way to do this? stat doesn't have S_ISHIDDEN ... - return name.split("/").last().beginsWith("."); - #endif - } + static auto hidden(const string& name) -> bool; static auto mode(const string& name) -> u32 { struct stat data{}; @@ -161,3 +169,7 @@ struct inode { }; } + +#if defined(NALL_HEADER_ONLY) + #include +#endif diff --git a/waterbox/ares64/ares/nall/intrinsics.hpp b/waterbox/ares64/ares/nall/intrinsics.hpp index 29c65da4ec..c3aa3d4871 100644 --- a/waterbox/ares64/ares/nall/intrinsics.hpp +++ b/waterbox/ares64/ares/nall/intrinsics.hpp @@ -1,5 +1,11 @@ #pragma once +#if defined(NALL_HEADER_ONLY) + #define NALL_HEADER_INLINE inline +#else + #define NALL_HEADER_INLINE +#endif + #if defined(__APPLE__) #include #elif defined(linux) || defined(__linux__) @@ -19,6 +25,11 @@ namespace nall { static constexpr bool GCC = 0; static constexpr bool Microsoft = 0; }; + #pragma clang diagnostic error "-Wc++20-extensions" + #pragma clang diagnostic error "-Wgnu-case-range" + #pragma clang diagnostic error "-Wgnu-statement-expression" + #pragma clang diagnostic error "-Wvla" + #pragma clang diagnostic warning "-Wimplicit-fallthrough" #pragma clang diagnostic warning "-Wreturn-type" #pragma clang diagnostic ignored "-Wunused-result" #pragma clang diagnostic ignored "-Wunknown-pragmas" @@ -28,7 +39,6 @@ namespace nall { #pragma clang diagnostic ignored "-Wswitch-bool" #pragma clang diagnostic ignored "-Wabsolute-value" #pragma clang diagnostic ignored "-Wtrigraphs" - #pragma clang diagnostic ignored "-Wnarrowing" #pragma clang diagnostic ignored "-Wattributes" #elif defined(__GNUC__) #define COMPILER_GCC @@ -37,13 +47,14 @@ namespace nall { static constexpr bool GCC = 1; static constexpr bool Microsoft = 0; }; + #pragma GCC diagnostic error "-Wvla" + #pragma GCC diagnostic warning "-Wimplicit-fallthrough" #pragma GCC diagnostic warning "-Wreturn-type" #pragma GCC diagnostic ignored "-Wunused-result" #pragma GCC diagnostic ignored "-Wunknown-pragmas" #pragma GCC diagnostic ignored "-Wpragmas" #pragma GCC diagnostic ignored "-Wswitch-bool" #pragma GCC diagnostic ignored "-Wtrigraphs" - #pragma GCC diagnostic ignored "-Wnarrowing" #pragma GCC diagnostic ignored "-Wattributes" #pragma GCC diagnostic ignored "-Wstringop-overflow" //GCC 10.2 warning heuristic is buggy #elif defined(_MSC_VER) @@ -180,7 +191,7 @@ namespace nall { }; #elif defined(__amd64__) || defined(_M_AMD64) #define ARCHITECTURE_AMD64 - #if defined(__SSE4_1__) + #if defined(__SSE4_1__) || defined(COMPILER_MICROSOFT) #define ARCHITECTURE_SUPPORTS_SSE4_1 1 #endif struct Architecture { @@ -191,9 +202,11 @@ namespace nall { static constexpr bool ppc64 = 0; static constexpr bool ppc32 = 0; }; -#elif defined(__aarch64__) +#elif defined(__aarch64__) || defined(_M_ARM64) #define ARCHITECTURE_ARM64 - #define ARCHITECTURE_SUPPORTS_SSE4_1 1 // simulated via sse2neon.h + #if !defined(COMPILER_MICROSOFT) + #define ARCHITECTURE_SUPPORTS_SSE4_1 1 // simulated via sse2neon.h + #endif struct Architecture { static constexpr bool x86 = 0; static constexpr bool amd64 = 0; @@ -242,7 +255,7 @@ namespace nall { /* Endian detection */ -#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN) || defined(__LITTLE_ENDIAN__) || defined(__i386__) || defined(__amd64__) || defined(_M_IX86) || defined(_M_AMD64) +#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN) || defined(__LITTLE_ENDIAN__) || defined(__i386__) || defined(__amd64__) || defined(_M_IX86) || defined(_M_AMD64) || defined(_M_ARM64) #define ENDIAN_LITTLE struct Endian { static constexpr bool Little = 1; diff --git a/waterbox/ares64/ares/nall/main.cpp b/waterbox/ares64/ares/nall/main.cpp new file mode 100644 index 0000000000..37b7a5ee30 --- /dev/null +++ b/waterbox/ares64/ares/nall/main.cpp @@ -0,0 +1,55 @@ +#include + +#if defined(PLATFORM_WINDOWS) + #include + #include + #include +#endif + +namespace nall { + +auto main(int argc, char** argv) -> int { + #if defined(PLATFORM_WINDOWS) + CoInitialize(0); + WSAData wsaData{0}; + WSAStartup(MAKEWORD(2, 2), &wsaData); + _setmode(_fileno(stdin ), O_BINARY); + _setmode(_fileno(stdout), O_BINARY); + _setmode(_fileno(stderr), O_BINARY); + #endif + + main(Arguments{argc, argv}); + + #if !defined(PLATFORM_WINDOWS) + //when a program is running, input on the terminal queues in stdin + //when terminating the program, the shell proceeds to try and execute all stdin data + //this is annoying behavior: this code tries to minimize the impact as much as it can + //we can flush all of stdin up to the last line feed, preventing spurious commands from executing + //however, even with setvbuf(_IONBF), we can't stop the last line from echoing to the terminal + auto flags = fcntl(fileno(stdin), F_GETFL, 0); + fcntl(fileno(stdin), F_SETFL, flags | O_NONBLOCK); //don't allow read() to block when empty + char buffer[4096], data = false; + while(read(fileno(stdin), buffer, sizeof(buffer)) > 0) data = true; + fcntl(fileno(stdin), F_SETFL, flags); //restore original flags for the terminal + if(data) putchar('\r'); //ensures PS1 is printed at the start of the line + #endif + + return EXIT_SUCCESS; +} + +} + +#if defined(PLATFORM_WINDOWS) && defined(SUBSYTEM_WINDOWS) + +auto WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nCmdShow) -> int { + //arguments are retrieved later via GetCommandLineW() + return nall::main(0, nullptr); +} + +#else + +auto main(int argc, char** argv) -> int { + return nall::main(argc, argv); +} + +#endif diff --git a/waterbox/ares64/ares/nall/main.hpp b/waterbox/ares64/ares/nall/main.hpp index 273e43f605..f50cc3753e 100644 --- a/waterbox/ares64/ares/nall/main.hpp +++ b/waterbox/ares64/ares/nall/main.hpp @@ -7,36 +7,9 @@ namespace nall { auto main(Arguments arguments) -> void; - auto main(int argc, char** argv) -> int { - #if defined(PLATFORM_WINDOWS) - CoInitialize(0); - WSAData wsaData{0}; - WSAStartup(MAKEWORD(2, 2), &wsaData); - _setmode(_fileno(stdin ), O_BINARY); - _setmode(_fileno(stdout), O_BINARY); - _setmode(_fileno(stderr), O_BINARY); - #endif - - main(Arguments{argc, argv}); - - #if !defined(PLATFORM_WINDOWS) - //when a program is running, input on the terminal queues in stdin - //when terminating the program, the shell proceeds to try and execute all stdin data - //this is annoying behavior: this code tries to minimize the impact as much as it can - //we can flush all of stdin up to the last line feed, preventing spurious commands from executing - //however, even with setvbuf(_IONBF), we can't stop the last line from echoing to the terminal - auto flags = fcntl(fileno(stdin), F_GETFL, 0); - fcntl(fileno(stdin), F_SETFL, flags | O_NONBLOCK); //don't allow read() to block when empty - char buffer[4096], data = false; - while(read(fileno(stdin), buffer, sizeof(buffer)) > 0) data = true; - fcntl(fileno(stdin), F_SETFL, flags); //restore original flags for the terminal - if(data) putchar('\r'); //ensures PS1 is printed at the start of the line - #endif - - return EXIT_SUCCESS; - } + auto main(int argc, char** argv) -> int; } -auto main(int argc, char** argv) -> int { - return nall::main(argc, argv); -} +#if defined(NALL_HEADER_ONLY) + #include +#endif diff --git a/waterbox/ares64/ares/nall/memory.cpp b/waterbox/ares64/ares/nall/memory.cpp new file mode 100644 index 0000000000..8479cff96b --- /dev/null +++ b/waterbox/ares64/ares/nall/memory.cpp @@ -0,0 +1,47 @@ +#include + +namespace nall::memory { + +NALL_HEADER_INLINE auto map(u32 size, bool executable) -> void* { + #if defined(API_WINDOWS) + DWORD protect = executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; + return VirtualAlloc(nullptr, size, MEM_RESERVE | MEM_COMMIT, protect); + #elif defined(API_POSIX) + int prot = PROT_READ | PROT_WRITE; + int flags = MAP_ANON | MAP_PRIVATE; + if(executable) { + prot |= PROT_EXEC; + #if defined(PLATFORM_MACOS) + flags |= MAP_JIT; + #endif + } + return mmap(nullptr, size, prot, flags, -1, 0); + #else + return nullptr; + #endif +} + +NALL_HEADER_INLINE auto unmap(void* target, u32 size) -> void { + #if defined(API_WINDOWS) + VirtualFree(target, 0, MEM_RELEASE); + #elif defined(API_POSIX) + munmap(target, size); + #endif +} + +NALL_HEADER_INLINE auto protect(void* target, u32 size, bool executable) -> void { + #if defined(API_WINDOWS) + DWORD protect = executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; + DWORD oldProtect; + VirtualProtect(target, size, protect, &oldProtect); + #elif defined(API_POSIX) + int prot = PROT_READ | PROT_WRITE; + if(executable) { + prot |= PROT_EXEC; + } + int ret = mprotect(target, size, prot); + assert(ret == 0); + #endif +} + +} diff --git a/waterbox/ares64/ares/nall/memory.hpp b/waterbox/ares64/ares/nall/memory.hpp index 01161f5389..c932702bae 100644 --- a/waterbox/ares64/ares/nall/memory.hpp +++ b/waterbox/ares64/ares/nall/memory.hpp @@ -195,47 +195,11 @@ template auto writem(void* target, T data) -> void { for(s32 n = size - 1; n >= 0; n--) *p++ = data >> n * 8; } -inline auto map(u32 size, bool executable) -> void* { - #if defined(API_WINDOWS) - DWORD protect = executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; - return VirtualAlloc(nullptr, size, MEM_RESERVE | MEM_COMMIT, protect); - #elif defined(API_POSIX) - int prot = PROT_READ | PROT_WRITE; - int flags = MAP_ANON | MAP_PRIVATE; - if(executable) { - prot |= PROT_EXEC; - #if defined(PLATFORM_MACOS) - flags |= MAP_JIT; - #endif - } - return mmap(nullptr, size, prot, flags, -1, 0); - #else - return nullptr; - #endif -} +auto map(u32 size, bool executable) -> void*; -inline auto unmap(void* target, u32 size) -> void { - #if defined(API_WINDOWS) - VirtualFree(target, 0, MEM_RELEASE); - #elif defined(API_POSIX) - munmap(target, size); - #endif -} +auto unmap(void* target, u32 size) -> void; -inline auto protect(void* target, u32 size, bool executable) -> void { - #if defined(API_WINDOWS) - DWORD protect = executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; - DWORD oldProtect; - VirtualProtect(target, size, protect, &oldProtect); - #elif defined(API_POSIX) - int prot = PROT_READ | PROT_WRITE; - if(executable) { - prot |= PROT_EXEC; - } - int ret = mprotect(target, size, prot); - assert(ret == 0); - #endif -} +auto protect(void* target, u32 size, bool executable) -> void; inline auto jitprotect(bool executable) -> void { #if defined(PLATFORM_MACOS) @@ -246,3 +210,7 @@ inline auto jitprotect(bool executable) -> void { } } + +#if defined(NALL_HEADER_ONLY) + #include +#endif diff --git a/waterbox/ares64/ares/nall/nall.cpp b/waterbox/ares64/ares/nall/nall.cpp new file mode 100644 index 0000000000..223dde853c --- /dev/null +++ b/waterbox/ares64/ares/nall/nall.cpp @@ -0,0 +1,33 @@ +#if !defined(NALL_HEADER_ONLY) + +#include + +#if defined(PLATFORM_WINDOWS) + #include +#endif + +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include +//currently unused by ares +//#include +//#include +//#include +#if defined(PLATFORM_WINDOWS) + //#include + //#include + //#include + #include + #include +#endif + +#endif diff --git a/waterbox/ares64/ares/nall/path.cpp b/waterbox/ares64/ares/nall/path.cpp new file mode 100644 index 0000000000..02a12b9f30 --- /dev/null +++ b/waterbox/ares64/ares/nall/path.cpp @@ -0,0 +1,144 @@ +#include + +#if defined(PLATFORM_WINDOWS) + #include +#endif + +namespace nall::Path { + +NALL_HEADER_INLINE auto program() -> string { + #if defined(PLATFORM_WINDOWS) + wchar_t path[PATH_MAX] = L""; + GetModuleFileName(nullptr, path, PATH_MAX); + string result = (const char*)utf8_t(path); + result.transform("\\", "/"); + return Path::real(result); + #else + Dl_info info; + dladdr((void*)&program, &info); + return Path::real(info.dli_fname); + #endif +} + +NALL_HEADER_INLINE auto root() -> string { + #if defined(PLATFORM_WINDOWS) + wchar_t path[PATH_MAX] = L""; + SHGetFolderPathW(nullptr, CSIDL_WINDOWS | CSIDL_FLAG_CREATE, nullptr, 0, path); + string result = (const char*)utf8_t(path); + result.transform("\\", "/"); + return slice(result, 0, 3); + #else + return "/"; + #endif +} + +NALL_HEADER_INLINE auto user() -> string { + #if defined(PLATFORM_WINDOWS) + wchar_t path[PATH_MAX] = L""; + SHGetFolderPathW(nullptr, CSIDL_PROFILE | CSIDL_FLAG_CREATE, nullptr, 0, path); + string result = (const char*)utf8_t(path); + result.transform("\\", "/"); + #else + struct passwd* userinfo = getpwuid(getuid()); + string result = userinfo->pw_dir; + #endif + if(!result) result = "."; + if(!result.endsWith("/")) result.append("/"); + return result; +} + +NALL_HEADER_INLINE auto desktop(string_view name) -> string { + #if defined(PLATFORM_WINDOWS) + wchar_t path[PATH_MAX] = L""; + SHGetFolderPathW(nullptr, CSIDL_DESKTOP | CSIDL_FLAG_CREATE, nullptr, 0, path); + string result = (const char*)utf8_t(path); + result.transform("\\", "/"); + #elif defined(PLATFORM_MACOS) + string result = {user(), "Desktop/"}; + #else + string result; + if(const char *env = getenv("XDG_DESKTOP_DIR")) { + result = string(env); + } else { + result = {user(), "Desktop/"}; + } + #endif + if(!result) result = "."; + if(!result.endsWith("/")) result.append("/"); + return result.append(name); +} + +NALL_HEADER_INLINE auto userSettings() -> string { + #if defined(PLATFORM_WINDOWS) + wchar_t path[PATH_MAX] = L""; + SHGetFolderPathW(nullptr, CSIDL_APPDATA | CSIDL_FLAG_CREATE, nullptr, 0, path); + string result = (const char*)utf8_t(path); + result.transform("\\", "/"); + #elif defined(PLATFORM_MACOS) + string result = {Path::user(), "Library/Application Support/"}; + #else + string result; + if(const char *env = getenv("XDG_CONFIG_HOME")) { + result = string(env); + } else { + result = {Path::user(), ".config/"}; + } + #endif + if(!result) result = "."; + if(!result.endsWith("/")) result.append("/"); + return result; +} + +NALL_HEADER_INLINE auto userData() -> string { + #if defined(PLATFORM_WINDOWS) + wchar_t path[PATH_MAX] = L""; + SHGetFolderPathW(nullptr, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, nullptr, 0, path); + string result = (const char*)utf8_t(path); + result.transform("\\", "/"); + #elif defined(PLATFORM_MACOS) + string result = {Path::user(), "Library/Application Support/"}; + #else + string result; + if(const char* env = getenv("XDG_DATA_HOME")) { + result = string(env); + } else { + result = {Path::user(), ".local/share/"}; + } + #endif + if(!result) result = "."; + if(!result.endsWith("/")) result.append("/"); + return result; +} + +NALL_HEADER_INLINE auto sharedData() -> string { + #if defined(PLATFORM_WINDOWS) + wchar_t path[PATH_MAX] = L""; + SHGetFolderPathW(nullptr, CSIDL_COMMON_APPDATA | CSIDL_FLAG_CREATE, nullptr, 0, path); + string result = (const char*)utf8_t(path); + result.transform("\\", "/"); + #elif defined(PLATFORM_MACOS) + string result = "/Library/Application Support/"; + #else + string result = "/usr/share/"; + #endif + if(!result) result = "."; + if(!result.endsWith("/")) result.append("/"); + return result; +} + +NALL_HEADER_INLINE auto temporary() -> string { + #if defined(PLATFORM_WINDOWS) + wchar_t path[PATH_MAX] = L""; + GetTempPathW(PATH_MAX, path); + string result = (const char*)utf8_t(path); + result.transform("\\", "/"); + #elif defined(P_tmpdir) + string result = P_tmpdir; + #else + string result = "/tmp/"; + #endif + if(!result.endsWith("/")) result.append("/"); + return result; +} + +} diff --git a/waterbox/ares64/ares/nall/path.hpp b/waterbox/ares64/ares/nall/path.hpp index f63eed2dd2..b9b602a68d 100644 --- a/waterbox/ares64/ares/nall/path.hpp +++ b/waterbox/ares64/ares/nall/path.hpp @@ -24,73 +24,19 @@ inline auto real(string_view name) -> string { return result; } -inline auto program() -> string { - #if defined(PLATFORM_WINDOWS) - wchar_t path[PATH_MAX] = L""; - GetModuleFileName(nullptr, path, PATH_MAX); - string result = (const char*)utf8_t(path); - result.transform("\\", "/"); - return Path::real(result); - #else - Dl_info info; - dladdr((void*)&program, &info); - return Path::real(info.dli_fname); - #endif -} +auto program() -> string; // / // c:/ -inline auto root() -> string { - #if defined(PLATFORM_WINDOWS) - wchar_t path[PATH_MAX] = L""; - SHGetFolderPathW(nullptr, CSIDL_WINDOWS | CSIDL_FLAG_CREATE, nullptr, 0, path); - string result = (const char*)utf8_t(path); - result.transform("\\", "/"); - return slice(result, 0, 3); - #else - return "/"; - #endif -} +auto root() -> string; // /home/username/ // c:/users/username/ -inline auto user() -> string { - #if defined(PLATFORM_WINDOWS) - wchar_t path[PATH_MAX] = L""; - SHGetFolderPathW(nullptr, CSIDL_PROFILE | CSIDL_FLAG_CREATE, nullptr, 0, path); - string result = (const char*)utf8_t(path); - result.transform("\\", "/"); - #else - struct passwd* userinfo = getpwuid(getuid()); - string result = userinfo->pw_dir; - #endif - if(!result) result = "."; - if(!result.endsWith("/")) result.append("/"); - return result; -} +auto user() -> string; // /home/username/Desktop/ // c:/users/username/Desktop/ -inline auto desktop(string_view name = {}) -> string { - #if defined(PLATFORM_WINDOWS) - wchar_t path[PATH_MAX] = L""; - SHGetFolderPathW(nullptr, CSIDL_DESKTOP | CSIDL_FLAG_CREATE, nullptr, 0, path); - string result = (const char*)utf8_t(path); - result.transform("\\", "/"); - #elif defined(PLATFORM_MACOS) - string result = {user(), "Desktop/"}; - #else - string result; - if(const char *env = getenv("XDG_DESKTOP_DIR")) { - result = string(env); - } else { - result = {user(), "Desktop/"}; - } - #endif - if(!result) result = "."; - if(!result.endsWith("/")) result.append("/"); - return result.append(name); -} +auto desktop(string_view name = {}) -> string; //todo: MacOS uses the same location for userData() and userSettings() //... is there a better option here? @@ -98,85 +44,24 @@ inline auto desktop(string_view name = {}) -> string { // /home/username/.config/ // ~/Library/Application Support/ // c:/users/username/appdata/roaming/ -inline auto userSettings() -> string { - #if defined(PLATFORM_WINDOWS) - wchar_t path[PATH_MAX] = L""; - SHGetFolderPathW(nullptr, CSIDL_APPDATA | CSIDL_FLAG_CREATE, nullptr, 0, path); - string result = (const char*)utf8_t(path); - result.transform("\\", "/"); - #elif defined(PLATFORM_MACOS) - string result = {Path::user(), "Library/Application Support/"}; - #else - string result; - if(const char *env = getenv("XDG_CONFIG_HOME")) { - result = string(env); - } else { - result = {Path::user(), ".config/"}; - } - #endif - if(!result) result = "."; - if(!result.endsWith("/")) result.append("/"); - return result; -} +auto userSettings() -> string; // /home/username/.local/share/ // ~/Library/Application Support/ // c:/users/username/appdata/local/ -inline auto userData() -> string { - #if defined(PLATFORM_WINDOWS) - wchar_t path[PATH_MAX] = L""; - SHGetFolderPathW(nullptr, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, nullptr, 0, path); - string result = (const char*)utf8_t(path); - result.transform("\\", "/"); - #elif defined(PLATFORM_MACOS) - string result = {Path::user(), "Library/Application Support/"}; - #else - string result; - if(const char* env = getenv("XDG_DATA_HOME")) { - result = string(env); - } else { - result = {Path::user(), ".local/share/"}; - } - #endif - if(!result) result = "."; - if(!result.endsWith("/")) result.append("/"); - return result; -} +auto userData() -> string; // /usr/share // /Library/Application Support/ // c:/ProgramData/ -inline auto sharedData() -> string { - #if defined(PLATFORM_WINDOWS) - wchar_t path[PATH_MAX] = L""; - SHGetFolderPathW(nullptr, CSIDL_COMMON_APPDATA | CSIDL_FLAG_CREATE, nullptr, 0, path); - string result = (const char*)utf8_t(path); - result.transform("\\", "/"); - #elif defined(PLATFORM_MACOS) - string result = "/Library/Application Support/"; - #else - string result = "/usr/share/"; - #endif - if(!result) result = "."; - if(!result.endsWith("/")) result.append("/"); - return result; -} +auto sharedData() -> string; // /tmp // c:/users/username/AppData/Local/Temp/ -inline auto temporary() -> string { - #if defined(PLATFORM_WINDOWS) - wchar_t path[PATH_MAX] = L""; - GetTempPathW(PATH_MAX, path); - string result = (const char*)utf8_t(path); - result.transform("\\", "/"); - #elif defined(P_tmpdir) - string result = P_tmpdir; - #else - string result = "/tmp/"; - #endif - if(!result.endsWith("/")) result.append("/"); - return result; -} +auto temporary() -> string; } + +#if defined(NALL_HEADER_ONLY) + #include +#endif diff --git a/waterbox/ares64/ares/nall/platform.cpp b/waterbox/ares64/ares/nall/platform.cpp new file mode 100644 index 0000000000..0c21aa283f --- /dev/null +++ b/waterbox/ares64/ares/nall/platform.cpp @@ -0,0 +1,33 @@ +#include + +#if defined(PLATFORM_WINDOWS) + +#include + +NALL_HEADER_INLINE auto poll(struct pollfd fds[], unsigned long nfds, int timeout) -> int { return WSAPoll(fds, nfds, timeout); } + +namespace nall { + +NALL_HEADER_INLINE auto recv(int socket, void* buffer, size_t length, int flags) -> ssize_t { + return ::recv(socket, (char*)buffer, length, flags); +} + +NALL_HEADER_INLINE auto send(int socket, const void* buffer, size_t length, int flags) -> ssize_t { + return ::send(socket, (const char*)buffer, length, flags); +} + +NALL_HEADER_INLINE auto setsockopt(int socket, int level, int option_name, const void* option_value, int option_len) -> int { + return ::setsockopt(socket, level, option_name, (const char*)option_value, option_len); +} + +NALL_HEADER_INLINE auto usleep(unsigned int us) -> int { + if(us != 0) { + Sleep(us / 1000); + } + + return 0; +} + +} + +#endif diff --git a/waterbox/ares64/ares/nall/platform.hpp b/waterbox/ares64/ares/nall/platform.hpp index 9b7b0b035a..5fabcb2aed 100644 --- a/waterbox/ares64/ares/nall/platform.hpp +++ b/waterbox/ares64/ares/nall/platform.hpp @@ -9,18 +9,13 @@ namespace Math { } #if defined(PLATFORM_WINDOWS) - #include - #include - #include - #include - #include - #include + #if defined(NALL_HEADER_ONLY) + #include + #endif #include #include #include - #include - #include - #include + #include #include #endif @@ -39,9 +34,7 @@ namespace Math { #include #include #include -#include #include -#include #include #include @@ -49,6 +42,7 @@ namespace Math { #if !defined(PLATFORM_WINDOWS) #include #include + #include #include #include #include @@ -68,25 +62,21 @@ namespace Math { #define __has_builtin(x) 0 #endif -#if defined(COMPILER_MICROSOFT) - #define va_copy(dest, src) ((dest) = (src)) -#endif - #if defined(PLATFORM_WINDOWS) - #undef IN - #undef OUT - #undef interface #define dllexport __declspec(dllexport) #define MSG_NOSIGNAL 0 + #define PATH_MAX 260 - extern "C" { - using pollfd = WSAPOLLFD; - } + #if !defined(INVALID_HANDLE_VALUE) + #define INVALID_HANDLE_VALUE ((HANDLE)-1) + #endif + + typedef void* HANDLE; inline auto access(const char* path, int amode) -> int { return _waccess(nall::utf16_t(path), amode); } inline auto getcwd(char* buf, size_t size) -> char* { wchar_t wpath[PATH_MAX] = L""; if(!_wgetcwd(wpath, size)) return nullptr; strcpy(buf, nall::utf8_t(wpath)); return buf; } inline auto mkdir(const char* path, int mode) -> int { return _wmkdir(nall::utf16_t(path)); } - inline auto poll(struct pollfd fds[], unsigned long nfds, int timeout) -> int { return WSAPoll(fds, nfds, timeout); } + inline auto poll(struct pollfd fds[], unsigned long nfds, int timeout) -> int; inline auto putenv(const char* value) -> int { return _wputenv(nall::utf16_t(value)); } inline auto realpath(const char* file_name, char* resolved_name) -> char* { wchar_t wfile_name[PATH_MAX] = L""; if(!_wfullpath(wfile_name, nall::utf16_t(file_name), PATH_MAX)) return nullptr; strcpy(resolved_name, nall::utf8_t(wfile_name)); return resolved_name; } inline auto rename(const char* oldname, const char* newname) -> int { return _wrename(nall::utf16_t(oldname), nall::utf16_t(newname)); } @@ -94,17 +84,11 @@ namespace Math { namespace nall { //network functions take void*, not char*. this allows them to be used without casting - inline auto recv(int socket, void* buffer, size_t length, int flags) -> ssize_t { - return ::recv(socket, (char*)buffer, length, flags); - } + auto recv(int socket, void* buffer, size_t length, int flags) -> ssize_t; + auto send(int socket, const void* buffer, size_t length, int flags) -> ssize_t; + auto setsockopt(int socket, int level, int option_name, const void* option_value, int option_len) -> int; - inline auto send(int socket, const void* buffer, size_t length, int flags) -> ssize_t { - return ::send(socket, (const char*)buffer, length, flags); - } - - inline auto setsockopt(int socket, int level, int option_name, const void* option_value, socklen_t option_len) -> int { - return ::setsockopt(socket, level, option_name, (const char*)option_value, option_len); - } + auto usleep(unsigned int us) -> int; } #else #define dllexport @@ -132,6 +116,12 @@ namespace Math { #endif #define likely(expression) __builtin_expect(bool(expression), true) #define unlikely(expression) __builtin_expect(bool(expression), false) +#elif defined(COMPILER_MICROSOFT) + #define bswap16(value) _byteswap_ushort(value) + #define bswap32(value) _byteswap_ulong(value) + #define bswap64(value) _byteswap_uint64(value) + #define likely(expression) expression + #define unlikely(expression) expression #else inline auto bswap16(u16 value) -> u16 { return value << 8 | value >> 8; @@ -151,16 +141,21 @@ namespace Math { #define unlikely(expression) expression #endif -//notify the processor/operating system that this thread is currently awaiting an event (eg a spinloop) -//calling this function aims to avoid consuming 100% CPU resources on the active thread during spinloops -inline auto spinloop() -> void { - #if defined(COMPILER_CLANG) || defined(COMPILER_GCC) +namespace nall { + //notify the processor/operating system that this thread is currently awaiting an event (eg a spinloop) + //calling this function aims to avoid consuming 100% CPU resources on the active thread during spinloops + inline auto spinloop() -> void { #if defined(ARCHITECTURE_X86) || defined(ARCHITECTURE_AMD64) - __builtin_ia32_pause(); - return; + #if defined(COMPILER_CLANG) || defined(COMPILER_GCC) + __builtin_ia32_pause(); + return; + #elif defined(COMPILER_MICROSOFT) + _mm_pause(); + return; + #endif #endif - #endif - usleep(1); + usleep(1); + } } #if defined(PLATFORM_MACOS) && !defined(MSG_NOSIGNAL) @@ -184,6 +179,8 @@ inline auto spinloop() -> void { //P0627: [[unreachable]] -- impossible to simulate with identical syntax, must omit brackets ... #if defined(COMPILER_CLANG) || defined(COMPILER_GCC) #define unreachable __builtin_unreachable() +#elif defined(COMPILER_MICROSOFT) + #define unreachable __assume(0) #else #define unreachable throw #endif @@ -194,3 +191,7 @@ inline auto spinloop() -> void { #define export $export #define register $register + +#if defined(NALL_HEADER_ONLY) + #include +#endif diff --git a/waterbox/ares64/ares/nall/primitives/bit-field.hpp b/waterbox/ares64/ares/nall/primitives/bit-field.hpp index d2bd0d667d..ffbf3e51ed 100644 --- a/waterbox/ares64/ares/nall/primitives/bit-field.hpp +++ b/waterbox/ares64/ares/nall/primitives/bit-field.hpp @@ -18,6 +18,7 @@ template struct BitField { enum : type { mask = 1ull << shift }; BitField(const BitField&) = delete; + BitField(BitField&&) = default; auto& operator=(const BitField& source) { target = target & ~mask | (bool)source << shift; @@ -72,6 +73,7 @@ template struct BitField { void>>>>; BitField(const BitField&) = delete; + BitField(BitField&&) = default; auto& operator=(const BitField& source) { target = target & ~mask | (bool)source << shift; diff --git a/waterbox/ares64/ares/nall/primitives/bit-range.hpp b/waterbox/ares64/ares/nall/primitives/bit-range.hpp index ea9345c07c..ae979113ad 100644 --- a/waterbox/ares64/ares/nall/primitives/bit-range.hpp +++ b/waterbox/ares64/ares/nall/primitives/bit-range.hpp @@ -20,6 +20,7 @@ template struct BitRange { enum : u32 { shift = lo }; BitRange(const BitRange& source) = delete; + BitRange(BitRange&& source) = default; auto& operator=(const BitRange& source) { target = target & ~mask | ((source.target & source.mask) >> source.shift) << shift & mask; @@ -138,6 +139,7 @@ template struct DynamicBitRange { void>>>>; DynamicBitRange(const DynamicBitRange& source) = delete; + DynamicBitRange(DynamicBitRange&& source) = default; auto& operator=(const DynamicBitRange& source) { target = target & ~mask | ((source.target & source.mask) >> source.shift) << shift & mask; diff --git a/waterbox/ares64/ares/nall/primitives/literals.hpp b/waterbox/ares64/ares/nall/primitives/literals.hpp index 0e85233876..54df171039 100644 --- a/waterbox/ares64/ares/nall/primitives/literals.hpp +++ b/waterbox/ares64/ares/nall/primitives/literals.hpp @@ -1,6 +1,6 @@ #pragma once -namespace nall { +namespace nall::primitives { inline auto operator"" _b(unsigned long long value) { return boolean{value}; } inline auto operator"" _n(unsigned long long value) { return natural{value}; } diff --git a/waterbox/ares64/ares/nall/primitives/types.hpp b/waterbox/ares64/ares/nall/primitives/types.hpp index 74ca6a6ab3..33e3143804 100644 --- a/waterbox/ares64/ares/nall/primitives/types.hpp +++ b/waterbox/ares64/ares/nall/primitives/types.hpp @@ -1,6 +1,6 @@ #pragma once -namespace nall { +namespace nall::primitives { using boolean = Boolean; using natural = Natural<>; using integer = Integer<>; diff --git a/waterbox/ares64/ares/nall/priority-queue.hpp b/waterbox/ares64/ares/nall/priority-queue.hpp index 4b96079553..4afd9cfe6b 100644 --- a/waterbox/ares64/ares/nall/priority-queue.hpp +++ b/waterbox/ares64/ares/nall/priority-queue.hpp @@ -82,10 +82,15 @@ struct priority_queue { return nothing; } - auto remove(const T& event) -> void { + auto remove(const T& event) -> u32 { + u32 cycles = 0; for(u32 i = 0; i < size; i++) { - if(heap[i].event == event) heap[i].valid = false; + if(heap[i].event == event) { + heap[i].valid = false; + cycles = max(cycles, heap[i].clock - clock); + } } + return cycles; } auto serialize(serializer& s) -> void { diff --git a/waterbox/ares64/ares/nall/random.cpp b/waterbox/ares64/ares/nall/random.cpp new file mode 100644 index 0000000000..02ef580cf8 --- /dev/null +++ b/waterbox/ares64/ares/nall/random.cpp @@ -0,0 +1,40 @@ +#include + +#if defined(PLATFORM_LINUX) && __has_include() + #include +#elif defined(PLATFORM_ANDROID) && __has_include() + #include +#elif defined(PLATFORM_WINDOWS) && __has_include() + #include +#else + #include +#endif + +namespace nall { + +NALL_HEADER_INLINE auto RNGBase::randomSeed() -> u256 { + u256 seed = 0; + #if defined(PLATFORM_BSD) || defined(PLATFORM_MACOS) + for(u32 n : range(8)) seed = seed << 32 | (u32)arc4random(); + #elif defined(PLATFORM_LINUX) && __has_include() + getrandom(&seed, 32, GRND_NONBLOCK); + #elif defined(PLATFORM_ANDROID) && __has_include() + syscall(__NR_getrandom, &seed, 32, 0x0001); //GRND_NONBLOCK + #elif defined(PLATFORM_WINDOWS) && __has_include() + HCRYPTPROV provider; + if(CryptAcquireContext(&provider, nullptr, MS_STRONG_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { + CryptGenRandom(provider, 32, (BYTE*)&seed); + CryptReleaseContext(provider, 0); + } + #else + srand(time(nullptr)); + for(u32 n : range(32)) seed = seed << 8 | (u8)rand(); + if(auto fp = fopen("/dev/urandom", "rb")) { + fread(&seed, 32, 1, fp); + fclose(fp); + } + #endif + return seed; +} + +} diff --git a/waterbox/ares64/ares/nall/random.hpp b/waterbox/ares64/ares/nall/random.hpp index d93532f6ee..c8114ba285 100644 --- a/waterbox/ares64/ares/nall/random.hpp +++ b/waterbox/ares64/ares/nall/random.hpp @@ -9,19 +9,14 @@ #include #endif -#if defined(PLATFORM_LINUX) && __has_include() - #include -#elif defined(PLATFORM_ANDROID) && __has_include() - #include -#elif defined(PLATFORM_WINDOWS) && __has_include() - #include -#else - #include -#endif - namespace nall { -template struct RNG { +struct RNGBase { +protected: + auto randomSeed() -> u256; +}; + +template struct RNG : RNGBase { template auto random() -> T { u64 value = 0; for(u32 n : range((sizeof(T) + 3) / 4)) { @@ -37,32 +32,6 @@ template struct RNG { if(value >= threshold) return value % range; } } - -protected: - auto randomSeed() -> u256 { - u256 seed = 0; - #if defined(PLATFORM_BSD) || defined(PLATFORM_MACOS) - for(u32 n : range(8)) seed = seed << 32 | (u32)arc4random(); - #elif defined(PLATFORM_LINUX) && __has_include() - getrandom(&seed, 32, GRND_NONBLOCK); - #elif defined(PLATFORM_ANDROID) && __has_include() - syscall(__NR_getrandom, &seed, 32, 0x0001); //GRND_NONBLOCK - #elif defined(PLATFORM_WINDOWS) && __has_include() - HCRYPTPROV provider; - if(CryptAcquireContext(&provider, nullptr, MS_STRONG_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { - CryptGenRandom(provider, 32, (BYTE*)&seed); - CryptReleaseContext(provider, 0); - } - #else - srand(time(nullptr)); - for(u32 n : range(32)) seed = seed << 8 | (u8)rand(); - if(auto fp = fopen("/dev/urandom", "rb")) { - fread(&seed, 32, 1, fp); - fclose(fp); - } - #endif - return seed; - } }; namespace PRNG { @@ -170,3 +139,7 @@ template inline auto random() -> T { } } + +#if defined(NALL_HEADER_ONLY) + #include +#endif diff --git a/waterbox/ares64/ares/nall/recompiler/amd64/encoder-instructions.hpp b/waterbox/ares64/ares/nall/recompiler/amd64/encoder-instructions.hpp index 9985c4112c..54aecf3804 100644 --- a/waterbox/ares64/ares/nall/recompiler/amd64/encoder-instructions.hpp +++ b/waterbox/ares64/ares/nall/recompiler/amd64/encoder-instructions.hpp @@ -150,13 +150,13 @@ if(ds.reg == rsp || ds.reg == r12) emit.sib(0, 4, 4); alwaysinline auto adc(reg8 rt, dis ds) { op(0x12); } alwaysinline auto add(reg8 rt, dis ds) { op(0x02); } - alwaysinline auto and(reg8 rt, dis ds) { op(0x22); } + alwaysinline auto and_(reg8 rt, dis ds) { op(0x22); } alwaysinline auto cmp(reg8 rt, dis ds) { op(0x3a); } alwaysinline auto mov(reg8 rt, dis ds) { op(0x8a); } - alwaysinline auto or (reg8 rt, dis ds) { op(0x0a); } + alwaysinline auto or_(reg8 rt, dis ds) { op(0x0a); } alwaysinline auto sbb(reg8 rt, dis ds) { op(0x1a); } alwaysinline auto sub(reg8 rt, dis ds) { op(0x2a); } - alwaysinline auto xor(reg8 rt, dis ds) { op(0x32); } + alwaysinline auto xor_(reg8 rt, dis ds) { op(0x32); } #undef op //op reg8,[reg64+imm8] @@ -168,13 +168,13 @@ emit.byte(ds.imm); alwaysinline auto adc(reg8 rt, dis8 ds) { op(0x12); } alwaysinline auto add(reg8 rt, dis8 ds) { op(0x02); } - alwaysinline auto and(reg8 rt, dis8 ds) { op(0x22); } + alwaysinline auto and_(reg8 rt, dis8 ds) { op(0x22); } alwaysinline auto cmp(reg8 rt, dis8 ds) { op(0x3a); } alwaysinline auto mov(reg8 rt, dis8 ds) { op(0x8a); } - alwaysinline auto or (reg8 rt, dis8 ds) { op(0x0a); } + alwaysinline auto or_(reg8 rt, dis8 ds) { op(0x0a); } alwaysinline auto sbb(reg8 rt, dis8 ds) { op(0x1a); } alwaysinline auto sub(reg8 rt, dis8 ds) { op(0x2a); } - alwaysinline auto xor(reg8 rt, dis8 ds) { op(0x32); } + alwaysinline auto xor_(reg8 rt, dis8 ds) { op(0x32); } #undef op //op reg32,[reg64] @@ -185,13 +185,13 @@ if(ds.reg == rsp || ds.reg == r12) emit.sib(0, 4, 4); alwaysinline auto adc(reg32 rt, dis ds) { op(0x13); } alwaysinline auto add(reg32 rt, dis ds) { op(0x03); } - alwaysinline auto and(reg32 rt, dis ds) { op(0x23); } + alwaysinline auto and_(reg32 rt, dis ds) { op(0x23); } alwaysinline auto cmp(reg32 rt, dis ds) { op(0x3b); } alwaysinline auto mov(reg32 rt, dis ds) { op(0x8b); } - alwaysinline auto or (reg32 rt, dis ds) { op(0x0b); } + alwaysinline auto or_(reg32 rt, dis ds) { op(0x0b); } alwaysinline auto sbb(reg32 rt, dis ds) { op(0x1b); } alwaysinline auto sub(reg32 rt, dis ds) { op(0x2b); } - alwaysinline auto xor(reg32 rt, dis ds) { op(0x33); } + alwaysinline auto xor_(reg32 rt, dis ds) { op(0x33); } #undef op //op reg32,[reg64+imm8] @@ -203,13 +203,13 @@ emit.byte(ds.imm); alwaysinline auto adc(reg32 rt, dis8 ds) { op(0x13); } alwaysinline auto add(reg32 rt, dis8 ds) { op(0x03); } - alwaysinline auto and(reg32 rt, dis8 ds) { op(0x23); } + alwaysinline auto and_(reg32 rt, dis8 ds) { op(0x23); } alwaysinline auto cmp(reg32 rt, dis8 ds) { op(0x3b); } alwaysinline auto mov(reg32 rt, dis8 ds) { op(0x8b); } - alwaysinline auto or (reg32 rt, dis8 ds) { op(0x0b); } + alwaysinline auto or_(reg32 rt, dis8 ds) { op(0x0b); } alwaysinline auto sbb(reg32 rt, dis8 ds) { op(0x1b); } alwaysinline auto sub(reg32 rt, dis8 ds) { op(0x2b); } - alwaysinline auto xor(reg32 rt, dis8 ds) { op(0x33); } + alwaysinline auto xor_(reg32 rt, dis8 ds) { op(0x33); } #undef op //op reg64,[reg64] @@ -220,13 +220,13 @@ if(ds.reg == rsp || ds.reg == r12) emit.sib(0, 4, 4); alwaysinline auto adc(reg64 rt, dis ds) { op(0x13); } alwaysinline auto add(reg64 rt, dis ds) { op(0x03); } - alwaysinline auto and(reg64 rt, dis ds) { op(0x23); } + alwaysinline auto and_(reg64 rt, dis ds) { op(0x23); } alwaysinline auto cmp(reg64 rt, dis ds) { op(0x3b); } alwaysinline auto mov(reg64 rt, dis ds) { op(0x8b); } - alwaysinline auto or (reg64 rt, dis ds) { op(0x0b); } + alwaysinline auto or_(reg64 rt, dis ds) { op(0x0b); } alwaysinline auto sbb(reg64 rt, dis ds) { op(0x1b); } alwaysinline auto sub(reg64 rt, dis ds) { op(0x2b); } - alwaysinline auto xor(reg64 rt, dis ds) { op(0x33); } + alwaysinline auto xor_(reg64 rt, dis ds) { op(0x33); } #undef op //op reg64,[reg64+imm8] @@ -238,13 +238,13 @@ emit.byte(ds.imm); alwaysinline auto adc(reg64 rt, dis8 ds) { op(0x13); } alwaysinline auto add(reg64 rt, dis8 ds) { op(0x03); } - alwaysinline auto and(reg64 rt, dis8 ds) { op(0x23); } + alwaysinline auto and_(reg64 rt, dis8 ds) { op(0x23); } alwaysinline auto cmp(reg64 rt, dis8 ds) { op(0x3b); } alwaysinline auto mov(reg64 rt, dis8 ds) { op(0x8b); } - alwaysinline auto or (reg64 rt, dis8 ds) { op(0x0b); } + alwaysinline auto or_(reg64 rt, dis8 ds) { op(0x0b); } alwaysinline auto sbb(reg64 rt, dis8 ds) { op(0x1b); } alwaysinline auto sub(reg64 rt, dis8 ds) { op(0x2b); } - alwaysinline auto xor(reg64 rt, dis8 ds) { op(0x33); } + alwaysinline auto xor_(reg64 rt, dis8 ds) { op(0x33); } #undef op //op reg64,[reg64+imm32] @@ -256,13 +256,13 @@ emit.dword(ds.imm); alwaysinline auto adc(reg64 rt, dis32 ds) { op(0x13); } alwaysinline auto add(reg64 rt, dis32 ds) { op(0x03); } - alwaysinline auto and(reg64 rt, dis32 ds) { op(0x23); } + alwaysinline auto and_(reg64 rt, dis32 ds) { op(0x23); } alwaysinline auto cmp(reg64 rt, dis32 ds) { op(0x3b); } alwaysinline auto mov(reg64 rt, dis32 ds) { op(0x8b); } - alwaysinline auto or (reg64 rt, dis32 ds) { op(0x0b); } + alwaysinline auto or_(reg64 rt, dis32 ds) { op(0x0b); } alwaysinline auto sbb(reg64 rt, dis32 ds) { op(0x1b); } alwaysinline auto sub(reg64 rt, dis32 ds) { op(0x2b); } - alwaysinline auto xor(reg64 rt, dis32 ds) { op(0x33); } + alwaysinline auto xor_(reg64 rt, dis32 ds) { op(0x33); } #undef op //op [reg64+imm8],reg8 @@ -274,13 +274,13 @@ emit.byte(dt.imm); alwaysinline auto adc(dis8 dt, reg8 rs) { op(0x10); } alwaysinline auto add(dis8 dt, reg8 rs) { op(0x00); } - alwaysinline auto and(dis8 dt, reg8 rs) { op(0x20); } + alwaysinline auto and_(dis8 dt, reg8 rs) { op(0x20); } alwaysinline auto cmp(dis8 dt, reg8 rs) { op(0x38); } alwaysinline auto mov(dis8 dt, reg8 rs) { op(0x88); } - alwaysinline auto or (dis8 dt, reg8 rs) { op(0x08); } + alwaysinline auto or_(dis8 dt, reg8 rs) { op(0x08); } alwaysinline auto sbb(dis8 dt, reg8 rs) { op(0x18); } alwaysinline auto sub(dis8 dt, reg8 rs) { op(0x28); } - alwaysinline auto xor(dis8 dt, reg8 rs) { op(0x30); } + alwaysinline auto xor_(dis8 dt, reg8 rs) { op(0x30); } #undef op //op reg64,imm32 @@ -290,12 +290,12 @@ emit.modrm(3, group, rt & 7); \ emit.dword(is.data); alwaysinline auto add(reg64 rt, imm32 is) { op(0); } - alwaysinline auto or (reg64 rt, imm32 is) { op(1); } + alwaysinline auto or_(reg64 rt, imm32 is) { op(1); } alwaysinline auto adc(reg64 rt, imm32 is) { op(2); } alwaysinline auto sbb(reg64 rt, imm32 is) { op(3); } - alwaysinline auto and(reg64 rt, imm32 is) { op(4); } + alwaysinline auto and_(reg64 rt, imm32 is) { op(4); } alwaysinline auto sub(reg64 rt, imm32 is) { op(5); } - alwaysinline auto xor(reg64 rt, imm32 is) { op(6); } + alwaysinline auto xor_(reg64 rt, imm32 is) { op(6); } alwaysinline auto cmp(reg64 rt, imm32 is) { op(7); } #undef op @@ -325,13 +325,13 @@ if(dt.reg == rsp || dt.reg == r12) emit.sib(0, 4, 4); alwaysinline auto adc(dis dt, reg32 rs) { op(0x11); } alwaysinline auto add(dis dt, reg32 rs) { op(0x01); } - alwaysinline auto and(dis dt, reg32 rs) { op(0x21); } + alwaysinline auto and_(dis dt, reg32 rs) { op(0x21); } alwaysinline auto cmp(dis dt, reg32 rs) { op(0x39); } alwaysinline auto mov(dis dt, reg32 rs) { op(0x89); } - alwaysinline auto or (dis dt, reg32 rs) { op(0x09); } + alwaysinline auto or_(dis dt, reg32 rs) { op(0x09); } alwaysinline auto sbb(dis dt, reg32 rs) { op(0x19); } alwaysinline auto sub(dis dt, reg32 rs) { op(0x29); } - alwaysinline auto xor(dis dt, reg32 rs) { op(0x31); } + alwaysinline auto xor_(dis dt, reg32 rs) { op(0x31); } #undef op //op [reg64+imm8],reg32 @@ -343,13 +343,13 @@ emit.byte(dt.imm); alwaysinline auto adc(dis8 dt, reg32 rs) { op(0x11); } alwaysinline auto add(dis8 dt, reg32 rs) { op(0x01); } - alwaysinline auto and(dis8 dt, reg32 rs) { op(0x21); } + alwaysinline auto and_(dis8 dt, reg32 rs) { op(0x21); } alwaysinline auto cmp(dis8 dt, reg32 rs) { op(0x39); } alwaysinline auto mov(dis8 dt, reg32 rs) { op(0x89); } - alwaysinline auto or (dis8 dt, reg32 rs) { op(0x09); } + alwaysinline auto or_(dis8 dt, reg32 rs) { op(0x09); } alwaysinline auto sbb(dis8 dt, reg32 rs) { op(0x19); } alwaysinline auto sub(dis8 dt, reg32 rs) { op(0x29); } - alwaysinline auto xor(dis8 dt, reg32 rs) { op(0x31); } + alwaysinline auto xor_(dis8 dt, reg32 rs) { op(0x31); } #undef op //op [reg64],reg64 @@ -360,13 +360,13 @@ if(dt.reg == rsp || dt.reg == r12) emit.sib(0, 4, 4); alwaysinline auto adc(dis dt, reg64 rs) { op(0x11); } alwaysinline auto add(dis dt, reg64 rs) { op(0x01); } - alwaysinline auto and(dis dt, reg64 rs) { op(0x21); } + alwaysinline auto and_(dis dt, reg64 rs) { op(0x21); } alwaysinline auto cmp(dis dt, reg64 rs) { op(0x39); } alwaysinline auto mov(dis dt, reg64 rs) { op(0x89); } - alwaysinline auto or (dis dt, reg64 rs) { op(0x09); } + alwaysinline auto or_(dis dt, reg64 rs) { op(0x09); } alwaysinline auto sbb(dis dt, reg64 rs) { op(0x19); } alwaysinline auto sub(dis dt, reg64 rs) { op(0x29); } - alwaysinline auto xor(dis dt, reg64 rs) { op(0x31); } + alwaysinline auto xor_(dis dt, reg64 rs) { op(0x31); } #undef op //op [reg64+imm8],reg64 @@ -378,13 +378,13 @@ emit.byte(dt.imm); alwaysinline auto adc(dis8 dt, reg64 rs) { op(0x11); } alwaysinline auto add(dis8 dt, reg64 rs) { op(0x01); } - alwaysinline auto and(dis8 dt, reg64 rs) { op(0x21); } + alwaysinline auto and_(dis8 dt, reg64 rs) { op(0x21); } alwaysinline auto cmp(dis8 dt, reg64 rs) { op(0x39); } alwaysinline auto mov(dis8 dt, reg64 rs) { op(0x89); } - alwaysinline auto or (dis8 dt, reg64 rs) { op(0x09); } + alwaysinline auto or_(dis8 dt, reg64 rs) { op(0x09); } alwaysinline auto sbb(dis8 dt, reg64 rs) { op(0x19); } alwaysinline auto sub(dis8 dt, reg64 rs) { op(0x29); } - alwaysinline auto xor(dis8 dt, reg64 rs) { op(0x31); } + alwaysinline auto xor_(dis8 dt, reg64 rs) { op(0x31); } #undef op //op [reg64+imm32],reg64 @@ -396,13 +396,13 @@ emit.dword(dt.imm); alwaysinline auto adc(dis32 dt, reg64 rs) { op(0x11); } alwaysinline auto add(dis32 dt, reg64 rs) { op(0x01); } - alwaysinline auto and(dis32 dt, reg64 rs) { op(0x21); } + alwaysinline auto and_(dis32 dt, reg64 rs) { op(0x21); } alwaysinline auto cmp(dis32 dt, reg64 rs) { op(0x39); } alwaysinline auto mov(dis32 dt, reg64 rs) { op(0x89); } - alwaysinline auto or (dis32 dt, reg64 rs) { op(0x09); } + alwaysinline auto or_(dis32 dt, reg64 rs) { op(0x09); } alwaysinline auto sbb(dis32 dt, reg64 rs) { op(0x19); } alwaysinline auto sub(dis32 dt, reg64 rs) { op(0x29); } - alwaysinline auto xor(dis32 dt, reg64 rs) { op(0x31); } + alwaysinline auto xor_(dis32 dt, reg64 rs) { op(0x31); } #undef op //op reg32,reg8 @@ -581,14 +581,14 @@ emit.modrm(3, rs & 7, rt & 7); alwaysinline auto adc (reg8 rt, reg8 rs) { op(0x10); } alwaysinline auto add (reg8 rt, reg8 rs) { op(0x00); } - alwaysinline auto and (reg8 rt, reg8 rs) { op(0x20); } + alwaysinline auto and_(reg8 rt, reg8 rs) { op(0x20); } alwaysinline auto cmp (reg8 rt, reg8 rs) { op(0x38); } alwaysinline auto mov (reg8 rt, reg8 rs) { op(0x88); } - alwaysinline auto or (reg8 rt, reg8 rs) { op(0x08); } + alwaysinline auto or_ (reg8 rt, reg8 rs) { op(0x08); } alwaysinline auto sbb (reg8 rt, reg8 rs) { op(0x18); } alwaysinline auto sub (reg8 rt, reg8 rs) { op(0x28); } alwaysinline auto test(reg8 rt, reg8 rs) { op(0x84); } - alwaysinline auto xor (reg8 rt, reg8 rs) { op(0x30); } + alwaysinline auto xor_(reg8 rt, reg8 rs) { op(0x30); } #undef op #define op(code) \ @@ -598,14 +598,14 @@ emit.modrm(3, rs & 7, rt & 7); alwaysinline auto adc (reg16 rt, reg16 rs) { op(0x11); } alwaysinline auto add (reg16 rt, reg16 rs) { op(0x01); } - alwaysinline auto and (reg16 rt, reg16 rs) { op(0x21); } + alwaysinline auto and_(reg16 rt, reg16 rs) { op(0x21); } alwaysinline auto cmp (reg16 rt, reg16 rs) { op(0x39); } alwaysinline auto mov (reg16 rt, reg16 rs) { op(0x89); } - alwaysinline auto or (reg16 rt, reg16 rs) { op(0x09); } + alwaysinline auto or_ (reg16 rt, reg16 rs) { op(0x09); } alwaysinline auto sbb (reg16 rt, reg16 rs) { op(0x19); } alwaysinline auto sub (reg16 rt, reg16 rs) { op(0x29); } alwaysinline auto test(reg16 rt, reg16 rs) { op(0x85); } - alwaysinline auto xor (reg16 rt, reg16 rs) { op(0x31); } + alwaysinline auto xor_(reg16 rt, reg16 rs) { op(0x31); } #undef op #define op(code) \ @@ -614,14 +614,14 @@ emit.modrm(3, rs & 7, rt & 7); alwaysinline auto adc (reg32 rt, reg32 rs) { op(0x11); } alwaysinline auto add (reg32 rt, reg32 rs) { op(0x01); } - alwaysinline auto and (reg32 rt, reg32 rs) { op(0x21); } + alwaysinline auto and_(reg32 rt, reg32 rs) { op(0x21); } alwaysinline auto cmp (reg32 rt, reg32 rs) { op(0x39); } alwaysinline auto mov (reg32 rt, reg32 rs) { op(0x89); } - alwaysinline auto or (reg32 rt, reg32 rs) { op(0x09); } + alwaysinline auto or_ (reg32 rt, reg32 rs) { op(0x09); } alwaysinline auto sbb (reg32 rt, reg32 rs) { op(0x19); } alwaysinline auto sub (reg32 rt, reg32 rs) { op(0x29); } alwaysinline auto test(reg32 rt, reg32 rs) { op(0x85); } - alwaysinline auto xor (reg32 rt, reg32 rs) { op(0x31); } + alwaysinline auto xor_(reg32 rt, reg32 rs) { op(0x31); } #undef op #define op(code) \ @@ -630,14 +630,14 @@ emit.modrm(3, rs & 7, rt & 7); alwaysinline auto adc (reg64 rt, reg64 rs) { op(0x11); } alwaysinline auto add (reg64 rt, reg64 rs) { op(0x01); } - alwaysinline auto and (reg64 rt, reg64 rs) { op(0x21); } + alwaysinline auto and_(reg64 rt, reg64 rs) { op(0x21); } alwaysinline auto cmp (reg64 rt, reg64 rs) { op(0x39); } alwaysinline auto mov (reg64 rt, reg64 rs) { op(0x89); } - alwaysinline auto or (reg64 rt, reg64 rs) { op(0x09); } + alwaysinline auto or_ (reg64 rt, reg64 rs) { op(0x09); } alwaysinline auto sbb (reg64 rt, reg64 rs) { op(0x19); } alwaysinline auto sub (reg64 rt, reg64 rs) { op(0x29); } alwaysinline auto test(reg64 rt, reg64 rs) { op(0x85); } - alwaysinline auto xor (reg64 rt, reg64 rs) { op(0x31); } + alwaysinline auto xor_(reg64 rt, reg64 rs) { op(0x31); } #undef op #define op(code) \ @@ -647,12 +647,12 @@ emit.byte(is.data); alwaysinline auto adc(reg32 rt, imm8 is) { op(2); } alwaysinline auto add(reg32 rt, imm8 is) { op(0); } - alwaysinline auto and(reg32 rt, imm8 is) { op(4); } + alwaysinline auto and_(reg32 rt, imm8 is) { op(4); } alwaysinline auto cmp(reg32 rt, imm8 is) { op(7); } - alwaysinline auto or (reg32 rt, imm8 is) { op(1); } + alwaysinline auto or_(reg32 rt, imm8 is) { op(1); } alwaysinline auto sbb(reg32 rt, imm8 is) { op(3); } alwaysinline auto sub(reg32 rt, imm8 is) { op(5); } - alwaysinline auto xor(reg32 rt, imm8 is) { op(6); } + alwaysinline auto xor_(reg32 rt, imm8 is) { op(6); } #undef op #define op(code) \ @@ -662,12 +662,12 @@ emit.byte(is.data); alwaysinline auto adc(reg64 rt, imm8 is) { op(2); } alwaysinline auto add(reg64 rt, imm8 is) { op(0); } - alwaysinline auto and(reg64 rt, imm8 is) { op(4); } + alwaysinline auto and_(reg64 rt, imm8 is) { op(4); } alwaysinline auto cmp(reg64 rt, imm8 is) { op(7); } - alwaysinline auto or (reg64 rt, imm8 is) { op(1); } + alwaysinline auto or_(reg64 rt, imm8 is) { op(1); } alwaysinline auto sbb(reg64 rt, imm8 is) { op(3); } alwaysinline auto sub(reg64 rt, imm8 is) { op(5); } - alwaysinline auto xor(reg64 rt, imm8 is) { op(6); } + alwaysinline auto xor_(reg64 rt, imm8 is) { op(6); } #undef op #define op(code, group) \ @@ -682,12 +682,12 @@ } alwaysinline auto adc(reg8 rt, imm8 is) { op(0x14, 2); } alwaysinline auto add(reg8 rt, imm8 is) { op(0x04, 0); } - alwaysinline auto and(reg8 rt, imm8 is) { op(0x24, 4); } + alwaysinline auto and_(reg8 rt, imm8 is) { op(0x24, 4); } alwaysinline auto cmp(reg8 rt, imm8 is) { op(0x3c, 7); } - alwaysinline auto or (reg8 rt, imm8 is) { op(0x0c, 1); } + alwaysinline auto or_(reg8 rt, imm8 is) { op(0x0c, 1); } alwaysinline auto sbb(reg8 rt, imm8 is) { op(0x1c, 3); } alwaysinline auto sub(reg8 rt, imm8 is) { op(0x2c, 5); } - alwaysinline auto xor(reg8 rt, imm8 is) { op(0x34, 6); } + alwaysinline auto xor_(reg8 rt, imm8 is) { op(0x34, 6); } #undef op #define op(code, group) \ @@ -702,19 +702,19 @@ } alwaysinline auto adc(reg32 rt, imm32 is) { op(0x15, 2); } alwaysinline auto add(reg32 rt, imm32 is) { op(0x05, 0); } - alwaysinline auto and(reg32 rt, imm32 is) { op(0x25, 4); } + alwaysinline auto and_(reg32 rt, imm32 is) { op(0x25, 4); } alwaysinline auto cmp(reg32 rt, imm32 is) { op(0x3d, 7); } - alwaysinline auto or (reg32 rt, imm32 is) { op(0x0d, 1); } + alwaysinline auto or_(reg32 rt, imm32 is) { op(0x0d, 1); } alwaysinline auto sbb(reg32 rt, imm32 is) { op(0x1d, 3); } alwaysinline auto sub(reg32 rt, imm32 is) { op(0x2d, 5); } - alwaysinline auto xor(reg32 rt, imm32 is) { op(0x35, 6); } + alwaysinline auto xor_(reg32 rt, imm32 is) { op(0x35, 6); } #undef op #define op(code) \ emit.rex(0, 0, 0, rt & 8); \ emit.byte(0xf7); \ emit.modrm(3, code, rt & 7); - alwaysinline auto not (reg32 rt) { op(2); } + alwaysinline auto not_(reg32 rt) { op(2); } alwaysinline auto neg (reg32 rt) { op(3); } alwaysinline auto mul (reg32 rt) { op(4); } alwaysinline auto imul(reg32 rt) { op(5); } @@ -726,7 +726,7 @@ emit.rex(1, 0, 0, rt & 8); \ emit.byte(0xf7); \ emit.modrm(3, code, rt & 7); - alwaysinline auto not (reg64 rt) { op(2); } + alwaysinline auto not_(reg64 rt) { op(2); } alwaysinline auto neg (reg64 rt) { op(3); } alwaysinline auto mul (reg64 rt) { op(4); } alwaysinline auto imul(reg64 rt) { op(5); } diff --git a/waterbox/ares64/ares/nall/recompiler/generic/encoder-instructions.hpp b/waterbox/ares64/ares/nall/recompiler/generic/encoder-instructions.hpp index a37a6b5632..aab3b71e00 100644 --- a/waterbox/ares64/ares/nall/recompiler/generic/encoder-instructions.hpp +++ b/waterbox/ares64/ares/nall/recompiler/generic/encoder-instructions.hpp @@ -30,8 +30,6 @@ OP1(mov64_s16, MOV_S16) OP1(mov64_u32, MOV_U32) OP1(mov64_s32, MOV_S32) - OP1(not32, NOT32) - OP1(not64, NOT) #undef OP1 //2 operand instructions @@ -71,10 +69,20 @@ OP2(xor64, XOR) OP2(shl32, SHL32) OP2(shl64, SHL) + OP2(mshl32, MSHL32) + OP2(mshl64, MSHL) OP2(lshr32, LSHR32) OP2(lshr64, LSHR) + OP2(mlshr32, MLSHR32) + OP2(mlshr64, MLSHR) OP2(ashr32, ASHR32) OP2(ashr64, ASHR) + OP2(mashr32, MASHR32) + OP2(mashr64, MASHR) + OP2(rotl32, ROTL32) + OP2(rotl64, ROTL) + OP2(rotr32, ROTR32) + OP2(rotr64, ROTR) #undef OP2 //compare instructions diff --git a/waterbox/ares64/ares/nall/recompiler/generic/generic.hpp b/waterbox/ares64/ares/nall/recompiler/generic/generic.hpp index 28e7b2125c..8872c460d2 100644 --- a/waterbox/ares64/ares/nall/recompiler/generic/generic.hpp +++ b/waterbox/ares64/ares/nall/recompiler/generic/generic.hpp @@ -3,6 +3,8 @@ #if defined(SLJIT) namespace nall::recompiler { struct generic { + static constexpr bool supported = Architecture::amd64 | Architecture::arm64 | Architecture::ppc64; + bump_allocator& allocator; sljit_compiler* compiler = nullptr; sljit_label* epilogue = nullptr; diff --git a/waterbox/ares64/ares/nall/run.cpp b/waterbox/ares64/ares/nall/run.cpp new file mode 100644 index 0000000000..a4f566f5b6 --- /dev/null +++ b/waterbox/ares64/ares/nall/run.cpp @@ -0,0 +1,102 @@ +#include +#include + +#if defined(PLATFORM_WINDOWS) + #include +#endif + +namespace nall { + +#if defined(PLATFORM_WINDOWS) + +NALL_HEADER_INLINE auto execute(const string& name, vector argl) -> execute_result_t { + for(auto& arg : argl) if(arg.find(" ")) arg = {"\"", arg, "\""}; + string arguments = argl.merge(" "); + + SECURITY_ATTRIBUTES sa; + ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES)); + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.bInheritHandle = true; + sa.lpSecurityDescriptor = nullptr; + + HANDLE stdoutRead; + HANDLE stdoutWrite; + if(!CreatePipe(&stdoutRead, &stdoutWrite, &sa, 0)) return {}; + if(!SetHandleInformation(stdoutRead, HANDLE_FLAG_INHERIT, 0)) return {}; + + HANDLE stderrRead; + HANDLE stderrWrite; + if(!CreatePipe(&stderrRead, &stderrWrite, &sa, 0)) return {}; + if(!SetHandleInformation(stderrRead, HANDLE_FLAG_INHERIT, 0)) return {}; + + HANDLE stdinRead; + HANDLE stdinWrite; + if(!CreatePipe(&stdinRead, &stdinWrite, &sa, 0)) return {}; + if(!SetHandleInformation(stdinWrite, HANDLE_FLAG_INHERIT, 0)) return {}; + + STARTUPINFO si; + ZeroMemory(&si, sizeof(STARTUPINFO)); + si.cb = sizeof(STARTUPINFO); + si.hStdOutput = stdoutWrite; + si.hStdError = stderrWrite; + si.hStdInput = stdinRead; + si.dwFlags = STARTF_USESTDHANDLES; + + PROCESS_INFORMATION pi; + ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); + + if(!CreateProcess( + nullptr, utf16_t(arguments), + nullptr, nullptr, true, CREATE_NO_WINDOW, + nullptr, nullptr, &si, &pi + )) return {}; + + DWORD exitCode = EXIT_FAILURE; + if(WaitForSingleObject(pi.hProcess, INFINITE)) return {}; + if(!GetExitCodeProcess(pi.hProcess, &exitCode)) return {}; + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + + char buffer[256]; + execute_result_t result; + result.code = exitCode; + + while(true) { + DWORD read, available, remaining; + if(!PeekNamedPipe(stdoutRead, nullptr, sizeof(buffer), &read, &available, &remaining)) break; + if(read == 0) break; + + if(!ReadFile(stdoutRead, buffer, sizeof(buffer), &read, nullptr)) break; + if(read == 0) break; + + auto offset = result.output.size(); + result.output.resize(offset + read); + memory::copy(result.output.get() + offset, buffer, read); + } + + while(true) { + DWORD read, available, remaining; + if(!PeekNamedPipe(stderrRead, nullptr, sizeof(buffer), &read, &available, &remaining)) break; + if(read == 0) break; + + if(!ReadFile(stderrRead, buffer, sizeof(buffer), &read, nullptr)) break; + if(read == 0) break; + + auto offset = result.error.size(); + result.error.resize(offset + read); + memory::copy(result.error.get() + offset, buffer, read); + } + + return result; +} + +NALL_HEADER_INLINE auto invoke(const string& name, vector argl) -> void { + for(auto& arg : argl) if(arg.find(" ")) arg = {"\"", arg, "\""}; + string arguments = argl.merge(" "); + string directory = Path::program().replace("/", "\\"); + ShellExecute(nullptr, nullptr, utf16_t(name), utf16_t(arguments), utf16_t(directory), SW_SHOWNORMAL); +} + +#endif + +} diff --git a/waterbox/ares64/ares/nall/run.hpp b/waterbox/ares64/ares/nall/run.hpp index 17a2733f3b..0dae8713ac 100644 --- a/waterbox/ares64/ares/nall/run.hpp +++ b/waterbox/ares64/ares/nall/run.hpp @@ -110,94 +110,18 @@ template inline auto invoke(const string& name, P&&... p) -> void #elif defined(PLATFORM_WINDOWS) +auto execute(const string& name, vector argl) -> execute_result_t; + template inline auto execute(const string& name, P&&... p) -> execute_result_t { vector argl(name, std::forward

(p)...); - for(auto& arg : argl) if(arg.find(" ")) arg = {"\"", arg, "\""}; - string arguments = argl.merge(" "); - - SECURITY_ATTRIBUTES sa; - ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES)); - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.bInheritHandle = true; - sa.lpSecurityDescriptor = nullptr; - - HANDLE stdoutRead; - HANDLE stdoutWrite; - if(!CreatePipe(&stdoutRead, &stdoutWrite, &sa, 0)) return {}; - if(!SetHandleInformation(stdoutRead, HANDLE_FLAG_INHERIT, 0)) return {}; - - HANDLE stderrRead; - HANDLE stderrWrite; - if(!CreatePipe(&stderrRead, &stderrWrite, &sa, 0)) return {}; - if(!SetHandleInformation(stderrRead, HANDLE_FLAG_INHERIT, 0)) return {}; - - HANDLE stdinRead; - HANDLE stdinWrite; - if(!CreatePipe(&stdinRead, &stdinWrite, &sa, 0)) return {}; - if(!SetHandleInformation(stdinWrite, HANDLE_FLAG_INHERIT, 0)) return {}; - - STARTUPINFO si; - ZeroMemory(&si, sizeof(STARTUPINFO)); - si.cb = sizeof(STARTUPINFO); - si.hStdOutput = stdoutWrite; - si.hStdError = stderrWrite; - si.hStdInput = stdinRead; - si.dwFlags = STARTF_USESTDHANDLES; - - PROCESS_INFORMATION pi; - ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); - - if(!CreateProcess( - nullptr, utf16_t(arguments), - nullptr, nullptr, true, CREATE_NO_WINDOW, - nullptr, nullptr, &si, &pi - )) return {}; - - DWORD exitCode = EXIT_FAILURE; - if(WaitForSingleObject(pi.hProcess, INFINITE)) return {}; - if(!GetExitCodeProcess(pi.hProcess, &exitCode)) return {}; - CloseHandle(pi.hThread); - CloseHandle(pi.hProcess); - - char buffer[256]; - execute_result_t result; - result.code = exitCode; - - while(true) { - DWORD read, available, remaining; - if(!PeekNamedPipe(stdoutRead, nullptr, sizeof(buffer), &read, &available, &remaining)) break; - if(read == 0) break; - - if(!ReadFile(stdoutRead, buffer, sizeof(buffer), &read, nullptr)) break; - if(read == 0) break; - - auto offset = result.output.size(); - result.output.resize(offset + read); - memory::copy(result.output.get() + offset, buffer, read); - } - - while(true) { - DWORD read, available, remaining; - if(!PeekNamedPipe(stderrRead, nullptr, sizeof(buffer), &read, &available, &remaining)) break; - if(read == 0) break; - - if(!ReadFile(stderrRead, buffer, sizeof(buffer), &read, nullptr)) break; - if(read == 0) break; - - auto offset = result.error.size(); - result.error.resize(offset + read); - memory::copy(result.error.get() + offset, buffer, read); - } - - return result; + return execute(name, std::move(argl)); } +auto invoke(const string& name, vector argl) -> void; + template inline auto invoke(const string& name, P&&... p) -> void { vector argl(std::forward

(p)...); - for(auto& arg : argl) if(arg.find(" ")) arg = {"\"", arg, "\""}; - string arguments = argl.merge(" "); - string directory = Path::program().replace("/", "\\"); - ShellExecute(nullptr, nullptr, utf16_t(name), utf16_t(arguments), utf16_t(directory), SW_SHOWNORMAL); + invoke(name, std::move(argl)); } #else @@ -212,3 +136,7 @@ template inline auto invoke(const string& name, P&&... p) -> void #endif } + +#if defined(NALL_HEADER_ONLY) + #include +#endif diff --git a/waterbox/ares64/ares/nall/serializer.hpp b/waterbox/ares64/ares/nall/serializer.hpp index 229edf23d6..741753db1c 100644 --- a/waterbox/ares64/ares/nall/serializer.hpp +++ b/waterbox/ares64/ares/nall/serializer.hpp @@ -76,10 +76,11 @@ struct serializer { } template auto operator()(T& value) -> serializer& { - static_assert(has_serialize_v || is_integral_v || is_floating_point_v); + constexpr bool integral = is_integral_v || is_same_v; + static_assert(has_serialize_v || integral || is_floating_point_v); if constexpr(has_serialize_v) { value.serialize(*this); - } else if constexpr(is_integral_v) { + } else if constexpr(integral) { integer(value); } else if constexpr(is_floating_point_v) { real(value); diff --git a/waterbox/ares64/ares/nall/shared-pointer.hpp b/waterbox/ares64/ares/nall/shared-pointer.hpp index 0666e065d6..190b6fd019 100644 --- a/waterbox/ares64/ares/nall/shared-pointer.hpp +++ b/waterbox/ares64/ares/nall/shared-pointer.hpp @@ -27,7 +27,7 @@ struct shared_pointer_this_base{}; template struct shared_pointer { template static auto create(P&&... p) { - return shared_pointer{new T{std::forward

(p)...}}; + return shared_pointer{new T(std::forward

(p)...)}; } using type = T; diff --git a/waterbox/ares64/ares/nall/smtp.cpp b/waterbox/ares64/ares/nall/smtp.cpp new file mode 100644 index 0000000000..36739c3c88 --- /dev/null +++ b/waterbox/ares64/ares/nall/smtp.cpp @@ -0,0 +1,149 @@ +#include + +#if defined(PLATFORM_WINDOWS) + #include +#endif + +namespace nall { + +NALL_HEADER_INLINE auto SMTP::send() -> bool { + info.message.append("From: =?UTF-8?B?", Encode::Base64(contact(info.from)), "?=\r\n"); + info.message.append("To: =?UTF-8?B?", Encode::Base64(contacts(info.to)), "?=\r\n"); + info.message.append("Cc: =?UTF-8?B?", Encode::Base64(contacts(info.cc)), "?=\r\n"); + info.message.append("Subject: =?UTF-8?B?", Encode::Base64(info.subject), "?=\r\n"); + + string uniqueID = boundary(); + + info.message.append("MIME-Version: 1.0\r\n"); + info.message.append("Content-Type: multipart/mixed; boundary=", uniqueID, "\r\n"); + info.message.append("\r\n"); + + string format = (info.format == Format::Plain ? "text/plain" : "text/html"); + + info.message.append("--", uniqueID, "\r\n"); + info.message.append("Content-Type: ", format, "; charset=UTF-8\r\n"); + info.message.append("Content-Transfer-Encoding: base64\r\n"); + info.message.append("\r\n"); + info.message.append(split(Encode::Base64(info.body)), "\r\n"); + info.message.append("\r\n"); + + for(auto& attachment : info.attachments) { + info.message.append("--", uniqueID, "\r\n"); + info.message.append("Content-Type: application/octet-stream\r\n"); + info.message.append("Content-Transfer-Encoding: base64\r\n"); + info.message.append("Content-Disposition: attachment; size=", attachment.buffer.size(), "; filename*=UTF-8''", filename(attachment.name), "\r\n"); + info.message.append("\r\n"); + info.message.append(split(Encode::Base64(attachment.buffer)), "\r\n"); + info.message.append("\r\n"); + } + + info.message.append("--", uniqueID, "--\r\n"); + + addrinfo hints; + memset(&hints, 0, sizeof(addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + + addrinfo* serverinfo; + s32 status = getaddrinfo(info.server, string(info.port), &hints, &serverinfo); + if(status != 0) return false; + + s32 sock = socket(serverinfo->ai_family, serverinfo->ai_socktype, serverinfo->ai_protocol); + if(sock == -1) return false; + + s32 result = connect(sock, serverinfo->ai_addr, serverinfo->ai_addrlen); + if(result == -1) return false; + + string response; + info.response.append(response = recv(sock)); + if(!response.beginsWith("220 ")) { close(sock); return false; } + + send(sock, {"HELO ", info.server, "\r\n"}); + info.response.append(response = recv(sock)); + if(!response.beginsWith("250 ")) { close(sock); return false; } + + send(sock, {"MAIL FROM: <", info.from.mail, ">\r\n"}); + info.response.append(response = recv(sock)); + if(!response.beginsWith("250 ")) { close(sock); return false; } + + for(auto& contact : info.to) { + send(sock, {"RCPT TO: <", contact.mail, ">\r\n"}); + info.response.append(response = recv(sock)); + if(!response.beginsWith("250 ")) { close(sock); return false; } + } + + for(auto& contact : info.cc) { + send(sock, {"RCPT TO: <", contact.mail, ">\r\n"}); + info.response.append(response = recv(sock)); + if(!response.beginsWith("250 ")) { close(sock); return false; } + } + + for(auto& contact : info.bcc) { + send(sock, {"RCPT TO: <", contact.mail, ">\r\n"}); + info.response.append(response = recv(sock)); + if(!response.beginsWith("250 ")) { close(sock); return false; } + } + + send(sock, {"DATA\r\n"}); + info.response.append(response = recv(sock)); + if(!response.beginsWith("354 ")) { close(sock); return false; } + + send(sock, {info.message, "\r\n", ".\r\n"}); + info.response.append(response = recv(sock)); + if(!response.beginsWith("250 ")) { close(sock); return false; } + + send(sock, {"QUIT\r\n"}); + info.response.append(response = recv(sock)); +//if(!response.beginsWith("221 ")) { close(sock); return false; } + + close(sock); + return true; +} + +NALL_HEADER_INLINE auto SMTP::send(s32 sock, const string& text) -> bool { + const char* data = text.data(); + u32 size = text.size(); + while(size) { + s32 length = ::send(sock, (const char*)data, size, 0); + if(length == -1) return false; + data += length; + size -= length; + } + return true; +} + +NALL_HEADER_INLINE auto SMTP::recv(s32 sock) -> string { + vector buffer; + while(true) { + char c; + if(::recv(sock, &c, sizeof(char), 0) < 1) break; + buffer.append(c); + if(c == '\n') break; + } + buffer.append(0); + return buffer; +} + +#if defined(API_WINDOWS) + +NALL_HEADER_INLINE auto SMTP::close(s32 sock) -> s32 { + return closesocket(sock); +} + +NALL_HEADER_INLINE SMTP::SMTP() { + s32 sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if(sock == INVALID_SOCKET && WSAGetLastError() == WSANOTINITIALISED) { + WSADATA wsaData; + if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { + WSACleanup(); + return; + } + } else { + close(sock); + } +} + +#endif + +} diff --git a/waterbox/ares64/ares/nall/smtp.hpp b/waterbox/ares64/ares/nall/smtp.hpp index 82f2d7d2c4..d19b4b1c65 100644 --- a/waterbox/ares64/ares/nall/smtp.hpp +++ b/waterbox/ares64/ares/nall/smtp.hpp @@ -1,17 +1,17 @@ #pragma once -#include #include #include +#include +#include +#include +#include #if !defined(PLATFORM_WINDOWS) #include #include #include #include -#else - #include - #include #endif namespace nall { @@ -102,7 +102,7 @@ inline auto SMTP::attachment(const u8* data, u32 size, string name) -> void { inline auto SMTP::attachment(string filename, string name) -> bool { if(!file::exists(filename)) return false; - if(name == "") name = notdir(filename); + if(name == "") name = Location::file(filename); auto buffer = file::read(filename); info.attachments.append({std::move(buffer), name}); return true; @@ -117,101 +117,6 @@ inline auto SMTP::body(string body, Format format) -> void { info.format = format; } -inline auto SMTP::send() -> bool { - info.message.append("From: =?UTF-8?B?", Base64::encode(contact(info.from)), "?=\r\n"); - info.message.append("To: =?UTF-8?B?", Base64::encode(contacts(info.to)), "?=\r\n"); - info.message.append("Cc: =?UTF-8?B?", Base64::encode(contacts(info.cc)), "?=\r\n"); - info.message.append("Subject: =?UTF-8?B?", Base64::encode(info.subject), "?=\r\n"); - - string uniqueID = boundary(); - - info.message.append("MIME-Version: 1.0\r\n"); - info.message.append("Content-Type: multipart/mixed; boundary=", uniqueID, "\r\n"); - info.message.append("\r\n"); - - string format = (info.format == Format::Plain ? "text/plain" : "text/html"); - - info.message.append("--", uniqueID, "\r\n"); - info.message.append("Content-Type: ", format, "; charset=UTF-8\r\n"); - info.message.append("Content-Transfer-Encoding: base64\r\n"); - info.message.append("\r\n"); - info.message.append(split(Base64::encode(info.body)), "\r\n"); - info.message.append("\r\n"); - - for(auto& attachment : info.attachments) { - info.message.append("--", uniqueID, "\r\n"); - info.message.append("Content-Type: application/octet-stream\r\n"); - info.message.append("Content-Transfer-Encoding: base64\r\n"); - info.message.append("Content-Disposition: attachment; size=", attachment.buffer.size(), "; filename*=UTF-8''", filename(attachment.name), "\r\n"); - info.message.append("\r\n"); - info.message.append(split(Base64::encode(attachment.buffer)), "\r\n"); - info.message.append("\r\n"); - } - - info.message.append("--", uniqueID, "--\r\n"); - - addrinfo hints; - memset(&hints, 0, sizeof(addrinfo)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE; - - addrinfo* serverinfo; - s32 status = getaddrinfo(info.server, string(info.port), &hints, &serverinfo); - if(status != 0) return false; - - s32 sock = socket(serverinfo->ai_family, serverinfo->ai_socktype, serverinfo->ai_protocol); - if(sock == -1) return false; - - s32 result = connect(sock, serverinfo->ai_addr, serverinfo->ai_addrlen); - if(result == -1) return false; - - string response; - info.response.append(response = recv(sock)); - if(!response.beginswith("220 ")) { close(sock); return false; } - - send(sock, {"HELO ", info.server, "\r\n"}); - info.response.append(response = recv(sock)); - if(!response.beginswith("250 ")) { close(sock); return false; } - - send(sock, {"MAIL FROM: <", info.from.mail, ">\r\n"}); - info.response.append(response = recv(sock)); - if(!response.beginswith("250 ")) { close(sock); return false; } - - for(auto& contact : info.to) { - send(sock, {"RCPT TO: <", contact.mail, ">\r\n"}); - info.response.append(response = recv(sock)); - if(!response.beginswith("250 ")) { close(sock); return false; } - } - - for(auto& contact : info.cc) { - send(sock, {"RCPT TO: <", contact.mail, ">\r\n"}); - info.response.append(response = recv(sock)); - if(!response.beginswith("250 ")) { close(sock); return false; } - } - - for(auto& contact : info.bcc) { - send(sock, {"RCPT TO: <", contact.mail, ">\r\n"}); - info.response.append(response = recv(sock)); - if(!response.beginswith("250 ")) { close(sock); return false; } - } - - send(sock, {"DATA\r\n"}); - info.response.append(response = recv(sock)); - if(!response.beginswith("354 ")) { close(sock); return false; } - - send(sock, {info.message, "\r\n", ".\r\n"}); - info.response.append(response = recv(sock)); - if(!response.beginswith("250 ")) { close(sock); return false; } - - send(sock, {"QUIT\r\n"}); - info.response.append(response = recv(sock)); -//if(!response.beginswith("221 ")) { close(sock); return false; } - - close(sock); - return true; -} - inline auto SMTP::message() -> string { return info.message; } @@ -220,42 +125,18 @@ inline auto SMTP::response() -> string { return info.response; } -inline auto SMTP::send(s32 sock, const string& text) -> bool { - const char* data = text.data(); - u32 size = text.size(); - while(size) { - s32 length = ::send(sock, (const char*)data, size, 0); - if(length == -1) return false; - data += length; - size -= length; - } - return true; -} - -inline auto SMTP::recv(s32 sock) -> string { - vector buffer; - while(true) { - char c; - if(::recv(sock, &c, sizeof(char), 0) < 1) break; - buffer.append(c); - if(c == '\n') break; - } - buffer.append(0); - return buffer; -} - inline auto SMTP::boundary() -> string { - random_lfsr random; + PRNG::LFSR random; random.seed(time(0)); string boundary; - for(u32 n = 0; n < 16; n++) boundary.append(hex<2>(random())); + for(u32 n = 0; n < 16; n++) boundary.append(hex(random.random(), 2L)); return boundary; } inline auto SMTP::filename(const string& filename) -> string { string result; for(auto& n : filename) { - if(n <= 32 || n >= 127) result.append("%", hex<2>(n)); + if(n <= 32 || n >= 127) result.append("%", hex(n, 2L)); else result.append(n); } return result; @@ -292,23 +173,8 @@ inline auto SMTP::split(const string& text) -> string { return result; } -#if defined(API_WINDOWS) -inline auto SMTP::close(s32 sock) -> s32 { - return closesocket(sock); } -inline SMTP::SMTP() { - s32 sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if(sock == INVALID_SOCKET && WSAGetLastError() == WSANOTINITIALISED) { - WSADATA wsaData; - if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { - WSACleanup(); - return; - } - } else { - close(sock); - } -} +#if defined(NALL_HEADER_ONLY) + #include #endif - -} diff --git a/waterbox/ares64/ares/nall/stdint.hpp b/waterbox/ares64/ares/nall/stdint.hpp index 9cee334c93..a6243976b1 100644 --- a/waterbox/ares64/ares/nall/stdint.hpp +++ b/waterbox/ares64/ares/nall/stdint.hpp @@ -8,8 +8,10 @@ typedef int64_t intmax_t; #if defined(_WIN64) typedef int64_t intptr_t; + typedef int64_t ssize_t; #else typedef int32_t intptr_t; + typedef int32_t ssize_t; #endif typedef unsigned char uint8_t; @@ -80,4 +82,7 @@ using f64 = float64_t; #if defined(__SIZEOF_INT128__) using s128 = int128_t; using u128 = uint128_t; +#else + //arithmetic.hpp + namespace nall { struct u128; } #endif diff --git a/waterbox/ares64/ares/nall/string/markup/node.hpp b/waterbox/ares64/ares/nall/string/markup/node.hpp index 33ed459baf..2f1ad7bfed 100644 --- a/waterbox/ares64/ares/nall/string/markup/node.hpp +++ b/waterbox/ares64/ares/nall/string/markup/node.hpp @@ -109,9 +109,11 @@ struct Node { return std::swap(shared->_children[x], shared->_children[y]), true; } - auto sort(function comparator = [](auto x, auto y) { - return nall::string::compare(x.shared->_name, y.shared->_name) < 0; - }) -> void { + auto operator<(const Node& node) -> bool { + return nall::string::compare(shared->_name, node.shared->_name) < 0; + } + + auto sort(function comparator = [](auto x, auto y) { return x < y; }) -> void { nall::sort(shared->_children.data(), shared->_children.size(), [&](auto x, auto y) { return comparator(x, y); //this call converts SharedNode objects to Node objects }); diff --git a/waterbox/ares64/ares/nall/string/markup/xml.hpp b/waterbox/ares64/ares/nall/string/markup/xml.hpp index 6de2d32755..21ac8e33a5 100644 --- a/waterbox/ares64/ares/nall/string/markup/xml.hpp +++ b/waterbox/ares64/ares/nall/string/markup/xml.hpp @@ -43,7 +43,8 @@ protected: //copy part of string from source document into target string; decode markup while copying auto copy(string& target, const char* source, u32 length) -> void { - target.reserve(length + 1); + string buffer; + buffer.resize(length); #if defined(NALL_XML_LITERAL) memory::copy(target.pointer(), source, length); @@ -51,7 +52,7 @@ protected: return; #endif - char* output = target.get(); + char* output = buffer.get(); while(length) { if(*source == '&') { if(!memory::compare(source, "<", 4)) { *output++ = '<'; source += 4; length -= 4; continue; } @@ -63,7 +64,7 @@ protected: if(_metadata == 0 && source[0] == '<' && source[1] == '!') { //comment - if(!memory::compare(source, "", 3)) source++, length--; source += 3, length -= 3; @@ -81,7 +82,8 @@ protected: *output++ = *source++, length--; } - *output = 0; + buffer.resize(output - buffer.get()); + target = std::move(buffer); } auto parseExpression(const char*& p) -> bool { @@ -199,19 +201,19 @@ protected: copy(_value, dataStart, dataEnd - dataStart); } - friend auto unserialize(const string&) -> Markup::SharedNode; + friend auto unserialize(const string&) -> Markup::Node; }; -inline auto unserialize(const string& markup) -> Markup::SharedNode { - auto node = new ManagedNode; +inline auto unserialize(const string& markup) -> Markup::Node { + SharedNode node(new ManagedNode); try { + const char* p = markup; node->parse(p); } catch(const char* error) { - delete node; - node = nullptr; + node.reset(); } - return node; + return (Markup::SharedNode&)node; } } diff --git a/waterbox/ares64/ares/nall/string/transform/dml.hpp b/waterbox/ares64/ares/nall/string/transform/dml.hpp index f5bc64278e..6111f6ca58 100644 --- a/waterbox/ares64/ares/nall/string/transform/dml.hpp +++ b/waterbox/ares64/ares/nall/string/transform/dml.hpp @@ -257,11 +257,11 @@ inline auto DML::anchor(const string& text) -> string { inline auto DML::markup(const string& s) -> string { string t; - boolean strong; - boolean emphasis; - boolean insertion; - boolean deletion; - boolean code; + Boolean strong; + Boolean emphasis; + Boolean insertion; + Boolean deletion; + Boolean code; maybe link; maybe image; @@ -300,7 +300,7 @@ inline auto DML::markup(const string& s) -> string { string uri = address(list.last()); string name = list.size() == 2 ? list.first() : uri.split("//", 1L).last(); list = side(1).split("; "); - boolean link, title, caption; + Boolean link, title, caption; string Class, width, height; for(auto p : list) { if(p == "link") { link = true; continue; } diff --git a/waterbox/ares64/ares/nall/string/utility.hpp b/waterbox/ares64/ares/nall/string/utility.hpp index 0417bce6c8..4b46f58176 100644 --- a/waterbox/ares64/ares/nall/string/utility.hpp +++ b/waterbox/ares64/ares/nall/string/utility.hpp @@ -161,7 +161,7 @@ template inline auto fromReal(char* result, T value) -> u32 { //Windows C-runtime does not support long double via sprintf() sprintf(buffer, "%f", (double)value); #else - sprintf(buffer, "%Lf", (long double)value); + snprintf(buffer, sizeof(buffer), "%Lf", (long double)value); #endif //remove excess 0's in fraction (2.500000 -> 2.5) diff --git a/waterbox/ares64/ares/nall/terminal.cpp b/waterbox/ares64/ares/nall/terminal.cpp new file mode 100644 index 0000000000..063d96da75 --- /dev/null +++ b/waterbox/ares64/ares/nall/terminal.cpp @@ -0,0 +1,21 @@ +#include + +namespace nall::terminal { + +NALL_HEADER_INLINE auto redirectStdioToTerminal(bool create) -> void { +#if defined(PLATFORM_WINDOWS) + if(create) { + FreeConsole(); + if(!AllocConsole()) return; + } else if(!AttachConsole(ATTACH_PARENT_PROCESS)) { + return; + } + + //unless a new terminal was requested, do not reopen already valid handles (allow redirection to/from file) + if(create || _get_osfhandle(_fileno(stdin )) < 0) freopen("CONIN$" , "r", stdin ); + if(create || _get_osfhandle(_fileno(stdout)) < 0) freopen("CONOUT$", "w", stdout); + if(create || _get_osfhandle(_fileno(stderr)) < 0) freopen("CONOUT$", "w", stderr); +#endif +} + +} diff --git a/waterbox/ares64/ares/nall/terminal.hpp b/waterbox/ares64/ares/nall/terminal.hpp index 6006b3feb8..9c4253f4db 100644 --- a/waterbox/ares64/ares/nall/terminal.hpp +++ b/waterbox/ares64/ares/nall/terminal.hpp @@ -4,6 +4,11 @@ namespace nall::terminal { +//control sequence introducer +constexpr char csi[] = "\x1b["; + +auto redirectStdioToTerminal(bool create) -> void; + inline auto escapable() -> bool { #if defined(PLATFORM_WINDOWS) //todo: colors are supported by Windows 10+ and with alternate terminals (eg msys) @@ -17,49 +22,53 @@ namespace color { template inline auto black(P&&... p) -> string { if(!escapable()) return string{std::forward

(p)...}; - return {"\e[30m", string{std::forward

(p)...}, "\e[0m"}; + return {csi, "30m", string{std::forward

(p)...}, csi, "0m"}; } template inline auto blue(P&&... p) -> string { if(!escapable()) return string{std::forward

(p)...}; - return {"\e[94m", string{std::forward

(p)...}, "\e[0m"}; + return {csi, "94m", string{std::forward

(p)...}, csi, "0m"}; } template inline auto green(P&&... p) -> string { if(!escapable()) return string{std::forward

(p)...}; - return {"\e[92m", string{std::forward

(p)...}, "\e[0m"}; + return {csi, "92m", string{std::forward

(p)...}, csi, "0m"}; } template inline auto cyan(P&&... p) -> string { if(!escapable()) return string{std::forward

(p)...}; - return {"\e[96m", string{std::forward

(p)...}, "\e[0m"}; + return {csi, "96m", string{std::forward

(p)...}, csi, "0m"}; } template inline auto red(P&&... p) -> string { if(!escapable()) return string{std::forward

(p)...}; - return {"\e[91m", string{std::forward

(p)...}, "\e[0m"}; + return {csi, "91m", string{std::forward

(p)...}, csi, "0m"}; } template inline auto magenta(P&&... p) -> string { if(!escapable()) return string{std::forward

(p)...}; - return {"\e[95m", string{std::forward

(p)...}, "\e[0m"}; + return {csi, "95m", string{std::forward

(p)...}, csi, "0m"}; } template inline auto yellow(P&&... p) -> string { if(!escapable()) return string{std::forward

(p)...}; - return {"\e[93m", string{std::forward

(p)...}, "\e[0m"}; + return {csi, "93m", string{std::forward

(p)...}, csi, "0m"}; } template inline auto white(P&&... p) -> string { if(!escapable()) return string{std::forward

(p)...}; - return {"\e[97m", string{std::forward

(p)...}, "\e[0m"}; + return {csi, "97m", string{std::forward

(p)...}, csi, "0m"}; } template inline auto gray(P&&... p) -> string { if(!escapable()) return string{std::forward

(p)...}; - return {"\e[37m", string{std::forward

(p)...}, "\e[0m"}; + return {csi, "37m", string{std::forward

(p)...}, csi, "0m"}; } } } + +#if defined(NALL_HEADER_ONLY) + #include +#endif diff --git a/waterbox/ares64/ares/nall/thread.cpp b/waterbox/ares64/ares/nall/thread.cpp new file mode 100644 index 0000000000..73e3cc311b --- /dev/null +++ b/waterbox/ares64/ares/nall/thread.cpp @@ -0,0 +1,53 @@ +#include + +namespace nall { + +#if defined(API_WINDOWS) + +NALL_HEADER_INLINE auto WINAPI _threadCallback(void* parameter) -> DWORD { + auto context = (thread::context*)parameter; + context->callback(context->parameter); + delete context; + return 0; +} + +NALL_HEADER_INLINE auto thread::close() -> void { + if(handle) { + CloseHandle(handle); + handle = 0; + } +} + +NALL_HEADER_INLINE auto thread::join() -> void { + if(handle) { + //wait until the thread has finished executing ... + WaitForSingleObject(handle, INFINITE); + CloseHandle(handle); + handle = 0; + } +} + +NALL_HEADER_INLINE auto thread::create(const function& callback, uintptr parameter, u32 stacksize) -> thread { + thread instance; + + auto context = new thread::context; + context->callback = callback; + context->parameter = parameter; + + instance.handle = CreateThread(nullptr, stacksize, _threadCallback, (void*)context, 0, nullptr); + return instance; +} + +NALL_HEADER_INLINE auto thread::detach() -> void { + //Windows threads do not use this concept: + //~thread() frees resources via CloseHandle() + //thread continues to run even after handle is closed +} + +NALL_HEADER_INLINE auto thread::exit() -> void { + ExitThread(0); +} + +#endif + +} diff --git a/waterbox/ares64/ares/nall/thread.hpp b/waterbox/ares64/ares/nall/thread.hpp index f7204e825f..a76896f9ac 100644 --- a/waterbox/ares64/ares/nall/thread.hpp +++ b/waterbox/ares64/ares/nall/thread.hpp @@ -128,50 +128,10 @@ private: HANDLE handle = 0; }; -inline auto WINAPI _threadCallback(void* parameter) -> DWORD { - auto context = (thread::context*)parameter; - context->callback(context->parameter); - delete context; - return 0; -} - -inline auto thread::close() -> void { - if(handle) { - CloseHandle(handle); - handle = 0; - } -} - -inline auto thread::join() -> void { - if(handle) { - //wait until the thread has finished executing ... - WaitForSingleObject(handle, INFINITE); - CloseHandle(handle); - handle = 0; - } -} - -inline auto thread::create(const function& callback, uintptr parameter, u32 stacksize) -> thread { - thread instance; - - auto context = new thread::context; - context->callback = callback; - context->parameter = parameter; - - instance.handle = CreateThread(nullptr, stacksize, _threadCallback, (void*)context, 0, nullptr); - return instance; -} - -inline auto thread::detach() -> void { - //Windows threads do not use this concept: - //~thread() frees resources via CloseHandle() - //thread continues to run even after handle is closed -} - -inline auto thread::exit() -> void { - ExitThread(0); -} - } #endif + +#if defined(NALL_HEADER_ONLY) + #include +#endif diff --git a/waterbox/ares64/ares/nall/traits.hpp b/waterbox/ares64/ares/nall/traits.hpp index 0e810e66b9..5862b36bb7 100644 --- a/waterbox/ares64/ares/nall/traits.hpp +++ b/waterbox/ares64/ares/nall/traits.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include diff --git a/waterbox/ares64/ares/nall/vfs/cdrom.hpp b/waterbox/ares64/ares/nall/vfs/cdrom.hpp index 084fa1ee95..f410a0b66b 100644 --- a/waterbox/ares64/ares/nall/vfs/cdrom.hpp +++ b/waterbox/ares64/ares/nall/vfs/cdrom.hpp @@ -134,9 +134,9 @@ private: memory::assign(target + 0, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff); //sync memory::assign(target + 6, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00); //sync auto [minute, second, frame] = CD::MSF(lbaFileBase + index.lba + sector); - target[12] = CD::BCD::encode(minute); - target[13] = CD::BCD::encode(second); - target[14] = CD::BCD::encode(frame); + target[12] = BCD::encode(minute); + target[13] = BCD::encode(second); + target[14] = BCD::encode(frame); target[15] = 0x01; //mode filedata.read({target + 16, length}); CD::RSPC::encodeMode1({target, 2352}); @@ -215,7 +215,20 @@ private: for(s32 sector : range(index.sectorCount())) { auto target = _image.data() + 2448ull * (LeadInSectors + index.lba + sector); auto sectorData = chd.read(lba); - memory::copy(target, 2352, sectorData.data(), sectorData.size()); + if(sectorData.size() == 2048) { + //ISO: generate header + parity data + memory::assign(target + 0, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff); //sync + memory::assign(target + 6, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00); //sync + auto [minute, second, frame] = CD::MSF(index.lba + sector); + target[12] = BCD::encode(minute); + target[13] = BCD::encode(second); + target[14] = BCD::encode(frame); + target[15] = 0x01; //mode + memory::copy(target + 16, 2048, sectorData.data(), sectorData.size()); + CD::RSPC::encodeMode1({target, 2352}); + } else { + memory::copy(target, 2352, sectorData.data(), sectorData.size()); + } lba++; } } diff --git a/waterbox/ares64/ares/nall/windows/detour.cpp b/waterbox/ares64/ares/nall/windows/detour.cpp new file mode 100644 index 0000000000..b5a2612711 --- /dev/null +++ b/waterbox/ares64/ares/nall/windows/detour.cpp @@ -0,0 +1,69 @@ +#include + +namespace nall { + +NALL_HEADER_INLINE auto detour::insert(const string& moduleName, const string& functionName, void*& source, void* target) -> bool { + #if defined(ARCHITECTURE_X86) + HMODULE module = GetModuleHandleW(utf16_t(moduleName)); + if(!module) return false; + + u8* sourceData = (u8*)GetProcAddress(module, functionName); + if(!sourceData) return false; + + u32 sourceLength = detour::length(sourceData); + if(sourceLength < 5) { + //unable to clone enough bytes to insert hook + #if 1 + string output = {"detour::insert(", moduleName, "::", functionName, ") failed: "}; + for(u32 n = 0; n < 16; n++) output.append(hex(sourceData[n], 2L), " "); + output.trimRight(" ", 1L); + MessageBoxA(0, output, "nall::detour", MB_OK); + #endif + return false; + } + + auto mirrorData = new u8[512](); + detour::mirror(mirrorData, sourceData); + + DWORD privileges; + VirtualProtect((void*)mirrorData, 512, PAGE_EXECUTE_READWRITE, &privileges); + VirtualProtect((void*)sourceData, 256, PAGE_EXECUTE_READWRITE, &privileges); + u64 address = (u64)target - ((u64)sourceData + 5); + sourceData[0] = 0xe9; //jmp target + sourceData[1] = address >> 0; + sourceData[2] = address >> 8; + sourceData[3] = address >> 16; + sourceData[4] = address >> 24; + VirtualProtect((void*)sourceData, 256, privileges, &privileges); + + source = (void*)mirrorData; + return true; + #else + return false; + #endif +} + +NALL_HEADER_INLINE auto detour::remove(const string& moduleName, const string& functionName, void*& source) -> bool { + HMODULE module = GetModuleHandleW(utf16_t(moduleName)); + if(!module) return false; + + auto sourceData = (u8*)GetProcAddress(module, functionName); + if(!sourceData) return false; + + auto mirrorData = (u8*)source; + if(mirrorData == sourceData) return false; //hook was never installed + + u32 length = detour::length(256 + mirrorData); + if(length < 5) return false; + + DWORD privileges; + VirtualProtect((void*)sourceData, 256, PAGE_EXECUTE_READWRITE, &privileges); + for(u32 n = 0; n < length; n++) sourceData[n] = mirrorData[256 + n]; + VirtualProtect((void*)sourceData, 256, privileges, &privileges); + + source = (void*)sourceData; + delete[] mirrorData; + return true; +} + +} diff --git a/waterbox/ares64/ares/nall/windows/detour.hpp b/waterbox/ares64/ares/nall/windows/detour.hpp index b80b8d9dce..ebc3113dea 100644 --- a/waterbox/ares64/ares/nall/windows/detour.hpp +++ b/waterbox/ares64/ares/nall/windows/detour.hpp @@ -1,10 +1,9 @@ #pragma once -#include #include #include #include -#include +#include namespace nall { @@ -25,107 +24,46 @@ protected: u32 mode; u16 modify; }; - static opcode opcodes[]; + static constexpr opcode opcodes[] = { + //TODO: + //* fs:, gs: should force another opcode copy + //* conditional branches within +5-byte range should fail + + {0x50, 1}, //push eax + {0x51, 1}, //push ecx + {0x52, 1}, //push edx + {0x53, 1}, //push ebx + {0x54, 1}, //push esp + {0x55, 1}, //push ebp + {0x56, 1}, //push esi + {0x57, 1}, //push edi + {0x58, 1}, //pop eax + {0x59, 1}, //pop ecx + {0x5a, 1}, //pop edx + {0x5b, 1}, //pop ebx + {0x5c, 1}, //pop esp + {0x5d, 1}, //pop ebp + {0x5e, 1}, //pop esi + {0x5f, 1}, //pop edi + {0x64, 1}, //fs: + {0x65, 1}, //gs: + {0x68, 5}, //push dword + {0x6a, 2}, //push byte + {0x74, 2, RelNear, 0x0f84}, //je near -> je far + {0x75, 2, RelNear, 0x0f85}, //jne near -> jne far + {0x89, 2}, //mov reg,reg + {0x8b, 2}, //mov reg,reg + {0x90, 1}, //nop + {0xa1, 5}, //mov eax,[dword] + {0xeb, 2, RelNear, 0xe9}, //jmp near -> jmp far + }; }; -//TODO: -//* fs:, gs: should force another opcode copy -//* conditional branches within +5-byte range should fail -detour::opcode detour::opcodes[] = { - {0x50, 1}, //push eax - {0x51, 1}, //push ecx - {0x52, 1}, //push edx - {0x53, 1}, //push ebx - {0x54, 1}, //push esp - {0x55, 1}, //push ebp - {0x56, 1}, //push esi - {0x57, 1}, //push edi - {0x58, 1}, //pop eax - {0x59, 1}, //pop ecx - {0x5a, 1}, //pop edx - {0x5b, 1}, //pop ebx - {0x5c, 1}, //pop esp - {0x5d, 1}, //pop ebp - {0x5e, 1}, //pop esi - {0x5f, 1}, //pop edi - {0x64, 1}, //fs: - {0x65, 1}, //gs: - {0x68, 5}, //push dword - {0x6a, 2}, //push byte - {0x74, 2, RelNear, 0x0f84}, //je near -> je far - {0x75, 2, RelNear, 0x0f85}, //jne near -> jne far - {0x89, 2}, //mov reg,reg - {0x8b, 2}, //mov reg,reg - {0x90, 1}, //nop - {0xa1, 5}, //mov eax,[dword] - {0xeb, 2, RelNear, 0xe9}, //jmp near -> jmp far -}; - -inline auto detour::insert(const string& moduleName, const string& functionName, void*& source, void* target) -> bool { - HMODULE module = GetModuleHandleW(utf16_t(moduleName)); - if(!module) return false; - - u8* sourceData = (u8*)GetProcAddress(module, functionName); - if(!sourceData) return false; - - u32 sourceLength = detour::length(sourceData); - if(sourceLength < 5) { - //unable to clone enough bytes to insert hook - #if 1 - string output = {"detour::insert(", moduleName, "::", functionName, ") failed: "}; - for(u32 n = 0; n < 16; n++) output.append(hex<2>(sourceData[n]), " "); - output.trimRight(" ", 1L); - MessageBoxA(0, output, "nall::detour", MB_OK); - #endif - return false; - } - - auto mirrorData = new u8[512](); - detour::mirror(mirrorData, sourceData); - - DWORD privileges; - VirtualProtect((void*)mirrorData, 512, PAGE_EXECUTE_READWRITE, &privileges); - VirtualProtect((void*)sourceData, 256, PAGE_EXECUTE_READWRITE, &privileges); - u64 address = (u64)target - ((u64)sourceData + 5); - sourceData[0] = 0xe9; //jmp target - sourceData[1] = address >> 0; - sourceData[2] = address >> 8; - sourceData[3] = address >> 16; - sourceData[4] = address >> 24; - VirtualProtect((void*)sourceData, 256, privileges, &privileges); - - source = (void*)mirrorData; - return true; -} - -inline auto detour::remove(const string& moduleName, const string& functionName, void*& source) -> bool { - HMODULE module = GetModuleHandleW(utf16_t(moduleName)); - if(!module) return false; - - auto sourceData = (u8*)GetProcAddress(module, functionName); - if(!sourceData) return false; - - auto mirrorData = (u8*)source; - if(mirrorData == sourceData) return false; //hook was never installed - - u32 length = detour::length(256 + mirrorData); - if(length < 5) return false; - - DWORD privileges; - VirtualProtect((void*)sourceData, 256, PAGE_EXECUTE_READWRITE, &privileges); - for(u32 n = 0; n < length; n++) sourceData[n] = mirrorData[256 + n]; - VirtualProtect((void*)sourceData, 256, privileges, &privileges); - - source = (void*)sourceData; - delete[] mirrorData; - return true; -} - inline auto detour::length(const u8* function) -> u32 { u32 length = 0; while(length < 5) { - detour::opcode *opcode = 0; - foreach(op, detour::opcodes) { + const detour::opcode *opcode = 0; + for(auto& op : detour::opcodes) { if(function[length] == op.prefix) { opcode = &op; break; @@ -143,8 +81,8 @@ inline auto detour::mirror(u8* target, const u8* source) -> u32 { u32 size = detour::length(source); while(size) { - detour::opcode* opcode = nullptr; - foreach(op, detour::opcodes) { + const detour::opcode* opcode = nullptr; + for(auto& op : detour::opcodes) { if(*source == op.prefix) { opcode = &op; break; @@ -183,7 +121,11 @@ inline auto detour::mirror(u8* target, const u8* source) -> u32 { return source - entryPoint; } -#undef Implied +#undef Copy #undef RelNear } + +#if defined(NALL_HEADER_ONLY) + #include +#endif diff --git a/waterbox/ares64/ares/nall/windows/guard.hpp b/waterbox/ares64/ares/nall/windows/guard.hpp deleted file mode 100644 index 147c567624..0000000000 --- a/waterbox/ares64/ares/nall/windows/guard.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef NALL_WINDOWS_GUARD_HPP -#define NALL_WINDOWS_GUARD_HPP - -#define boolean WindowsBoolean -#define interface WindowsInterface - -#undef UNICODE -#undef WINVER -#undef WIN32_LEAN_AND_LEAN -#undef _WIN32_WINNT -#undef _WIN32_IE -#undef NOMINMAX -#undef PATH_MAX - -#define UNICODE -#define WINVER 0x0601 -#define WIN32_LEAN_AND_MEAN -#define _WIN32_WINNT WINVER -#define _WIN32_IE WINVER -#define NOMINMAX -#define PATH_MAX 260 - -#else -#undef NALL_WINDOWS_GUARD_HPP - -#undef boolean -#undef interface - -#undef far -#undef near - -#endif diff --git a/waterbox/ares64/ares/nall/windows/guid.cpp b/waterbox/ares64/ares/nall/windows/guid.cpp new file mode 100644 index 0000000000..7f0f593906 --- /dev/null +++ b/waterbox/ares64/ares/nall/windows/guid.cpp @@ -0,0 +1,17 @@ +#include + +#include + +namespace nall { + +NALL_HEADER_INLINE auto guid() -> string { + GUID guidInstance; + CoCreateGuid(&guidInstance); + + wchar_t guidString[39]; + StringFromGUID2(guidInstance, guidString, 39); + + return (char*)utf8_t(guidString); +} + +} diff --git a/waterbox/ares64/ares/nall/windows/guid.hpp b/waterbox/ares64/ares/nall/windows/guid.hpp index 314683d490..e28ad8e7ce 100644 --- a/waterbox/ares64/ares/nall/windows/guid.hpp +++ b/waterbox/ares64/ares/nall/windows/guid.hpp @@ -1,17 +1,13 @@ -#pragma once - -#include - -namespace nall { - -inline auto guid() -> string { - GUID guidInstance; - CoCreateGuid(&guidInstance); - - wchar_t guidString[39]; - StringFromGUID2(guidInstance, guidString, 39); - - return (char*)utf8_t(guidString); -} - -} +#pragma once + +#include + +namespace nall { + +auto guid() -> string; + +} + +#if defined(NALL_HEADER_ONLY) + #include +#endif diff --git a/waterbox/ares64/ares/nall/windows/launcher.cpp b/waterbox/ares64/ares/nall/windows/launcher.cpp new file mode 100644 index 0000000000..a25db095a8 --- /dev/null +++ b/waterbox/ares64/ares/nall/windows/launcher.cpp @@ -0,0 +1,93 @@ +#include + +namespace nall { + +NALL_HEADER_INLINE auto launch(const char* applicationName, const char* libraryName, u32 entryPoint) -> bool { + #if defined(ARCHITECTURE_X86) + //if a launcher does not send at least one message, a wait cursor will appear + PostThreadMessage(GetCurrentThreadId(), WM_USER, 0, 0); + MSG msg; + GetMessage(&msg, 0, 0, 0); + + STARTUPINFOW si; + PROCESS_INFORMATION pi; + + memset(&si, 0, sizeof(STARTUPINFOW)); + BOOL result = CreateProcessW( + utf16_t(applicationName), GetCommandLineW(), NULL, NULL, TRUE, + DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS, //do not break if application creates its own processes + NULL, NULL, &si, &pi + ); + if(result == false) return false; + + u8 entryData[1024], entryHook[1024] = { + 0x68, 0x00, 0x00, 0x00, 0x00, //push libraryName + 0xb8, 0x00, 0x00, 0x00, 0x00, //mov eax,LoadLibraryW + 0xff, 0xd0, //call eax + 0xcd, 0x03, //int 3 + }; + + entryHook[1] = (u8)((entryPoint + 14) >> 0); + entryHook[2] = (u8)((entryPoint + 14) >> 8); + entryHook[3] = (u8)((entryPoint + 14) >> 16); + entryHook[4] = (u8)((entryPoint + 14) >> 24); + + auto pLoadLibraryW = (u32)GetProcAddress(GetModuleHandleW(L"kernel32"), "LoadLibraryW"); + entryHook[6] = pLoadLibraryW >> 0; + entryHook[7] = pLoadLibraryW >> 8; + entryHook[8] = pLoadLibraryW >> 16; + entryHook[9] = pLoadLibraryW >> 24; + + utf16_t buffer = utf16_t(libraryName); + memcpy(entryHook + 14, buffer, 2 * wcslen(buffer) + 2); + + while(true) { + DEBUG_EVENT event; + WaitForDebugEvent(&event, INFINITE); + + if(event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break; + + if(event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT) { + if(event.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) { + if(event.u.Exception.ExceptionRecord.ExceptionAddress == (void*)(entryPoint + 14 - 1)) { + HANDLE hProcess = OpenProcess(0, FALSE, event.dwProcessId); + HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, event.dwThreadId); + + CONTEXT context; + context.ContextFlags = CONTEXT_FULL; + GetThreadContext(hThread, &context); + + WriteProcessMemory(pi.hProcess, (void*)entryPoint, (void*)&entryData, sizeof entryData, NULL); + context.Eip = entryPoint; + SetThreadContext(hThread, &context); + + CloseHandle(hThread); + CloseHandle(hProcess); + } + + ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE); + continue; + } + + ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_EXCEPTION_NOT_HANDLED); + continue; + } + + if(event.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT) { + ReadProcessMemory(pi.hProcess, (void*)entryPoint, (void*)&entryData, sizeof entryData, NULL); + WriteProcessMemory(pi.hProcess, (void*)entryPoint, (void*)&entryHook, sizeof entryHook, NULL); + + ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE); + continue; + } + + ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE); + } + + return true; + #else + return false; + #endif +} + +} diff --git a/waterbox/ares64/ares/nall/windows/launcher.hpp b/waterbox/ares64/ares/nall/windows/launcher.hpp index 0d09faaf7e..1415b2869d 100644 --- a/waterbox/ares64/ares/nall/windows/launcher.hpp +++ b/waterbox/ares64/ares/nall/windows/launcher.hpp @@ -1,91 +1,15 @@ #pragma once +#include + namespace nall { //launch a new process and inject specified DLL into it -inline auto launch(const char* applicationName, const char* libraryName, u32 entryPoint) -> bool { - //if a launcher does not send at least one message, a wait cursor will appear - PostThreadMessage(GetCurrentThreadId(), WM_USER, 0, 0); - MSG msg; - GetMessage(&msg, 0, 0, 0); - - STARTUPINFOW si; - PROCESS_INFORMATION pi; - - memset(&si, 0, sizeof(STARTUPINFOW)); - BOOL result = CreateProcessW( - utf16_t(applicationName), GetCommandLineW(), NULL, NULL, TRUE, - DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS, //do not break if application creates its own processes - NULL, NULL, &si, &pi - ); - if(result == false) return false; - - u8 entryData[1024], entryHook[1024] = { - 0x68, 0x00, 0x00, 0x00, 0x00, //push libraryName - 0xb8, 0x00, 0x00, 0x00, 0x00, //mov eax,LoadLibraryW - 0xff, 0xd0, //call eax - 0xcd, 0x03, //int 3 - }; - - entryHook[1] = (u8)((entryPoint + 14) >> 0); - entryHook[2] = (u8)((entryPoint + 14) >> 8); - entryHook[3] = (u8)((entryPoint + 14) >> 16); - entryHook[4] = (u8)((entryPoint + 14) >> 24); - - auto pLoadLibraryW = (u32)GetProcAddress(GetModuleHandleW(L"kernel32"), "LoadLibraryW"); - entryHook[6] = pLoadLibraryW >> 0; - entryHook[7] = pLoadLibraryW >> 8; - entryHook[8] = pLoadLibraryW >> 16; - entryHook[9] = pLoadLibraryW >> 24; - - utf16_t buffer = utf16_t(libraryName); - memcpy(entryHook + 14, buffer, 2 * wcslen(buffer) + 2); - - while(true) { - DEBUG_EVENT event; - WaitForDebugEvent(&event, INFINITE); - - if(event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break; - - if(event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT) { - if(event.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) { - if(event.u.Exception.ExceptionRecord.ExceptionAddress == (void*)(entryPoint + 14 - 1)) { - HANDLE hProcess = OpenProcess(0, FALSE, event.dwProcessId); - HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, event.dwThreadId); - - CONTEXT context; - context.ContextFlags = CONTEXT_FULL; - GetThreadContext(hThread, &context); - - WriteProcessMemory(pi.hProcess, (void*)entryPoint, (void*)&entryData, sizeof entryData, NULL); - context.Eip = entryPoint; - SetThreadContext(hThread, &context); - - CloseHandle(hThread); - CloseHandle(hProcess); - } - - ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE); - continue; - } - - ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_EXCEPTION_NOT_HANDLED); - continue; - } - - if(event.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT) { - ReadProcessMemory(pi.hProcess, (void*)entryPoint, (void*)&entryData, sizeof entryData, NULL); - WriteProcessMemory(pi.hProcess, (void*)entryPoint, (void*)&entryHook, sizeof entryHook, NULL); - - ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE); - continue; - } - - ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE); - } - - return true; -} +auto launch(const char* applicationName, const char* libraryName, u32 entryPoint) -> bool; } + +#if defined(NALL_HEADER_ONLY) + #include +#endif diff --git a/waterbox/ares64/ares/nall/windows/registry.cpp b/waterbox/ares64/ares/nall/windows/registry.cpp new file mode 100644 index 0000000000..7703ab202e --- /dev/null +++ b/waterbox/ares64/ares/nall/windows/registry.cpp @@ -0,0 +1,113 @@ +#include + +#include + +#ifndef KEY_WOW64_64KEY + #define KEY_WOW64_64KEY 0x0100 +#endif +#ifndef KEY_WOW64_32KEY + #define KEY_WOW64_32KEY 0x0200 +#endif + +#ifndef NWR_FLAGS + #define NWR_FLAGS KEY_WOW64_64KEY +#endif + +#ifndef NWR_SIZE + #define NWR_SIZE 4096 +#endif + +namespace nall { + +NALL_HEADER_INLINE auto registry::root(const string& name) { + if(name == "HKCR") return HKEY_CLASSES_ROOT; + if(name == "HKCC") return HKEY_CURRENT_CONFIG; + if(name == "HKCU") return HKEY_CURRENT_USER; + if(name == "HKLM") return HKEY_LOCAL_MACHINE; + if(name == "HKU" ) return HKEY_USERS; + return (HKEY)nullptr; +} + +NALL_HEADER_INLINE auto registry::exists(const string& name) -> bool { + auto part = name.split("\\"); + HKEY handle, rootKey = root(part.takeLeft()); + string node = part.takeRight(); + string path = part.merge("\\"); + if(RegOpenKeyExW(rootKey, utf16_t(path), 0, NWR_FLAGS | KEY_READ, &handle) == ERROR_SUCCESS) { + wchar_t data[NWR_SIZE] = L""; + DWORD size = NWR_SIZE * sizeof(wchar_t); + LONG result = RegQueryValueExW(handle, utf16_t(node), nullptr, nullptr, (LPBYTE)&data, (LPDWORD)&size); + RegCloseKey(handle); + if(result == ERROR_SUCCESS) return true; + } + return false; +} + +NALL_HEADER_INLINE auto registry::read(const string& name) -> string { + auto part = name.split("\\"); + HKEY handle, rootKey = root(part.takeLeft()); + string node = part.takeRight(); + string path = part.merge("\\"); + if(RegOpenKeyExW(rootKey, utf16_t(path), 0, NWR_FLAGS | KEY_READ, &handle) == ERROR_SUCCESS) { + wchar_t data[NWR_SIZE] = L""; + DWORD size = NWR_SIZE * sizeof(wchar_t); + LONG result = RegQueryValueExW(handle, utf16_t(node), nullptr, nullptr, (LPBYTE)&data, (LPDWORD)&size); + RegCloseKey(handle); + if(result == ERROR_SUCCESS) return (const char*)utf8_t(data); + } + return ""; +} + +NALL_HEADER_INLINE auto registry::write(const string& name, const string& data) -> void { + auto part = name.split("\\"); + HKEY handle, rootKey = root(part.takeLeft()); + string node = part.takeRight(), path; + DWORD disposition; + for(u32 n = 0; n < part.size(); n++) { + path.append(part[n]); + if(RegCreateKeyExW(rootKey, utf16_t(path), 0, nullptr, 0, NWR_FLAGS | KEY_ALL_ACCESS, nullptr, &handle, &disposition) == ERROR_SUCCESS) { + if(n == part.size() - 1) { + RegSetValueExW(handle, utf16_t(node), 0, REG_SZ, (BYTE*)(wchar_t*)utf16_t(data), (data.length() + 1) * sizeof(wchar_t)); + } + RegCloseKey(handle); + } + path.append("\\"); + } +} + +NALL_HEADER_INLINE auto registry::remove(const string& name) -> bool { + auto part = name.split("\\"); + HKEY rootKey = root(part.takeLeft()); + string node = part.takeRight(); + string path = part.merge("\\"); + if(!node) return SHDeleteKeyW(rootKey, utf16_t(path)) == ERROR_SUCCESS; + return SHDeleteValueW(rootKey, utf16_t(path), utf16_t(node)) == ERROR_SUCCESS; +} + +NALL_HEADER_INLINE auto registry::contents(const string& name) -> vector { + vector result; + auto part = name.split("\\"); + HKEY handle, rootKey = root(part.takeLeft()); + part.removeRight(); + string path = part.merge("\\"); + if(RegOpenKeyExW(rootKey, utf16_t(path), 0, NWR_FLAGS | KEY_READ, &handle) == ERROR_SUCCESS) { + DWORD folders, nodes; + RegQueryInfoKey(handle, nullptr, nullptr, nullptr, &folders, nullptr, nullptr, &nodes, nullptr, nullptr, nullptr, nullptr); + for(u32 n = 0; n < folders; n++) { + wchar_t name[NWR_SIZE] = L""; + DWORD size = NWR_SIZE * sizeof(wchar_t); + RegEnumKeyEx(handle, n, (wchar_t*)&name, &size, nullptr, nullptr, nullptr, nullptr); + result.append(string{(const char*)utf8_t(name), "\\"}); + } + for(u32 n = 0; n < nodes; n++) { + wchar_t name[NWR_SIZE] = L""; + DWORD size = NWR_SIZE * sizeof(wchar_t); + RegEnumValueW(handle, n, (wchar_t*)&name, &size, nullptr, nullptr, nullptr, nullptr); + result.append((const char*)utf8_t(name)); + } + RegCloseKey(handle); + } + return result; +} + +} diff --git a/waterbox/ares64/ares/nall/windows/registry.hpp b/waterbox/ares64/ares/nall/windows/registry.hpp index e63e037db4..46f59ed2f3 100644 --- a/waterbox/ares64/ares/nall/windows/registry.hpp +++ b/waterbox/ares64/ares/nall/windows/registry.hpp @@ -1,119 +1,27 @@ -#pragma once - -#include -#include - -#include -#undef interface -#ifndef KEY_WOW64_64KEY - #define KEY_WOW64_64KEY 0x0100 -#endif -#ifndef KEY_WOW64_32KEY - #define KEY_WOW64_32KEY 0x0200 -#endif - -#ifndef NWR_FLAGS - #define NWR_FLAGS KEY_WOW64_64KEY -#endif - -#ifndef NWR_SIZE - #define NWR_SIZE 4096 -#endif - -namespace nall { - -struct registry { - static auto exists(const string& name) -> bool { - auto part = name.split("\\"); - HKEY handle, rootKey = root(part.takeLeft()); - string node = part.takeRight(); - string path = part.merge("\\"); - if(RegOpenKeyExW(rootKey, utf16_t(path), 0, NWR_FLAGS | KEY_READ, &handle) == ERROR_SUCCESS) { - wchar_t data[NWR_SIZE] = L""; - DWORD size = NWR_SIZE * sizeof(wchar_t); - LONG result = RegQueryValueExW(handle, utf16_t(node), nullptr, nullptr, (LPBYTE)&data, (LPDWORD)&size); - RegCloseKey(handle); - if(result == ERROR_SUCCESS) return true; - } - return false; - } - - static auto read(const string& name) -> string { - auto part = name.split("\\"); - HKEY handle, rootKey = root(part.takeLeft()); - string node = part.takeRight(); - string path = part.merge("\\"); - if(RegOpenKeyExW(rootKey, utf16_t(path), 0, NWR_FLAGS | KEY_READ, &handle) == ERROR_SUCCESS) { - wchar_t data[NWR_SIZE] = L""; - DWORD size = NWR_SIZE * sizeof(wchar_t); - LONG result = RegQueryValueExW(handle, utf16_t(node), nullptr, nullptr, (LPBYTE)&data, (LPDWORD)&size); - RegCloseKey(handle); - if(result == ERROR_SUCCESS) return (const char*)utf8_t(data); - } - return ""; - } - - static auto write(const string& name, const string& data = "") -> void { - auto part = name.split("\\"); - HKEY handle, rootKey = root(part.takeLeft()); - string node = part.takeRight(), path; - DWORD disposition; - for(u32 n = 0; n < part.size(); n++) { - path.append(part[n]); - if(RegCreateKeyExW(rootKey, utf16_t(path), 0, nullptr, 0, NWR_FLAGS | KEY_ALL_ACCESS, nullptr, &handle, &disposition) == ERROR_SUCCESS) { - if(n == part.size() - 1) { - RegSetValueExW(handle, utf16_t(node), 0, REG_SZ, (BYTE*)(wchar_t*)utf16_t(data), (data.length() + 1) * sizeof(wchar_t)); - } - RegCloseKey(handle); - } - path.append("\\"); - } - } - - static auto remove(const string& name) -> bool { - auto part = name.split("\\"); - HKEY rootKey = root(part.takeLeft()); - string node = part.takeRight(); - string path = part.merge("\\"); - if(!node) return SHDeleteKeyW(rootKey, utf16_t(path)) == ERROR_SUCCESS; - return SHDeleteValueW(rootKey, utf16_t(path), utf16_t(node)) == ERROR_SUCCESS; - } - - static auto contents(const string& name) -> vector { - vector result; - auto part = name.split("\\"); - HKEY handle, rootKey = root(part.takeLeft()); - part.removeRight(); - string path = part.merge("\\"); - if(RegOpenKeyExW(rootKey, utf16_t(path), 0, NWR_FLAGS | KEY_READ, &handle) == ERROR_SUCCESS) { - DWORD folders, nodes; - RegQueryInfoKey(handle, nullptr, nullptr, nullptr, &folders, nullptr, nullptr, &nodes, nullptr, nullptr, nullptr, nullptr); - for(u32 n = 0; n < folders; n++) { - wchar_t name[NWR_SIZE] = L""; - DWORD size = NWR_SIZE * sizeof(wchar_t); - RegEnumKeyEx(handle, n, (wchar_t*)&name, &size, nullptr, nullptr, nullptr, nullptr); - result.append(string{(const char*)utf8_t(name), "\\"}); - } - for(u32 n = 0; n < nodes; n++) { - wchar_t name[NWR_SIZE] = L""; - DWORD size = NWR_SIZE * sizeof(wchar_t); - RegEnumValueW(handle, n, (wchar_t*)&name, &size, nullptr, nullptr, nullptr, nullptr); - result.append((const char*)utf8_t(name)); - } - RegCloseKey(handle); - } - return result; - } - -private: - static auto root(const string& name) -> HKEY { - if(name == "HKCR") return HKEY_CLASSES_ROOT; - if(name == "HKCC") return HKEY_CURRENT_CONFIG; - if(name == "HKCU") return HKEY_CURRENT_USER; - if(name == "HKLM") return HKEY_LOCAL_MACHINE; - if(name == "HKU" ) return HKEY_USERS; - return nullptr; - } -}; - -} +#pragma once + +#include +#include + +namespace nall { + +struct registry { + static auto exists(const string& name) -> bool; + + static auto read(const string& name) -> string; + + static auto write(const string& name, const string& data = "") -> void; + + static auto remove(const string& name) -> bool; + + static auto contents(const string& name) -> vector; + +private: + static auto root(const string& name); +}; + +} + +#if defined(NALL_HEADER_ONLY) + #include +#endif diff --git a/waterbox/ares64/ares/nall/windows/utf8.cpp b/waterbox/ares64/ares/nall/windows/utf8.cpp new file mode 100644 index 0000000000..bf6c13fc39 --- /dev/null +++ b/waterbox/ares64/ares/nall/windows/utf8.cpp @@ -0,0 +1,37 @@ +#include + +#include + +namespace nall { + +NALL_HEADER_INLINE auto utf16_t::operator=(const char* s) -> utf16_t& { + reset(); + if(!s) s = ""; + length = MultiByteToWideChar(CP_UTF8, 0, s, -1, nullptr, 0); + buffer = new wchar_t[length + 1]; + MultiByteToWideChar(CP_UTF8, 0, s, -1, buffer, length); + buffer[length] = 0; + return *this; +} + +NALL_HEADER_INLINE auto utf8_t::operator=(const wchar_t* s) -> utf8_t& { + reset(); + if(!s) s = L""; + length = WideCharToMultiByte(CP_UTF8, 0, s, -1, nullptr, 0, nullptr, nullptr); + buffer = new char[length + 1]; + WideCharToMultiByte(CP_UTF8, 0, s, -1, buffer, length, nullptr, nullptr); + buffer[length] = 0; + return *this; +} + +NALL_HEADER_INLINE auto utf8_arguments(int& argc, char**& argv) -> void { + wchar_t** wargv = CommandLineToArgvW(GetCommandLineW(), &argc); + argv = new char*[argc + 1](); + for(u32 i = 0; i < argc; i++) { + utf8_t arg(wargv[i]); + argv[i] = new char[arg.size() + 1]; + strcpy(argv[i], arg); + } +} + +} diff --git a/waterbox/ares64/ares/nall/windows/utf8.hpp b/waterbox/ares64/ares/nall/windows/utf8.hpp index b13d260adb..d97f20f452 100644 --- a/waterbox/ares64/ares/nall/windows/utf8.hpp +++ b/waterbox/ares64/ares/nall/windows/utf8.hpp @@ -1,5 +1,7 @@ #pragma once +#include + namespace nall { //UTF-8 to UTF-16 struct utf16_t { @@ -9,15 +11,7 @@ namespace nall { utf16_t(const utf16_t&) = delete; auto operator=(const utf16_t&) -> utf16_t& = delete; - auto operator=(const char* s) -> utf16_t& { - reset(); - if(!s) s = ""; - length = MultiByteToWideChar(CP_UTF8, 0, s, -1, nullptr, 0); - buffer = new wchar_t[length + 1]; - MultiByteToWideChar(CP_UTF8, 0, s, -1, buffer, length); - buffer[length] = 0; - return *this; - } + auto operator=(const char* s) -> utf16_t&; operator wchar_t*() { return buffer; } operator const wchar_t*() const { return buffer; } @@ -45,15 +39,7 @@ namespace nall { utf8_t(const utf8_t&) = delete; auto operator=(const utf8_t&) -> utf8_t& = delete; - auto operator=(const wchar_t* s) -> utf8_t& { - reset(); - if(!s) s = L""; - length = WideCharToMultiByte(CP_UTF8, 0, s, -1, nullptr, 0, nullptr, nullptr); - buffer = new char[length + 1]; - WideCharToMultiByte(CP_UTF8, 0, s, -1, buffer, length, nullptr, nullptr); - buffer[length] = 0; - return *this; - } + auto operator=(const wchar_t* s) -> utf8_t&; auto reset() -> void { delete[] buffer; @@ -73,12 +59,10 @@ namespace nall { u32 length = 0; }; - inline auto utf8_arguments(int& argc, char**& argv) -> void { - wchar_t** wargv = CommandLineToArgvW(GetCommandLineW(), &argc); - argv = new char*[argc + 1](); - for(u32 i = 0; i < argc; i++) { - argv[i] = new char[PATH_MAX]; - strcpy(argv[i], nall::utf8_t(wargv[i])); - } - } + auto utf8_arguments(int& argc, char**& argv) -> void; + } + +#if defined(NALL_HEADER_ONLY) + #include +#endif diff --git a/waterbox/ares64/ares/nall/windows/windows.hpp b/waterbox/ares64/ares/nall/windows/windows.hpp new file mode 100644 index 0000000000..edb1b2e90d --- /dev/null +++ b/waterbox/ares64/ares/nall/windows/windows.hpp @@ -0,0 +1,12 @@ +#pragma once + +#undef NOMINMAX +#define NOMINMAX + +#undef UNICODE +#define UNICODE + +#undef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN + +#include diff --git a/waterbox/ares64/ares/thirdparty/angrylion-rdp b/waterbox/ares64/ares/thirdparty/angrylion-rdp index 7b20c1c308..1bd37704d0 160000 --- a/waterbox/ares64/ares/thirdparty/angrylion-rdp +++ b/waterbox/ares64/ares/thirdparty/angrylion-rdp @@ -1 +1 @@ -Subproject commit 7b20c1c308340fcf8ccd15b97ebbb52a61c3cca0 +Subproject commit 1bd37704d0d48d85ab2ed36140d8f9c012dcf804 diff --git a/waterbox/ares64/ares/thirdparty/sljit/API_CHANGES b/waterbox/ares64/ares/thirdparty/sljit/API_CHANGES index 34e2702c16..8ec367e302 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/API_CHANGES +++ b/waterbox/ares64/ares/thirdparty/sljit/API_CHANGES @@ -1,5 +1,30 @@ This file is the short summary of the API changes: +02.02.2022 - Backward compatible + All SLJIT_SET_* constants are + even numbers. + +27.01.2022 - Non-backward compatible + The arguments of sljit_emit_shift_into + are changed. + +17.12.2022 - Non-backward compatible + Replace sljit_emit_fast_enter and + sljit_get_return_address with + sljit_emit_op_dst. + +13.12.2022 - Non-backward compatible + Replace SLJIT_NOT with SLJIT_XOR. + +10.11.2022 - Non-backward compatible + Extract the pre/post update operations from + sljit_emit_mem to sljit_emit_mem_update + and sljit_emit_fmem to sljit_emit_fmem_update. + +04.11.2022 - Non-backward compatible + The SLJIT_32 flag is combined with the type + argument of cmov, not the dst_reg. + 16.06.2022 - Non-backward compatible Remove SLJIT_ENTER_CDECL and SLJIT_CALL_CDECL. The default calling mode is cdecl now. @@ -8,7 +33,7 @@ This file is the short summary of the API changes: Floating point comparison types are renamed. 01.03.2022 - Non-backward compatible - Remove SLJIT_NEG. Instead substraction from + Remove SLJIT_NEG. Instead subtraction from immedate 0 is preferred. 31.01.2022 - Non-backward compatible diff --git a/waterbox/ares64/ares/thirdparty/sljit/Makefile b/waterbox/ares64/ares/thirdparty/sljit/Makefile index 8ac03ad773..eb85af35b3 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/Makefile +++ b/waterbox/ares64/ares/thirdparty/sljit/Makefile @@ -32,7 +32,10 @@ EXAMPLE_TARGET = $(BINDIR)/func_call $(BINDIR)/first_program $(BINDIR)/branch $( SLJIT_HEADERS = $(SRCDIR)/sljitLir.h $(SRCDIR)/sljitConfig.h $(SRCDIR)/sljitConfigInternal.h SLJIT_LIR_FILES = $(SRCDIR)/sljitLir.c $(SRCDIR)/sljitUtils.c \ - $(SRCDIR)/sljitExecAllocator.c $(SRCDIR)/sljitProtExecAllocator.c $(SRCDIR)/sljitWXExecAllocator.c \ + $(SRCDIR)/allocator_src/sljitExecAllocatorCore.c $(SRCDIR)/allocator_src/sljitExecAllocatorApple.c \ + $(SRCDIR)/allocator_src/sljitExecAllocatorPosix.c $(SRCDIR)/allocator_src/sljitExecAllocatorWindows.c \ + $(SRCDIR)/allocator_src/sljitProtExecAllocatorNetBSD.c $(SRCDIR)/allocator_src/sljitProtExecAllocatorPosix.c \ + $(SRCDIR)/allocator_src/sljitWXExecAllocatorPosix.c $(SRCDIR)/allocator_src/sljitWXExecAllocatorWindows.c \ $(SRCDIR)/sljitNativeARM_32.c $(SRCDIR)/sljitNativeARM_T2_32.c $(SRCDIR)/sljitNativeARM_64.c \ $(SRCDIR)/sljitNativeMIPS_common.c $(SRCDIR)/sljitNativeMIPS_32.c $(SRCDIR)/sljitNativeMIPS_64.c \ $(SRCDIR)/sljitNativePPC_common.c $(SRCDIR)/sljitNativePPC_32.c $(SRCDIR)/sljitNativePPC_64.c \ diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitExecAllocatorApple.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitExecAllocatorApple.c new file mode 100644 index 0000000000..6352377c4d --- /dev/null +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitExecAllocatorApple.c @@ -0,0 +1,118 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +/* + On macOS systems, returns MAP_JIT if it is defined _and_ we're running on a + version where it's OK to have more than one JIT block or where MAP_JIT is + required. + On non-macOS systems, returns MAP_JIT if it is defined. +*/ +#include +#if TARGET_OS_OSX +#if defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86 +#include +#include + +#define SLJIT_MAP_JIT (get_map_jit_flag()) +#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) + +static SLJIT_INLINE int get_map_jit_flag() +{ + size_t page_size; + void *ptr; + struct utsname name; + static int map_jit_flag = -1; + + if (map_jit_flag < 0) { + map_jit_flag = 0; + uname(&name); + + /* Kernel version for 10.14.0 (Mojave) or later */ + if (atoi(name.release) >= 18) { + page_size = get_page_alignment() + 1; + /* Only use MAP_JIT if a hardened runtime is used */ + ptr = mmap(NULL, page_size, PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANON, -1, 0); + + if (ptr != MAP_FAILED) + munmap(ptr, page_size); + else + map_jit_flag = MAP_JIT; + } + } + return map_jit_flag; +} +#else /* !SLJIT_CONFIG_X86 */ +#if !(defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) +#error "Unsupported architecture" +#endif /* SLJIT_CONFIG_ARM */ + +#include +#include + +#define SLJIT_MAP_JIT (MAP_JIT) +#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) \ + apple_update_wx_flags(enable_exec) + +static SLJIT_INLINE void apple_update_wx_flags(sljit_s32 enable_exec) +{ +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 110000 + pthread_jit_write_protect_np(enable_exec); +#else +#error "Must target Big Sur or newer" +#endif /* BigSur */ +} +#endif /* SLJIT_CONFIG_X86 */ +#else /* !TARGET_OS_OSX */ +#define SLJIT_MAP_JIT (MAP_JIT) +#endif /* TARGET_OS_OSX */ + +static SLJIT_INLINE void* alloc_chunk(sljit_uw size) +{ + void *retval; + int prot = PROT_READ | PROT_WRITE | PROT_EXEC; + int flags = MAP_PRIVATE; + int fd = -1; + + flags |= MAP_ANON | SLJIT_MAP_JIT; + + retval = mmap(NULL, size, prot, flags, fd, 0); + if (retval == MAP_FAILED) + return NULL; + + SLJIT_UPDATE_WX_FLAGS(retval, (uint8_t *)retval + size, 0); + + return retval; +} + +static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size) +{ + munmap(chunk, size); +} + +#include "sljitExecAllocatorCore.c" diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitExecAllocator.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitExecAllocatorCore.c similarity index 64% rename from waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitExecAllocator.c rename to waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitExecAllocatorCore.c index 92d940ddc2..6cd391104c 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitExecAllocator.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitExecAllocatorCore.c @@ -61,166 +61,42 @@ [ one big free block ] */ -/* --------------------------------------------------------------------- */ -/* System (OS) functions */ -/* --------------------------------------------------------------------- */ +/* Expected functions: + alloc_chunk / free_chunk : + * allocate executable system memory chunks + * the size is always divisible by CHUNK_SIZE + SLJIT_ALLOCATOR_LOCK / SLJIT_ALLOCATOR_UNLOCK : + * provided as part of sljitUtils + * only the allocator requires this lock, sljit is fully thread safe + as it only uses local variables -/* 64 KByte. */ -#define CHUNK_SIZE (sljit_uw)0x10000u - -/* - alloc_chunk / free_chunk : - * allocate executable system memory chunks - * the size is always divisible by CHUNK_SIZE - SLJIT_ALLOCATOR_LOCK / SLJIT_ALLOCATOR_UNLOCK : - * provided as part of sljitUtils - * only the allocator requires this lock, sljit is fully thread safe - as it only uses local variables + Supported defines: + SLJIT_HAS_CHUNK_HEADER - (optional) sljit_chunk_header is defined + SLJIT_HAS_EXECUTABLE_OFFSET - (optional) has executable offset data + SLJIT_UPDATE_WX_FLAGS - (optional) update WX flags */ -#ifdef _WIN32 -#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) +#ifdef SLJIT_HAS_CHUNK_HEADER +#define CHUNK_HEADER_SIZE (sizeof(struct sljit_chunk_header)) +#else /* !SLJIT_HAS_CHUNK_HEADER */ +#define CHUNK_HEADER_SIZE 0 +#endif /* SLJIT_HAS_CHUNK_HEADER */ -static SLJIT_INLINE void* alloc_chunk(sljit_uw size) -{ - return VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); -} - -static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size) -{ - SLJIT_UNUSED_ARG(size); - VirtualFree(chunk, 0, MEM_RELEASE); -} - -#else /* POSIX */ - -#if defined(__APPLE__) && defined(MAP_JIT) -/* - On macOS systems, returns MAP_JIT if it is defined _and_ we're running on a - version where it's OK to have more than one JIT block or where MAP_JIT is - required. - On non-macOS systems, returns MAP_JIT if it is defined. -*/ -#include -#if TARGET_OS_OSX -#if defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86 -#ifdef MAP_ANON -#include -#include - -#define SLJIT_MAP_JIT (get_map_jit_flag()) - -static SLJIT_INLINE int get_map_jit_flag() -{ - size_t page_size; - void *ptr; - struct utsname name; - static int map_jit_flag = -1; - - if (map_jit_flag < 0) { - map_jit_flag = 0; - uname(&name); - - /* Kernel version for 10.14.0 (Mojave) or later */ - if (atoi(name.release) >= 18) { - page_size = get_page_alignment() + 1; - /* Only use MAP_JIT if a hardened runtime is used */ - ptr = mmap(NULL, page_size, PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANON, -1, 0); - - if (ptr != MAP_FAILED) - munmap(ptr, page_size); - else - map_jit_flag = MAP_JIT; - } - } - return map_jit_flag; -} -#endif /* MAP_ANON */ -#else /* !SLJIT_CONFIG_X86 */ -#if !(defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) -#error "Unsupported architecture" -#endif /* SLJIT_CONFIG_ARM */ -#include -#include - -#define SLJIT_MAP_JIT (MAP_JIT) -#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) \ - apple_update_wx_flags(enable_exec) - -static SLJIT_INLINE void apple_update_wx_flags(sljit_s32 enable_exec) -{ -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 110000 - pthread_jit_write_protect_np(enable_exec); -#else -#error "Must target Big Sur or newer" -#endif /* BigSur */ -} -#endif /* SLJIT_CONFIG_X86 */ -#else /* !TARGET_OS_OSX */ -#define SLJIT_MAP_JIT (MAP_JIT) -#endif /* TARGET_OS_OSX */ -#endif /* __APPLE__ && MAP_JIT */ #ifndef SLJIT_UPDATE_WX_FLAGS #define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) -#endif /* !SLJIT_UPDATE_WX_FLAGS */ -#ifndef SLJIT_MAP_JIT -#define SLJIT_MAP_JIT (0) -#endif /* !SLJIT_MAP_JIT */ +#endif /* SLJIT_UPDATE_WX_FLAGS */ -static SLJIT_INLINE void* alloc_chunk(sljit_uw size) -{ - void *retval; - int prot = PROT_READ | PROT_WRITE | PROT_EXEC; - int flags = MAP_PRIVATE; - int fd = -1; - -#ifdef PROT_MAX - prot |= PROT_MAX(prot); -#endif - -#ifdef MAP_ANON - flags |= MAP_ANON | SLJIT_MAP_JIT; -#else /* !MAP_ANON */ - if (SLJIT_UNLIKELY((dev_zero < 0) && open_dev_zero())) - return NULL; - - fd = dev_zero; -#endif /* MAP_ANON */ - - retval = mmap(NULL, size, prot, flags, fd, 0); - if (retval == MAP_FAILED) - return NULL; - -#ifdef __FreeBSD__ - /* HardenedBSD's mmap lies, so check permissions again */ - if (mprotect(retval, size, PROT_READ | PROT_WRITE | PROT_EXEC) < 0) { - munmap(retval, size); - return NULL; - } -#endif /* FreeBSD */ - - SLJIT_UPDATE_WX_FLAGS(retval, (uint8_t *)retval + size, 0); - - return retval; -} - -static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size) -{ - munmap(chunk, size); -} - -#endif /* windows */ - -/* --------------------------------------------------------------------- */ -/* Common functions */ -/* --------------------------------------------------------------------- */ - -#define CHUNK_MASK (~(CHUNK_SIZE - 1)) +#ifndef CHUNK_SIZE +/* 64 KByte if not specified. */ +#define CHUNK_SIZE (sljit_uw)0x10000 +#endif /* CHUNK_SIZE */ struct block_header { sljit_uw size; sljit_uw prev_size; +#ifdef SLJIT_HAS_EXECUTABLE_OFFSET + sljit_sw executable_offset; +#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */ }; struct free_block { @@ -234,8 +110,10 @@ struct free_block { ((struct block_header*)(((sljit_u8*)base) + offset)) #define AS_FREE_BLOCK(base, offset) \ ((struct free_block*)(((sljit_u8*)base) + offset)) -#define MEM_START(base) ((void*)(((sljit_u8*)base) + sizeof(struct block_header))) +#define MEM_START(base) ((void*)((base) + 1)) +#define CHUNK_MASK (~(CHUNK_SIZE - 1)) #define ALIGN_SIZE(size) (((size) + sizeof(struct block_header) + 7u) & ~(sljit_uw)7) +#define CHUNK_EXTRA_SIZE (sizeof(struct block_header) + CHUNK_HEADER_SIZE) static struct free_block* free_blocks; static sljit_uw allocated_size; @@ -273,11 +151,21 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size) struct free_block *free_block; sljit_uw chunk_size; - SLJIT_ALLOCATOR_LOCK(); +#ifdef SLJIT_HAS_CHUNK_HEADER + struct sljit_chunk_header *chunk_header; +#else /* !SLJIT_HAS_CHUNK_HEADER */ + void *chunk_header; +#endif /* SLJIT_HAS_CHUNK_HEADER */ + +#ifdef SLJIT_HAS_EXECUTABLE_OFFSET + sljit_sw executable_offset; +#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */ + if (size < (64 - sizeof(struct block_header))) size = (64 - sizeof(struct block_header)); size = ALIGN_SIZE(size); + SLJIT_ALLOCATOR_LOCK(); free_block = free_blocks; while (free_block) { if (free_block->size >= size) { @@ -289,6 +177,9 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size) free_block->size = chunk_size; header = AS_BLOCK_HEADER(free_block, chunk_size); header->prev_size = chunk_size; +#ifdef SLJIT_HAS_EXECUTABLE_OFFSET + header->executable_offset = free_block->header.executable_offset; +#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */ AS_BLOCK_HEADER(header, size)->prev_size = size; } else { @@ -304,17 +195,28 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size) free_block = free_block->next; } - chunk_size = (size + sizeof(struct block_header) + CHUNK_SIZE - 1) & CHUNK_MASK; - header = (struct block_header*)alloc_chunk(chunk_size); - if (!header) { + chunk_size = (size + CHUNK_EXTRA_SIZE + CHUNK_SIZE - 1) & CHUNK_MASK; + + chunk_header = alloc_chunk(chunk_size); + if (!chunk_header) { SLJIT_ALLOCATOR_UNLOCK(); return NULL; } - chunk_size -= sizeof(struct block_header); +#ifdef SLJIT_HAS_EXECUTABLE_OFFSET + executable_offset = (sljit_sw)((sljit_u8*)chunk_header->executable - (sljit_u8*)chunk_header); +#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */ + + chunk_size -= CHUNK_EXTRA_SIZE; total_size += chunk_size; + header = (struct block_header*)(((sljit_u8*)chunk_header) + CHUNK_HEADER_SIZE); + header->prev_size = 0; +#ifdef SLJIT_HAS_EXECUTABLE_OFFSET + header->executable_offset = executable_offset; +#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */ + if (chunk_size > size + 64) { /* Cut the allocated space into a free and a used block. */ allocated_size += size; @@ -323,6 +225,9 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size) free_block = AS_FREE_BLOCK(header, size); free_block->header.prev_size = size; +#ifdef SLJIT_HAS_EXECUTABLE_OFFSET + free_block->header.executable_offset = executable_offset; +#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */ sljit_insert_free_block(free_block, chunk_size); next_header = AS_BLOCK_HEADER(free_block, chunk_size); } @@ -332,9 +237,12 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size) header->size = chunk_size; next_header = AS_BLOCK_HEADER(header, chunk_size); } + SLJIT_ALLOCATOR_UNLOCK(); next_header->size = 1; next_header->prev_size = chunk_size; - SLJIT_ALLOCATOR_UNLOCK(); +#ifdef SLJIT_HAS_EXECUTABLE_OFFSET + next_header->executable_offset = executable_offset; +#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */ return MEM_START(header); } @@ -345,11 +253,15 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr) SLJIT_ALLOCATOR_LOCK(); header = AS_BLOCK_HEADER(ptr, -(sljit_sw)sizeof(struct block_header)); +#ifdef SLJIT_HAS_EXECUTABLE_OFFSET + header = AS_BLOCK_HEADER(header, -header->executable_offset); +#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */ allocated_size -= header->size; - /* Connecting free blocks together if possible. */ SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 0); + /* Connecting free blocks together if possible. */ + /* If header->prev_size == 0, free_block will equal to header. In this case, free_block->header.size will be > 0. */ free_block = AS_FREE_BLOCK(header, -(sljit_sw)header->prev_size); @@ -377,7 +289,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr) if (total_size - free_block->size > (allocated_size * 3 / 2)) { total_size -= free_block->size; sljit_remove_free_block(free_block); - free_chunk(free_block, free_block->size + sizeof(struct block_header)); + free_chunk(free_block, free_block->size + CHUNK_EXTRA_SIZE); } } @@ -400,7 +312,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void) AS_BLOCK_HEADER(free_block, free_block->size)->size == 1) { total_size -= free_block->size; sljit_remove_free_block(free_block); - free_chunk(free_block, free_block->size + sizeof(struct block_header)); + free_chunk(free_block, free_block->size + CHUNK_EXTRA_SIZE); } free_block = next_free_block; } @@ -409,3 +321,10 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void) SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 1); SLJIT_ALLOCATOR_UNLOCK(); } + +#ifdef SLJIT_HAS_EXECUTABLE_OFFSET +SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr) +{ + return ((struct block_header *)(ptr))[-1].executable_offset; +} +#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */ diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitExecAllocatorFreeBSD.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitExecAllocatorFreeBSD.c new file mode 100644 index 0000000000..3b93a4df76 --- /dev/null +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitExecAllocatorFreeBSD.c @@ -0,0 +1,89 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#ifdef PROC_WXMAP_CTL +static SLJIT_INLINE int sljit_is_wx_block(void) +{ + static int wx_block = -1; + if (wx_block < 0) { + int sljit_wx_enable = PROC_WX_MAPPINGS_PERMIT; + wx_block = !!procctl(P_PID, 0, PROC_WXMAP_CTL, &sljit_wx_enable); + } + return wx_block; +} + +#define SLJIT_IS_WX_BLOCK sljit_is_wx_block() +#else /* !PROC_WXMAP_CTL */ +#define SLJIT_IS_WX_BLOCK (1) +#endif /* PROC_WXMAP_CTL */ + +static SLJIT_INLINE void* alloc_chunk(sljit_uw size) +{ + void *retval; + int prot = PROT_READ | PROT_WRITE | PROT_EXEC; + int flags = MAP_PRIVATE; + int fd = -1; + +#ifdef PROT_MAX + prot |= PROT_MAX(prot); +#endif + +#ifdef MAP_ANON + flags |= MAP_ANON; +#else /* !MAP_ANON */ + if (SLJIT_UNLIKELY((dev_zero < 0) && open_dev_zero())) + return NULL; + + fd = dev_zero; +#endif /* MAP_ANON */ + +retry: + retval = mmap(NULL, size, prot, flags, fd, 0); + if (retval == MAP_FAILED) { + if (!SLJIT_IS_WX_BLOCK) + goto retry; + + return NULL; + } + + /* HardenedBSD's mmap lies, so check permissions again. */ + if (mprotect(retval, size, PROT_READ | PROT_WRITE | PROT_EXEC) < 0) { + munmap(retval, size); + return NULL; + } + + return retval; +} + +static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size) +{ + munmap(chunk, size); +} + +#include "sljitExecAllocatorCore.c" diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitExecAllocatorPosix.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitExecAllocatorPosix.c new file mode 100644 index 0000000000..a775f5629a --- /dev/null +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitExecAllocatorPosix.c @@ -0,0 +1,62 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +static SLJIT_INLINE void* alloc_chunk(sljit_uw size) +{ + void *retval; + int prot = PROT_READ | PROT_WRITE | PROT_EXEC; + int flags = MAP_PRIVATE; + int fd = -1; + +#ifdef PROT_MAX + prot |= PROT_MAX(prot); +#endif + +#ifdef MAP_ANON + flags |= MAP_ANON; +#else /* !MAP_ANON */ + if (SLJIT_UNLIKELY((dev_zero < 0) && open_dev_zero())) + return NULL; + + fd = dev_zero; +#endif /* MAP_ANON */ + + retval = mmap(NULL, size, prot, flags, fd, 0); + if (retval == MAP_FAILED) + return NULL; + + return retval; +} + +static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size) +{ + munmap(chunk, size); +} + +#include "sljitExecAllocatorCore.c" diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitExecAllocatorWindows.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitExecAllocatorWindows.c new file mode 100644 index 0000000000..f152a5a2cd --- /dev/null +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitExecAllocatorWindows.c @@ -0,0 +1,40 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) + +static SLJIT_INLINE void* alloc_chunk(sljit_uw size) +{ + return VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); +} + +static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size) +{ + SLJIT_UNUSED_ARG(size); + VirtualFree(chunk, 0, MEM_RELEASE); +} + +#include "sljitExecAllocatorCore.c" diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitProtExecAllocatorNetBSD.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitProtExecAllocatorNetBSD.c new file mode 100644 index 0000000000..0b7fd57787 --- /dev/null +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitProtExecAllocatorNetBSD.c @@ -0,0 +1,72 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define SLJIT_HAS_CHUNK_HEADER +#define SLJIT_HAS_EXECUTABLE_OFFSET + +struct sljit_chunk_header { + void *executable; +}; + +/* + * MAP_REMAPDUP is a NetBSD extension available sinde 8.0, make sure to + * adjust your feature macros (ex: -D_NETBSD_SOURCE) as needed + */ +static SLJIT_INLINE struct sljit_chunk_header* alloc_chunk(sljit_uw size) +{ + struct sljit_chunk_header *retval; + + retval = (struct sljit_chunk_header *)mmap(NULL, size, + PROT_READ | PROT_WRITE | PROT_MPROTECT(PROT_EXEC), + MAP_ANON | MAP_SHARED, -1, 0); + + if (retval == MAP_FAILED) + return NULL; + + retval->executable = mremap(retval, size, NULL, size, MAP_REMAPDUP); + if (retval->executable == MAP_FAILED) { + munmap((void *)retval, size); + return NULL; + } + + if (mprotect(retval->executable, size, PROT_READ | PROT_EXEC) == -1) { + munmap(retval->executable, size); + munmap((void *)retval, size); + return NULL; + } + + return retval; +} + +static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size) +{ + struct sljit_chunk_header *header = ((struct sljit_chunk_header *)chunk) - 1; + + munmap(header->executable, size); + munmap((void *)header, size); +} + +#include "sljitExecAllocatorCore.c" diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitProtExecAllocatorPosix.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitProtExecAllocatorPosix.c new file mode 100644 index 0000000000..f7cb6c5670 --- /dev/null +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitProtExecAllocatorPosix.c @@ -0,0 +1,172 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define SLJIT_HAS_CHUNK_HEADER +#define SLJIT_HAS_EXECUTABLE_OFFSET + +struct sljit_chunk_header { + void *executable; +}; + +#include +#include +#include +#include + +#ifndef O_NOATIME +#define O_NOATIME 0 +#endif + +/* this is a linux extension available since kernel 3.11 */ +#ifndef O_TMPFILE +#define O_TMPFILE 0x404000 +#endif + +#ifndef _GNU_SOURCE +char *secure_getenv(const char *name); +int mkostemp(char *template, int flags); +#endif + +static SLJIT_INLINE int create_tempfile(void) +{ + int fd; + char tmp_name[256]; + size_t tmp_name_len = 0; + char *dir; + struct stat st; +#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED + mode_t mode; +#endif + +#ifdef HAVE_MEMFD_CREATE + /* this is a GNU extension, make sure to use -D_GNU_SOURCE */ + fd = memfd_create("sljit", MFD_CLOEXEC); + if (fd != -1) { + fchmod(fd, 0); + return fd; + } +#endif + + dir = secure_getenv("TMPDIR"); + + if (dir) { + size_t len = strlen(dir); + if (len > 0 && len < sizeof(tmp_name)) { + if ((stat(dir, &st) == 0) && S_ISDIR(st.st_mode)) { + memcpy(tmp_name, dir, len + 1); + tmp_name_len = len; + } + } + } + +#ifdef P_tmpdir + if (!tmp_name_len) { + tmp_name_len = strlen(P_tmpdir); + if (tmp_name_len > 0 && tmp_name_len < sizeof(tmp_name)) + strcpy(tmp_name, P_tmpdir); + } +#endif + if (!tmp_name_len) { + strcpy(tmp_name, "/tmp"); + tmp_name_len = 4; + } + + SLJIT_ASSERT(tmp_name_len > 0 && tmp_name_len < sizeof(tmp_name)); + + if (tmp_name_len > 1 && tmp_name[tmp_name_len - 1] == '/') + tmp_name[--tmp_name_len] = '\0'; + + fd = open(tmp_name, O_TMPFILE | O_EXCL | O_RDWR | O_NOATIME | O_CLOEXEC, 0); + if (fd != -1) + return fd; + + if (tmp_name_len >= sizeof(tmp_name) - 7) + return -1; + + strcpy(tmp_name + tmp_name_len, "/XXXXXX"); +#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED + mode = umask(0777); +#endif + fd = mkostemp(tmp_name, O_CLOEXEC | O_NOATIME); +#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED + umask(mode); +#else + fchmod(fd, 0); +#endif + + if (fd == -1) + return -1; + + if (unlink(tmp_name)) { + close(fd); + return -1; + } + + return fd; +} + +static SLJIT_INLINE struct sljit_chunk_header* alloc_chunk(sljit_uw size) +{ + struct sljit_chunk_header *retval; + int fd; + + fd = create_tempfile(); + if (fd == -1) + return NULL; + + if (ftruncate(fd, (off_t)size)) { + close(fd); + return NULL; + } + + retval = (struct sljit_chunk_header *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + if (retval == MAP_FAILED) { + close(fd); + return NULL; + } + + retval->executable = mmap(NULL, size, PROT_READ | PROT_EXEC, MAP_SHARED, fd, 0); + + if (retval->executable == MAP_FAILED) { + munmap((void *)retval, size); + close(fd); + return NULL; + } + + close(fd); + return retval; +} + +static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size) +{ + struct sljit_chunk_header *header = ((struct sljit_chunk_header *)chunk) - 1; + + munmap(header->executable, size); + munmap((void *)header, size); +} + +#include "sljitExecAllocatorCore.c" diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitWXExecAllocator.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitWXExecAllocatorPosix.c similarity index 66% rename from waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitWXExecAllocator.c rename to waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitWXExecAllocatorPosix.c index 6893813155..36d301434a 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitWXExecAllocator.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitWXExecAllocatorPosix.c @@ -25,8 +25,7 @@ */ /* - This file contains a simple W^X executable memory allocator for POSIX - like systems and Windows + This file contains a simple W^X executable memory allocator In *NIX, MAP_ANON is required (that is considered a feature) so make sure to set the right availability macros for your system or the code @@ -51,55 +50,41 @@ not possible. */ -#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) \ - sljit_update_wx_flags((from), (to), (enable_exec)) - -#ifndef _WIN32 #include #include -#ifdef __NetBSD__ -#define SLJIT_PROT_WX PROT_MPROTECT(PROT_EXEC) -#define check_se_protected(ptr, size) (0) -#else /* POSIX */ +#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) \ + sljit_update_wx_flags((from), (to), (enable_exec)) + #if !(defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED) #include #define SLJIT_SE_LOCK() pthread_mutex_lock(&se_lock) #define SLJIT_SE_UNLOCK() pthread_mutex_unlock(&se_lock) +#else +#define SLJIT_SE_LOCK() +#define SLJIT_SE_UNLOCK() #endif /* !SLJIT_SINGLE_THREADED */ -#define check_se_protected(ptr, size) generic_se_protected(ptr, size) +#define SLJIT_WX_IS_BLOCK(ptr, size) generic_check_is_wx_block(ptr, size) -static SLJIT_INLINE int generic_se_protected(void *ptr, sljit_uw size) +static SLJIT_INLINE int generic_check_is_wx_block(void *ptr, sljit_uw size) { if (SLJIT_LIKELY(!mprotect(ptr, size, PROT_EXEC))) - return mprotect(ptr, size, PROT_READ | PROT_WRITE); + return !!mprotect(ptr, size, PROT_READ | PROT_WRITE); - return -1; + return 1; } -#endif /* NetBSD */ - -#ifndef SLJIT_SE_LOCK -#define SLJIT_SE_LOCK() -#endif -#ifndef SLJIT_SE_UNLOCK -#define SLJIT_SE_UNLOCK() -#endif -#ifndef SLJIT_PROT_WX -#define SLJIT_PROT_WX 0 -#endif SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size) { -#if !(defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED) \ - && !defined(__NetBSD__) +#if !(defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED) static pthread_mutex_t se_lock = PTHREAD_MUTEX_INITIALIZER; #endif - static int se_protected = !SLJIT_PROT_WX; - int prot = PROT_READ | PROT_WRITE | SLJIT_PROT_WX; + static int wx_block = -1; + int prot = PROT_READ | PROT_WRITE; sljit_uw* ptr; - if (SLJIT_UNLIKELY(se_protected < 0)) + if (SLJIT_UNLIKELY(wx_block > 0)) return NULL; #ifdef PROT_MAX @@ -112,11 +97,11 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size) if (ptr == MAP_FAILED) return NULL; - if (SLJIT_UNLIKELY(se_protected > 0)) { + if (SLJIT_UNLIKELY(wx_block < 0)) { SLJIT_SE_LOCK(); - se_protected = check_se_protected(ptr, size); + wx_block = SLJIT_WX_IS_BLOCK(ptr, size); SLJIT_SE_UNLOCK(); - if (SLJIT_UNLIKELY(se_protected < 0)) { + if (SLJIT_UNLIKELY(wx_block)) { munmap((void *)ptr, size); return NULL; } @@ -126,7 +111,6 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size) return ptr; } -#undef SLJIT_PROT_WX #undef SLJIT_SE_UNLOCK #undef SLJIT_SE_LOCK @@ -136,7 +120,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr) munmap((void*)start_ptr, *start_ptr); } -static void sljit_update_wx_flags(void *from, void *to, sljit_s32 enable_exec) +static void sljit_update_wx_flags(void *from, void *to, int enable_exec) { sljit_uw page_mask = (sljit_uw)get_page_alignment(); sljit_uw start = (sljit_uw)from; @@ -151,53 +135,6 @@ static void sljit_update_wx_flags(void *from, void *to, sljit_s32 enable_exec) mprotect((void*)start, end - start, prot); } -#else /* windows */ - -SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size) -{ - sljit_uw *ptr; - - size += sizeof(sljit_uw); - ptr = (sljit_uw*)VirtualAlloc(NULL, size, - MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - - if (!ptr) - return NULL; - - *ptr++ = size; - - return ptr; -} - -SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr) -{ - sljit_uw start = (sljit_uw)ptr - sizeof(sljit_uw); -#if defined(SLJIT_DEBUG) && SLJIT_DEBUG - sljit_uw page_mask = (sljit_uw)get_page_alignment(); - - SLJIT_ASSERT(!(start & page_mask)); -#endif - VirtualFree((void*)start, 0, MEM_RELEASE); -} - -static void sljit_update_wx_flags(void *from, void *to, sljit_s32 enable_exec) -{ - DWORD oldprot; - sljit_uw page_mask = (sljit_uw)get_page_alignment(); - sljit_uw start = (sljit_uw)from; - sljit_uw end = (sljit_uw)to; - DWORD prot = enable_exec ? PAGE_EXECUTE : PAGE_READWRITE; - - SLJIT_ASSERT(start < end); - - start &= ~page_mask; - end = (end + page_mask) & ~page_mask; - - VirtualProtect((void*)start, end - start, prot, &oldprot); -} - -#endif /* !windows */ - SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void) { /* This allocator does not keep unused memory for future allocations. */ diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitWXExecAllocatorWindows.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitWXExecAllocatorWindows.c new file mode 100644 index 0000000000..a9553bd7da --- /dev/null +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitWXExecAllocatorWindows.c @@ -0,0 +1,102 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + This file contains a simple W^X executable memory allocator + + In *NIX, MAP_ANON is required (that is considered a feature) so make + sure to set the right availability macros for your system or the code + will fail to build. + + If your system doesn't support mapping of anonymous pages (ex: IRIX) it + is also likely that it doesn't need this allocator and should be using + the standard one instead. + + It allocates a separate map for each code block and may waste a lot of + memory, because whatever was requested, will be rounded up to the page + size (minimum 4KB, but could be even bigger). + + It changes the page permissions (RW <-> RX) as needed and therefore, if you + will be updating the code after it has been generated, need to make sure to + block any concurrent execution, or could result in a SIGBUS, that could + even manifest itself at a different address than the one that was being + modified. + + Only use if you are unable to use the regular allocator because of security + restrictions and adding exceptions to your application or the system are + not possible. +*/ + +#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) \ + sljit_update_wx_flags((from), (to), (enable_exec)) + +SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size) +{ + sljit_uw *ptr; + + size += sizeof(sljit_uw); + ptr = (sljit_uw*)VirtualAlloc(NULL, size, + MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + + if (!ptr) + return NULL; + + *ptr++ = size; + + return ptr; +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr) +{ + sljit_uw start = (sljit_uw)ptr - sizeof(sljit_uw); +#if defined(SLJIT_DEBUG) && SLJIT_DEBUG + sljit_uw page_mask = (sljit_uw)get_page_alignment(); + + SLJIT_ASSERT(!(start & page_mask)); +#endif + VirtualFree((void*)start, 0, MEM_RELEASE); +} + +static void sljit_update_wx_flags(void *from, void *to, sljit_s32 enable_exec) +{ + DWORD oldprot; + sljit_uw page_mask = (sljit_uw)get_page_alignment(); + sljit_uw start = (sljit_uw)from; + sljit_uw end = (sljit_uw)to; + DWORD prot = enable_exec ? PAGE_EXECUTE : PAGE_READWRITE; + + SLJIT_ASSERT(start < end); + + start &= ~page_mask; + end = (end + page_mask) & ~page_mask; + + VirtualProtect((void*)start, end - start, prot, &oldprot); +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void) +{ + /* This allocator does not keep unused memory for future allocations. */ +} diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitConfig.h b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitConfig.h index 5fba7aa638..e11d4a2e1a 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitConfig.h +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitConfig.h @@ -96,7 +96,9 @@ extern "C" { /* Executable code allocation: If SLJIT_EXECUTABLE_ALLOCATOR is not defined, the application should - define SLJIT_MALLOC_EXEC, SLJIT_FREE_EXEC, and SLJIT_EXEC_OFFSET. */ + define SLJIT_MALLOC_EXEC and SLJIT_FREE_EXEC. + Optionally, depending on the implementation used for the allocator, + SLJIT_EXEC_OFFSET and SLJIT_UPDATE_WX_FLAGS might also be needed. */ #ifndef SLJIT_EXECUTABLE_ALLOCATOR /* Enabled by default. */ #define SLJIT_EXECUTABLE_ALLOCATOR 1 diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitConfigInternal.h b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitConfigInternal.h index bad7772bea..e9bd4d9322 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitConfigInternal.h +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitConfigInternal.h @@ -61,6 +61,8 @@ extern "C" { SLJIT_BIG_ENDIAN : big endian architecture SLJIT_UNALIGNED : unaligned memory accesses for non-fpu operations are supported SLJIT_FPU_UNALIGNED : unaligned memory accesses for fpu operations are supported + SLJIT_MASKED_SHIFT : all word shifts are always masked + SLJIT_MASKED_SHIFT32 : all 32 bit shifts are always masked SLJIT_INDIRECT_CALL : see SLJIT_FUNC_ADDR() for more information Constants: @@ -134,23 +136,23 @@ extern "C" { /********************************************************/ #if (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) - #ifndef _WIN32 #if defined(__i386__) || defined(__i386) #define SLJIT_CONFIG_X86_32 1 #elif defined(__x86_64__) #define SLJIT_CONFIG_X86_64 1 -#elif defined(__arm__) || defined(__ARM__) -#ifdef __thumb2__ -#define SLJIT_CONFIG_ARM_THUMB2 1 -#elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) -#define SLJIT_CONFIG_ARM_V7 1 -#else -#define SLJIT_CONFIG_ARM_V5 1 -#endif -#elif defined (__aarch64__) +#elif defined(__aarch64__) #define SLJIT_CONFIG_ARM_64 1 +#elif defined(__thumb2__) +#define SLJIT_CONFIG_ARM_THUMB2 1 +#elif (defined(__ARM_ARCH) && __ARM_ARCH >= 7) || \ + ((defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7S__)) \ + || (defined(__ARM_ARCH_8A__) || defined(__ARM_ARCH_8R__)) \ + || (defined(__ARM_ARCH_9A__))) +#define SLJIT_CONFIG_ARM_V7 1 +#elif defined(__arm__) || defined (__ARM__) +#define SLJIT_CONFIG_ARM_V5 1 #elif defined(__ppc64__) || defined(__powerpc64__) || (defined(_ARCH_PPC64) && defined(__64BIT__)) || (defined(_POWER) && defined(__64BIT__)) #define SLJIT_CONFIG_PPC_64 1 #elif defined(__ppc__) || defined(__powerpc__) || defined(_ARCH_PPC) || defined(_ARCH_PWR) || defined(_ARCH_PWR2) || defined(_POWER) @@ -603,7 +605,7 @@ typedef double sljit_f64; #endif #endif /* SLJIT_INDIRECT_CALL */ -/* The offset which needs to be substracted from the return address to +/* The offset which needs to be subtracted from the return address to determine the next executed instruction after return. */ #ifndef SLJIT_RETURN_ADDRESS_OFFSET #define SLJIT_RETURN_ADDRESS_OFFSET 0 @@ -631,12 +633,14 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void); #if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR) SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); #define SLJIT_EXEC_OFFSET(ptr) sljit_exec_offset(ptr) -#else -#define SLJIT_EXEC_OFFSET(ptr) 0 #endif #endif /* SLJIT_EXECUTABLE_ALLOCATOR */ +#ifndef SLJIT_EXEC_OFFSET +#define SLJIT_EXEC_OFFSET(ptr) 0 +#endif + /**********************************************/ /* Registers and locals offset determination. */ /**********************************************/ @@ -649,6 +653,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0 #define SLJIT_LOCALS_OFFSET_BASE (8 * SSIZE_OF(sw)) #define SLJIT_PREF_SHIFT_REG SLJIT_R2 +#define SLJIT_MASKED_SHIFT 1 +#define SLJIT_MASKED_SHIFT32 1 #elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) @@ -664,6 +670,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); #define SLJIT_LOCALS_OFFSET_BASE (4 * SSIZE_OF(sw)) #endif /* !_WIN64 */ #define SLJIT_PREF_SHIFT_REG SLJIT_R3 +#define SLJIT_MASKED_SHIFT 1 +#define SLJIT_MASKED_SHIFT32 1 #elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) @@ -688,6 +696,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); #define SLJIT_NUMBER_OF_FLOAT_REGISTERS 30 #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8 #define SLJIT_LOCALS_OFFSET_BASE (2 * (sljit_s32)sizeof(sljit_sw)) +#define SLJIT_MASKED_SHIFT 1 +#define SLJIT_MASKED_SHIFT32 1 #elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) @@ -717,6 +727,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); #define SLJIT_NUMBER_OF_FLOAT_REGISTERS 29 #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8 #endif +#define SLJIT_MASKED_SHIFT 1 +#define SLJIT_MASKED_SHIFT32 1 #elif (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) @@ -725,6 +737,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); #define SLJIT_LOCALS_OFFSET_BASE 0 #define SLJIT_NUMBER_OF_FLOAT_REGISTERS 30 #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 12 +#define SLJIT_MASKED_SHIFT 1 +#define SLJIT_MASKED_SHIFT32 1 #elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) @@ -754,6 +768,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); #define SLJIT_NUMBER_OF_FLOAT_REGISTERS 15 #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8 #define SLJIT_LOCALS_OFFSET_BASE SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE +#define SLJIT_MASKED_SHIFT 1 #elif (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitLir.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitLir.c index 91765656b5..4a73e8e495 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitLir.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitLir.c @@ -93,7 +93,8 @@ #define SSIZE_OF(type) ((sljit_s32)sizeof(sljit_ ## type)) #define VARIABLE_FLAG_SHIFT (10) -#define VARIABLE_FLAG_MASK (0x3f << VARIABLE_FLAG_SHIFT) +/* All variable flags are even. */ +#define VARIABLE_FLAG_MASK (0x3e << VARIABLE_FLAG_SHIFT) #define GET_FLAG_TYPE(op) ((op) >> VARIABLE_FLAG_SHIFT) #define GET_OPCODE(op) \ @@ -254,9 +255,9 @@ (((scratches < SLJIT_NUMBER_OF_SCRATCH_REGISTERS ? 0 : (scratches - SLJIT_NUMBER_OF_SCRATCH_REGISTERS)) + \ (saveds) + (sljit_s32)(extra)) * (sljit_s32)sizeof(sljit_sw)) -#define GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, size) \ +#define GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, type) \ (((fscratches < SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS ? 0 : (fscratches - SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS)) + \ - (fsaveds)) * (sljit_s32)(size)) + (fsaveds)) * SSIZE_OF(type)) #define ADJUST_LOCAL_OFFSET(p, i) \ if ((p) == (SLJIT_MEM1(SLJIT_SP))) \ @@ -272,25 +273,49 @@ #if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) #if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR) -#include "sljitProtExecAllocator.c" -#elif (defined SLJIT_WX_EXECUTABLE_ALLOCATOR && SLJIT_WX_EXECUTABLE_ALLOCATOR) -#include "sljitWXExecAllocator.c" + +#if defined(__NetBSD__) +#include "allocator_src/sljitProtExecAllocatorNetBSD.c" #else -#include "sljitExecAllocator.c" +#include "allocator_src/sljitProtExecAllocatorPosix.c" +#endif + +#elif (defined SLJIT_WX_EXECUTABLE_ALLOCATOR && SLJIT_WX_EXECUTABLE_ALLOCATOR) + +#if defined(_WIN32) +#include "allocator_src/sljitWXExecAllocatorWindows.c" +#else +#include "allocator_src/sljitWXExecAllocatorPosix.c" +#endif + +#else + +#if defined(_WIN32) +#include "allocator_src/sljitExecAllocatorWindows.c" +#elif defined(__APPLE__) +#include "allocator_src/sljitExecAllocatorApple.c" +#elif defined(__FreeBSD__) +#include "allocator_src/sljitExecAllocatorFreeBSD.c" +#else +#include "allocator_src/sljitExecAllocatorPosix.c" #endif #endif +#else /* !SLJIT_EXECUTABLE_ALLOCATOR */ + +#ifndef SLJIT_UPDATE_WX_FLAGS +#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) +#endif + +#endif /* SLJIT_EXECUTABLE_ALLOCATOR */ + #if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR) #define SLJIT_ADD_EXEC_OFFSET(ptr, exec_offset) ((sljit_u8 *)(ptr) + (exec_offset)) #else #define SLJIT_ADD_EXEC_OFFSET(ptr, exec_offset) ((sljit_u8 *)(ptr)) #endif -#ifndef SLJIT_UPDATE_WX_FLAGS -#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) -#endif - /* Argument checking features. */ #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) @@ -993,19 +1018,21 @@ static const char* op0_names[] = { static const char* op1_names[] = { "", ".u8", ".s8", ".u16", ".s16", ".u32", ".s32", "32", - ".p", "not", "clz", + ".p", "clz", "ctz", "rev" }; static const char* op2_names[] = { "add", "addc", "sub", "subc", "mul", "and", "or", "xor", - "shl", "lshr", "ashr", + "shl", "mshl", "lshr", "mlshr", + "ashr", "mashr", "rotl", "rotr" }; -static const char* op_src_names[] = { +static const char* op_src_dst_names[] = { "fast_return", "skip_frames_before_fast_return", "prefetch_l1", "prefetch_l2", "prefetch_l3", "prefetch_once", + "fast_enter", "get_return_address" }; static const char* fop1_names[] = { @@ -1095,7 +1122,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compil CHECK_ARGUMENT(fsaveds >= 0 && fsaveds <= SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS); CHECK_ARGUMENT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS); CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE); - CHECK_ARGUMENT((arg_types & SLJIT_ARG_FULL_MASK) < SLJIT_ARG_TYPE_F64); + CHECK_ARGUMENT((arg_types & SLJIT_ARG_FULL_MASK) <= SLJIT_ARG_TYPE_F32); CHECK_ARGUMENT(function_check_arguments(arg_types, scratches, (options & SLJIT_ENTER_REG_ARG) ? 0 : saveds, fscratches)); compiler->last_flags = 0; @@ -1125,7 +1152,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compil fprintf(compiler->verbose, " keep:%d,", SLJIT_KEPT_SAVEDS_COUNT(options)); } - fprintf(compiler->verbose, "scratches:%d, saveds:%d, fscratches:%d, fsaveds:%d, local_size:%d\n", + fprintf(compiler->verbose, " scratches:%d, saveds:%d, fscratches:%d, fsaveds:%d, local_size:%d\n", scratches, saveds, fscratches, fsaveds, local_size); } #endif @@ -1223,35 +1250,53 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return(struct sljit_compi case SLJIT_ARG_TYPE_P: CHECK_ARGUMENT(op == SLJIT_MOV_P); break; + case SLJIT_ARG_TYPE_F64: + CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); + CHECK_ARGUMENT(op == SLJIT_MOV_F64); + break; + case SLJIT_ARG_TYPE_F32: + CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); + CHECK_ARGUMENT(op == SLJIT_MOV_F32); + break; default: /* Context not initialized, void, etc. */ CHECK_ARGUMENT(0); break; } - FUNCTION_CHECK_SRC(src, srcw); + + if (GET_OPCODE(op) < SLJIT_MOV_F64) { + FUNCTION_CHECK_SRC(src, srcw); + } else { + FUNCTION_FCHECK(src, srcw); + } compiler->last_flags = 0; #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { - fprintf(compiler->verbose, " return%s%s ", !(op & SLJIT_32) ? "" : "32", - op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE]); - sljit_verbose_param(compiler, src, srcw); + if (GET_OPCODE(op) < SLJIT_MOV_F64) { + fprintf(compiler->verbose, " return%s%s ", !(op & SLJIT_32) ? "" : "32", + op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE]); + sljit_verbose_param(compiler, src, srcw); + } else { + fprintf(compiler->verbose, " return%s ", !(op & SLJIT_32) ? ".f64" : ".f32"); + sljit_verbose_fparam(compiler, src, srcw); + } fprintf(compiler->verbose, "\n"); } #endif CHECK_RETURN_OK; } -static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return_to(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - FUNCTION_CHECK_DST(dst, dstw); - compiler->last_flags = 0; + FUNCTION_CHECK_SRC(src, srcw); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { - fprintf(compiler->verbose, " fast_enter "); - sljit_verbose_param(compiler, dst, dstw); + fprintf(compiler->verbose, " return_to "); + sljit_verbose_param(compiler, src, srcw); fprintf(compiler->verbose, "\n"); } #endif @@ -1291,15 +1336,13 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler } #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_CLZ); + CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_REV); switch (GET_OPCODE(op)) { - case SLJIT_NOT: - /* Only SLJIT_32 and SLJIT_SET_Z are allowed. */ - CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)); - break; case SLJIT_MOV: case SLJIT_MOV_U32: + case SLJIT_MOV_S32: + case SLJIT_MOV32: case SLJIT_MOV_P: /* Nothing allowed */ CHECK_ARGUMENT(!(op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK))); @@ -1312,11 +1355,6 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler FUNCTION_CHECK_DST(dst, dstw); FUNCTION_CHECK_SRC(src, srcw); - - if (GET_OPCODE(op) >= SLJIT_NOT) { - CHECK_ARGUMENT(src != SLJIT_IMM); - compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_32 | SLJIT_SET_Z)); - } #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { @@ -1352,15 +1390,18 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler } #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_ADD && GET_OPCODE(op) <= SLJIT_ASHR); + CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_ADD && GET_OPCODE(op) <= SLJIT_ROTR); switch (GET_OPCODE(op)) { case SLJIT_AND: case SLJIT_OR: case SLJIT_XOR: case SLJIT_SHL: + case SLJIT_MSHL: case SLJIT_LSHR: + case SLJIT_MLSHR: case SLJIT_ASHR: + case SLJIT_MASHR: CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)); break; case SLJIT_MUL: @@ -1385,6 +1426,10 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler CHECK_ARGUMENT((compiler->last_flags & 0xff) == GET_FLAG_TYPE(SLJIT_SET_CARRY)); CHECK_ARGUMENT((op & SLJIT_32) == (compiler->last_flags & SLJIT_32)); break; + case SLJIT_ROTL: + case SLJIT_ROTR: + CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))); + break; default: SLJIT_UNREACHABLE(); break; @@ -1418,6 +1463,40 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler CHECK_RETURN_OK; } +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst_reg, + sljit_s32 src1_reg, + sljit_s32 src2_reg, + sljit_s32 src3, sljit_sw src3w) +{ +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + CHECK_ARGUMENT(GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_LSHR + || GET_OPCODE(op) == SLJIT_MSHL || GET_OPCODE(op) == SLJIT_MLSHR); + CHECK_ARGUMENT((op & ~(0xff | SLJIT_32 | SLJIT_SHIFT_INTO_NON_ZERO)) == 0); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg)); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src1_reg)); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src2_reg)); + FUNCTION_CHECK_SRC(src3, src3w); + CHECK_ARGUMENT(dst_reg != src2_reg); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " %s%s.into%s ", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], !(op & SLJIT_32) ? "" : "32", + (op & SLJIT_SHIFT_INTO_NON_ZERO) ? ".nz" : ""); + + sljit_verbose_reg(compiler, dst_reg); + fprintf(compiler->verbose, ", "); + sljit_verbose_reg(compiler, src1_reg); + fprintf(compiler->verbose, ", "); + sljit_verbose_reg(compiler, src2_reg); + fprintf(compiler->verbose, ", "); + sljit_verbose_param(compiler, src3, src3w); + fprintf(compiler->verbose, "\n"); + } +#endif + CHECK_RETURN_OK; +} + static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { @@ -1425,19 +1504,16 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_src(struct sljit_compi CHECK_ARGUMENT(op >= SLJIT_FAST_RETURN && op <= SLJIT_PREFETCH_ONCE); FUNCTION_CHECK_SRC(src, srcw); - if (op == SLJIT_FAST_RETURN || op == SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN) - { + if (op == SLJIT_FAST_RETURN || op == SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN) { CHECK_ARGUMENT(src != SLJIT_IMM); compiler->last_flags = 0; - } - else if (op >= SLJIT_PREFETCH_L1 && op <= SLJIT_PREFETCH_ONCE) - { + } else if (op >= SLJIT_PREFETCH_L1 && op <= SLJIT_PREFETCH_ONCE) { CHECK_ARGUMENT(src & SLJIT_MEM); } #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { - fprintf(compiler->verbose, " %s ", op_src_names[op - SLJIT_OP_SRC_BASE]); + fprintf(compiler->verbose, " %s ", op_src_dst_names[op - SLJIT_OP_SRC_DST_BASE]); sljit_verbose_param(compiler, src, srcw); fprintf(compiler->verbose, "\n"); } @@ -1445,6 +1521,26 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_src(struct sljit_compi CHECK_RETURN_OK; } +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw) +{ +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + CHECK_ARGUMENT(op >= SLJIT_FAST_ENTER && op <= SLJIT_GET_RETURN_ADDRESS); + FUNCTION_CHECK_DST(dst, dstw); + + if (op == SLJIT_FAST_ENTER) + compiler->last_flags = 0; +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " %s ", op_src_dst_names[op - SLJIT_OP_SRC_DST_BASE]); + sljit_verbose_param(compiler, dst, dstw); + fprintf(compiler->verbose, "\n"); + } +#endif + CHECK_RETURN_OK; +} + static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_register_index(sljit_s32 reg) { SLJIT_UNUSED_ARG(reg); @@ -1658,6 +1754,64 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop2(struct sljit_compile CHECK_RETURN_OK; } +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 freg, sljit_s32 reg) +{ +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); + CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_COPY_TO_F64 && GET_OPCODE(op) <= SLJIT_COPY_FROM_F64); + CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg)); + +#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) + CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg)); +#else /* !SLJIT_64BIT_ARCHITECTURE */ + switch (op) { + case SLJIT_COPY32_TO_F32: + case SLJIT_COPY32_FROM_F32: + CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg)); + break; + case SLJIT_COPY_TO_F64: + case SLJIT_COPY_FROM_F64: + if (reg & REG_PAIR_MASK) { + CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(REG_PAIR_FIRST(reg))); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(REG_PAIR_SECOND(reg))); + + if (op == SLJIT_COPY_TO_F64) + break; + + CHECK_ARGUMENT(REG_PAIR_FIRST(reg) != REG_PAIR_SECOND(reg)); + break; + } + + CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg)); + break; + } +#endif /* SLJIT_64BIT_ARCHITECTURE */ +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " copy%s_%s_f%s ", (op & SLJIT_32) ? "32" : "", + GET_OPCODE(op) == SLJIT_COPY_TO_F64 ? "to" : "from", (op & SLJIT_32) ? "32" : "64"); + + sljit_verbose_freg(compiler, freg); + + if (reg & REG_PAIR_MASK) { + fprintf(compiler->verbose, ", {"); + sljit_verbose_reg(compiler, REG_PAIR_FIRST(reg)); + fprintf(compiler->verbose, ", "); + sljit_verbose_reg(compiler, REG_PAIR_SECOND(reg)); + fprintf(compiler->verbose, "}\n"); + } else { + fprintf(compiler->verbose, ", "); + sljit_verbose_reg(compiler, reg); + fprintf(compiler->verbose, "\n"); + } + } +#endif + CHECK_RETURN_OK; +} + static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_label(struct sljit_compiler *compiler) { SLJIT_UNUSED_ARG(compiler); @@ -1704,11 +1858,10 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_jump(struct sljit_compile if ((type & 0xff) <= SLJIT_NOT_ZERO) CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z); else if ((compiler->last_flags & 0xff) == SLJIT_CARRY) { - CHECK_ARGUMENT((type & 0xff) == SLJIT_CARRY || (type & 0xff) == SLJIT_NOT_CARRY); + CHECK_ARGUMENT((type & 0xfe) == SLJIT_CARRY); compiler->last_flags = 0; } else - CHECK_ARGUMENT((type & 0xff) == (compiler->last_flags & 0xff) - || ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW) + CHECK_ARGUMENT((type & 0xfe) == (compiler->last_flags & 0xff) || CHECK_UNORDERED(type, compiler->last_flags)); } #endif @@ -1890,9 +2043,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_flags(struct sljit_com if (type <= SLJIT_NOT_ZERO) CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z); else - CHECK_ARGUMENT(type == (compiler->last_flags & 0xff) - || (type == SLJIT_NOT_CARRY && (compiler->last_flags & 0xff) == SLJIT_CARRY) - || (type == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW) + CHECK_ARGUMENT((type & 0xfe) == (compiler->last_flags & 0xff) || CHECK_UNORDERED(type, compiler->last_flags)); FUNCTION_CHECK_DST(dst, dstw); @@ -1918,29 +2069,29 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmov(struct sljit_compile sljit_s32 src, sljit_sw srcw) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - CHECK_ARGUMENT(type >= SLJIT_EQUAL && type <= SLJIT_ORDERED_LESS_EQUAL); + sljit_s32 cond = type & ~SLJIT_32; + + CHECK_ARGUMENT(cond >= SLJIT_EQUAL && cond <= SLJIT_ORDERED_LESS_EQUAL); CHECK_ARGUMENT(compiler->scratches != -1 && compiler->saveds != -1); - CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg & ~SLJIT_32)); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg)); if (src != SLJIT_IMM) { CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src)); CHECK_ARGUMENT(srcw == 0); } - if (type <= SLJIT_NOT_ZERO) + if (cond <= SLJIT_NOT_ZERO) CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z); else - CHECK_ARGUMENT(type == (compiler->last_flags & 0xff) - || (type == SLJIT_NOT_CARRY && (compiler->last_flags & 0xff) == SLJIT_CARRY) - || (type == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW) - || CHECK_UNORDERED(type, compiler->last_flags)); + CHECK_ARGUMENT((cond & 0xfe) == (compiler->last_flags & 0xff) + || CHECK_UNORDERED(cond, compiler->last_flags)); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " cmov%s %s, ", - !(dst_reg & SLJIT_32) ? "" : "32", - jump_names[type]); - sljit_verbose_reg(compiler, dst_reg & ~SLJIT_32); + !(type & SLJIT_32) ? "" : "32", + jump_names[type & ~SLJIT_32]); + sljit_verbose_reg(compiler, dst_reg); fprintf(compiler->verbose, ", "); sljit_verbose_param(compiler, src, srcw); fprintf(compiler->verbose, "\n"); @@ -1953,16 +2104,39 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem(struct sljit_compiler sljit_s32 reg, sljit_s32 mem, sljit_sw memw) { + if (SLJIT_UNLIKELY(compiler->skip_checks)) { + compiler->skip_checks = 0; + CHECK_RETURN_OK; + } + #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) sljit_s32 allowed_flags; + if (type & SLJIT_MEM_UNALIGNED) { + CHECK_ARGUMENT(!(type & (SLJIT_MEM_UNALIGNED_16 | SLJIT_MEM_UNALIGNED_32))); + } else if (type & SLJIT_MEM_UNALIGNED_16) { + CHECK_ARGUMENT(!(type & SLJIT_MEM_UNALIGNED_32)); + } else { + CHECK_ARGUMENT((reg & REG_PAIR_MASK) || (type & SLJIT_MEM_UNALIGNED_32)); + } + + allowed_flags = SLJIT_MEM_UNALIGNED; + + switch (type & 0xff) { + case SLJIT_MOV_U32: + case SLJIT_MOV_S32: + case SLJIT_MOV32: + allowed_flags = SLJIT_MEM_UNALIGNED | SLJIT_MEM_UNALIGNED_16; + break; + case SLJIT_MOV: + case SLJIT_MOV_P: + allowed_flags = SLJIT_MEM_UNALIGNED | SLJIT_MEM_UNALIGNED_16 | SLJIT_MEM_UNALIGNED_32; + break; + } + + CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | allowed_flags)) == 0); + if (reg & REG_PAIR_MASK) { - if (type & SLJIT_MEM_UNALIGNED) { - CHECK_ARGUMENT((type & ~(0xff | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32)) == 0); - CHECK_ARGUMENT((type & (SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32)) != (SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32)); - } else { - CHECK_ARGUMENT((type & ~(0xff | SLJIT_MEM_STORE)) == 0); - } CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV); CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(REG_PAIR_FIRST(reg))); CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(REG_PAIR_SECOND(reg))); @@ -1971,67 +2145,36 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem(struct sljit_compiler CHECK_ARGUMENT((type & 0xff) >= SLJIT_MOV && (type & 0xff) <= SLJIT_MOV_P); CHECK_ARGUMENT(!(type & SLJIT_32) || ((type & 0xff) >= SLJIT_MOV_U8 && (type & 0xff) <= SLJIT_MOV_S16)); CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg)); - - if (type & SLJIT_MEM_UNALIGNED) { - allowed_flags = SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32; - - switch (type & 0xff) { - case SLJIT_MOV_U8: - case SLJIT_MOV_S8: - case SLJIT_MOV_U16: - case SLJIT_MOV_S16: - allowed_flags = 0; - break; - case SLJIT_MOV_U32: - case SLJIT_MOV_S32: - case SLJIT_MOV32: - allowed_flags = SLJIT_MEM_ALIGNED_16; - break; - } - CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED | allowed_flags)) == 0); - CHECK_ARGUMENT((type & (SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32)) != (SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32)); - } else { - CHECK_ARGUMENT((type & SLJIT_MEM_PRE) || (type & SLJIT_MEM_POST)); - CHECK_ARGUMENT((type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) != (SLJIT_MEM_PRE | SLJIT_MEM_POST)); - CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_PRE | SLJIT_MEM_POST)) == 0); - CHECK_ARGUMENT((mem & REG_MASK) != 0 && (mem & REG_MASK) != reg); - } } FUNCTION_CHECK_SRC_MEM(mem, memw); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { - if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) { - if (type & SLJIT_MEM_SUPP) - CHECK_RETURN_OK; - if (sljit_emit_mem(compiler, type | SLJIT_MEM_SUPP, reg, mem, memw) == SLJIT_ERR_UNSUPPORTED) { - fprintf(compiler->verbose, " // mem: unsupported form, no instructions are emitted"); - CHECK_RETURN_OK; - } - } - if ((type & 0xff) == SLJIT_MOV32) - fprintf(compiler->verbose, " mem32.%s", - (type & SLJIT_MEM_STORE) ? "st" : "ld"); + fprintf(compiler->verbose, " %s32", + (type & SLJIT_MEM_STORE) ? "store" : "load"); else - fprintf(compiler->verbose, " mem%s.%s%s", + fprintf(compiler->verbose, " %s%s%s", + (type & SLJIT_MEM_STORE) ? "store" : "load", !(type & SLJIT_32) ? "" : "32", - (type & SLJIT_MEM_STORE) ? "st" : "ld", op1_names[(type & 0xff) - SLJIT_OP1_BASE]); - if (type & SLJIT_MEM_UNALIGNED) { - printf(".un%s%s ", (type & SLJIT_MEM_ALIGNED_16) ? ".16" : "", (type & SLJIT_MEM_ALIGNED_32) ? ".32" : ""); - } else - printf((type & SLJIT_MEM_PRE) ? ".pre " : ".post "); + if (type & SLJIT_MEM_UNALIGNED) + printf(".un"); + else if (type & SLJIT_MEM_UNALIGNED_16) + printf(".un16"); + else if (type & SLJIT_MEM_UNALIGNED_32) + printf(".un32"); if (reg & REG_PAIR_MASK) { - fprintf(compiler->verbose, "{"); + fprintf(compiler->verbose, " {"); sljit_verbose_reg(compiler, REG_PAIR_FIRST(reg)); fprintf(compiler->verbose, ", "); sljit_verbose_reg(compiler, REG_PAIR_SECOND(reg)); fprintf(compiler->verbose, "}, "); } else { + fprintf(compiler->verbose, " "); sljit_verbose_reg(compiler, reg); fprintf(compiler->verbose, ", "); } @@ -2042,43 +2185,118 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem(struct sljit_compiler CHECK_RETURN_OK; } +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 reg, + sljit_s32 mem, sljit_sw memw) +{ + if (SLJIT_UNLIKELY(compiler->skip_checks)) { + compiler->skip_checks = 0; + CHECK_RETURN_OK; + } + +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + CHECK_ARGUMENT((type & 0xff) >= SLJIT_MOV && (type & 0xff) <= SLJIT_MOV_P); + CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_POST)) == 0); + CHECK_ARGUMENT((mem & REG_MASK) != 0 && (mem & REG_MASK) != reg); + + FUNCTION_CHECK_SRC_MEM(mem, memw); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + if (type & SLJIT_MEM_SUPP) + CHECK_RETURN_OK; + if (sljit_emit_mem_update(compiler, type | SLJIT_MEM_SUPP, reg, mem, memw) == SLJIT_ERR_UNSUPPORTED) { + fprintf(compiler->verbose, " # mem: unsupported form, no instructions are emitted\n"); + CHECK_RETURN_OK; + } + + if ((type & 0xff) == SLJIT_MOV32) + fprintf(compiler->verbose, " %s32.%s ", + (type & SLJIT_MEM_STORE) ? "store" : "load", + (type & SLJIT_MEM_POST) ? "post" : "pre"); + else + fprintf(compiler->verbose, " %s%s%s.%s ", + (type & SLJIT_MEM_STORE) ? "store" : "load", + !(type & SLJIT_32) ? "" : "32", + op1_names[(type & 0xff) - SLJIT_OP1_BASE], + (type & SLJIT_MEM_POST) ? "post" : "pre"); + + sljit_verbose_reg(compiler, reg); + fprintf(compiler->verbose, ", "); + sljit_verbose_param(compiler, mem, memw); + fprintf(compiler->verbose, "\n"); + } +#endif + CHECK_RETURN_OK; +} + static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 freg, sljit_s32 mem, sljit_sw memw) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV_F64); + if (type & SLJIT_MEM_UNALIGNED) { - CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16 | (type & SLJIT_32 ? 0 : SLJIT_MEM_ALIGNED_32))) == 0); - CHECK_ARGUMENT((type & (SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32)) != (SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32)); + CHECK_ARGUMENT(!(type & (SLJIT_MEM_UNALIGNED_16 | SLJIT_MEM_UNALIGNED_32))); + } else if (type & SLJIT_MEM_UNALIGNED_16) { + CHECK_ARGUMENT(!(type & SLJIT_MEM_UNALIGNED_32)); } else { - CHECK_ARGUMENT((type & SLJIT_MEM_PRE) || (type & SLJIT_MEM_POST)); - CHECK_ARGUMENT((type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) != (SLJIT_MEM_PRE | SLJIT_MEM_POST)); - CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_PRE | SLJIT_MEM_POST)) == 0); + CHECK_ARGUMENT(type & SLJIT_MEM_UNALIGNED_32); + CHECK_ARGUMENT(!(type & SLJIT_32)); } + CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED | SLJIT_MEM_UNALIGNED_16 | SLJIT_MEM_UNALIGNED_32))); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg)); + FUNCTION_CHECK_SRC_MEM(mem, memw); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " %s.%s", + (type & SLJIT_MEM_STORE) ? "store" : "load", + !(type & SLJIT_32) ? "f64" : "f32"); + + if (type & SLJIT_MEM_UNALIGNED) + printf(".un"); + else if (type & SLJIT_MEM_UNALIGNED_16) + printf(".un16"); + else if (type & SLJIT_MEM_UNALIGNED_32) + printf(".un32"); + + fprintf(compiler->verbose, " "); + sljit_verbose_freg(compiler, freg); + fprintf(compiler->verbose, ", "); + sljit_verbose_param(compiler, mem, memw); + fprintf(compiler->verbose, "\n"); + } +#endif + CHECK_RETURN_OK; +} + +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 mem, sljit_sw memw) +{ +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV_F64); + CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_POST)) == 0); FUNCTION_CHECK_SRC_MEM(mem, memw); CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg)); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { - if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) { - if (type & SLJIT_MEM_SUPP) - CHECK_RETURN_OK; - if (sljit_emit_fmem(compiler, type | SLJIT_MEM_SUPP, freg, mem, memw) == SLJIT_ERR_UNSUPPORTED) { - fprintf(compiler->verbose, " // fmem: unsupported form, no instructions are emitted"); - CHECK_RETURN_OK; - } + if (type & SLJIT_MEM_SUPP) + CHECK_RETURN_OK; + if (sljit_emit_fmem_update(compiler, type | SLJIT_MEM_SUPP, freg, mem, memw) == SLJIT_ERR_UNSUPPORTED) { + fprintf(compiler->verbose, " # fmem: unsupported form, no instructions are emitted\n"); + CHECK_RETURN_OK; } - fprintf(compiler->verbose, " fmem.%s%s", - (type & SLJIT_MEM_STORE) ? "st" : "ld", - !(type & SLJIT_32) ? ".f64" : ".f32"); + fprintf(compiler->verbose, " %s.%s.%s ", + (type & SLJIT_MEM_STORE) ? "store" : "load", + !(type & SLJIT_32) ? "f64" : "f32", + (type & SLJIT_MEM_POST) ? "post" : "pre"); - if (type & SLJIT_MEM_UNALIGNED) { - printf(".un%s%s ", (type & SLJIT_MEM_ALIGNED_16) ? ".16" : "", (type & SLJIT_MEM_ALIGNED_32) ? ".32" : ""); - } else - printf((type & SLJIT_MEM_PRE) ? ".pre " : ".post "); sljit_verbose_freg(compiler, freg); fprintf(compiler->verbose, ", "); sljit_verbose_param(compiler, mem, memw); @@ -2169,36 +2387,11 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_put_label(struct sljit_co ADJUST_LOCAL_OFFSET(dst, dstw); \ ADJUST_LOCAL_OFFSET(src, srcw); -static SLJIT_INLINE sljit_s32 emit_mov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) -{ -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - /* At the moment the pointer size is always equal to sljit_sw. May be changed in the future. */ - if (src == SLJIT_RETURN_REG && (op == SLJIT_MOV || op == SLJIT_MOV_P)) - return SLJIT_SUCCESS; -#else - if (src == SLJIT_RETURN_REG && (op == SLJIT_MOV || op == SLJIT_MOV_U32 || op == SLJIT_MOV_S32 || op == SLJIT_MOV_P)) - return SLJIT_SUCCESS; -#endif - - SLJIT_SKIP_CHECKS(compiler); - return sljit_emit_op1(compiler, op, SLJIT_RETURN_REG, 0, src, srcw); -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) -{ - CHECK_ERROR(); - CHECK(check_sljit_emit_return(compiler, op, src, srcw)); - - FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); - - SLJIT_SKIP_CHECKS(compiler); - return sljit_emit_return_void(compiler); -} - #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \ || (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \ || ((defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) && !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)) \ - || (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) + || (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \ + || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) static SLJIT_INLINE sljit_s32 sljit_emit_cmov_generic(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 dst_reg, @@ -2206,14 +2399,14 @@ static SLJIT_INLINE sljit_s32 sljit_emit_cmov_generic(struct sljit_compiler *com { struct sljit_label *label; struct sljit_jump *jump; - sljit_s32 op = (dst_reg & SLJIT_32) ? SLJIT_MOV32 : SLJIT_MOV; + sljit_s32 op = (type & SLJIT_32) ? SLJIT_MOV32 : SLJIT_MOV; SLJIT_SKIP_CHECKS(compiler); - jump = sljit_emit_jump(compiler, type ^ 0x1); + jump = sljit_emit_jump(compiler, (type & ~SLJIT_32) ^ 0x1); FAIL_IF(!jump); SLJIT_SKIP_CHECKS(compiler); - FAIL_IF(sljit_emit_op1(compiler, op, dst_reg & ~SLJIT_32, 0, src, srcw)); + FAIL_IF(sljit_emit_op1(compiler, op, dst_reg, 0, src, srcw)); SLJIT_SKIP_CHECKS(compiler); label = sljit_emit_label(compiler); @@ -2303,6 +2496,50 @@ static sljit_s32 sljit_emit_fmem_unaligned(struct sljit_compiler *compiler, slji # include "sljitNativeS390X.c" #endif +static SLJIT_INLINE sljit_s32 emit_mov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) +{ +#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) + /* At the moment the pointer size is always equal to sljit_sw. May be changed in the future. */ + if (src == SLJIT_RETURN_REG && (op == SLJIT_MOV || op == SLJIT_MOV_P)) + return SLJIT_SUCCESS; +#else + if (src == SLJIT_RETURN_REG && (op == SLJIT_MOV || op == SLJIT_MOV_U32 || op == SLJIT_MOV_S32 || op == SLJIT_MOV_P)) + return SLJIT_SUCCESS; +#endif + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_op1(compiler, op, SLJIT_RETURN_REG, 0, src, srcw); +} + +#if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \ + && !((defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) && defined __SOFTFP__) + +static SLJIT_INLINE sljit_s32 emit_fmov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) +{ + if (src == SLJIT_FR0) + return SLJIT_SUCCESS; + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_fop1(compiler, op, SLJIT_RETURN_FREG, 0, src, srcw); +} + +#endif /* !SLJIT_CONFIG_X86_32 && !(SLJIT_CONFIG_ARM_32 && __SOFTFP__) */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_return(compiler, op, src, srcw)); + + if (GET_OPCODE(op) < SLJIT_MOV_F64) { + FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); + } else { + FAIL_IF(emit_fmov_before_return(compiler, op, src, srcw)); + } + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_return_void(compiler); +} + #if !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \ && !(defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) @@ -2372,7 +2609,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler if (condition <= SLJIT_NOT_ZERO) flags = SLJIT_SET_Z; else - flags = condition << VARIABLE_FLAG_SHIFT; + flags = (condition & 0xfe) << VARIABLE_FLAG_SHIFT; SLJIT_SKIP_CHECKS(compiler); PTR_FAIL_IF(sljit_emit_op2u(compiler, @@ -2410,35 +2647,33 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compile CHECK_PTR(check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w)); SLJIT_SKIP_CHECKS(compiler); - sljit_emit_fop1(compiler, SLJIT_CMP_F64 | ((type & 0xff) << VARIABLE_FLAG_SHIFT) | (type & SLJIT_32), src1, src1w, src2, src2w); + sljit_emit_fop1(compiler, SLJIT_CMP_F64 | ((type & 0xfe) << VARIABLE_FLAG_SHIFT) | (type & SLJIT_32), src1, src1w, src2, src2w); SLJIT_SKIP_CHECKS(compiler); return sljit_emit_jump(compiler, type); } #if !(defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) \ - && !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \ - && !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \ - && !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) + && !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 reg, sljit_s32 mem, sljit_sw memw) { CHECK_ERROR(); - CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); + CHECK(check_sljit_emit_mem_update(compiler, type, reg, mem, memw)); + SLJIT_UNUSED_ARG(type); + SLJIT_UNUSED_ARG(reg); + SLJIT_UNUSED_ARG(mem); + SLJIT_UNUSED_ARG(memw); - if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) - return SLJIT_ERR_UNSUPPORTED; - - return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw); + return SLJIT_ERR_UNSUPPORTED; } -#endif +#endif /* !SLJIT_CONFIG_ARM && !SLJIT_CONFIG_PPC */ -#if !(defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) \ - && !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \ - && !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) +#if !(defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \ + && !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 freg, @@ -2447,13 +2682,29 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil CHECK_ERROR(); CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw)); - if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) - return SLJIT_ERR_UNSUPPORTED; - return sljit_emit_fmem_unaligned(compiler, type, freg, mem, memw); } -#endif +#endif /* !SLJIT_CONFIG_ARM_32 && !SLJIT_CONFIG_MIPS */ + +#if !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \ + && !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 mem, sljit_sw memw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_fmem_update(compiler, type, freg, mem, memw)); + SLJIT_UNUSED_ARG(type); + SLJIT_UNUSED_ARG(freg); + SLJIT_UNUSED_ARG(mem); + SLJIT_UNUSED_ARG(memw); + + return SLJIT_ERR_UNSUPPORTED; +} + +#endif /* !SLJIT_CONFIG_ARM_64 && !SLJIT_CONFIG_PPC */ #if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \ && !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) @@ -2580,6 +2831,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp return SLJIT_ERR_UNSUPPORTED; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNREACHABLE(); + return SLJIT_ERR_UNSUPPORTED; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { SLJIT_UNUSED_ARG(compiler); @@ -2590,9 +2848,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp return SLJIT_ERR_UNSUPPORTED; } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler) +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) { SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(src); + SLJIT_UNUSED_ARG(srcw); SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } @@ -2659,6 +2919,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil return SLJIT_ERR_UNSUPPORTED; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst_reg, + sljit_s32 src1_reg, + sljit_s32 src2_reg, + sljit_s32 src3, sljit_sw src3w) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(op); + SLJIT_UNUSED_ARG(dst_reg); + SLJIT_UNUSED_ARG(src1_reg); + SLJIT_UNUSED_ARG(src2_reg); + SLJIT_UNUSED_ARG(src3); + SLJIT_UNUSED_ARG(src3w); + SLJIT_UNREACHABLE(); + return SLJIT_ERR_UNSUPPORTED; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { @@ -2723,6 +3000,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil return SLJIT_ERR_UNSUPPORTED; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 freg, sljit_s32 reg) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(op); + SLJIT_UNUSED_ARG(freg); + SLJIT_UNUSED_ARG(reg); + SLJIT_UNREACHABLE(); + return SLJIT_ERR_UNSUPPORTED; +} + SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler) { SLJIT_UNUSED_ARG(compiler); @@ -2857,6 +3145,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile return SLJIT_ERR_UNSUPPORTED; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 reg, sljit_s32 mem, sljit_sw memw) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(type); + SLJIT_UNUSED_ARG(reg); + SLJIT_UNUSED_ARG(mem); + SLJIT_UNUSED_ARG(memw); + SLJIT_UNREACHABLE(); + return SLJIT_ERR_UNSUPPORTED; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 freg, sljit_s32 mem, sljit_sw memw) { SLJIT_UNUSED_ARG(compiler); @@ -2868,6 +3167,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil return SLJIT_ERR_UNSUPPORTED; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 freg, sljit_s32 mem, sljit_sw memw) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(type); + SLJIT_UNUSED_ARG(freg); + SLJIT_UNUSED_ARG(mem); + SLJIT_UNUSED_ARG(memw); + SLJIT_UNREACHABLE(); + return SLJIT_ERR_UNSUPPORTED; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset) { SLJIT_UNUSED_ARG(compiler); diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitLir.h b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitLir.h index 1304843de1..87805dd7fd 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitLir.h +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitLir.h @@ -36,26 +36,24 @@ Advantages: - The execution can be continued from any LIR instruction. In other words, it is possible to jump to any label from anywhere, even from - a code fragment, which is compiled later, if both compiled code - shares the same context. See sljit_emit_enter for more details - - Supports self modifying code: target of (conditional) jump and call + a code fragment, which is compiled later, as long as the compiling + context is the same. See sljit_emit_enter for more details. + - Supports self modifying code: target of any jump and call instructions and some constant values can be dynamically modified - during runtime + during runtime. See SLJIT_REWRITABLE_JUMP. - although it is not suggested to do it frequently - can be used for inline caching: save an important value once in the instruction stream - - since this feature limits the optimization possibilities, a - special flag must be passed at compile time when these - instructions are emitted - A fixed stack space can be allocated for local variables - The compiler is thread-safe - The compiler is highly configurable through preprocessor macros. You can disable unneeded features (multithreading in single threaded applications), and you can use your own system functions - (including memory allocators). See sljitConfig.h + (including memory allocators). See sljitConfig.h. Disadvantages: - - No automatic register allocation, and temporary results are - not stored on the stack. (hence the name comes) + - The compiler is more like a platform independent assembler, so + there is no built-in variable management. Registers and stack must + be managed manually (the name of the compiler refers to this). In practice: - This approach is very effective for interpreters - One of the saved registers typically points to a stack interface @@ -77,7 +75,7 @@ #include "sljitConfig.h" /* The following header file defines useful macros for fine tuning -sljit based code generators. They are listed in the beginning +SLJIT based code generators. They are listed in the beginning of sljitConfigInternal.h */ #include "sljitConfigInternal.h" @@ -90,6 +88,10 @@ of sljitConfigInternal.h */ extern "C" { #endif +/* Version numbers. */ +#define SLJIT_MAJOR_VERSION 0 +#define SLJIT_MINOR_VERSION 95 + /* --------------------------------------------------------------------- */ /* Error codes */ /* --------------------------------------------------------------------- */ @@ -97,33 +99,31 @@ extern "C" { /* Indicates no error. */ #define SLJIT_SUCCESS 0 /* After the call of sljit_generate_code(), the error code of the compiler - is set to this value to avoid future sljit calls (in debug mode at least). + is set to this value to avoid further code generation. The complier should be freed after sljit_generate_code(). */ #define SLJIT_ERR_COMPILED 1 -/* Cannot allocate non executable memory. */ +/* Cannot allocate non-executable memory. */ #define SLJIT_ERR_ALLOC_FAILED 2 /* Cannot allocate executable memory. - Only for sljit_generate_code() */ + Only sljit_generate_code() returns with this error code. */ #define SLJIT_ERR_EX_ALLOC_FAILED 3 /* Return value for SLJIT_CONFIG_UNSUPPORTED placeholder architecture. */ #define SLJIT_ERR_UNSUPPORTED 4 /* An ivalid argument is passed to any SLJIT function. */ #define SLJIT_ERR_BAD_ARGUMENT 5 -/* Dynamic code modification is not enabled. */ -#define SLJIT_ERR_DYN_CODE_MOD 6 /* --------------------------------------------------------------------- */ /* Registers */ /* --------------------------------------------------------------------- */ /* - Scratch (R) registers: registers whose may not preserve their values + Scratch (R) registers: registers which may not preserve their values across function calls. - Saved (S) registers: registers whose preserve their values across + Saved (S) registers: registers which preserve their values across function calls. - The scratch and saved register sets are overlap. The last scratch register + The scratch and saved register sets overlap. The last scratch register is the first saved register, the one before the last is the second saved register, and so on. @@ -209,7 +209,7 @@ extern "C" { /* The SLJIT_SP provides direct access to the linear stack space allocated by sljit_emit_enter. It can only be used in the following form: SLJIT_MEM1(SLJIT_SP). The immediate offset is extended by the relative stack offset automatically. - The sljit_get_local_base can be used to obtain the absolute offset. */ + The sljit_get_local_base can be used to obtain the real address of a value. */ #define SLJIT_SP (SLJIT_NUMBER_OF_REGISTERS + 1) /* Return with machine word. */ @@ -249,6 +249,10 @@ extern "C" { /* Float registers >= SLJIT_FIRST_SAVED_FLOAT_REG are saved registers. */ #define SLJIT_FIRST_SAVED_FLOAT_REG (SLJIT_FS0 - SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS + 1) +/* Return with floating point arg. */ + +#define SLJIT_RETURN_FREG SLJIT_FR0 + /* --------------------------------------------------------------------- */ /* Argument type definitions */ /* --------------------------------------------------------------------- */ @@ -284,7 +288,7 @@ extern "C" { | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_32, 3) | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_F32, 4) Short form of argument type definition: - SLJIT_ARGS4(32, P, F64, 32, F32) + SLJIT_ARGS4(F32, P, F64, 32, F32) Argument passing: arg_a must be placed in SLJIT_R0 @@ -386,6 +390,7 @@ struct sljit_label { struct sljit_jump { struct sljit_jump *next; sljit_uw addr; + /* Architecture dependent flags. */ sljit_uw flags; union { sljit_uw target; @@ -423,17 +428,17 @@ struct sljit_compiler { struct sljit_memory_fragment *buf; struct sljit_memory_fragment *abuf; - /* Used scratch registers. */ + /* Available scratch registers. */ sljit_s32 scratches; - /* Used saved registers. */ + /* Available saved registers. */ sljit_s32 saveds; - /* Used float scratch registers. */ + /* Available float scratch registers. */ sljit_s32 fscratches; - /* Used float saved registers. */ + /* Available float saved registers. */ sljit_s32 fsaveds; /* Local stack size. */ sljit_s32 local_size; - /* Code size. */ + /* Maximum code size. */ sljit_uw size; /* Relative offset of the executable mapping from the writable mapping. */ sljit_sw executable_offset; @@ -514,7 +519,8 @@ struct sljit_compiler { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ || (defined SLJIT_DEBUG && SLJIT_DEBUG) \ || (defined SLJIT_VERBOSE && SLJIT_VERBOSE) - /* Trust arguments when the API function is called. */ + /* Trust arguments when an API function is called. + Used internally for calling API functions. */ sljit_s32 skip_checks; #endif }; @@ -523,7 +529,7 @@ struct sljit_compiler { /* Main functions */ /* --------------------------------------------------------------------- */ -/* Creates an sljit compiler. The allocator_data is required by some +/* Creates an SLJIT compiler. The allocator_data is required by some custom memory managers. This pointer is passed to SLJIT_MALLOC and SLJIT_FREE macros. Most allocators (including the default one) ignores this value, and it is recommended to pass NULL @@ -537,43 +543,44 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allo /* Frees everything except the compiled machine code. */ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler); -/* Returns the current error code. If an error is occurred, future sljit - calls which uses the same compiler argument returns early with the same +/* Returns the current error code. If an error occurres, future calls + which uses the same compiler argument returns early with the same error code. Thus there is no need for checking the error after every - call, it is enough to do it before the code is compiled. Removing + call, it is enough to do it after the code is compiled. Removing these checks increases the performance of the compiling process. */ static SLJIT_INLINE sljit_s32 sljit_get_compiler_error(struct sljit_compiler *compiler) { return compiler->error; } /* Sets the compiler error code to SLJIT_ERR_ALLOC_FAILED except if an error was detected before. After the error code is set the compiler behaves as if the allocation failure happened - during an sljit function call. This can greatly simplify error - checking, since only the compiler status needs to be checked - after the compilation. */ + during an SLJIT function call. This can greatly simplify error + checking, since it is enough to check the compiler status + after the code is compiled. */ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_compiler_memory_error(struct sljit_compiler *compiler); -/* - Allocate a small amount of memory. The size must be <= 64 bytes on 32 bit, +/* Allocate a small amount of memory. The size must be <= 64 bytes on 32 bit, and <= 128 bytes on 64 bit architectures. The memory area is owned by the compiler, and freed by sljit_free_compiler. The returned pointer is sizeof(sljit_sw) aligned. Excellent for allocating small blocks during - the compiling, and no need to worry about freeing them. The size is - enough to contain at most 16 pointers. If the size is outside of the range, + compiling, and no need to worry about freeing them. The size is enough + to contain at most 16 pointers. If the size is outside of the range, the function will return with NULL. However, this return value does not indicate that there is no more memory (does not set the current error code - of the compiler to out-of-memory status). -*/ + of the compiler to out-of-memory status). */ SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, sljit_s32 size); +/* Returns the allocator data passed to sljit_create_compiler. These pointers + may contain context data even if the normal/exec allocator ignores it. */ +static SLJIT_INLINE void* sljit_get_allocator_data(struct sljit_compiler *compiler) { return compiler->allocator_data; } +static SLJIT_INLINE void* sljit_get_exec_allocator_data(struct sljit_compiler *compiler) { return compiler->exec_allocator_data; } + #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) /* Passing NULL disables verbose. */ SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *compiler, FILE* verbose); #endif -/* - Create executable code from the sljit instruction stream. This is the final step - of the code generation so no more instructions can be added after this call. -*/ +/* Create executable code from the instruction stream. This is the final step + of the code generation so no more instructions can be emitted after this call. */ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler); @@ -581,8 +588,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code, void *exec_allocator_data); -/* - When the protected executable allocator is used the JIT code is mapped +/* When the protected executable allocator is used the JIT code is mapped twice. The first mapping has read/write and the second mapping has read/exec permissions. This function returns with the relative offset of the executable mapping using the writable mapping as the base after the machine code is @@ -590,26 +596,24 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code, void *exec_allocator_d allocator, since it uses only one mapping with read/write/exec permissions. Dynamic code modifications requires this value. - Before a successful code generation, this function returns with 0. -*/ + Before a successful code generation, this function returns with 0. */ static SLJIT_INLINE sljit_sw sljit_get_executable_offset(struct sljit_compiler *compiler) { return compiler->executable_offset; } -/* - The executable memory consumption of the generated code can be retrieved by +/* The executable memory consumption of the generated code can be retrieved by this function. The returned value can be used for statistical purposes. - Before a successful code generation, this function returns with 0. -*/ + Before a successful code generation, this function returns with 0. */ static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler *compiler) { return compiler->executable_size; } /* Returns with non-zero if the feature or limitation type passed as its - argument is present on the current CPU. + argument is present on the current CPU. The return value is one, if a + feature is fully supported, and it is two, if partially supported. Some features (e.g. floating point operations) require hardware (CPU) support while others (e.g. move with update) are emulated if not available. - However even if a feature is emulated, specialized code paths can be faster - than the emulation. Some limitations are emulated as well so their general - case is supported but it has extra performance costs. */ + However, even when a feature is emulated, specialized code paths may be + faster than the emulation. Some limitations are emulated as well so their + general case is supported but it has extra performance costs. */ /* [Not emulated] Floating-point support is available. */ #define SLJIT_HAS_FPU 0 @@ -619,10 +623,20 @@ static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler #define SLJIT_HAS_ZERO_REGISTER 2 /* [Emulated] Count leading zero is supported. */ #define SLJIT_HAS_CLZ 3 +/* [Emulated] Count trailing zero is supported. */ +#define SLJIT_HAS_CTZ 4 +/* [Emulated] Reverse the order of bytes is supported. */ +#define SLJIT_HAS_REV 5 +/* [Emulated] Rotate left/right is supported. */ +#define SLJIT_HAS_ROT 6 /* [Emulated] Conditional move is supported. */ -#define SLJIT_HAS_CMOV 4 -/* [Emulated] Conditional move is supported. */ -#define SLJIT_HAS_PREFETCH 5 +#define SLJIT_HAS_CMOV 7 +/* [Emulated] Prefetch instruction is available (emulated as a nop). */ +#define SLJIT_HAS_PREFETCH 8 +/* [Emulated] Copy from/to f32 operation is available (see sljit_emit_fcopy). */ +#define SLJIT_HAS_COPY_F32 9 +/* [Emulated] Copy from/to f64 operation is available (see sljit_emit_fcopy). */ +#define SLJIT_HAS_COPY_F64 10 #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) /* [Not emulated] SSE2 support is available on x86. */ @@ -645,8 +659,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) Otherwise it returns zero. */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type); -/* Instruction generation. Returns with any error code. If there is no - error, they return with SLJIT_SUCCESS. */ +/* The following functions generate machine code. If there is no + error, they return with SLJIT_SUCCESS, otherwise they return + with an error code. */ /* The executable code is a function from the viewpoint of the C @@ -654,30 +669,29 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type); Binary Interface) of the platform, which specify the purpose of machine registers and stack handling among other things. The sljit_emit_enter function emits the necessary instructions for - setting up a new context for the executable code and moves function - arguments to the saved registers. Furthermore the options argument + setting up a new context for the executable code. This is often + called as function prologue. Furthermore the options argument can be used to pass configuration options to the compiler. The available options are listed before sljit_emit_enter. - The function argument list is the combination of SLJIT_ARGx - (SLJIT_DEF_ARG1) macros. Currently maximum 4 arguments are - supported. The first integer argument is loaded into SLJIT_S0, - the second one is loaded into SLJIT_S1, and so on. Similarly, - the first floating point argument is loaded into SLJIT_FR0, - the second one is loaded into SLJIT_FR1, and so on. Furthermore - the register set used by the function must be declared as well. - The number of scratch and saved registers used by the function - must be passed to sljit_emit_enter. Only R registers between R0 + The function argument list is specified by the SLJIT_ARGSx + (SLJIT_ARGS0 .. SLJIT_ARGS4) macros. Currently maximum four + arguments are supported. See the description of SLJIT_ARGSx + macros about argument passing. Furthermore the register set + used by the function must be declared as well. The number of + scratch and saved registers available to the function must + be passed to sljit_emit_enter. Only R registers between R0 and "scratches" argument can be used later. E.g. if "scratches" - is set to 2, the scratch register set will be limited to SLJIT_R0 - and SLJIT_R1. The S registers and the floating point registers - ("fscratches" and "fsaveds") are specified in a similar manner. - The sljit_emit_enter is also capable of allocating a stack space - for local variables. The "local_size" argument contains the size - in bytes of this local area and its staring address is stored - in SLJIT_SP. The memory area between SLJIT_SP (inclusive) and - SLJIT_SP + local_size (exclusive) can be modified freely until - the function returns. The stack space is not initialized. + is set to two, the scratch register set will be limited to + SLJIT_R0 and SLJIT_R1. The S registers and the floating point + registers ("fscratches" and "fsaveds") are specified in a + similar manner. The sljit_emit_enter is also capable of + allocating a stack space for local data. The "local_size" + argument contains the size in bytes of this local area, and + it can be accessed using SLJIT_MEM1(SLJIT_SP). The memory + area between SLJIT_SP (inclusive) and SLJIT_SP + local_size + (exclusive) can be modified freely until the function returns. + The stack space is not initialized to zero. Note: the following conditions must met: 0 <= scratches <= SLJIT_NUMBER_OF_REGISTERS @@ -698,16 +712,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type); are not saved / restored on function enter / return. Instead, these registers can be used to pass / return data (such as global / local context pointers) across function calls. The - value of n must be between 1 and 3. Furthermore, this option - is only supported by register argument calling convention, so - SLJIT_ENTER_REG_ARG (see below) must be specified as well. */ + value of n must be between 1 and 3. This option is only + supported by SLJIT_ENTER_REG_ARG calling convention. */ #define SLJIT_ENTER_KEEP(n) (n) -/* The compiled function uses an sljit specific register argument - * calling convention. This is a lightweight function call type where - * both the caller and called function must be compiled with sljit. - * The jump type of the function call must be SLJIT_CALL_REG_ARG - * and the called function must store all arguments in registers. */ +/* The compiled function uses an SLJIT specific register argument + calling convention. This is a lightweight function call type where + both the caller and the called functions must be compiled by + SLJIT. The type argument of the call must be SLJIT_CALL_REG_ARG + and all arguments must be stored in scratch registers. */ #define SLJIT_ENTER_REG_ARG 0x00000004 /* The local_size must be >= 0 and <= SLJIT_MAX_LOCAL_SIZE. */ @@ -717,12 +730,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size); -/* The machine code has a context (which contains the local stack space size, - number of used registers, etc.) which initialized by sljit_emit_enter. Several - functions (such as sljit_emit_return) requres this context to be able to generate - the appropriate code. However, some code fragments (like inline cache) may have - no normal entry point so their context is unknown for the compiler. Their context - can be provided to the compiler by the sljit_set_context function. +/* The SLJIT compiler has a current context (which contains the local + stack space size, number of used registers, etc.) which is initialized + by sljit_emit_enter. Several functions (such as sljit_emit_return) + requires this context to be able to generate the appropriate code. + However, some code fragments (compiled separately) may have no + normal entry point so their context is unknown for the compiler. + + The sljit_set_context and sljit_emit_enter have the same arguments, + but sljit_set_context does not generate any machine code. Note: every call of sljit_emit_enter and sljit_set_context overwrites the previous context. */ @@ -731,51 +747,42 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size); -/* Return from machine code. The sljit_emit_return_void function does not return with - any value. The sljit_emit_return function returns with a single value which stores - the result of a data move instruction. The instruction is specified by the op - argument, and must be between SLJIT_MOV and SLJIT_MOV_P (see sljit_emit_op1). */ +/* Return to the caller function. The sljit_emit_return_void function + does not return with any value. The sljit_emit_return function returns + with a single value loaded from its source operand. The load operation + can be between SLJIT_MOV and SLJIT_MOV_P (see sljit_emit_op1) and + SLJIT_MOV_F32/SLJIT_MOV_F64 (see sljit_emit_fop1) depending on the + return value specified by sljit_emit_enter/sljit_set_context. */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler); SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw); -/* Generating entry and exit points for fast call functions (see SLJIT_FAST_CALL). - Both sljit_emit_fast_enter and SLJIT_FAST_RETURN operations preserve the - values of all registers and stack frame. The return address is stored in the - dst argument of sljit_emit_fast_enter, and this return address can be passed - to SLJIT_FAST_RETURN to continue the execution after the fast call. +/* Restores the saved registers and free the stack area, then the execution + continues from the address specified by the source operand. This + operation is similar to sljit_emit_return, but it ignores the return + address. The code where the exection continues should use the same context + as the caller function (see sljit_set_context). A word (pointer) value + can be passed in the SLJIT_RETURN_REG register. This function can be used + to jump to exception handlers. */ - Fast calls are cheap operations (usually only a single call instruction is - emitted) but they do not preserve any registers. However the callee function - can freely use / update any registers and stack values which can be - efficiently exploited by various optimizations. Registers can be saved - manually by the callee function if needed. - - Although returning to different address by SLJIT_FAST_RETURN is possible, - this address usually cannot be predicted by the return address predictor of - modern CPUs which may reduce performance. Furthermore certain security - enhancement technologies such as Intel Control-flow Enforcement Technology - (CET) may disallow returning to a different address. - - Flags: - (does not modify flags). */ - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw); +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw); /* Source and destination operands for arithmetical instructions imm - a simple immediate value (cannot be used as a destination) - reg - any of the registers (immediate argument must be 0) - [imm] - absolute immediate memory address + reg - any of the available registers (immediate argument must be 0) + [imm] - absolute memory address [reg+imm] - indirect memory address [reg+(reg<> 1) >> (src3 ^ value_mask)) + SLJIT_MSHL or SLJIT_MSHL32: + src3 &= value_mask + perform the SLJIT_SHL or SLJIT_SHL32 operation + SLJIT_LSHR or SLJIT_LSHR32: + dst_reg = src1_reg >> src3_reg + dst_reg |= ((src2_reg << 1) << (src3 ^ value_mask)) + SLJIT_MLSHR or SLJIT_MLSHR32: + src3 &= value_mask + perform the SLJIT_LSHR or SLJIT_LSHR32 operation + + op can be combined (or'ed) with SLJIT_SHIFT_INTO_NON_ZERO + + dst_reg specifies the destination register, where dst_reg + and src2_reg cannot be the same registers + src1_reg specifies the source register + src2_reg specifies the register which is shifted into src1_reg + src3 / src3w contains the shift amount + + Note: a rotate operation is performed if src1_reg and + src2_reg are the same registers + + Flags: - (may destroy flags) */ + +/* The src3 operand contains a non-zero value. Improves + the generated code on certain architectures, which + provides a small performance improvement. */ +#define SLJIT_SHIFT_INTO_NON_ZERO 0x200 + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst_reg, + sljit_s32 src1_reg, + sljit_s32 src2_reg, + sljit_s32 src3, sljit_sw src3w); + +/* Starting index of opcodes for sljit_emit_op_src + and sljit_emit_op_dst. */ +#define SLJIT_OP_SRC_DST_BASE 96 + +/* Fast return, see SLJIT_FAST_CALL for more details. + Note: src cannot be an immedate value Flags: - (does not modify flags) */ -#define SLJIT_FAST_RETURN (SLJIT_OP_SRC_BASE + 0) +#define SLJIT_FAST_RETURN (SLJIT_OP_SRC_DST_BASE + 0) /* Skip stack frames before fast return. Note: src cannot be an immedate value Flags: may destroy flags. */ -#define SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN (SLJIT_OP_SRC_BASE + 1) +#define SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN (SLJIT_OP_SRC_DST_BASE + 1) /* Prefetch value into the level 1 data cache Note: if the target CPU does not support data prefetch, no instructions are emitted. Note: this instruction never fails, even if the memory address is invalid. Flags: - (does not modify flags) */ -#define SLJIT_PREFETCH_L1 (SLJIT_OP_SRC_BASE + 2) +#define SLJIT_PREFETCH_L1 (SLJIT_OP_SRC_DST_BASE + 2) /* Prefetch value into the level 2 data cache Note: same as SLJIT_PREFETCH_L1 if the target CPU does not support this instruction form. Note: this instruction never fails, even if the memory address is invalid. Flags: - (does not modify flags) */ -#define SLJIT_PREFETCH_L2 (SLJIT_OP_SRC_BASE + 3) +#define SLJIT_PREFETCH_L2 (SLJIT_OP_SRC_DST_BASE + 3) /* Prefetch value into the level 3 data cache Note: same as SLJIT_PREFETCH_L2 if the target CPU does not support this instruction form. Note: this instruction never fails, even if the memory address is invalid. Flags: - (does not modify flags) */ -#define SLJIT_PREFETCH_L3 (SLJIT_OP_SRC_BASE + 4) +#define SLJIT_PREFETCH_L3 (SLJIT_OP_SRC_DST_BASE + 4) /* Prefetch a value which is only used once (and can be discarded afterwards) Note: same as SLJIT_PREFETCH_L1 if the target CPU does not support this instruction form. Note: this instruction never fails, even if the memory address is invalid. Flags: - (does not modify flags) */ -#define SLJIT_PREFETCH_ONCE (SLJIT_OP_SRC_BASE + 5) +#define SLJIT_PREFETCH_ONCE (SLJIT_OP_SRC_DST_BASE + 5) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw); +/* Fast enter, see SLJIT_FAST_CALL for more details. + Flags: - (does not modify flags) */ +#define SLJIT_FAST_ENTER (SLJIT_OP_SRC_DST_BASE + 6) + +/* Copies the return address into dst. The return address is the + address where the execution continues after the called function + returns (see: sljit_emit_return / sljit_emit_return_void). + Flags: - (does not modify flags) */ +#define SLJIT_GET_RETURN_ADDRESS (SLJIT_OP_SRC_DST_BASE + 7) + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw); + /* Starting index of opcodes for sljit_emit_fop1. */ -#define SLJIT_FOP1_BASE 160 +#define SLJIT_FOP1_BASE 128 /* Flags: - (does not modify flags) */ #define SLJIT_MOV_F64 (SLJIT_FOP1_BASE + 0) #define SLJIT_MOV_F32 (SLJIT_MOV_F64 | SLJIT_32) /* Convert opcodes: CONV[DST_TYPE].FROM[SRC_TYPE] - SRC/DST TYPE can be: D - double, S - single, W - signed word, I - signed int - Rounding mode when the destination is W or I: round towards zero. */ + SRC/DST TYPE can be: F64, F32, S32, SW + Rounding mode when the destination is SW or S32: round towards zero. */ /* Flags: - (may destroy flags) */ #define SLJIT_CONV_F64_FROM_F32 (SLJIT_FOP1_BASE + 1) #define SLJIT_CONV_F32_FROM_F64 (SLJIT_CONV_F64_FROM_F32 | SLJIT_32) @@ -1158,7 +1276,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *comp /* Flags: - (may destroy flags) */ #define SLJIT_CONV_F64_FROM_S32 (SLJIT_FOP1_BASE + 5) #define SLJIT_CONV_F32_FROM_S32 (SLJIT_CONV_F64_FROM_S32 | SLJIT_32) -/* Note: dst is the left and src is the right operand for SLJIT_CMPD. +/* Note: dst is the left and src is the right operand for SLJIT_CMP_F32/64. Flags: EQUAL_F | LESS_F | GREATER_EQUAL_F | GREATER_F | LESS_EQUAL_F */ #define SLJIT_CMP_F64 (SLJIT_FOP1_BASE + 6) #define SLJIT_CMP_F32 (SLJIT_CMP_F64 | SLJIT_32) @@ -1174,7 +1292,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil sljit_s32 src, sljit_sw srcw); /* Starting index of opcodes for sljit_emit_fop2. */ -#define SLJIT_FOP2_BASE 192 +#define SLJIT_FOP2_BASE 160 /* Flags: - (may destroy flags) */ #define SLJIT_ADD_F64 (SLJIT_FOP2_BASE + 0) @@ -1194,10 +1312,70 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w); +/* The following opcodes are used by sljit_emit_fcopy(). */ + +/* 64 bit: copy a 64 bit value from an integer register into a + 64 bit floating point register without any modifications. + 32 bit: copy a 32 bit register or register pair into a 64 bit + floating point register without any modifications. The + register, or the first register of the register pair + replaces the high order 32 bit of the floating point + register. If a register pair is passed, the low + order 32 bit is replaced by the second register. + Otherwise, the low order 32 bit is unchanged. */ +#define SLJIT_COPY_TO_F64 1 +/* Copy a 32 bit value from an integer register into a 32 bit + floating point register without any modifications. */ +#define SLJIT_COPY32_TO_F32 (SLJIT_COPY_TO_F64 | SLJIT_32) +/* 64 bit: copy the value of a 64 bit floating point register into + an integer register without any modifications. + 32 bit: copy a 64 bit floating point register into a 32 bit register + or a 32 bit register pair without any modifications. The + high order 32 bit of the floating point register is copied + into the register, or the first register of the register + pair. If a register pair is passed, the low order 32 bit + is copied into the second register. */ +#define SLJIT_COPY_FROM_F64 2 +/* Copy the value of a 32 bit floating point register into an integer + register without any modifications. The register should be processed + with 32 bit operations later. */ +#define SLJIT_COPY32_FROM_F32 (SLJIT_COPY_FROM_F64 | SLJIT_32) + +/* Special data copy which involves floating point registers. + + op must be between SLJIT_COPY_TO_F64 and SLJIT_COPY32_FROM_F32 + freg must be a floating point register + reg must be a register or register pair */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 freg, sljit_s32 reg); + /* Label and jump instructions. */ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler); +/* The SLJIT_FAST_CALL is a calling method for creating lightweight function + calls. This type of calls preserve the values of all registers and stack + frame. Unlike normal function calls, the enter and return operations must + be performed by the SLJIT_FAST_ENTER and SLJIT_FAST_RETURN operations + respectively. The return address is stored in the dst argument of the + SLJIT_FAST_ENTER operation, and this return address should be passed as + the src argument for the SLJIT_FAST_RETURN operation to return from the + called function. + + Fast calls are cheap operations (usually only a single call instruction is + emitted) but they do not preserve any registers. However the callee function + can freely use / update any registers and the locals area which can be + efficiently exploited by various optimizations. Registers can be saved + and restored manually if needed. + + Although returning to different address by SLJIT_FAST_RETURN is possible, + this address usually cannot be predicted by the return address predictor of + modern CPUs which may reduce performance. Furthermore certain security + enhancement technologies such as Intel Control-flow Enforcement Technology + (CET) may disallow returning to a different address (indirect jumps + can be used instead, see SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN). */ + /* Invert (negate) conditional type: xor (^) with 0x1 */ /* Integer comparison types. */ @@ -1209,25 +1387,25 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi #define SLJIT_LESS 2 #define SLJIT_SET_LESS SLJIT_SET(SLJIT_LESS) #define SLJIT_GREATER_EQUAL 3 -#define SLJIT_SET_GREATER_EQUAL SLJIT_SET(SLJIT_GREATER_EQUAL) +#define SLJIT_SET_GREATER_EQUAL SLJIT_SET(SLJIT_LESS) #define SLJIT_GREATER 4 #define SLJIT_SET_GREATER SLJIT_SET(SLJIT_GREATER) #define SLJIT_LESS_EQUAL 5 -#define SLJIT_SET_LESS_EQUAL SLJIT_SET(SLJIT_LESS_EQUAL) +#define SLJIT_SET_LESS_EQUAL SLJIT_SET(SLJIT_GREATER) #define SLJIT_SIG_LESS 6 #define SLJIT_SET_SIG_LESS SLJIT_SET(SLJIT_SIG_LESS) #define SLJIT_SIG_GREATER_EQUAL 7 -#define SLJIT_SET_SIG_GREATER_EQUAL SLJIT_SET(SLJIT_SIG_GREATER_EQUAL) +#define SLJIT_SET_SIG_GREATER_EQUAL SLJIT_SET(SLJIT_SIG_LESS) #define SLJIT_SIG_GREATER 8 #define SLJIT_SET_SIG_GREATER SLJIT_SET(SLJIT_SIG_GREATER) #define SLJIT_SIG_LESS_EQUAL 9 -#define SLJIT_SET_SIG_LESS_EQUAL SLJIT_SET(SLJIT_SIG_LESS_EQUAL) +#define SLJIT_SET_SIG_LESS_EQUAL SLJIT_SET(SLJIT_SIG_GREATER) #define SLJIT_OVERFLOW 10 #define SLJIT_SET_OVERFLOW SLJIT_SET(SLJIT_OVERFLOW) #define SLJIT_NOT_OVERFLOW 11 -/* Unlike other flags, sljit_emit_jump may destroy this flag. */ +/* Unlike other flags, sljit_emit_jump may destroy the carry flag. */ #define SLJIT_CARRY 12 #define SLJIT_SET_CARRY SLJIT_SET(SLJIT_CARRY) #define SLJIT_NOT_CARRY 13 @@ -1239,22 +1417,22 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi #define SLJIT_F_EQUAL 14 #define SLJIT_SET_F_EQUAL SLJIT_SET(SLJIT_F_EQUAL) #define SLJIT_F_NOT_EQUAL 15 -#define SLJIT_SET_F_NOT_EQUAL SLJIT_SET(SLJIT_F_NOT_EQUAL) +#define SLJIT_SET_F_NOT_EQUAL SLJIT_SET(SLJIT_F_EQUAL) #define SLJIT_F_LESS 16 #define SLJIT_SET_F_LESS SLJIT_SET(SLJIT_F_LESS) #define SLJIT_F_GREATER_EQUAL 17 -#define SLJIT_SET_F_GREATER_EQUAL SLJIT_SET(SLJIT_F_GREATER_EQUAL) +#define SLJIT_SET_F_GREATER_EQUAL SLJIT_SET(SLJIT_F_LESS) #define SLJIT_F_GREATER 18 #define SLJIT_SET_F_GREATER SLJIT_SET(SLJIT_F_GREATER) #define SLJIT_F_LESS_EQUAL 19 -#define SLJIT_SET_F_LESS_EQUAL SLJIT_SET(SLJIT_F_LESS_EQUAL) +#define SLJIT_SET_F_LESS_EQUAL SLJIT_SET(SLJIT_F_GREATER) /* Jumps when either argument contains a NaN value. */ #define SLJIT_UNORDERED 20 #define SLJIT_SET_UNORDERED SLJIT_SET(SLJIT_UNORDERED) /* Jumps when neither argument contains a NaN value. */ #define SLJIT_ORDERED 21 -#define SLJIT_SET_ORDERED SLJIT_SET(SLJIT_ORDERED) +#define SLJIT_SET_ORDERED SLJIT_SET(SLJIT_UNORDERED) /* Ordered / unordered floating point comparison types. @@ -1264,37 +1442,37 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi #define SLJIT_ORDERED_EQUAL 22 #define SLJIT_SET_ORDERED_EQUAL SLJIT_SET(SLJIT_ORDERED_EQUAL) #define SLJIT_UNORDERED_OR_NOT_EQUAL 23 -#define SLJIT_SET_UNORDERED_OR_NOT_EQUAL SLJIT_SET(SLJIT_UNORDERED_OR_NOT_EQUAL) +#define SLJIT_SET_UNORDERED_OR_NOT_EQUAL SLJIT_SET(SLJIT_ORDERED_EQUAL) #define SLJIT_ORDERED_LESS 24 #define SLJIT_SET_ORDERED_LESS SLJIT_SET(SLJIT_ORDERED_LESS) #define SLJIT_UNORDERED_OR_GREATER_EQUAL 25 -#define SLJIT_SET_UNORDERED_OR_GREATER_EQUAL SLJIT_SET(SLJIT_UNORDERED_OR_GREATER_EQUAL) +#define SLJIT_SET_UNORDERED_OR_GREATER_EQUAL SLJIT_SET(SLJIT_ORDERED_LESS) #define SLJIT_ORDERED_GREATER 26 #define SLJIT_SET_ORDERED_GREATER SLJIT_SET(SLJIT_ORDERED_GREATER) #define SLJIT_UNORDERED_OR_LESS_EQUAL 27 -#define SLJIT_SET_UNORDERED_OR_LESS_EQUAL SLJIT_SET(SLJIT_UNORDERED_OR_LESS_EQUAL) +#define SLJIT_SET_UNORDERED_OR_LESS_EQUAL SLJIT_SET(SLJIT_ORDERED_GREATER) #define SLJIT_UNORDERED_OR_EQUAL 28 #define SLJIT_SET_UNORDERED_OR_EQUAL SLJIT_SET(SLJIT_UNORDERED_OR_EQUAL) #define SLJIT_ORDERED_NOT_EQUAL 29 -#define SLJIT_SET_ORDERED_NOT_EQUAL SLJIT_SET(SLJIT_ORDERED_NOT_EQUAL) +#define SLJIT_SET_ORDERED_NOT_EQUAL SLJIT_SET(SLJIT_UNORDERED_OR_EQUAL) #define SLJIT_UNORDERED_OR_LESS 30 #define SLJIT_SET_UNORDERED_OR_LESS SLJIT_SET(SLJIT_UNORDERED_OR_LESS) #define SLJIT_ORDERED_GREATER_EQUAL 31 -#define SLJIT_SET_ORDERED_GREATER_EQUAL SLJIT_SET(SLJIT_ORDERED_GREATER_EQUAL) +#define SLJIT_SET_ORDERED_GREATER_EQUAL SLJIT_SET(SLJIT_UNORDERED_OR_LESS) #define SLJIT_UNORDERED_OR_GREATER 32 #define SLJIT_SET_UNORDERED_OR_GREATER SLJIT_SET(SLJIT_UNORDERED_OR_GREATER) #define SLJIT_ORDERED_LESS_EQUAL 33 -#define SLJIT_SET_ORDERED_LESS_EQUAL SLJIT_SET(SLJIT_ORDERED_LESS_EQUAL) +#define SLJIT_SET_ORDERED_LESS_EQUAL SLJIT_SET(SLJIT_UNORDERED_OR_GREATER) /* Unconditional jump types. */ #define SLJIT_JUMP 34 - /* Fast calling method. See sljit_emit_fast_enter / SLJIT_FAST_RETURN. */ +/* Fast calling method. See the description above. */ #define SLJIT_FAST_CALL 35 - /* Default C calling convention. */ +/* Default C calling convention. */ #define SLJIT_CALL 36 - /* Called function must be an sljit compiled function. - See SLJIT_ENTER_REG_ARG option. */ +/* Called function must be compiled by SLJIT. + See SLJIT_ENTER_REG_ARG option. */ #define SLJIT_CALL_REG_ARG 37 /* The target can be changed during runtime (see: sljit_set_jump_addr). */ @@ -1304,7 +1482,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi stack usage is reduced before the call, but it is not necessarily reduced to zero. In the latter case the compiler needs to allocate space for some arguments and the return address must be stored on the stack as well. */ -#define SLJIT_CALL_RETURN 0x2000 +#define SLJIT_CALL_RETURN 0x2000 /* Emit a jump instruction. The destination is not set, only the type of the jump. type must be between SLJIT_EQUAL and SLJIT_FAST_CALL @@ -1314,18 +1492,18 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type); /* Emit a C compiler (ABI) compatible function call. - type must be SLJIT_CALL or SLJIT_CALL_CDECL - type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP and SLJIT_CALL_RETURN - arg_types is the combination of SLJIT_RET / SLJIT_ARGx (SLJIT_DEF_RET / SLJIT_DEF_ARGx) macros + type must be SLJIT_CALL or SLJIT_CALL_REG_ARG + type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP and/or SLJIT_CALL_RETURN + arg_types can be specified by SLJIT_ARGSx (SLJIT_ARG_RETURN / SLJIT_ARG_VALUE) macros Flags: destroy all flags. */ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types); /* Basic arithmetic comparison. In most architectures it is implemented as - an compare operation followed by a sljit_emit_jump. However some - architectures (i.e: ARM64 or MIPS) may employ special optimizations here. - It is suggested to use this comparison form when appropriate. - type must be between SLJIT_EQUAL and SLJIT_I_SIG_LESS_EQUAL + a compare operation followed by a sljit_emit_jump. However some + architectures (i.e: ARM64 or MIPS) may employ special optimizations + here. It is suggested to use this comparison form when appropriate. + type must be between SLJIT_EQUAL and SLJIT_SIG_LESS_EQUAL type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP Flags: may destroy flags. */ @@ -1334,15 +1512,14 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler sljit_s32 src2, sljit_sw src2w); /* Basic floating point comparison. In most architectures it is implemented as - an SLJIT_FCMP operation (setting appropriate flags) followed by a + a SLJIT_CMP_F32/64 operation (setting appropriate flags) followed by a sljit_emit_jump. However some architectures (i.e: MIPS) may employ special optimizations here. It is suggested to use this comparison form when appropriate. type must be between SLJIT_F_EQUAL and SLJIT_ORDERED_LESS_EQUAL type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP Flags: destroy flags. - Note: if either operand is NaN, the behaviour is undefined for - types up to SLJIT_S_LESS_EQUAL. */ + Note: when an operand is NaN the behaviour depends on the comparison type. */ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w); @@ -1363,22 +1540,22 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi /* Emit a C compiler (ABI) compatible function call. Direct form: set src to SLJIT_IMM() and srcw to the address Indirect form: any other valid addressing mode - type must be SLJIT_CALL or SLJIT_CALL_CDECL + type must be SLJIT_CALL or SLJIT_CALL_REG_ARG type can be combined (or'ed) with SLJIT_CALL_RETURN - arg_types is the combination of SLJIT_RET / SLJIT_ARGx (SLJIT_DEF_RET / SLJIT_DEF_ARGx) macros + arg_types can be specified by SLJIT_ARGSx (SLJIT_ARG_RETURN / SLJIT_ARG_VALUE) macros Flags: destroy all flags. */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types, sljit_s32 src, sljit_sw srcw); -/* Perform the operation using the conditional flags as the second argument. - Type must always be between SLJIT_EQUAL and SLJIT_ORDERED_LESS_EQUAL. The value - represented by the type is 1, if the condition represented by the type - is fulfilled, and 0 otherwise. +/* Perform an operation using the conditional flags as the second argument. + Type must always be between SLJIT_EQUAL and SLJIT_ORDERED_LESS_EQUAL. + The value represented by the type is 1, if the condition represented + by the type is fulfilled, and 0 otherwise. - If op == SLJIT_MOV, SLJIT_MOV32: + When op is SLJIT_MOV or SLJIT_MOV32: Set dst to the value represented by the type (0 or 1). Flags: - (does not modify flags) - If op == SLJIT_OR, op == SLJIT_AND, op == SLJIT_XOR + When op is SLJIT_AND, SLJIT_AND32, SLJIT_OR, SLJIT_OR32, SLJIT_XOR, or SLJIT_XOR32 Performs the binary operation using dst as the first, and the value represented by type as the second argument. Result is written into dst. Flags: Z (may destroy flags) */ @@ -1391,49 +1568,50 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co instruction does not support memory access. type must be between SLJIT_EQUAL and SLJIT_ORDERED_LESS_EQUAL - dst_reg must be a valid register and it can be combined - with SLJIT_32 to perform a 32 bit arithmetic operation - src must be register or immediate (SLJIT_IMM) + type can be combined (or'ed) with SLJIT_32 + dst_reg must be a valid register + src must be a valid register or immediate (SLJIT_IMM) Flags: - (does not modify flags) */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 dst_reg, sljit_s32 src, sljit_sw srcw); -/* The following flags are used by sljit_emit_mem() and sljit_emit_fmem(). */ +/* The following flags are used by sljit_emit_mem(), sljit_emit_mem_update(), + sljit_emit_fmem(), and sljit_emit_fmem_update(). */ /* Memory load operation. This is the default. */ #define SLJIT_MEM_LOAD 0x000000 /* Memory store operation. */ #define SLJIT_MEM_STORE 0x000200 -/* Load or stora data from an unaligned address. */ +/* The following flags are used by sljit_emit_mem() and sljit_emit_fmem(). */ + +/* Load or stora data from an unaligned (byte aligned) address. */ #define SLJIT_MEM_UNALIGNED 0x000400 -/* Load or store data and update the base address with a single operation. */ -/* Base register is updated before the memory access. */ -#define SLJIT_MEM_PRE 0x000800 +/* Load or stora data from a 16 bit aligned address. */ +#define SLJIT_MEM_UNALIGNED_16 0x000800 +/* Load or stora data from a 32 bit aligned address. */ +#define SLJIT_MEM_UNALIGNED_32 0x001000 + +/* The following flags are used by sljit_emit_mem_update(), + and sljit_emit_fmem_update(). */ + +/* Base register is updated before the memory access (default). */ +#define SLJIT_MEM_PRE 0x000000 /* Base register is updated after the memory access. */ -#define SLJIT_MEM_POST 0x001000 - -/* The following flags are supported when SLJIT_MEM_UNALIGNED is specified: */ - -/* Defines 16 bit alignment for unaligned accesses. */ -#define SLJIT_MEM_ALIGNED_16 0x010000 -/* Defines 32 bit alignment for unaligned accesses. */ -#define SLJIT_MEM_ALIGNED_32 0x020000 - -/* The following flags are supported when SLJIT_MEM_PRE or - SLJIT_MEM_POST is specified: */ +#define SLJIT_MEM_POST 0x000400 /* When SLJIT_MEM_SUPP is passed, no instructions are emitted. Instead the function returns with SLJIT_SUCCESS if the instruction form is supported and SLJIT_ERR_UNSUPPORTED otherwise. This flag allows runtime checking of available instruction forms. */ -#define SLJIT_MEM_SUPP 0x010000 +#define SLJIT_MEM_SUPP 0x000800 /* The sljit_emit_mem emits instructions for various memory operations: - When SLJIT_MEM_UNALIGNED is set in type argument: + When SLJIT_MEM_UNALIGNED / SLJIT_MEM_UNALIGNED_16 / + SLJIT_MEM_UNALIGNED_32 is set in type argument: Emit instructions for unaligned memory loads or stores. When SLJIT_UNALIGNED is not defined, the only way to access unaligned memory data is using sljit_emit_mem. Otherwise all operations (e.g. @@ -1448,24 +1626,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil location specified by the mem/memw arguments, and the end address of this operation is the starting address of the data transfer between the second register and memory. The type argument must - be SLJIT_MOV. The SLJIT_MEM_UNALIGNED flag and its options are - allowed for this operation. - - When SLJIT_MEM_PRE or SLJIT_MEM_POST is set in type argument: - Emit a single memory load or store with update instruction. - When the requested instruction form is not supported by the CPU, - it returns with SLJIT_ERR_UNSUPPORTED instead of emulating the - instruction. This allows specializing tight loops based on - the supported instruction forms (see SLJIT_MEM_SUPP flag). - Absolute address (SLJIT_MEM0) forms are never supported - and the base (first) register specified by the mem argument - must not be SLJIT_SP and must also be different from the - register specified by the reg argument. + be SLJIT_MOV. The SLJIT_MEM_UNALIGNED* options are allowed for + this operation. type must be between SLJIT_MOV and SLJIT_MOV_P and can be - combined with SLJIT_MEM_* flags. + combined (or'ed) with SLJIT_MEM_* flags reg is a register or register pair, which is the source or - destination of the operation. + destination of the operation mem must be a memory operand Flags: - (does not modify flags) */ @@ -1473,11 +1640,35 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile sljit_s32 reg, sljit_s32 mem, sljit_sw memw); +/* Emit a single memory load or store with update instruction. + When the requested instruction form is not supported by the CPU, + it returns with SLJIT_ERR_UNSUPPORTED instead of emulating the + instruction. This allows specializing tight loops based on + the supported instruction forms (see SLJIT_MEM_SUPP flag). + Absolute address (SLJIT_MEM0) forms are never supported + and the base (first) register specified by the mem argument + must not be SLJIT_SP and must also be different from the + register specified by the reg argument. + + type must be between SLJIT_MOV and SLJIT_MOV_P and can be + combined (or'ed) with SLJIT_MEM_* flags + reg is the source or destination register of the operation + mem must be a memory operand + + Flags: - (does not modify flags) */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 reg, + sljit_s32 mem, sljit_sw memw); + /* Same as sljit_emit_mem except the followings: + Loading or storing a pair of registers is not supported. + type must be SLJIT_MOV_F64 or SLJIT_MOV_F32 and can be - combined with SLJIT_MEM_* flags. + combined (or'ed) with SLJIT_MEM_* flags. freg is the source or destination floating point register + of the operation mem must be a memory operand Flags: - (does not modify flags) */ @@ -1486,14 +1677,29 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil sljit_s32 freg, sljit_s32 mem, sljit_sw memw); -/* Copies the base address of SLJIT_SP + offset to dst. The offset can be - anything to negate the effect of relative addressing. For example if an - array of sljit_sw values is stored on the stack from offset 0x40, and R0 - contains the offset of an array item plus 0x120, this item can be - overwritten by two SLJIT instructions: +/* Same as sljit_emit_mem_update except the followings: + + type must be SLJIT_MOV_F64 or SLJIT_MOV_F32 and can be + combined (or'ed) with SLJIT_MEM_* flags + freg is the source or destination floating point register + of the operation + mem must be a memory operand + + Flags: - (does not modify flags) */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 mem, sljit_sw memw); + +/* Copies the base address of SLJIT_SP + offset to dst. The offset can + represent the starting address of a value in the local data (stack). + The offset is not limited by the local data limits, it can be any value. + For example if an array of bytes are stored on the stack from + offset 0x40, and R0 contains the offset of an array item plus 0x120, + this item can be changed by two SLJIT instructions: sljit_get_local_base(compiler, SLJIT_R1, 0, 0x40 - 0x120); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0, SLJIT_IMM, 0x5); + sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0, SLJIT_IMM, 0x5); Flags: - (may destroy flags) */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset); @@ -1521,19 +1727,72 @@ static SLJIT_INLINE sljit_uw sljit_get_const_addr(struct sljit_const *const_) { SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset); SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset); +/* --------------------------------------------------------------------- */ +/* CPU specific functions */ +/* --------------------------------------------------------------------- */ + +/* The following function is a helper function for sljit_emit_op_custom. + It returns with the real machine register index ( >=0 ) of any SLJIT_R, + SLJIT_S and SLJIT_SP registers. + + Note: it returns with -1 for virtual registers (only on x86-32). */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg); + +/* The following function is a helper function for sljit_emit_op_custom. + It returns with the real machine register ( >= 0 ) index of any SLJIT_FR, + and SLJIT_FS register. + + Note: the index is always an even number on ARM-32, MIPS. */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg); + +/* Any instruction can be inserted into the instruction stream by + sljit_emit_op_custom. It has a similar purpose as inline assembly. + The size parameter must match to the instruction size of the target + architecture: + + x86: 0 < size <= 15. The instruction argument can be byte aligned. + Thumb2: if size == 2, the instruction argument must be 2 byte aligned. + if size == 4, the instruction argument must be 4 byte aligned. + Otherwise: size must be 4 and instruction argument must be 4 byte aligned. */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, + void *instruction, sljit_u32 size); + +/* Flags were set by a 32 bit operation. */ +#define SLJIT_CURRENT_FLAGS_32 SLJIT_32 + +/* Flags were set by an ADD or ADDC operations. */ +#define SLJIT_CURRENT_FLAGS_ADD 0x01 +/* Flags were set by a SUB, SUBC, or NEG operation. */ +#define SLJIT_CURRENT_FLAGS_SUB 0x02 + +/* Flags were set by sljit_emit_op2u with SLJIT_SUB opcode. + Must be combined with SLJIT_CURRENT_FLAGS_SUB. */ +#define SLJIT_CURRENT_FLAGS_COMPARE 0x04 + +/* Define the currently available CPU status flags. It is usually used after + an sljit_emit_label or sljit_emit_op_custom operations to define which CPU + status flags are available. + + The current_flags must be a valid combination of SLJIT_SET_* and + SLJIT_CURRENT_FLAGS_* constants. */ + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler, + sljit_s32 current_flags); + /* --------------------------------------------------------------------- */ /* Miscellaneous utility functions */ /* --------------------------------------------------------------------- */ -#define SLJIT_MAJOR_VERSION 0 -#define SLJIT_MINOR_VERSION 94 - /* Get the human readable name of the platform. Can be useful on platforms - like ARM, where ARM and Thumb2 functions can be mixed, and - it is useful to know the type of the code generator. */ + like ARM, where ARM and Thumb2 functions can be mixed, and it is useful + to know the type of the code generator. */ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void); -/* Portable helper function to get an offset of a member. */ +/* Portable helper function to get an offset of a member. + Same as offsetof() macro defined in stddef.h */ #define SLJIT_OFFSETOF(base, member) ((sljit_sw)(&((base*)0x10)->member) - 0x10) #if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) @@ -1624,60 +1883,6 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void); #endif -/* --------------------------------------------------------------------- */ -/* CPU specific functions */ -/* --------------------------------------------------------------------- */ - -/* The following function is a helper function for sljit_emit_op_custom. - It returns with the real machine register index ( >=0 ) of any SLJIT_R, - SLJIT_S and SLJIT_SP registers. - - Note: it returns with -1 for virtual registers (only on x86-32). */ - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg); - -/* The following function is a helper function for sljit_emit_op_custom. - It returns with the real machine register index of any SLJIT_FLOAT register. - - Note: the index is always an even number on ARM-32, MIPS. */ - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg); - -/* Any instruction can be inserted into the instruction stream by - sljit_emit_op_custom. It has a similar purpose as inline assembly. - The size parameter must match to the instruction size of the target - architecture: - - x86: 0 < size <= 15. The instruction argument can be byte aligned. - Thumb2: if size == 2, the instruction argument must be 2 byte aligned. - if size == 4, the instruction argument must be 4 byte aligned. - Otherwise: size must be 4 and instruction argument must be 4 byte aligned. */ - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, - void *instruction, sljit_u32 size); - -/* Flags were set by a 32 bit operation. */ -#define SLJIT_CURRENT_FLAGS_32 SLJIT_32 - -/* Flags were set by an ADD or ADDC operations. */ -#define SLJIT_CURRENT_FLAGS_ADD 0x01 -/* Flags were set by a SUB, SUBC, or NEG operation. */ -#define SLJIT_CURRENT_FLAGS_SUB 0x02 - -/* Flags were set by sljit_emit_op2u with SLJIT_SUB opcode. - Must be combined with SLJIT_CURRENT_FLAGS_SUB. */ -#define SLJIT_CURRENT_FLAGS_COMPARE 0x04 - -/* Define the currently available CPU status flags. It is usually used after - an sljit_emit_label or sljit_emit_op_custom operations to define which CPU - status flags are available. - - The current_flags must be a valid combination of SLJIT_SET_* and - SLJIT_CURRENT_FLAGS_* constants. */ - -SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler, - sljit_s32 current_flags); - #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeARM_32.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeARM_32.c index a1f16f5055..8175293d2b 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeARM_32.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeARM_32.c @@ -101,6 +101,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define BKPT 0xe1200070 #define EOR 0xe0200000 #define LDR 0xe5100000 +#define LDR_POST 0xe4100000 #define MOV 0xe1a00000 #define MUL 0xe0000090 #define MVN 0xe1e00000 @@ -108,6 +109,8 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define ORR 0xe1800000 #define PUSH 0xe92d0000 #define POP 0xe8bd0000 +#define RBIT 0xe6ff0f30 +#define REV 0xe6bf0f30 #define RSB 0xe0600000 #define RSC 0xe0e00000 #define SBC 0xe0c00000 @@ -566,6 +569,7 @@ static SLJIT_INLINE void inline_set_jump_addr(sljit_uw jump_ptr, sljit_sw execut static sljit_uw get_imm(sljit_uw imm); static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_uw imm); +static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg); static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw executable_offset, sljit_uw new_constant, sljit_s32 flush_cache) { @@ -957,12 +961,22 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) #endif case SLJIT_HAS_CLZ: + case SLJIT_HAS_ROT: case SLJIT_HAS_CMOV: #if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) + case SLJIT_HAS_CTZ: + case SLJIT_HAS_REV: case SLJIT_HAS_PREFETCH: #endif + case SLJIT_HAS_COPY_F32: + case SLJIT_HAS_COPY_F64: return 1; +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + case SLJIT_HAS_CTZ: + return 2; +#endif + default: return 0; } @@ -1224,6 +1238,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1); + /* Doubles are saved, so alignment is unaffected. */ if ((size & SSIZE_OF(sw)) != 0 && (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG)) size += SSIZE_OF(sw); @@ -1236,8 +1251,11 @@ static sljit_s32 emit_add_sp(struct sljit_compiler *compiler, sljit_uw imm) sljit_uw imm2 = get_imm(imm); if (imm2 == 0) { - FAIL_IF(load_immediate(compiler, TMP_REG2, imm)); - imm2 = RM(TMP_REG2); + imm2 = (imm & ~(sljit_uw)0x3ff) >> 10; + imm = (imm & 0x3ff) >> 2; + + FAIL_IF(push_inst(compiler, ADD | SRC2_IMM | RD(SLJIT_SP) | RN(SLJIT_SP) | 0xb00 | imm2)); + return push_inst(compiler, ADD | SRC2_IMM | RD(SLJIT_SP) | RN(SLJIT_SP) | 0xf00 | (imm & 0xff)); } return push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | imm2); @@ -1246,11 +1264,11 @@ static sljit_s32 emit_add_sp(struct sljit_compiler *compiler, sljit_uw imm) static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size) { sljit_s32 local_size, fscratches, fsaveds, i, tmp; - sljit_s32 saveds_restore_start = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); + sljit_s32 restored_reg = 0; sljit_s32 lr_dst = TMP_PC; - sljit_uw reg_list; + sljit_uw reg_list = 0; - SLJIT_ASSERT(reg_map[TMP_REG2] == 14); + SLJIT_ASSERT(reg_map[TMP_REG2] == 14 && frame_size <= 128); local_size = compiler->local_size; fscratches = compiler->fscratches; @@ -1275,47 +1293,84 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit if (frame_size < 0) { lr_dst = TMP_REG2; frame_size = 0; - } else if (frame_size > 0) + } else if (frame_size > 0) { + SLJIT_ASSERT(frame_size == 1 || (frame_size & 0x7) == 0); lr_dst = 0; + frame_size &= ~0x7; + } - reg_list = 0; if (lr_dst != 0) reg_list |= (sljit_uw)1 << reg_map[lr_dst]; tmp = SLJIT_S0 - compiler->saveds; - if (saveds_restore_start != tmp) { - for (i = saveds_restore_start; i > tmp; i--) + i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); + if (tmp < i) { + restored_reg = i; + do { reg_list |= (sljit_uw)1 << reg_map[i]; - } else - saveds_restore_start = 0; + } while (--i > tmp); + } - for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) - reg_list |= (sljit_uw)1 << reg_map[i]; + i = compiler->scratches; + if (i >= SLJIT_FIRST_SAVED_REG) { + restored_reg = i; + do { + reg_list |= (sljit_uw)1 << reg_map[i]; + } while (--i >= SLJIT_FIRST_SAVED_REG); + } + + if (lr_dst == TMP_REG2 && reg_list == 0) { + restored_reg = TMP_REG2; + lr_dst = 0; + } if (lr_dst == 0 && (reg_list & (reg_list - 1)) == 0) { /* The local_size does not include the saved registers. */ - local_size += SSIZE_OF(sw); + tmp = 0; + if (reg_list != 0) { + tmp = 2; + if (local_size <= 0xfff) { + if (local_size == 0) { + SLJIT_ASSERT(restored_reg != TMP_REG2); + if (frame_size == 0) + return push_inst(compiler, LDR_POST | RN(SLJIT_SP) | RD(restored_reg) | 0x800008); + if (frame_size > 2 * SSIZE_OF(sw)) + return push_inst(compiler, LDR_POST | RN(SLJIT_SP) | RD(restored_reg) | (sljit_uw)(frame_size - (2 * SSIZE_OF(sw)))); + } - if (reg_list != 0) - local_size += SSIZE_OF(sw); + FAIL_IF(push_inst(compiler, LDR | 0x800000 | RN(SLJIT_SP) | RD(restored_reg) | (sljit_uw)local_size)); + tmp = 1; + } else if (frame_size == 0) { + frame_size = (restored_reg == TMP_REG2) ? SSIZE_OF(sw) : 2 * SSIZE_OF(sw); + tmp = 3; + } + + /* Place for the saved register. */ + if (restored_reg != TMP_REG2) + local_size += SSIZE_OF(sw); + } + + /* Place for the lr register. */ + local_size += SSIZE_OF(sw); if (frame_size > local_size) FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 25) | (sljit_uw)(frame_size - local_size))); else if (frame_size < local_size) FAIL_IF(emit_add_sp(compiler, (sljit_uw)(local_size - frame_size))); - if (reg_list == 0) + if (tmp <= 1) return SLJIT_SUCCESS; - if (saveds_restore_start != 0) { - SLJIT_ASSERT(reg_list == ((sljit_uw)1 << reg_map[saveds_restore_start])); - lr_dst = saveds_restore_start; - } else { - SLJIT_ASSERT(reg_list == ((sljit_uw)1 << reg_map[SLJIT_FIRST_SAVED_REG])); - lr_dst = SLJIT_FIRST_SAVED_REG; + if (tmp == 2) { + frame_size -= SSIZE_OF(sw); + if (restored_reg != TMP_REG2) + frame_size -= SSIZE_OF(sw); + + return push_inst(compiler, LDR | 0x800000 | RN(SLJIT_SP) | RD(restored_reg) | (sljit_uw)frame_size); } - return push_inst(compiler, LDR | 0x800000 | RN(SLJIT_SP) | RD(lr_dst) | (sljit_uw)(frame_size - 2 * SSIZE_OF(sw))); + tmp = (restored_reg == TMP_REG2) ? 0x800004 : 0x800008; + return push_inst(compiler, LDR_POST | RN(SLJIT_SP) | RD(restored_reg) | (sljit_uw)tmp); } if (local_size > 0) @@ -1328,13 +1383,18 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit SLJIT_ASSERT(lr_dst != 0); SLJIT_ASSERT(reg_list == (sljit_uw)1 << reg_map[lr_dst]); - return push_inst(compiler, 0xe49d0004 | RD(lr_dst)); + return push_inst(compiler, LDR_POST | RN(SLJIT_SP) | RD(lr_dst) | 0x800004); } FAIL_IF(push_inst(compiler, POP | reg_list)); + if (frame_size > 0) return push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 25) | ((sljit_uw)frame_size - sizeof(sljit_sw))); - return SLJIT_SUCCESS; + + if (lr_dst != 0) + return SLJIT_SUCCESS; + + return push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 25) | sizeof(sljit_sw)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler) @@ -1345,28 +1405,38 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler return emit_stack_frame_release(compiler, 0); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_return_to(compiler, src, srcw)); + + if (src & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1)); + src = TMP_REG1; + srcw = 0; + } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { + FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(src))); + src = TMP_REG1; + srcw = 0; + } + + FAIL_IF(emit_stack_frame_release(compiler, 1)); + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw); +} + /* --------------------------------------------------------------------- */ /* Operators */ /* --------------------------------------------------------------------- */ -#define EMIT_SHIFT_INS_AND_RETURN(opcode) \ - SLJIT_ASSERT(!(flags & INV_IMM) && !(src2 & SRC2_IMM)); \ - if (compiler->shift_imm != 0x20) { \ - SLJIT_ASSERT(src1 == TMP_REG1); \ - SLJIT_ASSERT(!(flags & ARGS_SWAPPED)); \ - \ - if (compiler->shift_imm != 0) \ - return push_inst(compiler, MOV | (flags & SET_FLAGS) | \ - RD(dst) | (compiler->shift_imm << 7) | (opcode << 5) | RM(src2)); \ - return push_inst(compiler, MOV | (flags & SET_FLAGS) | RD(dst) | RM(src2)); \ - } \ - return push_inst(compiler, MOV | (flags & SET_FLAGS) | RD(dst) \ - | RM8((flags & ARGS_SWAPPED) ? src1 : src2) | (sljit_uw)(opcode << 5) \ - | 0x10 | RM((flags & ARGS_SWAPPED) ? src2 : src1)); - static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_uw dst, sljit_uw src1, sljit_uw src2) { + sljit_s32 is_masked; + sljit_uw shift_type; + switch (GET_OPCODE(op)) { case SLJIT_MOV: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED)); @@ -1414,18 +1484,38 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl } return SLJIT_SUCCESS; - case SLJIT_NOT: - if (src2 & SRC2_IMM) - return push_inst(compiler, ((flags & INV_IMM) ? MOV : MVN) | (flags & SET_FLAGS) | RD(dst) | src2); - - return push_inst(compiler, MVN | (flags & SET_FLAGS) | RD(dst) | RM(src2)); - case SLJIT_CLZ: - SLJIT_ASSERT(!(flags & INV_IMM)); - SLJIT_ASSERT(!(src2 & SRC2_IMM)); + SLJIT_ASSERT(!(flags & INV_IMM) && !(src2 & SRC2_IMM)); FAIL_IF(push_inst(compiler, CLZ | RD(dst) | RM(src2))); return SLJIT_SUCCESS; + case SLJIT_CTZ: + SLJIT_ASSERT(!(flags & INV_IMM) && !(src2 & SRC2_IMM)); + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED)); +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + FAIL_IF(push_inst(compiler, RSB | SRC2_IMM | RD(TMP_REG1) | RN(src2) | 0)); + FAIL_IF(push_inst(compiler, AND | RD(TMP_REG2) | RN(src2) | RM(TMP_REG1))); + FAIL_IF(push_inst(compiler, CLZ | RD(dst) | RM(TMP_REG2))); + FAIL_IF(push_inst(compiler, CMP | SET_FLAGS | SRC2_IMM | RN(dst) | 32)); + return push_inst(compiler, (EOR ^ 0xf0000000) | SRC2_IMM | RD(dst) | RN(dst) | 0x1f); +#else /* !SLJIT_CONFIG_ARM_V5 */ + FAIL_IF(push_inst(compiler, RBIT | RD(dst) | RM(src2))); + return push_inst(compiler, CLZ | RD(dst) | RM(dst)); +#endif /* SLJIT_CONFIG_ARM_V5 */ + + case SLJIT_REV: +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (8 << 7) | (0 << 5) | RM(src2))); + FAIL_IF(push_inst(compiler, MOV | RD(dst) | (24 << 7) | (1 << 5) | RM(src2))); + FAIL_IF(push_inst(compiler, ORR | RD(dst) | RN(dst) | (16 << 7) | (0 << 5) | RM(TMP_REG1))); + FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (16 << 7) | (1 << 5) | RM(TMP_REG1))); + FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (8 << 7) | (3 << 5) | RM(TMP_REG1))); + FAIL_IF(push_inst(compiler, ORR | RD(dst) | RN(dst) | (8 << 7) | (0 << 5) | RM(TMP_REG1))); + return push_inst(compiler, ORR | RD(dst) | RN(dst) | (8 << 7) | (1 << 5) | RM(TMP_REG1)); +#else /* !SLJIT_CONFIG_ARM_V5 */ + return push_inst(compiler, REV | RD(dst) | RM(src2)); +#endif /* SLJIT_CONFIG_ARM_V5 */ + case SLJIT_ADD: SLJIT_ASSERT(!(flags & INV_IMM)); @@ -1475,21 +1565,68 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl return push_inst(compiler, ORR | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2))); case SLJIT_XOR: - SLJIT_ASSERT(!(flags & INV_IMM)); + if (flags & INV_IMM) { + SLJIT_ASSERT(src2 == SRC2_IMM); + return push_inst(compiler, MVN | (flags & SET_FLAGS) | RD(dst) | RM(src1)); + } return push_inst(compiler, EOR | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2))); case SLJIT_SHL: - EMIT_SHIFT_INS_AND_RETURN(0); + case SLJIT_MSHL: + shift_type = 0; + is_masked = GET_OPCODE(op) == SLJIT_MSHL; + break; case SLJIT_LSHR: - EMIT_SHIFT_INS_AND_RETURN(1); + case SLJIT_MLSHR: + shift_type = 1; + is_masked = GET_OPCODE(op) == SLJIT_MLSHR; + break; case SLJIT_ASHR: - EMIT_SHIFT_INS_AND_RETURN(2); + case SLJIT_MASHR: + shift_type = 2; + is_masked = GET_OPCODE(op) == SLJIT_MASHR; + break; + + case SLJIT_ROTL: + if (compiler->shift_imm == 0x20) { + FAIL_IF(push_inst(compiler, RSB | SRC2_IMM | RD(TMP_REG2) | RN(src2) | 0)); + src2 = TMP_REG2; + } else + compiler->shift_imm = (sljit_uw)(-(sljit_sw)compiler->shift_imm) & 0x1f; + /* fallthrough */ + + case SLJIT_ROTR: + shift_type = 3; + is_masked = 0; + break; + + default: + SLJIT_UNREACHABLE(); + return SLJIT_SUCCESS; } - SLJIT_UNREACHABLE(); - return SLJIT_SUCCESS; + SLJIT_ASSERT(!(flags & ARGS_SWAPPED) && !(flags & INV_IMM) && !(src2 & SRC2_IMM)); + + if (compiler->shift_imm != 0x20) { + SLJIT_ASSERT(src1 == TMP_REG1); + + if (compiler->shift_imm != 0) + return push_inst(compiler, MOV | (flags & SET_FLAGS) | + RD(dst) | (compiler->shift_imm << 7) | (shift_type << 5) | RM(src2)); + return push_inst(compiler, MOV | (flags & SET_FLAGS) | RD(dst) | RM(src2)); + } + + SLJIT_ASSERT(src1 != TMP_REG2); + + if (is_masked) { + FAIL_IF(push_inst(compiler, AND | RD(TMP_REG2) | RN(src2) | SRC2_IMM | 0x1f)); + src2 = TMP_REG2; + } + + return push_inst(compiler, MOV | (flags & SET_FLAGS) | RD(dst) + | RM8(src2) | (sljit_uw)(shift_type << 5) | 0x10 | RM(src1)); } #undef EMIT_SHIFT_INS_AND_RETURN @@ -1678,7 +1815,7 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, #endif } -static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, +static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg) { sljit_uw imm, offset_reg, tmp; @@ -2033,10 +2170,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile case SLJIT_MOV_S16: return emit_op(compiler, SLJIT_MOV_S16, ALLOW_ANY_IMM | SIGNED | HALF_SIZE, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw); - case SLJIT_NOT: - return emit_op(compiler, op, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw); - case SLJIT_CLZ: + case SLJIT_CTZ: + case SLJIT_REV: return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src, srcw); } @@ -2048,6 +2184,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { + sljit_s32 inp_flags; + CHECK_ERROR(); CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w)); ADJUST_LOCAL_OFFSET(dst, dstw); @@ -2062,9 +2200,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile return emit_op(compiler, op, ALLOW_IMM | ALLOW_NEG_IMM, dst, dstw, src1, src1w, src2, src2w); case SLJIT_OR: - case SLJIT_XOR: return emit_op(compiler, op, ALLOW_IMM, dst, dstw, src1, src1w, src2, src2w); + case SLJIT_XOR: + inp_flags = ALLOW_IMM; + if (((src1 & SLJIT_IMM) && src1w == -1) || ((src2 & SLJIT_IMM) && src2w == -1)) { + inp_flags |= ALLOW_INV_IMM; + } + return emit_op(compiler, op, inp_flags, dst, dstw, src1, src1w, src2, src2w); + case SLJIT_MUL: return emit_op(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w); @@ -2072,13 +2216,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile return emit_op(compiler, op, ALLOW_ANY_IMM, dst, dstw, src1, src1w, src2, src2w); case SLJIT_SHL: + case SLJIT_MSHL: case SLJIT_LSHR: + case SLJIT_MLSHR: case SLJIT_ASHR: + case SLJIT_MASHR: + case SLJIT_ROTL: + case SLJIT_ROTR: if (src2 & SLJIT_IMM) { compiler->shift_imm = src2w & 0x1f; return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src1, src1w); - } - else { + } else { compiler->shift_imm = 0x20; return emit_op(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w); } @@ -2098,6 +2246,55 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst_reg, + sljit_s32 src1_reg, + sljit_s32 src2_reg, + sljit_s32 src3, sljit_sw src3w) +{ + sljit_s32 is_left; + + CHECK_ERROR(); + CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w)); + + op = GET_OPCODE(op); + is_left = (op == SLJIT_SHL || op == SLJIT_MSHL); + + if (src1_reg == src2_reg) { + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_op2(compiler, is_left ? SLJIT_ROTL : SLJIT_ROTR, dst_reg, 0, src1_reg, 0, src3, src3w); + } + + ADJUST_LOCAL_OFFSET(src3, src3w); + + /* Shift type of ROR is 3. */ + if (src3 & SLJIT_IMM) { + src3w &= 0x1f; + + if (src3w == 0) + return SLJIT_SUCCESS; + + FAIL_IF(push_inst(compiler, MOV | RD(dst_reg) | RM(src1_reg) | ((sljit_uw)(is_left ? 0 : 1) << 5) | ((sljit_uw)src3w << 7))); + src3w = (src3w ^ 0x1f) + 1; + return push_inst(compiler, ORR | RD(dst_reg) | RN(dst_reg) | RM(src2_reg) | ((sljit_uw)(is_left ? 1 : 0) << 5) | ((sljit_uw)src3w << 7)); + } + + if (src3 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, src3, src3w, TMP_REG2)); + src3 = TMP_REG2; + } + + if (op == SLJIT_MSHL || op == SLJIT_MLSHR || dst_reg == src3) { + FAIL_IF(push_inst(compiler, AND | SRC2_IMM | RD(TMP_REG2) | RN(src3) | 0x1f)); + src3 = TMP_REG2; + } + + FAIL_IF(push_inst(compiler, MOV | RD(dst_reg) | RM8(src3) | ((sljit_uw)(is_left ? 0 : 1) << 5) | 0x10 | RM(src1_reg))); + FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(src2_reg) | ((sljit_uw)(is_left ? 1 : 0) << 5) | (1 << 7))); + FAIL_IF(push_inst(compiler, EOR | SRC2_IMM | RD(TMP_REG2) | RN(src3) | 0x1f)); + return push_inst(compiler, ORR | RD(dst_reg) | RN(dst_reg) | RM8(TMP_REG2) | ((sljit_uw)(is_left ? 1 : 0) << 5) | 0x10 | RM(TMP_REG1)); +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { @@ -2132,6 +2329,46 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *comp return SLJIT_SUCCESS; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw) +{ + sljit_s32 size, dst_r; + + CHECK_ERROR(); + CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw)); + ADJUST_LOCAL_OFFSET(dst, dstw); + + switch (op) { + case SLJIT_FAST_ENTER: + SLJIT_ASSERT(reg_map[TMP_REG2] == 14); + + if (FAST_IS_REG(dst)) + return push_inst(compiler, MOV | RD(dst) | RM(TMP_REG2)); + break; + case SLJIT_GET_RETURN_ADDRESS: + size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds - SLJIT_KEPT_SAVEDS_COUNT(compiler->options), 0); + + if (compiler->fsaveds > 0 || compiler->fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) { + /* The size of pc is not added above. */ + if ((size & SSIZE_OF(sw)) == 0) + size += SSIZE_OF(sw); + + size += GET_SAVED_FLOAT_REGISTERS_SIZE(compiler->fscratches, compiler->fsaveds, f64); + } + + SLJIT_ASSERT(((compiler->local_size + size + SSIZE_OF(sw)) & 0x7) == 0); + + dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2; + FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, dst_r, SLJIT_MEM1(SLJIT_SP), compiler->local_size + size, TMP_REG1)); + break; + } + + if (dst & SLJIT_MEM) + return emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1); + + return SLJIT_SUCCESS; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_register_index(reg)); @@ -2372,23 +2609,31 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil #undef EMIT_FPU_DATA_TRANSFER -/* --------------------------------------------------------------------- */ -/* Other instructions */ -/* --------------------------------------------------------------------- */ - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 freg, sljit_s32 reg) { + sljit_s32 reg2; + sljit_uw inst; + CHECK_ERROR(); - CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); - ADJUST_LOCAL_OFFSET(dst, dstw); + CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg)); - SLJIT_ASSERT(reg_map[TMP_REG2] == 14); + if (reg & REG_PAIR_MASK) { + reg2 = REG_PAIR_SECOND(reg); + reg = REG_PAIR_FIRST(reg); - if (FAST_IS_REG(dst)) - return push_inst(compiler, MOV | RD(dst) | RM(TMP_REG2)); + inst = VMOV2 | RN(reg) | RD(reg2) | VM(freg); + } else { + inst = VMOV | VN(freg) | RD(reg); - /* Memory. */ - return emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1); + if (!(op & SLJIT_32)) + inst |= 1 << 7; + } + + if (GET_OPCODE(op) == SLJIT_COPY_FROM_F64) + inst |= 1 << 20; + + return push_inst(compiler, inst); } /* --------------------------------------------------------------------- */ @@ -2834,7 +3079,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi src = TMP_REG1; } - if ((type & SLJIT_CALL_RETURN) && (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0)) { + if ((type & SLJIT_CALL_RETURN) && (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options)))) { FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(src))); src = TMP_REG1; } @@ -2880,6 +3125,33 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi return sljit_emit_ijump(compiler, type, src, srcw); } +#ifdef __SOFTFP__ + +static SLJIT_INLINE sljit_s32 emit_fmov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) +{ + if (compiler->options & SLJIT_ENTER_REG_ARG) { + if (src == SLJIT_FR0) + return SLJIT_SUCCESS; + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_fop1(compiler, op, SLJIT_RETURN_FREG, 0, src, srcw); + } + + if (FAST_IS_REG(src)) { + if (op & SLJIT_32) + return push_inst(compiler, VMOV | (1 << 20) | RD(SLJIT_R0) | VN(src)); + return push_inst(compiler, VMOV2 | (1 << 20) | RD(SLJIT_R0) | RN(SLJIT_R1) | VM(src)); + } + + SLJIT_SKIP_CHECKS(compiler); + + if (op & SLJIT_32) + return sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, src, srcw); + return sljit_emit_mem(compiler, SLJIT_MOV, SLJIT_REG_PAIR(SLJIT_R0, SLJIT_R1), src, srcw); +} + +#endif /* __SOFTFP__ */ + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 type) @@ -2930,9 +3202,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil CHECK_ERROR(); CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); - dst_reg &= ~SLJIT_32; - - cc = get_cc(compiler, type); + cc = get_cc(compiler, type & ~SLJIT_32); if (SLJIT_UNLIKELY(src & SLJIT_IMM)) { tmp = get_imm((sljit_uw)srcw); @@ -3058,7 +3328,7 @@ static sljit_s32 sljit_emit_mem_unaligned(struct sljit_compiler *compiler, sljit break; default: - if (type & SLJIT_MEM_ALIGNED_32) { + if (type & SLJIT_MEM_UNALIGNED_32) { flags = WORD_SIZE; if (!(type & SLJIT_MEM_STORE)) flags |= LOAD_DATA; @@ -3066,7 +3336,7 @@ static sljit_s32 sljit_emit_mem_unaligned(struct sljit_compiler *compiler, sljit return emit_op_mem(compiler, flags, reg, mem, memw, TMP_REG1); } - if (!(type & SLJIT_MEM_ALIGNED_16)) { + if (!(type & SLJIT_MEM_UNALIGNED_16)) { FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 3)); flags = BYTE_SIZE; steps = 3; @@ -3182,46 +3452,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile sljit_s32 mem, sljit_sw memw) { sljit_s32 flags; - sljit_uw is_type1_transfer, inst; CHECK_ERROR(); CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); - if (reg & REG_PAIR_MASK) { - ADJUST_LOCAL_OFFSET(mem, memw); - -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) - if ((type & SLJIT_MEM_UNALIGNED) && !(type & SLJIT_MEM_ALIGNED_32)) { - FAIL_IF(update_mem_addr(compiler, &mem, &memw, (type & SLJIT_MEM_ALIGNED_16) ? 0xfff - 6 : 0xfff - 7)); - - if (!(type & SLJIT_MEM_STORE) && REG_PAIR_FIRST(reg) == (mem & REG_MASK)) { - FAIL_IF(sljit_emit_mem_unaligned(compiler, type, REG_PAIR_SECOND(reg), SLJIT_MEM1(mem), memw + SSIZE_OF(sw))); - return sljit_emit_mem_unaligned(compiler, type, REG_PAIR_FIRST(reg), SLJIT_MEM1(mem), memw); - } - - FAIL_IF(sljit_emit_mem_unaligned(compiler, type, REG_PAIR_FIRST(reg), SLJIT_MEM1(mem), memw)); - return sljit_emit_mem_unaligned(compiler, type, REG_PAIR_SECOND(reg), SLJIT_MEM1(mem), memw + SSIZE_OF(sw)); - } -#endif /* SLJIT_CONFIG_ARM_V5 */ - - FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4)); - - flags = WORD_SIZE; - - if (!(type & SLJIT_MEM_STORE)) { - if (REG_PAIR_FIRST(reg) == (mem & REG_MASK)) { - FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, REG_PAIR_SECOND(reg), SLJIT_MEM1(mem), memw + SSIZE_OF(sw), TMP_REG1)); - return emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, REG_PAIR_FIRST(reg), SLJIT_MEM1(mem), memw, TMP_REG1); - } - - flags = WORD_SIZE | LOAD_DATA; - } - - FAIL_IF(emit_op_mem(compiler, flags, REG_PAIR_FIRST(reg), SLJIT_MEM1(mem), memw, TMP_REG1)); - return emit_op_mem(compiler, flags, REG_PAIR_SECOND(reg), SLJIT_MEM1(mem), memw + SSIZE_OF(sw), TMP_REG1); - } - - if (type & SLJIT_MEM_UNALIGNED) { + if (!(reg & REG_PAIR_MASK)) { #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) ADJUST_LOCAL_OFFSET(mem, memw); #endif /* SLJIT_CONFIG_ARM_V5 */ @@ -3229,6 +3464,49 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw); } + ADJUST_LOCAL_OFFSET(mem, memw); + +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + if (type & (SLJIT_MEM_UNALIGNED | SLJIT_MEM_UNALIGNED_16)) { + FAIL_IF(update_mem_addr(compiler, &mem, &memw, (type & SLJIT_MEM_UNALIGNED_16) ? 0xfff - 6 : 0xfff - 7)); + + if (!(type & SLJIT_MEM_STORE) && REG_PAIR_FIRST(reg) == (mem & REG_MASK)) { + FAIL_IF(sljit_emit_mem_unaligned(compiler, type, REG_PAIR_SECOND(reg), SLJIT_MEM1(mem), memw + SSIZE_OF(sw))); + return sljit_emit_mem_unaligned(compiler, type, REG_PAIR_FIRST(reg), SLJIT_MEM1(mem), memw); + } + + FAIL_IF(sljit_emit_mem_unaligned(compiler, type, REG_PAIR_FIRST(reg), SLJIT_MEM1(mem), memw)); + return sljit_emit_mem_unaligned(compiler, type, REG_PAIR_SECOND(reg), SLJIT_MEM1(mem), memw + SSIZE_OF(sw)); + } +#endif /* SLJIT_CONFIG_ARM_V5 */ + + FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4)); + + flags = WORD_SIZE; + + if (!(type & SLJIT_MEM_STORE)) { + if (REG_PAIR_FIRST(reg) == (mem & REG_MASK)) { + FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, REG_PAIR_SECOND(reg), SLJIT_MEM1(mem), memw + SSIZE_OF(sw), TMP_REG1)); + return emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, REG_PAIR_FIRST(reg), SLJIT_MEM1(mem), memw, TMP_REG1); + } + + flags = WORD_SIZE | LOAD_DATA; + } + + FAIL_IF(emit_op_mem(compiler, flags, REG_PAIR_FIRST(reg), SLJIT_MEM1(mem), memw, TMP_REG1)); + return emit_op_mem(compiler, flags, REG_PAIR_SECOND(reg), SLJIT_MEM1(mem), memw + SSIZE_OF(sw), TMP_REG1); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 reg, + sljit_s32 mem, sljit_sw memw) +{ + sljit_s32 flags; + sljit_uw is_type1_transfer, inst; + + CHECK_ERROR(); + CHECK(check_sljit_emit_mem_update(compiler, type, reg, mem, memw)); + is_type1_transfer = 1; switch (type & 0xff) { @@ -3269,16 +3547,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) { if (!is_type1_transfer && memw != 0) return SLJIT_ERR_UNSUPPORTED; - } - else { + } else { if (is_type1_transfer) { if (memw > 4095 || memw < -4095) return SLJIT_ERR_UNSUPPORTED; - } - else { - if (memw > 255 || memw < -255) - return SLJIT_ERR_UNSUPPORTED; - } + } else if (memw > 255 || memw < -255) + return SLJIT_ERR_UNSUPPORTED; } if (type & SLJIT_MEM_SUPP) @@ -3292,20 +3566,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile if (is_type1_transfer) inst |= (1 << 25); - if (type & SLJIT_MEM_PRE) - inst |= (1 << 21); - else + if (type & SLJIT_MEM_POST) inst ^= (1 << 24); + else + inst |= (1 << 21); return push_inst(compiler, inst); } inst = EMIT_DATA_TRANSFER(flags, 0, reg, mem & REG_MASK, 0); - if (type & SLJIT_MEM_PRE) - inst |= (1 << 21); - else + if (type & SLJIT_MEM_POST) inst ^= (1 << 24); + else + inst |= (1 << 21); if (is_type1_transfer) { if (memw >= 0) @@ -3336,10 +3610,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil CHECK_ERROR(); CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw)); - if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) - return SLJIT_ERR_UNSUPPORTED; - - if (type & SLJIT_MEM_ALIGNED_32) + if (type & SLJIT_MEM_UNALIGNED_32) return emit_fop_mem(compiler, ((type ^ SLJIT_32) & SLJIT_32) | ((type & SLJIT_MEM_STORE) ? 0 : FPU_LOAD), freg, mem, memw); #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) @@ -3347,23 +3618,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(freg) | RD(TMP_REG2))); if (type & SLJIT_32) - return sljit_emit_mem_unaligned(compiler, SLJIT_MOV | SLJIT_MEM_STORE | (type & SLJIT_MEM_ALIGNED_16), TMP_REG2, mem, memw); + return sljit_emit_mem_unaligned(compiler, SLJIT_MOV | SLJIT_MEM_STORE | (type & SLJIT_MEM_UNALIGNED_16), TMP_REG2, mem, memw); max_offset = 0xfff - 7; - if (type & SLJIT_MEM_ALIGNED_16) + if (type & SLJIT_MEM_UNALIGNED_16) max_offset++; FAIL_IF(update_mem_addr(compiler, &mem, &memw, max_offset)); mem |= SLJIT_MEM; - FAIL_IF(sljit_emit_mem_unaligned(compiler, SLJIT_MOV | SLJIT_MEM_STORE | (type & SLJIT_MEM_ALIGNED_16), TMP_REG2, mem, memw)); + FAIL_IF(sljit_emit_mem_unaligned(compiler, SLJIT_MOV | SLJIT_MEM_STORE | (type & SLJIT_MEM_UNALIGNED_16), TMP_REG2, mem, memw)); FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(freg) | 0x80 | RD(TMP_REG2))); - return sljit_emit_mem_unaligned(compiler, SLJIT_MOV | SLJIT_MEM_STORE | (type & SLJIT_MEM_ALIGNED_16), TMP_REG2, mem, memw + 4); + return sljit_emit_mem_unaligned(compiler, SLJIT_MOV | SLJIT_MEM_STORE | (type & SLJIT_MEM_UNALIGNED_16), TMP_REG2, mem, memw + 4); } max_offset = (type & SLJIT_32) ? 0xfff - 3 : 0xfff - 7; - if (type & SLJIT_MEM_ALIGNED_16) + if (type & SLJIT_MEM_UNALIGNED_16) max_offset++; FAIL_IF(update_mem_addr(compiler, &mem, &memw, max_offset)); @@ -3382,11 +3653,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil mem |= SLJIT_MEM; - FAIL_IF(sljit_emit_mem_unaligned(compiler, SLJIT_MOV | (type & SLJIT_MEM_ALIGNED_16), dst, mem, memw)); + FAIL_IF(sljit_emit_mem_unaligned(compiler, SLJIT_MOV | (type & SLJIT_MEM_UNALIGNED_16), dst, mem, memw)); FAIL_IF(push_inst(compiler, VMOV | VN(freg) | RD(dst))); if (!(type & SLJIT_32)) { - FAIL_IF(sljit_emit_mem_unaligned(compiler, SLJIT_MOV | (type & SLJIT_MEM_ALIGNED_16), dst, mem, memw + 4)); + FAIL_IF(sljit_emit_mem_unaligned(compiler, SLJIT_MOV | (type & SLJIT_MEM_UNALIGNED_16), dst, mem, memw + 4)); FAIL_IF(push_inst(compiler, VMOV | VN(freg) | 0x80 | RD(dst))); } diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeARM_64.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeARM_64.c index 1fbdae572a..c3215742f4 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeARM_64.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeARM_64.c @@ -86,6 +86,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define CSINC 0x9a800400 #define EOR 0xca000000 #define EORI 0xd2000000 +#define EXTR 0x93c00000 #define FABS 0x1e60c000 #define FADD 0x1e602800 #define FCMP 0x1e602000 @@ -93,11 +94,13 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define FCVTZS 0x9e780000 #define FDIV 0x1e601800 #define FMOV 0x1e604000 +#define FMOV_R 0x9e660000 #define FMUL 0x1e600800 #define FNEG 0x1e614000 #define FSUB 0x1e603800 #define LDRI 0xf9400000 #define LDRI_F64 0xfd400000 +#define LDRI_POST 0xf8400400 #define LDP 0xa9400000 #define LDP_F64 0x6d400000 #define LDP_POST 0xa8c00000 @@ -112,7 +115,10 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define ORN 0xaa200000 #define ORR 0xaa000000 #define ORRI 0xb2000000 +#define RBIT 0xdac00000 #define RET 0xd65f0000 +#define REV 0xdac00c00 +#define RORV 0x9ac02c00 #define SBC 0xda000000 #define SBFM 0x93000000 #define SCVTF 0x9e620000 @@ -389,8 +395,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) #endif case SLJIT_HAS_CLZ: + case SLJIT_HAS_CTZ: + case SLJIT_HAS_REV: + case SLJIT_HAS_ROT: case SLJIT_HAS_CMOV: case SLJIT_HAS_PREFETCH: + case SLJIT_HAS_COPY_F32: + case SLJIT_HAS_COPY_F64: return 1; default: @@ -629,6 +640,8 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s switch (op) { case SLJIT_MUL: case SLJIT_CLZ: + case SLJIT_CTZ: + case SLJIT_REV: case SLJIT_ADDC: case SLJIT_SUBC: /* No form with immediate operand (except imm 0, which @@ -637,10 +650,6 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s case SLJIT_MOV: SLJIT_ASSERT(!(flags & SET_FLAGS) && (flags & ARG2_IMM) && arg1 == TMP_REG1); return load_immediate(compiler, dst, imm); - case SLJIT_NOT: - SLJIT_ASSERT(flags & ARG2_IMM); - FAIL_IF(load_immediate(compiler, dst, (flags & INT_OP) ? (~imm & 0xffffffff) : ~imm)); - goto set_flags; case SLJIT_SUB: compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB; if (flags & ARG1_IMM) @@ -687,8 +696,13 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s break; CHECK_FLAGS(3 << 29); return push_inst(compiler, (ANDI ^ inv_bits) | RD(dst) | RN(reg) | inst_bits); - case SLJIT_OR: case SLJIT_XOR: + if (imm == -1) { + FAIL_IF(push_inst(compiler, (ORN ^ inv_bits) | RD(dst) | RN(TMP_ZERO) | RM(reg))); + goto set_flags; + } + /* fallthrough */ + case SLJIT_OR: inst_bits = logical_imm(imm, LOGICAL_IMM_CHECK | ((flags & INT_OP) ? 16 : 32)); if (!inst_bits) break; @@ -699,36 +713,50 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s FAIL_IF(push_inst(compiler, (inst_bits ^ inv_bits) | RD(dst) | RN(reg))); goto set_flags; case SLJIT_SHL: + case SLJIT_MSHL: if (flags & ARG1_IMM) break; + if (flags & INT_OP) { imm &= 0x1f; - FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) - | (((sljit_ins)-imm & 0x1f) << 16) | ((31 - (sljit_ins)imm) << 10))); - } - else { + inst_bits = (((sljit_ins)-imm & 0x1f) << 16) | ((31 - (sljit_ins)imm) << 10); + } else { imm &= 0x3f; - FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | (1 << 22) - | (((sljit_ins)-imm & 0x3f) << 16) | ((63 - (sljit_ins)imm) << 10))); + inst_bits = ((sljit_ins)1 << 22) | (((sljit_ins)-imm & 0x3f) << 16) | ((63 - (sljit_ins)imm) << 10); } + + FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | inst_bits)); goto set_flags; case SLJIT_LSHR: + case SLJIT_MLSHR: case SLJIT_ASHR: + case SLJIT_MASHR: if (flags & ARG1_IMM) break; - if (op == SLJIT_ASHR) + + if (op >= SLJIT_ASHR) inv_bits |= 1 << 30; + if (flags & INT_OP) { imm &= 0x1f; - FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) - | ((sljit_ins)imm << 16) | (31 << 10))); - } - else { + inst_bits = ((sljit_ins)imm << 16) | (31 << 10); + } else { imm &= 0x3f; - FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) - | (1 << 22) | ((sljit_ins)imm << 16) | (63 << 10))); + inst_bits = ((sljit_ins)1 << 22) | ((sljit_ins)imm << 16) | (63 << 10); } + + FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | inst_bits)); goto set_flags; + case SLJIT_ROTL: + case SLJIT_ROTR: + if (flags & ARG1_IMM) + break; + + if (op == SLJIT_ROTL) + imm = -imm; + + imm &= (flags & INT_OP) ? 0x1f : 0x3f; + return push_inst(compiler, (EXTR ^ (inv_bits | (inv_bits >> 9))) | RD(dst) | RN(arg1) | RM(arg1) | ((sljit_ins)imm << 10)); default: SLJIT_UNREACHABLE(); break; @@ -787,13 +815,17 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s case SLJIT_MOV_S32: SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); return push_inst(compiler, SBFM | (1 << 22) | RD(dst) | RN(arg2) | (31 << 10)); - case SLJIT_NOT: - SLJIT_ASSERT(arg1 == TMP_REG1); - FAIL_IF(push_inst(compiler, (ORN ^ inv_bits) | RD(dst) | RN(TMP_ZERO) | RM(arg2))); - break; /* Set flags. */ case SLJIT_CLZ: SLJIT_ASSERT(arg1 == TMP_REG1); return push_inst(compiler, (CLZ ^ inv_bits) | RD(dst) | RN(arg2)); + case SLJIT_CTZ: + SLJIT_ASSERT(arg1 == TMP_REG1); + FAIL_IF(push_inst(compiler, (RBIT ^ inv_bits) | RD(dst) | RN(arg2))); + return push_inst(compiler, (CLZ ^ inv_bits) | RD(dst) | RN(dst)); + case SLJIT_REV: + SLJIT_ASSERT(arg1 == TMP_REG1); + inv_bits |= inv_bits >> 21; + return push_inst(compiler, (REV ^ inv_bits) | RD(dst) | RN(arg2)); case SLJIT_ADD: compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD; CHECK_FLAGS(1 << 29); @@ -832,14 +864,23 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s FAIL_IF(push_inst(compiler, (EOR ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2))); break; /* Set flags. */ case SLJIT_SHL: + case SLJIT_MSHL: FAIL_IF(push_inst(compiler, (LSLV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2))); break; /* Set flags. */ case SLJIT_LSHR: + case SLJIT_MLSHR: FAIL_IF(push_inst(compiler, (LSRV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2))); break; /* Set flags. */ case SLJIT_ASHR: + case SLJIT_MASHR: FAIL_IF(push_inst(compiler, (ASRV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2))); break; /* Set flags. */ + case SLJIT_ROTL: + FAIL_IF(push_inst(compiler, (SUB ^ inv_bits) | RD(TMP_REG2) | RN(TMP_ZERO) | RM(arg2))); + arg2 = TMP_REG2; + /* fallthrough */ + case SLJIT_ROTR: + return push_inst(compiler, (RORV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)); default: SLJIT_UNREACHABLE(); return SLJIT_SUCCESS; @@ -911,9 +952,19 @@ static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, s } } - if (argw <= 255 && argw >= -256) + if (argw <= 0xff && argw >= -0x100) return push_inst(compiler, STURBI | type | RT(reg) | RN(arg) | (((sljit_ins)argw & 0x1ff) << 12)); + if (argw >= 0) { + if (argw <= 0xfff0ff && ((argw + 0x100) & 0xfff) <= 0x1ff) { + FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(tmp_reg) | RN(arg) | (((sljit_ins)argw >> 12) << 10))); + return push_inst(compiler, STURBI | type | RT(reg) | RN(tmp_reg) | (((sljit_ins)argw & 0x1ff) << 12)); + } + } else if (argw >= -0xfff100 && ((-argw + 0xff) & 0xfff) <= 0x1ff) { + FAIL_IF(push_inst(compiler, SUBI | (1 << 22) | RD(tmp_reg) | RN(arg) | (((sljit_ins)-argw >> 12) << 10))); + return push_inst(compiler, STURBI | type | RT(reg) | RN(tmp_reg) | (((sljit_ins)argw & 0x1ff) << 12)); + } + FAIL_IF(load_immediate(compiler, tmp_reg, argw)); return push_inst(compiler, STRB | type | RT(reg) | RN(arg) | RM(tmp_reg)); @@ -936,7 +987,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 2); - saved_regs_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, SSIZE_OF(f64)); + saved_regs_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64); local_size = (local_size + saved_regs_size + 0xf) & ~0xf; compiler->local_size = local_size; @@ -1109,25 +1160,33 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 2); - saved_regs_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, SSIZE_OF(f64)); + saved_regs_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64); compiler->local_size = (local_size + saved_regs_size + 0xf) & ~0xf; return SLJIT_SUCCESS; } -static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) +static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to) { sljit_s32 local_size, prev, fprev, i, tmp; sljit_ins offs; local_size = compiler->local_size; - if (local_size > 512 && local_size <= 512 + 496) { - FAIL_IF(push_inst(compiler, LDP_POST | RT(TMP_FP) | RT2(TMP_LR) - | RN(SLJIT_SP) | ((sljit_ins)(local_size - 512) << (15 - 3)))); - local_size = 512; - } else - FAIL_IF(push_inst(compiler, LDP | RT(TMP_FP) | RT2(TMP_LR) | RN(SLJIT_SP))); + if (!is_return_to) { + if (local_size > 512 && local_size <= 512 + 496) { + FAIL_IF(push_inst(compiler, LDP_POST | RT(TMP_FP) | RT2(TMP_LR) + | RN(SLJIT_SP) | ((sljit_ins)(local_size - 512) << (15 - 3)))); + local_size = 512; + } else + FAIL_IF(push_inst(compiler, LDP | RT(TMP_FP) | RT2(TMP_LR) | RN(SLJIT_SP))); + } else { + if (local_size > 512 && local_size <= 512 + 248) { + FAIL_IF(push_inst(compiler, LDRI_POST | RT(TMP_FP) | RN(SLJIT_SP) | ((sljit_ins)(local_size - 512) << 12))); + local_size = 512; + } else + FAIL_IF(push_inst(compiler, LDRI | RT(TMP_FP) | RN(SLJIT_SP) | 0)); + } if (local_size > 512) { local_size -= 512; @@ -1203,11 +1262,34 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler CHECK_ERROR(); CHECK(check_sljit_emit_return_void(compiler)); - FAIL_IF(emit_stack_frame_release(compiler)); + FAIL_IF(emit_stack_frame_release(compiler, 0)); return push_inst(compiler, RET | RN(TMP_LR)); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_return_to(compiler, src, srcw)); + + if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); + FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1)); + src = TMP_REG1; + srcw = 0; + } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { + FAIL_IF(push_inst(compiler, ORR | RD(TMP_REG1) | RN(TMP_ZERO) | RM(src))); + src = TMP_REG1; + srcw = 0; + } + + FAIL_IF(emit_stack_frame_release(compiler, 1)); + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw); +} + /* --------------------------------------------------------------------- */ /* Operators */ /* --------------------------------------------------------------------- */ @@ -1404,6 +1486,75 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst_reg, + sljit_s32 src1_reg, + sljit_s32 src2_reg, + sljit_s32 src3, sljit_sw src3w) +{ + sljit_ins inv_bits, imm; + sljit_s32 is_left; + sljit_sw mask; + + CHECK_ERROR(); + CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w)); + + is_left = (GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_MSHL); + + if (src1_reg == src2_reg) { + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_op2(compiler, (is_left ? SLJIT_ROTL : SLJIT_ROTR) | (op & SLJIT_32), dst_reg, 0, src1_reg, 0, src3, src3w); + } + + ADJUST_LOCAL_OFFSET(src3, src3w); + + inv_bits = (op & SLJIT_32) ? W_OP : 0; + + if (src3 & SLJIT_IMM) { + mask = inv_bits ? 0x1f : 0x3f; + src3w &= mask; + + if (src3w == 0) + return SLJIT_SUCCESS; + + if (is_left) + src3w = (src3w ^ mask) + 1; + + return push_inst(compiler, (EXTR ^ (inv_bits | (inv_bits >> 9))) | RD(dst_reg) + | RN(is_left ? src1_reg : src2_reg) | RM(is_left ? src2_reg : src1_reg) | ((sljit_ins)src3w << 10)); + } + + if (src3 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, inv_bits ? INT_SIZE : WORD_SIZE, TMP_REG2, src3, src3w, TMP_REG2)); + src3 = TMP_REG2; + } else if (dst_reg == src3) { + FAIL_IF(push_inst(compiler, ORR | RD(TMP_REG2) | RN(TMP_ZERO) | RM(src3))); + src3 = TMP_REG2; + } + + FAIL_IF(push_inst(compiler, ((is_left ? LSLV : LSRV) ^ inv_bits) | RD(dst_reg) | RN(src1_reg) | RM(src3))); + + if (!(op & SLJIT_SHIFT_INTO_NON_ZERO)) { + /* Shift left/right by 1. */ + if (is_left) + imm = (sljit_ins)(inv_bits ? ((1 << 16) | (31 << 10)) : ((1 << 16) | (63 << 10) | (1 << 22))); + else + imm = (sljit_ins)(inv_bits ? ((31 << 16) | (30 << 10)) : ((63 << 16) | (62 << 10) | (1 << 22))); + + FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(TMP_REG1) | RN(src2_reg) | imm)); + + /* Set imm to mask. */ + imm = (sljit_ins)(inv_bits ? (4 << 10) : ((5 << 10) | (1 << 22))); + FAIL_IF(push_inst(compiler, (EORI ^ inv_bits) | RD(TMP_REG2) | RN(src3) | imm)); + + src2_reg = TMP_REG1; + } else + FAIL_IF(push_inst(compiler, (SUB ^ inv_bits) | RD(TMP_REG2) | RN(TMP_ZERO) | RM(src3))); + + FAIL_IF(push_inst(compiler, ((is_left ? LSRV : LSLV) ^ inv_bits) | RD(TMP_REG1) | RN(src2_reg) | RM(TMP_REG2))); + return push_inst(compiler, (ORR ^ inv_bits) | RD(dst_reg) | RN(dst_reg) | RM(TMP_REG1)); +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { @@ -1444,6 +1595,32 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *comp return SLJIT_SUCCESS; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw) +{ + sljit_s32 dst_r = TMP_LR; + + CHECK_ERROR(); + CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw)); + ADJUST_LOCAL_OFFSET(dst, dstw); + + switch (op) { + case SLJIT_FAST_ENTER: + if (FAST_IS_REG(dst)) + return push_inst(compiler, ORR | RD(dst) | RN(TMP_ZERO) | RM(TMP_LR)); + break; + case SLJIT_GET_RETURN_ADDRESS: + dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; + FAIL_IF(emit_op_mem(compiler, WORD_SIZE, dst_r, SLJIT_MEM1(SLJIT_SP), 0x8, TMP_REG2)); + break; + } + + if (dst & SLJIT_MEM) + return emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2); + + return SLJIT_SUCCESS; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_register_index(reg)); @@ -1678,21 +1855,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil return emit_fop_mem(compiler, mem_flags | STORE, TMP_FREG1, dst, dstw); } -/* --------------------------------------------------------------------- */ -/* Other instructions */ -/* --------------------------------------------------------------------- */ - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 freg, sljit_s32 reg) { + sljit_ins inst; + CHECK_ERROR(); - CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); - ADJUST_LOCAL_OFFSET(dst, dstw); + CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg)); - if (FAST_IS_REG(dst)) - return push_inst(compiler, ORR | RD(dst) | RN(TMP_ZERO) | RM(TMP_LR)); + if (GET_OPCODE(op) == SLJIT_COPY_TO_F64) + inst = FMOV_R | RN(reg) | VD(freg) | (sljit_ins)1 << 16; + else + inst = FMOV_R | VN(freg) | RD(reg); - /* Memory. */ - return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_LR, dst, dstw, TMP_REG1); + if (op & SLJIT_32) + inst ^= ((sljit_ins)1 << 31) | ((sljit_ins)1 << 22); + + return push_inst(compiler, inst); } /* --------------------------------------------------------------------- */ @@ -1836,7 +2015,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); if (type & SLJIT_CALL_RETURN) { - PTR_FAIL_IF(emit_stack_frame_release(compiler)); + PTR_FAIL_IF(emit_stack_frame_release(compiler, 0)); type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP); } @@ -1885,10 +2064,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi CHECK_ERROR(); CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); - ADJUST_LOCAL_OFFSET(src, srcw); if (!(src & SLJIT_IMM)) { if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1)); src = TMP_REG1; } @@ -1913,20 +2092,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi SLJIT_UNUSED_ARG(arg_types); CHECK_ERROR(); CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); - ADJUST_LOCAL_OFFSET(src, srcw); if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1)); src = TMP_REG1; } if (type & SLJIT_CALL_RETURN) { - if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) { + if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { FAIL_IF(push_inst(compiler, ORR | RD(TMP_REG1) | RN(TMP_ZERO) | RM(src))); src = TMP_REG1; } - FAIL_IF(emit_stack_frame_release(compiler)); + FAIL_IF(emit_stack_frame_release(compiler, 0)); type = SLJIT_JUMP; } @@ -1986,22 +2165,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil sljit_s32 dst_reg, sljit_s32 src, sljit_sw srcw) { - sljit_ins inv_bits = (dst_reg & SLJIT_32) ? W_OP : 0; + sljit_ins inv_bits = (type & SLJIT_32) ? W_OP : 0; sljit_ins cc; CHECK_ERROR(); CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); if (SLJIT_UNLIKELY(src & SLJIT_IMM)) { - if (dst_reg & SLJIT_32) + if (type & SLJIT_32) srcw = (sljit_s32)srcw; FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); src = TMP_REG1; srcw = 0; } - cc = get_cc(compiler, type); - dst_reg &= ~SLJIT_32; + cc = get_cc(compiler, type & ~SLJIT_32); return push_inst(compiler, (CSEL ^ inv_bits) | (cc << 12) | RD(dst_reg) | RN(dst_reg) | RM(src)); } @@ -2010,59 +2188,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile sljit_s32 reg, sljit_s32 mem, sljit_sw memw) { - sljit_u32 sign = 0, inst; + sljit_u32 inst; CHECK_ERROR(); CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); - if (!(reg & REG_PAIR_MASK)) { - if (type & SLJIT_MEM_UNALIGNED) - return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw); - - if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -256)) - return SLJIT_ERR_UNSUPPORTED; - - if (type & SLJIT_MEM_SUPP) - return SLJIT_SUCCESS; - - switch (type & 0xff) { - case SLJIT_MOV: - case SLJIT_MOV_P: - inst = STURBI | (MEM_SIZE_SHIFT(WORD_SIZE) << 30) | 0x400; - break; - case SLJIT_MOV_S8: - sign = 1; - /* fallthrough */ - case SLJIT_MOV_U8: - inst = STURBI | (MEM_SIZE_SHIFT(BYTE_SIZE) << 30) | 0x400; - break; - case SLJIT_MOV_S16: - sign = 1; - /* fallthrough */ - case SLJIT_MOV_U16: - inst = STURBI | (MEM_SIZE_SHIFT(HALF_SIZE) << 30) | 0x400; - break; - case SLJIT_MOV_S32: - sign = 1; - /* fallthrough */ - case SLJIT_MOV_U32: - case SLJIT_MOV32: - inst = STURBI | (MEM_SIZE_SHIFT(INT_SIZE) << 30) | 0x400; - break; - default: - SLJIT_UNREACHABLE(); - inst = STURBI | (MEM_SIZE_SHIFT(WORD_SIZE) << 30) | 0x400; - break; - } - - if (!(type & SLJIT_MEM_STORE)) - inst |= sign ? 0x00800000 : 0x00400000; - - if (type & SLJIT_MEM_PRE) - inst |= 0x800; - - return push_inst(compiler, inst | RT(reg) | RN(mem & REG_MASK) | (sljit_ins)((memw & 0x1ff) << 12)); - } + if (!(reg & REG_PAIR_MASK)) + return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw); ADJUST_LOCAL_OFFSET(mem, memw); @@ -2123,17 +2255,68 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile return push_inst(compiler, ((type & SLJIT_MEM_STORE) ? STP : LDP) | RT(REG_PAIR_FIRST(reg)) | RT2(REG_PAIR_SECOND(reg)) | RN(mem & REG_MASK) | (sljit_ins)((memw & 0x3f8) << 12)); } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 reg, + sljit_s32 mem, sljit_sw memw) +{ + sljit_u32 sign = 0, inst; + + CHECK_ERROR(); + CHECK(check_sljit_emit_mem_update(compiler, type, reg, mem, memw)); + + if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -256)) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_MEM_SUPP) + return SLJIT_SUCCESS; + + switch (type & 0xff) { + case SLJIT_MOV: + case SLJIT_MOV_P: + inst = STURBI | (MEM_SIZE_SHIFT(WORD_SIZE) << 30) | 0x400; + break; + case SLJIT_MOV_S8: + sign = 1; + /* fallthrough */ + case SLJIT_MOV_U8: + inst = STURBI | (MEM_SIZE_SHIFT(BYTE_SIZE) << 30) | 0x400; + break; + case SLJIT_MOV_S16: + sign = 1; + /* fallthrough */ + case SLJIT_MOV_U16: + inst = STURBI | (MEM_SIZE_SHIFT(HALF_SIZE) << 30) | 0x400; + break; + case SLJIT_MOV_S32: + sign = 1; + /* fallthrough */ + case SLJIT_MOV_U32: + case SLJIT_MOV32: + inst = STURBI | (MEM_SIZE_SHIFT(INT_SIZE) << 30) | 0x400; + break; + default: + SLJIT_UNREACHABLE(); + inst = STURBI | (MEM_SIZE_SHIFT(WORD_SIZE) << 30) | 0x400; + break; + } + + if (!(type & SLJIT_MEM_STORE)) + inst |= sign ? 0x00800000 : 0x00400000; + + if (!(type & SLJIT_MEM_POST)) + inst |= 0x800; + + return push_inst(compiler, inst | RT(reg) | RN(mem & REG_MASK) | (sljit_ins)((memw & 0x1ff) << 12)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 freg, sljit_s32 mem, sljit_sw memw) { sljit_u32 inst; CHECK_ERROR(); - CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw)); - - if (type & SLJIT_MEM_UNALIGNED) - return sljit_emit_fmem_unaligned(compiler, type, freg, mem, memw); + CHECK(check_sljit_emit_fmem_update(compiler, type, freg, mem, memw)); if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -256)) return SLJIT_ERR_UNSUPPORTED; @@ -2149,7 +2332,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil if (!(type & SLJIT_MEM_STORE)) inst |= 0x00400000; - if (type & SLJIT_MEM_PRE) + if (!(type & SLJIT_MEM_POST)) inst |= 0x800; return push_inst(compiler, inst | VT(freg) | RN(mem & REG_MASK) | (sljit_ins)((memw & 0x1ff) << 12)); diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeARM_T2_32.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeARM_T2_32.c index 55c810bb78..73dd7f99d5 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeARM_T2_32.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeARM_T2_32.c @@ -160,6 +160,12 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define POP_W 0xe8bd0000 #define PUSH 0xb400 #define PUSH_W 0xe92d0000 +#define REV 0xba00 +#define REV_W 0xfa90f080 +#define RBIT 0xfa90f0a0 +#define RORS 0x41c0 +#define ROR_W 0xfa60f000 +#define ROR_WI 0xea4f0030 #define RSB_WI 0xf1c00000 #define RSBSI 0x4240 #define SBCI 0xf1600000 @@ -492,8 +498,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) #endif case SLJIT_HAS_CLZ: + case SLJIT_HAS_CTZ: + case SLJIT_HAS_REV: + case SLJIT_HAS_ROT: case SLJIT_HAS_CMOV: case SLJIT_HAS_PREFETCH: + case SLJIT_HAS_COPY_F32: + case SLJIT_HAS_COPY_F64: return 1; default: @@ -593,7 +604,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s arg1 must be register, imm arg2 must be register, imm */ sljit_s32 reg; - sljit_uw imm, nimm; + sljit_uw imm, imm2; if (SLJIT_UNLIKELY((flags & (ARG1_IMM | ARG2_IMM)) == (ARG1_IMM | ARG2_IMM))) { /* Both are immediates, no temporaries are used. */ @@ -608,45 +619,41 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s switch (flags & 0xffff) { case SLJIT_CLZ: + case SLJIT_CTZ: + case SLJIT_REV: case SLJIT_MUL: /* No form with immediate operand. */ break; case SLJIT_MOV: SLJIT_ASSERT(!(flags & SET_FLAGS) && (flags & ARG2_IMM) && arg1 == TMP_REG2); return load_immediate(compiler, dst, imm); - case SLJIT_NOT: - if (!(flags & SET_FLAGS)) - return load_immediate(compiler, dst, ~imm); - /* Since the flags should be set, we just fallback to the register mode. - Although some clever things could be done here, "NOT IMM" does not worth the efforts. */ - break; case SLJIT_ADD: compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD; - nimm = NEGATE(imm); + imm2 = NEGATE(imm); if (IS_2_LO_REGS(reg, dst)) { if (imm <= 0x7) return push_inst16(compiler, ADDSI3 | IMM3(imm) | RD3(dst) | RN3(reg)); - if (nimm <= 0x7) - return push_inst16(compiler, SUBSI3 | IMM3(nimm) | RD3(dst) | RN3(reg)); + if (imm2 <= 0x7) + return push_inst16(compiler, SUBSI3 | IMM3(imm2) | RD3(dst) | RN3(reg)); if (reg == dst) { if (imm <= 0xff) return push_inst16(compiler, ADDSI8 | IMM8(imm) | RDN3(dst)); - if (nimm <= 0xff) - return push_inst16(compiler, SUBSI8 | IMM8(nimm) | RDN3(dst)); + if (imm2 <= 0xff) + return push_inst16(compiler, SUBSI8 | IMM8(imm2) | RDN3(dst)); } } if (!(flags & SET_FLAGS)) { if (imm <= 0xfff) return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(imm)); - if (nimm <= 0xfff) - return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(nimm)); + if (imm2 <= 0xfff) + return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(imm2)); } - nimm = get_imm(imm); - if (nimm != INVALID_IMM) - return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm); - nimm = get_imm(NEGATE(imm)); - if (nimm != INVALID_IMM) - return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm); + imm2 = get_imm(imm); + if (imm2 != INVALID_IMM) + return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm2); + imm = get_imm(NEGATE(imm)); + if (imm != INVALID_IMM) + return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); break; case SLJIT_ADDC: compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD; @@ -667,39 +674,39 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s if (flags & UNUSED_RETURN) { if (imm <= 0xff && reg_map[reg] <= 7) return push_inst16(compiler, CMPI | IMM8(imm) | RDN3(reg)); - nimm = get_imm(imm); - if (nimm != INVALID_IMM) - return push_inst32(compiler, CMPI_W | RN4(reg) | nimm); - nimm = get_imm(NEGATE(imm)); - if (nimm != INVALID_IMM) - return push_inst32(compiler, CMNI_W | RN4(reg) | nimm); + imm2 = get_imm(imm); + if (imm2 != INVALID_IMM) + return push_inst32(compiler, CMPI_W | RN4(reg) | imm2); + imm = get_imm(NEGATE(imm)); + if (imm != INVALID_IMM) + return push_inst32(compiler, CMNI_W | RN4(reg) | imm); break; } - nimm = NEGATE(imm); + imm2 = NEGATE(imm); if (IS_2_LO_REGS(reg, dst)) { if (imm <= 0x7) return push_inst16(compiler, SUBSI3 | IMM3(imm) | RD3(dst) | RN3(reg)); - if (nimm <= 0x7) - return push_inst16(compiler, ADDSI3 | IMM3(nimm) | RD3(dst) | RN3(reg)); + if (imm2 <= 0x7) + return push_inst16(compiler, ADDSI3 | IMM3(imm2) | RD3(dst) | RN3(reg)); if (reg == dst) { if (imm <= 0xff) return push_inst16(compiler, SUBSI8 | IMM8(imm) | RDN3(dst)); - if (nimm <= 0xff) - return push_inst16(compiler, ADDSI8 | IMM8(nimm) | RDN3(dst)); + if (imm2 <= 0xff) + return push_inst16(compiler, ADDSI8 | IMM8(imm2) | RDN3(dst)); } } if (!(flags & SET_FLAGS)) { if (imm <= 0xfff) return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(imm)); - if (nimm <= 0xfff) - return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(nimm)); + if (imm2 <= 0xfff) + return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(imm2)); } - nimm = get_imm(imm); - if (nimm != INVALID_IMM) - return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm); - nimm = get_imm(NEGATE(imm)); - if (nimm != INVALID_IMM) - return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm); + imm2 = get_imm(imm); + if (imm2 != INVALID_IMM) + return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm2); + imm = get_imm(NEGATE(imm)); + if (imm != INVALID_IMM) + return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); break; case SLJIT_SUBC: compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB; @@ -710,32 +717,43 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s return push_inst32(compiler, SBCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); break; case SLJIT_AND: - nimm = get_imm(imm); - if (nimm != INVALID_IMM) - return push_inst32(compiler, ((flags & UNUSED_RETURN) ? TSTI : ANDI) | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm); + imm2 = get_imm(imm); + if (imm2 != INVALID_IMM) + return push_inst32(compiler, ((flags & UNUSED_RETURN) ? TSTI : ANDI) | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm2); imm = get_imm(~imm); if (imm != INVALID_IMM) return push_inst32(compiler, BICI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); break; case SLJIT_OR: - nimm = get_imm(imm); - if (nimm != INVALID_IMM) - return push_inst32(compiler, ORRI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm); + imm2 = get_imm(imm); + if (imm2 != INVALID_IMM) + return push_inst32(compiler, ORRI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm2); imm = get_imm(~imm); if (imm != INVALID_IMM) return push_inst32(compiler, ORNI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); break; case SLJIT_XOR: + if (imm == (sljit_uw)-1) { + if (IS_2_LO_REGS(dst, reg)) + return push_inst16(compiler, MVNS | RD3(dst) | RN3(reg)); + return push_inst32(compiler, MVN_W | (flags & SET_FLAGS) | RD4(dst) | RM4(reg)); + } imm = get_imm(imm); if (imm != INVALID_IMM) return push_inst32(compiler, EORI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); break; case SLJIT_SHL: + case SLJIT_MSHL: case SLJIT_LSHR: + case SLJIT_MLSHR: case SLJIT_ASHR: + case SLJIT_MASHR: + case SLJIT_ROTL: + case SLJIT_ROTR: if (flags & ARG1_IMM) break; imm &= 0x1f; + if (imm == 0) { if (!(flags & SET_FLAGS)) return push_inst16(compiler, MOV | SET_REGS44(dst, reg)); @@ -743,19 +761,28 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg)); return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg)); } + switch (flags & 0xffff) { case SLJIT_SHL: + case SLJIT_MSHL: if (IS_2_LO_REGS(dst, reg)) return push_inst16(compiler, LSLSI | RD3(dst) | RN3(reg) | (imm << 6)); return push_inst32(compiler, LSL_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm)); case SLJIT_LSHR: + case SLJIT_MLSHR: if (IS_2_LO_REGS(dst, reg)) return push_inst16(compiler, LSRSI | RD3(dst) | RN3(reg) | (imm << 6)); return push_inst32(compiler, LSR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm)); - default: /* SLJIT_ASHR */ + case SLJIT_ASHR: + case SLJIT_MASHR: if (IS_2_LO_REGS(dst, reg)) return push_inst16(compiler, ASRSI | RD3(dst) | RN3(reg) | (imm << 6)); return push_inst32(compiler, ASR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm)); + case SLJIT_ROTL: + imm = (imm ^ 0x1f) + 1; + /* fallthrough */ + default: /* SLJIT_ROTR */ + return push_inst32(compiler, ROR_WI | RD4(dst) | RM4(reg) | IMM5(imm)); } default: SLJIT_UNREACHABLE(); @@ -807,15 +834,17 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s if (IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, SXTH | RD3(dst) | RN3(arg2)); return push_inst32(compiler, SXTH_W | RD4(dst) | RM4(arg2)); - case SLJIT_NOT: - SLJIT_ASSERT(arg1 == TMP_REG2); - if (IS_2_LO_REGS(dst, arg2)) - return push_inst16(compiler, MVNS | RD3(dst) | RN3(arg2)); - return push_inst32(compiler, MVN_W | (flags & SET_FLAGS) | RD4(dst) | RM4(arg2)); case SLJIT_CLZ: SLJIT_ASSERT(arg1 == TMP_REG2); - FAIL_IF(push_inst32(compiler, CLZ | RN4(arg2) | RD4(dst) | RM4(arg2))); - return SLJIT_SUCCESS; + return push_inst32(compiler, CLZ | RN4(arg2) | RD4(dst) | RM4(arg2)); + case SLJIT_CTZ: + SLJIT_ASSERT(arg1 == TMP_REG2); + FAIL_IF(push_inst32(compiler, RBIT | RN4(arg2) | RD4(dst) | RM4(arg2))); + return push_inst32(compiler, CLZ | RN4(dst) | RD4(dst) | RM4(dst)); + case SLJIT_REV: + if (IS_2_LO_REGS(dst, arg2)) + return push_inst16(compiler, REV | RD3(dst) | RN3(arg2)); + return push_inst32(compiler, REV_W | RN4(arg2) | RD4(dst) | RM4(arg2)); case SLJIT_ADD: compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD; if (IS_3_LO_REGS(dst, arg1, arg2)) @@ -865,18 +894,38 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, EORS | RD3(dst) | RN3(arg2)); return push_inst32(compiler, EOR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); + case SLJIT_MSHL: + FAIL_IF(push_inst32(compiler, ANDI | RD4(TMP_REG2) | RN4(arg2) | 0x1f)); + arg2 = TMP_REG2; + /* fallthrough */ case SLJIT_SHL: if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, LSLS | RD3(dst) | RN3(arg2)); return push_inst32(compiler, LSL_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); + case SLJIT_MLSHR: + FAIL_IF(push_inst32(compiler, ANDI | RD4(TMP_REG2) | RN4(arg2) | 0x1f)); + arg2 = TMP_REG2; + /* fallthrough */ case SLJIT_LSHR: if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, LSRS | RD3(dst) | RN3(arg2)); return push_inst32(compiler, LSR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); + case SLJIT_MASHR: + FAIL_IF(push_inst32(compiler, ANDI | RD4(TMP_REG2) | RN4(arg2) | 0x1f)); + arg2 = TMP_REG2; + /* fallthrough */ case SLJIT_ASHR: if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, ASRS | RD3(dst) | RN3(arg2)); return push_inst32(compiler, ASR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); + case SLJIT_ROTL: + FAIL_IF(push_inst32(compiler, RSB_WI | RD4(TMP_REG2) | RN4(arg2) | 0)); + arg2 = TMP_REG2; + /* fallthrough */ + case SLJIT_ROTR: + if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2)) + return push_inst16(compiler, RORS | RD3(dst) | RN3(arg2)); + return push_inst32(compiler, ROR_W | RD4(dst) | RN4(arg1) | RM4(arg2)); } SLJIT_UNREACHABLE(); @@ -1311,6 +1360,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1); + /* Doubles are saved, so alignment is unaffected. */ if ((size & SSIZE_OF(sw)) != 0 && (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG)) size += SSIZE_OF(sw); @@ -1341,9 +1391,9 @@ static sljit_s32 emit_add_sp(struct sljit_compiler *compiler, sljit_uw imm) static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size) { sljit_s32 local_size, fscratches, fsaveds, i, tmp; - sljit_s32 saveds_restore_start = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); + sljit_s32 restored_reg = 0; sljit_s32 lr_dst = TMP_PC; - sljit_uw reg_list; + sljit_uw reg_list = 0; SLJIT_ASSERT(reg_map[TMP_REG2] == 14 && frame_size <= 128); @@ -1370,49 +1420,88 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit if (frame_size < 0) { lr_dst = TMP_REG2; frame_size = 0; - } else if (frame_size > 0) + } else if (frame_size > 0) { + SLJIT_ASSERT(frame_size == 1 || (frame_size & 0x7) == 0); lr_dst = 0; + frame_size &= ~0x7; + } - reg_list = 0; tmp = SLJIT_S0 - compiler->saveds; - if (saveds_restore_start != tmp) { - for (i = saveds_restore_start; i > tmp; i--) + i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); + if (tmp < i) { + restored_reg = i; + do { reg_list |= (sljit_uw)1 << reg_map[i]; - } else - saveds_restore_start = 0; + } while (--i > tmp); + } - for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) - reg_list |= (sljit_uw)1 << reg_map[i]; + i = compiler->scratches; + if (i >= SLJIT_FIRST_SAVED_REG) { + restored_reg = i; + do { + reg_list |= (sljit_uw)1 << reg_map[i]; + } while (--i >= SLJIT_FIRST_SAVED_REG); + } + + if (lr_dst == TMP_REG2 && reg_list == 0) { + reg_list |= (sljit_uw)1 << reg_map[TMP_REG2]; + restored_reg = TMP_REG2; + lr_dst = 0; + } if (lr_dst == 0 && (reg_list & (reg_list - 1)) == 0) { /* The local_size does not include the saved registers. */ + tmp = 0; + if (reg_list != 0) { + tmp = 2; + if (local_size <= 0xfff) { + if (local_size == 0) { + SLJIT_ASSERT(restored_reg != TMP_REG2); + if (frame_size == 0) + return push_inst32(compiler, LDRI | RT4(restored_reg) | RN4(SLJIT_SP) | 0x308); + if (frame_size > 2 * SSIZE_OF(sw)) + return push_inst32(compiler, LDRI | RT4(restored_reg) | RN4(SLJIT_SP) | 0x100 | (sljit_ins)(frame_size - (2 * SSIZE_OF(sw)))); + } + + if (reg_map[restored_reg] <= 7 && local_size <= 0x3fc) + FAIL_IF(push_inst16(compiler, STR_SP | 0x800 | RDN3(restored_reg) | (sljit_ins)(local_size >> 2))); + else + FAIL_IF(push_inst32(compiler, LDR | RT4(restored_reg) | RN4(SLJIT_SP) | (sljit_ins)local_size)); + tmp = 1; + } else if (frame_size == 0) { + frame_size = (restored_reg == TMP_REG2) ? SSIZE_OF(sw) : 2 * SSIZE_OF(sw); + tmp = 3; + } + + /* Place for the saved register. */ + if (restored_reg != TMP_REG2) + local_size += SSIZE_OF(sw); + } + + /* Place for the lr register. */ local_size += SSIZE_OF(sw); - if (reg_list != 0) - local_size += SSIZE_OF(sw); - if (frame_size > local_size) - FAIL_IF(push_inst16(compiler, SUB_SP_I | ((sljit_uw)(frame_size - local_size) >> 2))); + FAIL_IF(push_inst16(compiler, SUB_SP_I | ((sljit_ins)(frame_size - local_size) >> 2))); else if (frame_size < local_size) FAIL_IF(emit_add_sp(compiler, (sljit_uw)(local_size - frame_size))); - if (reg_list == 0) + if (tmp <= 1) return SLJIT_SUCCESS; - if (saveds_restore_start != 0) { - SLJIT_ASSERT(reg_list == ((sljit_uw)1 << reg_map[saveds_restore_start])); - lr_dst = saveds_restore_start; - } else { - SLJIT_ASSERT(reg_list == ((sljit_uw)1 << reg_map[SLJIT_FIRST_SAVED_REG])); - lr_dst = SLJIT_FIRST_SAVED_REG; + if (tmp == 2) { + frame_size -= SSIZE_OF(sw); + if (restored_reg != TMP_REG2) + frame_size -= SSIZE_OF(sw); + + if (reg_map[restored_reg] <= 7) + return push_inst16(compiler, STR_SP | 0x800 | RDN3(restored_reg) | (sljit_ins)(frame_size >> 2)); + + return push_inst32(compiler, LDR | RT4(restored_reg) | RN4(SLJIT_SP) | (sljit_ins)frame_size); } - frame_size -= 2 * SSIZE_OF(sw); - - if (reg_map[lr_dst] <= 7) - return push_inst16(compiler, STR_SP | 0x800 | RDN3(lr_dst) | (sljit_uw)(frame_size >> 2)); - - return push_inst32(compiler, LDR | RT4(lr_dst) | RN4(SLJIT_SP) | (sljit_uw)frame_size); + tmp = (restored_reg == TMP_REG2) ? 0x304 : 0x308; + return push_inst32(compiler, LDRI | RT4(restored_reg) | RN4(SLJIT_SP) | (sljit_ins)tmp); } if (local_size > 0) @@ -1427,12 +1516,8 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit FAIL_IF(push_inst16(compiler, POP | reg_list)); } else { - if (lr_dst != 0) { - if (reg_list == 0) - return push_inst32(compiler, 0xf85d0b04 | RT4(lr_dst)); - + if (lr_dst != 0) reg_list |= (sljit_uw)1 << reg_map[lr_dst]; - } /* At least two registers must be set for POP_W instruction. */ SLJIT_ASSERT((reg_list & (reg_list - 1)) != 0); @@ -1441,8 +1526,12 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit } if (frame_size > 0) - return push_inst16(compiler, SUB_SP_I | (((sljit_uw)frame_size - sizeof(sljit_sw)) >> 2)); - return SLJIT_SUCCESS; + return push_inst16(compiler, SUB_SP_I | (((sljit_ins)frame_size - sizeof(sljit_sw)) >> 2)); + + if (lr_dst != 0) + return SLJIT_SUCCESS; + + return push_inst16(compiler, ADD_SP_I | 1); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler) @@ -1453,6 +1542,28 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler return emit_stack_frame_release(compiler, 0); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_return_to(compiler, src, srcw)); + + if (src & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1)); + src = TMP_REG1; + srcw = 0; + } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { + FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG1, src))); + src = TMP_REG1; + srcw = 0; + } + + FAIL_IF(emit_stack_frame_release(compiler, 1)); + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw); +} + /* --------------------------------------------------------------------- */ /* Operators */ /* --------------------------------------------------------------------- */ @@ -1709,6 +1820,63 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst_reg, + sljit_s32 src1_reg, + sljit_s32 src2_reg, + sljit_s32 src3, sljit_sw src3w) +{ + sljit_s32 is_left; + + CHECK_ERROR(); + CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w)); + + op = GET_OPCODE(op); + is_left = (op == SLJIT_SHL || op == SLJIT_MSHL); + + if (src1_reg == src2_reg) { + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_op2(compiler, is_left ? SLJIT_ROTL : SLJIT_ROTR, dst_reg, 0, src1_reg, 0, src3, src3w); + } + + ADJUST_LOCAL_OFFSET(src3, src3w); + + if (src3 & SLJIT_IMM) { + src3w &= 0x1f; + + if (src3w == 0) + return SLJIT_SUCCESS; + + if (IS_2_LO_REGS(dst_reg, src1_reg)) + FAIL_IF(push_inst16(compiler, (is_left ? LSLSI : LSRSI) | RD3(dst_reg) | RN3(src1_reg) | ((sljit_ins)src3w << 6))); + else + FAIL_IF(push_inst32(compiler, (is_left ? LSL_WI : LSR_WI) | RD4(dst_reg) | RM4(src1_reg) | IMM5(src3w))); + + src3w = (src3w ^ 0x1f) + 1; + return push_inst32(compiler, ORR_W | RD4(dst_reg) | RN4(dst_reg) | RM4(src2_reg) | (is_left ? 0x10 : 0x0) | IMM5(src3w)); + } + + if (src3 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, src3, src3w, TMP_REG2)); + src3 = TMP_REG2; + } + + if (op == SLJIT_MSHL || op == SLJIT_MLSHR || dst_reg == src3) { + FAIL_IF(push_inst32(compiler, ANDI | RD4(TMP_REG2) | RN4(src3) | 0x1f)); + src3 = TMP_REG2; + } + + if (dst_reg == src1_reg && IS_2_LO_REGS(dst_reg, src3)) + FAIL_IF(push_inst16(compiler, (is_left ? LSLS : LSRS) | RD3(dst_reg) | RN3(src3))); + else + FAIL_IF(push_inst32(compiler, (is_left ? LSL_W : LSR_W) | RD4(dst_reg) | RN4(src1_reg) | RM4(src3))); + + FAIL_IF(push_inst32(compiler, (is_left ? LSR_WI : LSL_WI) | RD4(TMP_REG1) | RM4(src2_reg) | (1 << 6))); + FAIL_IF(push_inst32(compiler, EORI | RD4(TMP_REG2) | RN4(src3) | 0x1f)); + FAIL_IF(push_inst32(compiler, (is_left ? LSR_W : LSL_W) | RD4(TMP_REG1) | RN4(TMP_REG1) | RM4(TMP_REG2))); + return push_inst32(compiler, ORR_W | RD4(dst_reg) | RN4(dst_reg) | RM4(TMP_REG1)); +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { @@ -1738,6 +1906,46 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *comp return SLJIT_SUCCESS; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw) +{ + sljit_s32 size, dst_r; + + CHECK_ERROR(); + CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw)); + ADJUST_LOCAL_OFFSET(dst, dstw); + + switch (op) { + case SLJIT_FAST_ENTER: + SLJIT_ASSERT(reg_map[TMP_REG2] == 14); + + if (FAST_IS_REG(dst)) + return push_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG2)); + break; + case SLJIT_GET_RETURN_ADDRESS: + size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds - SLJIT_KEPT_SAVEDS_COUNT(compiler->options), 0); + + if (compiler->fsaveds > 0 || compiler->fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) { + /* The size of pc is not added above. */ + if ((size & SSIZE_OF(sw)) == 0) + size += SSIZE_OF(sw); + + size += GET_SAVED_FLOAT_REGISTERS_SIZE(compiler->fscratches, compiler->fsaveds, f64); + } + + SLJIT_ASSERT(((compiler->local_size + size + SSIZE_OF(sw)) & 0x7) == 0); + + dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2; + FAIL_IF(emit_op_mem(compiler, WORD_SIZE, dst_r, SLJIT_MEM1(SLJIT_SP), compiler->local_size + size, TMP_REG1)); + break; + } + + if (dst & SLJIT_MEM) + return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw, TMP_REG1); + + return SLJIT_SUCCESS; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_register_index(reg)); @@ -1972,23 +2180,31 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil return emit_fop_mem(compiler, (op & SLJIT_32), TMP_FREG1, dst, dstw); } -/* --------------------------------------------------------------------- */ -/* Other instructions */ -/* --------------------------------------------------------------------- */ - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 freg, sljit_s32 reg) { + sljit_s32 reg2; + sljit_ins inst; + CHECK_ERROR(); - CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); - ADJUST_LOCAL_OFFSET(dst, dstw); + CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg)); - SLJIT_ASSERT(reg_map[TMP_REG2] == 14); + if (reg & REG_PAIR_MASK) { + reg2 = REG_PAIR_SECOND(reg); + reg = REG_PAIR_FIRST(reg); - if (FAST_IS_REG(dst)) - return push_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG2)); + inst = VMOV2 | RN4(reg) | RT4(reg2) | DM4(freg); + } else { + inst = VMOV | DN4(freg) | RT4(reg); - /* Memory. */ - return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw, TMP_REG1); + if (!(op & SLJIT_32)) + inst |= 1 << 7; + } + + if (GET_OPCODE(op) == SLJIT_COPY_FROM_F64) + inst |= 1 << 20; + + return push_inst32(compiler, inst); } /* --------------------------------------------------------------------- */ @@ -2413,7 +2629,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi src = TMP_REG1; } - if ((type & SLJIT_CALL_RETURN) && (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0)) { + if ((type & SLJIT_CALL_RETURN) && (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options)))) { FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG1, src))); src = TMP_REG1; } @@ -2460,6 +2676,33 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi return sljit_emit_ijump(compiler, type, src, srcw); } +#ifdef __SOFTFP__ + +static SLJIT_INLINE sljit_s32 emit_fmov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) +{ + if (compiler->options & SLJIT_ENTER_REG_ARG) { + if (src == SLJIT_FR0) + return SLJIT_SUCCESS; + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_fop1(compiler, op, SLJIT_RETURN_FREG, 0, src, srcw); + } + + if (FAST_IS_REG(src)) { + if (op & SLJIT_32) + return push_inst32(compiler, VMOV | (1 << 20) | DN4(src) | RT4(SLJIT_R0)); + return push_inst32(compiler, VMOV2 | (1 << 20) | DM4(src) | RT4(SLJIT_R0) | RN4(SLJIT_R1)); + } + + SLJIT_SKIP_CHECKS(compiler); + + if (op & SLJIT_32) + return sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, src, srcw); + return sljit_emit_mem(compiler, SLJIT_MOV, SLJIT_REG_PAIR(SLJIT_R0, SLJIT_R1), src, srcw); +} + +#endif /* __SOFTFP__ */ + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 type) @@ -2522,9 +2765,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil CHECK_ERROR(); CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); - dst_reg &= ~SLJIT_32; - - cc = get_cc(compiler, type); + cc = get_cc(compiler, type & ~SLJIT_32); if (!(src & SLJIT_IMM)) { FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8)); @@ -2567,64 +2808,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile { sljit_s32 flags; sljit_uw imm, tmp; - sljit_ins inst; CHECK_ERROR(); CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); - if (!(reg & REG_PAIR_MASK)) { - if (type & SLJIT_MEM_UNALIGNED) - return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw); + if (!(reg & REG_PAIR_MASK)) + return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw); - if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -255)) - return SLJIT_ERR_UNSUPPORTED; - - if (type & SLJIT_MEM_SUPP) - return SLJIT_SUCCESS; - - switch (type & 0xff) { - case SLJIT_MOV: - case SLJIT_MOV_U32: - case SLJIT_MOV_S32: - case SLJIT_MOV32: - case SLJIT_MOV_P: - flags = WORD_SIZE; - break; - case SLJIT_MOV_U8: - flags = BYTE_SIZE; - break; - case SLJIT_MOV_S8: - flags = BYTE_SIZE | SIGNED; - break; - case SLJIT_MOV_U16: - flags = HALF_SIZE; - break; - case SLJIT_MOV_S16: - flags = HALF_SIZE | SIGNED; - break; - default: - SLJIT_UNREACHABLE(); - flags = WORD_SIZE; - break; - } - - if (type & SLJIT_MEM_STORE) - flags |= STORE; - - inst = sljit_mem32[flags] | 0x900; - - if (type & SLJIT_MEM_PRE) - inst |= 0x400; - - if (memw >= 0) - inst |= 0x200; - else - memw = -memw; - - return push_inst32(compiler, inst | RT4(reg) | RN4(mem & REG_MASK) | (sljit_ins)memw); - } - - if (type & SLJIT_MEM_UNALIGNED) { + if (type & (SLJIT_MEM_UNALIGNED | SLJIT_MEM_UNALIGNED_16 | SLJIT_MEM_UNALIGNED_32)) { if ((mem & REG_MASK) == 0) { if ((memw & 0xfff) >= (0x1000 - SSIZE_OF(sw))) { imm = get_imm((sljit_uw)((memw + 0x1000) & ~0xfff)); @@ -2786,6 +2977,64 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile return push_inst32(compiler, ((type & SLJIT_MEM_STORE) ? STRD : LDRD) | (sljit_ins)flags | RN4(mem & REG_MASK) | RT4(REG_PAIR_FIRST(reg)) | RD4(REG_PAIR_SECOND(reg)) | (sljit_ins)memw); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 reg, + sljit_s32 mem, sljit_sw memw) +{ + sljit_s32 flags; + sljit_ins inst; + + CHECK_ERROR(); + CHECK(check_sljit_emit_mem_update(compiler, type, reg, mem, memw)); + + if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -255)) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_MEM_SUPP) + return SLJIT_SUCCESS; + + switch (type & 0xff) { + case SLJIT_MOV: + case SLJIT_MOV_U32: + case SLJIT_MOV_S32: + case SLJIT_MOV32: + case SLJIT_MOV_P: + flags = WORD_SIZE; + break; + case SLJIT_MOV_U8: + flags = BYTE_SIZE; + break; + case SLJIT_MOV_S8: + flags = BYTE_SIZE | SIGNED; + break; + case SLJIT_MOV_U16: + flags = HALF_SIZE; + break; + case SLJIT_MOV_S16: + flags = HALF_SIZE | SIGNED; + break; + default: + SLJIT_UNREACHABLE(); + flags = WORD_SIZE; + break; + } + + if (type & SLJIT_MEM_STORE) + flags |= STORE; + + inst = sljit_mem32[flags] | 0x900; + + if (!(type & SLJIT_MEM_POST)) + inst |= 0x400; + + if (memw >= 0) + inst |= 0x200; + else + memw = -memw; + + return push_inst32(compiler, inst | RT4(reg) | RN4(mem & REG_MASK) | (sljit_ins)memw); +} + static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem, sljit_sw *memw, sljit_s32 max_offset) { sljit_s32 arg = *mem; @@ -2854,10 +3103,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil CHECK_ERROR(); CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw)); - if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) - return SLJIT_ERR_UNSUPPORTED; - - if (type & SLJIT_MEM_ALIGNED_32) + if (type & SLJIT_MEM_UNALIGNED_32) return emit_fop_mem(compiler, ((type ^ SLJIT_32) & SLJIT_32) | ((type & SLJIT_MEM_STORE) ? 0 : FPU_LOAD), freg, mem, memw); if (type & SLJIT_MEM_STORE) { diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeMIPS_32.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeMIPS_32.c index ca9dbd0a53..1691905db7 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeMIPS_32.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeMIPS_32.c @@ -44,6 +44,35 @@ static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_ return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst)); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 freg, sljit_s32 reg) +{ + sljit_s32 reg2; + sljit_ins inst; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg)); + + if (reg & REG_PAIR_MASK) { + reg2 = REG_PAIR_SECOND(reg); + reg = REG_PAIR_FIRST(reg); + + inst = T(reg2) | FS(freg) | (1 << 11); + + if (op == SLJIT_COPY_TO_F64) + FAIL_IF(push_inst(compiler, MTC1 | inst, MOVABLE_INS)); + else + FAIL_IF(push_inst(compiler, MFC1 | inst, DR(reg2))); + } + + inst = T(reg) | FS(freg); + + if (GET_OPCODE(op) == SLJIT_COPY_TO_F64) + return push_inst(compiler, MTC1 | inst, MOVABLE_INS); + + return push_inst(compiler, MFC1 | inst, DR(reg)); +} + SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) { sljit_ins *inst = (sljit_ins *)addr; @@ -267,7 +296,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi if ((type & 0xff) == SLJIT_CALL_REG_ARG) { if (type & SLJIT_CALL_RETURN) { - if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) { + if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { FAIL_IF(push_inst(compiler, ADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG))); src = PIC_ADDR_REG; srcw = 0; diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeMIPS_64.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeMIPS_64.c index 443bade802..a29fe0730d 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeMIPS_64.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeMIPS_64.c @@ -128,6 +128,22 @@ static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_ return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst)); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 freg, sljit_s32 reg) +{ + sljit_ins inst; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg)); + + inst = T(reg) | FS(freg); + + if (GET_OPCODE(op) == SLJIT_COPY_TO_F64) + return push_inst(compiler, ((op & SLJIT_32) ? MTC1 : DMTC1) | inst, MOVABLE_INS); + + return push_inst(compiler, ((op & SLJIT_32) ? MFC1 : DMFC1) | inst, DR(reg)); +} + SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) { sljit_ins *inst = (sljit_ins *)addr; @@ -282,7 +298,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi if ((type & 0xff) == SLJIT_CALL_REG_ARG) { if (type & SLJIT_CALL_RETURN) { - if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) { + if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { FAIL_IF(push_inst(compiler, DADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG))); src = PIC_ADDR_REG; srcw = 0; diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeMIPS_common.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeMIPS_common.c index 928e111ac5..2b00d4f16d 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeMIPS_common.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeMIPS_common.c @@ -42,6 +42,14 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) return "MIPS64-R6" SLJIT_CPUINFO; #endif /* SLJIT_CONFIG_MIPS_32 */ +#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2) + +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + return "MIPS32-R2" SLJIT_CPUINFO; +#else /* !SLJIT_CONFIG_MIPS_32 */ + return "MIPS64-R2" SLJIT_CPUINFO; +#endif /* SLJIT_CONFIG_MIPS_32 */ + #elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) @@ -193,6 +201,11 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { #endif /* SLJIT_MIPS_REV >= 6 */ #define DIV_S (HI(17) | FMT_S | LO(3)) #define DINSU (HI(31) | LO(6)) +#define DMFC1 (HI(17) | (1 << 21) | LO(0)) +#define DMTC1 (HI(17) | (5 << 21) | LO(0)) +#define DROTR (HI(0) | (1 << 21) | LO(58)) +#define DROTR32 (HI(0) | (1 << 21) | LO(62)) +#define DROTRV (HI(0) | (1 << 6) | LO(22)) #define DSLL (HI(0) | LO(56)) #define DSLL32 (HI(0) | LO(60)) #define DSLLV (HI(0) | LO(20)) @@ -220,7 +233,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { #define LWL (HI(34)) #define LWR (HI(38)) #define LWC1 (HI(49)) -#define MFC1 (HI(17)) +#define MFC1 (HI(17) | (0 << 21)) #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) #define MOD (HI(0) | (3 << 6) | LO(26)) #define MODU (HI(0) | (3 << 6) | LO(27)) @@ -245,6 +258,8 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { #define NOR (HI(0) | LO(39)) #define OR (HI(0) | LO(37)) #define ORI (HI(13)) +#define ROTR (HI(0) | (1 << 21) | LO(2)) +#define ROTRV (HI(0) | (1 << 6) | LO(6)) #define SD (HI(63)) #define SDL (HI(44)) #define SDR (HI(45)) @@ -293,12 +308,16 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { #define SLL_W SLL #define SRA_W SRA #define SUBU_W SUBU +#define STORE_W SW +#define LOAD_W LW #else #define ADDU_W DADDU #define ADDIU_W DADDIU #define SLL_W DSLL #define SRA_W DSRA #define SUBU_W DSUBU +#define STORE_W SD +#define LOAD_W LD #endif #define SIMM_MAX (0x7fff) @@ -713,15 +732,22 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) #error "FIR check is not implemented for this architecture" #endif case SLJIT_HAS_ZERO_REGISTER: + case SLJIT_HAS_COPY_F32: + case SLJIT_HAS_COPY_F64: return 1; - #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) case SLJIT_HAS_CLZ: case SLJIT_HAS_CMOV: case SLJIT_HAS_PREFETCH: return 1; -#endif /* SLJIT_MIPS_REV >= 1 */ + case SLJIT_HAS_CTZ: + return 2; +#endif /* SLJIT_MIPS_REV >= 1 */ +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2) + case SLJIT_HAS_ROT: + return 1; +#endif /* SLJIT_MIPS_REV >= 2 */ default: return 0; } @@ -766,14 +792,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type) #define SLOW_SRC2 0x20000 #define SLOW_DEST 0x40000 -#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) -#define STACK_STORE SW -#define STACK_LOAD LW -#else -#define STACK_STORE SD -#define STACK_LOAD LD -#endif - static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw); static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size, sljit_ins *ins_ptr); @@ -801,12 +819,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) { if ((local_size & SSIZE_OF(sw)) != 0) local_size += SSIZE_OF(sw); - local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64)); + local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64); } local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf; #else - local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64)); + local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64); local_size = (local_size + SLJIT_LOCALS_OFFSET + 31) & ~0x1f; #endif compiler->local_size = local_size; @@ -850,17 +868,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi #endif } - FAIL_IF(push_inst(compiler, STACK_STORE | base | TA(RETURN_ADDR_REG) | IMM(offset), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, STORE_W | base | TA(RETURN_ADDR_REG) | IMM(offset), UNMOVABLE_INS)); tmp = SLJIT_S0 - saveds; for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) { offset -= SSIZE_OF(sw); - FAIL_IF(push_inst(compiler, STACK_STORE | base | T(i) | IMM(offset), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, STORE_W | base | T(i) | IMM(offset), MOVABLE_INS)); } for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { offset -= SSIZE_OF(sw); - FAIL_IF(push_inst(compiler, STACK_STORE | base | T(i) | IMM(offset), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, STORE_W | base | T(i) | IMM(offset), MOVABLE_INS)); } #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) @@ -997,12 +1015,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) { if ((local_size & SSIZE_OF(sw)) != 0) local_size += SSIZE_OF(sw); - local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64)); + local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64); } compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf; #else - local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64)); + local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64); compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 31) & ~0x1f; #endif return SLJIT_SUCCESS; @@ -1011,12 +1029,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size, sljit_ins *ins_ptr) { sljit_s32 local_size, i, tmp, offset; + sljit_s32 load_return_addr = (frame_size == 0); sljit_s32 scratches = compiler->scratches; sljit_s32 saveds = compiler->saveds; sljit_s32 fsaveds = compiler->fsaveds; sljit_s32 fscratches = compiler->fscratches; sljit_s32 kept_saveds_count = SLJIT_KEPT_SAVEDS_COUNT(compiler->options); + SLJIT_ASSERT(frame_size == 1 || (frame_size & 0xf) == 0); + frame_size &= ~0xf; + local_size = compiler->local_size; tmp = GET_SAVED_REGISTERS_SIZE(scratches, saveds - kept_saveds_count, 1); @@ -1024,10 +1046,10 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) { if ((tmp & SSIZE_OF(sw)) != 0) tmp += SSIZE_OF(sw); - tmp += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64)); + tmp += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64); } #else - tmp += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64)); + tmp += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64); #endif if (local_size <= SIMM_MAX) { @@ -1047,18 +1069,18 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit SLJIT_ASSERT(local_size >= frame_size); offset = local_size - SSIZE_OF(sw); - if (frame_size == 0) - FAIL_IF(push_inst(compiler, STACK_LOAD | S(SLJIT_SP) | TA(RETURN_ADDR_REG) | IMM(offset), RETURN_ADDR_REG)); + if (load_return_addr) + FAIL_IF(push_inst(compiler, LOAD_W | S(SLJIT_SP) | TA(RETURN_ADDR_REG) | IMM(offset), RETURN_ADDR_REG)); tmp = SLJIT_S0 - saveds; for (i = SLJIT_S0 - kept_saveds_count; i > tmp; i--) { offset -= SSIZE_OF(sw); - FAIL_IF(push_inst(compiler, STACK_LOAD | S(SLJIT_SP) | T(i) | IMM(offset), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, LOAD_W | S(SLJIT_SP) | T(i) | IMM(offset), MOVABLE_INS)); } for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { offset -= SSIZE_OF(sw); - FAIL_IF(push_inst(compiler, STACK_LOAD | S(SLJIT_SP) | T(i) | IMM(offset), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, LOAD_W | S(SLJIT_SP) | T(i) | IMM(offset), MOVABLE_INS)); } #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) @@ -1099,8 +1121,38 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler return push_inst(compiler, ins, UNMOVABLE_INS); } -#undef STACK_STORE -#undef STACK_LOAD +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw) +{ + sljit_ins ins; + + CHECK_ERROR(); + CHECK(check_sljit_emit_return_to(compiler, src, srcw)); + + if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw)); + src = PIC_ADDR_REG; + srcw = 0; + } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { + FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG))); + src = PIC_ADDR_REG; + srcw = 0; + } + + FAIL_IF(emit_stack_frame_release(compiler, 1, &ins)); + + if (!(src & SLJIT_IMM)) { + FAIL_IF(push_inst(compiler, JR | S(src), UNMOVABLE_INS)); + return push_inst(compiler, ins, UNMOVABLE_INS); + } + + if (ins != NOP) + FAIL_IF(push_inst(compiler, ins, MOVABLE_INS)); + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw); +} /* --------------------------------------------------------------------- */ /* Operators */ @@ -1302,7 +1354,7 @@ static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, s if (SLJIT_UNLIKELY(argw)) { FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | DA(tmp_ar) | SH_IMM(argw), tmp_ar)); - FAIL_IF(push_inst(compiler, ADDU_W | S(base) | TA(tmp_ar) | DA(tmp_ar), tmp_ar)); + FAIL_IF(push_inst(compiler, ADDU_W | SA(tmp_ar) | T(base) | DA(tmp_ar), tmp_ar)); } else FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(OFFS_REG(arg)) | DA(tmp_ar), tmp_ar)); @@ -1312,7 +1364,7 @@ static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, s FAIL_IF(load_immediate(compiler, tmp_ar, TO_ARGW_HI(argw))); if (base != 0) - FAIL_IF(push_inst(compiler, ADDU_W | S(base) | TA(tmp_ar) | DA(tmp_ar), tmp_ar)); + FAIL_IF(push_inst(compiler, ADDU_W | SA(tmp_ar) | T(base) | DA(tmp_ar), tmp_ar)); return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar) | IMM(argw), delay_slot); } @@ -1342,55 +1394,124 @@ static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, slji #define SELECT_OP(a, b) (b) -#define EMIT_SHIFT(op_dimm, op_dimm32, op_imm, op_dv, op_v) \ - if (flags & SRC2_IMM) { \ - if (op & SLJIT_SET_Z) \ - FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \ - if (!(flags & UNUSED_DEST)) \ - FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \ - } \ - else { \ - if (op & SLJIT_SET_Z) \ - FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \ - if (!(flags & UNUSED_DEST)) \ - FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | D(dst), DR(dst))); \ - } +#define EMIT_SHIFT(dimm, dimm32, imm, dv, v) \ + op_imm = (imm); \ + op_v = (v); #else /* !SLJIT_CONFIG_MIPS_32 */ #define SELECT_OP(a, b) \ (!(op & SLJIT_32) ? a : b) -#define EMIT_SHIFT(op_dimm, op_dimm32, op_imm, op_dv, op_v) \ - if (flags & SRC2_IMM) { \ - if (src2 >= 32) { \ - SLJIT_ASSERT(!(op & SLJIT_32)); \ - ins = op_dimm32; \ - src2 -= 32; \ - } \ - else \ - ins = (op & SLJIT_32) ? op_imm : op_dimm; \ - if (op & SLJIT_SET_Z) \ - FAIL_IF(push_inst(compiler, ins | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \ - if (!(flags & UNUSED_DEST)) \ - FAIL_IF(push_inst(compiler, ins | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \ - } \ - else { \ - ins = (op & SLJIT_32) ? op_v : op_dv; \ - if (op & SLJIT_SET_Z) \ - FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \ - if (!(flags & UNUSED_DEST)) \ - FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | D(dst), DR(dst))); \ - } +#define EMIT_SHIFT(dimm, dimm32, imm, dv, v) \ + op_dimm = (dimm); \ + op_dimm32 = (dimm32); \ + op_imm = (imm); \ + op_dv = (dv); \ + op_v = (v); #endif /* SLJIT_CONFIG_MIPS_32 */ +#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV < 1) + +static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src) +{ + sljit_s32 is_clz = (GET_OPCODE(op) == SLJIT_CLZ); +#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) + sljit_ins max = (op & SLJIT_32) ? 32 : 64; +#else /* !SLJIT_CONFIG_RISCV_64 */ + sljit_ins max = 32; +#endif /* SLJIT_CONFIG_RISCV_64 */ + + /* The TMP_REG2 is the next value. */ + if (src != TMP_REG2) + FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src) | TA(0) | D(TMP_REG2), DR(TMP_REG2))); + + FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG2) | TA(0) | IMM(is_clz ? 13 : 14), UNMOVABLE_INS)); + /* The OTHER_FLAG is the counter. Delay slot. */ + FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(max), OTHER_FLAG)); + + if (!is_clz) { + FAIL_IF(push_inst(compiler, ANDI | S(TMP_REG2) | T(TMP_REG1) | IMM(1), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, BNE | S(TMP_REG1) | TA(0) | IMM(11), UNMOVABLE_INS)); + } else + FAIL_IF(push_inst(compiler, BLTZ | S(TMP_REG2) | TA(0) | IMM(11), UNMOVABLE_INS)); + + /* Delay slot. */ + FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(0), OTHER_FLAG)); + + /* The TMP_REG1 is the next shift. */ + FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | T(TMP_REG1) | IMM(max), DR(TMP_REG1))); + + FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(TMP_REG2) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG)); + FAIL_IF(push_inst(compiler, SELECT_OP(DSRL, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), DR(TMP_REG1))); + + FAIL_IF(push_inst(compiler, (is_clz ? SELECT_OP(DSRLV, SRLV) : SELECT_OP(DSLLV, SLLV)) | S(TMP_REG1) | TA(EQUAL_FLAG) | D(TMP_REG2), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, BNE | S(TMP_REG2) | TA(0) | IMM(-4), UNMOVABLE_INS)); + /* Delay slot. */ + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); + + FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(TMP_REG1) | T(TMP_REG2) | IMM(-1), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, (is_clz ? SELECT_OP(DSRLV, SRLV) : SELECT_OP(DSLLV, SLLV)) | S(TMP_REG2) | TA(EQUAL_FLAG) | D(TMP_REG2), DR(TMP_REG2))); + + FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG2) | TA(0) | IMM(-7), UNMOVABLE_INS)); + /* Delay slot. */ + FAIL_IF(push_inst(compiler, OR | SA(OTHER_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG)); + + return push_inst(compiler, SELECT_OP(DADDU, ADDU) | SA(OTHER_FLAG) | TA(0) | D(dst), DR(dst)); +} + +#endif /* SLJIT_MIPS_REV < 1 */ + +static sljit_s32 emit_rev(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src) +{ + SLJIT_UNUSED_ARG(op); + +#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) + if (!(op & SLJIT_32)) { + FAIL_IF(push_inst(compiler, DSRL32 | T(src) | D(TMP_REG1) | SH_IMM(0), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, ORI | SA(0) | TA(OTHER_FLAG) | 0xffff, OTHER_FLAG)); + FAIL_IF(push_inst(compiler, DSLL32 | T(src) | D(dst) | SH_IMM(0), DR(dst))); + FAIL_IF(push_inst(compiler, DSLL32 | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(0), OTHER_FLAG)); + FAIL_IF(push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst))); + FAIL_IF(push_inst(compiler, ORI | SA(OTHER_FLAG) | TA(OTHER_FLAG) | 0xffff, OTHER_FLAG)); + + FAIL_IF(push_inst(compiler, DSRL | T(dst) | D(TMP_REG1) | SH_IMM(16), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, AND | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst))); + FAIL_IF(push_inst(compiler, AND | S(TMP_REG1) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, DSLL | TA(OTHER_FLAG) | DA(EQUAL_FLAG) | SH_IMM(8), EQUAL_FLAG)); + FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst))); + FAIL_IF(push_inst(compiler, XOR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); + FAIL_IF(push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst))); + + FAIL_IF(push_inst(compiler, DSRL | T(dst) | D(TMP_REG1) | SH_IMM(8), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, AND | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst))); + FAIL_IF(push_inst(compiler, AND | S(TMP_REG1) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(8), DR(dst))); + return push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)); + } +#endif /* SLJIT_CONFIG_MIPS_64 */ + + FAIL_IF(push_inst(compiler, SRL | T(src) | D(TMP_REG1) | SH_IMM(16), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, LUI | TA(OTHER_FLAG) | 0xff, OTHER_FLAG)); + FAIL_IF(push_inst(compiler, SLL | T(src) | D(dst) | SH_IMM(16), DR(dst))); + FAIL_IF(push_inst(compiler, ORI | SA(OTHER_FLAG) | TA(OTHER_FLAG) | 0xff, OTHER_FLAG)); + FAIL_IF(push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst))); + + FAIL_IF(push_inst(compiler, SRL | T(dst) | D(TMP_REG1) | SH_IMM(8), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, AND | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst))); + FAIL_IF(push_inst(compiler, AND | S(TMP_REG1) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, SLL | T(dst) | D(dst) | SH_IMM(8), DR(dst))); + return push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)); +} + static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_s32 src1, sljit_sw src2) { sljit_s32 is_overflow, is_carry, carry_src_ar, is_handled; + sljit_ins op_imm, op_v; #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) - sljit_ins ins; + sljit_ins ins, op_dimm, op_dimm32, op_dv; #endif switch (GET_OPCODE(op)) { @@ -1481,43 +1602,41 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl return SLJIT_SUCCESS; #endif /* SLJIT_CONFIG_MIPS_64 */ - case SLJIT_NOT: - SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); - if (op & SLJIT_SET_Z) - FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); - if (!(flags & UNUSED_DEST)) - FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst))); - return SLJIT_SUCCESS; - +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) case SLJIT_CLZ: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); -#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) - if (op & SLJIT_SET_Z) - FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); - if (!(flags & UNUSED_DEST)) - FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst))); +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + return push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | D(dst), DR(dst)); +#else /* SLJIT_MIPS_REV < 6 */ + return push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst)); +#endif /* SLJIT_MIPS_REV >= 6 */ + case SLJIT_CTZ: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src2) | D(TMP_REG1), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, AND | S(src2) | T(TMP_REG1) | D(dst), DR(dst))); +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(dst) | D(dst), DR(dst))); +#else /* SLJIT_MIPS_REV < 6 */ + FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(dst) | T(dst) | D(dst), DR(dst))); +#endif /* SLJIT_MIPS_REV >= 6 */ + FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(TMP_REG1) | IMM(SELECT_OP(-64, -32)), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(SELECT_OP(26, 27)), DR(TMP_REG1))); + return push_inst(compiler, XOR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)); #else /* SLJIT_MIPS_REV < 1 */ - /* Nearly all instructions are unmovable in the following sequence. */ - FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1))); - /* Check zero. */ - FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(5), UNMOVABLE_INS)); -#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) - FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM(32), UNMOVABLE_INS)); -#else /* !SLJIT_CONFIG_MIPS_32 */ - FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM((op & SLJIT_32) ? 32 : 64), UNMOVABLE_INS)); -#endif /* SLJIT_CONFIG_MIPS_32 */ - FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | T(dst) | IMM(-1), DR(dst))); - /* Loop for searching the highest bit. */ - FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(dst) | IMM(1), DR(dst))); - FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS)); - FAIL_IF(push_inst(compiler, SELECT_OP(DSLL, SLL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS)); + case SLJIT_CLZ: + case SLJIT_CTZ: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + return emit_clz_ctz(compiler, op, dst, src2); #endif /* SLJIT_MIPS_REV >= 1 */ - return SLJIT_SUCCESS; + + case SLJIT_REV: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + return emit_rev(compiler, op, dst, src2); case SLJIT_ADD: /* Overflow computation (both add and sub): overflow = src1_sign ^ src2_sign ^ result_sign ^ carry_flag */ is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW; - carry_src_ar = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); + carry_src_ar = GET_FLAG_TYPE(op) == SLJIT_CARRY; if (flags & SRC2_IMM) { if (is_overflow) { @@ -1573,7 +1692,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl return push_inst(compiler, XOR | S(TMP_REG1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG); case SLJIT_ADDC: - carry_src_ar = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); + carry_src_ar = GET_FLAG_TYPE(op) == SLJIT_CARRY; if (flags & SRC2_IMM) { FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst))); @@ -1620,11 +1739,11 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl is_handled = 0; if (flags & SRC2_IMM) { - if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) { + if (GET_FLAG_TYPE(op) == SLJIT_LESS) { FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); is_handled = 1; } - else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) { + else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS) { FAIL_IF(push_inst(compiler, SLTI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); is_handled = 1; } @@ -1641,19 +1760,15 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl switch (GET_FLAG_TYPE(op)) { case SLJIT_LESS: - case SLJIT_GREATER_EQUAL: FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); break; case SLJIT_GREATER: - case SLJIT_LESS_EQUAL: FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG)); break; case SLJIT_SIG_LESS: - case SLJIT_SIG_GREATER_EQUAL: FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); break; case SLJIT_SIG_GREATER: - case SLJIT_SIG_LESS_EQUAL: FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG)); break; } @@ -1676,7 +1791,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl } is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW; - is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); + is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY; if (flags & SRC2_IMM) { if (is_overflow) { @@ -1725,7 +1840,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl flags &= ~SRC2_IMM; } - is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); + is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY; if (flags & SRC2_IMM) { if (is_carry) @@ -1791,24 +1906,155 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl return SLJIT_SUCCESS; case SLJIT_XOR: + if (!(flags & LOGICAL_OP)) { + SLJIT_ASSERT((flags & SRC2_IMM) && src2 == -1); + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); + if (!(flags & UNUSED_DEST)) + FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | D(dst), DR(dst))); + return SLJIT_SUCCESS; + } EMIT_LOGICAL(XORI, XOR); return SLJIT_SUCCESS; case SLJIT_SHL: + case SLJIT_MSHL: EMIT_SHIFT(DSLL, DSLL32, SLL, DSLLV, SLLV); - return SLJIT_SUCCESS; + break; case SLJIT_LSHR: + case SLJIT_MLSHR: EMIT_SHIFT(DSRL, DSRL32, SRL, DSRLV, SRLV); - return SLJIT_SUCCESS; + break; case SLJIT_ASHR: + case SLJIT_MASHR: EMIT_SHIFT(DSRA, DSRA32, SRA, DSRAV, SRAV); + break; + +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2) + case SLJIT_ROTL: + if ((flags & SRC2_IMM) || src2 == 0) { +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + src2 = -src2 & 0x1f; +#else /* !SLJIT_CONFIG_MIPS_32 */ + src2 = -src2 & ((op & SLJIT_32) ? 0x1f : 0x3f); +#endif /* SLJIT_CONFIG_MIPS_32 */ + } else { + FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src2) | D(TMP_REG2), DR(TMP_REG2))); + src2 = TMP_REG2; + } + /* fallthrough */ + + case SLJIT_ROTR: + EMIT_SHIFT(DROTR, DROTR32, ROTR, DROTRV, ROTRV); + break; +#else /* SLJIT_MIPS_REV < 1 */ + case SLJIT_ROTL: + case SLJIT_ROTR: + if (flags & SRC2_IMM) { + SLJIT_ASSERT(src2 != 0); +#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) + if (!(op & SLJIT_32)) { + if (GET_OPCODE(op) == SLJIT_ROTL) + op_imm = ((src2 < 32) ? DSLL : DSLL32); + else + op_imm = ((src2 < 32) ? DSRL : DSRL32); + + FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(OTHER_FLAG) | (((sljit_ins)src2 & 0x1f) << 6), OTHER_FLAG)); + + src2 = 64 - src2; + if (GET_OPCODE(op) == SLJIT_ROTL) + op_imm = ((src2 < 32) ? DSRL : DSRL32); + else + op_imm = ((src2 < 32) ? DSLL : DSLL32); + + FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | (((sljit_ins)src2 & 0x1f) << 6), DR(dst))); + return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)); + } +#endif /* SLJIT_CONFIG_MIPS_64 */ + + op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SLL : SRL; + FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(OTHER_FLAG) | ((sljit_ins)src2 << 6), OTHER_FLAG)); + + src2 = 32 - src2; + op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SRL : SLL; + FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | (((sljit_ins)src2 & 0x1f) << 6), DR(dst))); + return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)); + } + + if (src2 == 0) { + if (dst != src1) + return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | TA(0) | D(dst), DR(dst)); + return SLJIT_SUCCESS; + } + + FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); + +#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) + if (!(op & SLJIT_32)) { + op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? DSLLV : DSRLV; + FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG)); + op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? DSRLV : DSLLV; + FAIL_IF(push_inst(compiler, op_v | SA(EQUAL_FLAG) | T(src1) | D(dst), DR(dst))); + return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)); + } +#endif /* SLJIT_CONFIG_MIPS_64 */ + + op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? SLLV : SRLV; + FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG)); + op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? SRLV : SLLV; + FAIL_IF(push_inst(compiler, op_v | SA(EQUAL_FLAG) | T(src1) | D(dst), DR(dst))); + return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)); +#endif /* SLJIT_MIPS_REV >= 2 */ + + default: + SLJIT_UNREACHABLE(); return SLJIT_SUCCESS; } - SLJIT_UNREACHABLE(); - return SLJIT_SUCCESS; +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + if ((flags & SRC2_IMM) || src2 == 0) { + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); + + if (flags & UNUSED_DEST) + return SLJIT_SUCCESS; + return push_inst(compiler, op_imm | T(src1) | D(dst) | SH_IMM(src2), DR(dst)); + } + + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); + + if (flags & UNUSED_DEST) + return SLJIT_SUCCESS; + return push_inst(compiler, op_v | S(src2) | T(src1) | D(dst), DR(dst)); +#else /* !SLJIT_CONFIG_MIPS_32 */ + if ((flags & SRC2_IMM) || src2 == 0) { + if (src2 >= 32) { + SLJIT_ASSERT(!(op & SLJIT_32)); + ins = op_dimm32; + src2 -= 32; + } + else + ins = (op & SLJIT_32) ? op_imm : op_dimm; + + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, ins | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); + + if (flags & UNUSED_DEST) + return SLJIT_SUCCESS; + return push_inst(compiler, ins | T(src1) | D(dst) | SH_IMM(src2), DR(dst)); + } + + ins = (op & SLJIT_32) ? op_v : op_dv; + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); + + if (flags & UNUSED_DEST) + return SLJIT_SUCCESS; + return push_inst(compiler, ins | S(src2) | T(src1) | D(dst), DR(dst)); +#endif /* SLJIT_CONFIG_MIPS_32 */ } #define CHECK_IMM(flags, srcw) \ @@ -2098,10 +2344,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile case SLJIT_MOV_S16: return emit_op(compiler, op, HALF_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw); - case SLJIT_NOT: - return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw); - case SLJIT_CLZ: + case SLJIT_CTZ: + case SLJIT_REV: return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw); } @@ -2147,14 +2392,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile compiler->status_flags_state = 0; return emit_op(compiler, op, flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w); + case SLJIT_XOR: + if (((src1 & SLJIT_IMM) && src1w == -1) || ((src2 & SLJIT_IMM) && src2w == -1)) { + return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w); + } + /* fallthrough */ case SLJIT_AND: case SLJIT_OR: - case SLJIT_XOR: return emit_op(compiler, op, flags | CUMULATIVE_OP | LOGICAL_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w); case SLJIT_SHL: + case SLJIT_MSHL: case SLJIT_LSHR: + case SLJIT_MLSHR: case SLJIT_ASHR: + case SLJIT_MASHR: + case SLJIT_ROTL: + case SLJIT_ROTR: #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) if (src2 & SLJIT_IMM) src2w &= 0x1f; @@ -2184,6 +2438,97 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w); } +#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) +#define SELECT_OP3(op, src2w, D, D32, W) (((op & SLJIT_32) ? (W) : ((src2w) < 32) ? (D) : (D32)) | (((sljit_ins)src2w & 0x1f) << 6)) +#define SELECT_OP2(op, D, W) ((op & SLJIT_32) ? (W) : (D)) +#else /* !SLJIT_CONFIG_MIPS_64 */ +#define SELECT_OP3(op, src2w, D, D32, W) ((W) | ((sljit_ins)(src2w) << 6)) +#define SELECT_OP2(op, D, W) (W) +#endif /* SLJIT_CONFIG_MIPS_64 */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst_reg, + sljit_s32 src1_reg, + sljit_s32 src2_reg, + sljit_s32 src3, sljit_sw src3w) +{ + sljit_s32 is_left; + sljit_ins ins1, ins2, ins3; +#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) + sljit_s32 inp_flags = ((op & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA; + sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64; +#else /* !SLJIT_CONFIG_MIPS_64 */ + sljit_s32 inp_flags = WORD_DATA | LOAD_DATA; + sljit_sw bit_length = 32; +#endif /* SLJIT_CONFIG_MIPS_64 */ + + CHECK_ERROR(); + CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w)); + + is_left = (GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_MSHL); + + if (src1_reg == src2_reg) { + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_op2(compiler, (is_left ? SLJIT_ROTL : SLJIT_ROTR) | (op & SLJIT_32), dst_reg, 0, src1_reg, 0, src3, src3w); + } + + ADJUST_LOCAL_OFFSET(src3, src3w); + + if (src3 & SLJIT_IMM) { + src3w &= bit_length - 1; + + if (src3w == 0) + return SLJIT_SUCCESS; + + if (is_left) { + ins1 = SELECT_OP3(op, src3w, DSLL, DSLL32, SLL); + src3w = bit_length - src3w; + ins2 = SELECT_OP3(op, src3w, DSRL, DSRL32, SRL); + } else { + ins1 = SELECT_OP3(op, src3w, DSRL, DSRL32, SRL); + src3w = bit_length - src3w; + ins2 = SELECT_OP3(op, src3w, DSLL, DSLL32, SLL); + } + + FAIL_IF(push_inst(compiler, ins1 | T(src1_reg) | D(dst_reg), DR(dst_reg))); + FAIL_IF(push_inst(compiler, ins2 | T(src2_reg) | D(TMP_REG1), DR(TMP_REG1))); + return push_inst(compiler, OR | S(dst_reg) | T(TMP_REG1) | D(dst_reg), DR(dst_reg)); + } + + if (src3 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, inp_flags, DR(TMP_REG2), src3, src3w)); + src3 = TMP_REG2; + } else if (dst_reg == src3) { + FAIL_IF(push_inst(compiler, SELECT_OP2(op, DADDU, ADDU) | S(src3) | TA(0) | D(TMP_REG2), DR(TMP_REG2))); + src3 = TMP_REG2; + } + + if (is_left) { + ins1 = SELECT_OP2(op, DSRL, SRL); + ins2 = SELECT_OP2(op, DSLLV, SLLV); + ins3 = SELECT_OP2(op, DSRLV, SRLV); + } else { + ins1 = SELECT_OP2(op, DSLL, SLL); + ins2 = SELECT_OP2(op, DSRLV, SRLV); + ins3 = SELECT_OP2(op, DSLLV, SLLV); + } + + FAIL_IF(push_inst(compiler, ins2 | S(src3) | T(src1_reg) | D(dst_reg), DR(dst_reg))); + + if (!(op & SLJIT_SHIFT_INTO_NON_ZERO)) { + FAIL_IF(push_inst(compiler, ins1 | T(src2_reg) | D(TMP_REG1) | (1 << 6), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, XORI | S(src3) | T(TMP_REG2) | ((sljit_ins)bit_length - 1), DR(TMP_REG2))); + src2_reg = TMP_REG1; + } else + FAIL_IF(push_inst(compiler, SELECT_OP2(op, DSUBU, SUBU) | SA(0) | T(src3) | D(TMP_REG2), DR(TMP_REG2))); + + FAIL_IF(push_inst(compiler, ins3 | S(TMP_REG2) | T(src2_reg) | D(TMP_REG1), DR(TMP_REG1))); + return push_inst(compiler, OR | S(dst_reg) | T(TMP_REG1) | D(dst_reg), DR(dst_reg)); +} + +#undef SELECT_OP3 +#undef SELECT_OP2 + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { @@ -2216,6 +2561,36 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *comp return SLJIT_SUCCESS; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw) +{ + sljit_s32 dst_ar = RETURN_ADDR_REG; + + CHECK_ERROR(); + CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw)); + ADJUST_LOCAL_OFFSET(dst, dstw); + + switch (op) { + case SLJIT_FAST_ENTER: + if (FAST_IS_REG(dst)) + return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), UNMOVABLE_INS); + break; + case SLJIT_GET_RETURN_ADDRESS: + dst_ar = DR(FAST_IS_REG(dst) ? dst : TMP_REG2); + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst_ar, SLJIT_MEM1(SLJIT_SP), compiler->local_size - SSIZE_OF(sw))); + break; + } + + if (dst & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, WORD_DATA, dst_ar, dst, dstw)); + + if (op == SLJIT_FAST_ENTER) + compiler->delay_slot = UNMOVABLE_INS; + } + + return SLJIT_SUCCESS; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_register_index(reg)); @@ -2340,36 +2715,30 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile switch (GET_FLAG_TYPE(op)) { case SLJIT_F_EQUAL: case SLJIT_ORDERED_EQUAL: - case SLJIT_UNORDERED_OR_NOT_EQUAL: inst = C_EQ_S; break; case SLJIT_F_NOT_EQUAL: case SLJIT_UNORDERED_OR_EQUAL: - case SLJIT_ORDERED_NOT_EQUAL: inst = C_UEQ_S; break; case SLJIT_F_LESS: case SLJIT_ORDERED_LESS: - case SLJIT_UNORDERED_OR_GREATER_EQUAL: inst = C_OLT_S; break; case SLJIT_F_GREATER_EQUAL: case SLJIT_UNORDERED_OR_LESS: - case SLJIT_ORDERED_GREATER_EQUAL: inst = C_ULT_S; break; case SLJIT_F_GREATER: case SLJIT_ORDERED_GREATER: - case SLJIT_UNORDERED_OR_LESS_EQUAL: inst = C_ULE_S; break; case SLJIT_F_LESS_EQUAL: case SLJIT_UNORDERED_OR_GREATER: - case SLJIT_ORDERED_LESS_EQUAL: inst = C_OLE_S; break; default: - SLJIT_ASSERT(GET_FLAG_TYPE(op) == SLJIT_UNORDERED || GET_FLAG_TYPE(op) == SLJIT_ORDERED); + SLJIT_ASSERT(GET_FLAG_TYPE(op) == SLJIT_UNORDERED); inst = C_UN_S; break; } @@ -2507,25 +2876,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil #undef FLOAT_DATA #undef FMT -/* --------------------------------------------------------------------- */ -/* Other instructions */ -/* --------------------------------------------------------------------- */ - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) -{ - CHECK_ERROR(); - CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); - ADJUST_LOCAL_OFFSET(dst, dstw); - - if (FAST_IS_REG(dst)) - return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), UNMOVABLE_INS); - - /* Memory. */ - FAIL_IF(emit_op_mem(compiler, WORD_DATA, RETURN_ADDR_REG, dst, dstw)); - compiler->delay_slot = UNMOVABLE_INS; - return SLJIT_SUCCESS; -} - /* --------------------------------------------------------------------- */ /* Conditional instructions */ /* --------------------------------------------------------------------- */ @@ -2849,7 +3199,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi CHECK_ERROR(); CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); - ADJUST_LOCAL_OFFSET(src, srcw); if (src & SLJIT_IMM) { jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); @@ -2861,8 +3210,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi jump->flags |= IS_MOVABLE; src = TMP_REG2; - } - else if (src & SLJIT_MEM) { + } else if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(TMP_REG2), src, srcw)); src = TMP_REG2; } @@ -2882,6 +3231,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi compiler->size += 6; #endif } + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); return SLJIT_SUCCESS; } @@ -3000,7 +3350,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil if (SLJIT_UNLIKELY(src & SLJIT_IMM)) { #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) - if (dst_reg & SLJIT_32) + if (type & SLJIT_32) srcw = (sljit_s32)srcw; #endif FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw)); @@ -3008,9 +3358,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil srcw = 0; } - dst_reg &= ~SLJIT_32; - - switch (type) { + switch (type & ~SLJIT_32) { case SLJIT_EQUAL: ins = MOVZ | TA(EQUAL_FLAG); break; @@ -3068,8 +3416,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil #endif /* SLJIT_MIPS_REV >= 1 */ } -#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) - static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem, sljit_sw *memw, sljit_s16 max_offset) { sljit_s32 arg = *mem; @@ -3080,7 +3426,7 @@ static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem if (SLJIT_UNLIKELY(argw)) { FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | D(TMP_REG1) | SH_IMM(argw), DR(TMP_REG1))); - FAIL_IF(push_inst(compiler, ADDU_W | S(arg & REG_MASK) | T(TMP_REG1) | D(TMP_REG1), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG1) | T(arg & REG_MASK) | D(TMP_REG1), DR(TMP_REG1))); } else FAIL_IF(push_inst(compiler, ADDU_W | S(arg & REG_MASK) | T(OFFS_REG(arg)) | D(TMP_REG1), DR(TMP_REG1))); @@ -3108,7 +3454,7 @@ static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem if ((arg & REG_MASK) == 0) return SLJIT_SUCCESS; - return push_inst(compiler, ADDU_W | S(arg & REG_MASK) | T(TMP_REG1) | D(TMP_REG1), DR(TMP_REG1)); + return push_inst(compiler, ADDU_W | S(TMP_REG1) | T(arg & REG_MASK) | D(TMP_REG1), DR(TMP_REG1)); } #if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN) @@ -3123,18 +3469,70 @@ static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem #define MEMF64_FS_SECOND(freg) FS(freg) #endif /* SLJIT_LITTLE_ENDIAN */ +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) +#define MEM_CHECK_UNALIGNED(type) ((type) & (SLJIT_MEM_UNALIGNED | SLJIT_MEM_UNALIGNED_16)) +#else /* !SLJIT_CONFIG_MIPS_32 */ +#define MEM_CHECK_UNALIGNED(type) ((type) & (SLJIT_MEM_UNALIGNED | SLJIT_MEM_UNALIGNED_16 | SLJIT_MEM_UNALIGNED_32)) +#endif /* SLJIT_CONFIG_MIPS_32 */ + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 reg, sljit_s32 mem, sljit_sw memw) { sljit_s32 op = type & 0xff; sljit_s32 flags = 0; + sljit_ins ins; +#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + sljit_ins ins_right; +#endif /* !(SLJIT_MIPS_REV >= 6) */ CHECK_ERROR(); CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); - if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) - return SLJIT_ERR_UNSUPPORTED; + if (reg & REG_PAIR_MASK) { + ADJUST_LOCAL_OFFSET(mem, memw); + +#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + if (MEM_CHECK_UNALIGNED(type)) { + FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - (2 * SSIZE_OF(sw) - 1))); + + if (!(type & SLJIT_MEM_STORE) && (mem == REG_PAIR_FIRST(reg) || mem == REG_PAIR_SECOND(reg))) { + FAIL_IF(push_inst(compiler, ADDU_W | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1))); + mem = TMP_REG1; + } + +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + ins = ((type & SLJIT_MEM_STORE) ? SWL : LWL) | S(mem); + ins_right = ((type & SLJIT_MEM_STORE) ? SWR : LWR) | S(mem); +#else /* !SLJIT_CONFIG_MIPS_32 */ + ins = ((type & SLJIT_MEM_STORE) ? SDL : LDL) | S(mem); + ins_right = ((type & SLJIT_MEM_STORE) ? SDR : LDR) | S(mem); +#endif /* SLJIT_CONFIG_MIPS_32 */ + + FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_FIRST(reg)) | IMM(memw), DR(REG_PAIR_FIRST(reg)))); + FAIL_IF(push_inst(compiler, ins_right | T(REG_PAIR_FIRST(reg)) | IMM(memw + (SSIZE_OF(sw) - 1)), DR(REG_PAIR_FIRST(reg)))); + FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_SECOND(reg)) | IMM(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg)))); + return push_inst(compiler, ins_right | T(REG_PAIR_SECOND(reg)) | IMM((memw + 2 * SSIZE_OF(sw) - 1)), DR(REG_PAIR_SECOND(reg))); + } +#endif /* !(SLJIT_MIPS_REV >= 6) */ + + FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - SSIZE_OF(sw))); + + ins = ((type & SLJIT_MEM_STORE) ? STORE_W : LOAD_W) | S(mem); + + if (!(type & SLJIT_MEM_STORE) && mem == REG_PAIR_FIRST(reg)) { + FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_SECOND(reg)) | IMM(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg)))); + return push_inst(compiler, ins | T(REG_PAIR_FIRST(reg)) | IMM(memw), DR(REG_PAIR_FIRST(reg))); + } + + FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_FIRST(reg)) | IMM(memw), DR(REG_PAIR_FIRST(reg)))); + return push_inst(compiler, ins | T(REG_PAIR_SECOND(reg)) | IMM(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg))); + } + +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw); +#else /* !(SLJIT_MIPS_REV >= 6) */ + ADJUST_LOCAL_OFFSET(mem, memw); switch (op) { case SLJIT_MOV_U8: @@ -3172,7 +3570,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile case SLJIT_MOV: case SLJIT_MOV_P: #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) - if (type & SLJIT_MEM_ALIGNED_32) { + if (type & SLJIT_MEM_UNALIGNED_32) { flags = WORD_DATA; if (!(type & SLJIT_MEM_STORE)) flags |= LOAD_DATA; @@ -3189,7 +3587,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile } if (mem == reg) { - FAIL_IF(push_inst(compiler, DADDU | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, ADDU_W | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1))); mem = TMP_REG1; } @@ -3206,37 +3604,32 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile return push_inst(compiler, SWR | S(mem) | T(reg) | IMM(memw + 3), MOVABLE_INS); } + if (mem == reg) { + FAIL_IF(push_inst(compiler, ADDU_W | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1))); + mem = TMP_REG1; + } + + FAIL_IF(push_inst(compiler, LWL | S(mem) | T(reg) | IMM(memw), DR(reg))); #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) - if (mem == reg) { - FAIL_IF(push_inst(compiler, ADDU | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1))); - mem = TMP_REG1; - } - - FAIL_IF(push_inst(compiler, LWL | S(mem) | T(reg) | IMM(memw), DR(reg))); return push_inst(compiler, LWR | S(mem) | T(reg) | IMM(memw + 3), DR(reg)); - #else /* !SLJIT_CONFIG_MIPS_32 */ - if (mem == reg) { - FAIL_IF(push_inst(compiler, DADDU | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1))); - mem = TMP_REG1; - } - - FAIL_IF(push_inst(compiler, LWL | S(mem) | T(reg) | IMM(memw), DR(reg))); FAIL_IF(push_inst(compiler, LWR | S(mem) | T(reg) | IMM(memw + 3), DR(reg))); - if (op == SLJIT_MOV_U32) { -#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2) - return push_inst(compiler, DINSU | T(reg) | SA(0) | (31 << 11) | (0 << 11), DR(reg)); -#else /* SLJIT_MIPS_REV < 1 */ - FAIL_IF(push_inst(compiler, DSLL32 | T(reg) | D(reg) | SH_IMM(0), DR(reg))); - return push_inst(compiler, DSRL32 | T(reg) | D(reg) | SH_IMM(0), DR(reg)); -#endif /* SLJIT_MIPS_REV >= 2 */ - } + if (op != SLJIT_MOV_U32) + return SLJIT_SUCCESS; - return SLJIT_SUCCESS; +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2) + return push_inst(compiler, DINSU | T(reg) | SA(0) | (31 << 11) | (0 << 11), DR(reg)); +#else /* SLJIT_MIPS_REV < 1 */ + FAIL_IF(push_inst(compiler, DSLL32 | T(reg) | D(reg) | SH_IMM(0), DR(reg))); + return push_inst(compiler, DSRL32 | T(reg) | D(reg) | SH_IMM(0), DR(reg)); +#endif /* SLJIT_MIPS_REV >= 2 */ #endif /* SLJIT_CONFIG_MIPS_32 */ +#endif /* SLJIT_MIPS_REV >= 6 */ } +#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 freg, sljit_s32 mem, sljit_sw memw) @@ -3244,9 +3637,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil CHECK_ERROR(); CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw)); - if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) - return SLJIT_ERR_UNSUPPORTED; - FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - (type & SLJIT_32) ? 3 : 7)); SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2); @@ -3318,12 +3708,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil return SLJIT_SUCCESS; } +#endif /* !SLJIT_MIPS_REV || SLJIT_MIPS_REV < 6 */ + #undef MEM16_IMM_FIRST #undef MEM16_IMM_SECOND #undef MEMF64_FS_FIRST #undef MEMF64_FS_SECOND - -#endif /* !SLJIT_MIPS_REV || SLJIT_MIPS_REV < 6 */ +#undef MEM_CHECK_UNALIGNED #undef TO_ARGW_HI diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativePPC_32.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativePPC_32.c index 1eb518a6da..25cfcb9072 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativePPC_32.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativePPC_32.c @@ -38,12 +38,15 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS; } +/* Simplified mnemonics: clrlwi. */ #define INS_CLEAR_LEFT(dst, src, from) \ - (RLWINM | S(src) | A(dst) | ((from) << 6) | (31 << 1)) + (RLWINM | S(src) | A(dst) | RLWI_MBE(from, 31)) static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_s32 src1, sljit_s32 src2) { + sljit_u32 imm; + switch (op) { case SLJIT_MOV: case SLJIT_MOV_U32: @@ -82,14 +85,20 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl } return SLJIT_SUCCESS; - case SLJIT_NOT: - SLJIT_ASSERT(src1 == TMP_REG1); - return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2)); - case SLJIT_CLZ: SLJIT_ASSERT(src1 == TMP_REG1); return push_inst(compiler, CNTLZW | S(src2) | A(dst)); + case SLJIT_CTZ: + SLJIT_ASSERT(src1 == TMP_REG1); + FAIL_IF(push_inst(compiler, NEG | D(TMP_REG1) | A(src2))); + FAIL_IF(push_inst(compiler, AND | S(src2) | A(dst) | B(TMP_REG1))); + FAIL_IF(push_inst(compiler, CNTLZW | S(dst) | A(dst))); + FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG1) | A(dst) | IMM(-32))); + /* The highest bits are set, if dst < 32, zero otherwise. */ + FAIL_IF(push_inst(compiler, SRWI(27) | S(TMP_REG1) | A(TMP_REG1))); + return push_inst(compiler, XOR | S(dst) | A(dst) | B(TMP_REG1)); + case SLJIT_ADD: if (flags & ALT_FORM1) { /* Setting XER SO is not enough, CR SO is also needed. */ @@ -103,12 +112,14 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl if (flags & ALT_FORM3) return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm); + imm = compiler->imm; + if (flags & ALT_FORM4) { - FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1)))); + FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((imm >> 16) & 0xffff) + ((imm >> 15) & 0x1)))); src1 = dst; } - return push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff)); + return push_inst(compiler, ADDI | D(dst) | A(src1) | (imm & 0xffff)); } if (flags & ALT_FORM3) { SLJIT_ASSERT(src2 == TMP_REG2); @@ -208,8 +219,10 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl } if (flags & ALT_FORM3) { SLJIT_ASSERT(src2 == TMP_REG2); - FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(compiler->imm))); - return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16)); + imm = compiler->imm; + + FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(imm))); + return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(imm >> 16)); } return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2)); @@ -224,34 +237,82 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl } if (flags & ALT_FORM3) { SLJIT_ASSERT(src2 == TMP_REG2); - FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(compiler->imm))); - return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16)); + imm = compiler->imm; + + FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(imm))); + return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(imm >> 16)); + } + if (flags & ALT_FORM4) { + SLJIT_ASSERT(src1 == TMP_REG1); + return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2)); } return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_SHL: + case SLJIT_MSHL: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2); - compiler->imm &= 0x1f; - return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11) | ((31 - compiler->imm) << 1)); + imm = compiler->imm & 0x1f; + return push_inst(compiler, SLWI(imm) | RC(flags) | S(src1) | A(dst)); } + + if (op == SLJIT_MSHL) { + FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | 0x1f)); + src2 = TMP_REG2; + } + return push_inst(compiler, SLW | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_LSHR: + case SLJIT_MLSHR: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2); - compiler->imm &= 0x1f; - return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (((32 - compiler->imm) & 0x1f) << 11) | (compiler->imm << 6) | (31 << 1)); + imm = compiler->imm & 0x1f; + /* Since imm can be 0, SRWI() cannot be used. */ + return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | RLWI_SH((32 - imm) & 0x1f) | RLWI_MBE(imm, 31)); } + + if (op == SLJIT_MLSHR) { + FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | 0x1f)); + src2 = TMP_REG2; + } + return push_inst(compiler, SRW | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_ASHR: + case SLJIT_MASHR: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2); - compiler->imm &= 0x1f; - return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11)); + imm = compiler->imm & 0x1f; + return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (imm << 11)); } + + if (op == SLJIT_MASHR) { + FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | 0x1f)); + src2 = TMP_REG2; + } + return push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2)); + + case SLJIT_ROTL: + case SLJIT_ROTR: + if (flags & ALT_FORM1) { + SLJIT_ASSERT(src2 == TMP_REG2); + imm = compiler->imm; + + if (op == SLJIT_ROTR) + imm = (sljit_u32)(-(sljit_s32)imm); + + imm &= 0x1f; + return push_inst(compiler, RLWINM | S(src1) | A(dst) | RLWI_SH(imm) | RLWI_MBE(0, 31)); + } + + if (op == SLJIT_ROTR) { + FAIL_IF(push_inst(compiler, SUBFIC | D(TMP_REG2) | A(src2) | 0)); + src2 = TMP_REG2; + } + + return push_inst(compiler, RLWNM | S(src1) | A(dst) | B(src2) | RLWI_MBE(0, 31)); } SLJIT_UNREACHABLE(); @@ -264,6 +325,48 @@ static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_ return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value)); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 freg, sljit_s32 reg) +{ + sljit_s32 reg2 = 0; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg)); + + if (op & SLJIT_32) { + if (op == SLJIT_COPY32_TO_F32) { + FAIL_IF(push_inst(compiler, STW | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET)); + return push_inst(compiler, LFS | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET); + } + + FAIL_IF(push_inst(compiler, STFS | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET)); + return push_inst(compiler, LWZ | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET); + } + + if (reg & REG_PAIR_MASK) { + reg2 = REG_PAIR_SECOND(reg); + reg = REG_PAIR_FIRST(reg); + } + + if (op == SLJIT_COPY_TO_F64) { + FAIL_IF(push_inst(compiler, STW | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI)); + + if (reg2 != 0) + FAIL_IF(push_inst(compiler, STW | S(reg2) | A(SLJIT_SP) | TMP_MEM_OFFSET_LOW)); + else + FAIL_IF(push_inst(compiler, STFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET_LOW)); + + return push_inst(compiler, LFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET); + } + + FAIL_IF(push_inst(compiler, STFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET)); + + if (reg2 != 0) + FAIL_IF(push_inst(compiler, LWZ | S(reg2) | A(SLJIT_SP) | TMP_MEM_OFFSET_LOW)); + + return push_inst(compiler, LWZ | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI); +} + SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) { sljit_ins *inst = (sljit_ins *)addr; diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativePPC_64.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativePPC_64.c index 61491011c4..8d774cf57a 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativePPC_64.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativePPC_64.c @@ -35,8 +35,9 @@ #error "Must implement count leading zeroes" #endif -#define PUSH_RLDICR(reg, shift) \ - push_inst(compiler, RLDI(reg, reg, 63 - shift, shift, 1)) +/* Computes SLDI(63 - shift). */ +#define PUSH_SLDI_NEG(reg, shift) \ + push_inst(compiler, RLDICR | S(reg) | A(reg) | RLDI_SH(63 - shift) | RLDI_ME(shift)) static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm) { @@ -66,14 +67,14 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, if ((tmp & ~0xffff000000000000ul) == 0) { FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48))); shift += 15; - return PUSH_RLDICR(reg, shift); + return PUSH_SLDI_NEG(reg, shift); } if ((tmp & ~0xffffffff00000000ul) == 0) { FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | (sljit_ins)(tmp >> 48))); FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp >> 32))); shift += 31; - return PUSH_RLDICR(reg, shift); + return PUSH_SLDI_NEG(reg, shift); } /* Cut out the 16 bit from immediate. */ @@ -82,13 +83,13 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, if (tmp2 <= 0xffff) { FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48))); - FAIL_IF(PUSH_RLDICR(reg, shift)); + FAIL_IF(PUSH_SLDI_NEG(reg, shift)); return push_inst(compiler, ORI | S(reg) | A(reg) | (sljit_ins)tmp2); } if (tmp2 <= 0xffffffff) { FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48))); - FAIL_IF(PUSH_RLDICR(reg, shift)); + FAIL_IF(PUSH_SLDI_NEG(reg, shift)); FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | (sljit_ins)(tmp2 >> 16))); return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp2)) : SLJIT_SUCCESS; } @@ -100,22 +101,23 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48))); shift2 += 15; shift += (63 - shift2); - FAIL_IF(PUSH_RLDICR(reg, shift)); + FAIL_IF(PUSH_SLDI_NEG(reg, shift)); FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | (sljit_ins)(tmp2 >> 48))); - return PUSH_RLDICR(reg, shift2); + return PUSH_SLDI_NEG(reg, shift2); } /* The general version. */ FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | (sljit_ins)((sljit_uw)imm >> 48))); FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm >> 32))); - FAIL_IF(PUSH_RLDICR(reg, 31)); + FAIL_IF(PUSH_SLDI_NEG(reg, 31)); FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(imm >> 16))); return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)); } -/* Simplified mnemonics: clrldi. */ -#define INS_CLEAR_LEFT(dst, src, from) \ - (RLDICL | S(src) | A(dst) | ((from) << 6) | (1 << 5)) +#undef PUSH_SLDI_NEG + +#define CLRLDI(dst, src, n) \ + (RLDICL | S(src) | A(dst) | RLDI_SH(0) | RLDI_MB(n)) /* Sign extension for integer operations. */ #define UN_EXTS() \ @@ -145,6 +147,8 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_s32 src1, sljit_s32 src2) { + sljit_u32 imm; + switch (op) { case SLJIT_MOV: case SLJIT_MOV_P: @@ -159,7 +163,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { if (op == SLJIT_MOV_S32) return push_inst(compiler, EXTSW | S(src2) | A(dst)); - return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 0)); + return push_inst(compiler, CLRLDI(dst, src2, 32)); } else { SLJIT_ASSERT(dst == src2); @@ -172,7 +176,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { if (op == SLJIT_MOV_S8) return push_inst(compiler, EXTSB | S(src2) | A(dst)); - return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24)); + return push_inst(compiler, CLRLDI(dst, src2, 56)); } else if ((flags & REG_DEST) && op == SLJIT_MOV_S8) return push_inst(compiler, EXTSB | S(src2) | A(dst)); @@ -187,36 +191,39 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { if (op == SLJIT_MOV_S16) return push_inst(compiler, EXTSH | S(src2) | A(dst)); - return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16)); + return push_inst(compiler, CLRLDI(dst, src2, 48)); } else { SLJIT_ASSERT(dst == src2); } return SLJIT_SUCCESS; - case SLJIT_NOT: - SLJIT_ASSERT(src1 == TMP_REG1); - UN_EXTS(); - return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2)); - case SLJIT_CLZ: SLJIT_ASSERT(src1 == TMP_REG1); - if (flags & ALT_FORM1) - return push_inst(compiler, CNTLZW | S(src2) | A(dst)); - return push_inst(compiler, CNTLZD | S(src2) | A(dst)); + return push_inst(compiler, ((flags & ALT_FORM1) ? CNTLZW : CNTLZD) | S(src2) | A(dst)); + + case SLJIT_CTZ: + SLJIT_ASSERT(src1 == TMP_REG1); + FAIL_IF(push_inst(compiler, NEG | D(TMP_REG1) | A(src2))); + FAIL_IF(push_inst(compiler, AND | S(src2) | A(dst) | B(TMP_REG1))); + FAIL_IF(push_inst(compiler, ((flags & ALT_FORM1) ? CNTLZW : CNTLZD) | S(dst) | A(dst))); + FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG1) | A(dst) | IMM((flags & ALT_FORM1) ? -32 : -64))); + /* The highest bits are set, if dst < bit width, zero otherwise. */ + FAIL_IF(push_inst(compiler, ((flags & ALT_FORM1) ? SRWI(27) : SRDI(58)) | S(TMP_REG1) | A(TMP_REG1))); + return push_inst(compiler, XOR | S(dst) | A(dst) | B(TMP_REG1)); case SLJIT_ADD: if (flags & ALT_FORM1) { if (flags & ALT_SIGN_EXT) { - FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, src1, 32, 31, 1))); + FAIL_IF(push_inst(compiler, SLDI(32) | S(src1) | A(TMP_REG1))); src1 = TMP_REG1; - FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1))); + FAIL_IF(push_inst(compiler, SLDI(32) | S(src2) | A(TMP_REG2))); src2 = TMP_REG2; } /* Setting XER SO is not enough, CR SO is also needed. */ FAIL_IF(push_inst(compiler, ADD | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2))); if (flags & ALT_SIGN_EXT) - return push_inst(compiler, RLDI(dst, dst, 32, 32, 0)); + return push_inst(compiler, SRDI(32) | S(dst) | A(dst)); return SLJIT_SUCCESS; } @@ -227,12 +234,14 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl if (flags & ALT_FORM3) return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm); + imm = compiler->imm; + if (flags & ALT_FORM4) { - FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1)))); + FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((imm >> 16) & 0xffff) + ((imm >> 15) & 0x1)))); src1 = dst; } - return push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff)); + return push_inst(compiler, ADDI | D(dst) | A(src1) | (imm & 0xffff)); } if (flags & ALT_FORM3) { SLJIT_ASSERT(src2 == TMP_REG2); @@ -287,11 +296,11 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl if (flags & ALT_FORM3) { if (flags & ALT_SIGN_EXT) { if (src1 != TMP_ZERO) { - FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, src1, 32, 31, 1))); + FAIL_IF(push_inst(compiler, SLDI(32) | S(src1) | A(TMP_REG1))); src1 = TMP_REG1; } if (src2 != TMP_ZERO) { - FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1))); + FAIL_IF(push_inst(compiler, SLDI(32) | S(src2) | A(TMP_REG2))); src2 = TMP_REG2; } } @@ -303,7 +312,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl FAIL_IF(push_inst(compiler, NEG | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2))); if (flags & ALT_SIGN_EXT) - return push_inst(compiler, RLDI(dst, dst, 32, 32, 0)); + return push_inst(compiler, SRDI(32) | S(dst) | A(dst)); return SLJIT_SUCCESS; } @@ -362,8 +371,10 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl } if (flags & ALT_FORM3) { SLJIT_ASSERT(src2 == TMP_REG2); - FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(compiler->imm))); - return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16)); + imm = compiler->imm; + + FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(imm))); + return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(imm >> 16)); } return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2)); @@ -378,46 +389,110 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl } if (flags & ALT_FORM3) { SLJIT_ASSERT(src2 == TMP_REG2); - FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(compiler->imm))); - return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16)); + imm = compiler->imm; + + FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(imm))); + return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(imm >> 16)); + } + if (flags & ALT_FORM4) { + SLJIT_ASSERT(src1 == TMP_REG1); + UN_EXTS(); + return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2)); } return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_SHL: + case SLJIT_MSHL: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2); + imm = compiler->imm; + if (flags & ALT_FORM2) { - compiler->imm &= 0x1f; - return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11) | ((31 - compiler->imm) << 1)); + imm &= 0x1f; + return push_inst(compiler, SLWI(imm) | RC(flags) | S(src1) | A(dst)); } - compiler->imm &= 0x3f; - return push_inst(compiler, RLDI(dst, src1, compiler->imm, 63 - compiler->imm, 1) | RC(flags)); + + imm &= 0x3f; + return push_inst(compiler, SLDI(imm) | RC(flags) | S(src1) | A(dst)); } + + if (op == SLJIT_MSHL) { + FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | ((flags & ALT_FORM2) ? 0x1f : 0x3f))); + src2 = TMP_REG2; + } + return push_inst(compiler, ((flags & ALT_FORM2) ? SLW : SLD) | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_LSHR: + case SLJIT_MLSHR: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2); + imm = compiler->imm; + if (flags & ALT_FORM2) { - compiler->imm &= 0x1f; - return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (((32 - compiler->imm) & 0x1f) << 11) | (compiler->imm << 6) | (31 << 1)); + imm &= 0x1f; + /* Since imm can be 0, SRWI() cannot be used. */ + return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | RLWI_SH((32 - imm) & 0x1f) | RLWI_MBE(imm, 31)); } - compiler->imm &= 0x3f; - return push_inst(compiler, RLDI(dst, src1, 64 - compiler->imm, compiler->imm, 0) | RC(flags)); + + imm &= 0x3f; + /* Since imm can be 0, SRDI() cannot be used. */ + return push_inst(compiler, RLDICL | RC(flags) | S(src1) | A(dst) | RLDI_SH((64 - imm) & 0x3f) | RLDI_MB(imm)); } + + if (op == SLJIT_MLSHR) { + FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | ((flags & ALT_FORM2) ? 0x1f : 0x3f))); + src2 = TMP_REG2; + } + return push_inst(compiler, ((flags & ALT_FORM2) ? SRW : SRD) | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_ASHR: + case SLJIT_MASHR: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2); + imm = compiler->imm; + if (flags & ALT_FORM2) { - compiler->imm &= 0x1f; - return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11)); + imm &= 0x1f; + return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (imm << 11)); } - compiler->imm &= 0x3f; - return push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | ((compiler->imm & 0x1f) << 11) | ((compiler->imm & 0x20) >> 4)); + + imm &= 0x3f; + return push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | RLDI_SH(imm)); } + + if (op == SLJIT_MASHR) { + FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | ((flags & ALT_FORM2) ? 0x1f : 0x3f))); + src2 = TMP_REG2; + } + return push_inst(compiler, ((flags & ALT_FORM2) ? SRAW : SRAD) | RC(flags) | S(src1) | A(dst) | B(src2)); + + case SLJIT_ROTL: + case SLJIT_ROTR: + if (flags & ALT_FORM1) { + SLJIT_ASSERT(src2 == TMP_REG2); + imm = compiler->imm; + + if (op == SLJIT_ROTR) + imm = (sljit_u32)(-(sljit_s32)imm); + + if (flags & ALT_FORM2) { + imm &= 0x1f; + return push_inst(compiler, RLWINM | S(src1) | A(dst) | RLWI_SH(imm) | RLWI_MBE(0, 31)); + } + + imm &= 0x3f; + return push_inst(compiler, RLDICL | S(src1) | A(dst) | RLDI_SH(imm)); + } + + if (op == SLJIT_ROTR) { + FAIL_IF(push_inst(compiler, SUBFIC | D(TMP_REG2) | A(src2) | 0)); + src2 = TMP_REG2; + } + + return push_inst(compiler, ((flags & ALT_FORM2) ? (RLWNM | RLWI_MBE(0, 31)) : (RLDCL | RLDI_MB(0))) | S(src1) | A(dst) | B(src2)); } SLJIT_UNREACHABLE(); @@ -483,11 +558,26 @@ static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_ { FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 48))); FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value >> 32))); - FAIL_IF(PUSH_RLDICR(reg, 31)); + FAIL_IF(push_inst(compiler, SLDI(32) | S(reg) | A(reg))); FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(init_value >> 16))); return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value)); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 freg, sljit_s32 reg) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg)); + + if (GET_OPCODE(op) == SLJIT_COPY_TO_F64) { + FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? STW : STD) | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET)); + return push_inst(compiler, ((op & SLJIT_32) ? LFS : LFD) | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET); + } + + FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? STFS : STFD) | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET)); + return push_inst(compiler, ((op & SLJIT_32) ? LWZ : LD) | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET); +} + SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) { sljit_ins *inst = (sljit_ins*)addr; diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativePPC_common.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativePPC_common.c index 719e772bc4..81ba7d36b0 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativePPC_common.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativePPC_common.c @@ -183,6 +183,8 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define FSUBS (HI(59) | LO(20)) #define LD (HI(58) | 0) #define LFD (HI(50)) +#define LFS (HI(48)) +#define LWBRX (HI(31) | LO(534)) #define LWZ (HI(32)) #define MFCR (HI(31) | LO(19)) #define MFLR (HI(31) | LO(339) | 0x80000) @@ -203,8 +205,13 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define OR (HI(31) | LO(444)) #define ORI (HI(24)) #define ORIS (HI(25)) -#define RLDICL (HI(30)) +#define RLDCL (HI(30) | LO(8)) +#define RLDICL (HI(30) | LO(0 << 1)) +#define RLDICR (HI(30) | LO(1 << 1)) +#define RLDIMI (HI(30) | LO(3 << 1)) +#define RLWIMI (HI(20)) #define RLWINM (HI(21)) +#define RLWNM (HI(23)) #define SLD (HI(31) | LO(27)) #define SLW (HI(31) | LO(24)) #define SRAD (HI(31) | LO(794)) @@ -218,7 +225,9 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define STDUX (HI(31) | LO(181)) #define STFD (HI(54)) #define STFIWX (HI(31) | LO(983)) +#define STFS (HI(52)) #define STW (HI(36)) +#define STWBRX (HI(31) | LO(662)) #define STWU (HI(37)) #define STWUX (HI(31) | LO(183)) #define SUBF (HI(31) | LO(40)) @@ -233,9 +242,34 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define SIMM_MIN (-0x8000) #define UIMM_MAX (0xffff) -#define RLDI(dst, src, sh, mb, type) \ - (HI(30) | S(src) | A(dst) | ((sljit_ins)(type) << 2) | (((sljit_ins)(sh) & 0x1f) << 11) \ - | (((sljit_ins)(sh) & 0x20) >> 4) | (((sljit_ins)(mb) & 0x1f) << 6) | ((sljit_ins)(mb) & 0x20)) +/* Shift helpers. */ +#define RLWI_SH(sh) ((sljit_ins)(sh) << 11) +#define RLWI_MBE(mb, me) (((sljit_ins)(mb) << 6) | ((sljit_ins)(me) << 1)) +#define RLDI_SH(sh) ((((sljit_ins)(sh) & 0x1f) << 11) | (((sljit_ins)(sh) & 0x20) >> 4)) +#define RLDI_MB(mb) ((((sljit_ins)(mb) & 0x1f) << 6) | ((sljit_ins)(mb) & 0x20)) +#define RLDI_ME(me) RLDI_MB(me) + +#define SLWI(shift) (RLWINM | RLWI_SH(shift) | RLWI_MBE(0, 31 - (shift))) +#define SLDI(shift) (RLDICR | RLDI_SH(shift) | RLDI_ME(63 - (shift))) +/* shift > 0 */ +#define SRWI(shift) (RLWINM | RLWI_SH(32 - (shift)) | RLWI_MBE((shift), 31)) +#define SRDI(shift) (RLDICL | RLDI_SH(64 - (shift)) | RLDI_MB(shift)) + +#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) +#define SLWI_W(shift) SLWI(shift) +#define TMP_MEM_OFFSET (2 * sizeof(sljit_sw)) +#else /* !SLJIT_CONFIG_PPC_32 */ +#define SLWI_W(shift) SLDI(shift) +#define TMP_MEM_OFFSET (6 * sizeof(sljit_sw)) +#endif /* SLJIT_CONFIG_PPC_32 */ + +#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN) +#define TMP_MEM_OFFSET_LOW TMP_MEM_OFFSET +#define TMP_MEM_OFFSET_HI (TMP_MEM_OFFSET + sizeof(sljit_s32)) +#else /* !SLJIT_LITTLE_ENDIAN */ +#define TMP_MEM_OFFSET_LOW (TMP_MEM_OFFSET + sizeof(sljit_s32)) +#define TMP_MEM_OFFSET_HI TMP_MEM_OFFSET +#endif /* SLJIT_LITTLE_ENDIAN */ #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_uw addr, void* func) @@ -371,7 +405,7 @@ static SLJIT_INLINE void put_label_set(struct sljit_put_label *put_label) inst++; } - inst[1] = RLDI(reg, reg, 32, 31, 1); + inst[1] = SLDI(32) | S(reg) | A(reg); inst[2] = ORIS | S(reg) | A(reg) | IMM((addr >> 16) & 0xffff); inst += 2; } @@ -379,7 +413,7 @@ static SLJIT_INLINE void put_label_set(struct sljit_put_label *put_label) inst[1] = ORI | S(reg) | A(reg) | IMM(addr & 0xffff); } -#endif +#endif /* SLJIT_CONFIG_PPC_64 */ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) { @@ -641,9 +675,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) /* A saved register is set to a zero value. */ case SLJIT_HAS_ZERO_REGISTER: case SLJIT_HAS_CLZ: + case SLJIT_HAS_ROT: case SLJIT_HAS_PREFETCH: return 1; + case SLJIT_HAS_CTZ: + case SLJIT_HAS_REV: + return 2; + default: return 0; } @@ -713,13 +752,16 @@ ALT_FORM5 0x010000 */ #endif #if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2) -#define LR_SAVE_OFFSET 2 * SSIZE_OF(sw) +#define LR_SAVE_OFFSET (2 * SSIZE_OF(sw)) #else #define LR_SAVE_OFFSET SSIZE_OF(sw) #endif #define STACK_MAX_DISTANCE (0x8000 - SSIZE_OF(sw) - LR_SAVE_OFFSET) +static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg, + sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg); + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) @@ -736,7 +778,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 0) - + GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64)); + + GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64); if (!(options & SLJIT_ENTER_REG_ARG)) local_size += SSIZE_OF(sw); @@ -846,7 +888,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 0) - + GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64)); + + GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64); if (!(options & SLJIT_ENTER_REG_ARG)) local_size += SSIZE_OF(sw); @@ -855,7 +897,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp return SLJIT_SUCCESS; } -static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) +static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to) { sljit_s32 i, tmp, base, offset; sljit_s32 local_size = compiler->local_size; @@ -873,7 +915,8 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) } offset = local_size; - FAIL_IF(push_inst(compiler, STACK_LOAD | S(0) | A(base) | IMM(offset + LR_SAVE_OFFSET))); + if (!is_return_to) + FAIL_IF(push_inst(compiler, STACK_LOAD | S(0) | A(base) | IMM(offset + LR_SAVE_OFFSET))); tmp = SLJIT_FS0 - compiler->fsaveds; for (i = SLJIT_FS0; i > tmp; i--) { @@ -902,7 +945,8 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) FAIL_IF(push_inst(compiler, STACK_LOAD | S(i) | A(base) | IMM(offset))); } - push_inst(compiler, MTLR | S(0)); + if (!is_return_to) + push_inst(compiler, MTLR | S(0)); if (local_size > 0) return push_inst(compiler, ADDI | D(SLJIT_SP) | A(base) | IMM(local_size)); @@ -911,17 +955,40 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) return push_inst(compiler, OR | S(base) | A(SLJIT_SP) | B(base)); } +#undef STACK_STORE +#undef STACK_LOAD + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler) { CHECK_ERROR(); CHECK(check_sljit_emit_return_void(compiler)); - FAIL_IF(emit_stack_frame_release(compiler)); + FAIL_IF(emit_stack_frame_release(compiler, 0)); return push_inst(compiler, BLR); } -#undef STACK_STORE -#undef STACK_LOAD +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_return_to(compiler, src, srcw)); + + if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_CALL_REG, src, srcw, TMP_CALL_REG)); + src = TMP_CALL_REG; + srcw = 0; + } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { + FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src))); + src = TMP_CALL_REG; + srcw = 0; + } + + FAIL_IF(emit_stack_frame_release(compiler, 1)); + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw); +} /* --------------------------------------------------------------------- */ /* Operators */ @@ -1087,7 +1154,6 @@ static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flag { sljit_ins inst; sljit_s32 offs_reg; - sljit_sw high_short; /* Should work when (arg & REG_MASK) == 0. */ SLJIT_ASSERT(A(0) == 0); @@ -1098,11 +1164,7 @@ static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flag offs_reg = OFFS_REG(arg); if (argw != 0) { -#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) - FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(arg)) | A(tmp_reg) | ((sljit_ins)argw << 11) | ((31 - (sljit_ins)argw) << 1))); -#else - FAIL_IF(push_inst(compiler, RLDI(tmp_reg, OFFS_REG(arg), argw, 63 - argw, 1))); -#endif + FAIL_IF(push_inst(compiler, SLWI_W(argw) | S(OFFS_REG(arg)) | A(tmp_reg))); offs_reg = tmp_reg; } @@ -1110,7 +1172,7 @@ static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flag #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) SLJIT_ASSERT(!(inst & INT_ALIGNED)); -#endif +#endif /* SLJIT_CONFIG_PPC_64 */ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(offs_reg)); } @@ -1125,36 +1187,24 @@ static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flag inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK]; return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg)); } -#endif +#endif /* SLJIT_CONFIG_PPC_64 */ if (argw <= SIMM_MAX && argw >= SIMM_MIN) return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | IMM(argw)); #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) if (argw <= 0x7fff7fffl && argw >= -0x80000000l) { -#endif - - high_short = (sljit_s32)(argw + ((argw & 0x8000) << 1)) & ~0xffff; - -#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) - SLJIT_ASSERT(high_short && high_short <= 0x7fffffffl && high_short >= -0x80000000l); -#else - SLJIT_ASSERT(high_short); -#endif - - FAIL_IF(push_inst(compiler, ADDIS | D(tmp_reg) | A(arg) | IMM(high_short >> 16))); +#endif /* SLJIT_CONFIG_PPC_64 */ + FAIL_IF(push_inst(compiler, ADDIS | D(tmp_reg) | A(arg) | IMM((argw + 0x8000) >> 16))); return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(tmp_reg) | IMM(argw)); - #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) } - /* The rest is PPC-64 only. */ - FAIL_IF(load_immediate(compiler, tmp_reg, argw)); inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK]; return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg)); -#endif +#endif /* SLJIT_CONFIG_PPC_64 */ } static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 input_flags, @@ -1277,29 +1327,94 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile return SLJIT_SUCCESS; } -static sljit_s32 emit_prefetch(struct sljit_compiler *compiler, - sljit_s32 src, sljit_sw srcw) +static sljit_s32 emit_rev(struct sljit_compiler *compiler, sljit_s32 op_flags, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) { - if (!(src & OFFS_REG_MASK)) { - if (srcw == 0 && (src & REG_MASK)) - return push_inst(compiler, DCBT | A(0) | B(src & REG_MASK)); + sljit_s32 mem, offs_reg, inp_flags; + sljit_sw memw; + SLJIT_UNUSED_ARG(op_flags); - FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); - /* Works with SLJIT_MEM0() case as well. */ - return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1)); + if (!((dst | src) & SLJIT_MEM)) { + /* Both are registers. */ +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + if (!(op_flags & SLJIT_32)) { + FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(0) | IMM(TMP_MEM_OFFSET_HI))); + FAIL_IF(push_inst(compiler, RLDICL | S(src) | A(TMP_REG1) | RLDI_SH(32) | RLDI_MB(32))); + FAIL_IF(push_inst(compiler, STWBRX | S(src) | A(SLJIT_SP) | B(TMP_REG2))); + FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(0) | IMM(TMP_MEM_OFFSET_LOW))); + FAIL_IF(push_inst(compiler, STWBRX | S(TMP_REG1) | A(SLJIT_SP) | B(TMP_REG2))); + return push_inst(compiler, LD | D(dst) | A(SLJIT_SP) | TMP_MEM_OFFSET); + } +#endif /* SLJIT_CONFIG_PPC_64 */ + + FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(0) | IMM(TMP_MEM_OFFSET))); + FAIL_IF(push_inst(compiler, STWBRX | S(src) | A(SLJIT_SP) | B(TMP_REG2))); + return push_inst(compiler, LWZ | D(dst) | A(SLJIT_SP) | TMP_MEM_OFFSET); } - srcw &= 0x3; + mem = src; + memw = srcw; - if (srcw == 0) - return push_inst(compiler, DCBT | A(src & REG_MASK) | B(OFFS_REG(src))); + if (dst & SLJIT_MEM) { + mem = dst; + memw = dstw; -#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) - FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(src)) | A(TMP_REG1) | ((sljit_ins)srcw << 11) | ((31 - (sljit_ins)srcw) << 1))); -#else - FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, OFFS_REG(src), srcw, 63 - srcw, 1))); -#endif - return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1)); + if (src & SLJIT_MEM) { +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + inp_flags = ((op_flags & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA; +#else /* !SLJIT_CONFIG_PPC_64 */ + inp_flags = WORD_DATA | LOAD_DATA; +#endif /* SLJIT_CONFIG_PPC_64 */ + FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG1, src, srcw, TMP_REG2)); + src = TMP_REG1; + } + } + + if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) { + offs_reg = OFFS_REG(mem); + mem &= REG_MASK; + memw &= 0x3; + + if (memw != 0) { + FAIL_IF(push_inst(compiler, SLWI_W(memw) | S(offs_reg) | A(TMP_REG2))); + offs_reg = TMP_REG2; + } +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + } else if (memw > 0x7fff7fffl || memw < -0x80000000l) { + FAIL_IF(load_immediate(compiler, TMP_REG2, memw)); + offs_reg = TMP_REG2; + mem &= REG_MASK; +#endif /* SLJIT_CONFIG_PPC_64 */ + } else { + FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(mem & REG_MASK) | IMM(memw))); + if (memw > SIMM_MAX || memw < SIMM_MIN) + FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(TMP_REG2) | IMM((memw + 0x8000) >> 16))); + + mem = 0; + offs_reg = TMP_REG2; + } + +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + if (!(op_flags & SLJIT_32)) { + if (dst & SLJIT_MEM) { + FAIL_IF(push_inst(compiler, STWBRX | S(src) | A(mem) | B(offs_reg))); + FAIL_IF(push_inst(compiler, RLDICL | S(src) | A(TMP_REG1) | RLDI_SH(32) | RLDI_MB(32))); + FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(offs_reg) | IMM(SSIZE_OF(s32)))); + return push_inst(compiler, STWBRX | S(TMP_REG1) | A(mem) | B(TMP_REG2)); + } + + FAIL_IF(push_inst(compiler, LWBRX | S(dst) | A(mem) | B(offs_reg))); + FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(offs_reg) | IMM(SSIZE_OF(s32)))); + FAIL_IF(push_inst(compiler, LWBRX | S(TMP_REG1) | A(mem) | B(TMP_REG2))); + return push_inst(compiler, RLDIMI | S(TMP_REG1) | A(dst) | RLDI_SH(32) | RLDI_MB(0)); + } +#endif /* SLJIT_CONFIG_PPC_64 */ + + if (dst & SLJIT_MEM) + return push_inst(compiler, STWBRX | S(src) | A(mem) | B(offs_reg)); + + return push_inst(compiler, LWBRX | S(dst) | A(mem) | B(offs_reg)); } #define EMIT_MOV(type, type_flags, type_cast) \ @@ -1322,14 +1437,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile if (GET_FLAG_TYPE(op_flags) == SLJIT_OVERFLOW) FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO))); - if (op < SLJIT_NOT && FAST_IS_REG(src) && src == dst) { + if (op <= SLJIT_MOV_P && FAST_IS_REG(src) && src == dst) { if (!TYPE_CAST_NEEDED(op)) return SLJIT_SUCCESS; } #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) if (op_flags & SLJIT_32) { - if (op < SLJIT_NOT) { + if (op <= SLJIT_MOV_P) { if (src & SLJIT_MEM) { if (op == SLJIT_MOV_S32) op = SLJIT_MOV_U32; @@ -1379,15 +1494,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile case SLJIT_MOV_S16: return EMIT_MOV(SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, (sljit_s16)); - case SLJIT_NOT: - return emit_op(compiler, SLJIT_NOT, flags, dst, dstw, TMP_REG1, 0, src, srcw); - case SLJIT_CLZ: + case SLJIT_CTZ: #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) - return emit_op(compiler, SLJIT_CLZ, flags | (!(op_flags & SLJIT_32) ? 0 : ALT_FORM1), dst, dstw, TMP_REG1, 0, src, srcw); + return emit_op(compiler, op, flags | (!(op_flags & SLJIT_32) ? 0 : ALT_FORM1), dst, dstw, TMP_REG1, 0, src, srcw); #else - return emit_op(compiler, SLJIT_CLZ, flags, dst, dstw, TMP_REG1, 0, src, srcw); + return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw); #endif + case SLJIT_REV: + return emit_rev(compiler, op_flags, dst, dstw, src, srcw); } return SLJIT_SUCCESS; @@ -1533,7 +1648,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0); } } - return emit_op(compiler, SLJIT_ADD, flags | ((GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w); + return emit_op(compiler, SLJIT_ADD, flags | ((GET_FLAG_TYPE(op) == SLJIT_CARRY) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w); case SLJIT_ADDC: compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD; @@ -1600,7 +1715,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile } /* We know ALT_SIGN_EXT is set if it is an SLJIT_32 on 64 bit systems. */ - return emit_op(compiler, SLJIT_SUB, flags | ((GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w); + return emit_op(compiler, SLJIT_SUB, flags | ((GET_FLAG_TYPE(op) == SLJIT_CARRY) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w); case SLJIT_SUBC: compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB; @@ -1625,9 +1740,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO))); return emit_op(compiler, SLJIT_MUL, flags, dst, dstw, src1, src1w, src2, src2w); + case SLJIT_XOR: + if ((src2 & SLJIT_IMM) && src2w == -1) { + return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM4, dst, dstw, TMP_REG1, 0, src1, src1w); + } + if ((src1 & SLJIT_IMM) && src1w == -1) { + return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM4, dst, dstw, TMP_REG1, 0, src2, src2w); + } + /* fallthrough */ case SLJIT_AND: case SLJIT_OR: - case SLJIT_XOR: /* Commutative unsigned operations. */ if (!HAS_FLAGS(op) || GET_OPCODE(op) == SLJIT_AND) { if (TEST_UL_IMM(src2, src2w)) { @@ -1661,8 +1783,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w); case SLJIT_SHL: + case SLJIT_MSHL: case SLJIT_LSHR: + case SLJIT_MLSHR: case SLJIT_ASHR: + case SLJIT_MASHR: + case SLJIT_ROTL: + case SLJIT_ROTR: #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) if (op & SLJIT_32) flags |= ALT_FORM2; @@ -1692,6 +1819,115 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil #undef TEST_SUB_FORM2 #undef TEST_SUB_FORM3 +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst_reg, + sljit_s32 src1_reg, + sljit_s32 src2_reg, + sljit_s32 src3, sljit_sw src3w) +{ + sljit_s32 is_right; +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + sljit_s32 inp_flags = ((op & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA; + sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64; +#else /* !SLJIT_CONFIG_PPC_64 */ + sljit_s32 inp_flags = WORD_DATA | LOAD_DATA; + sljit_sw bit_length = 32; +#endif /* SLJIT_CONFIG_PPC_64 */ + + CHECK_ERROR(); + CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w)); + + is_right = (GET_OPCODE(op) == SLJIT_LSHR || GET_OPCODE(op) == SLJIT_MLSHR); + + if (src1_reg == src2_reg) { + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_op2(compiler, (is_right ? SLJIT_ROTR : SLJIT_ROTL) | (op & SLJIT_32), dst_reg, 0, src1_reg, 0, src3, src3w); + } + + ADJUST_LOCAL_OFFSET(src3, src3w); + + if (src3 & SLJIT_IMM) { + src3w &= bit_length - 1; + + if (src3w == 0) + return SLJIT_SUCCESS; + +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + if (!(op & SLJIT_32)) { + if (is_right) { + FAIL_IF(push_inst(compiler, SRDI(src3w) | S(src1_reg) | A(dst_reg))); + return push_inst(compiler, RLDIMI | S(src2_reg) | A(dst_reg) | RLDI_SH(64 - src3w) | RLDI_MB(0)); + } + + FAIL_IF(push_inst(compiler, SLDI(src3w) | S(src1_reg) | A(dst_reg))); + /* Computes SRDI(64 - src2w). */ + FAIL_IF(push_inst(compiler, RLDICL | S(src2_reg) | A(TMP_REG1) | RLDI_SH(src3w) | RLDI_MB(64 - src3w))); + return push_inst(compiler, OR | S(dst_reg) | A(dst_reg) | B(TMP_REG1)); + } +#endif /* SLJIT_CONFIG_PPC_64 */ + + if (is_right) { + FAIL_IF(push_inst(compiler, SRWI(src3w) | S(src1_reg) | A(dst_reg))); + return push_inst(compiler, RLWIMI | S(src2_reg) | A(dst_reg) | RLWI_SH(32 - src3w) | RLWI_MBE(0, src3w - 1)); + } + + FAIL_IF(push_inst(compiler, SLWI(src3w) | S(src1_reg) | A(dst_reg))); + return push_inst(compiler, RLWIMI | S(src2_reg) | A(dst_reg) | RLWI_SH(src3w) | RLWI_MBE(32 - src3w, 31)); + } + + if (src3 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG2, src3, src3w, TMP_REG2)); + src3 = TMP_REG2; + } + +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + if (!(op & SLJIT_32)) { + if (GET_OPCODE(op) == SLJIT_MSHL || GET_OPCODE(op) == SLJIT_MLSHR || dst_reg == src3) { + FAIL_IF(push_inst(compiler, ANDI | S(src3) | A(TMP_REG2) | 0x3f)); + src3 = TMP_REG2; + } + + FAIL_IF(push_inst(compiler, (is_right ? SRD : SLD) | S(src1_reg) | A(dst_reg) | B(src3))); + FAIL_IF(push_inst(compiler, (is_right ? SLDI(1) : SRDI(1)) | S(src2_reg) | A(TMP_REG1))); + FAIL_IF(push_inst(compiler, XORI | S(src3) | A(TMP_REG2) | 0x3f)); + FAIL_IF(push_inst(compiler, (is_right ? SLD : SRD) | S(TMP_REG1) | A(TMP_REG1) | B(TMP_REG2))); + return push_inst(compiler, OR | S(dst_reg) | A(dst_reg) | B(TMP_REG1)); + } +#endif /* SLJIT_CONFIG_PPC_64 */ + + if (GET_OPCODE(op) == SLJIT_MSHL || GET_OPCODE(op) == SLJIT_MLSHR || dst_reg == src3) { + FAIL_IF(push_inst(compiler, ANDI | S(src3) | A(TMP_REG2) | 0x1f)); + src3 = TMP_REG2; + } + + FAIL_IF(push_inst(compiler, (is_right ? SRW : SLW) | S(src1_reg) | A(dst_reg) | B(src3))); + FAIL_IF(push_inst(compiler, (is_right ? SLWI(1) : SRWI(1)) | S(src2_reg) | A(TMP_REG1))); + FAIL_IF(push_inst(compiler, XORI | S(src3) | A(TMP_REG2) | 0x1f)); + FAIL_IF(push_inst(compiler, (is_right ? SLW : SRW) | S(TMP_REG1) | A(TMP_REG1) | B(TMP_REG2))); + return push_inst(compiler, OR | S(dst_reg) | A(dst_reg) | B(TMP_REG1)); +} + +static sljit_s32 emit_prefetch(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw) +{ + if (!(src & OFFS_REG_MASK)) { + if (srcw == 0 && (src & REG_MASK)) + return push_inst(compiler, DCBT | A(0) | B(src & REG_MASK)); + + FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); + /* Works with SLJIT_MEM0() case as well. */ + return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1)); + } + + srcw &= 0x3; + + if (srcw == 0) + return push_inst(compiler, DCBT | A(src & REG_MASK) | B(OFFS_REG(src))); + + FAIL_IF(push_inst(compiler, SLWI_W(srcw) | S(OFFS_REG(src)) | A(TMP_REG1))); + return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1)); +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { @@ -1704,7 +1940,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *comp if (FAST_IS_REG(src)) FAIL_IF(push_inst(compiler, MTLR | S(src))); else { - FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw)); + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src, srcw, TMP_REG2)); FAIL_IF(push_inst(compiler, MTLR | S(TMP_REG2))); } @@ -1721,6 +1957,34 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *comp return SLJIT_SUCCESS; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw) +{ + sljit_s32 dst_r; + + CHECK_ERROR(); + CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw)); + ADJUST_LOCAL_OFFSET(dst, dstw); + + switch (op) { + case SLJIT_FAST_ENTER: + if (FAST_IS_REG(dst)) + return push_inst(compiler, MFLR | D(dst)); + + FAIL_IF(push_inst(compiler, MFLR | D(TMP_REG1))); + break; + case SLJIT_GET_RETURN_ADDRESS: + dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst_r, SLJIT_MEM1(SLJIT_SP), compiler->local_size + LR_SAVE_OFFSET, TMP_REG2)); + break; + } + + if (dst & SLJIT_MEM) + return emit_op_mem(compiler, WORD_DATA, TMP_REG1, dst, dstw, TMP_REG2); + + return SLJIT_SUCCESS; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_register_index(reg)); @@ -1749,21 +2013,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c #define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 6)) #define SELECT_FOP(op, single, double) ((sljit_ins)((op & SLJIT_32) ? single : double)) -#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) -#define FLOAT_TMP_MEM_OFFSET (6 * sizeof(sljit_sw)) -#else -#define FLOAT_TMP_MEM_OFFSET (2 * sizeof(sljit_sw)) - -#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN) -#define FLOAT_TMP_MEM_OFFSET_LOW (2 * sizeof(sljit_sw)) -#define FLOAT_TMP_MEM_OFFSET_HI (3 * sizeof(sljit_sw)) -#else -#define FLOAT_TMP_MEM_OFFSET_LOW (3 * sizeof(sljit_sw)) -#define FLOAT_TMP_MEM_OFFSET_HI (2 * sizeof(sljit_sw)) -#endif - -#endif /* SLJIT_CONFIG_PPC_64 */ - static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) @@ -1780,19 +2029,19 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp if (op == SLJIT_CONV_SW_FROM_F64) { if (FAST_IS_REG(dst)) { - FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1)); - return emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1); + FAIL_IF(push_inst(compiler, STFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET)); + return push_inst(compiler, LD | S(dst) | A(SLJIT_SP) | TMP_MEM_OFFSET); } return emit_op_mem(compiler, DOUBLE_DATA, TMP_FREG1, dst, dstw, TMP_REG1); } -#else +#else /* !SLJIT_CONFIG_PPC_64 */ FAIL_IF(push_inst(compiler, FCTIWZ | FD(TMP_FREG1) | FB(src))); -#endif +#endif /* SLJIT_CONFIG_PPC_64 */ if (FAST_IS_REG(dst)) { - FAIL_IF(load_immediate(compiler, TMP_REG1, FLOAT_TMP_MEM_OFFSET)); + FAIL_IF(load_immediate(compiler, TMP_REG1, TMP_MEM_OFFSET)); FAIL_IF(push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(SLJIT_SP) | B(TMP_REG1))); - return emit_op_mem(compiler, INT_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1); + return push_inst(compiler, LWZ | S(dst) | A(SLJIT_SP) | TMP_MEM_OFFSET); } SLJIT_ASSERT(dst & SLJIT_MEM); @@ -1800,22 +2049,16 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp if (dst & OFFS_REG_MASK) { dstw &= 0x3; if (dstw) { -#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) - FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(dst)) | A(TMP_REG1) | ((sljit_ins)dstw << 11) | ((31 - (sljit_ins)dstw) << 1))); -#else - FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, OFFS_REG(dst), dstw, 63 - dstw, 1))); -#endif + FAIL_IF(push_inst(compiler, SLWI_W(dstw) | S(OFFS_REG(dst)) | A(TMP_REG1))); dstw = TMP_REG1; - } - else + } else dstw = OFFS_REG(dst); } else { if ((dst & REG_MASK) && !dstw) { dstw = dst & REG_MASK; dst = 0; - } - else { + } else { /* This works regardless we have SLJIT_MEM1 or SLJIT_MEM0. */ FAIL_IF(load_immediate(compiler, TMP_REG1, dstw)); dstw = TMP_REG1; @@ -1839,8 +2082,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); src = TMP_REG1; - } - else if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) { + } else if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) { if (FAST_IS_REG(src)) FAIL_IF(push_inst(compiler, EXTSW | S(src) | A(TMP_REG1))); else @@ -1849,21 +2091,21 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp } if (FAST_IS_REG(src)) { - FAIL_IF(emit_op_mem(compiler, WORD_DATA, src, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1)); - FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1)); - } - else + FAIL_IF(push_inst(compiler, STD | S(src) | A(SLJIT_SP) | TMP_MEM_OFFSET)); + FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET)); + } else FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1)); FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1))); if (dst & SLJIT_MEM) return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1); + if (op & SLJIT_32) return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)); return SLJIT_SUCCESS; -#else +#else /* !SLJIT_CONFIG_PPC_64 */ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; sljit_s32 invert_sign = 1; @@ -1872,8 +2114,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp FAIL_IF(load_immediate(compiler, TMP_REG1, srcw ^ (sljit_sw)0x80000000)); src = TMP_REG1; invert_sign = 0; - } - else if (!FAST_IS_REG(src)) { + } else if (!FAST_IS_REG(src)) { FAIL_IF(emit_op_mem(compiler, WORD_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1)); src = TMP_REG1; } @@ -1882,16 +2123,16 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp The double precision format has exactly 53 bit precision, so the lower 32 bit represents the lower 32 bit of such value. The result of xor 2^31 is the same as adding 0x80000000 to the input, which shifts it into the 0 - 0xffffffff range. To get the converted floating - point value, we need to substract 2^53 + 2^31 from the constructed value. */ + point value, we need to subtract 2^53 + 2^31 from the constructed value. */ FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(0) | 0x4330)); if (invert_sign) FAIL_IF(push_inst(compiler, XORIS | S(src) | A(TMP_REG1) | 0x8000)); - FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_HI, TMP_REG1)); - FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW, TMP_REG2)); + FAIL_IF(push_inst(compiler, STW | S(TMP_REG2) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI)); + FAIL_IF(push_inst(compiler, STW | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET_LOW)); FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG1) | A(0) | 0x8000)); - FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1)); - FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW, TMP_REG2)); - FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG2, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1)); + FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET)); + FAIL_IF(push_inst(compiler, STW | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET_LOW)); + FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG2) | A(SLJIT_SP) | TMP_MEM_OFFSET)); FAIL_IF(push_inst(compiler, FSUB | FD(dst_r) | FA(TMP_FREG1) | FB(TMP_FREG2))); @@ -1901,7 +2142,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)); return SLJIT_SUCCESS; -#endif +#endif /* SLJIT_CONFIG_PPC_64 */ } static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op, @@ -1922,13 +2163,10 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile switch (GET_FLAG_TYPE(op)) { case SLJIT_UNORDERED_OR_EQUAL: - case SLJIT_ORDERED_NOT_EQUAL: return push_inst(compiler, CROR | ((4 + 2) << 21) | ((4 + 2) << 16) | ((4 + 3) << 11)); case SLJIT_UNORDERED_OR_LESS: - case SLJIT_ORDERED_GREATER_EQUAL: return push_inst(compiler, CROR | ((4 + 0) << 21) | ((4 + 0) << 16) | ((4 + 3) << 11)); case SLJIT_UNORDERED_OR_GREATER: - case SLJIT_ORDERED_LESS_EQUAL: return push_inst(compiler, CROR | ((4 + 1) << 21) | ((4 + 1) << 16) | ((4 + 3) << 11)); } @@ -2036,24 +2274,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil #undef SELECT_FOP -/* --------------------------------------------------------------------- */ -/* Other instructions */ -/* --------------------------------------------------------------------- */ - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) -{ - CHECK_ERROR(); - CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); - ADJUST_LOCAL_OFFSET(dst, dstw); - - if (FAST_IS_REG(dst)) - return push_inst(compiler, MFLR | D(dst)); - - /* Memory. */ - FAIL_IF(push_inst(compiler, MFLR | D(TMP_REG2))); - return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0); -} - /* --------------------------------------------------------------------- */ /* Conditional instructions */ /* --------------------------------------------------------------------- */ @@ -2204,7 +2424,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile #endif if (type & SLJIT_CALL_RETURN) { - PTR_FAIL_IF(emit_stack_frame_release(compiler)); + PTR_FAIL_IF(emit_stack_frame_release(compiler, 0)); type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP); } @@ -2219,7 +2439,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi CHECK_ERROR(); CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); - ADJUST_LOCAL_OFFSET(src, srcw); if (FAST_IS_REG(src)) { #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) @@ -2246,9 +2465,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi FAIL_IF(emit_const(compiler, TMP_CALL_REG, 0)); src_r = TMP_CALL_REG; - } - else { - FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_CALL_REG, 0, TMP_REG1, 0, src, srcw)); + } else { + ADJUST_LOCAL_OFFSET(src, srcw); + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_CALL_REG, src, srcw, TMP_CALL_REG)); src_r = TMP_CALL_REG; } @@ -2267,17 +2486,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi if (src & SLJIT_MEM) { ADJUST_LOCAL_OFFSET(src, srcw); - FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_CALL_REG, 0, TMP_REG1, 0, src, srcw)); + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_CALL_REG, src, srcw, TMP_CALL_REG)); src = TMP_CALL_REG; } if (type & SLJIT_CALL_RETURN) { - if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) { + if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src))); src = TMP_CALL_REG; } - FAIL_IF(emit_stack_frame_release(compiler)); + FAIL_IF(emit_stack_frame_release(compiler, 0)); type = SLJIT_JUMP; } @@ -2425,7 +2644,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co } FAIL_IF(push_inst(compiler, (from_xer ? MFXER : MFCR) | D(reg))); - FAIL_IF(push_inst(compiler, RLWINM | S(reg) | A(reg) | ((1 + bit) << 11) | (31 << 6) | (31 << 1))); + /* Simplified mnemonics: extrwi. */ + FAIL_IF(push_inst(compiler, RLWINM | S(reg) | A(reg) | RLWI_SH(1 + bit) | RLWI_MBE(31, 31))); if (invert) FAIL_IF(push_inst(compiler, XORI | S(reg) | A(reg) | 0x1)); @@ -2453,18 +2673,94 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);; } +#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) + +#define EMIT_MEM_LOAD_IMM(inst, mem, memw) \ + ((sljit_s16)(memw) > SIMM_MAX - SSIZE_OF(sw)) + +#else /* !SLJIT_CONFIG_PPC_32 */ + +#define EMIT_MEM_LOAD_IMM(inst, mem, memw) \ + ((((inst) & INT_ALIGNED) && ((memw) & 0x3) != 0) \ + || ((sljit_s16)(memw) > SIMM_MAX - SSIZE_OF(sw)) \ + || ((memw) > 0x7fff7fffl || (memw) < -0x80000000l)) \ + +#endif /* SLJIT_CONFIG_PPC_32 */ + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 reg, sljit_s32 mem, sljit_sw memw) +{ + sljit_ins inst; + + CHECK_ERROR(); + CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); + + if (!(reg & REG_PAIR_MASK)) + return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw); + + ADJUST_LOCAL_OFFSET(mem, memw); + + inst = data_transfer_insts[WORD_DATA | ((type & SLJIT_MEM_STORE) ? 0 : LOAD_DATA)]; + + if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) { + memw &= 0x3; + + if (memw != 0) { + FAIL_IF(push_inst(compiler, SLWI_W(memw) | S(OFFS_REG(mem)) | A(TMP_REG1))); + FAIL_IF(push_inst(compiler, ADD | D(TMP_REG1) | A(TMP_REG1) | B(mem & REG_MASK))); + } else + FAIL_IF(push_inst(compiler, ADD | D(TMP_REG1) | A(mem & REG_MASK) | B(OFFS_REG(mem)))); + + mem = TMP_REG1; + memw = 0; + } else { + if (EMIT_MEM_LOAD_IMM(inst, mem, memw)) { + if ((mem & REG_MASK) != 0) { + SLJIT_SKIP_CHECKS(compiler); + FAIL_IF(sljit_emit_op2(compiler, SLJIT_ADD, TMP_REG1, 0, mem & REG_MASK, 0, SLJIT_IMM, memw)); + } else + FAIL_IF(load_immediate(compiler, TMP_REG1, memw)); + + memw = 0; + mem = TMP_REG1; + } else if (memw > SIMM_MAX || memw < SIMM_MIN) { + FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG1) | A(mem & REG_MASK) | IMM((memw + 0x8000) >> 16))); + + memw &= 0xffff; + mem = TMP_REG1; + } else { + memw &= 0xffff; + mem &= REG_MASK; + } + } + + SLJIT_ASSERT((memw >= 0 && memw <= SIMM_MAX - SSIZE_OF(sw)) || (memw >= 0x8000 && memw <= 0xffff)); + +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + inst &= (sljit_ins)~INT_ALIGNED; +#endif /* SLJIT_CONFIG_PPC_64 */ + + if (!(type & SLJIT_MEM_STORE) && mem == REG_PAIR_FIRST(reg)) { + FAIL_IF(push_inst(compiler, inst | D(REG_PAIR_SECOND(reg)) | A(mem) | IMM(memw + SSIZE_OF(sw)))); + return push_inst(compiler, inst | D(REG_PAIR_FIRST(reg)) | A(mem) | IMM(memw)); + } + + FAIL_IF(push_inst(compiler, inst | D(REG_PAIR_FIRST(reg)) | A(mem) | IMM(memw))); + return push_inst(compiler, inst | D(REG_PAIR_SECOND(reg)) | A(mem) | IMM(memw + SSIZE_OF(sw))); +} + +#undef EMIT_MEM_LOAD_IMM + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 reg, + sljit_s32 mem, sljit_sw memw) { sljit_s32 mem_flags; sljit_ins inst; CHECK_ERROR(); - CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); - - if (type & SLJIT_MEM_UNALIGNED) - return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw); + CHECK(check_sljit_emit_mem_update(compiler, type, reg, mem, memw)); if (type & SLJIT_MEM_POST) return SLJIT_ERR_UNSUPPORTED; @@ -2552,7 +2848,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile return SLJIT_SUCCESS; } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 freg, sljit_s32 mem, sljit_sw memw) { @@ -2560,10 +2856,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil sljit_ins inst; CHECK_ERROR(); - CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw)); - - if (type & SLJIT_MEM_UNALIGNED) - return sljit_emit_fmem_unaligned(compiler, type, freg, mem, memw); + CHECK(check_sljit_emit_fmem_update(compiler, type, freg, mem, memw)); if (type & SLJIT_MEM_POST) return SLJIT_ERR_UNSUPPORTED; @@ -2611,7 +2904,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi PTR_FAIL_IF(emit_const(compiler, dst_r, init_value)); if (dst & SLJIT_MEM) - PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0)); + PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, dst_r, dst, dstw, TMP_REG1)); return const_; } diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeRISCV_32.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeRISCV_32.c index 24b8dc3905..4490be2aaf 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeRISCV_32.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeRISCV_32.c @@ -27,6 +27,7 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r, sljit_sw imm, sljit_s32 tmp_r) { SLJIT_UNUSED_ARG(tmp_r); + SLJIT_ASSERT(dst_r != tmp_r); if (imm <= SIMM_MAX && imm >= SIMM_MIN) return push_inst(compiler, ADDI | RD(dst_r) | RS1(TMP_ZERO) | IMM_I(imm)); @@ -42,6 +43,51 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r return push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(imm)); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 freg, sljit_s32 reg) +{ + sljit_ins inst; + sljit_s32 reg2 = 0; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg)); + + if (op & SLJIT_32) { + if (op == SLJIT_COPY32_TO_F32) + inst = FMV_W_X | RS1(reg) | FRD(freg); + else + inst = FMV_X_W | FRS1(freg) | RD(reg); + + return push_inst(compiler, inst); + } + + FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(-16))); + + if (reg & REG_PAIR_MASK) { + reg2 = REG_PAIR_SECOND(reg); + reg = REG_PAIR_FIRST(reg); + } + + if (op == SLJIT_COPY_TO_F64) { + if (reg2 != 0) + FAIL_IF(push_inst(compiler, SW | RS1(SLJIT_SP) | RS2(reg2) | (8 << 7))); + else + FAIL_IF(push_inst(compiler, FSW | RS1(SLJIT_SP) | FRS2(freg) | (8 << 7))); + + FAIL_IF(push_inst(compiler, SW | RS1(SLJIT_SP) | RS2(reg) | (12 << 7))); + FAIL_IF(push_inst(compiler, FLD | FRD(freg) | RS1(SLJIT_SP) | IMM_I(8))); + } else { + FAIL_IF(push_inst(compiler, FSD | RS1(SLJIT_SP) | FRS2(freg) | (8 << 7))); + + if (reg2 != 0) + FAIL_IF(push_inst(compiler, FMV_X_W | FRS1(freg) | RD(reg2))); + + FAIL_IF(push_inst(compiler, LW | RD(reg) | RS1(SLJIT_SP) | IMM_I(12))); + } + + return push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(16)); +} + static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value, sljit_ins last_ins) { if ((init_value & 0x800) != 0) diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeRISCV_64.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeRISCV_64.c index 16a5f5f557..f93d6ff667 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeRISCV_64.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeRISCV_64.c @@ -28,6 +28,8 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r { sljit_sw high; + SLJIT_ASSERT(dst_r != tmp_r); + if (imm <= SIMM_MAX && imm >= SIMM_MIN) return push_inst(compiler, ADDI | RD(dst_r) | RS1(TMP_ZERO) | IMM_I(imm)); @@ -124,6 +126,25 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r return push_inst(compiler, XOR | RD(dst_r) | RS1(dst_r) | RS2(tmp_r)); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 freg, sljit_s32 reg) +{ + sljit_ins inst; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg)); + + if (GET_OPCODE(op) == SLJIT_COPY_TO_F64) + inst = FMV_W_X | RS1(reg) | FRD(freg); + else + inst = FMV_X_W | FRS1(freg) | RD(reg); + + if (!(op & SLJIT_32)) + inst |= (sljit_ins)1 << 25; + + return push_inst(compiler, inst); +} + static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value, sljit_ins last_ins) { sljit_sw high; diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeRISCV_common.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeRISCV_common.c index cc7d4a0e7b..473e06040a 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeRISCV_common.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeRISCV_common.c @@ -97,16 +97,19 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define FLD (F3(0x3) | OPC(0x7)) #define FLE_S (F7(0x50) | F3(0x0) | OPC(0x53)) #define FLT_S (F7(0x50) | F3(0x1) | OPC(0x53)) -#define FSD (F3(0x3) | OPC(0x27)) /* These conversion opcodes are partly defined. */ #define FCVT_S_D (F7(0x20) | OPC(0x53)) #define FCVT_S_W (F7(0x68) | OPC(0x53)) #define FCVT_W_S (F7(0x60) | F3(0x1) | OPC(0x53)) #define FMUL_S (F7(0x8) | F3(0x7) | OPC(0x53)) +#define FMV_X_W (F7(0x70) | F3(0x0) | OPC(0x53)) +#define FMV_W_X (F7(0x78) | F3(0x0) | OPC(0x53)) +#define FSD (F3(0x3) | OPC(0x27)) #define FSGNJ_S (F7(0x10) | F3(0x0) | OPC(0x53)) #define FSGNJN_S (F7(0x10) | F3(0x1) | OPC(0x53)) #define FSGNJX_S (F7(0x10) | F3(0x2) | OPC(0x53)) #define FSUB_S (F7(0x4) | F3(0x7) | OPC(0x53)) +#define FSW (F3(0x2) | OPC(0x27)) #define JAL (OPC(0x6f)) #define JALR (F3(0x0) | OPC(0x67)) #define LD (F3(0x3) | OPC(0x3)) @@ -236,7 +239,7 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i jump->flags |= PATCH_ABS44; inst[3] = inst[0]; - return inst + 4; + return inst + 3; } if (target_addr <= S52_MAX) { @@ -531,7 +534,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) { switch (feature_type) { case SLJIT_HAS_FPU: +#ifdef SLJIT_IS_FPU_AVAILABLE + return SLJIT_IS_FPU_AVAILABLE; +#elif defined(__riscv_float_abi_soft) + return 0; +#else + return 1; +#endif /* SLJIT_IS_FPU_AVAILABLE */ case SLJIT_HAS_ZERO_REGISTER: + case SLJIT_HAS_COPY_F32: +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + case SLJIT_HAS_COPY_F64: +#endif /* !SLJIT_CONFIG_RISCV_64 */ return 1; default: return 0; @@ -592,6 +606,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type) #define STACK_MAX_DISTANCE (-SIMM_MIN) +static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw); + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) @@ -608,10 +624,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) { if ((local_size & SSIZE_OF(sw)) != 0) local_size += SSIZE_OF(sw); - local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64)); + local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64); } #else - local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64)); + local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64); #endif local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf; compiler->local_size = local_size; @@ -702,10 +718,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) { if ((local_size & SSIZE_OF(sw)) != 0) local_size += SSIZE_OF(sw); - local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64)); + local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64); } #else - local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64)); + local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64); #endif compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf; @@ -714,7 +730,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp #define STACK_MAX_DISTANCE (-SIMM_MIN - 16) -static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) +static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to) { sljit_s32 i, tmp, offset; sljit_s32 local_size = compiler->local_size; @@ -734,7 +750,8 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) SLJIT_ASSERT(local_size > 0); offset = local_size - SSIZE_OF(sw); - FAIL_IF(push_inst(compiler, STACK_LOAD | RD(RETURN_ADDR_REG) | RS1(SLJIT_SP) | IMM_I(offset))); + if (!is_return_to) + FAIL_IF(push_inst(compiler, STACK_LOAD | RD(RETURN_ADDR_REG) | RS1(SLJIT_SP) | IMM_I(offset))); tmp = SLJIT_S0 - compiler->saveds; for (i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); i > tmp; i--) { @@ -774,10 +791,33 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler CHECK_ERROR(); CHECK(check_sljit_emit_return_void(compiler)); - FAIL_IF(emit_stack_frame_release(compiler)); + FAIL_IF(emit_stack_frame_release(compiler, 0)); return push_inst(compiler, JALR | RD(TMP_ZERO) | RS1(RETURN_ADDR_REG) | IMM_I(0)); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_return_to(compiler, src, srcw)); + + if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw)); + src = TMP_REG1; + srcw = 0; + } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { + FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(src) | IMM_I(0))); + src = TMP_REG1; + srcw = 0; + } + + FAIL_IF(emit_stack_frame_release(compiler, 1)); + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw); +} + /* --------------------------------------------------------------------- */ /* Operators */ /* --------------------------------------------------------------------- */ @@ -980,23 +1020,22 @@ static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, s if (SLJIT_UNLIKELY(argw)) { FAIL_IF(push_inst(compiler, SLLI | RD(tmp_r) | RS1(OFFS_REG(arg)) | IMM_I(argw))); - FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(base) | RS2(tmp_r))); + FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(tmp_r) | RS2(base))); } else FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(base) | RS2(OFFS_REG(arg)))); - return push_mem_inst(compiler, flags, reg, tmp_r, 0); + + argw = 0; + } else { + FAIL_IF(load_immediate(compiler, tmp_r, TO_ARGW_HI(argw), TMP_REG3)); + + if (base != 0) + FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(tmp_r) | RS2(base))); } - FAIL_IF(load_immediate(compiler, tmp_r, TO_ARGW_HI(argw), TMP_REG3)); - - if (base != 0) - FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(base) | RS2(tmp_r))); - return push_mem_inst(compiler, flags, reg, tmp_r, argw & 0xfff); } -#undef TO_ARGW_HI - static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w) { if (getput_arg_fast(compiler, flags, reg, arg1, arg1w)) @@ -1006,12 +1045,101 @@ static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, slji #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) #define WORD 0 +#define WORD_32 0 #define IMM_EXTEND(v) (IMM_I(v)) #else /* !SLJIT_CONFIG_RISCV_32 */ #define WORD word +#define WORD_32 0x08 #define IMM_EXTEND(v) (IMM_I((op & SLJIT_32) ? (v) : (32 + (v)))) #endif /* SLJIT_CONFIG_RISCV_32 */ +static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src) +{ + sljit_s32 is_clz = (GET_OPCODE(op) == SLJIT_CLZ); +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + sljit_ins word = (op & SLJIT_32) >> 5; + sljit_ins max = (op & SLJIT_32) ? 32 : 64; +#else /* !SLJIT_CONFIG_RISCV_64 */ + sljit_ins max = 32; +#endif /* SLJIT_CONFIG_RISCV_64 */ + + SLJIT_ASSERT(WORD == 0 || WORD == 0x8); + + /* The OTHER_FLAG is the counter. */ + FAIL_IF(push_inst(compiler, ADDI | WORD | RD(OTHER_FLAG) | RS1(TMP_ZERO) | IMM_I(max))); + + /* The TMP_REG2 is the next value. */ + if (src != TMP_REG2) + FAIL_IF(push_inst(compiler, ADDI | WORD | RD(TMP_REG2) | RS1(src) | IMM_I(0))); + + FAIL_IF(push_inst(compiler, BEQ | RS1(TMP_REG2) | RS2(TMP_ZERO) | ((sljit_ins)((is_clz ? 4 : 5) * SSIZE_OF(ins)) << 7) | ((sljit_ins)(8 * SSIZE_OF(ins)) << 20))); + + FAIL_IF(push_inst(compiler, ADDI | WORD | RD(OTHER_FLAG) | RS1(TMP_ZERO) | IMM_I(0))); + if (!is_clz) { + FAIL_IF(push_inst(compiler, ANDI | RD(TMP_REG1) | RS1(TMP_REG2) | IMM_I(1))); + FAIL_IF(push_inst(compiler, BNE | RS1(TMP_REG1) | RS2(TMP_ZERO) | ((sljit_ins)(2 * SSIZE_OF(ins)) << 7) | ((sljit_ins)(8 * SSIZE_OF(ins)) << 20))); + } else + FAIL_IF(push_inst(compiler, BLT | RS1(TMP_REG2) | RS2(TMP_ZERO) | ((sljit_ins)(2 * SSIZE_OF(ins)) << 7) | ((sljit_ins)(8 * SSIZE_OF(ins)) << 20))); + + /* The TMP_REG1 is the next shift. */ + FAIL_IF(push_inst(compiler, ADDI | WORD | RD(TMP_REG1) | RS1(TMP_ZERO) | IMM_I(max))); + + FAIL_IF(push_inst(compiler, ADDI | WORD | RD(EQUAL_FLAG) | RS1(TMP_REG2) | IMM_I(0))); + FAIL_IF(push_inst(compiler, SRLI | WORD | RD(TMP_REG1) | RS1(TMP_REG1) | IMM_I(1))); + + FAIL_IF(push_inst(compiler, (is_clz ? SRL : SLL) | WORD | RD(TMP_REG2) | RS1(EQUAL_FLAG) | RS2(TMP_REG1))); + FAIL_IF(push_inst(compiler, BNE | RS1(TMP_REG2) | RS2(TMP_ZERO) | ((sljit_ins)0xfe000e80 - ((2 * SSIZE_OF(ins)) << 7)))); + FAIL_IF(push_inst(compiler, ADDI | WORD | RD(TMP_REG2) | RS1(TMP_REG1) | IMM_I(-1))); + FAIL_IF(push_inst(compiler, (is_clz ? SRL : SLL) | WORD | RD(TMP_REG2) | RS1(EQUAL_FLAG) | RS2(TMP_REG2))); + FAIL_IF(push_inst(compiler, OR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(TMP_REG1))); + FAIL_IF(push_inst(compiler, BEQ | RS1(TMP_REG2) | RS2(TMP_ZERO) | ((sljit_ins)0xfe000e80 - ((5 * SSIZE_OF(ins)) << 7)))); + + return push_inst(compiler, ADDI | WORD | RD(dst) | RS1(OTHER_FLAG) | IMM_I(0)); +} + +static sljit_s32 emit_rev(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src) +{ + SLJIT_UNUSED_ARG(op); + +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + if (!(op & SLJIT_32)) { + FAIL_IF(push_inst(compiler, LUI | RD(OTHER_FLAG) | 0x10000)); + FAIL_IF(push_inst(compiler, SRLI | RD(TMP_REG1) | RS1(src) | IMM_I(32))); + FAIL_IF(push_inst(compiler, ADDI | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | IMM_I(0xfff))); + FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(src) | IMM_I(32))); + FAIL_IF(push_inst(compiler, SLLI | RD(EQUAL_FLAG) | RS1(OTHER_FLAG) | IMM_I(32))); + FAIL_IF(push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1))); + FAIL_IF(push_inst(compiler, OR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(EQUAL_FLAG))); + + FAIL_IF(push_inst(compiler, SRLI | RD(TMP_REG1) | RS1(dst) | IMM_I(16))); + FAIL_IF(push_inst(compiler, AND | RD(dst) | RS1(dst) | RS2(OTHER_FLAG))); + FAIL_IF(push_inst(compiler, AND | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(OTHER_FLAG))); + FAIL_IF(push_inst(compiler, SLLI | RD(EQUAL_FLAG) | RS1(OTHER_FLAG) | IMM_I(8))); + FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(dst) | IMM_I(16))); + FAIL_IF(push_inst(compiler, XOR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(EQUAL_FLAG))); + FAIL_IF(push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1))); + + FAIL_IF(push_inst(compiler, SRLI | RD(TMP_REG1) | RS1(dst) | IMM_I(8))); + FAIL_IF(push_inst(compiler, AND | RD(dst) | RS1(dst) | RS2(OTHER_FLAG))); + FAIL_IF(push_inst(compiler, AND | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(OTHER_FLAG))); + FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(dst) | IMM_I(8))); + return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1)); + } +#endif /* SLJIT_CONFIG_RISCV_64 */ + + FAIL_IF(push_inst(compiler, SRLI | WORD_32 | RD(TMP_REG1) | RS1(src) | IMM_I(16))); + FAIL_IF(push_inst(compiler, LUI | RD(OTHER_FLAG) | 0xff0000)); + FAIL_IF(push_inst(compiler, SLLI | WORD_32 | RD(dst) | RS1(src) | IMM_I(16))); + FAIL_IF(push_inst(compiler, ORI | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | IMM_I(0xff))); + FAIL_IF(push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1))); + + FAIL_IF(push_inst(compiler, SRLI | WORD_32 | RD(TMP_REG1) | RS1(dst) | IMM_I(8))); + FAIL_IF(push_inst(compiler, AND | RD(dst) | RS1(dst) | RS2(OTHER_FLAG))); + FAIL_IF(push_inst(compiler, AND | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(OTHER_FLAG))); + FAIL_IF(push_inst(compiler, SLLI | WORD_32 | RD(dst) | RS1(dst) | IMM_I(8))); + return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1)); +} + #define EMIT_LOGICAL(op_imm, op_reg) \ if (flags & SRC2_IMM) { \ if (op & SLJIT_SET_Z) \ @@ -1026,30 +1154,21 @@ static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, slji FAIL_IF(push_inst(compiler, op_reg | RD(dst) | RS1(src1) | RS2(src2))); \ } -#define EMIT_SHIFT(op_imm, op_reg) \ - if (flags & SRC2_IMM) { \ - if (op & SLJIT_SET_Z) \ - FAIL_IF(push_inst(compiler, op_imm | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2))); \ - if (!(flags & UNUSED_DEST)) \ - FAIL_IF(push_inst(compiler, op_imm | WORD | RD(dst) | RS1(src1) | IMM_I(src2))); \ - } \ - else { \ - if (op & SLJIT_SET_Z) \ - FAIL_IF(push_inst(compiler, op_reg | WORD | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2))); \ - if (!(flags & UNUSED_DEST)) \ - FAIL_IF(push_inst(compiler, op_reg | WORD | RD(dst) | RS1(src1) | RS2(src2))); \ - } +#define EMIT_SHIFT(imm, reg) \ + op_imm = (imm); \ + op_reg = (reg); static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_s32 src1, sljit_sw src2) { sljit_s32 is_overflow, is_carry, carry_src_r, is_handled; + sljit_ins op_imm, op_reg; #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) sljit_ins word = (op & SLJIT_32) >> 5; - - SLJIT_ASSERT(word == 0 || word == 0x8); #endif /* SLJIT_CONFIG_RISCV_64 */ + SLJIT_ASSERT(WORD == 0 || WORD == 0x8); + switch (GET_OPCODE(op)) { case SLJIT_MOV: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); @@ -1110,34 +1229,18 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl #endif /* SLJIT_CONFIG_RISCV_64 */ case SLJIT_CLZ: + case SLJIT_CTZ: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); - /* Nearly all instructions are unmovable in the following sequence. */ -#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) - FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(src2) | IMM_I(0))); - FAIL_IF(push_inst(compiler, ADDI | RD(dst) | RS1(TMP_ZERO) | IMM_I(32))); -#else /* !SLJIT_CONFIG_RISCV_32 */ - if (op & SLJIT_32) { - FAIL_IF(push_inst(compiler, SLLI | RD(TMP_REG1) | RS1(src2) | IMM_I(32))); - FAIL_IF(push_inst(compiler, ADDI | RD(dst) | RS1(TMP_ZERO) | IMM_I(32))); - } else { - FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(src2) | IMM_I(0))); - FAIL_IF(push_inst(compiler, ADDI | RD(dst) | RS1(TMP_ZERO) | IMM_I(64))); - } -#endif /* SLJIT_CONFIG_RISCV_32 */ - /* Check zero. */ - FAIL_IF(push_inst(compiler, BEQ | RS1(TMP_REG1) | RS2(TMP_ZERO) | ((sljit_ins)(6 * SSIZE_OF(ins)) << 7))); - FAIL_IF(push_inst(compiler, ADDI | RD(dst) | RS1(TMP_ZERO) | IMM_I(0))); - FAIL_IF(push_inst(compiler, BLT | RS1(TMP_REG1) | RS2(TMP_ZERO) | ((sljit_ins)(4 * SSIZE_OF(ins)) << 7))); - /* Loop for searching the highest bit. */ - FAIL_IF(push_inst(compiler, ADDI | RD(dst) | RS1(dst) | IMM_I(1))); - FAIL_IF(push_inst(compiler, SLLI | RD(TMP_REG1) | RS1(TMP_REG1) | IMM_I(1))); - FAIL_IF(push_inst(compiler, BGE | RS1(TMP_REG1) | RS2(TMP_ZERO) | ((sljit_ins)(0x1fc001d - 1 * SSIZE_OF(ins)) << 7))); - return SLJIT_SUCCESS; + return emit_clz_ctz(compiler, op, dst, src2); + + case SLJIT_REV: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + return emit_rev(compiler, op, dst, src2); case SLJIT_ADD: /* Overflow computation (both add and sub): overflow = src1_sign ^ src2_sign ^ result_sign ^ carry_flag */ is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW; - carry_src_r = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); + carry_src_r = GET_FLAG_TYPE(op) == SLJIT_CARRY; if (flags & SRC2_IMM) { if (is_overflow) { @@ -1193,7 +1296,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl return push_inst(compiler, XOR | RD(OTHER_FLAG) | RS1(TMP_REG1) | RS2(OTHER_FLAG)); case SLJIT_ADDC: - carry_src_r = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); + carry_src_r = GET_FLAG_TYPE(op) == SLJIT_CARRY; if (flags & SRC2_IMM) { FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(src2))); @@ -1240,11 +1343,11 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl is_handled = 0; if (flags & SRC2_IMM) { - if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) { + if (GET_FLAG_TYPE(op) == SLJIT_LESS) { FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2))); is_handled = 1; } - else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) { + else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS) { FAIL_IF(push_inst(compiler, SLTI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2))); is_handled = 1; } @@ -1261,19 +1364,15 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl switch (GET_FLAG_TYPE(op)) { case SLJIT_LESS: - case SLJIT_GREATER_EQUAL: FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(src1) | RS2(src2))); break; case SLJIT_GREATER: - case SLJIT_LESS_EQUAL: FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(src2) | RS2(src1))); break; case SLJIT_SIG_LESS: - case SLJIT_SIG_GREATER_EQUAL: FAIL_IF(push_inst(compiler, SLT | RD(OTHER_FLAG) | RS1(src1) | RS2(src2))); break; case SLJIT_SIG_GREATER: - case SLJIT_SIG_LESS_EQUAL: FAIL_IF(push_inst(compiler, SLT | RD(OTHER_FLAG) | RS1(src2) | RS2(src1))); break; } @@ -1296,7 +1395,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl } is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW; - is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); + is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY; if (flags & SRC2_IMM) { if (is_overflow) { @@ -1345,7 +1444,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl flags &= ~SRC2_IMM; } - is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); + is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY; if (flags & SRC2_IMM) { if (is_carry) @@ -1406,20 +1505,71 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl return SLJIT_SUCCESS; case SLJIT_SHL: + case SLJIT_MSHL: EMIT_SHIFT(SLLI, SLL); - return SLJIT_SUCCESS; + break; case SLJIT_LSHR: + case SLJIT_MLSHR: EMIT_SHIFT(SRLI, SRL); - return SLJIT_SUCCESS; + break; case SLJIT_ASHR: + case SLJIT_MASHR: EMIT_SHIFT(SRAI, SRA); + break; + + case SLJIT_ROTL: + case SLJIT_ROTR: + if (flags & SRC2_IMM) { + SLJIT_ASSERT(src2 != 0); + + op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SLLI : SRLI; + FAIL_IF(push_inst(compiler, op_imm | WORD | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2))); + +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + src2 = ((op & SLJIT_32) ? 32 : 64) - src2; +#else /* !SLJIT_CONFIG_RISCV_64 */ + src2 = 32 - src2; +#endif /* SLJIT_CONFIG_RISCV_64 */ + op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SRLI : SLLI; + FAIL_IF(push_inst(compiler, op_imm | WORD | RD(dst) | RS1(src1) | IMM_I(src2))); + return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)); + } + + if (src2 == TMP_ZERO) { + if (dst != src1) + return push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(0)); + return SLJIT_SUCCESS; + } + + FAIL_IF(push_inst(compiler, SUB | WORD | RD(EQUAL_FLAG) | RS1(TMP_ZERO) | RS2(src2))); + op_reg = (GET_OPCODE(op) == SLJIT_ROTL) ? SLL : SRL; + FAIL_IF(push_inst(compiler, op_reg | WORD | RD(OTHER_FLAG) | RS1(src1) | RS2(src2))); + op_reg = (GET_OPCODE(op) == SLJIT_ROTL) ? SRL : SLL; + FAIL_IF(push_inst(compiler, op_reg | WORD | RD(dst) | RS1(src1) | RS2(EQUAL_FLAG))); + return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)); + + default: + SLJIT_UNREACHABLE(); return SLJIT_SUCCESS; } - SLJIT_UNREACHABLE(); - return SLJIT_SUCCESS; + if (flags & SRC2_IMM) { + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, op_imm | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2))); + + if (flags & UNUSED_DEST) + return SLJIT_SUCCESS; + return push_inst(compiler, op_imm | WORD | RD(dst) | RS1(src1) | IMM_I(src2)); + } + + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, op_reg | WORD | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2))); + + if (flags & UNUSED_DEST) + return SLJIT_SUCCESS; + return push_inst(compiler, op_reg | WORD | RD(dst) | RS1(src1) | RS2(src2)); } #undef IMM_EXTEND @@ -1599,8 +1749,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile return SLJIT_SUCCESS; } -#undef WORD - SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) @@ -1649,10 +1797,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile case SLJIT_MOV_S16: return emit_op(compiler, op, HALF_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw); - case SLJIT_NOT: - return emit_op(compiler, SLJIT_XOR | (op & (SLJIT_32 | SLJIT_SET_Z)), flags, dst, dstw, src, srcw, SLJIT_IMM, -1); - case SLJIT_CLZ: + case SLJIT_CTZ: + case SLJIT_REV: return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw); } @@ -1704,19 +1851,24 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w); case SLJIT_SHL: + case SLJIT_MSHL: case SLJIT_LSHR: + case SLJIT_MLSHR: case SLJIT_ASHR: -#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) - if (src2 & SLJIT_IMM) - src2w &= 0x1f; -#else + case SLJIT_MASHR: + case SLJIT_ROTL: + case SLJIT_ROTR: if (src2 & SLJIT_IMM) { +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) + src2w &= 0x1f; +#else /* !SLJIT_CONFIG_RISCV_32 */ if (op & SLJIT_32) src2w &= 0x1f; else src2w &= 0x3f; +#endif /* SLJIT_CONFIG_RISCV_32 */ } -#endif + return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w); } @@ -1735,6 +1887,91 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst_reg, + sljit_s32 src1_reg, + sljit_s32 src2_reg, + sljit_s32 src3, sljit_sw src3w) +{ + sljit_s32 is_left; + sljit_ins ins1, ins2, ins3; +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + sljit_ins word = (op & SLJIT_32) >> 5; + sljit_s32 inp_flags = ((op & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA; + sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64; +#else /* !SLJIT_CONFIG_RISCV_64 */ + sljit_s32 inp_flags = WORD_DATA | LOAD_DATA; + sljit_sw bit_length = 32; +#endif /* SLJIT_CONFIG_RISCV_64 */ + + SLJIT_ASSERT(WORD == 0 || WORD == 0x8); + + CHECK_ERROR(); + CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w)); + + is_left = (GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_MSHL); + + if (src1_reg == src2_reg) { + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_op2(compiler, (is_left ? SLJIT_ROTL : SLJIT_ROTR) | (op & SLJIT_32), dst_reg, 0, src1_reg, 0, src3, src3w); + } + + ADJUST_LOCAL_OFFSET(src3, src3w); + + if (src3 & SLJIT_IMM) { + src3w &= bit_length - 1; + + if (src3w == 0) + return SLJIT_SUCCESS; + + if (is_left) { + ins1 = SLLI | WORD | IMM_I(src3w); + src3w = bit_length - src3w; + ins2 = SRLI | WORD | IMM_I(src3w); + } else { + ins1 = SRLI | WORD | IMM_I(src3w); + src3w = bit_length - src3w; + ins2 = SLLI | WORD | IMM_I(src3w); + } + + FAIL_IF(push_inst(compiler, ins1 | RD(dst_reg) | RS1(src1_reg))); + FAIL_IF(push_inst(compiler, ins2 | RD(TMP_REG1) | RS1(src2_reg))); + return push_inst(compiler, OR | RD(dst_reg) | RS1(dst_reg) | RS2(TMP_REG1)); + } + + if (src3 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG2, src3, src3w)); + src3 = TMP_REG2; + } else if (dst_reg == src3) { + push_inst(compiler, ADDI | WORD | RD(TMP_REG2) | RS1(src3) | IMM_I(0)); + src3 = TMP_REG2; + } + + if (is_left) { + ins1 = SLL; + ins2 = SRLI; + ins3 = SRL; + } else { + ins1 = SRL; + ins2 = SLLI; + ins3 = SLL; + } + + FAIL_IF(push_inst(compiler, ins1 | WORD | RD(dst_reg) | RS1(src1_reg) | RS2(src3))); + + if (!(op & SLJIT_SHIFT_INTO_NON_ZERO)) { + FAIL_IF(push_inst(compiler, ins2 | WORD | RD(TMP_REG1) | RS1(src2_reg) | IMM_I(1))); + FAIL_IF(push_inst(compiler, XORI | RD(TMP_REG2) | RS1(src3) | IMM_I((sljit_ins)bit_length - 1))); + src2_reg = TMP_REG1; + } else + FAIL_IF(push_inst(compiler, SUB | WORD | RD(TMP_REG2) | RS1(TMP_ZERO) | RS2(src3))); + + FAIL_IF(push_inst(compiler, ins3 | WORD | RD(TMP_REG1) | RS1(src2_reg) | RS2(TMP_REG2))); + return push_inst(compiler, OR | RD(dst_reg) | RS1(dst_reg) | RS2(TMP_REG1)); +} + +#undef WORD + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { @@ -1762,6 +1999,34 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *comp return SLJIT_SUCCESS; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw) +{ + sljit_s32 dst_r; + + CHECK_ERROR(); + CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw)); + ADJUST_LOCAL_OFFSET(dst, dstw); + + switch (op) { + case SLJIT_FAST_ENTER: + if (FAST_IS_REG(dst)) + return push_inst(compiler, ADDI | RD(dst) | RS1(RETURN_ADDR_REG) | IMM_I(0)); + + SLJIT_ASSERT(RETURN_ADDR_REG == TMP_REG2); + break; + case SLJIT_GET_RETURN_ADDRESS: + dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2; + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst_r, SLJIT_MEM1(SLJIT_SP), compiler->local_size - SSIZE_OF(sw))); + break; + } + + if (dst & SLJIT_MEM) + return emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw); + + return SLJIT_SUCCESS; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_register_index(reg)); @@ -1888,38 +2153,29 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile switch (GET_FLAG_TYPE(op)) { case SLJIT_F_EQUAL: - case SLJIT_F_NOT_EQUAL: case SLJIT_ORDERED_EQUAL: - case SLJIT_UNORDERED_OR_NOT_EQUAL: inst = FEQ_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src2); break; case SLJIT_F_LESS: - case SLJIT_F_GREATER_EQUAL: case SLJIT_ORDERED_LESS: - case SLJIT_UNORDERED_OR_GREATER_EQUAL: inst = FLT_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src2); break; case SLJIT_ORDERED_GREATER: - case SLJIT_UNORDERED_OR_LESS_EQUAL: inst = FLT_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src2) | FRS2(src1); break; case SLJIT_F_GREATER: - case SLJIT_F_LESS_EQUAL: case SLJIT_UNORDERED_OR_GREATER: - case SLJIT_ORDERED_LESS_EQUAL: inst = FLE_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src2); break; case SLJIT_UNORDERED_OR_LESS: - case SLJIT_ORDERED_GREATER_EQUAL: inst = FLE_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src2) | FRS2(src1); break; case SLJIT_UNORDERED_OR_EQUAL: /* Not supported. */ - case SLJIT_ORDERED_NOT_EQUAL: /* Not supported. */ FAIL_IF(push_inst(compiler, FLT_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src2))); FAIL_IF(push_inst(compiler, FLT_S | FMT(op) | RD(TMP_REG1) | FRS1(src2) | FRS2(src1))); inst = OR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(TMP_REG1); break; - default: /* SLJIT_UNORDERED, SLJIT_ORDERED */ + default: /* SLJIT_UNORDERED */ FAIL_IF(push_inst(compiler, FADD_S | FMT(op) | FRD(TMP_FREG1) | FRS1(src1) | FRS2(src2))); inst = FEQ_S | FMT(op) | RD(OTHER_FLAG) | FRS1(TMP_FREG1) | FRS2(TMP_FREG1); break; @@ -2059,23 +2315,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil #undef FLOAT_DATA #undef FMT -/* --------------------------------------------------------------------- */ -/* Other instructions */ -/* --------------------------------------------------------------------- */ - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) -{ - CHECK_ERROR(); - CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); - ADJUST_LOCAL_OFFSET(dst, dstw); - - if (FAST_IS_REG(dst)) - return push_inst(compiler, ADDI | RD(dst) | RS1(RETURN_ADDR_REG) | IMM_I(0)); - - /* Memory. */ - return emit_op_mem(compiler, WORD_DATA, RETURN_ADDR_REG, dst, dstw); -} - /* --------------------------------------------------------------------- */ /* Conditional instructions */ /* --------------------------------------------------------------------- */ @@ -2196,7 +2435,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); if (type & SLJIT_CALL_RETURN) { - PTR_FAIL_IF(emit_stack_frame_release(compiler)); + PTR_FAIL_IF(emit_stack_frame_release(compiler, 0)); type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP); } @@ -2313,10 +2552,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi CHECK_ERROR(); CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); - ADJUST_LOCAL_OFFSET(src, srcw); if (!(src & SLJIT_IMM)) { if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw)); src = TMP_REG1; } @@ -2348,20 +2587,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi SLJIT_UNUSED_ARG(arg_types); CHECK_ERROR(); CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); - ADJUST_LOCAL_OFFSET(src, srcw); if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw)); src = TMP_REG1; } if (type & SLJIT_CALL_RETURN) { - if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) { + if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(src) | IMM_I(0))); src = TMP_REG1; } - FAIL_IF(emit_stack_frame_release(compiler)); + FAIL_IF(emit_stack_frame_release(compiler, 0)); type = SLJIT_JUMP; } @@ -2466,6 +2705,62 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 reg, + sljit_s32 mem, sljit_sw memw) +{ + sljit_s32 flags; + + CHECK_ERROR(); + CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); + + if (!(reg & REG_PAIR_MASK)) + return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw); + + if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) { + memw &= 0x3; + + if (SLJIT_UNLIKELY(memw != 0)) { + FAIL_IF(push_inst(compiler, SLLI | RD(TMP_REG1) | RS1(OFFS_REG(mem)) | IMM_I(memw))); + FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(mem & REG_MASK))); + } else + FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RS1(mem & REG_MASK) | RS2(OFFS_REG(mem)))); + + mem = TMP_REG1; + memw = 0; + } else if (memw > SIMM_MAX - SSIZE_OF(sw) || memw < SIMM_MIN) { + if (((memw + 0x800) & 0xfff) <= 0xfff - SSIZE_OF(sw)) { + FAIL_IF(load_immediate(compiler, TMP_REG1, TO_ARGW_HI(memw), TMP_REG3)); + memw &= 0xfff; + } else { + FAIL_IF(load_immediate(compiler, TMP_REG1, memw, TMP_REG3)); + memw = 0; + } + + if (mem & REG_MASK) + FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(mem & REG_MASK))); + + mem = TMP_REG1; + } else { + mem &= REG_MASK; + memw &= 0xfff; + } + + SLJIT_ASSERT((memw >= 0 && memw <= SIMM_MAX - SSIZE_OF(sw)) || (memw > SIMM_MAX && memw <= 0xfff)); + + if (!(type & SLJIT_MEM_STORE) && mem == REG_PAIR_FIRST(reg)) { + FAIL_IF(push_mem_inst(compiler, WORD_DATA | LOAD_DATA, REG_PAIR_SECOND(reg), mem, (memw + SSIZE_OF(sw)) & 0xfff)); + return push_mem_inst(compiler, WORD_DATA | LOAD_DATA, REG_PAIR_FIRST(reg), mem, memw); + } + + flags = WORD_DATA | (!(type & SLJIT_MEM_STORE) ? LOAD_DATA : 0); + + FAIL_IF(push_mem_inst(compiler, flags, REG_PAIR_FIRST(reg), mem, memw)); + return push_mem_inst(compiler, flags, REG_PAIR_SECOND(reg), mem, (memw + SSIZE_OF(sw)) & 0xfff); +} + +#undef TO_ARGW_HI + SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) { struct sljit_const *const_; diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeS390X.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeS390X.c index be1ef438d3..8d86d072b1 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeS390X.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeS390X.c @@ -103,11 +103,8 @@ static const sljit_gpr r15 = 15; /* reg_map[SLJIT_NUMBER_OF_REGISTERS + 1]: stac /* When reg cannot be unused. */ #define IS_GPR_REG(reg) ((reg > 0) && (reg) <= SLJIT_SP) -/* Link registers. The normal link register is r14, but since - we use that for flags we need to use r0 instead to do fast - calls so that flags are preserved. */ +/* Link register. */ static const sljit_gpr link_r = 14; /* r14 */ -static const sljit_gpr fast_link_r = 0; /* r0 */ #define TMP_FREG1 (0) @@ -144,12 +141,6 @@ static SLJIT_INLINE sljit_gpr gpr(sljit_s32 r) return reg_map[r]; } -static SLJIT_INLINE sljit_gpr fgpr(sljit_s32 r) -{ - SLJIT_ASSERT(r >= 0 && r < (sljit_s32)(sizeof(freg_map) / sizeof(freg_map[0]))); - return freg_map[r]; -} - /* Size of instruction in bytes. Tags must already be cleared. */ static SLJIT_INLINE sljit_uw sizeof_ins(sljit_ins ins) { @@ -998,7 +989,7 @@ static sljit_s32 make_addr_bx(struct sljit_compiler *compiler, (cond) ? EVAL(i1, r, addr) : EVAL(i2, r, addr) /* May clobber tmp1. */ -static sljit_s32 load_word(struct sljit_compiler *compiler, sljit_gpr dst, +static sljit_s32 load_word(struct sljit_compiler *compiler, sljit_gpr dst_r, sljit_s32 src, sljit_sw srcw, sljit_s32 is_32bit) { @@ -1006,21 +997,36 @@ static sljit_s32 load_word(struct sljit_compiler *compiler, sljit_gpr dst, sljit_ins ins; SLJIT_ASSERT(src & SLJIT_MEM); - if (have_ldisp() || !is_32bit) - FAIL_IF(make_addr_bxy(compiler, &addr, src, srcw, tmp1)); - else + + if (is_32bit && ((src & OFFS_REG_MASK) || is_u12(srcw) || !is_s20(srcw))) { FAIL_IF(make_addr_bx(compiler, &addr, src, srcw, tmp1)); + return push_inst(compiler, 0x58000000 /* l */ | R20A(dst_r) | R16A(addr.index) | R12A(addr.base) | (sljit_ins)addr.offset); + } - if (is_32bit) - ins = WHEN(is_u12(addr.offset), dst, l, ly, addr); - else - ins = lg(dst, addr.offset, addr.index, addr.base); + FAIL_IF(make_addr_bxy(compiler, &addr, src, srcw, tmp1)); - return push_inst(compiler, ins); + ins = is_32bit ? 0xe30000000058 /* ly */ : 0xe30000000004 /* lg */; + return push_inst(compiler, ins | R36A(dst_r) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset)); } /* May clobber tmp1. */ -static sljit_s32 store_word(struct sljit_compiler *compiler, sljit_gpr src, +static sljit_s32 load_unsigned_word(struct sljit_compiler *compiler, sljit_gpr dst_r, + sljit_s32 src, sljit_sw srcw, + sljit_s32 is_32bit) +{ + struct addr addr; + sljit_ins ins; + + SLJIT_ASSERT(src & SLJIT_MEM); + + FAIL_IF(make_addr_bxy(compiler, &addr, src, srcw, tmp1)); + + ins = is_32bit ? 0xe30000000016 /* llgf */ : 0xe30000000004 /* lg */; + return push_inst(compiler, ins | R36A(dst_r) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset)); +} + +/* May clobber tmp1. */ +static sljit_s32 store_word(struct sljit_compiler *compiler, sljit_gpr src_r, sljit_s32 dst, sljit_sw dstw, sljit_s32 is_32bit) { @@ -1028,17 +1034,16 @@ static sljit_s32 store_word(struct sljit_compiler *compiler, sljit_gpr src, sljit_ins ins; SLJIT_ASSERT(dst & SLJIT_MEM); - if (have_ldisp() || !is_32bit) - FAIL_IF(make_addr_bxy(compiler, &addr, dst, dstw, tmp1)); - else + + if (is_32bit && ((dst & OFFS_REG_MASK) || is_u12(dstw) || !is_s20(dstw))) { FAIL_IF(make_addr_bx(compiler, &addr, dst, dstw, tmp1)); + return push_inst(compiler, 0x50000000 /* st */ | R20A(src_r) | R16A(addr.index) | R12A(addr.base) | (sljit_ins)addr.offset); + } - if (is_32bit) - ins = WHEN(is_u12(addr.offset), src, st, sty, addr); - else - ins = stg(src, addr.offset, addr.index, addr.base); + FAIL_IF(make_addr_bxy(compiler, &addr, dst, dstw, tmp1)); - return push_inst(compiler, ins); + ins = is_32bit ? 0xe30000000050 /* sty */ : 0xe30000000024 /* stg */; + return push_inst(compiler, ins | R36A(src_r) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset)); } #undef WHEN @@ -1638,12 +1643,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) { /* TODO(mundaym): implement all */ switch (feature_type) { + case SLJIT_HAS_FPU: case SLJIT_HAS_CLZ: - return have_eimm() ? 1 : 0; /* FLOGR instruction */ + case SLJIT_HAS_REV: + case SLJIT_HAS_ROT: + case SLJIT_HAS_PREFETCH: + case SLJIT_HAS_COPY_F32: + case SLJIT_HAS_COPY_F64: + return 1; + case SLJIT_HAS_CTZ: + return 2; case SLJIT_HAS_CMOV: return have_lscond1() ? 1 : 0; - case SLJIT_HAS_FPU: - return 1; } return 0; } @@ -1762,7 +1773,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp return SLJIT_SUCCESS; } -static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) +static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_gpr last_reg) { sljit_s32 offset, i, tmp; sljit_s32 local_size = compiler->local_size; @@ -1778,7 +1789,7 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) offset = 2 * SSIZE_OF(sw); if (saveds + scratches >= SLJIT_NUMBER_OF_REGISTERS) { if (kept_saveds_count == 0) { - FAIL_IF(push_inst(compiler, lmg(r6, r14, offset, r15))); + FAIL_IF(push_inst(compiler, lmg(r6, last_reg, offset, r15))); offset += 9 * SSIZE_OF(sw); } else { FAIL_IF(push_inst(compiler, lmg(r6, r13 - (sljit_gpr)kept_saveds_count, offset, r15))); @@ -1795,10 +1806,14 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) if (kept_saveds_count == 0) { if (saveds == 0) { - FAIL_IF(push_inst(compiler, lg(r14, offset, 0, r15))); + if (last_reg == r14) + FAIL_IF(push_inst(compiler, lg(r14, offset, 0, r15))); offset += SSIZE_OF(sw); + } else if (saveds == 1 && last_reg == r13) { + FAIL_IF(push_inst(compiler, lg(r13, offset, 0, r15))); + offset += 2 * SSIZE_OF(sw); } else { - FAIL_IF(push_inst(compiler, lmg(r14 - (sljit_gpr)saveds, r14, offset, r15))); + FAIL_IF(push_inst(compiler, lmg(r14 - (sljit_gpr)saveds, last_reg, offset, r15))); offset += (saveds + 1) * SSIZE_OF(sw); } } else if (saveds > kept_saveds_count) { @@ -1813,7 +1828,8 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) } if (kept_saveds_count > 0) { - FAIL_IF(push_inst(compiler, lg(r14, offset, 0, r15))); + if (last_reg == r14) + FAIL_IF(push_inst(compiler, lg(r14, offset, 0, r15))); offset += SSIZE_OF(sw); } @@ -1836,10 +1852,33 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler CHECK_ERROR(); CHECK(check_sljit_emit_return_void(compiler)); - FAIL_IF(emit_stack_frame_release(compiler)); + FAIL_IF(emit_stack_frame_release(compiler, r14)); return push_inst(compiler, br(r14)); /* return */ } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_return_to(compiler, src, srcw)); + + if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); + FAIL_IF(load_word(compiler, tmp1, src, srcw, 0 /* 64-bit */)); + src = TMP_REG2; + srcw = 0; + } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { + FAIL_IF(push_inst(compiler, lgr(tmp1, gpr(src)))); + src = TMP_REG2; + srcw = 0; + } + + FAIL_IF(emit_stack_frame_release(compiler, r13)); + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw); +} + /* --------------------------------------------------------------------- */ /* Operators */ /* --------------------------------------------------------------------- */ @@ -1928,12 +1967,85 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile return push_inst(compiler, lgr(arg1, tmp0)); } +static sljit_s32 sljit_emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 op, sljit_gpr dst_r, sljit_gpr src_r) +{ + sljit_s32 is_ctz = (GET_OPCODE(op) == SLJIT_CTZ); + + if ((op & SLJIT_32) && src_r != tmp0) { + FAIL_IF(push_inst(compiler, 0xb9160000 /* llgfr */ | R4A(tmp0) | R0A(src_r))); + src_r = tmp0; + } + + if (is_ctz) { + FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? 0x1300 /* lcr */ : 0xb9030000 /* lcgr */) | R4A(tmp1) | R0A(src_r))); + + if (src_r == tmp0) + FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? 0x1400 /* nr */ : 0xb9800000 /* ngr */) | R4A(tmp0) | R0A(tmp1))); + else + FAIL_IF(push_inst(compiler, 0xb9e40000 /* ngrk */ | R12A(tmp1) | R4A(tmp0) | R0A(src_r))); + + src_r = tmp0; + } + + FAIL_IF(push_inst(compiler, 0xb9830000 /* flogr */ | R4A(tmp0) | R0A(src_r))); + + if (is_ctz) + FAIL_IF(push_inst(compiler, 0xec00000000d9 /* aghik */ | R36A(tmp1) | R32A(tmp0) | ((sljit_ins)(-64 & 0xffff) << 16))); + + if (op & SLJIT_32) { + if (!is_ctz && dst_r != tmp0) + return push_inst(compiler, 0xec00000000d9 /* aghik */ | R36A(dst_r) | R32A(tmp0) | ((sljit_ins)(-32 & 0xffff) << 16)); + + FAIL_IF(push_inst(compiler, 0xc20800000000 /* agfi */ | R36A(tmp0) | (sljit_u32)-32)); + } + + if (is_ctz) + FAIL_IF(push_inst(compiler, 0xec0000000057 /* rxsbg */ | R36A(tmp0) | R32A(tmp1) | ((sljit_ins)((op & SLJIT_32) ? 59 : 58) << 24) | (63 << 16) | ((sljit_ins)((op & SLJIT_32) ? 5 : 6) << 8))); + + if (dst_r == tmp0) + return SLJIT_SUCCESS; + + return push_inst(compiler, ((op & SLJIT_32) ? 0x1800 /* lr */ : 0xb9040000 /* lgr */) | R4A(dst_r) | R0A(tmp0)); +} + +static sljit_s32 sljit_emit_rev(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ + struct addr addr; + sljit_gpr reg; + sljit_ins ins; + + if (dst & SLJIT_MEM) { + if (src & SLJIT_MEM) { + FAIL_IF(load_word(compiler, tmp0, src, srcw, op & SLJIT_32)); + reg = tmp0; + } else + reg = gpr(src); + + FAIL_IF(make_addr_bxy(compiler, &addr, dst, dstw, tmp1)); + ins = (op & SLJIT_32) ? 0xe3000000003e /* strv */ : 0xe3000000002f /* strvg */; + return push_inst(compiler, ins | R36A(reg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset)); + } + + reg = gpr(dst); + + if (src & SLJIT_MEM) { + FAIL_IF(make_addr_bxy(compiler, &addr, src, srcw, tmp1)); + ins = (op & SLJIT_32) ? 0xe3000000001e /* lrv */ : 0xe3000000000f /* lrvg */; + return push_inst(compiler, ins | R36A(reg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset)); + } + + ins = (op & SLJIT_32) ? 0xb91f0000 /* lrvr */ : 0xb90f0000 /* lrvgr */; + return push_inst(compiler, ins | R4A(reg) | R0A(gpr(src))); +} + /* LEVAL will be defined later with different parameters as needed */ #define WHEN2(cond, i1, i2) (cond) ? LEVAL(i1) : LEVAL(i2) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op, - sljit_s32 dst, sljit_sw dstw, - sljit_s32 src, sljit_sw srcw) + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) { sljit_ins ins; struct addr mem; @@ -2159,65 +2271,28 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile SLJIT_ASSERT((src & SLJIT_IMM) == 0); /* no immediates */ - dst_r = FAST_IS_REG(dst) ? gpr(REG_MASK & dst) : tmp0; - src_r = FAST_IS_REG(src) ? gpr(REG_MASK & src) : tmp0; - if (src & SLJIT_MEM) - FAIL_IF(load_word(compiler, src_r, src, srcw, src & SLJIT_32)); + dst_r = FAST_IS_REG(dst) ? gpr(dst) : tmp0; + src_r = FAST_IS_REG(src) ? gpr(src) : tmp0; compiler->status_flags_state = op & (VARIABLE_FLAG_MASK | SLJIT_SET_Z); /* TODO(mundaym): optimize loads and stores */ - switch (opcode | (op & SLJIT_32)) { - case SLJIT_NOT: - /* emulate ~x with x^-1 */ - FAIL_IF(push_load_imm_inst(compiler, tmp1, -1)); - if (src_r != dst_r) - FAIL_IF(push_inst(compiler, lgr(dst_r, src_r))); - - FAIL_IF(push_inst(compiler, xgr(dst_r, tmp1))); - break; - case SLJIT_NOT32: - /* emulate ~x with x^-1 */ - if (have_eimm()) - FAIL_IF(push_inst(compiler, xilf(dst_r, 0xffffffff))); - else { - FAIL_IF(push_load_imm_inst(compiler, tmp1, -1)); - if (src_r != dst_r) - FAIL_IF(push_inst(compiler, lr(dst_r, src_r))); - - FAIL_IF(push_inst(compiler, xr(dst_r, tmp1))); - } - break; + switch (opcode) { case SLJIT_CLZ: - if (have_eimm()) { - FAIL_IF(push_inst(compiler, flogr(tmp0, src_r))); /* clobbers tmp1 */ - if (dst_r != tmp0) - FAIL_IF(push_inst(compiler, lgr(dst_r, tmp0))); - } else { - abort(); /* TODO(mundaym): no eimm (?) */ - } - break; - case SLJIT_CLZ32: - if (have_eimm()) { - FAIL_IF(push_inst(compiler, sllg(tmp1, src_r, 32, 0))); - FAIL_IF(push_inst(compiler, iilf(tmp1, 0xffffffff))); - FAIL_IF(push_inst(compiler, flogr(tmp0, tmp1))); /* clobbers tmp1 */ - if (dst_r != tmp0) - FAIL_IF(push_inst(compiler, lr(dst_r, tmp0))); - } else { - abort(); /* TODO(mundaym): no eimm (?) */ - } + case SLJIT_CTZ: + if (src & SLJIT_MEM) + FAIL_IF(load_unsigned_word(compiler, src_r, src, srcw, op & SLJIT_32)); + + FAIL_IF(sljit_emit_clz_ctz(compiler, op, dst_r, src_r)); break; + case SLJIT_REV: + return sljit_emit_rev(compiler, op, dst, dstw, src, srcw); default: SLJIT_UNREACHABLE(); } - if ((op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_SET_Z | SLJIT_SET_OVERFLOW)) - FAIL_IF(update_zero_overflow(compiler, op, dst_r)); - - /* TODO(carenas): doesn't need FAIL_IF */ if (dst & SLJIT_MEM) - FAIL_IF(store_word(compiler, dst_r, dst, dstw, op & SLJIT_32)); + return store_word(compiler, dst_r, dst, dstw, op & SLJIT_32); return SLJIT_SUCCESS; } @@ -2236,11 +2311,6 @@ static SLJIT_INLINE int is_commutative(sljit_s32 op) return 0; } -static SLJIT_INLINE int is_shift(sljit_s32 op) { - sljit_s32 v = GET_OPCODE(op); - return (v == SLJIT_SHL || v == SLJIT_ASHR || v == SLJIT_LSHR) ? 1 : 0; -} - static const struct ins_forms add_forms = { 0x1a00, /* ar */ 0xb9080000, /* agr */ @@ -2639,12 +2709,12 @@ static sljit_s32 sljit_emit_bitwise(struct sljit_compiler *compiler, sljit_s32 o FAIL_IF(emit_move(compiler, tmp0, src1, src1w)); if ((imm & 0x000000000000ffffull) != 0 || imm == 0) - return push_inst(compiler, 0xa7010000 | R20A(src_r) | imm); + return push_inst(compiler, 0xa7010000 /* tmll */ | R20A(src_r) | imm); if ((imm & 0x00000000ffff0000ull) != 0) - return push_inst(compiler, 0xa7000000 | R20A(src_r) | (imm >> 16)); + return push_inst(compiler, 0xa7000000 /* tmlh */ | R20A(src_r) | (imm >> 16)); if ((imm & 0x0000ffff00000000ull) != 0) - return push_inst(compiler, 0xa7030000 | R20A(src_r) | (imm >> 32)); - return push_inst(compiler, 0xa7020000 | R20A(src_r) | (imm >> 48)); + return push_inst(compiler, 0xa7030000 /* tmhl */ | R20A(src_r) | (imm >> 32)); + return push_inst(compiler, 0xa7020000 /* tmhh */ | R20A(src_r) | (imm >> 48)); } if (!(op & SLJIT_SET_Z)) @@ -2674,33 +2744,41 @@ static sljit_s32 sljit_emit_shift(struct sljit_compiler *compiler, sljit_s32 op, sljit_ins ins; if (FAST_IS_REG(src1)) - src_r = gpr(src1 & REG_MASK); + src_r = gpr(src1); else FAIL_IF(emit_move(compiler, tmp0, src1, src1w)); - if (src2 & SLJIT_IMM) + if (!(src2 & SLJIT_IMM)) { + if (FAST_IS_REG(src2)) + base_r = gpr(src2); + else { + FAIL_IF(emit_move(compiler, tmp1, src2, src2w)); + base_r = tmp1; + } + + if ((op & SLJIT_32) && (type == SLJIT_MSHL || type == SLJIT_MLSHR || type == SLJIT_MASHR)) { + if (base_r != tmp1) { + FAIL_IF(push_inst(compiler, 0xec0000000055 /* risbg */ | R36A(tmp1) | R32A(base_r) | (59 << 24) | (1 << 23) | (63 << 16))); + base_r = tmp1; + } else + FAIL_IF(push_inst(compiler, 0xa5070000 /* nill */ | R20A(tmp1) | 0x1f)); + } + } else imm = (sljit_ins)(src2w & ((op & SLJIT_32) ? 0x1f : 0x3f)); - else if (FAST_IS_REG(src2)) - base_r = gpr(src2 & REG_MASK); - else { - FAIL_IF(emit_move(compiler, tmp1, src2, src2w)); - base_r = tmp1; - } if ((op & SLJIT_32) && dst_r == src_r) { - if (type == SLJIT_SHL) + if (type == SLJIT_SHL || type == SLJIT_MSHL) ins = 0x89000000 /* sll */; - else if (type == SLJIT_LSHR) + else if (type == SLJIT_LSHR || type == SLJIT_MLSHR) ins = 0x88000000 /* srl */; else ins = 0x8a000000 /* sra */; FAIL_IF(push_inst(compiler, ins | R20A(dst_r) | R12A(base_r) | imm)); - } - else { - if (type == SLJIT_SHL) + } else { + if (type == SLJIT_SHL || type == SLJIT_MSHL) ins = (op & SLJIT_32) ? 0xeb00000000df /* sllk */ : 0xeb000000000d /* sllg */; - else if (type == SLJIT_LSHR) + else if (type == SLJIT_LSHR || type == SLJIT_MLSHR) ins = (op & SLJIT_32) ? 0xeb00000000de /* srlk */ : 0xeb000000000c /* srlg */; else ins = (op & SLJIT_32) ? 0xeb00000000dc /* srak */ : 0xeb000000000a /* srag */; @@ -2714,6 +2792,47 @@ static sljit_s32 sljit_emit_shift(struct sljit_compiler *compiler, sljit_s32 op, return SLJIT_SUCCESS; } +static sljit_s32 sljit_emit_rotate(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) +{ + sljit_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0; + sljit_gpr src_r = tmp0; + sljit_gpr base_r = tmp0; + sljit_ins imm = 0; + sljit_ins ins; + + if (FAST_IS_REG(src1)) + src_r = gpr(src1); + else + FAIL_IF(emit_move(compiler, tmp0, src1, src1w)); + + if (!(src2 & SLJIT_IMM)) { + if (FAST_IS_REG(src2)) + base_r = gpr(src2); + else { + FAIL_IF(emit_move(compiler, tmp1, src2, src2w)); + base_r = tmp1; + } + } + + if (GET_OPCODE(op) == SLJIT_ROTR) { + if (!(src2 & SLJIT_IMM)) { + ins = (op & SLJIT_32) ? 0x1300 /* lcr */ : 0xb9030000 /* lcgr */; + FAIL_IF(push_inst(compiler, ins | R4A(tmp1) | R0A(base_r))); + base_r = tmp1; + } else + src2w = -src2w; + } + + if (src2 & SLJIT_IMM) + imm = (sljit_ins)(src2w & ((op & SLJIT_32) ? 0x1f : 0x3f)); + + ins = (op & SLJIT_32) ? 0xeb000000001d /* rll */ : 0xeb000000001c /* rllg */; + return push_inst(compiler, ins | R36A(dst_r) | R32A(src_r) | R28A(base_r) | (imm << 16)); +} + static const struct ins_forms addc_forms = { 0xb9980000, /* alcr */ 0xb9880000, /* alcgr */ @@ -2786,10 +2905,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile FAIL_IF(sljit_emit_bitwise(compiler, op, dst, src1, src1w, src2, src2w)); break; case SLJIT_SHL: + case SLJIT_MSHL: case SLJIT_LSHR: + case SLJIT_MLSHR: case SLJIT_ASHR: + case SLJIT_MASHR: FAIL_IF(sljit_emit_shift(compiler, op, dst, src1, src1w, src2, src2w)); break; + case SLJIT_ROTL: + case SLJIT_ROTR: + FAIL_IF(sljit_emit_rotate(compiler, op, dst, src1, src1w, src2, src2w)); + break; } if (dst & SLJIT_MEM) @@ -2808,11 +2934,129 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil return sljit_emit_op2(compiler, op, (sljit_s32)tmp0, 0, src1, src1w, src2, src2w); } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src( - struct sljit_compiler *compiler, - sljit_s32 op, sljit_s32 src, sljit_sw srcw) +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst_reg, + sljit_s32 src1_reg, + sljit_s32 src2_reg, + sljit_s32 src3, sljit_sw src3w) +{ + sljit_s32 is_right; + sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64; + sljit_gpr dst_r = gpr(dst_reg); + sljit_gpr src1_r = gpr(src1_reg); + sljit_gpr src2_r = gpr(src2_reg); + sljit_gpr src3_r = tmp1; + sljit_ins ins; + + CHECK_ERROR(); + CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w)); + + is_right = (GET_OPCODE(op) == SLJIT_LSHR || GET_OPCODE(op) == SLJIT_MLSHR); + + if (src1_reg == src2_reg) { + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_op2(compiler, (is_right ? SLJIT_ROTR : SLJIT_ROTL) | (op & SLJIT_32), dst_reg, 0, src1_reg, 0, src3, src3w); + } + + ADJUST_LOCAL_OFFSET(src3, src3w); + + if (src3 & SLJIT_IMM) { + src3w &= bit_length - 1; + + if (src3w == 0) + return SLJIT_SUCCESS; + + if (op & SLJIT_32) { + if (dst_r == src1_r) { + ins = is_right ? 0x88000000 /* srl */ : 0x89000000 /* sll */; + FAIL_IF(push_inst(compiler, ins | R20A(dst_r) | (sljit_ins)src3w)); + } else { + ins = is_right ? 0xeb00000000de /* srlk */ : 0xeb00000000df /* sllk */; + FAIL_IF(push_inst(compiler, ins | R36A(dst_r) | R32A(src1_r) | ((sljit_ins)src3w << 16))); + } + } else { + ins = is_right ? 0xeb000000000c /* srlg */ : 0xeb000000000d /* sllg */; + FAIL_IF(push_inst(compiler, ins | R36A(dst_r) | R32A(src1_r) | ((sljit_ins)src3w << 16))); + } + + ins = 0xec0000000055 /* risbg */; + + if (is_right) { + src3w = bit_length - src3w; + ins |= ((sljit_ins)(64 - bit_length) << 24) | ((sljit_ins)(63 - src3w) << 16) | ((sljit_ins)src3w << 8); + } else + ins |= ((sljit_ins)(64 - src3w) << 24) | ((sljit_ins)63 << 16) | ((sljit_ins)(src3w + 64 - bit_length) << 8); + + return push_inst(compiler, ins | R36A(dst_r) | R32A(src2_r)); + } + + if (!(src3 & SLJIT_MEM)) { + src3_r = gpr(src3); + + if (dst_r == src3_r) { + FAIL_IF(push_inst(compiler, 0x1800 /* lr */ | R4A(tmp1) | R0A(src3_r))); + src3_r = tmp1; + } + } else + FAIL_IF(load_word(compiler, tmp1, src3, src3w, op & SLJIT_32)); + + if (op & SLJIT_32) { + if (GET_OPCODE(op) == SLJIT_MSHL || GET_OPCODE(op) == SLJIT_MLSHR) { + if (src3_r != tmp1) { + FAIL_IF(push_inst(compiler, 0xec0000000055 /* risbg */ | R36A(tmp1) | R32A(src3_r) | (59 << 24) | (1 << 23) | (63 << 16))); + src3_r = tmp1; + } else + FAIL_IF(push_inst(compiler, 0xa5070000 /* nill */ | R20A(tmp1) | 0x1f)); + } + + if (dst_r == src1_r) { + ins = is_right ? 0x88000000 /* srl */ : 0x89000000 /* sll */; + FAIL_IF(push_inst(compiler, ins | R20A(dst_r) | R12A(src3_r))); + } else { + ins = is_right ? 0xeb00000000de /* srlk */ : 0xeb00000000df /* sllk */; + FAIL_IF(push_inst(compiler, ins | R36A(dst_r) | R32A(src1_r) | R28A(src3_r))); + } + + if (src3_r != tmp1) { + FAIL_IF(push_inst(compiler, 0xa50f0000 /* llill */ | R20A(tmp1) | 0x1f)); + FAIL_IF(push_inst(compiler, 0x1700 /* xr */ | R4A(tmp1) | R0A(src3_r))); + } else + FAIL_IF(push_inst(compiler, 0xc00700000000 /* xilf */ | R36A(tmp1) | 0x1f)); + + ins = is_right ? 0xeb00000000df /* sllk */ : 0xeb00000000de /* srlk */; + FAIL_IF(push_inst(compiler, ins | R36A(tmp0) | R32A(src2_r) | R28A(tmp1) | (0x1 << 16))); + + return push_inst(compiler, 0x1600 /* or */ | R4A(dst_r) | R0A(tmp0)); + } + + ins = is_right ? 0xeb000000000c /* srlg */ : 0xeb000000000d /* sllg */; + FAIL_IF(push_inst(compiler, ins | R36A(dst_r) | R32A(src1_r) | R28A(src3_r))); + + ins = is_right ? 0xeb000000000d /* sllg */ : 0xeb000000000c /* srlg */; + + if (!(op & SLJIT_SHIFT_INTO_NON_ZERO)) { + if (src3_r != tmp1) + FAIL_IF(push_inst(compiler, 0xa50f0000 /* llill */ | R20A(tmp1) | 0x3f)); + + FAIL_IF(push_inst(compiler, ins | R36A(tmp0) | R32A(src2_r) | (0x1 << 16))); + src2_r = tmp0; + + if (src3_r != tmp1) + FAIL_IF(push_inst(compiler, 0xb9820000 /* xgr */ | R4A(tmp1) | R0A(src3_r))); + else + FAIL_IF(push_inst(compiler, 0xc00700000000 /* xilf */ | R36A(tmp1) | 0x3f)); + } else + FAIL_IF(push_inst(compiler, 0xb9030000 /* lcgr */ | R4A(tmp1) | R0A(src3_r))); + + FAIL_IF(push_inst(compiler, ins | R36A(tmp0) | R32A(src2_r) | R28A(tmp1))); + return push_inst(compiler, 0xb9810000 /* ogr */ | R4A(dst_r) | R0A(tmp0)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src, sljit_sw srcw) { sljit_gpr src_r; + struct addr addr; CHECK_ERROR(); CHECK(check_sljit_emit_op_src(compiler, op, src, srcw)); @@ -2826,22 +3070,49 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src( return push_inst(compiler, br(src_r)); case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN: - /* TODO(carenas): implement? */ return SLJIT_SUCCESS; case SLJIT_PREFETCH_L1: case SLJIT_PREFETCH_L2: case SLJIT_PREFETCH_L3: case SLJIT_PREFETCH_ONCE: - /* TODO(carenas): implement */ - return SLJIT_SUCCESS; + FAIL_IF(make_addr_bxy(compiler, &addr, src, srcw, tmp1)); + return push_inst(compiler, 0xe31000000036 /* pfd */ | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset)); default: - /* TODO(carenas): probably should not success by default */ return SLJIT_SUCCESS; } return SLJIT_SUCCESS; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw) +{ + sljit_gpr dst_r = link_r; + sljit_s32 size; + + CHECK_ERROR(); + CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw)); + ADJUST_LOCAL_OFFSET(dst, dstw); + + switch (op) { + case SLJIT_FAST_ENTER: + if (FAST_IS_REG(dst)) + return push_inst(compiler, lgr(gpr(dst), link_r)); + break; + case SLJIT_GET_RETURN_ADDRESS: + dst_r = FAST_IS_REG(dst) ? gpr(dst) : tmp0; + + size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds - SLJIT_KEPT_SAVEDS_COUNT(compiler->options), 2); + FAIL_IF(load_word(compiler, dst_r, SLJIT_MEM1(SLJIT_SP), compiler->local_size + size, 0)); + break; + } + + if (dst & SLJIT_MEM) + return store_word(compiler, dst_r, dst, dstw, 0); + + return SLJIT_SUCCESS; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_register_index(reg)); @@ -2851,7 +3122,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_float_register_index(reg)); - return (sljit_s32)fgpr(reg); + return (sljit_s32)freg_map[reg]; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, @@ -3120,21 +3391,31 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil return SLJIT_SUCCESS; } -/* --------------------------------------------------------------------- */ -/* Other instructions */ -/* --------------------------------------------------------------------- */ - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 freg, sljit_s32 reg) { + sljit_gpr gen_r; + CHECK_ERROR(); - CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); - ADJUST_LOCAL_OFFSET(dst, dstw); + CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg)); - if (FAST_IS_REG(dst)) - return push_inst(compiler, lgr(gpr(dst), fast_link_r)); + gen_r = gpr(reg); - /* memory */ - return store_word(compiler, fast_link_r, dst, dstw, 0); + if (GET_OPCODE(op) == SLJIT_COPY_TO_F64) { + if (op & SLJIT_32) { + FAIL_IF(push_inst(compiler, 0xeb000000000d /* sllg */ | R36A(tmp0) | R32A(gen_r) | (32 << 16))); + gen_r = tmp0; + } + + return push_inst(compiler, 0xb3c10000 /* ldgr */ | F4(freg) | R0A(gen_r)); + } + + FAIL_IF(push_inst(compiler, 0xb3cd0000 /* lgdr */ | R4A(gen_r) | F0(freg))); + + if (!(op & SLJIT_32)) + return SLJIT_SUCCESS; + + return push_inst(compiler, 0xeb000000000c /* srlg */ | R36A(gen_r) | R32A(gen_r) | (32 << 16)); } /* --------------------------------------------------------------------- */ @@ -3174,7 +3455,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile /* emit jump instruction */ type &= 0xff; if (type >= SLJIT_FAST_CALL) - PTR_FAIL_IF(push_inst(compiler, brasl(type == SLJIT_FAST_CALL ? fast_link_r : link_r, 0))); + PTR_FAIL_IF(push_inst(compiler, brasl(link_r, 0))); else PTR_FAIL_IF(push_inst(compiler, brcl(mask, 0))); @@ -3189,7 +3470,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); if (type & SLJIT_CALL_RETURN) { - PTR_FAIL_IF(emit_stack_frame_release(compiler)); + PTR_FAIL_IF(emit_stack_frame_release(compiler, r14)); type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP); } @@ -3215,7 +3496,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi /* emit jump instruction */ if (type >= SLJIT_FAST_CALL) - return push_inst(compiler, basr(type == SLJIT_FAST_CALL ? fast_link_r : link_r, src_r)); + return push_inst(compiler, basr(link_r, src_r)); return push_inst(compiler, br(src_r)); } @@ -3233,15 +3514,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi ADJUST_LOCAL_OFFSET(src, srcw); FAIL_IF(load_word(compiler, tmp1, src, srcw, 0 /* 64-bit */)); src = TMP_REG2; + srcw = 0; } if (type & SLJIT_CALL_RETURN) { - if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) { + if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { FAIL_IF(push_inst(compiler, lgr(tmp1, gpr(src)))); src = TMP_REG2; + srcw = 0; } - FAIL_IF(emit_stack_frame_release(compiler)); + FAIL_IF(emit_stack_frame_release(compiler, r14)); type = SLJIT_JUMP; } @@ -3323,27 +3606,92 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil sljit_s32 dst_reg, sljit_s32 src, sljit_sw srcw) { - sljit_u8 mask = get_cc(compiler, type); - sljit_gpr dst_r = gpr(dst_reg & ~SLJIT_32); - sljit_gpr src_r = FAST_IS_REG(src) ? gpr(src) : tmp0; + sljit_ins mask = get_cc(compiler, type & ~SLJIT_32); + sljit_gpr src_r; + sljit_ins ins; CHECK_ERROR(); CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); - if (src & SLJIT_IMM) { - /* TODO(mundaym): fast path with lscond2 */ - FAIL_IF(push_load_imm_inst(compiler, src_r, srcw)); + if (type & SLJIT_32) + srcw = (sljit_s32)srcw; + + if (have_lscond2() && (src & SLJIT_IMM) && is_s16(srcw)) { + ins = (type & SLJIT_32) ? 0xec0000000042 /* lochi */ : 0xec0000000046 /* locghi */; + return push_inst(compiler, ins | R36A(gpr(dst_reg)) | (mask << 32) | (sljit_ins)(srcw & 0xffff) << 16); } - #define LEVAL(i) i(dst_r, src_r, mask) - if (have_lscond1()) - return push_inst(compiler, - WHEN2(dst_reg & SLJIT_32, locr, locgr)); + if (src & SLJIT_IMM) { + FAIL_IF(push_load_imm_inst(compiler, tmp0, srcw)); + src_r = tmp0; + } else + src_r = gpr(src); - #undef LEVAL + if (have_lscond1()) { + ins = (type & SLJIT_32) ? 0xb9f20000 /* locr */ : 0xb9e20000 /* locgr */; + return push_inst(compiler, ins | (mask << 12) | R4A(gpr(dst_reg)) | R0A(src_r)); + } - /* TODO(mundaym): implement */ - return SLJIT_ERR_UNSUPPORTED; + return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 reg, + sljit_s32 mem, sljit_sw memw) +{ + sljit_ins ins, reg1, reg2, base, offs = 0; + + CHECK_ERROR(); + CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); + + if (!(reg & REG_PAIR_MASK)) + return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw); + + ADJUST_LOCAL_OFFSET(mem, memw); + + base = gpr(mem & REG_MASK); + reg1 = gpr(REG_PAIR_FIRST(reg)); + reg2 = gpr(REG_PAIR_SECOND(reg)); + + if (mem & OFFS_REG_MASK) { + memw &= 0x3; + offs = gpr(OFFS_REG(mem)); + + if (memw != 0) { + FAIL_IF(push_inst(compiler, 0xeb000000000d /* sllg */ | R36A(tmp1) | R32A(offs) | ((sljit_ins)memw << 16))); + offs = tmp1; + } else if (!(type & SLJIT_MEM_STORE) && (base == reg1 || base == reg2) && (offs == reg1 || offs == reg2)) { + FAIL_IF(push_inst(compiler, 0xb9f80000 | R12A(tmp1) | R4A(base) | R0A(offs))); + base = tmp1; + offs = 0; + } + + memw = 0; + } else if (memw < -0x80000 || memw > 0x7ffff - ((reg2 == reg1 + 1) ? 0 : SSIZE_OF(sw))) { + FAIL_IF(push_load_imm_inst(compiler, tmp1, memw)); + + if (base == 0) + base = tmp1; + else + offs = tmp1; + + memw = 0; + } + + if (offs == 0 && reg2 == (reg1 + 1)) { + ins = (type & SLJIT_MEM_STORE) ? 0xeb0000000024 /* stmg */ : 0xeb0000000004 /* lmg */; + return push_inst(compiler, ins | R36A(reg1) | R32A(reg2) | R28A(base) | disp_s20((sljit_s32)memw)); + } + + ins = ((type & SLJIT_MEM_STORE) ? 0xe30000000024 /* stg */ : 0xe30000000004 /* lg */) | R32A(offs) | R28A(base); + + if (!(type & SLJIT_MEM_STORE) && base == reg1) { + FAIL_IF(push_inst(compiler, ins | R36A(reg2) | disp_s20((sljit_s32)memw + SSIZE_OF(sw)))); + return push_inst(compiler, ins | R36A(reg1) | disp_s20((sljit_s32)memw)); + } + + FAIL_IF(push_inst(compiler, ins | R36A(reg1) | disp_s20((sljit_s32)memw))); + return push_inst(compiler, ins | R36A(reg2) | disp_s20((sljit_s32)memw + SSIZE_OF(sw))); } /* --------------------------------------------------------------------- */ diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeX86_32.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeX86_32.c index 2a45a2ca6c..69c917101f 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeX86_32.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeX86_32.c @@ -114,7 +114,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw inst_size += 4; } else if (flags & EX86_SHIFT_INS) { - imma &= 0x1f; + SLJIT_ASSERT(imma <= 0x1f); if (imma != 1) { inst_size++; flags |= EX86_BYTE_ARG; @@ -528,20 +528,27 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp return SLJIT_SUCCESS; } -static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) +static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to) { sljit_s32 kept_saveds_count = SLJIT_KEPT_SAVEDS_COUNT(compiler->options); - sljit_s32 saveds; + sljit_s32 local_size, saveds; sljit_uw size; sljit_u8 *inst; - BINARY_IMM32(ADD, compiler->local_size, SLJIT_SP, 0); - size = (sljit_uw)((compiler->scratches > 9 ? (compiler->scratches - 9) : 0) + (compiler->saveds <= 3 ? compiler->saveds : 3) - kept_saveds_count); + local_size = compiler->local_size; + if (!(compiler->options & SLJIT_ENTER_REG_ARG)) size++; + else if (is_return_to && size == 0) { + local_size += SSIZE_OF(sw); + is_return_to = 0; + } + + if (local_size > 0) + BINARY_IMM32(ADD, local_size, SLJIT_SP, 0); if (size == 0) return SLJIT_SUCCESS; @@ -563,6 +570,9 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) if (!(compiler->options & SLJIT_ENTER_REG_ARG)) POP_REG(reg_map[TMP_REG1]); + if (is_return_to) + BINARY_IMM32(ADD, sizeof(sljit_sw), SLJIT_SP, 0); + return SLJIT_SUCCESS; } @@ -576,7 +586,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler SLJIT_ASSERT(compiler->args_size >= 0); SLJIT_ASSERT(compiler->local_size > 0); - FAIL_IF(emit_stack_frame_release(compiler)); + FAIL_IF(emit_stack_frame_release(compiler, 0)); inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); FAIL_IF(!inst); @@ -585,6 +595,31 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler return SLJIT_SUCCESS; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw) +{ + sljit_s32 src_r; + + CHECK_ERROR(); + CHECK(check_sljit_emit_return_to(compiler, src, srcw)); + + if ((src & SLJIT_MEM) || (src > SLJIT_R2 && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options)))) { + ADJUST_LOCAL_OFFSET(src, srcw); + CHECK_EXTRA_REGS(src, srcw, (void)0); + + src_r = (compiler->options & SLJIT_ENTER_REG_ARG) ? TMP_REG1 : SLJIT_R1; + + EMIT_MOV(compiler, src_r, 0, src, srcw); + src = src_r; + srcw = 0; + } + + FAIL_IF(emit_stack_frame_release(compiler, 1)); + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw); +} + /* --------------------------------------------------------------------- */ /* Call / return instructions */ /* --------------------------------------------------------------------- */ @@ -796,7 +831,7 @@ static sljit_s32 tail_call_with_args(struct sljit_compiler *compiler, types >>= SLJIT_ARG_SHIFT; } - return emit_stack_frame_release(compiler); + return emit_stack_frame_release(compiler, 0); } stack_size = args_size + SSIZE_OF(sw); @@ -971,7 +1006,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile if (type & SLJIT_CALL_RETURN) { if ((type & 0xff) == SLJIT_CALL_REG_ARG) { PTR_FAIL_IF(tail_call_reg_arg_with_args(compiler, arg_types)); - PTR_FAIL_IF(emit_stack_frame_release(compiler)); + PTR_FAIL_IF(emit_stack_frame_release(compiler, 0)); SLJIT_SKIP_CHECKS(compiler); return sljit_emit_jump(compiler, SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP)); @@ -1022,7 +1057,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi if ((type & 0xff) == SLJIT_CALL_REG_ARG) { FAIL_IF(tail_call_reg_arg_with_args(compiler, arg_types)); - if ((src & SLJIT_MEM) || (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0)) { + if ((src & SLJIT_MEM) || (src > SLJIT_R2 && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options)))) { ADJUST_LOCAL_OFFSET(src, srcw); CHECK_EXTRA_REGS(src, srcw, (void)0); @@ -1031,7 +1066,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi srcw = 0; } - FAIL_IF(emit_stack_frame_release(compiler)); + FAIL_IF(emit_stack_frame_release(compiler, 0)); SLJIT_SKIP_CHECKS(compiler); return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw); @@ -1080,14 +1115,37 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi return post_call_with_args(compiler, arg_types, stack_size); } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) +static SLJIT_INLINE sljit_s32 emit_fmov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) +{ + sljit_u8* inst; + + if (compiler->options & SLJIT_ENTER_REG_ARG) { + if (src == SLJIT_FR0) + return SLJIT_SUCCESS; + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_fop1(compiler, op, SLJIT_RETURN_FREG, 0, src, srcw); + } + + if (FAST_IS_REG(src)) { + FAIL_IF(emit_sse2_store(compiler, op & SLJIT_32, SLJIT_MEM1(SLJIT_SP), 0, src)); + + src = SLJIT_MEM1(SLJIT_SP); + srcw = 0; + } else { + ADJUST_LOCAL_OFFSET(src, srcw); + } + + inst = emit_x86_instruction(compiler, 1 | EX86_SSE2_OP1, 0, 0, src, srcw); + *inst = (op & SLJIT_32) ? FLDS : FLDL; + + return SLJIT_SUCCESS; +} + +static sljit_s32 emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) { sljit_u8 *inst; - CHECK_ERROR(); - CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); - ADJUST_LOCAL_OFFSET(dst, dstw); - CHECK_EXTRA_REGS(dst, dstw, (void)0); if (FAST_IS_REG(dst)) { @@ -1103,7 +1161,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * /* Memory. */ inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw); FAIL_IF(!inst); - *inst++ = POP_rm; + *inst = POP_rm; return SLJIT_SUCCESS; } @@ -1123,8 +1181,8 @@ static sljit_s32 emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src else { inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw); FAIL_IF(!inst); - *inst++ = GROUP_FF; - *inst |= PUSH_rm; + inst[0] = GROUP_FF; + inst[1] |= PUSH_rm; inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); FAIL_IF(!inst); @@ -1135,8 +1193,24 @@ static sljit_s32 emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src return SLJIT_SUCCESS; } +static sljit_s32 sljit_emit_get_return_address(struct sljit_compiler *compiler, + sljit_s32 dst, sljit_sw dstw) +{ + sljit_s32 options = compiler->options; + sljit_s32 saveds = compiler->saveds; + sljit_s32 scratches = compiler->scratches; + + saveds = ((scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3) - SLJIT_KEPT_SAVEDS_COUNT(options)) * SSIZE_OF(sw); + + /* Saving ebp. */ + if (!(options & SLJIT_ENTER_REG_ARG)) + saveds += SSIZE_OF(sw); + + return emit_mov(compiler, dst, dstw, SLJIT_MEM1(SLJIT_SP), compiler->local_size + saveds); +} + /* --------------------------------------------------------------------- */ -/* Memory operations */ +/* Other operations */ /* --------------------------------------------------------------------- */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, @@ -1150,12 +1224,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile CHECK_ERROR(); CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); - if (!(reg & REG_PAIR_MASK)) { - if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) - return SLJIT_ERR_UNSUPPORTED; - + if (!(reg & REG_PAIR_MASK)) return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw); - } ADJUST_LOCAL_OFFSET(mem, memw); @@ -1221,6 +1291,79 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile return SLJIT_SUCCESS; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 freg, sljit_s32 reg) +{ + sljit_u8 *inst; + sljit_s32 reg2; + sljit_sw regw, reg2w; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg)); + + regw = 0; + reg2 = 0; + reg2w = 0; + + if (reg & REG_PAIR_MASK) { + reg2 = REG_PAIR_SECOND(reg); + reg = REG_PAIR_FIRST(reg); + + if (reg == reg2) + reg = 0; + + CHECK_EXTRA_REGS(reg2, reg2w, (void)0); + } + + CHECK_EXTRA_REGS(reg, regw, (void)0); + + if (op & SLJIT_32) { + inst = emit_x86_instruction(compiler, 2 | EX86_PREF_66 | EX86_SSE2_OP1, freg, 0, reg, regw); + inst[0] = GROUP_0F; + inst[1] = GET_OPCODE(op) == SLJIT_COPY_TO_F64 ? MOVD_x_rm : MOVD_rm_x; + return SLJIT_SUCCESS; + } + + if (op == SLJIT_COPY_FROM_F64) { + inst = (sljit_u8*)ensure_buf(compiler, 1 + 5); + FAIL_IF(!inst); + INC_SIZE(5); + + inst[0] = GROUP_66; + inst[1] = GROUP_0F; + inst[2] = PSHUFD_x_xm; + inst[3] = U8(MOD_REG | (TMP_FREG << 3) | freg); + inst[4] = 1; + } else if (reg != 0) { + inst = emit_x86_instruction(compiler, 2 | EX86_PREF_66 | EX86_SSE2_OP1, TMP_FREG, 0, reg, regw); + inst[0] = GROUP_0F; + inst[1] = MOVD_x_rm; + } + + if (reg2 != 0) { + inst = emit_x86_instruction(compiler, 2 | EX86_PREF_66 | EX86_SSE2_OP1, freg, 0, reg2, reg2w); + inst[0] = GROUP_0F; + inst[1] = GET_OPCODE(op) == SLJIT_COPY_TO_F64 ? MOVD_x_rm : MOVD_rm_x; + } + + if (GET_OPCODE(op) == SLJIT_COPY_TO_F64) { + inst = (sljit_u8*)ensure_buf(compiler, 1 + 4); + FAIL_IF(!inst); + INC_SIZE(4); + + inst[0] = GROUP_66; + inst[1] = GROUP_0F; + inst[2] = PUNPCKLDQ_x_xm; + inst[3] = U8(MOD_REG | (freg << 3) | (reg == 0 ? freg : TMP_FREG)); + } else { + inst = emit_x86_instruction(compiler, 2 | EX86_PREF_66 | EX86_SSE2_OP1, TMP_FREG, 0, reg, regw); + inst[0] = GROUP_0F; + inst[1] = MOVD_rm_x; + } + + return SLJIT_SUCCESS; +} + static sljit_s32 skip_frames_before_return(struct sljit_compiler *compiler) { sljit_sw size; diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeX86_64.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeX86_64.c index 7b0d7cea4a..b5efc1fda1 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeX86_64.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeX86_64.c @@ -37,9 +37,9 @@ static sljit_s32 emit_load_imm64(struct sljit_compiler *compiler, sljit_s32 reg, inst = (sljit_u8*)ensure_buf(compiler, 1 + 2 + sizeof(sljit_sw)); FAIL_IF(!inst); INC_SIZE(2 + sizeof(sljit_sw)); - *inst++ = REX_W | ((reg_map[reg] <= 7) ? 0 : REX_B); - *inst++ = U8(MOV_r_i32 | (reg_map[reg] & 0x7)); - sljit_unaligned_store_sw(inst, imm); + inst[0] = REX_W | ((reg_map[reg] <= 7) ? 0 : REX_B); + inst[1] = U8(MOV_r_i32 | (reg_map[reg] & 0x7)); + sljit_unaligned_store_sw(inst + 2, imm); return SLJIT_SUCCESS; } @@ -157,7 +157,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw inst_size += 4; } else if (flags & EX86_SHIFT_INS) { - imma &= compiler->mode32 ? 0x1f : 0x3f; + SLJIT_ASSERT(imma <= (compiler->mode32 ? 0x1f : 0x3f)); if (imma != 1) { inst_size++; flags |= EX86_BYTE_ARG; @@ -196,6 +196,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw *inst++ = 0x66; if (rex) *inst++ = rex; + buf_ptr = inst + size; /* Encode mod/rm byte. */ @@ -370,6 +371,12 @@ static sljit_u8* generate_put_label_code(struct sljit_put_label *put_label, slji return code_ptr; } +#ifdef _WIN64 +typedef struct { + sljit_sw regs[2]; +} sljit_sse2_reg; +#endif /* _WIN64 */ + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) @@ -423,7 +430,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi #ifdef _WIN64 local_size += SLJIT_LOCALS_OFFSET; - saved_float_regs_size = GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, 16); + saved_float_regs_size = GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sse2_reg); if (saved_float_regs_size > 0) { saved_float_regs_offset = ((local_size + 0xf) & ~0xf); @@ -533,15 +540,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi tmp = SLJIT_FS0 - fsaveds; for (i = SLJIT_FS0; i > tmp; i--) { inst = emit_x86_instruction(compiler, 2 | EX86_SSE2, i, 0, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset); - *inst++ = GROUP_0F; - *inst = MOVAPS_xm_x; + inst[0] = GROUP_0F; + inst[1] = MOVAPS_xm_x; saved_float_regs_offset += 16; } for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) { inst = emit_x86_instruction(compiler, 2 | EX86_SSE2, i, 0, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset); - *inst++ = GROUP_0F; - *inst = MOVAPS_xm_x; + inst[0] = GROUP_0F; + inst[1] = MOVAPS_xm_x; saved_float_regs_offset += 16; } } @@ -565,7 +572,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp #ifdef _WIN64 local_size += SLJIT_LOCALS_OFFSET; - saved_float_regs_size = GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, 16); + saved_float_regs_size = GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sse2_reg); if (saved_float_regs_size > 0) local_size = ((local_size + 0xf) & ~0xf) + saved_float_regs_size; @@ -579,10 +586,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp return SLJIT_SUCCESS; } -static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) +static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to) { sljit_uw size; - sljit_s32 i, tmp; + sljit_s32 local_size, i, tmp; sljit_u8 *inst; #ifdef _WIN64 sljit_s32 saved_float_regs_offset; @@ -591,7 +598,7 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) #endif /* _WIN64 */ #ifdef _WIN64 - saved_float_regs_offset = GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, 16); + saved_float_regs_offset = GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sse2_reg); if (saved_float_regs_offset > 0) { compiler->mode32 = 1; @@ -600,41 +607,32 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) tmp = SLJIT_FS0 - fsaveds; for (i = SLJIT_FS0; i > tmp; i--) { inst = emit_x86_instruction(compiler, 2 | EX86_SSE2, i, 0, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset); - *inst++ = GROUP_0F; - *inst = MOVAPS_x_xm; + inst[0] = GROUP_0F; + inst[1] = MOVAPS_x_xm; saved_float_regs_offset += 16; } for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) { inst = emit_x86_instruction(compiler, 2 | EX86_SSE2, i, 0, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset); - *inst++ = GROUP_0F; - *inst = MOVAPS_x_xm; + inst[0] = GROUP_0F; + inst[1] = MOVAPS_x_xm; saved_float_regs_offset += 16; } + + compiler->mode32 = 0; } #endif /* _WIN64 */ - if (compiler->local_size > 0) { - if (compiler->local_size <= 127) { - inst = (sljit_u8*)ensure_buf(compiler, 1 + 4); - FAIL_IF(!inst); - INC_SIZE(4); - *inst++ = REX_W; - *inst++ = GROUP_BINARY_83; - *inst++ = MOD_REG | ADD | 4; - *inst = U8(compiler->local_size); - } - else { - inst = (sljit_u8*)ensure_buf(compiler, 1 + 7); - FAIL_IF(!inst); - INC_SIZE(7); - *inst++ = REX_W; - *inst++ = GROUP_BINARY_81; - *inst++ = MOD_REG | ADD | 4; - sljit_unaligned_store_s32(inst, compiler->local_size); - } + local_size = compiler->local_size; + + if (is_return_to && compiler->scratches < SLJIT_FIRST_SAVED_REG && (compiler->saveds == SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { + local_size += SSIZE_OF(sw); + is_return_to = 0; } + if (local_size > 0) + BINARY_IMM32(ADD, local_size, SLJIT_SP, 0); + tmp = compiler->scratches; for (i = SLJIT_FIRST_SAVED_REG; i <= tmp; i++) { size = reg_map[i] >= 8 ? 2 : 1; @@ -657,6 +655,9 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) POP_REG(reg_lmap[i]); } + if (is_return_to) + BINARY_IMM32(ADD, sizeof(sljit_sw), SLJIT_SP, 0); + return SLJIT_SUCCESS; } @@ -667,7 +668,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler CHECK_ERROR(); CHECK(check_sljit_emit_return_void(compiler)); - FAIL_IF(emit_stack_frame_release(compiler)); + compiler->mode32 = 0; + + FAIL_IF(emit_stack_frame_release(compiler, 0)); inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); FAIL_IF(!inst); @@ -676,6 +679,28 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler return SLJIT_SUCCESS; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_return_to(compiler, src, srcw)); + + compiler->mode32 = 0; + + if ((src & SLJIT_MEM) || (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options)))) { + ADJUST_LOCAL_OFFSET(src, srcw); + + EMIT_MOV(compiler, TMP_REG2, 0, src, srcw); + src = TMP_REG2; + srcw = 0; + } + + FAIL_IF(emit_stack_frame_release(compiler, 1)); + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw); +} + /* --------------------------------------------------------------------- */ /* Call / return instructions */ /* --------------------------------------------------------------------- */ @@ -803,7 +828,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL)); if (type & SLJIT_CALL_RETURN) { - PTR_FAIL_IF(emit_stack_frame_release(compiler)); + PTR_FAIL_IF(emit_stack_frame_release(compiler, 0)); type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP); } @@ -827,12 +852,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi } if (type & SLJIT_CALL_RETURN) { - if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) { + if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { EMIT_MOV(compiler, TMP_REG2, 0, src, srcw); src = TMP_REG2; } - FAIL_IF(emit_stack_frame_release(compiler)); + FAIL_IF(emit_stack_frame_release(compiler, 0)); } if ((type & 0xff) != SLJIT_CALL_REG_ARG) @@ -845,14 +870,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi return sljit_emit_ijump(compiler, type, src, srcw); } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) +static sljit_s32 emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) { sljit_u8 *inst; - CHECK_ERROR(); - CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); - ADJUST_LOCAL_OFFSET(dst, dstw); - if (FAST_IS_REG(dst)) { if (reg_map[dst] < 8) { inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); @@ -874,7 +895,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * compiler->mode32 = 1; inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw); FAIL_IF(!inst); - *inst++ = POP_rm; + *inst = POP_rm; return SLJIT_SUCCESS; } @@ -904,8 +925,8 @@ static sljit_s32 emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src compiler->mode32 = 1; inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw); FAIL_IF(!inst); - *inst++ = GROUP_FF; - *inst |= PUSH_rm; + inst[0] = GROUP_FF; + inst[1] |= PUSH_rm; inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); FAIL_IF(!inst); @@ -916,8 +937,18 @@ static sljit_s32 emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src return SLJIT_SUCCESS; } +static sljit_s32 sljit_emit_get_return_address(struct sljit_compiler *compiler, + sljit_s32 dst, sljit_sw dstw) +{ + sljit_s32 saved_regs_size; + + compiler->mode32 = 0; + saved_regs_size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds - SLJIT_KEPT_SAVEDS_COUNT(compiler->options), 0); + return emit_mov(compiler, dst, dstw, SLJIT_MEM1(SLJIT_SP), compiler->local_size + saved_regs_size); +} + /* --------------------------------------------------------------------- */ -/* Memory operations */ +/* Other operations */ /* --------------------------------------------------------------------- */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, @@ -931,12 +962,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile CHECK_ERROR(); CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); - if (!(reg & REG_PAIR_MASK)) { - if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) - return SLJIT_ERR_UNSUPPORTED; - + if (!(reg & REG_PAIR_MASK)) return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw); - } ADJUST_LOCAL_OFFSET(mem, memw); @@ -1004,10 +1031,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile return SLJIT_SUCCESS; } -/* --------------------------------------------------------------------- */ -/* Extend input */ -/* --------------------------------------------------------------------- */ - static sljit_s32 emit_mov_int(struct sljit_compiler *compiler, sljit_s32 sign, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) @@ -1043,7 +1066,7 @@ static sljit_s32 emit_mov_int(struct sljit_compiler *compiler, sljit_s32 sign, if (sign) { inst = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw); FAIL_IF(!inst); - *inst++ = MOVSXD_r_rm; + *inst = MOVSXD_r_rm; } else { compiler->mode32 = 1; FAIL_IF(emit_mov(compiler, dst_r, 0, src, srcw)); @@ -1062,6 +1085,41 @@ static sljit_s32 emit_mov_int(struct sljit_compiler *compiler, sljit_s32 sign, return SLJIT_SUCCESS; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 freg, sljit_s32 reg) +{ + sljit_u8 *inst; + sljit_u32 size; + sljit_u8 rex = 0; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg)); + + if (!(op & SLJIT_32)) + rex = REX_W; + + if (freg_map[freg] >= 8) + rex |= REX_R; + + if (reg_map[reg] >= 8) + rex |= REX_B; + + size = (rex != 0) ? 5 : 4; + + inst = (sljit_u8*)ensure_buf(compiler, 1 + size); + FAIL_IF(!inst); + INC_SIZE(size); + + *inst++ = GROUP_66; + if (rex != 0) + *inst++ = rex; + inst[0] = GROUP_0F; + inst[1] = GET_OPCODE(op) == SLJIT_COPY_TO_F64 ? MOVD_x_rm : MOVD_rm_x; + inst[2] = U8(reg_lmap[reg] | (freg_lmap[freg] << 3) | MOD_REG); + + return SLJIT_SUCCESS; +} + static sljit_s32 skip_frames_before_return(struct sljit_compiler *compiler) { sljit_s32 tmp, size; diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeX86_common.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeX86_common.c index e595538bce..a9645bc175 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeX86_common.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeX86_common.c @@ -69,7 +69,7 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) #define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2) static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 3] = { - 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 7, 6, 3, 4, 5 + 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 5, 7, 6, 4, 3 }; #define CHECK_EXTRA_REGS(p, w, do) \ @@ -174,6 +174,8 @@ static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = { #define AND_rm_r 0x21 #define ANDPD_x_xm 0x54 #define BSR_r_rm (/* GROUP_0F */ 0xbd) +#define BSF_r_rm (/* GROUP_0F */ 0xbc) +#define BSWAP_r (/* GROUP_0F */ 0xc8) #define CALL_i32 0xe8 #define CALL_rm (/* GROUP_FF */ 2 << 3) #define CDQ 0x99 @@ -187,6 +189,8 @@ static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = { #define CVTTSD2SI_r_xm 0x2c #define DIV (/* GROUP_F7 */ 6 << 3) #define DIVSD_x_xm 0x5e +#define FLDS 0xd9 +#define FLDL 0xdd #define FSTPS 0xd9 #define FSTPD 0xdd #define INT3 0xcc @@ -202,6 +206,7 @@ static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = { #define JMP_rm (/* GROUP_FF */ 4 << 3) #define LEA_r_m 0x8d #define LOOP_i8 0xe2 +#define LZCNT_r_rm (/* GROUP_F3 */ /* GROUP_0F */ 0xbd) #define MOV_r_rm 0x8b #define MOV_r_i32 0xb8 #define MOV_rm_r 0x89 @@ -210,6 +215,8 @@ static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = { #define MOV_rm8_r8 0x88 #define MOVAPS_x_xm 0x28 #define MOVAPS_xm_x 0x29 +#define MOVD_x_rm 0x6e +#define MOVD_rm_x 0x7e #define MOVSD_x_xm 0x10 #define MOVSD_xm_x 0x11 #define MOVSXD_r_rm 0x63 @@ -231,10 +238,14 @@ static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = { #define POP_rm 0x8f #define POPF 0x9d #define PREFETCH 0x18 +#define PSHUFD_x_xm 0x70 +#define PUNPCKLDQ_x_xm 0x62 #define PUSH_i32 0x68 #define PUSH_r 0x50 #define PUSH_rm (/* GROUP_FF */ 6 << 3) #define PUSHF 0x9c +#define ROL (/* SHIFT */ 0 << 3) +#define ROR (/* SHIFT */ 1 << 3) #define RET_near 0xc3 #define RET_i16 0xc2 #define SBB (/* BINARY */ 3 << 3) @@ -243,6 +254,8 @@ static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = { #define SBB_rm_r 0x19 #define SAR (/* SHIFT */ 7 << 3) #define SHL (/* SHIFT */ 4 << 3) +#define SHLD (/* GROUP_0F */ 0xa5) +#define SHRD (/* GROUP_0F */ 0xad) #define SHR (/* SHIFT */ 5 << 3) #define SUB (/* BINARY */ 5 << 3) #define SUB_EAX_i32 0x2d @@ -251,6 +264,7 @@ static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = { #define SUBSD_x_xm 0x5c #define TEST_EAX_i32 0xa9 #define TEST_rm_r 0x85 +#define TZCNT_r_rm (/* GROUP_F3 */ /* GROUP_0F */ 0xbc) #define UCOMISD_x_xm 0x2e #define UNPCKLPD_x_xm 0x14 #define XCHG_EAX_r 0x90 @@ -262,6 +276,8 @@ static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = { #define XORPD_x_xm 0x57 #define GROUP_0F 0x0f +#define GROUP_66 0x66 +#define GROUP_F3 0xf3 #define GROUP_F7 0xf7 #define GROUP_FF 0xff #define GROUP_BINARY_81 0x81 @@ -283,10 +299,15 @@ static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = { /* Multithreading does not affect these static variables, since they store built-in CPU features. Therefore they can be overwritten by different threads if they detect the CPU features in the same time. */ +#define CPU_FEATURE_DETECTED 0x001 #if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2) -static sljit_s32 cpu_has_sse2 = -1; +#define CPU_FEATURE_SSE2 0x002 #endif -static sljit_s32 cpu_has_cmov = -1; +#define CPU_FEATURE_LZCNT 0x004 +#define CPU_FEATURE_TZCNT 0x008 +#define CPU_FEATURE_CMOV 0x010 + +static sljit_u32 cpu_feature_list = 0; #ifdef _WIN32_WCE #include @@ -319,17 +340,64 @@ static SLJIT_INLINE void sljit_unaligned_store_sw(void *addr, sljit_sw value) static void get_cpu_features(void) { - sljit_u32 features; + sljit_u32 feature_list = CPU_FEATURE_DETECTED; + sljit_u32 value; #if defined(_MSC_VER) && _MSC_VER >= 1400 int CPUInfo[4]; - __cpuid(CPUInfo, 1); - features = (sljit_u32)CPUInfo[3]; -#elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_C) + __cpuid(CPUInfo, 0); + if (CPUInfo[0] >= 7) { + __cpuidex(CPUInfo, 7, 0); + if (CPUInfo[1] & 0x8) + feature_list |= CPU_FEATURE_TZCNT; + } + + __cpuid(CPUInfo, (int)0x80000001); + if (CPUInfo[2] & 0x20) + feature_list |= CPU_FEATURE_LZCNT; + + __cpuid(CPUInfo, 1); + value = (sljit_u32)CPUInfo[3]; + +#elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_C) || defined(__TINYC__) /* AT&T syntax. */ + __asm__ ( + "movl $0x0, %%eax\n" + "lzcnt %%eax, %%eax\n" + "setnz %%al\n" + "movl %%eax, %0\n" + : "=g" (value) + : +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + : "eax" +#else + : "rax" +#endif + ); + + if (value & 0x1) + feature_list |= CPU_FEATURE_LZCNT; + + __asm__ ( + "movl $0x0, %%eax\n" + "tzcnt %%eax, %%eax\n" + "setnz %%al\n" + "movl %%eax, %0\n" + : "=g" (value) + : +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + : "eax" +#else + : "rax" +#endif + ); + + if (value & 0x1) + feature_list |= CPU_FEATURE_TZCNT; + __asm__ ( "movl $0x1, %%eax\n" #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) @@ -342,30 +410,54 @@ static void get_cpu_features(void) "pop %%ebx\n" #endif "movl %%edx, %0\n" - : "=g" (features) + : "=g" (value) : #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - : "%eax", "%ecx", "%edx" + : "eax", "ecx", "edx" #else - : "%rax", "%rbx", "%rcx", "%rdx" + : "rax", "rbx", "rcx", "rdx" #endif ); #else /* _MSC_VER && _MSC_VER >= 1400 */ /* Intel syntax. */ + __asm { + mov eax, 0 + lzcnt eax, eax + setnz al + mov value, eax + } + + if (value & 0x1) + feature_list |= CPU_FEATURE_LZCNT; + + __asm { + mov eax, 0 + tzcnt eax, eax + setnz al + mov value, eax + } + + if (value & 0x1) + feature_list |= CPU_FEATURE_TZCNT; + __asm { mov eax, 1 cpuid - mov features, edx + mov value, edx } #endif /* _MSC_VER && _MSC_VER >= 1400 */ #if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2) - cpu_has_sse2 = (features >> 26) & 0x1; + if (value & 0x4000000) + feature_list |= CPU_FEATURE_SSE2; #endif - cpu_has_cmov = (features >> 15) & 0x1; + if (value & 0x8000) + feature_list |= CPU_FEATURE_CMOV; + + cpu_feature_list = feature_list; } static sljit_u8 get_jump_code(sljit_uw type) @@ -454,13 +546,13 @@ static sljit_u8* generate_near_jump_code(struct sljit_jump *jump, sljit_u8 *code else label_addr = jump->u.target - (sljit_uw)executable_offset; - short_jump = (sljit_sw)(label_addr - (jump->addr + 2)) >= -128 && (sljit_sw)(label_addr - (jump->addr + 2)) <= 127; - #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if ((sljit_sw)(label_addr - (jump->addr + 1)) > HALFWORD_MAX || (sljit_sw)(label_addr - (jump->addr + 1)) < HALFWORD_MIN) return generate_far_jump_code(jump, code_ptr); #endif + short_jump = (sljit_sw)(label_addr - (jump->addr + 2)) >= -128 && (sljit_sw)(label_addr - (jump->addr + 2)) <= 127; + if (type == SLJIT_JUMP) { if (short_jump) *code_ptr++ = JMP_i8; @@ -586,32 +678,33 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil jump = compiler->jumps; while (jump) { - jump_addr = jump->addr + (sljit_uw)executable_offset; + if (jump->flags & (PATCH_MB | PATCH_MW)) { + if (jump->flags & JUMP_LABEL) + jump_addr = jump->u.label->addr; + else + jump_addr = jump->u.target; - if (jump->flags & PATCH_MB) { - SLJIT_ASSERT((sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_s8))) >= -128 && (sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_s8))) <= 127); - *(sljit_u8*)jump->addr = U8(jump->u.label->addr - (jump_addr + sizeof(sljit_s8))); - } else if (jump->flags & PATCH_MW) { - if (jump->flags & JUMP_LABEL) { + jump_addr -= jump->addr + (sljit_uw)executable_offset; + + if (jump->flags & PATCH_MB) { + jump_addr -= sizeof(sljit_s8); + SLJIT_ASSERT((sljit_sw)jump_addr >= -128 && (sljit_sw)jump_addr <= 127); + *(sljit_u8*)jump->addr = U8(jump_addr); + } else { + jump_addr -= sizeof(sljit_s32); #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - sljit_unaligned_store_sw((void*)jump->addr, (sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_sw)))); + sljit_unaligned_store_sw((void*)jump->addr, (sljit_sw)jump_addr); #else - SLJIT_ASSERT((sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_s32))) >= HALFWORD_MIN && (sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_s32))) <= HALFWORD_MAX); - sljit_unaligned_store_s32((void*)jump->addr, (sljit_s32)(jump->u.label->addr - (jump_addr + sizeof(sljit_s32)))); -#endif - } - else { -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - sljit_unaligned_store_sw((void*)jump->addr, (sljit_sw)(jump->u.target - (jump_addr + sizeof(sljit_sw)))); -#else - SLJIT_ASSERT((sljit_sw)(jump->u.target - (jump_addr + sizeof(sljit_s32))) >= HALFWORD_MIN && (sljit_sw)(jump->u.target - (jump_addr + sizeof(sljit_s32))) <= HALFWORD_MAX); - sljit_unaligned_store_s32((void*)jump->addr, (sljit_s32)(jump->u.target - (jump_addr + sizeof(sljit_s32)))); + SLJIT_ASSERT((sljit_sw)jump_addr >= HALFWORD_MIN && (sljit_sw)jump_addr <= HALFWORD_MAX); + sljit_unaligned_store_s32((void*)jump->addr, (sljit_s32)jump_addr); #endif } } #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) - else if (jump->flags & PATCH_MD) - sljit_unaligned_store_sw((void*)jump->addr, (sljit_sw)jump->u.label->addr); + else if (jump->flags & PATCH_MD) { + SLJIT_ASSERT(jump->flags & JUMP_LABEL); + sljit_unaligned_store_sw((void*)jump->addr, (sljit_sw)jump->u.label->addr); + } #endif jump = jump->next; @@ -652,9 +745,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) #ifdef SLJIT_IS_FPU_AVAILABLE return SLJIT_IS_FPU_AVAILABLE; #elif (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2) - if (cpu_has_sse2 == -1) + if (cpu_feature_list == 0) get_cpu_features(); - return cpu_has_sse2; + return (cpu_feature_list & CPU_FEATURE_SSE2) != 0; #else /* SLJIT_DETECT_SSE2 */ return 1; #endif /* SLJIT_DETECT_SSE2 */ @@ -662,25 +755,40 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) case SLJIT_HAS_VIRTUAL_REGISTERS: return 1; -#endif +#endif /* SLJIT_CONFIG_X86_32 */ case SLJIT_HAS_CLZ: - case SLJIT_HAS_CMOV: - if (cpu_has_cmov == -1) + if (cpu_feature_list == 0) get_cpu_features(); - return cpu_has_cmov; + return (cpu_feature_list & CPU_FEATURE_LZCNT) ? 1 : 2; + + case SLJIT_HAS_CTZ: + if (cpu_feature_list == 0) + get_cpu_features(); + + return (cpu_feature_list & CPU_FEATURE_TZCNT) ? 1 : 2; + + case SLJIT_HAS_CMOV: + if (cpu_feature_list == 0) + get_cpu_features(); + return (cpu_feature_list & CPU_FEATURE_CMOV) != 0; + + case SLJIT_HAS_REV: + case SLJIT_HAS_ROT: case SLJIT_HAS_PREFETCH: + case SLJIT_HAS_COPY_F32: + case SLJIT_HAS_COPY_F64: return 1; case SLJIT_HAS_SSE2: #if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2) - if (cpu_has_sse2 == -1) + if (cpu_feature_list == 0) get_cpu_features(); - return cpu_has_sse2; -#else + return (cpu_feature_list & CPU_FEATURE_SSE2) != 0; +#else /* !SLJIT_DETECT_SSE2 */ return 1; -#endif +#endif /* SLJIT_DETECT_SSE2 */ default: return 0; @@ -767,14 +875,14 @@ static SLJIT_INLINE sljit_s32 emit_endbranch(struct sljit_compiler *compiler) inst = (sljit_u8*)ensure_buf(compiler, 1 + 4); FAIL_IF(!inst); INC_SIZE(4); - *inst++ = 0xf3; - *inst++ = 0x0f; - *inst++ = 0x1e; + inst[0] = GROUP_F3; + inst[1] = GROUP_0F; + inst[2] = 0x1e; #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - *inst = 0xfb; -#else - *inst = 0xfa; -#endif + inst[3] = 0xfb; +#else /* !SLJIT_CONFIG_X86_32 */ + inst[3] = 0xfa; +#endif /* SLJIT_CONFIG_X86_32 */ #else /* !SLJIT_CONFIG_X86_CET */ SLJIT_UNUSED_ARG(compiler); #endif /* SLJIT_CONFIG_X86_CET */ @@ -797,13 +905,13 @@ static SLJIT_INLINE sljit_s32 emit_rdssp(struct sljit_compiler *compiler, sljit_ inst = (sljit_u8*)ensure_buf(compiler, 1 + size); FAIL_IF(!inst); INC_SIZE(size); - *inst++ = 0xf3; + *inst++ = GROUP_F3; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) *inst++ = REX_W | (reg_map[reg] <= 7 ? 0 : REX_B); #endif - *inst++ = 0x0f; - *inst++ = 0x1e; - *inst = (0x3 << 6) | (0x1 << 3) | (reg_map[reg] & 0x7); + inst[0] = GROUP_0F; + inst[1] = 0x1e; + inst[2] = U8(MOD_REG | (0x1 << 3) | reg_lmap[reg]); return SLJIT_SUCCESS; } @@ -821,13 +929,13 @@ static SLJIT_INLINE sljit_s32 emit_incssp(struct sljit_compiler *compiler, sljit inst = (sljit_u8*)ensure_buf(compiler, 1 + size); FAIL_IF(!inst); INC_SIZE(size); - *inst++ = 0xf3; + *inst++ = GROUP_F3; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) *inst++ = REX_W | (reg_map[reg] <= 7 ? 0 : REX_B); #endif - *inst++ = 0x0f; - *inst++ = 0xae; - *inst = (0x3 << 6) | (0x5 << 3) | (reg_map[reg] & 0x7); + inst[0] = GROUP_0F; + inst[1] = 0xae; + inst[2] = (0x3 << 6) | (0x5 << 3) | (reg_map[reg] & 0x7); return SLJIT_SUCCESS; } @@ -855,19 +963,7 @@ static SLJIT_INLINE sljit_s32 adjust_shadow_stack(struct sljit_compiler *compile FAIL_IF(emit_rdssp(compiler, TMP_REG1)); /* Load return address on shadow stack into TMP_REG1. */ -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - SLJIT_ASSERT(reg_map[TMP_REG1] == 5); - - /* Hand code unsupported "mov 0x0(%ebp),%ebp". */ - inst = (sljit_u8*)ensure_buf(compiler, 1 + 3); - FAIL_IF(!inst); - INC_SIZE(3); - *inst++ = 0x8b; - *inst++ = 0x6d; - *inst = 0; -#else /* !SLJIT_CONFIG_X86_32 */ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(TMP_REG1), 0); -#endif /* SLJIT_CONFIG_X86_32 */ /* Compare return address against TMP_REG1. */ FAIL_IF(emit_cmp_binary (compiler, TMP_REG1, 0, src, srcw)); @@ -895,8 +991,8 @@ static SLJIT_INLINE sljit_s32 adjust_shadow_stack(struct sljit_compiler *compile inst = (sljit_u8*)ensure_buf(compiler, 1 + 2); FAIL_IF(!inst); INC_SIZE(2); - *inst++ = JMP_i8; - *inst = size_before_rdssp_inst - compiler->size; + inst[0] = JMP_i8; + inst[1] = size_before_rdssp_inst - compiler->size; *jz_after_cmp_inst = compiler->size - size_jz_after_cmp_inst; #else /* !SLJIT_CONFIG_X86_CET || !__SHSTK__ */ @@ -1049,8 +1145,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile inst = (sljit_u8*)ensure_buf(compiler, 1 + 2); FAIL_IF(!inst); INC_SIZE(2); - *inst++ = REX_W; - *inst = CDQ; + inst[0] = REX_W; + inst[1] = CDQ; } #endif } @@ -1059,14 +1155,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile inst = (sljit_u8*)ensure_buf(compiler, 1 + 2); FAIL_IF(!inst); INC_SIZE(2); - *inst++ = GROUP_F7; - *inst = MOD_REG | ((op >= SLJIT_DIVMOD_UW) ? reg_map[TMP_REG1] : reg_map[SLJIT_R1]); -#else + inst[0] = GROUP_F7; + inst[1] = MOD_REG | ((op >= SLJIT_DIVMOD_UW) ? reg_map[TMP_REG1] : reg_map[SLJIT_R1]); +#else /* !SLJIT_CONFIG_X86_32 */ #ifdef _WIN64 size = (!compiler->mode32 || op >= SLJIT_DIVMOD_UW) ? 3 : 2; -#else +#else /* !_WIN64 */ size = (!compiler->mode32) ? 3 : 2; -#endif +#endif /* _WIN64 */ inst = (sljit_u8*)ensure_buf(compiler, 1 + size); FAIL_IF(!inst); INC_SIZE(size); @@ -1075,29 +1171,29 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile *inst++ = REX_W | ((op >= SLJIT_DIVMOD_UW) ? REX_B : 0); else if (op >= SLJIT_DIVMOD_UW) *inst++ = REX_B; - *inst++ = GROUP_F7; - *inst = MOD_REG | ((op >= SLJIT_DIVMOD_UW) ? reg_lmap[TMP_REG1] : reg_lmap[SLJIT_R1]); -#else + inst[0] = GROUP_F7; + inst[1] = MOD_REG | ((op >= SLJIT_DIVMOD_UW) ? reg_lmap[TMP_REG1] : reg_lmap[SLJIT_R1]); +#else /* !_WIN64 */ if (!compiler->mode32) *inst++ = REX_W; - *inst++ = GROUP_F7; - *inst = MOD_REG | reg_map[SLJIT_R1]; -#endif -#endif + inst[0] = GROUP_F7; + inst[1] = MOD_REG | reg_map[SLJIT_R1]; +#endif /* _WIN64 */ +#endif /* SLJIT_CONFIG_X86_32 */ switch (op) { case SLJIT_LMUL_UW: - *inst |= MUL; + inst[1] |= MUL; break; case SLJIT_LMUL_SW: - *inst |= IMUL; + inst[1] |= IMUL; break; case SLJIT_DIVMOD_UW: case SLJIT_DIV_UW: - *inst |= DIV; + inst[1] |= DIV; break; case SLJIT_DIVMOD_SW: case SLJIT_DIV_SW: - *inst |= IDIV; + inst[1] |= IDIV; break; } #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && !defined(_WIN64) @@ -1178,8 +1274,8 @@ static sljit_s32 emit_mov_byte(struct sljit_compiler *compiler, sljit_s32 sign, EMIT_MOV(compiler, dst, 0, src, 0); inst = emit_x86_instruction(compiler, 2, dst, 0, dst, 0); FAIL_IF(!inst); - *inst++ = GROUP_0F; - *inst = sign ? MOVSX_r_rm8 : MOVZX_r_rm8; + inst[0] = GROUP_0F; + inst[1] = sign ? MOVSX_r_rm8 : MOVZX_r_rm8; } else { if (dst != src) @@ -1207,8 +1303,8 @@ static sljit_s32 emit_mov_byte(struct sljit_compiler *compiler, sljit_s32 sign, /* src can be memory addr or reg_map[src] < 4 on x86_32 architectures. */ inst = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw); FAIL_IF(!inst); - *inst++ = GROUP_0F; - *inst = sign ? MOVSX_r_rm8 : MOVZX_r_rm8; + inst[0] = GROUP_0F; + inst[1] = sign ? MOVSX_r_rm8 : MOVZX_r_rm8; } if (dst & SLJIT_MEM) { @@ -1278,15 +1374,15 @@ static sljit_s32 emit_prefetch(struct sljit_compiler *compiler, sljit_s32 op, inst = emit_x86_instruction(compiler, 2, 0, 0, src, srcw); FAIL_IF(!inst); - *inst++ = GROUP_0F; - *inst++ = PREFETCH; + inst[0] = GROUP_0F; + inst[1] = PREFETCH; if (op == SLJIT_PREFETCH_L1) - *inst |= (1 << 3); + inst[2] |= (1 << 3); else if (op == SLJIT_PREFETCH_L2) - *inst |= (2 << 3); + inst[2] |= (2 << 3); else if (op == SLJIT_PREFETCH_L3) - *inst |= (3 << 3); + inst[2] |= (3 << 3); return SLJIT_SUCCESS; } @@ -1326,8 +1422,8 @@ static sljit_s32 emit_mov_half(struct sljit_compiler *compiler, sljit_s32 sign, else { inst = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw); FAIL_IF(!inst); - *inst++ = GROUP_0F; - *inst = sign ? MOVSX_r_rm16 : MOVZX_r_rm16; + inst[0] = GROUP_0F; + inst[1] = sign ? MOVSX_r_rm16 : MOVZX_r_rm16; } if (dst & SLJIT_MEM) { @@ -1349,8 +1445,8 @@ static sljit_s32 emit_unary(struct sljit_compiler *compiler, sljit_u8 opcode, /* Same input and output */ inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw); FAIL_IF(!inst); - *inst++ = GROUP_F7; - *inst |= opcode; + inst[0] = GROUP_F7; + inst[1] |= opcode; return SLJIT_SUCCESS; } @@ -1358,107 +1454,146 @@ static sljit_s32 emit_unary(struct sljit_compiler *compiler, sljit_u8 opcode, EMIT_MOV(compiler, dst, 0, src, srcw); inst = emit_x86_instruction(compiler, 1, 0, 0, dst, 0); FAIL_IF(!inst); - *inst++ = GROUP_F7; - *inst |= opcode; + inst[0] = GROUP_F7; + inst[1] |= opcode; return SLJIT_SUCCESS; } EMIT_MOV(compiler, TMP_REG1, 0, src, srcw); inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REG1, 0); FAIL_IF(!inst); - *inst++ = GROUP_F7; - *inst |= opcode; - EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0); - return SLJIT_SUCCESS; -} - -static sljit_s32 emit_not_with_flags(struct sljit_compiler *compiler, - sljit_s32 dst, sljit_sw dstw, - sljit_s32 src, sljit_sw srcw) -{ - sljit_u8* inst; - - if (FAST_IS_REG(dst)) { - EMIT_MOV(compiler, dst, 0, src, srcw); - inst = emit_x86_instruction(compiler, 1, 0, 0, dst, 0); - FAIL_IF(!inst); - *inst++ = GROUP_F7; - *inst |= NOT_rm; - inst = emit_x86_instruction(compiler, 1, dst, 0, dst, 0); - FAIL_IF(!inst); - *inst = OR_r_rm; - return SLJIT_SUCCESS; - } - - EMIT_MOV(compiler, TMP_REG1, 0, src, srcw); - inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REG1, 0); - FAIL_IF(!inst); - *inst++ = GROUP_F7; - *inst |= NOT_rm; - inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, TMP_REG1, 0); - FAIL_IF(!inst); - *inst = OR_r_rm; + inst[0] = GROUP_F7; + inst[1] |= opcode; EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0); return SLJIT_SUCCESS; } #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) static const sljit_sw emit_clz_arg = 32 + 31; +static const sljit_sw emit_ctz_arg = 32; #endif -static sljit_s32 emit_clz(struct sljit_compiler *compiler, sljit_s32 op_flags, +static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 is_clz, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_u8* inst; sljit_s32 dst_r; + sljit_sw max; - SLJIT_UNUSED_ARG(op_flags); - - if (cpu_has_cmov == -1) + if (cpu_feature_list == 0) get_cpu_features(); dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; + if (is_clz ? (cpu_feature_list & CPU_FEATURE_LZCNT) : (cpu_feature_list & CPU_FEATURE_TZCNT)) { + inst = emit_x86_instruction(compiler, 2 | EX86_PREF_F3, dst_r, 0, src, srcw); + FAIL_IF(!inst); + inst[0] = GROUP_0F; + inst[1] = is_clz ? LZCNT_r_rm : TZCNT_r_rm; + + if (dst & SLJIT_MEM) + EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0); + return SLJIT_SUCCESS; + } + inst = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw); FAIL_IF(!inst); - *inst++ = GROUP_0F; - *inst = BSR_r_rm; + inst[0] = GROUP_0F; + inst[1] = is_clz ? BSR_r_rm : BSF_r_rm; #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - if (cpu_has_cmov) { + max = is_clz ? (32 + 31) : 32; + + if (cpu_feature_list & CPU_FEATURE_CMOV) { if (dst_r != TMP_REG1) { - EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, 32 + 31); + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, max); inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG1, 0); } else - inst = emit_x86_instruction(compiler, 2, dst_r, 0, SLJIT_MEM0(), (sljit_sw)&emit_clz_arg); + inst = emit_x86_instruction(compiler, 2, dst_r, 0, SLJIT_MEM0(), is_clz ? (sljit_sw)&emit_clz_arg : (sljit_sw)&emit_ctz_arg); FAIL_IF(!inst); - *inst++ = GROUP_0F; - *inst = CMOVE_r_rm; + inst[0] = GROUP_0F; + inst[1] = CMOVE_r_rm; } else - FAIL_IF(sljit_emit_cmov_generic(compiler, SLJIT_EQUAL, dst_r, SLJIT_IMM, 32 + 31)); + FAIL_IF(sljit_emit_cmov_generic(compiler, SLJIT_EQUAL, dst_r, SLJIT_IMM, max)); - inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 31, dst_r, 0); + if (is_clz) { + inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 31, dst_r, 0); + FAIL_IF(!inst); + *(inst + 1) |= XOR; + } #else - if (cpu_has_cmov) { - EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, !(op_flags & SLJIT_32) ? (64 + 63) : (32 + 31)); + if (is_clz) + max = compiler->mode32 ? (32 + 31) : (64 + 63); + else + max = compiler->mode32 ? 32 : 64; + + if (cpu_feature_list & CPU_FEATURE_CMOV) { + EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, max); inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0); FAIL_IF(!inst); - *inst++ = GROUP_0F; - *inst = CMOVE_r_rm; + inst[0] = GROUP_0F; + inst[1] = CMOVE_r_rm; } else - FAIL_IF(sljit_emit_cmov_generic(compiler, SLJIT_EQUAL, dst_r, SLJIT_IMM, !(op_flags & SLJIT_32) ? (64 + 63) : (32 + 31))); + FAIL_IF(sljit_emit_cmov_generic(compiler, SLJIT_EQUAL, dst_r, SLJIT_IMM, max)); - inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, !(op_flags & SLJIT_32) ? 63 : 31, dst_r, 0); + if (is_clz) { + inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, max >> 1, dst_r, 0); + FAIL_IF(!inst); + *(inst + 1) |= XOR; + } #endif + if (dst & SLJIT_MEM) + EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0); + return SLJIT_SUCCESS; +} + +static sljit_s32 emit_bswap(struct sljit_compiler *compiler, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ + sljit_u8 *inst; + sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; + sljit_uw size; +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + sljit_u8 rex = 0; +#endif /* SLJIT_CONFIG_X86_64 */ + + if (src != dst_r) + EMIT_MOV(compiler, dst_r, 0, src, srcw); + + size = 2; +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if (!compiler->mode32) + rex = REX_W; + + if (reg_map[dst_r] >= 8) + rex |= REX_B; + + if (rex != 0) + size++; +#endif /* SLJIT_CONFIG_X86_64 */ + + inst = (sljit_u8*)ensure_buf(compiler, 1 + size); FAIL_IF(!inst); - *(inst + 1) |= XOR; + INC_SIZE(size); + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if (rex != 0) + *inst++ = rex; + + inst[0] = GROUP_0F; + inst[1] = BSWAP_r | reg_lmap[dst_r]; +#else /* !SLJIT_CONFIG_X86_64 */ + inst[0] = GROUP_0F; + inst[1] = BSWAP_r | reg_map[dst_r]; +#endif /* SLJIT_CONFIG_X86_64 */ if (dst & SLJIT_MEM) EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0); @@ -1469,10 +1604,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { - sljit_s32 op_flags = GET_ALL_FLAGS(op); #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) sljit_s32 dst_is_ereg = 0; -#endif +#else /* !SLJIT_CONFIG_X86_32 */ + sljit_s32 op_flags = GET_ALL_FLAGS(op); +#endif /* SLJIT_CONFIG_X86_32 */ CHECK_ERROR(); CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw)); @@ -1483,14 +1619,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile CHECK_EXTRA_REGS(src, srcw, (void)0); #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = op_flags & SLJIT_32; -#endif +#endif /* SLJIT_CONFIG_X86_64 */ op = GET_OPCODE(op); if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = 0; -#endif +#endif /* SLJIT_CONFIG_X86_64 */ if (FAST_IS_REG(src) && src == dst) { if (!TYPE_CAST_NEEDED(op)) @@ -1508,7 +1644,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile op = SLJIT_MOV_S32; } } -#endif +#endif /* SLJIT_CONFIG_X86_64 */ if (src & SLJIT_IMM) { switch (op) { @@ -1531,12 +1667,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile case SLJIT_MOV_S32: srcw = (sljit_s32)srcw; break; -#endif +#endif /* SLJIT_CONFIG_X86_64 */ } #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) if (SLJIT_UNLIKELY(dst_is_ereg)) return emit_mov(compiler, dst, dstw, src, srcw); -#endif +#endif /* SLJIT_CONFIG_X86_32 */ } #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) @@ -1544,7 +1680,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile SLJIT_ASSERT(dst == SLJIT_MEM1(SLJIT_SP)); dst = TMP_REG1; } -#endif +#endif /* SLJIT_CONFIG_X86_32 */ switch (op) { case SLJIT_MOV: @@ -1553,7 +1689,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile case SLJIT_MOV_U32: case SLJIT_MOV_S32: case SLJIT_MOV32: -#endif +#endif /* SLJIT_CONFIG_X86_32 */ EMIT_MOV(compiler, dst, dstw, src, srcw); break; case SLJIT_MOV_U8: @@ -1580,24 +1716,22 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile EMIT_MOV(compiler, dst, dstw, src, srcw); compiler->mode32 = 0; break; -#endif +#endif /* SLJIT_CONFIG_X86_64 */ } #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) if (SLJIT_UNLIKELY(dst_is_ereg) && dst == TMP_REG1) return emit_mov(compiler, SLJIT_MEM1(SLJIT_SP), dstw, TMP_REG1, 0); -#endif +#endif /* SLJIT_CONFIG_X86_32 */ return SLJIT_SUCCESS; } switch (op) { - case SLJIT_NOT: - if (SLJIT_UNLIKELY(op_flags & SLJIT_SET_Z)) - return emit_not_with_flags(compiler, dst, dstw, src, srcw); - return emit_unary(compiler, NOT_rm, dst, dstw, src, srcw); - case SLJIT_CLZ: - return emit_clz(compiler, op_flags, dst, dstw, src, srcw); + case SLJIT_CTZ: + return emit_clz_ctz(compiler, (op == SLJIT_CLZ), dst, dstw, src, srcw); + case SLJIT_REV: + return emit_bswap(compiler, dst, dstw, src, srcw); } return SLJIT_SUCCESS; @@ -1795,14 +1929,14 @@ static sljit_s32 emit_mul(struct sljit_compiler *compiler, if (dst_r == src1 && !(src2 & SLJIT_IMM)) { inst = emit_x86_instruction(compiler, 2, dst_r, 0, src2, src2w); FAIL_IF(!inst); - *inst++ = GROUP_0F; - *inst = IMUL_r_rm; + inst[0] = GROUP_0F; + inst[1] = IMUL_r_rm; } else if (dst_r == src2 && !(src1 & SLJIT_IMM)) { inst = emit_x86_instruction(compiler, 2, dst_r, 0, src1, src1w); FAIL_IF(!inst); - *inst++ = GROUP_0F; - *inst = IMUL_r_rm; + inst[0] = GROUP_0F; + inst[1] = IMUL_r_rm; } else if (src1 & SLJIT_IMM) { if (src2 & SLJIT_IMM) { @@ -1846,8 +1980,8 @@ static sljit_s32 emit_mul(struct sljit_compiler *compiler, FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src1w)); inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0); FAIL_IF(!inst); - *inst++ = GROUP_0F; - *inst = IMUL_r_rm; + inst[0] = GROUP_0F; + inst[1] = IMUL_r_rm; } #endif } @@ -1889,8 +2023,8 @@ static sljit_s32 emit_mul(struct sljit_compiler *compiler, FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w)); inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0); FAIL_IF(!inst); - *inst++ = GROUP_0F; - *inst = IMUL_r_rm; + inst[0] = GROUP_0F; + inst[1] = IMUL_r_rm; } #endif } @@ -1901,8 +2035,8 @@ static sljit_s32 emit_mul(struct sljit_compiler *compiler, EMIT_MOV(compiler, dst_r, 0, src1, src1w); inst = emit_x86_instruction(compiler, 2, dst_r, 0, src2, src2w); FAIL_IF(!inst); - *inst++ = GROUP_0F; - *inst = IMUL_r_rm; + inst[0] = GROUP_0F; + inst[1] = IMUL_r_rm; } if (dst & SLJIT_MEM) @@ -2135,6 +2269,9 @@ static sljit_s32 emit_shift(struct sljit_compiler *compiler, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + sljit_s32 mode32; +#endif sljit_u8* inst; if ((src2 & SLJIT_IMM) || (src2 == SLJIT_PREF_SHIFT_REG)) { @@ -2174,41 +2311,62 @@ static sljit_s32 emit_shift(struct sljit_compiler *compiler, inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); FAIL_IF(!inst); *inst |= mode; - EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); + return emit_mov(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); } - else if (FAST_IS_REG(dst) && dst != src2 && dst != TMP_REG1 && !ADDRESSING_DEPENDS_ON(src2, dst)) { + + if (FAST_IS_REG(dst) && dst != src2 && dst != TMP_REG1 && !ADDRESSING_DEPENDS_ON(src2, dst)) { if (src1 != dst) EMIT_MOV(compiler, dst, 0, src1, src1w); +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + mode32 = compiler->mode32; + compiler->mode32 = 0; +#endif EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_PREF_SHIFT_REG, 0); +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = mode32; +#endif EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w); inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, dst, 0); FAIL_IF(!inst); *inst |= mode; - EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); - } - else { - /* This case is complex since ecx itself may be used for - addressing, and this case must be supported as well. */ - EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_PREF_SHIFT_REG, 0); - EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w); - inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); - FAIL_IF(!inst); - *inst |= mode; - EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, SLJIT_MEM1(SLJIT_SP), 0); -#else - EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_PREF_SHIFT_REG, 0); - EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w); - inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); - FAIL_IF(!inst); - *inst |= mode; - EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG2, 0); +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = 0; #endif - if (dst != TMP_REG1) - return emit_mov(compiler, dst, dstw, TMP_REG1, 0); + EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = mode32; +#endif + return SLJIT_SUCCESS; } + /* This case is complex since ecx itself may be used for + addressing, and this case must be supported as well. */ + EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_PREF_SHIFT_REG, 0); +#else /* !SLJIT_CONFIG_X86_32 */ + mode32 = compiler->mode32; + compiler->mode32 = 0; + EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_PREF_SHIFT_REG, 0); + compiler->mode32 = mode32; +#endif /* SLJIT_CONFIG_X86_32 */ + + EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w); + inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); + FAIL_IF(!inst); + *inst |= mode; + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, SLJIT_MEM1(SLJIT_SP), 0); +#else + compiler->mode32 = 0; + EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG2, 0); + compiler->mode32 = mode32; +#endif /* SLJIT_CONFIG_X86_32 */ + + if (dst != TMP_REG1) + return emit_mov(compiler, dst, dstw, TMP_REG1, 0); + return SLJIT_SUCCESS; } @@ -2221,12 +2379,13 @@ static sljit_s32 emit_shift_with_flags(struct sljit_compiler *compiler, /* The CPU does not set flags if the shift count is 0. */ if (src2 & SLJIT_IMM) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) - if ((src2w & 0x3f) != 0 || (compiler->mode32 && (src2w & 0x1f) != 0)) + src2w &= compiler->mode32 ? 0x1f : 0x3f; +#else /* !SLJIT_CONFIG_X86_64 */ + src2w &= 0x1f; +#endif /* SLJIT_CONFIG_X86_64 */ + if (src2w != 0) return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w); -#else - if ((src2w & 0x1f) != 0) - return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w); -#endif + if (!set_flags) return emit_mov(compiler, dst, dstw, src1, src1w); /* OR dst, src, 0 */ @@ -2305,17 +2464,33 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile return emit_cum_binary(compiler, BINARY_OPCODE(OR), dst, dstw, src1, src1w, src2, src2w); case SLJIT_XOR: + if (!HAS_FLAGS(op)) { + if ((src2 & SLJIT_IMM) && src2w == -1) + return emit_unary(compiler, NOT_rm, dst, dstw, src1, src1w); + if ((src1 & SLJIT_IMM) && src1w == -1) + return emit_unary(compiler, NOT_rm, dst, dstw, src2, src2w); + } + return emit_cum_binary(compiler, BINARY_OPCODE(XOR), dst, dstw, src1, src1w, src2, src2w); case SLJIT_SHL: + case SLJIT_MSHL: return emit_shift_with_flags(compiler, SHL, HAS_FLAGS(op), dst, dstw, src1, src1w, src2, src2w); case SLJIT_LSHR: + case SLJIT_MLSHR: return emit_shift_with_flags(compiler, SHR, HAS_FLAGS(op), dst, dstw, src1, src1w, src2, src2w); case SLJIT_ASHR: + case SLJIT_MASHR: return emit_shift_with_flags(compiler, SAR, HAS_FLAGS(op), dst, dstw, src1, src1w, src2, src2w); + case SLJIT_ROTL: + return emit_shift_with_flags(compiler, ROL, 0, + dst, dstw, src1, src1w, src2, src2w); + case SLJIT_ROTR: + return emit_shift_with_flags(compiler, ROR, 0, + dst, dstw, src1, src1w, src2, src2w); } return SLJIT_SUCCESS; @@ -2350,6 +2525,200 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil return emit_test_binary(compiler, src1, src1w, src2, src2w); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst_reg, + sljit_s32 src1_reg, + sljit_s32 src2_reg, + sljit_s32 src3, sljit_sw src3w) +{ + sljit_s32 is_rotate, is_left, move_src1; + sljit_u8* inst; + sljit_sw src1w = 0; + sljit_sw dstw = 0; + /* The whole register must be saved even for 32 bit operations. */ + sljit_u8 restore_ecx = 0; +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + sljit_sw src2w = 0; + sljit_s32 restore_sp4 = 0; +#endif /* SLJIT_CONFIG_X86_32 */ + + CHECK_ERROR(); + CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w)); + ADJUST_LOCAL_OFFSET(src3, src3w); + + CHECK_EXTRA_REGS(dst_reg, dstw, (void)0); + CHECK_EXTRA_REGS(src3, src3w, (void)0); + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = op & SLJIT_32; +#endif /* SLJIT_CONFIG_X86_64 */ + + if (src3 & SLJIT_IMM) { +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + src3w &= 0x1f; +#else /* !SLJIT_CONFIG_X86_32 */ + src3w &= (op & SLJIT_32) ? 0x1f : 0x3f; +#endif /* SLJIT_CONFIG_X86_32 */ + + if (src3w == 0) + return SLJIT_SUCCESS; + } + + is_left = (GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_MSHL); + + is_rotate = (src1_reg == src2_reg); + CHECK_EXTRA_REGS(src1_reg, src1w, (void)0); + CHECK_EXTRA_REGS(src2_reg, src2w, (void)0); + + if (is_rotate) + return emit_shift(compiler, is_left ? ROL : ROR, dst_reg, dstw, src1_reg, src1w, src3, src3w); + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + if (src2_reg & SLJIT_MEM) { + EMIT_MOV(compiler, TMP_REG1, 0, src2_reg, src2w); + src2_reg = TMP_REG1; + } +#endif /* SLJIT_CONFIG_X86_32 */ + + if (dst_reg == SLJIT_PREF_SHIFT_REG && !(src3 & SLJIT_IMM) && (src3 != SLJIT_PREF_SHIFT_REG || src1_reg != SLJIT_PREF_SHIFT_REG)) { +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + EMIT_MOV(compiler, TMP_REG1, 0, src1_reg, src1w); + src1_reg = TMP_REG1; + src1w = 0; +#else /* !SLJIT_CONFIG_X86_64 */ + if (src2_reg != TMP_REG1) { + EMIT_MOV(compiler, TMP_REG1, 0, src1_reg, src1w); + src1_reg = TMP_REG1; + src1w = 0; + } else if ((src1_reg & SLJIT_MEM) || src1_reg == SLJIT_PREF_SHIFT_REG) { + restore_sp4 = (src3 == SLJIT_R0) ? SLJIT_R1 : SLJIT_R0; + EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), restore_sp4, 0); + EMIT_MOV(compiler, restore_sp4, 0, src1_reg, src1w); + src1_reg = restore_sp4; + src1w = 0; + } else { + EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), src1_reg, 0); + restore_sp4 = src1_reg; + } +#endif /* SLJIT_CONFIG_X86_64 */ + + if (src3 != SLJIT_PREF_SHIFT_REG) + EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src3, src3w); + } else { + if (src2_reg == SLJIT_PREF_SHIFT_REG && !(src3 & SLJIT_IMM) && src3 != SLJIT_PREF_SHIFT_REG) { +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = 0; +#endif /* SLJIT_CONFIG_X86_64 */ + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_PREF_SHIFT_REG, 0); +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = op & SLJIT_32; +#endif /* SLJIT_CONFIG_X86_64 */ + src2_reg = TMP_REG1; + restore_ecx = 1; + } + + move_src1 = 0; +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if (dst_reg != src1_reg) { + if (dst_reg != src3) { + EMIT_MOV(compiler, dst_reg, 0, src1_reg, src1w); + src1_reg = dst_reg; + src1w = 0; + } else + move_src1 = 1; + } +#else /* !SLJIT_CONFIG_X86_64 */ + if (dst_reg & SLJIT_MEM) { + if (src2_reg != TMP_REG1) { + EMIT_MOV(compiler, TMP_REG1, 0, src1_reg, src1w); + src1_reg = TMP_REG1; + src1w = 0; + } else if ((src1_reg & SLJIT_MEM) || src1_reg == SLJIT_PREF_SHIFT_REG) { + restore_sp4 = (src3 == SLJIT_R0) ? SLJIT_R1 : SLJIT_R0; + EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), restore_sp4, 0); + EMIT_MOV(compiler, restore_sp4, 0, src1_reg, src1w); + src1_reg = restore_sp4; + src1w = 0; + } else { + EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), src1_reg, 0); + restore_sp4 = src1_reg; + } + } else if (dst_reg != src1_reg) { + if (dst_reg != src3) { + EMIT_MOV(compiler, dst_reg, 0, src1_reg, src1w); + src1_reg = dst_reg; + src1w = 0; + } else + move_src1 = 1; + } +#endif /* SLJIT_CONFIG_X86_64 */ + + if (!(src3 & SLJIT_IMM) && src3 != SLJIT_PREF_SHIFT_REG) { + if (!restore_ecx) { +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = 0; + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_PREF_SHIFT_REG, 0); + compiler->mode32 = op & SLJIT_32; + restore_ecx = 1; +#else /* !SLJIT_CONFIG_X86_64 */ + if (src1_reg != TMP_REG1 && src2_reg != TMP_REG1) { + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_PREF_SHIFT_REG, 0); + restore_ecx = 1; + } else { + EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_PREF_SHIFT_REG, 0); + restore_ecx = 2; + } +#endif /* SLJIT_CONFIG_X86_64 */ + } + EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src3, src3w); + } + + if (move_src1) { + EMIT_MOV(compiler, dst_reg, 0, src1_reg, src1w); + src1_reg = dst_reg; + src1w = 0; + } + } + + inst = emit_x86_instruction(compiler, 2, src2_reg, 0, src1_reg, src1w); + FAIL_IF(!inst); + inst[0] = GROUP_0F; + + if (src3 & SLJIT_IMM) { + inst[1] = U8((is_left ? SHLD : SHRD) - 1); + + /* Immedate argument is added separately. */ + inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); + FAIL_IF(!inst); + INC_SIZE(1); + *inst = U8(src3w); + } else + inst[1] = U8(is_left ? SHLD : SHRD); + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if (restore_ecx) { + compiler->mode32 = 0; + EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); + } + + if (src1_reg != dst_reg) { + compiler->mode32 = op & SLJIT_32; + return emit_mov(compiler, dst_reg, dstw, src1_reg, 0); + } +#else /* !SLJIT_CONFIG_X86_64 */ + if (restore_ecx) + EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, restore_ecx == 1 ? TMP_REG1 : SLJIT_MEM1(SLJIT_SP), 0); + + if (src1_reg != dst_reg) + EMIT_MOV(compiler, dst_reg, dstw, src1_reg, 0); + + if (restore_sp4) + return emit_mov(compiler, restore_sp4, 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32)); +#endif /* SLJIT_CONFIG_X86_32 */ + + return SLJIT_SUCCESS; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { @@ -2377,6 +2746,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *comp return SLJIT_SUCCESS; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw)); + ADJUST_LOCAL_OFFSET(dst, dstw); + + CHECK_EXTRA_REGS(dst, dstw, (void)0); + + switch (op) { + case SLJIT_FAST_ENTER: + return emit_fast_enter(compiler, dst, dstw); + case SLJIT_GET_RETURN_ADDRESS: + return sljit_emit_get_return_address(compiler, dst, dstw); + } + + return SLJIT_SUCCESS; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_register_index(reg)); @@ -2442,8 +2830,8 @@ static sljit_s32 emit_sse2(struct sljit_compiler *compiler, sljit_u8 opcode, inst = emit_x86_instruction(compiler, 2 | (single ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2, xmm1, 0, xmm2, xmm2w); FAIL_IF(!inst); - *inst++ = GROUP_0F; - *inst = opcode; + inst[0] = GROUP_0F; + inst[1] = opcode; return SLJIT_SUCCESS; } @@ -2454,8 +2842,8 @@ static sljit_s32 emit_sse2_logic(struct sljit_compiler *compiler, sljit_u8 opcod inst = emit_x86_instruction(compiler, 2 | (pref66 ? EX86_PREF_66 : 0) | EX86_SSE2, xmm1, 0, xmm2, xmm2w); FAIL_IF(!inst); - *inst++ = GROUP_0F; - *inst = opcode; + inst[0] = GROUP_0F; + inst[1] = opcode; return SLJIT_SUCCESS; } @@ -2475,9 +2863,12 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { - sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; + sljit_s32 dst_r; sljit_u8 *inst; + CHECK_EXTRA_REGS(dst, dstw, (void)0); + dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; + #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64) compiler->mode32 = 0; @@ -2485,8 +2876,8 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp inst = emit_x86_instruction(compiler, 2 | ((op & SLJIT_32) ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2_OP2, dst_r, 0, src, srcw); FAIL_IF(!inst); - *inst++ = GROUP_0F; - *inst = CVTTSD2SI_r_xm; + inst[0] = GROUP_0F; + inst[1] = CVTTSD2SI_r_xm; if (dst & SLJIT_MEM) return emit_mov(compiler, dst, dstw, TMP_REG1, 0); @@ -2500,6 +2891,8 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG; sljit_u8 *inst; + CHECK_EXTRA_REGS(src, srcw, (void)0); + #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW) compiler->mode32 = 0; @@ -2517,8 +2910,8 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp inst = emit_x86_instruction(compiler, 2 | ((op & SLJIT_32) ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2_OP1, dst_r, 0, src, srcw); FAIL_IF(!inst); - *inst++ = GROUP_0F; - *inst = CVTSI2SD_x_rm; + inst[0] = GROUP_0F; + inst[1] = CVTSI2SD_x_rm; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = 1; @@ -2534,9 +2927,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile { switch (GET_FLAG_TYPE(op)) { case SLJIT_ORDERED_LESS: - case SLJIT_UNORDERED_OR_GREATER_EQUAL: case SLJIT_UNORDERED_OR_GREATER: - case SLJIT_ORDERED_LESS_EQUAL: if (!FAST_IS_REG(src2)) { FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src2, src2w)); src2 = TMP_FREG; @@ -2701,9 +3092,8 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi inst = (sljit_u8*)ensure_buf(compiler, 2); PTR_FAIL_IF(!inst); - - *inst++ = 0; - *inst++ = 0; + inst[0] = 0; + inst[1] = 0; return label; } @@ -2731,8 +3121,8 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile inst = (sljit_u8*)ensure_buf(compiler, 2); PTR_FAIL_IF_NULL(inst); - *inst++ = 0; - *inst++ = 1; + inst[0] = 0; + inst[1] = 1; return jump; } @@ -2763,8 +3153,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi inst = (sljit_u8*)ensure_buf(compiler, 2); FAIL_IF_NULL(inst); - *inst++ = 0; - *inst++ = 1; + inst[0] = 0; + inst[1] = 1; } else { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) @@ -2773,8 +3163,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi #endif inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw); FAIL_IF(!inst); - *inst++ = GROUP_FF; - *inst = U8(*inst | ((type >= SLJIT_FAST_CALL) ? CALL_rm : JMP_rm)); + inst[0] = GROUP_FF; + inst[1] = U8(inst[1] | ((type >= SLJIT_FAST_CALL) ? CALL_rm : JMP_rm)); } return SLJIT_SUCCESS; } @@ -2784,10 +3174,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co sljit_s32 type) { sljit_u8 *inst; - sljit_u8 cond_set = 0; + sljit_u8 cond_set; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) sljit_s32 reg; -#endif +#endif /* !SLJIT_CONFIG_X86_64 */ /* ADJUST_LOCAL_OFFSET and CHECK_EXTRA_REGS might overwrite these values. */ sljit_s32 dst_save = dst; sljit_sw dstw_save = dstw; @@ -2807,13 +3197,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co FAIL_IF(!inst); INC_SIZE(4 + 3); /* Set low register to conditional flag. */ - *inst++ = (reg_map[TMP_REG1] <= 7) ? REX : REX_B; - *inst++ = GROUP_0F; - *inst++ = cond_set; - *inst++ = MOD_REG | reg_lmap[TMP_REG1]; - *inst++ = U8(REX | (reg_map[TMP_REG1] <= 7 ? 0 : REX_R) | (reg_map[dst] <= 7 ? 0 : REX_B)); - *inst++ = OR_rm8_r8; - *inst++ = U8(MOD_REG | (reg_lmap[TMP_REG1] << 3) | reg_lmap[dst]); + inst[0] = (reg_map[TMP_REG1] <= 7) ? REX : REX_B; + inst[1] = GROUP_0F; + inst[2] = cond_set; + inst[3] = MOD_REG | reg_lmap[TMP_REG1]; + inst[4] = U8(REX | (reg_map[TMP_REG1] <= 7 ? 0 : REX_R) | (reg_map[dst] <= 7 ? 0 : REX_B)); + inst[5] = OR_rm8_r8; + inst[6] = U8(MOD_REG | (reg_lmap[TMP_REG1] << 3) | reg_lmap[dst]); return SLJIT_SUCCESS; } @@ -2823,15 +3213,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co FAIL_IF(!inst); INC_SIZE(4 + 4); /* Set low register to conditional flag. */ - *inst++ = (reg_map[reg] <= 7) ? REX : REX_B; - *inst++ = GROUP_0F; - *inst++ = cond_set; - *inst++ = MOD_REG | reg_lmap[reg]; - *inst++ = REX_W | (reg_map[reg] <= 7 ? 0 : (REX_B | REX_R)); + inst[0] = (reg_map[reg] <= 7) ? REX : REX_B; + inst[1] = GROUP_0F; + inst[2] = cond_set; + inst[3] = MOD_REG | reg_lmap[reg]; + inst[4] = REX_W | (reg_map[reg] <= 7 ? 0 : (REX_B | REX_R)); /* The movzx instruction does not affect flags. */ - *inst++ = GROUP_0F; - *inst++ = MOVZX_r_rm8; - *inst = U8(MOD_REG | (reg_lmap[reg] << 3) | reg_lmap[reg]); + inst[5] = GROUP_0F; + inst[6] = MOVZX_r_rm8; + inst[7] = U8(MOD_REG | (reg_lmap[reg] << 3) | reg_lmap[reg]); if (reg != TMP_REG1) return SLJIT_SUCCESS; @@ -2844,110 +3234,52 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co SLJIT_SKIP_CHECKS(compiler); return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REG1, 0); -#else +#else /* !SLJIT_CONFIG_X86_64 */ + SLJIT_ASSERT(reg_map[TMP_REG1] < 4); + /* The SLJIT_CONFIG_X86_32 code path starts here. */ - if (GET_OPCODE(op) < SLJIT_ADD && FAST_IS_REG(dst)) { - if (reg_map[dst] <= 4) { - /* Low byte is accessible. */ - inst = (sljit_u8*)ensure_buf(compiler, 1 + 3 + 3); - FAIL_IF(!inst); - INC_SIZE(3 + 3); - /* Set low byte to conditional flag. */ - *inst++ = GROUP_0F; - *inst++ = cond_set; - *inst++ = U8(MOD_REG | reg_map[dst]); - - *inst++ = GROUP_0F; - *inst++ = MOVZX_r_rm8; - *inst = U8(MOD_REG | (reg_map[dst] << 3) | reg_map[dst]); - return SLJIT_SUCCESS; - } - - /* Low byte is not accessible. */ - if (cpu_has_cmov == -1) - get_cpu_features(); - - if (cpu_has_cmov) { - EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, 1); - /* a xor reg, reg operation would overwrite the flags. */ - EMIT_MOV(compiler, dst, 0, SLJIT_IMM, 0); - - inst = (sljit_u8*)ensure_buf(compiler, 1 + 3); - FAIL_IF(!inst); - INC_SIZE(3); - - *inst++ = GROUP_0F; - /* cmovcc = setcc - 0x50. */ - *inst++ = U8(cond_set - 0x50); - *inst++ = U8(MOD_REG | (reg_map[dst] << 3) | reg_map[TMP_REG1]); - return SLJIT_SUCCESS; - } - - inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 3 + 3 + 1); + if (GET_OPCODE(op) < SLJIT_ADD && FAST_IS_REG(dst) && reg_map[dst] <= 4) { + /* Low byte is accessible. */ + inst = (sljit_u8*)ensure_buf(compiler, 1 + 3 + 3); FAIL_IF(!inst); - INC_SIZE(1 + 3 + 3 + 1); - *inst++ = U8(XCHG_EAX_r | reg_map[TMP_REG1]); - /* Set al to conditional flag. */ - *inst++ = GROUP_0F; - *inst++ = cond_set; - *inst++ = MOD_REG | 0 /* eax */; + INC_SIZE(3 + 3); + /* Set low byte to conditional flag. */ + inst[0] = GROUP_0F; + inst[1] = cond_set; + inst[2] = U8(MOD_REG | reg_map[dst]); - *inst++ = GROUP_0F; - *inst++ = MOVZX_r_rm8; - *inst++ = U8(MOD_REG | (reg_map[dst] << 3) | 0 /* eax */); - *inst++ = U8(XCHG_EAX_r | reg_map[TMP_REG1]); + inst[3] = GROUP_0F; + inst[4] = MOVZX_r_rm8; + inst[5] = U8(MOD_REG | (reg_map[dst] << 3) | reg_map[dst]); return SLJIT_SUCCESS; } if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && FAST_IS_REG(dst) && reg_map[dst] <= 4) { - SLJIT_ASSERT(reg_map[SLJIT_R0] == 0); + inst = (sljit_u8*)ensure_buf(compiler, 1 + 3 + 2); + FAIL_IF(!inst); + INC_SIZE(3 + 2); - if (dst != SLJIT_R0) { - inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 3 + 2 + 1); - FAIL_IF(!inst); - INC_SIZE(1 + 3 + 2 + 1); - /* Set low register to conditional flag. */ - *inst++ = U8(XCHG_EAX_r | reg_map[TMP_REG1]); - *inst++ = GROUP_0F; - *inst++ = cond_set; - *inst++ = MOD_REG | 0 /* eax */; - *inst++ = OR_rm8_r8; - *inst++ = MOD_REG | (0 /* eax */ << 3) | reg_map[dst]; - *inst++ = U8(XCHG_EAX_r | reg_map[TMP_REG1]); - } - else { - inst = (sljit_u8*)ensure_buf(compiler, 1 + 2 + 3 + 2 + 2); - FAIL_IF(!inst); - INC_SIZE(2 + 3 + 2 + 2); - /* Set low register to conditional flag. */ - *inst++ = XCHG_r_rm; - *inst++ = U8(MOD_REG | (1 /* ecx */ << 3) | reg_map[TMP_REG1]); - *inst++ = GROUP_0F; - *inst++ = cond_set; - *inst++ = MOD_REG | 1 /* ecx */; - *inst++ = OR_rm8_r8; - *inst++ = MOD_REG | (1 /* ecx */ << 3) | 0 /* eax */; - *inst++ = XCHG_r_rm; - *inst++ = U8(MOD_REG | (1 /* ecx */ << 3) | reg_map[TMP_REG1]); - } + /* Set low byte to conditional flag. */ + inst[0] = GROUP_0F; + inst[1] = cond_set; + inst[2] = U8(MOD_REG | reg_map[TMP_REG1]); + + inst[3] = OR_rm8_r8; + inst[4] = U8(MOD_REG | (reg_map[TMP_REG1] << 3) | reg_map[dst]); return SLJIT_SUCCESS; } - /* Set TMP_REG1 to the bit. */ - inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 3 + 3 + 1); + inst = (sljit_u8*)ensure_buf(compiler, 1 + 3 + 3); FAIL_IF(!inst); - INC_SIZE(1 + 3 + 3 + 1); - *inst++ = U8(XCHG_EAX_r | reg_map[TMP_REG1]); - /* Set al to conditional flag. */ - *inst++ = GROUP_0F; - *inst++ = cond_set; - *inst++ = MOD_REG | 0 /* eax */; + INC_SIZE(3 + 3); + /* Set low byte to conditional flag. */ + inst[0] = GROUP_0F; + inst[1] = cond_set; + inst[2] = U8(MOD_REG | reg_map[TMP_REG1]); - *inst++ = GROUP_0F; - *inst++ = MOVZX_r_rm8; - *inst++ = MOD_REG | (0 << 3) /* eax */ | 0 /* eax */; - - *inst++ = U8(XCHG_EAX_r | reg_map[TMP_REG1]); + inst[3] = GROUP_0F; + inst[4] = MOVZX_r_rm8; + inst[5] = U8(MOD_REG | (reg_map[TMP_REG1] << 3) | reg_map[TMP_REG1]); if (GET_OPCODE(op) < SLJIT_ADD) return emit_mov(compiler, dst, dstw, TMP_REG1, 0); @@ -2967,7 +3299,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - dst_reg &= ~SLJIT_32; + type &= ~SLJIT_32; if (!sljit_has_cpu_feature(SLJIT_HAS_CMOV) || (dst_reg >= SLJIT_R3 && dst_reg <= SLJIT_S3)) return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw); @@ -2980,8 +3312,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil CHECK_EXTRA_REGS(src, srcw, (void)0); #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) - compiler->mode32 = dst_reg & SLJIT_32; - dst_reg &= ~SLJIT_32; + compiler->mode32 = type & SLJIT_32; + type &= ~SLJIT_32; #endif if (SLJIT_UNLIKELY(src & SLJIT_IMM)) { @@ -2992,8 +3324,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil inst = emit_x86_instruction(compiler, 2, dst_reg, 0, src, srcw); FAIL_IF(!inst); - *inst++ = GROUP_0F; - *inst = U8(get_jump_code((sljit_uw)type) - 0x40); + inst[0] = GROUP_0F; + inst[1] = U8(get_jump_code((sljit_uw)type) - 0x40); return SLJIT_SUCCESS; } @@ -3060,8 +3392,8 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi inst = (sljit_u8*)ensure_buf(compiler, 2); PTR_FAIL_IF(!inst); - *inst++ = 0; - *inst++ = 2; + inst[0] = 0; + inst[1] = 2; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (dst & SLJIT_MEM) @@ -3114,8 +3446,8 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct slj inst = (sljit_u8*)ensure_buf(compiler, 2); PTR_FAIL_IF(!inst); - *inst++ = 0; - *inst++ = 3; + inst[0] = 0; + inst[1] = 3; return put_label; } diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitProtExecAllocator.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitProtExecAllocator.c deleted file mode 100644 index 915411fbed..0000000000 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitProtExecAllocator.c +++ /dev/null @@ -1,474 +0,0 @@ -/* - * Stack-less Just-In-Time compiler - * - * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - This file contains a simple executable memory allocator - - It is assumed, that executable code blocks are usually medium (or sometimes - large) memory blocks, and the allocator is not too frequently called (less - optimized than other allocators). Thus, using it as a generic allocator is - not suggested. - - How does it work: - Memory is allocated in continuous memory areas called chunks by alloc_chunk() - Chunk format: - [ block ][ block ] ... [ block ][ block terminator ] - - All blocks and the block terminator is started with block_header. The block - header contains the size of the previous and the next block. These sizes - can also contain special values. - Block size: - 0 - The block is a free_block, with a different size member. - 1 - The block is a block terminator. - n - The block is used at the moment, and the value contains its size. - Previous block size: - 0 - This is the first block of the memory chunk. - n - The size of the previous block. - - Using these size values we can go forward or backward on the block chain. - The unused blocks are stored in a chain list pointed by free_blocks. This - list is useful if we need to find a suitable memory area when the allocator - is called. - - When a block is freed, the new free block is connected to its adjacent free - blocks if possible. - - [ free block ][ used block ][ free block ] - and "used block" is freed, the three blocks are connected together: - [ one big free block ] -*/ - -/* --------------------------------------------------------------------- */ -/* System (OS) functions */ -/* --------------------------------------------------------------------- */ - -/* 64 KByte. */ -#define CHUNK_SIZE (sljit_uw)0x10000 - -struct chunk_header { - void *executable; -}; - -/* - alloc_chunk / free_chunk : - * allocate executable system memory chunks - * the size is always divisible by CHUNK_SIZE - SLJIT_ALLOCATOR_LOCK / SLJIT_ALLOCATOR_UNLOCK : - * provided as part of sljitUtils - * only the allocator requires this lock, sljit is fully thread safe - as it only uses local variables -*/ - -#ifndef __NetBSD__ -#include -#include -#include -#include - -#ifndef O_NOATIME -#define O_NOATIME 0 -#endif - -/* this is a linux extension available since kernel 3.11 */ -#ifndef O_TMPFILE -#define O_TMPFILE 020200000 -#endif - -#ifndef _GNU_SOURCE -char *secure_getenv(const char *name); -int mkostemp(char *template, int flags); -#endif - -static SLJIT_INLINE int create_tempfile(void) -{ - int fd; - char tmp_name[256]; - size_t tmp_name_len = 0; - char *dir; - struct stat st; -#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED - mode_t mode; -#endif - -#ifdef HAVE_MEMFD_CREATE - /* this is a GNU extension, make sure to use -D_GNU_SOURCE */ - fd = memfd_create("sljit", MFD_CLOEXEC); - if (fd != -1) { - fchmod(fd, 0); - return fd; - } -#endif - - dir = secure_getenv("TMPDIR"); - - if (dir) { - tmp_name_len = strlen(dir); - if (tmp_name_len > 0 && tmp_name_len < sizeof(tmp_name)) { - if ((stat(dir, &st) == 0) && S_ISDIR(st.st_mode)) - strcpy(tmp_name, dir); - } - } - -#ifdef P_tmpdir - if (!tmp_name_len) { - tmp_name_len = strlen(P_tmpdir); - if (tmp_name_len > 0 && tmp_name_len < sizeof(tmp_name)) - strcpy(tmp_name, P_tmpdir); - } -#endif - if (!tmp_name_len) { - strcpy(tmp_name, "/tmp"); - tmp_name_len = 4; - } - - SLJIT_ASSERT(tmp_name_len > 0 && tmp_name_len < sizeof(tmp_name)); - - if (tmp_name[tmp_name_len - 1] == '/') - tmp_name[--tmp_name_len] = '\0'; - -#ifdef __linux__ - /* - * the previous trimming might had left an empty string if TMPDIR="/" - * so work around the problem below - */ - fd = open(tmp_name_len ? tmp_name : "/", - O_TMPFILE | O_EXCL | O_RDWR | O_NOATIME | O_CLOEXEC, 0); - if (fd != -1) - return fd; -#endif - - if (tmp_name_len + 7 >= sizeof(tmp_name)) - return -1; - - strcpy(tmp_name + tmp_name_len, "/XXXXXX"); -#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED - mode = umask(0777); -#endif - fd = mkostemp(tmp_name, O_CLOEXEC | O_NOATIME); -#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED - umask(mode); -#else - fchmod(fd, 0); -#endif - - if (fd == -1) - return -1; - - if (unlink(tmp_name)) { - close(fd); - return -1; - } - - return fd; -} - -static SLJIT_INLINE struct chunk_header* alloc_chunk(sljit_uw size) -{ - struct chunk_header *retval; - int fd; - - fd = create_tempfile(); - if (fd == -1) - return NULL; - - if (ftruncate(fd, (off_t)size)) { - close(fd); - return NULL; - } - - retval = (struct chunk_header *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - - if (retval == MAP_FAILED) { - close(fd); - return NULL; - } - - retval->executable = mmap(NULL, size, PROT_READ | PROT_EXEC, MAP_SHARED, fd, 0); - - if (retval->executable == MAP_FAILED) { - munmap((void *)retval, size); - close(fd); - return NULL; - } - - close(fd); - return retval; -} -#else -/* - * MAP_REMAPDUP is a NetBSD extension available sinde 8.0, make sure to - * adjust your feature macros (ex: -D_NETBSD_SOURCE) as needed - */ -static SLJIT_INLINE struct chunk_header* alloc_chunk(sljit_uw size) -{ - struct chunk_header *retval; - - retval = (struct chunk_header *)mmap(NULL, size, - PROT_READ | PROT_WRITE | PROT_MPROTECT(PROT_EXEC), - MAP_ANON | MAP_SHARED, -1, 0); - - if (retval == MAP_FAILED) - return NULL; - - retval->executable = mremap(retval, size, NULL, size, MAP_REMAPDUP); - if (retval->executable == MAP_FAILED) { - munmap((void *)retval, size); - return NULL; - } - - if (mprotect(retval->executable, size, PROT_READ | PROT_EXEC) == -1) { - munmap(retval->executable, size); - munmap((void *)retval, size); - return NULL; - } - - return retval; -} -#endif /* NetBSD */ - -static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size) -{ - struct chunk_header *header = ((struct chunk_header *)chunk) - 1; - - munmap(header->executable, size); - munmap((void *)header, size); -} - -/* --------------------------------------------------------------------- */ -/* Common functions */ -/* --------------------------------------------------------------------- */ - -#define CHUNK_MASK (~(CHUNK_SIZE - 1)) - -struct block_header { - sljit_uw size; - sljit_uw prev_size; - sljit_sw executable_offset; -}; - -struct free_block { - struct block_header header; - struct free_block *next; - struct free_block *prev; - sljit_uw size; -}; - -#define AS_BLOCK_HEADER(base, offset) \ - ((struct block_header*)(((sljit_u8*)base) + offset)) -#define AS_FREE_BLOCK(base, offset) \ - ((struct free_block*)(((sljit_u8*)base) + offset)) -#define MEM_START(base) ((void*)((base) + 1)) -#define ALIGN_SIZE(size) (((size) + sizeof(struct block_header) + 7u) & ~(sljit_uw)7) - -static struct free_block* free_blocks; -static sljit_uw allocated_size; -static sljit_uw total_size; - -static SLJIT_INLINE void sljit_insert_free_block(struct free_block *free_block, sljit_uw size) -{ - free_block->header.size = 0; - free_block->size = size; - - free_block->next = free_blocks; - free_block->prev = NULL; - if (free_blocks) - free_blocks->prev = free_block; - free_blocks = free_block; -} - -static SLJIT_INLINE void sljit_remove_free_block(struct free_block *free_block) -{ - if (free_block->next) - free_block->next->prev = free_block->prev; - - if (free_block->prev) - free_block->prev->next = free_block->next; - else { - SLJIT_ASSERT(free_blocks == free_block); - free_blocks = free_block->next; - } -} - -SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size) -{ - struct chunk_header *chunk_header; - struct block_header *header; - struct block_header *next_header; - struct free_block *free_block; - sljit_uw chunk_size; - sljit_sw executable_offset; - - SLJIT_ALLOCATOR_LOCK(); - if (size < (64 - sizeof(struct block_header))) - size = (64 - sizeof(struct block_header)); - size = ALIGN_SIZE(size); - - free_block = free_blocks; - while (free_block) { - if (free_block->size >= size) { - chunk_size = free_block->size; - if (chunk_size > size + 64) { - /* We just cut a block from the end of the free block. */ - chunk_size -= size; - free_block->size = chunk_size; - header = AS_BLOCK_HEADER(free_block, chunk_size); - header->prev_size = chunk_size; - header->executable_offset = free_block->header.executable_offset; - AS_BLOCK_HEADER(header, size)->prev_size = size; - } - else { - sljit_remove_free_block(free_block); - header = (struct block_header*)free_block; - size = chunk_size; - } - allocated_size += size; - header->size = size; - SLJIT_ALLOCATOR_UNLOCK(); - return MEM_START(header); - } - free_block = free_block->next; - } - - chunk_size = sizeof(struct chunk_header) + sizeof(struct block_header); - chunk_size = (chunk_size + size + CHUNK_SIZE - 1) & CHUNK_MASK; - - chunk_header = alloc_chunk(chunk_size); - if (!chunk_header) { - SLJIT_ALLOCATOR_UNLOCK(); - return NULL; - } - - executable_offset = (sljit_sw)((sljit_u8*)chunk_header->executable - (sljit_u8*)chunk_header); - - chunk_size -= sizeof(struct chunk_header) + sizeof(struct block_header); - total_size += chunk_size; - - header = (struct block_header *)(chunk_header + 1); - - header->prev_size = 0; - header->executable_offset = executable_offset; - if (chunk_size > size + 64) { - /* Cut the allocated space into a free and a used block. */ - allocated_size += size; - header->size = size; - chunk_size -= size; - - free_block = AS_FREE_BLOCK(header, size); - free_block->header.prev_size = size; - free_block->header.executable_offset = executable_offset; - sljit_insert_free_block(free_block, chunk_size); - next_header = AS_BLOCK_HEADER(free_block, chunk_size); - } - else { - /* All space belongs to this allocation. */ - allocated_size += chunk_size; - header->size = chunk_size; - next_header = AS_BLOCK_HEADER(header, chunk_size); - } - next_header->size = 1; - next_header->prev_size = chunk_size; - next_header->executable_offset = executable_offset; - SLJIT_ALLOCATOR_UNLOCK(); - return MEM_START(header); -} - -SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr) -{ - struct block_header *header; - struct free_block* free_block; - - SLJIT_ALLOCATOR_LOCK(); - header = AS_BLOCK_HEADER(ptr, -(sljit_sw)sizeof(struct block_header)); - header = AS_BLOCK_HEADER(header, -header->executable_offset); - allocated_size -= header->size; - - /* Connecting free blocks together if possible. */ - - /* If header->prev_size == 0, free_block will equal to header. - In this case, free_block->header.size will be > 0. */ - free_block = AS_FREE_BLOCK(header, -(sljit_sw)header->prev_size); - if (SLJIT_UNLIKELY(!free_block->header.size)) { - free_block->size += header->size; - header = AS_BLOCK_HEADER(free_block, free_block->size); - header->prev_size = free_block->size; - } - else { - free_block = (struct free_block*)header; - sljit_insert_free_block(free_block, header->size); - } - - header = AS_BLOCK_HEADER(free_block, free_block->size); - if (SLJIT_UNLIKELY(!header->size)) { - free_block->size += ((struct free_block*)header)->size; - sljit_remove_free_block((struct free_block*)header); - header = AS_BLOCK_HEADER(free_block, free_block->size); - header->prev_size = free_block->size; - } - - /* The whole chunk is free. */ - if (SLJIT_UNLIKELY(!free_block->header.prev_size && header->size == 1)) { - /* If this block is freed, we still have (allocated_size / 2) free space. */ - if (total_size - free_block->size > (allocated_size * 3 / 2)) { - total_size -= free_block->size; - sljit_remove_free_block(free_block); - free_chunk(free_block, free_block->size + - sizeof(struct chunk_header) + - sizeof(struct block_header)); - } - } - - SLJIT_ALLOCATOR_UNLOCK(); -} - -SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void) -{ - struct free_block* free_block; - struct free_block* next_free_block; - - SLJIT_ALLOCATOR_LOCK(); - - free_block = free_blocks; - while (free_block) { - next_free_block = free_block->next; - if (!free_block->header.prev_size && - AS_BLOCK_HEADER(free_block, free_block->size)->size == 1) { - total_size -= free_block->size; - sljit_remove_free_block(free_block); - free_chunk(free_block, free_block->size + - sizeof(struct chunk_header) + - sizeof(struct block_header)); - } - free_block = next_free_block; - } - - SLJIT_ASSERT((total_size && free_blocks) || (!total_size && !free_blocks)); - SLJIT_ALLOCATOR_UNLOCK(); -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr) -{ - return ((struct block_header *)(ptr))[-1].executable_offset; -} diff --git a/waterbox/ares64/ares/thirdparty/sljit/test_src/sljitTest.c b/waterbox/ares64/ares/thirdparty/sljit/test_src/sljitTest.c index d20695e9ce..1a133a7a4d 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/test_src/sljitTest.c +++ b/waterbox/ares64/ares/thirdparty/sljit/test_src/sljitTest.c @@ -74,6 +74,9 @@ union executable_code { void (SLJIT_FUNC *test73_f2)(sljit_sw a, sljit_sw b, sljit_s32 c, sljit_s32 d); void (SLJIT_FUNC *test73_f3)(sljit_f64 a, sljit_f64 b, sljit_f64 c, sljit_sw d); void (SLJIT_FUNC *test73_f4)(sljit_f64 a, sljit_f64 b, sljit_sw c, sljit_sw d); + + sljit_f32 (SLJIT_FUNC *test81_f1)(sljit_sw a); + sljit_f64 (SLJIT_FUNC *test81_f2)(sljit_sw a); }; typedef union executable_code executable_code; @@ -94,6 +97,12 @@ static sljit_s32 silent = 0; return; \ } +#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) +#define WCONST(const64, const32) ((sljit_sw)SLJIT_W(const64)) +#else /* !SLJIT_64BIT_ARCHITECTURE */ +#define WCONST(const64, const32) ((sljit_sw)const32) +#endif /* SLJIT_64BIT_ARCHITECTURE */ + static void cond_set(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_s32 type) { /* Testing both sljit_emit_op_flags and sljit_emit_jump. */ @@ -213,7 +222,7 @@ static void test2(void) /* Test mov. */ executable_code code; struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[8]; + sljit_sw buf[10]; static sljit_sw data[2] = { 0, -9876 }; if (verbose) @@ -232,24 +241,38 @@ static void test2(void) sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 2, 0, 0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 9999); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_S0, 0); + /* buf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_sw), SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, sizeof(sljit_sw)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM2(SLJIT_S1, SLJIT_R1), 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 2); + /* buf[2] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM2(SLJIT_S1, SLJIT_S0), SLJIT_WORD_SHIFT, SLJIT_MEM2(SLJIT_S1, SLJIT_R1), 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 3); + /* buf[3] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM2(SLJIT_S1, SLJIT_S0), SLJIT_WORD_SHIFT, SLJIT_MEM0(), (sljit_sw)&buf); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_sw)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), (sljit_sw)&data); + /* buf[4] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_sw), SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf - 0x12345678); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), 0x12345678); + /* buf[5] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_sw), SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 3456); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&buf - 0xff890 + 6 * (sljit_sw)sizeof(sljit_sw)); + /* buf[6] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0xff890, SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&buf + 0xff890 + 7 * (sljit_sw)sizeof(sljit_sw)); + /* buf[7] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), -0xff890, SLJIT_R0, 0); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf - 0xfff0ff + 8 * (sljit_sw)sizeof(sljit_sw)); + /* buf[8] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0xfff0ff, SLJIT_IMM, 7896); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf + 0xfff100 + 9 * (sljit_sw)sizeof(sljit_sw)); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -2450); + /* buf[9] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), -0xfff100, SLJIT_R1, 0); sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R2, 0); code.code = sljit_generate_code(compiler); @@ -262,8 +285,10 @@ static void test2(void) FAILED(buf[3] != 5678, "test2 case 4 failed\n"); FAILED(buf[4] != -9876, "test2 case 5 failed\n"); FAILED(buf[5] != 5678, "test2 case 6 failed\n"); - FAILED(buf[6] != 3456, "test2 case 6 failed\n"); - FAILED(buf[7] != 3456, "test2 case 6 failed\n"); + FAILED(buf[6] != 3456, "test2 case 7 failed\n"); + FAILED(buf[7] != 3456, "test2 case 8 failed\n"); + FAILED(buf[8] != 7896, "test2 case 9 failed\n"); + FAILED(buf[9] != -2450, "test2 case 10 failed\n"); sljit_free_code(code.code, NULL); successful_tests++; @@ -287,13 +312,16 @@ static void test3(void) buf[4] = 0x12345678; sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 1, 0, 0, 0); + /* buf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_op1(compiler, SLJIT_NOT, SLJIT_MEM0(), (sljit_sw)&buf[1], SLJIT_MEM0(), (sljit_sw)&buf[1]); - sljit_emit_op1(compiler, SLJIT_NOT, SLJIT_RETURN_REG, 0, SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_op1(compiler, SLJIT_NOT, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2); + sljit_emit_op2(compiler, SLJIT_XOR, SLJIT_MEM0(), (sljit_sw)&buf[1], SLJIT_MEM0(), (sljit_sw)&buf[1], SLJIT_IMM, -1); + /* buf[3] */ + sljit_emit_op2(compiler, SLJIT_XOR, SLJIT_RETURN_REG, 0, SLJIT_IMM, -1, SLJIT_MEM1(SLJIT_S0), 0); + sljit_emit_op2(compiler, SLJIT_XOR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_IMM, -1); + /* buf[4] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&buf[4] - 0xff0000 - 0x20); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, (sljit_sw)&buf[4] - 0xff0000); - sljit_emit_op1(compiler, SLJIT_NOT, SLJIT_MEM1(SLJIT_R1), 0xff0000 + 0x20, SLJIT_MEM1(SLJIT_R2), 0xff0000); + sljit_emit_op2(compiler, SLJIT_XOR, SLJIT_MEM1(SLJIT_R1), 0xff0000 + 0x20, SLJIT_IMM, -1, SLJIT_MEM1(SLJIT_R2), 0xff0000); sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); code.code = sljit_generate_code(compiler); @@ -326,11 +354,14 @@ static void test4(void) buf[3] = 0; sljit_emit_enter(compiler, 0, SLJIT_ARGS2(W, P, W), 3, 2, 0, 0, 0); - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_IMM, 0, SLJIT_S1, 0); + /* buf[0] */ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM0(), (sljit_sw)&buf[0], SLJIT_IMM, 0, SLJIT_MEM0(), (sljit_sw)&buf[1]); + /* buf[2] */ + sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_IMM, 0, SLJIT_S1, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 299); + /* buf[3] */ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_IMM, 0, SLJIT_R1, 0); - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0, SLJIT_S1, 0); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2); sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); code.code = sljit_generate_code(compiler); @@ -370,22 +401,32 @@ static void test5(void) sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 2, 0, 0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_sw)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 50); + /* buf[2] */ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 1, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 1, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 0); + /* buf[0] */ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_sw) + 2); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 50); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), 0); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); + /* buf[5] */ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_IMM, 4, SLJIT_R0, 0); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_IMM, 50, SLJIT_R1, 0); + /* buf[4] */ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_IMM, 50, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw)); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R1, 0); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw)); + /* buf[5] */ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw)); + /* buf[3] */ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R1, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0x1e7d39f2); + /* buf[6] */ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R1, 0, SLJIT_IMM, 0x23de7c06); + /* buf[7] */ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_IMM, 0x3d72e452, SLJIT_R1, 0); + /* buf[8] */ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_IMM, -43, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw)); + /* Return value */ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_IMM, 1000, SLJIT_R0, 0); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1430); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_IMM, -99, SLJIT_R0, 0); @@ -436,32 +477,44 @@ static void test6(void) sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 1, 0, 0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1); sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, -1); + /* buf[0] */ sljit_emit_op2(compiler, SLJIT_ADDC, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, 0, SLJIT_IMM, 0); sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R0, 0); + /* buf[1] */ sljit_emit_op2(compiler, SLJIT_ADDC, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_IMM, 4); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 100); + /* buf[2] */ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_R0, 0, SLJIT_IMM, 50); sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 6000); + /* buf[3] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_IMM, 10); sljit_emit_op2(compiler, SLJIT_SUBC, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_IMM, 5); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 100); - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2); + sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2); + /* buf[4] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 4, SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 5000); + sljit_emit_op2(compiler, SLJIT_SUBC, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 4, SLJIT_R0, 0); sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 4, SLJIT_R0, 0); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_R1, 0); + /* buf[5] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 5, SLJIT_R1, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 5000); sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_IMM, 6000, SLJIT_R0, 0); + /* buf[6] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 6, SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 100); sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 32768); + /* buf[7] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 7, SLJIT_R1, 0); sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, -32767); + /* buf[8] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 8, SLJIT_R1, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x52cd3bf4); + /* buf[9] */ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 9, SLJIT_R0, 0, SLJIT_IMM, 0x3da297c6); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 6000); + /* buf[10] */ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 10, SLJIT_R1, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 10, SLJIT_R1, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 10); @@ -513,23 +566,33 @@ static void test7(void) sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 1, 0, 0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0xf0C000); + /* buf[2] */ sljit_emit_op2(compiler, SLJIT_OR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_R0, 0, SLJIT_IMM, 0x308f); + /* buf[0] */ sljit_emit_op2(compiler, SLJIT_XOR, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw)); + /* buf[3] */ sljit_emit_op2(compiler, SLJIT_AND, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_IMM, 0xf0f0f0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3); + /* buf[4] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0xC0F0); sljit_emit_op2(compiler, SLJIT_XOR, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 5); sljit_emit_op2(compiler, SLJIT_OR, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 0xff0000); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 4, SLJIT_R0, 0); + /* buf[5] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0xC0F0); sljit_emit_op2(compiler, SLJIT_AND, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 5); sljit_emit_op2(compiler, SLJIT_OR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 5, SLJIT_R2, 0, SLJIT_IMM, 0xff0000); + /* buf[1] */ sljit_emit_op2(compiler, SLJIT_XOR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_IMM, 0xFFFFFF, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw)); + /* buf[6] */ sljit_emit_op2(compiler, SLJIT_OR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 6, SLJIT_IMM, (sljit_sw)0xa56c82c0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 6); + /* buf[7] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 7); sljit_emit_op2(compiler, SLJIT_XOR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 7, SLJIT_IMM, (sljit_sw)0xff00ff00, SLJIT_R0, 0); + /* Return vaue */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0xff00ff00); sljit_emit_op2(compiler, SLJIT_OR, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 0x0f); sljit_emit_op2(compiler, SLJIT_AND, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0x888888, SLJIT_R1, 0); + sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); code.code = sljit_generate_code(compiler); @@ -593,10 +656,10 @@ static void test8(void) /* buf[6] */ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 6, SLJIT_OVERFLOW); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1); - sljit_emit_op1(compiler, SLJIT_NOT | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_R0, 0); + sljit_emit_op2(compiler, SLJIT_XOR | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, -1); /* buf[7] */ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 7, SLJIT_ZERO); - sljit_emit_op1(compiler, SLJIT_NOT | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_R1, 0); + sljit_emit_op2(compiler, SLJIT_XOR | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, -1, SLJIT_R1, 0); /* buf[8] */ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 8, SLJIT_ZERO); sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_IMM, 0xffff, SLJIT_R0, 0); @@ -688,7 +751,8 @@ static void test9(void) /* Test shift. */ executable_code code; struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[13]; + sljit_sw buf[15]; + sljit_s32 i; #ifdef SLJIT_PREF_SHIFT_REG sljit_s32 shift_reg = SLJIT_PREF_SHIFT_REG; #else @@ -701,57 +765,61 @@ static void test9(void) printf("Run test9\n"); FAILED(!compiler, "cannot create compiler\n"); - buf[0] = 0; - buf[1] = 0; - buf[2] = 0; - buf[3] = 0; + + for (i = 0; i < 15; i++) + buf[i] = -1; + buf[4] = 1 << 10; - buf[5] = 0; - buf[6] = 0; - buf[7] = 0; - buf[8] = 0; buf[9] = 3; - buf[10] = 0; - buf[11] = 0; - buf[12] = 0; sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 4, 2, 0, 0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0xf); sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 3); sljit_emit_op2(compiler, SLJIT_LSHR, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1); + /* buf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 1); + /* buf[1] */ sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R1, 0, SLJIT_IMM, 1); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -64); sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 2); + /* buf[2] */ sljit_emit_op2(compiler, SLJIT_ASHR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_R0, 0, shift_reg, 0); sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 0xff); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 4); sljit_emit_op2(compiler, SLJIT_SHL, shift_reg, 0, shift_reg, 0, SLJIT_R0, 0); + /* buf[3] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, shift_reg, 0); sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 0xff); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 8); + /* buf[4] */ sljit_emit_op2(compiler, SLJIT_LSHR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 4, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 4, SLJIT_R0, 0); + /* buf[5] */ sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 5, shift_reg, 0, SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 0xf); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2); sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_R0, 0); + /* buf[6] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 6, SLJIT_S1, 0); sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_R0, 0, SLJIT_S1, 0, SLJIT_R0, 0); + /* buf[7] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 7, SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0xf00); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 4); sljit_emit_op2(compiler, SLJIT_LSHR, SLJIT_R1, 0, SLJIT_R2, 0, SLJIT_R0, 0); + /* buf[8] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 8, SLJIT_R1, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)buf); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 9); + /* buf[9] */ sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_MEM2(SLJIT_R0, SLJIT_R1), SLJIT_WORD_SHIFT, SLJIT_MEM2(SLJIT_R0, SLJIT_R1), SLJIT_WORD_SHIFT, SLJIT_MEM2(SLJIT_R0, SLJIT_R1), SLJIT_WORD_SHIFT); sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 4); sljit_emit_op2(compiler, SLJIT_SHL, shift_reg, 0, SLJIT_IMM, 2, shift_reg, 0); + /* buf[10] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 10, shift_reg, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0xa9); @@ -774,6 +842,7 @@ static void test9(void) #if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R0, 0, SLJIT_R0, 0); #endif + /* buf[11] */ sljit_emit_op2(compiler, SLJIT_OR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 11, SLJIT_R1, 0, SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 0); @@ -788,8 +857,22 @@ static void test9(void) sljit_emit_op2(compiler, SLJIT_OR, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x630000); sljit_emit_op2(compiler, SLJIT_ASHR, SLJIT_R0, 0, SLJIT_R0, 0, shift_reg, 0); + /* buf[12] */ sljit_emit_op2(compiler, SLJIT_OR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 12, SLJIT_R1, 0, SLJIT_R0, 0); + /* Test shift_reg keeps 64 bit value after 32 bit operation. */ + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 0); + sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, -3062); + sljit_emit_op2(compiler, SLJIT_ASHR32, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R1, 0); + /* buf[13] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 13, shift_reg, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, -4691); + sljit_emit_op2(compiler, SLJIT_LSHR32, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_R0, 0); + /* buf[14] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 14, shift_reg, 0); + sljit_emit_return_void(compiler); code.code = sljit_generate_code(compiler); @@ -810,6 +893,8 @@ static void test9(void) FAILED(buf[10] != 32, "test9 case 11 failed\n"); FAILED(buf[11] != 0x4ae37da9, "test9 case 12 failed\n"); FAILED(buf[12] != 0x63f65c, "test9 case 13 failed\n"); + FAILED(buf[13] != -3062, "test9 case 14 failed\n"); + FAILED(buf[14] != -4691, "test9 case 15 failed\n"); sljit_free_code(code.code, NULL); successful_tests++; @@ -837,23 +922,30 @@ static void test10(void) sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 1, 0, 0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 5); sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); + /* buf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 7); sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_R0, 0, SLJIT_R2, 0, SLJIT_IMM, 8); + /* buf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0); sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_R0, 0, SLJIT_IMM, -3, SLJIT_IMM, -4); + /* buf[2] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -2); + /* buf[3] */ sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_sw) / 2); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&buf[3]); + /* buf[4] */ sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 1, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 1, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 1); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 9); sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R0, 0); + /* buf[5] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 5, SLJIT_R0, 0); #if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 3); sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0x123456789)); + /* buf[6] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 6, SLJIT_R0, 0); #endif sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 11, SLJIT_IMM, 10); @@ -915,6 +1007,7 @@ static void test11(void) SLJIT_ASSERT(!sljit_alloc_memory(compiler, 0)); SLJIT_ASSERT(!sljit_alloc_memory(compiler, 16 * sizeof(sljit_sw) + 1)); + /* buf[0] */ const1 = sljit_emit_const(compiler, SLJIT_MEM0(), (sljit_sw)&buf[0], -0x81b9); value = sljit_alloc_memory(compiler, 16 * sizeof(sljit_sw)); @@ -924,8 +1017,10 @@ static void test11(void) memset(value, 255, 16 * sizeof(sljit_sw)); } + /* buf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2); const2 = sljit_emit_const(compiler, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_WORD_SHIFT - 1, -65535); + /* buf[2] */ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf[0] + 2 * (sljit_sw)sizeof(sljit_sw) - 2); const3 = sljit_emit_const(compiler, SLJIT_MEM1(SLJIT_R0), 0, word_value1); @@ -936,6 +1031,7 @@ static void test11(void) memset(value, 255, 16); } + /* Return vaue */ const4 = sljit_emit_const(compiler, SLJIT_RETURN_REG, 0, (sljit_sw)0xf7afcdb7); sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); @@ -954,9 +1050,13 @@ static void test11(void) FAILED(buf[1] != -65535, "test11 case 3 failed\n"); FAILED(buf[2] != word_value1, "test11 case 4 failed\n"); + /* buf[0] */ sljit_set_const(const1_addr, -1, executable_offset); + /* buf[1] */ sljit_set_const(const2_addr, word_value2, executable_offset); + /* buf[2] */ sljit_set_const(const3_addr, (sljit_sw)0xbab0fea1, executable_offset); + /* Return vaue */ sljit_set_const(const4_addr, -60089, executable_offset); FAILED(code.func1((sljit_sw)&buf) != -60089, "test11 case 5 failed\n"); @@ -1061,7 +1161,7 @@ static void test13(void) { /* Test fpu monadic functions. */ executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); + struct sljit_compiler* compiler; sljit_f64 buf[7]; sljit_sw buf2[6]; @@ -1072,12 +1172,12 @@ static void test13(void) if (verbose) printf("no fpu available, test13 skipped\n"); successful_tests++; - if (compiler) - sljit_free_compiler(compiler); return; } + compiler = sljit_create_compiler(NULL, NULL); FAILED(!compiler, "cannot create compiler\n"); + buf[0] = 7.75; buf[1] = -4.5; buf[2] = 0.0; @@ -1094,30 +1194,41 @@ static void test13(void) buf2[5] = 10; sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, P, P), 3, 2, 6, 0, 0); + /* buf[2] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM0(), (sljit_sw)&buf[2], SLJIT_MEM0(), (sljit_sw)&buf[1]); + /* buf[3] */ sljit_emit_fop1(compiler, SLJIT_ABS_F64, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_f64), SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64)); + /* buf[4] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM0(), (sljit_sw)&buf[0]); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2 * sizeof(sljit_f64)); sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 0); sljit_emit_fop1(compiler, SLJIT_NEG_F64, SLJIT_FR2, 0, SLJIT_FR0, 0); sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR3, 0, SLJIT_FR2, 0); sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM0(), (sljit_sw)&buf[4], SLJIT_FR3, 0); + /* buf[5] */ sljit_emit_fop1(compiler, SLJIT_ABS_F64, SLJIT_FR4, 0, SLJIT_FR1, 0); sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_f64), SLJIT_FR4, 0); + /* buf[6] */ sljit_emit_fop1(compiler, SLJIT_NEG_F64, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_f64), SLJIT_FR4, 0); + /* buf2[0] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR5, 0, SLJIT_MEM1(SLJIT_S0), 0); sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_GREATER, SLJIT_FR5, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64)); sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_F_GREATER); + /* buf2[1] */ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_GREATER, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64), SLJIT_FR5, 0); sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_sw), SLJIT_F_GREATER); + /* buf2[2] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_FR5, 0); sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_EQUAL, SLJIT_FR1, 0, SLJIT_FR1, 0); sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_sw), SLJIT_F_EQUAL); + /* buf2[3] */ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_LESS, SLJIT_FR1, 0, SLJIT_FR1, 0); sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_sw), SLJIT_F_LESS); + /* buf2[4] */ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_EQUAL, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64)); sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_sw), SLJIT_F_EQUAL); + /* buf2[5] */ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_NOT_EQUAL, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64)); sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_sw), SLJIT_F_NOT_EQUAL); @@ -1149,7 +1260,7 @@ static void test14(void) { /* Test fpu diadic functions. */ executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); + struct sljit_compiler* compiler; sljit_f64 buf[15]; if (verbose) @@ -1159,10 +1270,12 @@ static void test14(void) if (verbose) printf("no fpu available, test14 skipped\n"); successful_tests++; - if (compiler) - sljit_free_compiler(compiler); return; } + + compiler = sljit_create_compiler(NULL, NULL); + FAILED(!compiler, "cannot create compiler\n"); + buf[0] = 7.25; buf[1] = 3.5; buf[2] = 1.75; @@ -1179,45 +1292,56 @@ static void test14(void) buf[13] = 4.0; buf[14] = 0.0; - FAILED(!compiler, "cannot create compiler\n"); sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 3, 1, 6, 0, 0); /* ADD */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_f64)); sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64)); sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 2); + /* buf[3] */ sljit_emit_fop2(compiler, SLJIT_ADD_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 3, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 0, SLJIT_MEM1(SLJIT_S0), 0); sljit_emit_fop2(compiler, SLJIT_ADD_F64, SLJIT_FR0, 0, SLJIT_FR0, 0, SLJIT_FR1, 0); sljit_emit_fop2(compiler, SLJIT_ADD_F64, SLJIT_FR1, 0, SLJIT_FR0, 0, SLJIT_FR1, 0); + /* buf[4] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 4, SLJIT_FR0, 0); + /* buf[5] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 5, SLJIT_FR1, 0); /* SUB */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), 0); sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR3, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 2); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 2); + /* buf[6] */ sljit_emit_fop2(compiler, SLJIT_SUB_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 6, SLJIT_FR3, 0, SLJIT_MEM2(SLJIT_S0, SLJIT_R1), SLJIT_F64_SHIFT); sljit_emit_fop2(compiler, SLJIT_SUB_F64, SLJIT_FR2, 0, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 2); sljit_emit_fop2(compiler, SLJIT_SUB_F64, SLJIT_FR3, 0, SLJIT_FR2, 0, SLJIT_FR3, 0); + /* buf[7] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 7, SLJIT_FR2, 0); + /* buf[8] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 8, SLJIT_FR3, 0); /* MUL */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 1); + /* buf[9] */ sljit_emit_fop2(compiler, SLJIT_MUL_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 9, SLJIT_MEM2(SLJIT_S0, SLJIT_R1), SLJIT_F64_SHIFT, SLJIT_FR1, 0); sljit_emit_fop2(compiler, SLJIT_MUL_F64, SLJIT_FR1, 0, SLJIT_FR1, 0, SLJIT_FR2, 0); sljit_emit_fop2(compiler, SLJIT_MUL_F64, SLJIT_FR5, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 2, SLJIT_FR2, 0); + /* buf[10] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 10, SLJIT_FR1, 0); + /* buf[11] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 11, SLJIT_FR5, 0); /* DIV */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR5, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 12); sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 13); sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR4, 0, SLJIT_FR5, 0); + /* buf[12] */ sljit_emit_fop2(compiler, SLJIT_DIV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 12, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 12, SLJIT_FR1, 0); sljit_emit_fop2(compiler, SLJIT_DIV_F64, SLJIT_FR5, 0, SLJIT_FR5, 0, SLJIT_FR1, 0); sljit_emit_fop2(compiler, SLJIT_DIV_F64, SLJIT_FR4, 0, SLJIT_FR1, 0, SLJIT_FR4, 0); + /* buf[13] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 13, SLJIT_FR5, 0); + /* buf[14] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 14, SLJIT_FR4, 0); sljit_emit_return_void(compiler); @@ -1249,13 +1373,18 @@ static sljit_sw func(sljit_sw a, sljit_sw b, sljit_sw c) return a + b + c + 5; } +static sljit_sw func4(sljit_sw a, sljit_sw b, sljit_sw c, sljit_sw d) +{ + return func(a, b, c) + d; +} + static void test15(void) { /* Test function call. */ executable_code code; struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); struct sljit_jump* jump = NULL; - sljit_sw buf[7]; + sljit_sw buf[9]; if (verbose) printf("Run test15\n"); @@ -1267,16 +1396,20 @@ static void test15(void) buf[3] = 0; buf[4] = 0; buf[5] = 0; - buf[6] = SLJIT_FUNC_ADDR(func); + buf[6] = 0; + buf[7] = 0; + buf[8] = SLJIT_FUNC_ADDR(func); - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 4, 1, 0, 0, 0); + sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 4, 2, 0, 0, 0); + /* buf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 5); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 7); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -3); sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(W, W, W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(func)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_RETURN_REG, 0); + /* buf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -5); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -10); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 2); @@ -1284,24 +1417,28 @@ static void test15(void) sljit_set_target(jump, (sljit_uw)-1); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_RETURN_REG, 0); + /* buf[2] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(func)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 40); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -3); sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(W, W, W, W), SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_RETURN_REG, 0); + /* buf[3] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -60); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(func)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -30); sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(W, W, W, W), SLJIT_R1, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_RETURN_REG, 0); + /* buf[4] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 10); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 16); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(func)); sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(W, W, W, W), SLJIT_R2, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_RETURN_REG, 0); + /* buf[5] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 100); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 110); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 120); @@ -1309,11 +1446,29 @@ static void test15(void) sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(W, W, W, W), SLJIT_R3, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_RETURN_REG, 0); + /* buf[6] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 2); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 3); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(func)); + sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(W, W, W, W), SLJIT_S1, 0); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_RETURN_REG, 0); + + /* buf[7] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 2); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 3); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -6); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(func4)); + sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W), SLJIT_S1, 0); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_RETURN_REG, 0); + + /* buf[8] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -10); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -16); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 6); - sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(W, W, W, W), SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_RETURN_REG, 0); + sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(W, W, W, W), SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw)); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_RETURN_REG, 0); sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); @@ -1329,7 +1484,9 @@ static void test15(void) FAILED(buf[3] != SLJIT_FUNC_ADDR(func) - 85, "test15 case 5 failed\n"); FAILED(buf[4] != SLJIT_FUNC_ADDR(func) + 31, "test15 case 6 failed\n"); FAILED(buf[5] != 335, "test15 case 7 failed\n"); - FAILED(buf[6] != -15, "test15 case 8 failed\n"); + FAILED(buf[6] != 11, "test15 case 8 failed\n"); + FAILED(buf[7] != 5, "test15 case 9 failed\n"); + FAILED(buf[8] != -15, "test15 case 10 failed\n"); sljit_free_code(code.code, NULL); successful_tests++; @@ -1418,11 +1575,12 @@ static void test17(void) sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 3, 1, 0, 0, 0); for (i = 0; i <= 0xfff; i++) { - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0x81818000 | i); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0x81818000 | i); if ((i & 0x3ff) == 0) + /* buf[0-3] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), (i >> 10) * (sljit_sw)sizeof(sljit_sw), SLJIT_R0, 0); } + /* buf[4] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R0, 0); sljit_emit_return_void(compiler); @@ -1471,42 +1629,51 @@ static void test18(void) sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 3, 2, 0, 0, 0); #if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) + /* buf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, SLJIT_W(0x1122334455667788)); + /* buf[1] */ sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_IMM, SLJIT_W(0x1122334455667788)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(1000000000000)); + /* buf[2] */ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(1000000000000)); + /* buf[3] */ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_IMM, SLJIT_W(5000000000000), SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0x1108080808)); + /* buf[4] */ sljit_emit_op2(compiler, SLJIT_ADD32, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 4, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0x1120202020)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x1108080808)); sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x1120202020)); sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_ZERO); + /* buf[5] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 5, SLJIT_S1, 0); sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_R0, 0); sljit_emit_op2u(compiler, SLJIT_AND32 | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x1120202020)); + /* buf[6] */ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 6, SLJIT_ZERO); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x1108080808)); sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x2208080808)); + /* buf[7] */ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 7, SLJIT_LESS); sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_R0, 0); sljit_emit_op2u(compiler, SLJIT_AND32 | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x1104040404)); + /* buf[8] */ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 8, SLJIT_NOT_ZERO); sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 4); + /* buf[9] */ sljit_emit_op2(compiler, SLJIT_SHL32, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 9, SLJIT_IMM, SLJIT_W(0xffff0000), SLJIT_R0, 0); - + /* buf[10] */ sljit_emit_op2(compiler, SLJIT_MUL32, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 10, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 10, SLJIT_IMM, -1); -#else - /* 32 bit operations. */ - +#else /* !SLJIT_64BIT_ARCHITECTURE */ + /* buf[0] */ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, 0x11223344); + /* buf[1] */ sljit_emit_op2(compiler, SLJIT_ADD32, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_IMM, 0x44332211); - -#endif +#endif /* SLJIT_64BIT_ARCHITECTURE */ sljit_emit_return_void(compiler); @@ -1519,16 +1686,16 @@ static void test18(void) FAILED(buf[0] != SLJIT_W(0x1122334455667788), "test18 case 1 failed\n"); #if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN) FAILED(buf[1] != 0x55667788, "test18 case 2 failed\n"); -#else +#else /* !SLJIT_LITTLE_ENDIAN */ FAILED(buf[1] != SLJIT_W(0x5566778800000000), "test18 case 2 failed\n"); -#endif +#endif /* SLJIT_LITTLE_ENDIAN */ FAILED(buf[2] != SLJIT_W(2000000000000), "test18 case 3 failed\n"); FAILED(buf[3] != SLJIT_W(4000000000000), "test18 case 4 failed\n"); #if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN) FAILED(buf[4] != 0x28282828, "test18 case 5 failed\n"); -#else +#else /* !SLJIT_LITTLE_ENDIAN */ FAILED(buf[4] != SLJIT_W(0x2828282800000000), "test18 case 5 failed\n"); -#endif +#endif /* SLJIT_LITTLE_ENDIAN */ FAILED(buf[5] != 0, "test18 case 6 failed\n"); FAILED(buf[6] != 1, "test18 case 7 failed\n"); FAILED(buf[7] != 1, "test18 case 8 failed\n"); @@ -1536,14 +1703,14 @@ static void test18(void) #if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN) FAILED(buf[9] != (sljit_sw)0xfff00000, "test18 case 10 failed\n"); FAILED(buf[10] != (sljit_sw)0xffffffff, "test18 case 11 failed\n"); -#else +#else /* !SLJIT_LITTLE_ENDIAN */ FAILED(buf[9] != (sljit_sw)SLJIT_W(0xfff0000000000000), "test18 case 10 failed\n"); FAILED(buf[10] != (sljit_sw)SLJIT_W(0xffffffff00000000), "test18 case 11 failed\n"); -#endif -#else +#endif /* SLJIT_LITTLE_ENDIAN */ +#else /* !SLJIT_64BIT_ARCHITECTURE */ FAILED(buf[0] != 0x11223344, "test18 case 1 failed\n"); FAILED(buf[1] != 0x44332211, "test18 case 2 failed\n"); -#endif +#endif /* SLJIT_64BIT_ARCHITECTURE */ sljit_free_code(code.code, NULL); successful_tests++; @@ -1570,14 +1737,21 @@ static void test19(void) buf[7] = 0; sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 3, 1, 0, 0, 0); + /* buf[0] */ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw)); + /* buf[2] */ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM0(), (sljit_sw)&buf[2], SLJIT_MEM0(), (sljit_sw)&buf[1], SLJIT_MEM0(), (sljit_sw)&buf[0]); + /* buf[3] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, sizeof(sljit_sw)); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_MEM1(SLJIT_R0), (sljit_sw)&buf[0], SLJIT_MEM1(SLJIT_R1), (sljit_sw)&buf[0]); + /* buf[4] */ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 4, SLJIT_MEM0(), (sljit_sw)&buf[0], SLJIT_IMM, 2); + /* buf[5] */ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 5, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_R0), (sljit_sw)&buf[0] + 4 * (sljit_sw)sizeof(sljit_sw)); + /* buf[7] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 7, SLJIT_IMM, 10); + /* buf[6] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 7); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_R1), (sljit_sw)&buf[5], SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_MEM1(SLJIT_R1), (sljit_sw)&buf[5]); @@ -1627,18 +1801,24 @@ static void test20(void) buf[5] = -12345; sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 5, 5, 0, 0, 4 * sizeof(sljit_sw)); + /* buf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_uw), SLJIT_MEM1(SLJIT_S0), 0); + /* buf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_uw)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -1); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, -1); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, -1); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S4, 0, SLJIT_IMM, -1); + /* buf[2] */ sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_uw), SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_uw)); + /* buf[3] */ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_uw), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_uw), SLJIT_MEM1(SLJIT_SP), 0); sljit_get_local_base(compiler, SLJIT_R0, 0, -offset_value); sljit_get_local_base(compiler, SLJIT_MEM1(SLJIT_S0), 0, -0x1234); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S0), 0); + /* buf[4] */ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_uw), SLJIT_MEM1(SLJIT_R0), offset_value, SLJIT_MEM1(SLJIT_R1), 0x1234 + sizeof(sljit_sw)); + /* buf[5] */ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_uw)); /* Dummy last instructions. */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 23); @@ -1706,6 +1886,7 @@ static void test21(void) sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 2, 0, 0, 2 * sizeof(sljit_sw)); + /* Return value */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, 10); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), 0, SLJIT_MEM1(SLJIT_SP), 0); @@ -1727,7 +1908,9 @@ static void test21(void) sljit_set_context(compiler, 0, 1, 3, 2, 0, 0, 2 * sizeof(sljit_sw)); sljit_emit_op0(compiler, SLJIT_ENDBR); + /* buf[2] */ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), 0); + /* buf[3] */ sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_SP), 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw)); @@ -1782,39 +1965,55 @@ static void test22(void) sljit_emit_enter(compiler, 0, SLJIT_ARGS3(VOID, P, P, P), 3, 3, 0, 0, 0); + /* sbuf[0] */ sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_IMM, -13); + /* sbuf[1] */ sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s16), SLJIT_IMM, 0x1234); sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_s16)); + /* buf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, 2 * sizeof(sljit_s16)); + /* sbuf[3] */ sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s16), SLJIT_MEM1(SLJIT_S1), -(sljit_sw)sizeof(sljit_s16)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0xff0000 + 8000); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 2); + /* sbuf[4] */ sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_MEM2(SLJIT_S1, SLJIT_R1), 1, SLJIT_R0, 0); sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R2, 0, SLJIT_S1, 0, SLJIT_IMM, 0x1234 - 3 * sizeof(sljit_s16)); + /* sbuf[5] */ sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_MEM1(SLJIT_R2), 0x1234, SLJIT_IMM, -9317); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S1, 0, SLJIT_IMM, 0x1234 + 4 * sizeof(sljit_s16)); + /* sbuf[6] */ sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_MEM1(SLJIT_R2), -0x1234, SLJIT_IMM, -9317); sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R2, 0, SLJIT_S1, 0, SLJIT_IMM, 0x12348 - 5 * sizeof(sljit_s16)); + /* sbuf[7] */ sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_MEM1(SLJIT_R2), 0x12348, SLJIT_IMM, -8888); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S1, 0, SLJIT_IMM, 0x12348 + 6 * sizeof(sljit_s16)); + /* sbuf[8] */ sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_MEM1(SLJIT_R2), -0x12348, SLJIT_IMM, -8888); + /* bbuf[0] */ sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_MEM1(SLJIT_S2), 0, SLJIT_IMM, -45); + /* sbuf[1] */ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_s8), SLJIT_IMM, 0x12); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 4 * sizeof(sljit_s8)); sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S2), 2 * sizeof(sljit_s8)); sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_S1, 0, SLJIT_R1, 0); sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_S1, 0, SLJIT_S1, 0); sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_R2, 0, SLJIT_S1, 0); + /* buf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R2, 0); + /* bbuf[3] */ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_S2), 3 * sizeof(sljit_s8), SLJIT_S1, 0); + /* bbuf[4] */ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM2(SLJIT_S2, SLJIT_R0), 0, SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1); sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_R0, 0, SLJIT_IMM, 0); + /* buf[2] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); + /* buf[3] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R0, 0); sljit_emit_return_void(compiler); @@ -1886,40 +2085,54 @@ static void test23(void) ibuf[4] = 658923; sljit_emit_enter(compiler, 0, SLJIT_ARGS2(W, P, P), 3, 3, 0, 0, 0); + /* ibuf[0] */ sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_IMM, 34567); + /* ibuf[4] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 4); sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), 0, SLJIT_IMM, -7654); + /* buf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, garbage); sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_s32)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); + /* buf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, garbage); sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_s32)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0); + /* buf[2] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, garbage); sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_s32)); sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R0, 0, SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R0, 0); + /* buf[3] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x0f00f00); sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 0x7777); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0x7777 + 3 * sizeof(sljit_sw), SLJIT_R0, 0); + /* buf[4] */ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 0x7777); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), -0x7777 + 4 * (sljit_sw)sizeof(sljit_sw), SLJIT_R0, 0); + /* buf[5] */ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 5 * sizeof(sljit_sw)); sljit_emit_op2(compiler, SLJIT_LSHR, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM2(SLJIT_R1, SLJIT_R1), 0, SLJIT_IMM, 16); + /* buf[7] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); sljit_emit_op2(compiler, SLJIT_OR, SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 1, SLJIT_IMM, 64, SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 1); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)&buf[7], SLJIT_IMM, 0x123456); + /* buf[6] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), (sljit_sw)&buf[6], SLJIT_MEM0(), (sljit_sw)&buf[7]); + /* buf[7] */ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 5 * sizeof(sljit_sw)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(sljit_sw), SLJIT_R1, 0); + /* buf[8] */ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S0, 0, SLJIT_IMM, 7 * sizeof(sljit_sw)); sljit_emit_op2(compiler, SLJIT_LSHR, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM2(SLJIT_R2, SLJIT_R2), 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf[8] - 0x12340); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0x12340, SLJIT_R2, 0); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_R0), 0x12340, SLJIT_MEM1(SLJIT_R2), 3 * sizeof(sljit_sw), SLJIT_IMM, 6); + /* ibuf[4] */ sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_s32), SLJIT_IMM, 0x12345678); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0x2bd700 | 243); sljit_emit_return(compiler, SLJIT_MOV_S8, SLJIT_R1, 0); @@ -1998,47 +2211,62 @@ static void test24(void) sljit_emit_enter(compiler, 0, SLJIT_ARGS3(VOID, P, P, P), 3, 3, 0, 0, 0); /* Nothing should be updated. */ + /* sbuf[1] */ sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_MEM0(), (sljit_sw)&sbuf[1], SLJIT_MEM0(), (sljit_sw)&sbuf[0]); + /* bbuf[1] */ sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_MEM0(), (sljit_sw)&bbuf[1], SLJIT_MEM0(), (sljit_sw)&bbuf[0]); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2); + /* sbuf[2] */ sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), 1, SLJIT_MEM0(), (sljit_sw)&sbuf[3]); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf[0]); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, sizeof(sljit_sw)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 2); + /* buf[2] */ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM2(SLJIT_R0, SLJIT_R2), SLJIT_WORD_SHIFT, SLJIT_MEM0(), (sljit_sw)&buf[0], SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_s8)); + /* bbuf[2] */ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_R0), (sljit_sw)&bbuf[1], SLJIT_MEM1(SLJIT_R0), (sljit_sw)&bbuf[2]); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, sizeof(sljit_s16)); + /* sbuf[4] */ sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_MEM1(SLJIT_R1), (sljit_sw)&sbuf[3], SLJIT_R1, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 3); + /* buf[3] */ sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_WORD_SHIFT); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 4); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_S0, 0); + /* buf[4] */ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_WORD_SHIFT); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 9 * sizeof(sljit_sw)); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 4 * sizeof(sljit_sw)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -(4 << SLJIT_WORD_SHIFT)); + /* buf[5] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM2(SLJIT_R0, SLJIT_R2), 0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf - 0x7fff8000 + 6 * (sljit_sw)sizeof(sljit_sw)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 952467); + /* buf[6] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0x7fff8000, SLJIT_R1, 0); + /* buf[7] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0x7fff8000 + sizeof(sljit_sw), SLJIT_MEM1(SLJIT_R0), 0x7fff8000); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf + 0x7fff7fff + 6 * (sljit_sw)sizeof(sljit_sw)); + /* buf[8] */ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_R0), -0x7fff7fff + 2 * (sljit_sw)sizeof(sljit_sw), SLJIT_MEM1(SLJIT_R0), -0x7fff7fff + (sljit_sw)sizeof(sljit_sw), SLJIT_MEM1(SLJIT_R0), -0x7fff7fff); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&bbuf - 0x7fff7ffe + 3 * (sljit_sw)sizeof(sljit_s8)); + /* bbuf[4] */ sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_MEM1(SLJIT_R0), 0x7fff7fff, SLJIT_MEM1(SLJIT_R0), 0x7fff7ffe); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&bbuf + 0x7fff7fff + 5 * (sljit_sw)sizeof(sljit_s8)); + /* bbuf[5] */ sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_MEM1(SLJIT_R0), -0x7fff7fff, SLJIT_MEM1(SLJIT_R0), -0x7fff8000); #if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&bbuf - SLJIT_W(0x123456123456)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&bbuf - SLJIT_W(0x123456123456)); + /* bbuf[6] */ sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_MEM1(SLJIT_R0), SLJIT_W(0x123456123456) + 6 * sizeof(sljit_s8), SLJIT_MEM1(SLJIT_R1), SLJIT_W(0x123456123456)); -#endif +#endif /* SLJIT_64BIT_ARCHITECTURE */ sljit_emit_return_void(compiler); @@ -2138,7 +2366,7 @@ static void test25(void) FAILED(buf[13] != SLJIT_W(0x07fff00ffff00000), "test25 case 14 failed\n"); sljit_free_code(code.code, NULL); -#endif +#endif /* SLJIT_64BIT_ARCHITECTURE */ successful_tests++; } @@ -2176,22 +2404,29 @@ static void test26(void) sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, 3); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, 1); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), -3); + /* ibuf[1] */ sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32) - 1, SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), -1); + /* buf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) - 3, SLJIT_R0, 0); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 100); + /* buf[2] */ sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_MEM1(SLJIT_R0), (sljit_sw)sizeof(sljit_sw) * 2 - 103, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2 - 3, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3 - 3); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S1, 0, SLJIT_IMM, 100); + /* ibuf[2] */ sljit_emit_op2(compiler, SLJIT_MUL32, SLJIT_MEM1(SLJIT_R0), (sljit_sw)sizeof(sljit_s32) * 2 - 101, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32) * 2 - 1, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32) * 3 - 1); if (sljit_has_cpu_feature(SLJIT_HAS_FPU)) { sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S2, 0, SLJIT_S2, 0, SLJIT_IMM, 3); + /* dbuf[1] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_f64) - 3, SLJIT_MEM1(SLJIT_S2), -3); + /* dbuf[2] */ sljit_emit_fop2(compiler, SLJIT_ADD_F64, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_f64) * 2 - 3, SLJIT_MEM1(SLJIT_S2), -3, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_f64) - 3); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S2, 0, SLJIT_IMM, 2); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sizeof(sljit_f64) * 3 - 4) >> 1); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S2, 0, SLJIT_IMM, 1); + /* dbuf[3] */ sljit_emit_fop2(compiler, SLJIT_DIV_F64, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64) * 3 - 5, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_f64) * 2 - 3, SLJIT_MEM2(SLJIT_R2, SLJIT_R1), 1); } @@ -2254,6 +2489,7 @@ static void test27(void) /* 3 arguments passed, 3 arguments used. */ sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 4, 3, 0, 0, 0); + /* buf[0] */ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, 1); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x1001); @@ -2264,6 +2500,7 @@ static void test27(void) sljit_emit_op0(compiler, SLJIT_ENDBR); /* ENDBR should keep the flags. */ sljit_emit_op0(compiler, SLJIT_NOP); /* Nop should keep the flags. */ SET_NEXT_BYTE(SLJIT_GREATER); + /* buf[2] */ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_R1, 0); SET_NEXT_BYTE(SLJIT_LESS); sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_R0, 0); @@ -2272,6 +2509,7 @@ static void test27(void) sljit_emit_op0(compiler, SLJIT_ENDBR); /* ENDBR should keep the flags. */ sljit_emit_op0(compiler, SLJIT_NOP); /* Nop should keep the flags. */ SET_NEXT_BYTE(SLJIT_GREATER); + /* buf[4] */ sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_R1, 0); SET_NEXT_BYTE(SLJIT_LESS); @@ -2281,37 +2519,47 @@ static void test27(void) /* 0x100000010 on 64 bit machines, 0x10 on 32 bit machines. */ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_R0, 0, SLJIT_IMM, 0x80); SET_NEXT_BYTE(SLJIT_GREATER); + /* buf[6] */ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_IMM, 0x80); SET_NEXT_BYTE(SLJIT_LESS); sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_R0, 0); sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_GREATER, SLJIT_R0, 0, SLJIT_IMM, 0x80); SET_NEXT_BYTE(SLJIT_GREATER); + /* buf[7] */ sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_IMM, 0x80); SET_NEXT_BYTE(SLJIT_LESS); + /* buf[8] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1); /* 0xff..ff on all machines. */ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 1); SET_NEXT_BYTE(SLJIT_LESS_EQUAL); + /* buf[9] */ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 1); SET_NEXT_BYTE(SLJIT_GREATER_EQUAL); + /* buf[10] */ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER, SLJIT_R2, 0, SLJIT_R1, 0, SLJIT_IMM, -1); SET_NEXT_BYTE(SLJIT_SIG_GREATER); + /* buf[12] */ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, -1); SET_NEXT_BYTE(SLJIT_SIG_LESS); sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_R1, 0, SLJIT_R0, 0); SET_NEXT_BYTE(SLJIT_EQUAL); + /* buf[14] */ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_R0, 0); SET_NEXT_BYTE(SLJIT_NOT_EQUAL); sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_IMM, -2); SET_NEXT_BYTE(SLJIT_OVERFLOW); + /* buf[16] */ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_IMM, -2); SET_NEXT_BYTE(SLJIT_NOT_OVERFLOW); sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_IMM, -2); SET_NEXT_BYTE(SLJIT_GREATER_EQUAL); + /* buf[17] */ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_IMM, -2); SET_NEXT_BYTE(SLJIT_LESS_EQUAL); + /* buf[20] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)((sljit_uw)1 << ((8 * sizeof(sljit_uw)) - 1))); sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_IMM, 1); SET_NEXT_BYTE(SLJIT_SIG_LESS); @@ -2320,9 +2568,11 @@ static void test27(void) sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_IMM, 1); sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER_EQUAL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, -2); SET_NEXT_BYTE(SLJIT_SIG_GREATER_EQUAL); + /* buf[21] */ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 2); SET_NEXT_BYTE(SLJIT_SIG_GREATER); + /* buf[22] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0x80000000); sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 16); sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 16); @@ -2330,15 +2580,18 @@ static void test27(void) sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)0xffffffff); sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_R1, 0); SET_NEXT_BYTE(SLJIT_OVERFLOW); + /* buf[24] */ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_R1, 0); SET_NEXT_BYTE(SLJIT_NOT_OVERFLOW); sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R1, 0, SLJIT_R1, 0); sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_R1, 0); SET_NEXT_BYTE(SLJIT_OVERFLOW); + /* buf[25] */ sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_R1, 0); SET_NEXT_BYTE(SLJIT_NOT_OVERFLOW); + /* buf[26] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_IMM, 1); sljit_emit_op2u(compiler, SLJIT_SUBC | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_IMM, 0); @@ -2346,6 +2599,7 @@ static void test27(void) sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_S0), 1, SLJIT_R0, 0); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, 1); + /* buf[27] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1); sljit_emit_op2u(compiler, SLJIT_ADD | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_IMM, 1); sljit_emit_op2u(compiler, SLJIT_ADDC | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_IMM, 1); @@ -2353,10 +2607,12 @@ static void test27(void) sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_S0), 1, SLJIT_R0, 0); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, 1); + /* buf[28] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1); sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, (8 * sizeof(sljit_sw)) - 1); sljit_emit_op2u(compiler, SLJIT_ADD | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, 0); SET_NEXT_BYTE(SLJIT_EQUAL); + /* buf[34] */ sljit_emit_op2u(compiler, SLJIT_ADD | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_R0, 0); SET_NEXT_BYTE(SLJIT_EQUAL); @@ -2380,16 +2636,20 @@ static void test27(void) sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0); sljit_emit_op2(compiler, SLJIT_SUBC | SLJIT_SET_CARRY, SLJIT_R2, 0, SLJIT_IMM, 1, SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_S0), 1, SLJIT_R2, 0); + /* buf[35] */ sljit_emit_op2u(compiler, SLJIT_SUBC | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R1, 0); sljit_emit_op2(compiler, SLJIT_SUBC, SLJIT_R2, 0, SLJIT_IMM, 1, SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_S0), 2, SLJIT_R2, 0); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, 2); + /* buf[36] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -34); sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_IMM, 0x1234); SET_NEXT_BYTE(SLJIT_LESS); + /* buf[37] */ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_R0, 0, SLJIT_IMM, 0x1234); SET_NEXT_BYTE(SLJIT_SIG_LESS); + /* buf[38] */ #if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x12300000000) - 43); #else @@ -2398,6 +2658,7 @@ static void test27(void) sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, -96); sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_R1, 0); SET_NEXT_BYTE(SLJIT_LESS); + /* buf[39] */ sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_SIG_GREATER, SLJIT_R0, 0, SLJIT_R1, 0); SET_NEXT_BYTE(SLJIT_SIG_GREATER); @@ -2490,12 +2751,15 @@ static void test28(void) sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -234); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw)); sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_S3, 0, SLJIT_R3, 0, SLJIT_R4, 0); + /* buf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_S3, 0); sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_S3, 0, SLJIT_IMM, 0); sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_NOT_ZERO); + /* buf[2] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_S3, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S4, 0, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw)); sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_S4, 0, SLJIT_S4, 0, SLJIT_R4, 0); + /* buf[3] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_S4, 0); const1 = sljit_emit_const(compiler, SLJIT_S3, 0, 0); @@ -2503,6 +2767,7 @@ static void test28(void) sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_S3, 0, SLJIT_S3, 0, SLJIT_IMM, 100); label = sljit_emit_label(compiler); sljit_emit_op0(compiler, SLJIT_ENDBR); + /* buf[4] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_S3, 0); sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R4, 0); @@ -2569,7 +2834,7 @@ static void test29(void) sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_uw), SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R4, 0, SLJIT_IMM, SLJIT_W(0xcef97a70b5)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_uw), SLJIT_R4, 0); -#endif +#endif /* SLJIT_64BIT_ARCHITECTURE */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -187); sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_R0, 0, SLJIT_R1, 0); @@ -2610,7 +2875,7 @@ static void test29(void) sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, SLJIT_W(0xcef97a70b5)); sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R4, 0, SLJIT_R3, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 23 * sizeof(sljit_uw), SLJIT_R4, 0); -#endif +#endif /* SLJIT_64BIT_ARCHITECTURE */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, 0x9faa5); sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_S2, 0, SLJIT_S2, 0); @@ -2637,7 +2902,7 @@ static void test29(void) FAILED(buf[9] != SLJIT_W(-1938520854), "test29 case 10 failed\n"); FAILED(buf[10] != SLJIT_W(3236202668), "test29 case 11 failed\n"); FAILED(buf[11] != SLJIT_W(0xf97a70b5), "test29 case 12 failed\n"); -#endif +#endif /* SLJIT_64BIT_ARCHITECTURE */ FAILED(buf[12] != 69, "test29 case 13 failed\n"); FAILED(buf[13] != -93, "test29 case 14 failed\n"); @@ -2653,7 +2918,7 @@ static void test29(void) FAILED(buf[21] != SLJIT_W(-1938520854), "test29 case 22 failed\n"); FAILED(buf[22] != SLJIT_W(3236202668), "test29 case 23 failed\n"); FAILED(buf[23] != SLJIT_W(0xf97a70b5), "test29 case 24 failed\n"); -#endif +#endif /* SLJIT_64BIT_ARCHITECTURE */ FAILED(buf[24] != -91, "test29 case 25 failed\n"); @@ -2706,6 +2971,7 @@ static void test30(void) sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S1, 0); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S2, 0); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S3, 0); + /* buf[0] */ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0, SLJIT_S4, 0); sljit_emit_return_void(compiler); @@ -2744,37 +3010,47 @@ static void test31(void) FAILED(!compiler, "cannot create compiler\n"); + /* buf[0] */ sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 3, 5, 0, 0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0); sljit_emit_op2u(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_IMM, -45); cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_NOT_OVERFLOW); + /* buf[1] */ sljit_emit_op2u(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_IMM, -45); cond_set(compiler, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_OVERFLOW); + /* buf[2] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, big_word); sljit_emit_op2(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R2, 0, SLJIT_S2, 0, SLJIT_IMM, -2); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 33); /* Should not change flags. */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0); /* Should not change flags. */ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_OVERFLOW); + /* buf[3] */ sljit_emit_op2(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R2, 0, SLJIT_S2, 0, SLJIT_IMM, -2); cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_NOT_OVERFLOW); + /* buf[4] */ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_S3, 0, SLJIT_IMM, 0x3f6b0); sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_S4, 0, SLJIT_IMM, 0x2a783); sljit_emit_op2(compiler, SLJIT_MUL32 | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_S3, 0, SLJIT_S4, 0); cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_OVERFLOW); + /* buf[5] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R1, 0); + /* buf[6] */ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, big_word2); sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R2, 0, SLJIT_R1, 0); sljit_emit_op2(compiler, SLJIT_MUL32 | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 23); cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_OVERFLOW); + /* buf[7] */ sljit_emit_op2u(compiler, SLJIT_MUL32 | SLJIT_SET_OVERFLOW, SLJIT_R2, 0, SLJIT_IMM, -23); cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_NOT_OVERFLOW); + /* buf[8] */ sljit_emit_op2u(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R2, 0, SLJIT_IMM, -23); cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_NOT_OVERFLOW); + /* buf[9] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 67); sljit_emit_op2(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, -23); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_R1, 0); @@ -2811,7 +3087,7 @@ static void test32(void) { /* Floating point set flags. */ executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); + struct sljit_compiler* compiler; sljit_s32 i; sljit_sw buf[16]; @@ -2826,6 +3102,16 @@ static void test32(void) if (verbose) printf("Run test32\n"); + if (!sljit_has_cpu_feature(SLJIT_HAS_FPU)) { + if (verbose) + printf("no fpu available, test32 skipped\n"); + successful_tests++; + return; + } + + compiler = sljit_create_compiler(NULL, NULL); + FAILED(!compiler, "cannot create compiler\n"); + for (i = 0; i < 16; i++) buf[i] = 5; @@ -2837,16 +3123,6 @@ static void test32(void) dbuf[2].value = -13.0; dbuf[3].value = 27.0; - if (!sljit_has_cpu_feature(SLJIT_HAS_FPU)) { - if (verbose) - printf("no fpu available, test32 skipped\n"); - successful_tests++; - if (compiler) - sljit_free_compiler(compiler); - return; - } - - FAILED(!compiler, "cannot create compiler\n"); SLJIT_ASSERT(sizeof(sljit_f64) == 8 && sizeof(sljit_s32) == 4 && sizeof(dbuf[0]) == 8); sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, P, P), 1, 2, 4, 0, 0); @@ -2854,39 +3130,53 @@ static void test32(void) sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S1), 0); sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_UNORDERED, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_f64), SLJIT_FR0, 0); sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_f64)); + /* buf[0] */ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_UNORDERED); sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_ORDERED, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_f64), SLJIT_FR0, 0); + /* buf[1] */ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_ORDERED); sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_f64)); sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_UNORDERED, SLJIT_FR1, 0, SLJIT_FR2, 0); + /* buf[2] */ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_UNORDERED); sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_ORDERED, SLJIT_FR1, 0, SLJIT_FR2, 0); + /* buf[3] */ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_ORDERED); sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_LESS, SLJIT_FR1, 0, SLJIT_FR2, 0); + /* buf[4] */ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_F_LESS); sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_GREATER_EQUAL, SLJIT_FR1, 0, SLJIT_FR2, 0); + /* buf[5] */ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_F_GREATER_EQUAL); sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_GREATER, SLJIT_FR1, 0, SLJIT_FR2, 0); + /* buf[6] */ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_F_GREATER); sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_LESS_EQUAL, SLJIT_FR1, 0, SLJIT_FR2, 0); + /* buf[7] */ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_F_LESS_EQUAL); sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_EQUAL, SLJIT_FR1, 0, SLJIT_FR2, 0); + /* buf[8] */ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_F_EQUAL); sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_NOT_EQUAL, SLJIT_FR1, 0, SLJIT_FR2, 0); + /* buf[9] */ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_F_NOT_EQUAL); sljit_emit_fop2(compiler, SLJIT_ADD_F64, SLJIT_FR3, 0, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f64)); sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_UNORDERED, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_f64)); + /* buf[10] */ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_UNORDERED); sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_EQUAL, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_f64)); + /* buf[11] */ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_F_EQUAL); sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_ORDERED, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f64), SLJIT_FR0, 0); + /* buf[12] */ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_ORDERED); sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_UNORDERED, SLJIT_FR3, 0, SLJIT_FR2, 0); sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), 0); + /* buf[13] */ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_UNORDERED); sljit_emit_return_void(compiler); @@ -2942,22 +3232,27 @@ static void test33(void) sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 3, 3, 0, 0, 0); + /* buf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 20); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 10); sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, SLJIT_R2, 0, SLJIT_R0, 0, SLJIT_R1, 0); sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_ZERO); + /* buf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -10); jump = sljit_emit_jump(compiler, SLJIT_LESS); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_IMM, 11); sljit_set_label(jump, sljit_emit_label(compiler)); + /* buf[2] */ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_SIG_GREATER, SLJIT_R2, 0, SLJIT_R0, 0, SLJIT_R1, 0); sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_SIG_GREATER); + /* buf[3] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_IMM, 45); jump = sljit_emit_jump(compiler, SLJIT_NOT_EQUAL); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_IMM, 55); sljit_set_label(jump, sljit_emit_label(compiler)); + /* buf[4-5] */ #if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)SLJIT_W(0x8000000000000000)); #else @@ -2967,20 +3262,25 @@ static void test33(void) sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_OVERFLOW, SLJIT_R2, 0, SLJIT_R0, 0, SLJIT_R1, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_IMM, 33); jump = sljit_emit_jump(compiler, SLJIT_NOT_OVERFLOW); + /* buf[5] */ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_ZERO); + /* buf[4] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_IMM, 13); sljit_set_label(jump, sljit_emit_label(compiler)); + /* buf[6] */ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0x80000000); sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_R0, 0); sljit_emit_op2(compiler, SLJIT_SUB32 | SLJIT_SET_Z | SLJIT_SET_OVERFLOW, SLJIT_R2, 0, SLJIT_R0, 0, SLJIT_R1, 0); sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 0); sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_NOT_ZERO); + /* buf[7] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_IMM, 78); jump = sljit_emit_jump(compiler, SLJIT_OVERFLOW); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_IMM, 48); sljit_set_label(jump, sljit_emit_label(compiler)); + /* buf[8] */ #if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)SLJIT_W(0x8000000000000000)); #else @@ -2991,6 +3291,7 @@ static void test33(void) sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_IMM, 30); jump = sljit_emit_jump(compiler, SLJIT_NOT_OVERFLOW); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_IMM, 50); + /* buf[9] */ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_ZERO); sljit_set_label(jump, sljit_emit_label(compiler)); @@ -3044,7 +3345,7 @@ static void test34(void) sljit_set_context(compiler, 0, 1, 5, 5, 0, 0, 2 * sizeof(sljit_p)); sljit_emit_op0(compiler, SLJIT_ENDBR); - sljit_emit_fast_enter(compiler, SLJIT_R1, 0); + sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_R1, 0); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 4); sljit_emit_op_src(compiler, SLJIT_FAST_RETURN, SLJIT_R1, 0); @@ -3058,7 +3359,7 @@ static void test34(void) sljit_set_context(compiler, 0, 1, 5, 5, 0, 0, 2 * sizeof(sljit_p)); sljit_emit_op0(compiler, SLJIT_ENDBR); - sljit_emit_fast_enter(compiler, SLJIT_R4, 0); + sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_R4, 0); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 6); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(codeA.code)); sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_R1, 0); @@ -3074,7 +3375,7 @@ static void test34(void) sljit_set_context(compiler, 0, 1, 5, 5, 0, 0, 2 * sizeof(sljit_p)); sljit_emit_op0(compiler, SLJIT_ENDBR); - sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_p)); + sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_p)); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 8); jump = sljit_emit_jump(compiler, SLJIT_FAST_CALL | SLJIT_REWRITABLE_JUMP); sljit_set_target(jump, SLJIT_FUNC_UADDR(codeB.code)); @@ -3090,7 +3391,7 @@ static void test34(void) sljit_set_context(compiler, 0, 1, 5, 5, 0, 0, 2 * sizeof(sljit_p)); sljit_emit_op0(compiler, SLJIT_ENDBR); - sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), 0); + sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_MEM1(SLJIT_SP), 0); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 10); sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM, SLJIT_FUNC_ADDR(codeC.code)); sljit_emit_op_src(compiler, SLJIT_FAST_RETURN, SLJIT_MEM1(SLJIT_SP), 0); @@ -3104,7 +3405,7 @@ static void test34(void) FAILED(!compiler, "cannot create compiler\n"); sljit_set_context(compiler, 0, 1, 5, 5, 0, 0, 2 * sizeof(sljit_p)); - sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_S0), 0); + sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_MEM1(SLJIT_S0), 0); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 12); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_p), SLJIT_IMM, SLJIT_FUNC_ADDR(codeD.code)); sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_p)); @@ -3165,7 +3466,7 @@ static void test35(void) FAILED(!compiler, "cannot create compiler\n"); sljit_set_context(compiler, 0, 0, 2, 2, 0, 0, 0); - sljit_emit_fast_enter(compiler, SLJIT_MEM0(), (sljit_sw)&buf[0]); + sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_MEM0(), (sljit_sw)&buf[0]); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 5); jump = sljit_emit_jump(compiler, SLJIT_FAST_CALL | SLJIT_REWRITABLE_JUMP); @@ -3186,7 +3487,7 @@ static void test35(void) sljit_set_context(compiler, 0, 0, 2, 2, 0, 0, 0); sljit_emit_op0(compiler, SLJIT_ENDBR); - sljit_emit_fast_enter(compiler, SLJIT_R1, 0); + sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_R1, 0); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 7); sljit_emit_op_src(compiler, SLJIT_FAST_RETURN, SLJIT_R1, 0); @@ -3269,16 +3570,24 @@ static void test36(void) sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 13); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 15); + /* buf[0], compare_buf[0-6] */ cmp_test(compiler, SLJIT_EQUAL, SLJIT_IMM, 9, SLJIT_R0, 0); + /* buf[1] */ cmp_test(compiler, SLJIT_EQUAL, SLJIT_R0, 0, SLJIT_R1, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 3); + /* buf[2] */ cmp_test(compiler, SLJIT_EQUAL, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_IMM, -13); + /* buf[3] */ cmp_test(compiler, SLJIT_NOT_EQUAL, SLJIT_IMM, 0, SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); + /* buf[4] */ cmp_test(compiler, SLJIT_NOT_EQUAL | SLJIT_REWRITABLE_JUMP, SLJIT_IMM, 0, SLJIT_R0, 0); + /* buf[5] */ cmp_test(compiler, SLJIT_EQUAL, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), SLJIT_WORD_SHIFT); + /* buf[6] */ cmp_test(compiler, SLJIT_EQUAL | SLJIT_REWRITABLE_JUMP, SLJIT_R0, 0, SLJIT_IMM, 0); + /* buf[7-16], compare_buf[7-16] */ cmp_test(compiler, SLJIT_SIG_LESS, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_IMM, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -8); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0); @@ -3292,6 +3601,7 @@ static void test36(void) cmp_test(compiler, SLJIT_SIG_LESS, SLJIT_IMM, 0, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_sw)); cmp_test(compiler, SLJIT_SIG_LESS | SLJIT_REWRITABLE_JUMP, SLJIT_IMM, 0, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_sw)); + /* buf[17-28], compare_buf[17-28] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 8); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0); cmp_test(compiler, SLJIT_LESS, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_sw)); @@ -3307,6 +3617,7 @@ static void test36(void) cmp_test(compiler, SLJIT_GREATER, SLJIT_R0, 0, SLJIT_R1, 0); cmp_test(compiler, SLJIT_GREATER | SLJIT_REWRITABLE_JUMP, SLJIT_R0, 0, SLJIT_R1, 0); + /* buf[29-39], compare_buf[29-39] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -3); cmp_test(compiler, SLJIT_SIG_LESS, SLJIT_R0, 0, SLJIT_R1, 0); cmp_test(compiler, SLJIT_SIG_GREATER_EQUAL, SLJIT_R0, 0, SLJIT_R1, 0); @@ -3324,20 +3635,22 @@ static void test36(void) sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0xf00000004)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_R1, 0); + /* buf[40-43] */ cmp_test(compiler, SLJIT_LESS | SLJIT_32, SLJIT_R1, 0, SLJIT_IMM, 5); cmp_test(compiler, SLJIT_LESS, SLJIT_R0, 0, SLJIT_IMM, 5); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0xff0000004)); sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_R0, 0); cmp_test(compiler, SLJIT_SIG_GREATER | SLJIT_32, SLJIT_R1, 0, SLJIT_IMM, 5); cmp_test(compiler, SLJIT_SIG_GREATER, SLJIT_R0, 0, SLJIT_IMM, 5); -#else +#else /* !SLJIT_64BIT_ARCHITECTURE */ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 4); + /* buf[40-43] */ cmp_test(compiler, SLJIT_LESS | SLJIT_32, SLJIT_R0, 0, SLJIT_IMM, 5); cmp_test(compiler, SLJIT_GREATER | SLJIT_32, SLJIT_R0, 0, SLJIT_IMM, 5); sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0xf0000004); cmp_test(compiler, SLJIT_SIG_GREATER | SLJIT_32, SLJIT_R0, 0, SLJIT_IMM, 5); cmp_test(compiler, SLJIT_SIG_LESS | SLJIT_32, SLJIT_R0, 0, SLJIT_IMM, 5); -#endif +#endif /* SLJIT_64BIT_ARCHITECTURE */ sljit_emit_return_void(compiler); @@ -3360,11 +3673,9 @@ static void test36(void) #if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) #define BITN(n) (SLJIT_W(1) << (63 - (n))) -#define RESN(n) (n) -#else +#else /* !SLJIT_64BIT_ARCHITECTURE */ #define BITN(n) (1 << (31 - ((n) & 0x1f))) -#define RESN(n) ((n) & 0x1f) -#endif +#endif /* SLJIT_64BIT_ARCHITECTURE */ static void test37(void) { @@ -3372,7 +3683,7 @@ static void test37(void) executable_code code; struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); sljit_sw buf[9]; - sljit_s32 ibuf[2]; + sljit_s32 ibuf[3]; sljit_s32 i; if (verbose) @@ -3382,45 +3693,55 @@ static void test37(void) for (i = 0; i < 9; i++) buf[i] = -1; + for (i = 0; i < 3; i++) + ibuf[i] = -1; buf[2] = 0; buf[4] = BITN(13); - ibuf[0] = -1; - ibuf[1] = -1; - sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, P, P), 1, 3, 0, 0, 0); + + sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, P, P), 2, 3, 0, 0, 0); + /* buf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, BITN(27)); sljit_emit_op1(compiler, SLJIT_CLZ, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); + /* buf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, BITN(47)); sljit_emit_op1(compiler, SLJIT_CLZ, SLJIT_R0, 0, SLJIT_S2, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0); + /* buf[2] */ sljit_emit_op1(compiler, SLJIT_CLZ, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw)); + /* buf[3] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1); sljit_emit_op1(compiler, SLJIT_CLZ, SLJIT_R0, 0, SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R0, 0); + /* ibuf[0] */ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0); sljit_emit_op1(compiler, SLJIT_CLZ32, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_R0, 0); + /* buf[4] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1); sljit_emit_op1(compiler, SLJIT_CLZ, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R0, 0); + /* buf[5] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, BITN(58)); sljit_emit_op1(compiler, SLJIT_CLZ, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R0, 0); + /* buf[6] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); sljit_emit_op1(compiler, SLJIT_CLZ, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R0, 0); -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0xff08a00000)); -#else - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0x08a00000); -#endif + /* ibuf[1] */ + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, WCONST(0xff08a00000, 0x08a00000)); sljit_emit_op1(compiler, SLJIT_CLZ32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32), SLJIT_R0, 0); + /* buf[7] */ sljit_emit_op1(compiler, SLJIT_CLZ32, SLJIT_R0, 0, SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R0, 0); -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0xffc8a00000)); -#else - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0xc8a00000); -#endif + /* buf[8] */ + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, WCONST(0xffc8a00000, 0xc8a00000)); sljit_emit_op1(compiler, SLJIT_CLZ32, SLJIT_R0, 0, SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R0, 0); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 0xa00a); + sljit_emit_op2(compiler, SLJIT_SHL32, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_IMM, 8); + /* ibuf[2] */ + sljit_emit_op1(compiler, SLJIT_CLZ32, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_s32), SLJIT_R0, 0); + sljit_emit_return_void(compiler); code.code = sljit_generate_code(compiler); @@ -3428,32 +3749,24 @@ static void test37(void) sljit_free_compiler(compiler); code.func2((sljit_sw)&buf, (sljit_sw)&ibuf); - FAILED(buf[0] != RESN(27), "test37 case 1 failed\n"); - FAILED(buf[1] != RESN(47), "test37 case 2 failed\n"); -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - FAILED(buf[2] != 64, "test37 case 3 failed\n"); -#else - FAILED(buf[2] != 32, "test37 case 3 failed\n"); -#endif + FAILED(buf[0] != 27, "test37 case 1 failed\n"); + FAILED(buf[1] != WCONST(47, 15), "test37 case 2 failed\n"); + FAILED(buf[2] != WCONST(64, 32), "test37 case 3 failed\n"); FAILED(buf[3] != 0, "test37 case 4 failed\n"); FAILED(ibuf[0] != 32, "test37 case 5 failed\n"); - FAILED(buf[4] != RESN(13), "test37 case 6 failed\n"); - FAILED(buf[5] != RESN(58), "test37 case 7 failed\n"); -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - FAILED(buf[6] != 64, "test37 case 8 failed\n"); -#else - FAILED(buf[6] != 32, "test37 case 8 failed\n"); -#endif + FAILED(buf[4] != 13, "test37 case 6 failed\n"); + FAILED(buf[5] != WCONST(58, 26), "test37 case 7 failed\n"); + FAILED(buf[6] != WCONST(64, 32), "test37 case 8 failed\n"); FAILED(ibuf[1] != 4, "test37 case 9 failed\n"); - FAILED((buf[7] & (sljit_sw)0xffffffff) != 4, "test37 case 10 failed\n"); FAILED((buf[8] & (sljit_sw)0xffffffff) != 0, "test37 case 11 failed\n"); + FAILED(ibuf[2] != 8, "test37 case 12 failed\n"); sljit_free_code(code.code, NULL); successful_tests++; } + #undef BITN -#undef RESN static void test38(void) { @@ -3644,22 +3957,26 @@ static void test40(void) sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_IMM, -6, SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0x123456); sljit_emit_op_flags(compiler, SLJIT_OR, SLJIT_R1, 0, SLJIT_SIG_LESS); + /* buf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R1, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -13); sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_IMM, -13, SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, 0); sljit_emit_op_flags(compiler, SLJIT_OR | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_EQUAL); + /* buf[1] */ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_NOT_EQUAL); sljit_emit_op2(compiler, SLJIT_OR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), 0); sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_IMM, -13, SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0); sljit_emit_op_flags(compiler, SLJIT_OR | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_EQUAL); + /* buf[2] */ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_EQUAL); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -13); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 3); sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R1, 0); + /* buf[3] */ sljit_emit_op_flags(compiler, SLJIT_OR, SLJIT_MEM2(SLJIT_S0, SLJIT_R1), SLJIT_WORD_SHIFT, SLJIT_SIG_LESS); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -8); @@ -3671,22 +3988,28 @@ static void test40(void) sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_R1, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, 0x88); sljit_emit_op_flags(compiler, SLJIT_OR, SLJIT_S3, 0, SLJIT_NOT_EQUAL); + /* buf[4] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 4, SLJIT_S1, 0); + /* buf[5] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 5, SLJIT_S3, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x84); sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_IMM, 0x180, SLJIT_R0, 0); + /* buf[6] */ sljit_emit_op_flags(compiler, SLJIT_OR | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 6, SLJIT_EQUAL); + /* buf[7] */ sljit_emit_op_flags(compiler, SLJIT_OR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 7, SLJIT_EQUAL); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1); sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, 1); sljit_emit_op_flags(compiler, SLJIT_OR | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_NOT_EQUAL); + /* buf[8] */ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 8, SLJIT_NOT_EQUAL); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x123456); sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_R0, 0, SLJIT_IMM, 1); sljit_emit_op_flags(compiler, SLJIT_OR, SLJIT_R0, 0, SLJIT_GREATER); + /* buf[9] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 9, SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, 0xbaddead); @@ -3975,6 +4298,7 @@ static void test42(void) sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S4, 0, SLJIT_IMM, 0x9a3b06d); #if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) + /* buf[7-26] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(-0x5dc4f897b8cd67f5)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0x3f8b5c026cb088df)); sljit_emit_op0(compiler, SLJIT_LMUL_UW); @@ -4043,7 +4367,7 @@ static void test42(void) sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 25 * sizeof(sljit_sw), SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 26 * sizeof(sljit_sw), SLJIT_R1, 0); -#else +#else /* !SLJIT_64BIT_ARCHITECTURE */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -0x58cd67f5); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0x3cb088df); sljit_emit_op0(compiler, SLJIT_LMUL_UW); @@ -4107,8 +4431,9 @@ static void test42(void) sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R1, 0, SLJIT_R1, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 25 * sizeof(sljit_sw), SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 26 * sizeof(sljit_sw), SLJIT_R1, 0); -#endif +#endif /* SLJIT_64BIT_ARCHITECTURE */ + /* buf[0-6] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R2, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R3, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R4, 0); @@ -4142,7 +4467,7 @@ static void test42(void) FAILED(buf[12] != SLJIT_W(2532236178951865933), "test42 case 13 failed\n"); FAILED(buf[13] != SLJIT_W(-1), "test42 case 14 failed\n"); FAILED(buf[14] != SLJIT_W(-2177944059851366166), "test42 case 15 failed\n"); -#else +#else /* !SLJIT_64BIT_ARCHITECTURE */ FAILED(buf[7] != -1587000939, "test42 case 8 failed\n"); FAILED(buf[8] != 665003983, "test42 case 9 failed\n"); FAILED(buf[9] != -1587000939, "test42 case 10 failed\n"); @@ -4151,7 +4476,7 @@ static void test42(void) FAILED(buf[12] != 768706125, "test42 case 13 failed\n"); FAILED(buf[13] != -1, "test42 case 14 failed\n"); FAILED(buf[14] != -471654166, "test42 case 15 failed\n"); -#endif +#endif /* SLJIT_64BIT_ARCHITECTURE */ FAILED(buf[15] != 56, "test42 case 16 failed\n"); FAILED(buf[16] != 58392872, "test42 case 17 failed\n"); @@ -4163,12 +4488,12 @@ static void test42(void) FAILED(buf[20] != SLJIT_W(0x3d4af2c543), "test42 case 21 failed\n"); FAILED(buf[21] != SLJIT_W(-0xaf978), "test42 case 22 failed\n"); FAILED(buf[22] != SLJIT_W(0xa64ae42b7d6), "test42 case 23 failed\n"); -#else +#else /* !SLJIT_64BIT_ARCHITECTURE */ FAILED(buf[19] != SLJIT_W(0xda5), "test42 case 20 failed\n"); FAILED(buf[20] != SLJIT_W(0xb86d0), "test42 case 21 failed\n"); FAILED(buf[21] != SLJIT_W(-0x6b6e), "test42 case 22 failed\n"); FAILED(buf[22] != SLJIT_W(0xd357), "test42 case 23 failed\n"); -#endif +#endif /* SLJIT_64BIT_ARCHITECTURE */ FAILED(buf[23] != 0x0, "test42 case 24 failed\n"); FAILED(buf[24] != (sljit_sw)0xf2906b14, "test42 case 25 failed\n"); @@ -4183,7 +4508,7 @@ static void test43(void) { /* Test floating point compare. */ executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); + struct sljit_compiler* compiler; struct sljit_jump* jump; union { @@ -4201,11 +4526,10 @@ static void test43(void) if (verbose) printf("no fpu available, test43 skipped\n"); successful_tests++; - if (compiler) - sljit_free_compiler(compiler); return; } + compiler = sljit_create_compiler(NULL, NULL); FAILED(!compiler, "cannot create compiler\n"); dbuf[0].value = 12.125; @@ -4274,16 +4598,20 @@ static void test44(void) sljit_emit_enter(compiler, 0, SLJIT_ARGS1(P, P), 3, 2, 0, 0, 0); sljit_emit_op1(compiler, SLJIT_MOV_P, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), 0); + /* buf[1] */ sljit_emit_op1(compiler, SLJIT_MOV_P, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_p), SLJIT_R0, 0); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_p)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 2); + /* buf[2] */ sljit_emit_op1(compiler, SLJIT_MOV_P, SLJIT_MEM2(SLJIT_S0, SLJIT_R1), SLJIT_POINTER_SHIFT, SLJIT_R0, 0); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_p)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 3 << SLJIT_POINTER_SHIFT); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_S0, 0); + /* buf[3] */ sljit_emit_op1(compiler, SLJIT_MOV_P, SLJIT_MEM2(SLJIT_R2, SLJIT_R1), 0, SLJIT_R0, 0); sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 2 * sizeof(sljit_p)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 1 << SLJIT_POINTER_SHIFT); + /* buf[4] */ sljit_emit_op1(compiler, SLJIT_MOV_P, SLJIT_MEM2(SLJIT_R2, SLJIT_R1), 2, SLJIT_R0, 0); sljit_emit_return(compiler, SLJIT_MOV_P, SLJIT_R0, 0); @@ -4307,7 +4635,7 @@ static void test45(void) /* Test single precision floating point. */ executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); + struct sljit_compiler* compiler; sljit_f32 buf[12]; sljit_sw buf2[6]; struct sljit_jump* jump; @@ -4319,11 +4647,10 @@ static void test45(void) if (verbose) printf("no fpu available, test45 skipped\n"); successful_tests++; - if (compiler) - sljit_free_compiler(compiler); return; } + compiler = sljit_create_compiler(NULL, NULL); FAILED(!compiler, "cannot create compiler\n"); buf[0] = 5.5; @@ -4348,42 +4675,58 @@ static void test45(void) sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, P, P), 3, 2, 6, 0, 0); + /* buf[2] */ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), 0); sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR5, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f32)); sljit_emit_fop1(compiler, SLJIT_NEG_F32, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f32), SLJIT_FR0, 0); + /* buf[3] */ sljit_emit_fop1(compiler, SLJIT_ABS_F32, SLJIT_FR1, 0, SLJIT_FR5, 0); sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_f32), SLJIT_FR1, 0); + /* buf[4] */ sljit_emit_fop1(compiler, SLJIT_ABS_F32, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_f32), SLJIT_FR5, 0); + /* buf[5] */ sljit_emit_fop1(compiler, SLJIT_NEG_F32, SLJIT_FR4, 0, SLJIT_MEM1(SLJIT_S0), 0); sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_f32), SLJIT_FR4, 0); + /* buf[6] */ sljit_emit_fop2(compiler, SLJIT_ADD_F32, SLJIT_FR0, 0, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f32)); sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_f32), SLJIT_FR0, 0); + /* buf[7] */ sljit_emit_fop2(compiler, SLJIT_SUB_F32, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_f32), SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_f32), SLJIT_FR5, 0); + /* buf[8] */ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), 0); sljit_emit_fop2(compiler, SLJIT_MUL_F32, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_f32), SLJIT_FR0, 0, SLJIT_FR0, 0); + /* buf[9] */ sljit_emit_fop2(compiler, SLJIT_DIV_F32, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_f32), SLJIT_FR0, 0); sljit_emit_fop1(compiler, SLJIT_ABS_F32, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_f32), SLJIT_FR2, 0); + /* buf[10] */ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 0x3d0ac); sljit_emit_fop1(compiler, SLJIT_NEG_F32, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_f32), SLJIT_MEM1(SLJIT_R0), 0x3d0ac); + /* buf[11] */ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 0x3d0ac + sizeof(sljit_f32)); sljit_emit_fop1(compiler, SLJIT_ABS_F32, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_f32), SLJIT_MEM1(SLJIT_R0), -0x3d0ac); + /* buf2[0] */ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), 0); sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f32)); sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_EQUAL, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), 0); cond_set(compiler, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_F_EQUAL); + /* buf2[1] */ sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_LESS, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), 0); cond_set(compiler, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_sw), SLJIT_F_LESS); + /* buf2[2] */ sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_EQUAL, SLJIT_FR1, 0, SLJIT_FR2, 0); cond_set(compiler, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_sw), SLJIT_F_EQUAL); + /* buf2[3] */ sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_GREATER_EQUAL, SLJIT_FR1, 0, SLJIT_FR2, 0); cond_set(compiler, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_sw), SLJIT_F_GREATER_EQUAL); + /* buf2[4] */ jump = sljit_emit_fcmp(compiler, SLJIT_F_LESS_EQUAL | SLJIT_32, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f32)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_sw), SLJIT_IMM, 7); sljit_set_label(jump, sljit_emit_label(compiler)); + /* buf2[5] */ jump = sljit_emit_fcmp(compiler, SLJIT_F_GREATER | SLJIT_32, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_FR2, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_sw), SLJIT_IMM, 6); sljit_set_label(jump, sljit_emit_label(compiler)); @@ -4440,47 +4783,65 @@ static void test46(void) sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -7); sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, SLJIT_R2, 0, SLJIT_IMM, 13); + /* buf[0] */ sljit_emit_op_flags(compiler, SLJIT_MOV32, SLJIT_MEM0(), (sljit_sw)&buf, SLJIT_LESS); + /* buf[2] */ sljit_emit_op_flags(compiler, SLJIT_AND32, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_s32), SLJIT_NOT_ZERO); sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_IMM, -7); + /* buf[4] */ sljit_emit_op_flags(compiler, SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_s32), SLJIT_EQUAL); + /* buf[6] */ sljit_emit_op_flags(compiler, SLJIT_AND32, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_s32), SLJIT_NOT_EQUAL); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x1235); sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, 0x1235); sljit_emit_op_flags(compiler, SLJIT_AND32 | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_ZERO); + /* buf[8] */ sljit_emit_op_flags(compiler, SLJIT_AND32, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_s32), SLJIT_ZERO); + /* buf[10] */ sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_s32), SLJIT_R0, 0); sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_IMM, -7); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 12); + /* buf[12] */ sljit_emit_op_flags(compiler, SLJIT_MOV32, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 2, SLJIT_EQUAL); sljit_emit_op_flags(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_EQUAL); + /* buf[14] */ sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_s32), SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 16); + /* buf[16] */ sljit_emit_op_flags(compiler, SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 2, SLJIT_EQUAL); + /* buf[18] */ sljit_emit_op_flags(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 18 * sizeof(sljit_s32), SLJIT_NOT_EQUAL); sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_IMM, -7); + /* buf[20] */ sljit_emit_op_flags(compiler, SLJIT_XOR32 | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_S0), 20 * sizeof(sljit_s32), SLJIT_ZERO); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 39); sljit_emit_op_flags(compiler, SLJIT_XOR32, SLJIT_R0, 0, SLJIT_NOT_ZERO); + /* buf[22] */ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 22 * sizeof(sljit_s32), SLJIT_R0, 0); sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_R2, 0, SLJIT_IMM, -7); + /* buf2[0] */ sljit_emit_op_flags(compiler, SLJIT_AND, SLJIT_MEM0(), (sljit_sw)&buf2, SLJIT_GREATER); sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_R2, 0, SLJIT_IMM, 5); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1); + /* buf2[1] */ sljit_emit_op_flags(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_SIG_LESS); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2); sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, SLJIT_R2, 0, SLJIT_IMM, 5); + /* buf2[2] */ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_LESS); sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_NOT_EQUAL); sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_R2, 0, SLJIT_IMM, 5); + /* buf2[3] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_sw), SLJIT_S2, 0); sljit_emit_op_flags(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_SIG_LESS); + /* buf2[4] */ sljit_emit_op_flags(compiler, SLJIT_OR, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_sw), SLJIT_ZERO); sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_R2, 0, SLJIT_IMM, 0); + /* buf2[5] */ sljit_emit_op_flags(compiler, SLJIT_XOR, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_sw), SLJIT_GREATER); sljit_emit_return_void(compiler); @@ -4542,15 +4903,18 @@ static void test47(void) buf[2] = 0; sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 1, 0, 0, 0); + /* buf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x3a5c6f); sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_IMM, 3); sljit_set_target(sljit_emit_jump(compiler, SLJIT_LESS), 0x11223344); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); + /* buf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0xd37c10); #if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) sljit_set_target(sljit_emit_jump(compiler, SLJIT_LESS), SLJIT_W(0x112233445566)); #endif sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0); + /* buf[2] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x59b48e); #if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) sljit_set_target(sljit_emit_jump(compiler, SLJIT_LESS), SLJIT_W(0x1122334455667788)); @@ -4575,7 +4939,7 @@ static void test48(void) { /* Test floating point conversions. */ executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); + struct sljit_compiler* compiler; int i; sljit_f64 dbuf[10]; sljit_f32 sbuf[10]; @@ -4589,12 +4953,12 @@ static void test48(void) if (verbose) printf("no fpu available, test48 skipped\n"); successful_tests++; - if (compiler) - sljit_free_compiler(compiler); return; } + compiler = sljit_create_compiler(NULL, NULL); FAILED(!compiler, "cannot create compiler\n"); + for (i = 0; i < 10; i++) { dbuf[i] = 0.0; sbuf[i] = 0.0; @@ -4728,7 +5092,7 @@ static void test49(void) { /* Test floating point conversions. */ executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); + struct sljit_compiler* compiler; int i; sljit_f64 dbuf[10]; sljit_f32 sbuf[9]; @@ -4744,11 +5108,10 @@ static void test49(void) if (verbose) printf("no fpu available, test49 skipped\n"); successful_tests++; - if (compiler) - sljit_free_compiler(compiler); return; } + compiler = sljit_create_compiler(NULL, NULL); FAILED(!compiler, "cannot create compiler\n"); for (i = 0; i < 9; i++) { @@ -4809,7 +5172,7 @@ static void test49(void) sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_SW, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_f64), SLJIT_R0, 0); /* dbuf[9] */ sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_S32, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_f64), SLJIT_IMM, SLJIT_W(0x7766554433)); -#endif +#endif /* SLJIT_64BIT_ARCHITECTURE */ sljit_emit_return_void(compiler); @@ -4856,7 +5219,7 @@ static void test49(void) FAILED(dbuf[9] != (sljit_f64)SLJIT_W(0x66554433), "test49 case 30 failed\n"); FAILED(wbuf[8] != SLJIT_W(0x1122334455), "test48 case 31 failed\n"); FAILED(ibuf[8] == 0x4455, "test48 case 32 failed\n"); -#endif +#endif /* SLJIT_64BIT_ARCHITECTURE */ sljit_free_code(code.code, NULL); successful_tests++; @@ -4866,7 +5229,7 @@ static void test50(void) { /* Test stack and floating point operations. */ executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); + struct sljit_compiler* compiler; #if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) sljit_uw size1, size2, size3; int result; @@ -4880,11 +5243,10 @@ static void test50(void) if (verbose) printf("no fpu available, test50 skipped\n"); successful_tests++; - if (compiler) - sljit_free_compiler(compiler); return; } + compiler = sljit_create_compiler(NULL, NULL); FAILED(!compiler, "cannot create compiler\n"); sbuf[0] = 245.5; @@ -5098,8 +5460,6 @@ static void test52(void) return; } - /* Next test. */ - compiler = sljit_create_compiler(NULL, NULL); FAILED(!compiler, "cannot create compiler\n"); buf[0] = 6.25; @@ -5193,7 +5553,7 @@ static void test53(void) buf[i] = 0; if (verbose) - printf("Run test78\n"); + printf("Run test53\n"); FAILED(!compiler, "cannot create compiler\n"); @@ -5203,15 +5563,15 @@ static void test53(void) for (i = 0; i < SLJIT_NUMBER_OF_REGISTERS; i++, addr++) { if (sljit_get_register_index(SLJIT_R(i)) == -1) continue; - + /* buf_start[i * 3] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_IMM, (sljit_sw)addr); sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM2(SLJIT_R(i), SLJIT_R(i)), 1, SLJIT_IMM, 88 + i); - + /* buf_start[i * 3 + 1] */ if (i != 0) { sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)(addr * 2 + 1)); sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM2(SLJIT_R(i), SLJIT_R0), 0, SLJIT_IMM, 147 + i); } - + /* buf_start[i * 3 + 2] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_IMM, (sljit_sw)(addr * 3 + 2)); sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_R(i)), 0, SLJIT_IMM, 191 + i); } @@ -5279,18 +5639,23 @@ static void test54(void) sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 34); sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_R0, 0, SLJIT_IMM, -10); sljit_emit_cmov(compiler, SLJIT_SIG_LESS, SLJIT_R0, SLJIT_R1, 0); + /* buf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER, SLJIT_R0, 0, SLJIT_IMM, -10); sljit_emit_cmov(compiler, SLJIT_SIG_GREATER, SLJIT_R0, SLJIT_R1, 0); + /* buf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 24); sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, 24); sljit_emit_cmov(compiler, SLJIT_NOT_EQUAL, SLJIT_R0, SLJIT_IMM, 66); + /* buf[2] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R0, 0); sljit_emit_cmov(compiler, SLJIT_EQUAL, SLJIT_R0, SLJIT_IMM, 78); + /* buf[3] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R0, 0); sljit_emit_cmov(compiler, SLJIT_EQUAL, SLJIT_R0, SLJIT_IMM, large_num); + /* buf[4] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R0, 0); #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) @@ -5300,22 +5665,26 @@ static void test54(void) sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -45); sljit_emit_op2(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 8); sljit_emit_cmov(compiler, SLJIT_OVERFLOW, SLJIT_R3, SLJIT_IMM, 35); + /* buf[5] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R3, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, large_num); sljit_emit_op2u(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_IMM, large_num); sljit_emit_cmov(compiler, SLJIT_OVERFLOW, SLJIT_R3, SLJIT_IMM, 35); + /* buf[6] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R3, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 71); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 13); sljit_emit_op2(compiler, SLJIT_LSHR | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 8); sljit_emit_cmov(compiler, SLJIT_EQUAL, SLJIT_R3, SLJIT_R0, 0); + /* buf[7] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R3, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 12); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -29); sljit_emit_op2(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 8); sljit_emit_cmov(compiler, SLJIT_NOT_OVERFLOW, SLJIT_R0, SLJIT_R3, 0); + /* buf[8] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R3, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 16); @@ -5323,8 +5692,10 @@ static void test54(void) sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, 21); sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, 8); sljit_emit_cmov(compiler, SLJIT_NOT_EQUAL, SLJIT_R3, SLJIT_R4, 0); + /* buf[9] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_R3, 0); sljit_emit_cmov(compiler, SLJIT_EQUAL, SLJIT_R3, SLJIT_R4, 0); + /* buf[10] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_R3, 0); if (sljit_has_cpu_feature(SLJIT_HAS_FPU)) { @@ -5335,53 +5706,65 @@ static void test54(void) sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 16); sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_EQUAL, SLJIT_FR1, 0, SLJIT_FR2, 0); sljit_emit_cmov(compiler, SLJIT_F_EQUAL, SLJIT_R0, SLJIT_IMM, -45); + /* buf[11] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_R0, 0); sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_GREATER, SLJIT_FR1, 0, SLJIT_FR2, 0); sljit_emit_cmov(compiler, SLJIT_F_GREATER, SLJIT_R0, SLJIT_IMM, -45); + /* buf[12] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_R0, 0); sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_GREATER_EQUAL, SLJIT_FR1, 0, SLJIT_FR2, 0); sljit_emit_cmov(compiler, SLJIT_F_GREATER_EQUAL, SLJIT_R0, SLJIT_IMM, 33); + /* buf[13] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 8); sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_LESS, SLJIT_FR1, 0, SLJIT_FR2, 0); sljit_emit_cmov(compiler, SLJIT_F_LESS, SLJIT_R0, SLJIT_IMM, -70); + /* buf[14] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw), SLJIT_R0, 0); sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_LESS_EQUAL, SLJIT_FR2, 0, SLJIT_FR1, 0); sljit_emit_cmov(compiler, SLJIT_F_LESS_EQUAL, SLJIT_R0, SLJIT_IMM, -60); + /* buf[15] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 15 * sizeof(sljit_sw), SLJIT_R0, 0); sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_NOT_EQUAL, SLJIT_FR1, 0, SLJIT_FR2, 0); sljit_emit_cmov(compiler, SLJIT_F_NOT_EQUAL, SLJIT_R0, SLJIT_IMM, 31); + /* buf[16] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_sw), SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 53); sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_ORDERED, SLJIT_FR1, 0, SLJIT_FR0, 0); sljit_emit_cmov(compiler, SLJIT_ORDERED, SLJIT_R0, SLJIT_IMM, 17); + /* buf[17] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 17 * sizeof(sljit_sw), SLJIT_R0, 0); sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_UNORDERED, SLJIT_FR1, 0, SLJIT_FR0, 0); sljit_emit_cmov(compiler, SLJIT_UNORDERED, SLJIT_R0, SLJIT_IMM, 59); + /* buf[18] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 18 * sizeof(sljit_sw), SLJIT_R0, 0); } sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 177); sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_IMM, 178); - sljit_emit_cmov(compiler, SLJIT_LESS, SLJIT_R0 | SLJIT_32, SLJIT_IMM, 200); + sljit_emit_cmov(compiler, SLJIT_LESS | SLJIT_32, SLJIT_R0, SLJIT_IMM, 200); + /* ibuf[0] */ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 95); sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R3, 0, SLJIT_IMM, 177); sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_LESS_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 95); - sljit_emit_cmov(compiler, SLJIT_LESS_EQUAL, SLJIT_R3 | SLJIT_32, SLJIT_R0, 0); + sljit_emit_cmov(compiler, SLJIT_LESS_EQUAL | SLJIT_32, SLJIT_R3, SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0); + /* ibuf[1] */ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32), SLJIT_R3, 0); sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R3, 0, SLJIT_IMM, 56); sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, -63); sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_SIG_LESS, SLJIT_R3, 0, SLJIT_R4, 0); - sljit_emit_cmov(compiler, SLJIT_SIG_LESS, SLJIT_R3 | SLJIT_32, SLJIT_R4, 0); + sljit_emit_cmov(compiler, SLJIT_SIG_LESS | SLJIT_32, SLJIT_R3, SLJIT_R4, 0); + /* ibuf[2] */ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_s32), SLJIT_R3, 0); sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_SIG_GREATER, SLJIT_R3, 0, SLJIT_R4, 0); - sljit_emit_cmov(compiler, SLJIT_SIG_GREATER, SLJIT_R3 | SLJIT_32, SLJIT_R4, 0); + sljit_emit_cmov(compiler, SLJIT_SIG_GREATER | SLJIT_32, SLJIT_R3, SLJIT_R4, 0); + /* ibuf[3] */ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_s32), SLJIT_R3, 0); sljit_emit_return_void(compiler); @@ -5488,7 +5871,7 @@ static void test55(void) static void test56(void) { - /* Check integer substraction with negative immediate. */ + /* Check integer subtraction with negative immediate. */ executable_code code; struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); sljit_sw buf[13]; @@ -5506,34 +5889,47 @@ static void test56(void) sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 90 << 12); sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, -(91 << 12)); + /* buf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R1, 0); + /* buf[1] */ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_SIG_GREATER); sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_LESS, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, -(91 << 12)); + /* buf[2] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R1, 0); + /* buf[3] */ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_LESS); sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER_EQUAL, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, -(91 << 12)); + /* buf[4] */ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_SIG_GREATER_EQUAL); sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, -(91 << 12)); + /* buf[5] */ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_LESS_EQUAL); sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, -(91 << 12)); + /* buf[6] */ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_GREATER); sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, -(91 << 12)); + /* buf[7] */ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_SIG_LESS); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 90); sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, -91); + /* buf[8] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R0, 0); + /* buf[9] */ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_SIG_GREATER); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 90); sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, -91); + /* buf[10] */ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_LESS_EQUAL); sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, -0x7fffffff); sljit_emit_op2(compiler, SLJIT_ADD32 | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, -(91 << 12)); + /* buf[11] */ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_OVERFLOW); sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, -0x7fffffff-1); sljit_emit_op2(compiler, SLJIT_SUB32 | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_IMM, 0, SLJIT_R0, 0); + /* buf[12] */ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_OVERFLOW); sljit_emit_return_void(compiler); @@ -5657,7 +6053,7 @@ static void test58(void) { /* Check function calls with floating point arguments. */ executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); + struct sljit_compiler* compiler; struct sljit_jump* jump = NULL; sljit_f64 dbuf[7]; sljit_f32 sbuf[7]; @@ -5670,11 +6066,12 @@ static void test58(void) if (verbose) printf("no fpu available, test58 skipped\n"); successful_tests++; - if (compiler) - sljit_free_compiler(compiler); return; } + compiler = sljit_create_compiler(NULL, NULL); + FAILED(!compiler, "cannot create compiler\n"); + dbuf[0] = 5.25; dbuf[1] = 0.0; dbuf[2] = 2.5; @@ -5692,8 +6089,6 @@ static void test58(void) wbuf[0] = 0; wbuf[1] = 0; - FAILED(!compiler, "cannot create compiler\n"); - sljit_emit_enter(compiler, 0, SLJIT_ARGS3(VOID, P, P, P), 3, 3, 4, 0, sizeof(sljit_sw)); sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S1), 0); @@ -5949,97 +6344,113 @@ static void test60(void) sljit_emit_enter(compiler, 0, SLJIT_ARGS3(VOID, P, P, P), 4, 3, 4, 0, sizeof(sljit_sw)); - supported[0] = sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_R1, SLJIT_MEM1(SLJIT_R0), 2 * sizeof(sljit_sw)); + supported[0] = sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_SUPP, SLJIT_R1, SLJIT_MEM1(SLJIT_R0), 2 * sizeof(sljit_sw)); if (supported[0] == SLJIT_SUCCESS) { sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S0, 0); - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_PRE, SLJIT_R1, SLJIT_MEM1(SLJIT_R0), 2 * sizeof(sljit_sw)); + sljit_emit_mem_update(compiler, SLJIT_MOV, SLJIT_R1, SLJIT_MEM1(SLJIT_R0), 2 * sizeof(sljit_sw)); + /* buf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R1, 0); + /* buf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0); } - supported[1] = sljit_emit_mem(compiler, SLJIT_MOV_S8 | SLJIT_MEM_SUPP | SLJIT_MEM_POST, SLJIT_R0, SLJIT_MEM1(SLJIT_R2), -2 * (sljit_sw)sizeof(sljit_s8)); + supported[1] = sljit_emit_mem_update(compiler, SLJIT_MOV_S8 | SLJIT_MEM_SUPP | SLJIT_MEM_POST, SLJIT_R0, SLJIT_MEM1(SLJIT_R2), -2 * (sljit_sw)sizeof(sljit_s8)); if (supported[1] == SLJIT_SUCCESS) { sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S1, 0, SLJIT_IMM, 2 * sizeof(sljit_s8)); - sljit_emit_mem(compiler, SLJIT_MOV_S8 | SLJIT_MEM_POST, SLJIT_R0, SLJIT_MEM1(SLJIT_R2), -2 * (sljit_sw)sizeof(sljit_s8)); + sljit_emit_mem_update(compiler, SLJIT_MOV_S8 | SLJIT_MEM_POST, SLJIT_R0, SLJIT_MEM1(SLJIT_R2), -2 * (sljit_sw)sizeof(sljit_s8)); + /* buf[3] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R0, 0); + /* buf[4] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R2, 0); } - supported[2] = sljit_emit_mem(compiler, SLJIT_MOV_S32 | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_R2, SLJIT_MEM1(SLJIT_R1), -2 * (sljit_sw)sizeof(sljit_s32)); + supported[2] = sljit_emit_mem_update(compiler, SLJIT_MOV_S32 | SLJIT_MEM_SUPP, SLJIT_R2, SLJIT_MEM1(SLJIT_R1), -2 * (sljit_sw)sizeof(sljit_s32)); if (supported[2] == SLJIT_SUCCESS) { sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S2, 0, SLJIT_IMM, 2 * sizeof(sljit_s32)); - sljit_emit_mem(compiler, SLJIT_MOV_S32 | SLJIT_MEM_PRE, SLJIT_R2, SLJIT_MEM1(SLJIT_R1), -2 * (sljit_sw)sizeof(sljit_s32)); + sljit_emit_mem_update(compiler, SLJIT_MOV_S32, SLJIT_R2, SLJIT_MEM1(SLJIT_R1), -2 * (sljit_sw)sizeof(sljit_s32)); + /* buf[5] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R2, 0); + /* buf[6] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R1, 0); } - supported[3] = sljit_emit_mem(compiler, SLJIT_MOV32 | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_R1, SLJIT_MEM1(SLJIT_R2), 2 * sizeof(sljit_s32)); + supported[3] = sljit_emit_mem_update(compiler, SLJIT_MOV32 | SLJIT_MEM_SUPP | SLJIT_MEM_STORE, SLJIT_R1, SLJIT_MEM1(SLJIT_R2), 2 * sizeof(sljit_s32)); if (supported[3] == SLJIT_SUCCESS) { sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, -8765); sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R2, 0, SLJIT_S2, 0, SLJIT_IMM, sizeof(sljit_s32)); - sljit_emit_mem(compiler, SLJIT_MOV32 | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_R1, SLJIT_MEM1(SLJIT_R2), 2 * sizeof(sljit_s32)); + sljit_emit_mem_update(compiler, SLJIT_MOV32 | SLJIT_MEM_STORE, SLJIT_R1, SLJIT_MEM1(SLJIT_R2), 2 * sizeof(sljit_s32)); + /* buf[7] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R2, 0); } - supported[4] = sljit_emit_mem(compiler, SLJIT_MOV_S8 | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_POST, SLJIT_R1, SLJIT_MEM1(SLJIT_R2), -128 * (sljit_sw)sizeof(sljit_s8)); + supported[4] = sljit_emit_mem_update(compiler, SLJIT_MOV_S8 | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_POST, SLJIT_R1, SLJIT_MEM1(SLJIT_R2), -128 * (sljit_sw)sizeof(sljit_s8)); if (supported[4] == SLJIT_SUCCESS) { sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -121); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_S1, 0); - sljit_emit_mem(compiler, SLJIT_MOV_S8 | SLJIT_MEM_STORE | SLJIT_MEM_POST, SLJIT_R1, SLJIT_MEM1(SLJIT_R2), -128 * (sljit_sw)sizeof(sljit_s8)); + sljit_emit_mem_update(compiler, SLJIT_MOV_S8 | SLJIT_MEM_STORE | SLJIT_MEM_POST, SLJIT_R1, SLJIT_MEM1(SLJIT_R2), -128 * (sljit_sw)sizeof(sljit_s8)); + /* buf[8] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R2, 0); } - supported[5] = sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_R1, SLJIT_MEM1(SLJIT_R0), 1); + supported[5] = sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_STORE, SLJIT_R1, SLJIT_MEM1(SLJIT_R0), 1); if (supported[5] == SLJIT_SUCCESS) { sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 9 * sizeof(sljit_sw) - 1); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -881199); - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_R1, SLJIT_MEM1(SLJIT_R0), 1); + sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_STORE, SLJIT_R1, SLJIT_MEM1(SLJIT_R0), 1); + /* buf[10] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_R0, 0); } - supported[6] = sljit_emit_mem(compiler, SLJIT_MOV_S32 | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0); + supported[6] = sljit_emit_mem_update(compiler, SLJIT_MOV_S32 | SLJIT_MEM_SUPP, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0); if (supported[6] == SLJIT_SUCCESS) { sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S2, 0, SLJIT_IMM, 213); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -213); - sljit_emit_mem(compiler, SLJIT_MOV_S32 | SLJIT_MEM_PRE, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0); + sljit_emit_mem_update(compiler, SLJIT_MOV_S32, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0); + /* buf[11] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_R0, 0); + /* buf[12] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_R1, 0); } - supported[7] = sljit_emit_mem(compiler, SLJIT_MOV_S32 | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0); + supported[7] = sljit_emit_mem_update(compiler, SLJIT_MOV_S32 | SLJIT_MEM_SUPP | SLJIT_MEM_STORE, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0); if (supported[7] == SLJIT_SUCCESS) { sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_S2, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 2 * sizeof(sljit_s32)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -7890); - sljit_emit_mem(compiler, SLJIT_MOV_S32 | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0); + sljit_emit_mem_update(compiler, SLJIT_MOV_S32 | SLJIT_MEM_STORE, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0); + /* buf[13] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_R1, 0); } - supported[8] = sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_POST, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 2); + supported[8] = sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_POST, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 2); if (supported[8] == SLJIT_SUCCESS) { sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 2 * sizeof(sljit_sw)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 2 * sizeof(sljit_sw)); - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_POST, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 2); + sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_POST, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 2); + /* buf[14] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw), SLJIT_R0, 0); + /* buf[15] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 15 * sizeof(sljit_sw), SLJIT_R1, 0); } - supported[9] = sljit_emit_mem(compiler, SLJIT_MOV_S8 | SLJIT_MEM_SUPP | SLJIT_MEM_POST, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0); + supported[9] = sljit_emit_mem_update(compiler, SLJIT_MOV_S8 | SLJIT_MEM_SUPP | SLJIT_MEM_POST, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0); if (supported[9] == SLJIT_SUCCESS) { sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S1, 0, SLJIT_IMM, 2 * sizeof(sljit_s8)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -2 * (sljit_sw)sizeof(sljit_s8)); - sljit_emit_mem(compiler, SLJIT_MOV_S8 | SLJIT_MEM_POST, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0); + sljit_emit_mem_update(compiler, SLJIT_MOV_S8 | SLJIT_MEM_POST, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0); + /* buf[16] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_sw), SLJIT_R0, 0); + /* buf[17] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 17 * sizeof(sljit_sw), SLJIT_R1, 0); } - SLJIT_ASSERT(sljit_emit_mem(compiler, SLJIT_MOV_S8 | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 1) == SLJIT_ERR_UNSUPPORTED); - SLJIT_ASSERT(sljit_emit_mem(compiler, SLJIT_MOV_S8 | SLJIT_MEM_SUPP | SLJIT_MEM_POST, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 1) == SLJIT_ERR_UNSUPPORTED); + SLJIT_ASSERT(sljit_emit_mem_update(compiler, SLJIT_MOV_S8 | SLJIT_MEM_SUPP, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 1) == SLJIT_ERR_UNSUPPORTED); + SLJIT_ASSERT(sljit_emit_mem_update(compiler, SLJIT_MOV_S8 | SLJIT_MEM_SUPP, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 1) == SLJIT_ERR_UNSUPPORTED); #if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) /* TODO: at least for ARM (both V5 and V7) the range below needs further fixing */ - SLJIT_ASSERT(sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_R1, SLJIT_MEM1(SLJIT_R0), 256) == SLJIT_ERR_UNSUPPORTED); - SLJIT_ASSERT(sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_POST, SLJIT_R1, SLJIT_MEM1(SLJIT_R0), -257) == SLJIT_ERR_UNSUPPORTED); + SLJIT_ASSERT(sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_SUPP, SLJIT_R1, SLJIT_MEM1(SLJIT_R0), 256) == SLJIT_ERR_UNSUPPORTED); + SLJIT_ASSERT(sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_POST, SLJIT_R1, SLJIT_MEM1(SLJIT_R0), -257) == SLJIT_ERR_UNSUPPORTED); #endif sljit_emit_return_void(compiler); @@ -6095,7 +6506,7 @@ static void test61(void) { /* Test float memory accesses with pre/post updates. */ executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); + struct sljit_compiler* compiler; sljit_u32 i; sljit_s32 supported[6]; sljit_sw wbuf[6]; @@ -6109,17 +6520,18 @@ static void test61(void) static sljit_u8 expected[6] = { 0, 0, 0, 0, 0, 0 }; #endif + if (verbose) + printf("Run test61\n"); + if (!sljit_has_cpu_feature(SLJIT_HAS_FPU)) { if (verbose) printf("no fpu available, test61 skipped\n"); successful_tests++; - if (compiler) - sljit_free_compiler(compiler); return; } - if (verbose) - printf("Run test61\n"); + compiler = sljit_create_compiler(NULL, NULL); + FAILED(!compiler, "cannot create compiler\n"); for (i = 0; i < 6; i++) wbuf[i] = 0; @@ -6134,67 +6546,77 @@ static void test61(void) sbuf[2] = 0.0; sbuf[3] = 0.0; - FAILED(!compiler, "cannot create compiler\n"); - sljit_emit_enter(compiler, 0, SLJIT_ARGS3(VOID, P, P, P), 4, 3, 4, 0, sizeof(sljit_sw)); - supported[0] = sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_FR0, SLJIT_MEM1(SLJIT_R0), 4 * sizeof(sljit_f64)); + supported[0] = sljit_emit_fmem_update(compiler, SLJIT_MOV_F64 | SLJIT_MEM_SUPP, SLJIT_FR0, SLJIT_MEM1(SLJIT_R0), 4 * sizeof(sljit_f64)); if (supported[0] == SLJIT_SUCCESS) { + /* dbuf[1] */ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_S1, 0, SLJIT_IMM, 4 * sizeof(sljit_f64)); - sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_PRE, SLJIT_FR0, SLJIT_MEM1(SLJIT_R0), 4 * sizeof(sljit_f64)); + sljit_emit_fmem_update(compiler, SLJIT_MOV_F64, SLJIT_FR0, SLJIT_MEM1(SLJIT_R0), 4 * sizeof(sljit_f64)); sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f64), SLJIT_FR0, 0); + /* wbuf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); } - supported[1] = sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_POST, SLJIT_FR2, SLJIT_MEM1(SLJIT_R0), -(sljit_sw)sizeof(sljit_f64)); + supported[1] = sljit_emit_fmem_update(compiler, SLJIT_MOV_F64 | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_POST, SLJIT_FR2, SLJIT_MEM1(SLJIT_R0), -(sljit_sw)sizeof(sljit_f64)); if (supported[1] == SLJIT_SUCCESS) { + /* dbuf[2] */ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S1, 0, SLJIT_IMM, 2 * sizeof(sljit_f64)); sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S1), 0); - sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_STORE | SLJIT_MEM_POST, SLJIT_FR2, SLJIT_MEM1(SLJIT_R0), -(sljit_sw)sizeof(sljit_f64)); + sljit_emit_fmem_update(compiler, SLJIT_MOV_F64 | SLJIT_MEM_STORE | SLJIT_MEM_POST, SLJIT_FR2, SLJIT_MEM1(SLJIT_R0), -(sljit_sw)sizeof(sljit_f64)); + /* wbuf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0); } - supported[2] = sljit_emit_fmem(compiler, SLJIT_MOV_F32 | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_FR1, SLJIT_MEM1(SLJIT_R2), -4 * (sljit_sw)sizeof(sljit_f32)); + supported[2] = sljit_emit_fmem_update(compiler, SLJIT_MOV_F32 | SLJIT_MEM_SUPP | SLJIT_MEM_STORE, SLJIT_FR1, SLJIT_MEM1(SLJIT_R2), -4 * (sljit_sw)sizeof(sljit_f32)); if (supported[2] == SLJIT_SUCCESS) { + /* sbuf[0] */ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S2, 0, SLJIT_IMM, 4 * sizeof(sljit_f32)); sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_f32)); - sljit_emit_fmem(compiler, SLJIT_MOV_F32 | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_FR1, SLJIT_MEM1(SLJIT_R2), -4 * (sljit_sw)sizeof(sljit_f32)); + sljit_emit_fmem_update(compiler, SLJIT_MOV_F32 | SLJIT_MEM_STORE, SLJIT_FR1, SLJIT_MEM1(SLJIT_R2), -4 * (sljit_sw)sizeof(sljit_f32)); + /* wbuf[2] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R2, 0); } - supported[3] = sljit_emit_fmem(compiler, SLJIT_MOV_F32 | SLJIT_MEM_SUPP | SLJIT_MEM_POST, SLJIT_FR1, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_f32)); + supported[3] = sljit_emit_fmem_update(compiler, SLJIT_MOV_F32 | SLJIT_MEM_SUPP | SLJIT_MEM_POST, SLJIT_FR1, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_f32)); if (supported[3] == SLJIT_SUCCESS) { + /* sbuf[2] */ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S2, 0, SLJIT_IMM, sizeof(sljit_f32)); - sljit_emit_fmem(compiler, SLJIT_MOV_F32 | SLJIT_MEM_POST, SLJIT_FR1, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_f32)); + sljit_emit_fmem_update(compiler, SLJIT_MOV_F32 | SLJIT_MEM_POST, SLJIT_FR1, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_f32)); sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S2), 2 * sizeof(sljit_f32), SLJIT_FR1, 0); + /* wbuf[3] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R1, 0); } - supported[4] = sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_FR0, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0); + supported[4] = sljit_emit_fmem_update(compiler, SLJIT_MOV_F64 | SLJIT_MEM_SUPP, SLJIT_FR0, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0); if (supported[4] == SLJIT_SUCCESS) { + /* dbuf[3] */ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S1, 0, SLJIT_IMM, 8 * sizeof(sljit_f64)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -8 * (sljit_sw)sizeof(sljit_f64)); - sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_PRE, SLJIT_FR0, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0); + sljit_emit_fmem_update(compiler, SLJIT_MOV_F64, SLJIT_FR0, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0); sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_f64), SLJIT_FR0, 0); + /* wbuf[4] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R1, 0); } - supported[5] = sljit_emit_fmem(compiler, SLJIT_MOV_F32 | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_FR2, SLJIT_MEM2(SLJIT_R2, SLJIT_R1), 0); + supported[5] = sljit_emit_fmem_update(compiler, SLJIT_MOV_F32 | SLJIT_MEM_SUPP | SLJIT_MEM_STORE, SLJIT_FR2, SLJIT_MEM2(SLJIT_R2, SLJIT_R1), 0); if (supported[5] == SLJIT_SUCCESS) { + /* sbuf[3] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_S2, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 3 * sizeof(sljit_f32)); sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_f32)); - sljit_emit_fmem(compiler, SLJIT_MOV_F32 | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_FR2, SLJIT_MEM2(SLJIT_R2, SLJIT_R1), 0); + sljit_emit_fmem_update(compiler, SLJIT_MOV_F32 | SLJIT_MEM_STORE, SLJIT_FR2, SLJIT_MEM2(SLJIT_R2, SLJIT_R1), 0); + /* wbuf[5] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R2, 0); } - SLJIT_ASSERT(sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_SUPP | SLJIT_MEM_POST, SLJIT_FR0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0) == SLJIT_ERR_UNSUPPORTED); - SLJIT_ASSERT(sljit_emit_fmem(compiler, SLJIT_MOV_F32 | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_POST, SLJIT_FR0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0) == SLJIT_ERR_UNSUPPORTED); + SLJIT_ASSERT(sljit_emit_fmem_update(compiler, SLJIT_MOV_F64 | SLJIT_MEM_SUPP | SLJIT_MEM_POST, SLJIT_FR0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0) == SLJIT_ERR_UNSUPPORTED); + SLJIT_ASSERT(sljit_emit_fmem_update(compiler, SLJIT_MOV_F32 | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_POST, SLJIT_FR0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0) == SLJIT_ERR_UNSUPPORTED); #if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) /* TODO: at least for ARM (both V5 and V7) the range below needs further fixing */ - SLJIT_ASSERT(sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_FR0, SLJIT_MEM1(SLJIT_R0), 256) == SLJIT_ERR_UNSUPPORTED); - SLJIT_ASSERT(sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_SUPP | SLJIT_MEM_POST, SLJIT_FR0, SLJIT_MEM1(SLJIT_R0), -257) == SLJIT_ERR_UNSUPPORTED); + SLJIT_ASSERT(sljit_emit_fmem_update(compiler, SLJIT_MOV_F64 | SLJIT_MEM_SUPP, SLJIT_FR0, SLJIT_MEM1(SLJIT_R0), 256) == SLJIT_ERR_UNSUPPORTED); + SLJIT_ASSERT(sljit_emit_fmem_update(compiler, SLJIT_MOV_F64 | SLJIT_MEM_SUPP | SLJIT_MEM_POST, SLJIT_FR0, SLJIT_MEM1(SLJIT_R0), -257) == SLJIT_ERR_UNSUPPORTED); #endif sljit_emit_return_void(compiler); @@ -6253,7 +6675,7 @@ static void test62(void) FAILED(!compiler, "cannot create compiler\n"); sljit_set_context(compiler, 0, SLJIT_ARGS1(W, W), 1, 1, 0, 0, 0); - sljit_emit_fast_enter(compiler, SLJIT_R0, 0); + sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_R0, 0); sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, SLJIT_S0, 0, SLJIT_IMM, 42); sljit_emit_op_src(compiler, SLJIT_FAST_RETURN, SLJIT_R0, 0); @@ -6313,6 +6735,7 @@ static void test63(void) sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 1, 0, 0, 2 * sizeof(sljit_sw)); + /* buf[0-1] */ put_label[0] = sljit_emit_put_label(compiler, SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); @@ -6323,6 +6746,7 @@ static void test63(void) sljit_set_put_label(put_label[0], label[0]); sljit_set_put_label(put_label[1], label[0]); + /* buf[2-3] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)(buf + 2) - offs); put_label[2] = sljit_emit_put_label(compiler, SLJIT_MEM1(SLJIT_R0), offs); @@ -6333,6 +6757,7 @@ static void test63(void) sljit_set_put_label(put_label[2], label[1]); sljit_set_put_label(put_label[3], label[1]); + /* Return value */ put_label[4] = sljit_emit_put_label(compiler, SLJIT_RETURN_REG, 0); sljit_set_put_label(put_label[4], label[0]); sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); @@ -6422,36 +6847,44 @@ static void test64(void) sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 1, 0, 0, 2 * sizeof(sljit_sw)); + /* buf[0] */ put_label[0] = sljit_emit_put_label(compiler, SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); + /* buf[1] */ put_label[1] = sljit_emit_put_label(compiler, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_uw)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_uw), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_uw)); sljit_set_put_label(put_label[0], &label[0]); sljit_set_put_label(put_label[1], &label[0]); + /* buf[2] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)(buf + 2) - offs1); put_label[0] = sljit_emit_put_label(compiler, SLJIT_MEM1(SLJIT_R0), offs1); + /* buf[3] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (offs1 + (sljit_sw)sizeof(sljit_uw)) >> 1); put_label[1] = sljit_emit_put_label(compiler, SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 1); sljit_set_put_label(put_label[0], &label[1]); sljit_set_put_label(put_label[1], &label[1]); + /* buf[4] */ put_label[0] = sljit_emit_put_label(compiler, SLJIT_R1, 0); sljit_set_put_label(put_label[0], &label[2]); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_uw), SLJIT_R1, 0); + /* buf[5] */ put_label[0] = sljit_emit_put_label(compiler, SLJIT_R2, 0); sljit_set_put_label(put_label[0], &label[3]); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_uw), SLJIT_R2, 0); + /* buf[6] */ put_label[0] = sljit_emit_put_label(compiler, SLJIT_R1, 0); sljit_set_put_label(put_label[0], &label[4]); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_uw), SLJIT_R1, 0); + /* buf[7] */ put_label[0] = sljit_emit_put_label(compiler, SLJIT_RETURN_REG, 0); sljit_set_put_label(put_label[0], &label[5]); sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); @@ -6590,7 +7023,7 @@ static void test67(void) /* First function, never returns. */ label = sljit_emit_label(compiler); sljit_set_label(call, label); - sljit_emit_fast_enter(compiler, SLJIT_R1, 0); + sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_R1, 0); call = sljit_emit_jump(compiler, SLJIT_FAST_CALL); @@ -6599,7 +7032,7 @@ static void test67(void) /* Second function, skips the first function. */ sljit_set_label(call, sljit_emit_label(compiler)); - sljit_emit_fast_enter(compiler, SLJIT_R2, 0); + sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_R2, 0); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1); @@ -6653,7 +7086,7 @@ static void test68(void) /* Recursive fast call. */ label = sljit_emit_label(compiler); sljit_set_label(call, label); - sljit_emit_fast_enter(compiler, SLJIT_R1, 0); + sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_R1, 0); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1); @@ -6697,50 +7130,50 @@ static void test69(void) FAILED(!compiler, "cannot create compiler\n"); sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 3, 1, 0, 0, 0); - + /* buf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)1 << ((sizeof (sljit_sw) * 8) - 2)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_R0, 0); sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_R1, 0); sljit_emit_label(compiler); sljit_set_current_flags(compiler, SLJIT_SET_OVERFLOW | SLJIT_CURRENT_FLAGS_ADD); cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_OVERFLOW); - + /* buf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 5); sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_R1, 0); sljit_emit_label(compiler); sljit_set_current_flags(compiler, SLJIT_SET_OVERFLOW | SLJIT_CURRENT_FLAGS_ADD); cond_set(compiler, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_OVERFLOW); - + /* buf[2] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_R0, 0); sljit_emit_op2(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_R1, 0); sljit_emit_label(compiler); sljit_set_current_flags(compiler, SLJIT_SET_OVERFLOW); cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_OVERFLOW); - + /* buf[3] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 5); sljit_emit_op2(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_R1, 0); sljit_emit_label(compiler); sljit_set_current_flags(compiler, SLJIT_SET_OVERFLOW); cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_OVERFLOW); - + /* buf[4] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 6); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 5); sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_R1, 0, SLJIT_R2, 0); sljit_emit_label(compiler); sljit_set_current_flags(compiler, SLJIT_SET_GREATER | SLJIT_CURRENT_FLAGS_SUB | SLJIT_CURRENT_FLAGS_COMPARE); cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_GREATER); - + /* buf[5] */ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_R2, 0); sljit_emit_label(compiler); sljit_set_current_flags(compiler, SLJIT_SET_Z | SLJIT_CURRENT_FLAGS_SUB | SLJIT_CURRENT_FLAGS_COMPARE); cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_ZERO); - + /* buf[6] */ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)(1u << 31)); sljit_emit_op2u(compiler, SLJIT_ADD32 | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_R1, 0); sljit_emit_label(compiler); sljit_set_current_flags(compiler, SLJIT_SET_Z | SLJIT_CURRENT_FLAGS_32 | SLJIT_CURRENT_FLAGS_ADD); cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_ZERO); - + /* buf[7] */ sljit_emit_op2u(compiler, SLJIT_SHL32 | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_IMM, 1); sljit_emit_label(compiler); sljit_set_current_flags(compiler, SLJIT_SET_Z | SLJIT_CURRENT_FLAGS_32); @@ -7357,7 +7790,7 @@ static void test72(void) { /* Test using all fpu registers. */ executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); + struct sljit_compiler* compiler; sljit_f64 buf[SLJIT_NUMBER_OF_FLOAT_REGISTERS]; sljit_f64 buf2[2]; struct sljit_jump *jump; @@ -7370,12 +7803,10 @@ static void test72(void) if (verbose) printf("no fpu available, test72 skipped\n"); successful_tests++; - if (compiler) - sljit_free_compiler(compiler); return; } - /* Next test. */ + compiler = sljit_create_compiler(NULL, NULL); FAILED(!compiler, "cannot create compiler\n"); buf2[0] = 7.75; @@ -7498,11 +7929,15 @@ static void test73(void) FAILED(!compiler, "cannot create compiler\n"); sljit_emit_enter(compiler, 0, SLJIT_ARGS4(VOID, 32_R, W, W_R, 32), 3, 2, 0, 0, 0); + /* wbuf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&wbuf); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_S0, 0); + /* wbuf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw), SLJIT_R2, 0); + /* ibuf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&ibuf); sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0); + /* ibuf[1] */ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_s32), SLJIT_S1, 0); sljit_emit_return_void(compiler); @@ -7524,11 +7959,15 @@ static void test73(void) FAILED(!compiler, "cannot create compiler\n"); sljit_emit_enter(compiler, 0, SLJIT_ARGS4(VOID, 32, W_R, W, 32_R), 4, 2, 0, 0, 8192); + /* wbuf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&wbuf); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_R1, 0); + /* wbuf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_sw), SLJIT_S1, 0); + /* ibuf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&ibuf); sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_S0, 0); + /* ibuf[1] */ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_s32), SLJIT_R3, 0); sljit_emit_return_void(compiler); @@ -7550,11 +7989,15 @@ static void test73(void) FAILED(!compiler, "cannot create compiler\n"); sljit_emit_enter(compiler, 0, SLJIT_ARGS4(VOID, 32_R, W_R, W_R, 32_R), 4, 1, 0, 0, SLJIT_MAX_LOCAL_SIZE); + /* wbuf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, (sljit_sw)&wbuf); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R1, 0); + /* wbuf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R2, 0); + /* ibuf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, (sljit_sw)&ibuf); sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); + /* ibuf[1] */ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_s32), SLJIT_R3, 0); sljit_emit_return_void(compiler); @@ -7577,11 +8020,15 @@ static void test73(void) sljit_emit_enter(compiler, 0, SLJIT_ARGS4(VOID, W_R, W_R, 32_R, 32_R), 4, 1, 0, 0, SLJIT_MAX_LOCAL_SIZE); sljit_set_context(compiler, 0, SLJIT_ARGS4(VOID, W_R, W_R, 32_R, 32_R), 4, 1, 0, 0, SLJIT_MAX_LOCAL_SIZE); + /* wbuf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, (sljit_sw)&wbuf); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); + /* wbuf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R1, 0); + /* ibuf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, (sljit_sw)&ibuf); sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R2, 0); + /* ibuf[1] */ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_s32), SLJIT_R3, 0); sljit_emit_return_void(compiler); @@ -7604,10 +8051,14 @@ static void test73(void) FAILED(!compiler, "cannot create compiler\n"); sljit_emit_enter(compiler, 0, SLJIT_ARGS4(VOID, F64, F64, F64, W_R), 1, 0, 3, 0, SLJIT_MAX_LOCAL_SIZE); + /* wbuf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)&wbuf, SLJIT_R0, 0); + /* dbuf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&dbuf); sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_FR0, 0); + /* dbuf[1] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64), SLJIT_FR1, 0); + /* dbuf[2] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 2 * sizeof(sljit_f64), SLJIT_FR2, 0); sljit_emit_return_void(compiler); @@ -7629,11 +8080,15 @@ static void test73(void) FAILED(!compiler, "cannot create compiler\n"); sljit_emit_enter(compiler, 0, SLJIT_ARGS4(VOID, F64, F64, W, W_R), 2, 1, 2, 0, SLJIT_MAX_LOCAL_SIZE); + /* wbuf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&wbuf); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_S0, 0); + /* wbuf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_sw), SLJIT_R1, 0); + /* dbuf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&dbuf); sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_FR0, 0); + /* dbuf[1] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64), SLJIT_FR1, 0); sljit_emit_return_void(compiler); @@ -7802,7 +8257,7 @@ static void test75_set(struct sljit_compiler *compiler, sljit_s32 compare, sljit sljit_s32 is_ordered; if (sljit_cmp_info(type)) { - sljit_emit_fop1(compiler, compare | SLJIT_SET(type), left_fr, 0, right_fr, 0); + sljit_emit_fop1(compiler, compare | SLJIT_SET(type & 0xfe), left_fr, 0, right_fr, 0); sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_R0, 0, type); jump1 = sljit_emit_jump(compiler, type); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 2); @@ -7817,7 +8272,7 @@ static void test75_set(struct sljit_compiler *compiler, sljit_s32 compare, sljit } SLJIT_ASSERT(sljit_cmp_info(type) && sljit_cmp_info(SLJIT_UNORDERED) && sljit_cmp_info(SLJIT_ORDERED)); - sljit_emit_fop1(compiler, compare | SLJIT_SET(type), left_fr, 0, right_fr, 0); + sljit_emit_fop1(compiler, compare | SLJIT_SET(type & 0xfe), left_fr, 0, right_fr, 0); sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_R0, 0, type); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0); @@ -7871,15 +8326,6 @@ static void test75(void) sljit_s32 value1; } sbuf[3]; - dbuf[0].u.value1 = 0x7fffffff; - dbuf[0].u.value2 = 0x7fffffff; - dbuf[1].value = -13.0; - dbuf[2].value = 27.0; - - sbuf[0].value1 = 0x7fffffff; - sbuf[1].value = -13.0; - sbuf[2].value = 27.0; - if (verbose) printf("Run test75\n"); @@ -7890,12 +8336,21 @@ static void test75(void) return; } - for (i = 0; i < 96; i++) - bbuf[i] = -3; - compiler = sljit_create_compiler(NULL, NULL); FAILED(!compiler, "cannot create compiler\n"); + dbuf[0].u.value1 = 0x7fffffff; + dbuf[0].u.value2 = 0x7fffffff; + dbuf[1].value = -13.0; + dbuf[2].value = 27.0; + + sbuf[0].value1 = 0x7fffffff; + sbuf[1].value = -13.0; + sbuf[2].value = 27.0; + + for (i = 0; i < 96; i++) + bbuf[i] = -3; + sljit_emit_enter(compiler, 0, SLJIT_ARGS3(VOID, P, P, P), 3, 3, 6, 0, 0); i = SLJIT_CMP_F64; @@ -8171,7 +8626,6 @@ static void test76(void) if (verbose) printf("Run test76\n"); - /* Next test. */ for (i = 0; i < 9; i++) buf[i] = -1; @@ -8191,8 +8645,11 @@ static void test76(void) jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS4(W, W, W, W, W)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&buf); + /* buf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0); + /* buf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw), SLJIT_S0, 0); + /* buf[2] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(sljit_sw), SLJIT_S1, 0); sljit_emit_return_void(compiler); @@ -8200,6 +8657,7 @@ static void test76(void) sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG, SLJIT_ARGS4(W, W_R, W_R, W_R, W_R), 4, 2, 0, 0, 32); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, (sljit_sw)&buf); + /* buf[3-6] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R1, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R2, 0); @@ -8246,8 +8704,11 @@ static void test76(void) jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS4(W, W, W, W, W)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&buf); + /* buf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0); + /* buf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw), SLJIT_S0, 0); + /* buf[2] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(sljit_sw), SLJIT_S1, 0); sljit_emit_return_void(compiler); @@ -8256,6 +8717,7 @@ static void test76(void) sljit_set_context(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(1), SLJIT_ARGS4(W, W_R, W_R, W_R, W_R), 6, 2, 0, 0, SLJIT_MAX_LOCAL_SIZE); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, (sljit_sw)&buf); + /* buf[3-7] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_sw), SLJIT_S0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_sw), SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_sw), SLJIT_R1, 0); @@ -8305,7 +8767,9 @@ static void test76(void) jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS4(VOID, W, W, W, W)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf); + /* buf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_S0, 0); + /* buf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_sw), SLJIT_S1, 0); sljit_emit_return_void(compiler); @@ -8313,6 +8777,7 @@ static void test76(void) sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(2), SLJIT_ARGS4(W, W_R, W_R, W_R, W_R), 4, 3, 0, 0, SLJIT_MAX_LOCAL_SIZE); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, (sljit_sw)&buf); + /* buf[2-7] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 2 * sizeof(sljit_sw), SLJIT_S0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 3 * sizeof(sljit_sw), SLJIT_S1, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 4 * sizeof(sljit_sw), SLJIT_R0, 0); @@ -8358,9 +8823,13 @@ static void test76(void) jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS0(W)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&buf); + /* buf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0); + /* buf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw), SLJIT_S0, 0); + /* buf[2] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(sljit_sw), SLJIT_S1, 0); + /* buf[3] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 3 * sizeof(sljit_sw), SLJIT_S2, 0); sljit_emit_return_void(compiler); @@ -8368,7 +8837,9 @@ static void test76(void) sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(2), SLJIT_ARGS0(W), 4, 3, 0, 0, SLJIT_MAX_LOCAL_SIZE); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf); + /* buf[4] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 4 * sizeof(sljit_sw), SLJIT_S0, 0); + /* buf[5] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 5 * sizeof(sljit_sw), SLJIT_S1, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -6278); @@ -8387,9 +8858,12 @@ static void test76(void) sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG, SLJIT_ARGS4(W, W_R, W_R, W_R, W_R), 4, 2, 0, 0, 256); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, (sljit_sw)&buf); + /* buf[6] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R0, 0); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_R1, 0); + /* buf[7] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R2, 0); + /* buf[8] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R3, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, -1); @@ -8428,8 +8902,11 @@ static void test76(void) sljit_emit_enter(compiler, 0, SLJIT_ARGS0(VOID), 2, 3, 3, 0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&dbuf); + /* dbuf[0] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_R1), 0); + /* dbuf[1] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_f64)); + /* dbuf[2] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(sljit_f64)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1706); @@ -8440,9 +8917,13 @@ static void test76(void) jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS4(W, F64, F64, F64, W)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&buf); + /* buf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0); + /* buf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw), SLJIT_S0, 0); + /* buf[2] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(sljit_sw), SLJIT_S1, 0); + /* buf[3] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 3 * sizeof(sljit_sw), SLJIT_S2, 0); sljit_emit_return_void(compiler); @@ -8450,12 +8931,17 @@ static void test76(void) sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(1), SLJIT_ARGS4(W, F64, F64, F64, W_R), 1, 3, 3, 0, SLJIT_MAX_LOCAL_SIZE); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, (sljit_sw)&buf); + /* buf[4] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_sw), SLJIT_S0, 0); + /* buf[5] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_sw), SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, (sljit_sw)&dbuf); + /* dbuf[0] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_FR2, 0); + /* dbuf[1] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f64), SLJIT_FR0, 0); + /* dbuf[2] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_f64), SLJIT_FR1, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2784); @@ -8506,8 +8992,11 @@ static void test76(void) jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS4(VOID, F64, W, W, W)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf); + /* buf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_S0, 0); + /* buf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_sw), SLJIT_S1, 0); + /* buf[2] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 2 * sizeof(sljit_sw), SLJIT_S2, 0); sljit_emit_return_void(compiler); @@ -8515,10 +9004,15 @@ static void test76(void) sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(2), SLJIT_ARGS4(VOID, F64, W_R, W_R, W_R), 3, 3, 3, 0, SLJIT_MAX_LOCAL_SIZE); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, (sljit_sw)&buf); + /* buf[3] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 3 * sizeof(sljit_sw), SLJIT_S0, 0); + /* buf[4] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 4 * sizeof(sljit_sw), SLJIT_S1, 0); + /* buf[5] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 5 * sizeof(sljit_sw), SLJIT_R0, 0); + /* buf[6] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 6 * sizeof(sljit_sw), SLJIT_R1, 0); + /* buf[7] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 7 * sizeof(sljit_sw), SLJIT_R2, 0); sljit_emit_fop1(compiler, SLJIT_NEG_F64, SLJIT_MEM0(), (sljit_sw)&dbuf, SLJIT_FR0, 0); @@ -8567,9 +9061,13 @@ static void test76(void) jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS0(W)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&buf); + /* buf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0); + /* buf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw), SLJIT_S0, 0); + /* buf[2] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(sljit_sw), SLJIT_S1, 0); + /* buf[3] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 3 * sizeof(sljit_sw), SLJIT_S2, 0); sljit_emit_return_void(compiler); @@ -8577,12 +9075,17 @@ static void test76(void) sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(2), SLJIT_ARGS0(W), 1, 3, 3, 0, SLJIT_MAX_LOCAL_SIZE); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf); + /* buf[4] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 4 * sizeof(sljit_sw), SLJIT_S0, 0); + /* buf[5] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 5 * sizeof(sljit_sw), SLJIT_S1, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&dbuf); + /* dbuf[0] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_R0), 0); + /* dbuf[1] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64)); + /* dbuf[2] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_R0), 2 * sizeof(sljit_f64)); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1706); @@ -8597,11 +9100,15 @@ static void test76(void) sljit_set_label(jump, sljit_emit_label(compiler)); sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG, SLJIT_ARGS4(W, F64, F64, F64, W_R), 1, 0, 3, 0, 256); + /* buf[6] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)&buf[6], SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&dbuf); + /* dbuf[0] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_FR2, 0); + /* dbuf[1] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64), SLJIT_FR0, 0); + /* dbuf[2] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 2 * sizeof(sljit_f64), SLJIT_FR1, 0); sljit_emit_return(compiler, SLJIT_MOV, SLJIT_IMM, 5074); @@ -8755,31 +9262,31 @@ static void test77(void) #endif /* SLJIT_UNALIGNED */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 18 >> 1); - sljit_emit_mem(compiler, SLJIT_MOV_S32 | SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16, SLJIT_R0, SLJIT_MEM2(SLJIT_S1, SLJIT_R1), 1); + sljit_emit_mem(compiler, SLJIT_MOV_S32 | SLJIT_MEM_UNALIGNED_16, SLJIT_R0, SLJIT_MEM2(SLJIT_S1, SLJIT_R1), 1); /* wbuf[8] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_MEM0(), (sljit_sw)&ibuf); /* bbuf[18] */ - sljit_emit_mem(compiler, SLJIT_MOV_S32 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16, SLJIT_R0, SLJIT_MEM2(SLJIT_S1, SLJIT_R1), 1); + sljit_emit_mem(compiler, SLJIT_MOV_S32 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED_16, SLJIT_R0, SLJIT_MEM2(SLJIT_S1, SLJIT_R1), 1); - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16, SLJIT_R0, SLJIT_MEM0(), (sljit_sw)bbuf + 22); + sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_UNALIGNED_16, SLJIT_R0, SLJIT_MEM0(), (sljit_sw)bbuf + 22); /* wbuf[9] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), 0); /* bbuf[22] */ - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16, SLJIT_R0, SLJIT_MEM0(), (sljit_sw)bbuf + 22); + sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED_16, SLJIT_R0, SLJIT_MEM0(), (sljit_sw)bbuf + 22); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S1, 0, SLJIT_IMM, 128); - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_32, SLJIT_R0, SLJIT_MEM1(SLJIT_R0), -128 + 32); + sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_UNALIGNED_32, SLJIT_R0, SLJIT_MEM1(SLJIT_R0), -128 + 32); /* wbuf[10] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_R0, 0); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S1, 0, SLJIT_IMM, 128); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), 0); /* bbuf[32] */ - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_32, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), -128 + 32); + sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED_32, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), -128 + 32); sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_UNALIGNED, SLJIT_R0, SLJIT_MEM1(SLJIT_S0), 0); /* wbuf[11] */ @@ -8869,35 +9376,35 @@ static void test77(void) sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED, SLJIT_FR0, SLJIT_MEM1(SLJIT_R0), 100000 + 5); #endif /* SLJIT_FPU_UNALIGNED */ - sljit_emit_fmem(compiler, SLJIT_MOV_F32 | SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16, SLJIT_FR0, SLJIT_MEM1(SLJIT_S2), 14); + sljit_emit_fmem(compiler, SLJIT_MOV_F32 | SLJIT_MEM_UNALIGNED_16, SLJIT_FR0, SLJIT_MEM1(SLJIT_S2), 14); /* sbuf[2] */ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_f32), SLJIT_FR0, 0); sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S1), 0); /* bbuf[14] */ - sljit_emit_fmem(compiler, SLJIT_MOV_F32 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16, SLJIT_FR0, SLJIT_MEM1(SLJIT_S2), 14); + sljit_emit_fmem(compiler, SLJIT_MOV_F32 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED_16, SLJIT_FR0, SLJIT_MEM1(SLJIT_S2), 14); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 18 >> 1); - sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16, SLJIT_FR0, SLJIT_MEM2(SLJIT_S2, SLJIT_R0), 1); + sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_UNALIGNED_16, SLJIT_FR0, SLJIT_MEM2(SLJIT_S2, SLJIT_R0), 1); /* dbuf[2] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f64), SLJIT_FR0, 0); sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), 0); /* bbuf[18] */ - sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16, SLJIT_FR0, SLJIT_MEM2(SLJIT_S2, SLJIT_R0), 1); + sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED_16, SLJIT_FR0, SLJIT_MEM2(SLJIT_S2, SLJIT_R0), 1); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S2, 0, SLJIT_IMM, 128); - sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_32, SLJIT_FR0, SLJIT_MEM1(SLJIT_R0), -128 + 28); + sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_UNALIGNED_32, SLJIT_FR0, SLJIT_MEM1(SLJIT_R0), -128 + 28); /* dbuf[3] */ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_f64), SLJIT_FR0, 0); sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), 0); /* bbuf[28] */ - sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_32, SLJIT_FR0, SLJIT_MEM1(SLJIT_R0), -128 + 28); + sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED_32, SLJIT_FR0, SLJIT_MEM1(SLJIT_R0), -128 + 28); - sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_32, SLJIT_FR0, SLJIT_MEM1(SLJIT_S0), 0); + sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_UNALIGNED_32, SLJIT_FR0, SLJIT_MEM1(SLJIT_S0), 0); /* dbuf[4] */ - sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_32, SLJIT_FR0, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_f64)); + sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED_32, SLJIT_FR0, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_f64)); sljit_emit_return_void(compiler); @@ -8951,8 +9458,11 @@ static void test78(void) sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)(buf + 6), SLJIT_R0, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf); + /* buf[3] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 3 * sizeof(sljit_sw), SLJIT_S0, 0); + /* buf[4] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 4 * sizeof(sljit_sw), SLJIT_S1, 0); + /* buf[5] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 5 * sizeof(sljit_sw), SLJIT_S2, 0); for (i = 1; i < SLJIT_NUMBER_OF_REGISTERS - 3; i++) @@ -8964,8 +9474,11 @@ static void test78(void) sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(3), SLJIT_ARGS4(VOID, W_R, W_R, W_R, W_R), 4, 3, 0, 0, SLJIT_MAX_LOCAL_SIZE); sljit_set_context(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(3), SLJIT_ARGS4(VOID, W_R, W_R, W_R, W_R), 4, 3, 0, 0, SLJIT_MAX_LOCAL_SIZE); + /* buf[0] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)(buf + 0), SLJIT_S0, 0); + /* buf[1] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)(buf + 1), SLJIT_S1, 0); + /* buf[2] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)(buf + 2), SLJIT_S2, 0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 6501); @@ -9002,7 +9515,6 @@ static void test78(void) static void test79(void) { -#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) || (defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) /* Test register pair movement. */ executable_code code; struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); @@ -9042,7 +9554,7 @@ static void test79(void) sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 5814); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 7201); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S0, 0, SLJIT_IMM, 6 * sizeof(sljit_sw) + 77); - /* buf[6], buf[7] */ + /* buf[6-7] */ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE, SLJIT_REG_PAIR(SLJIT_R0, SLJIT_R1), SLJIT_MEM1(SLJIT_R2), -77); sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 36); @@ -9094,12 +9606,12 @@ static void test79(void) sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 3065); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, 7481); sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S2, 0, SLJIT_S0, 0, SLJIT_IMM, 0x7f7f0 + 20 * sizeof(sljit_sw)); - /* buf[20], buf[21] */ + /* buf[20-21] */ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE, SLJIT_REG_PAIR(SLJIT_R3, SLJIT_R4), SLJIT_MEM1(SLJIT_S2), -0x7f7f0); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 3275); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, -8714); - /* buf[22], buf[23] */ + /* buf[22-23] */ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE, SLJIT_REG_PAIR(SLJIT_S1, SLJIT_S3), SLJIT_MEM0(), (sljit_sw)(buf + 22)); sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_LOAD | SLJIT_MEM_UNALIGNED, SLJIT_REG_PAIR(SLJIT_R0, SLJIT_R1), SLJIT_MEM0(), (sljit_sw)bbuf + 1); @@ -9112,10 +9624,10 @@ static void test79(void) sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S4, 0, SLJIT_IMM, -9035); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)bbuf + 18 - 0x7f0f); /* bbuf[18], buf[18] + sizeof(sljit_sw) */ - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16, SLJIT_REG_PAIR(SLJIT_R4, SLJIT_S4), SLJIT_MEM1(SLJIT_R0), 0x7f0f); + sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED_16, SLJIT_REG_PAIR(SLJIT_R4, SLJIT_S4), SLJIT_MEM1(SLJIT_R0), 0x7f0f); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, (sljit_sw)bbuf + 34 - 0xfff); - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_LOAD | SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16, SLJIT_REG_PAIR(SLJIT_S1, SLJIT_R0), SLJIT_MEM1(SLJIT_S1), 0xfff); + sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_LOAD | SLJIT_MEM_UNALIGNED_16, SLJIT_REG_PAIR(SLJIT_S1, SLJIT_R0), SLJIT_MEM1(SLJIT_S1), 0xfff); /* buf[26] */ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 26 * sizeof(sljit_sw), SLJIT_S1, 0); /* buf[27] */ @@ -9138,7 +9650,7 @@ static void test79(void) sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, (sljit_sw)bbuf + 50 + 0xfff); sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -9035); /* bbuf[50], buf[50] + sizeof(sljit_sw) */ - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16, SLJIT_REG_PAIR(SLJIT_R2, SLJIT_R3), SLJIT_MEM1(SLJIT_R2), -0xfff); + sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED_16, SLJIT_REG_PAIR(SLJIT_R2, SLJIT_R3), SLJIT_MEM1(SLJIT_R2), -0xfff); sljit_emit_return_void(compiler); @@ -9184,7 +9696,1406 @@ static void test79(void) FAILED(buf[32] != -1, "test79 case 33 failed\n"); sljit_free_code(code.code, NULL); -#endif /* SLJIT_CONFIG_X86 || SLJIT_CONFIG_ARM */ + successful_tests++; +} + +static void test80(void) +{ + /* Test masked shift. */ + executable_code code; + struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); + sljit_sw buf[8]; + sljit_s32 ibuf[8]; + sljit_s32 i; + + if (verbose) + printf("Run test80\n"); + + FAILED(!compiler, "cannot create compiler\n"); + + for (i = 0; i < 8; i++) + buf[i] = -1; + for (i = 0; i < 8; i++) + ibuf[i] = -1; + + sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, W, W), 5, 5, 0, 0, 2 * sizeof(sljit_sw)); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x1234); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 8 * sizeof(sljit_sw) + 4); + sljit_emit_op2(compiler, SLJIT_MSHL, SLJIT_R2, 0, SLJIT_R0, 0, SLJIT_R1, 0); + /* buf[0] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R2, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, 8 * sizeof(sljit_sw)); + /* buf[1] */ + sljit_emit_op2(compiler, SLJIT_MSHL, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0, SLJIT_MEM1(SLJIT_SP), 0); + + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0x5678); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 32 + 8); + sljit_emit_op2(compiler, SLJIT_MSHL32, SLJIT_R2, 0, SLJIT_R0, 0, SLJIT_R1, 0); + /* ibuf[0] */ + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_R2, 0); + + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R3, 0, SLJIT_IMM, 1); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, -2); + /* ibuf[1] */ + sljit_emit_op2(compiler, SLJIT_MSHL32 | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32), SLJIT_R3, 0, SLJIT_R4, 0); + /* buf[2] */ + sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_NOT_ZERO); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -1); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 8 * sizeof(sljit_sw) + 4); + sljit_emit_op2(compiler, SLJIT_MLSHR | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_R2, 0); + /* buf[3] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R0, 0); + /* buf[4] */ + sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_NOT_ZERO); + + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, 0x5678); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), SLJIT_IMM, -32); + sljit_emit_op2(compiler, SLJIT_MLSHR32, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32)); + /* ibuf[2] */ + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_s32), SLJIT_MEM1(SLJIT_SP), 0); + + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0x345678); + sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_S1, 0, SLJIT_IMM, 0x123000 - 3 * sizeof(sljit_s32)); + /* ibuf[3] */ + sljit_emit_op2(compiler, SLJIT_MLSHR32, SLJIT_MEM1(SLJIT_R1), 0x123000, SLJIT_R0, 0, SLJIT_IMM, 32 + 4); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -0x100); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 8 * sizeof(sljit_sw) + 4); + sljit_emit_op2(compiler, SLJIT_MASHR, SLJIT_R1, 0, SLJIT_R3, 0, SLJIT_R2, 0); + /* buf[5] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R1, 0); + + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), SLJIT_IMM, -0x100); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R2, 0, SLJIT_IMM, -32 + 1); + sljit_emit_op2(compiler, SLJIT_MASHR32, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), SLJIT_R2, 0); + /* ibuf[4] */ + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_s32), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32)); + + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_s32), SLJIT_IMM, 0x7fffffff); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, -1); + /* ibuf[5] */ + sljit_emit_op2(compiler, SLJIT_MLSHR32 | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_s32), SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_s32), SLJIT_R0, 0); + /* buf[6] */ + sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_NOT_ZERO); + +#if (defined SLJIT_MASKED_SHIFT && SLJIT_MASKED_SHIFT) + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 12344321); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, (8 * sizeof(sljit_sw)) + 1); + /* buf[7] */ + sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R1, 0, SLJIT_R2, 0); +#endif /* SLJIT_MASKED_SHIFT */ +#if (defined SLJIT_MASKED_SHIFT32 && SLJIT_MASKED_SHIFT32) + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 24688643); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R2, 0, SLJIT_IMM, (8 * sizeof(sljit_s32)) + 1); + /* ibuf[6] */ + sljit_emit_op2(compiler, SLJIT_LSHR32, SLJIT_MEM1(SLJIT_S1), 6 * sizeof(sljit_s32), SLJIT_R1, 0, SLJIT_R2, 0); +#endif /* SLJIT_MASKED_SHIFT32 */ + + sljit_emit_return_void(compiler); + + code.code = sljit_generate_code(compiler); + CHECK(compiler); + sljit_free_compiler(compiler); + + code.func2((sljit_sw)buf, (sljit_sw)ibuf); + + FAILED(buf[0] != 0x12340, "test80 case 1 failed\n"); + FAILED(buf[1] != 0x1234, "test80 case 2 failed\n"); + FAILED(ibuf[0] != 0x567800, "test80 case 3 failed\n"); + FAILED(ibuf[1] != (sljit_sw)1 << 30, "test80 case 4 failed\n"); + FAILED(buf[2] != 1, "test80 case 5 failed\n"); + FAILED(buf[3] != ((sljit_uw)-1 >> 4), "test80 case 6 failed\n"); + FAILED(buf[4] != 1, "test80 case 7 failed\n"); + FAILED(ibuf[2] != 0x5678, "test80 case 8 failed\n"); + FAILED(ibuf[3] != 0x34567, "test80 case 9 failed\n"); + FAILED(buf[5] != -0x10, "test80 case 10 failed\n"); + FAILED(ibuf[4] != -0x80, "test80 case 11 failed\n"); + FAILED(ibuf[5] != 0, "test80 case 12 failed\n"); + FAILED(buf[6] != 0, "test80 case 13 failed\n"); +#if (defined SLJIT_MASKED_SHIFT && SLJIT_MASKED_SHIFT) + FAILED(buf[7] != 24688642, "test80 case 14 failed\n"); +#endif /* SLJIT_MASKED_SHIFT */ +#if (defined SLJIT_MASKED_SHIFT32 && SLJIT_MASKED_SHIFT32) + FAILED(ibuf[6] != 12344321, "test80 case 15 failed\n"); +#endif /* SLJIT_MASKED_SHIFT32 */ + + sljit_free_code(code.code, NULL); + successful_tests++; +} + +static void test81(void) +{ + /* Test return with floating point value. */ + executable_code code; + struct sljit_compiler* compiler; + struct sljit_jump* jump; + sljit_f64 dbuf[2]; + sljit_f32 sbuf[2]; + + if (verbose) + printf("Run test81\n"); + + if (!sljit_has_cpu_feature(SLJIT_HAS_FPU)) { + if (verbose) + printf("no fpu available, test81 skipped\n"); + successful_tests++; + return; + } + + /* Next test. */ + + compiler = sljit_create_compiler(NULL, NULL); + FAILED(!compiler, "cannot create compiler\n"); + + sljit_emit_enter(compiler, 0, SLJIT_ARGS1(F64, W), 0, 1, 3, 0, 0); + sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), 0); + sljit_emit_return(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0); + + code.code = sljit_generate_code(compiler); + CHECK(compiler); + sljit_free_compiler(compiler); + + dbuf[0] = 35.125; + FAILED(code.test81_f2((sljit_sw)dbuf) != 35.125, "test81 case 1 failed\n"); + + sljit_free_code(code.code, NULL); + + /* Next test. */ + + compiler = sljit_create_compiler(NULL, NULL); + FAILED(!compiler, "cannot create compiler\n"); + + sljit_emit_enter(compiler, 0, SLJIT_ARGS1(F32, W), 0, 1, 1, 0, 0); + sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_RETURN_FREG, 0, SLJIT_MEM1(SLJIT_S0), 0); + sljit_emit_return(compiler, SLJIT_MOV_F32, SLJIT_RETURN_FREG, 0); + + code.code = sljit_generate_code(compiler); + CHECK(compiler); + sljit_free_compiler(compiler); + + sbuf[0] = -9027.5; + FAILED(code.test81_f1((sljit_sw)sbuf) != -9027.5, "test81 case 2 failed\n"); + + sljit_free_code(code.code, NULL); + + /* Next test. */ + + compiler = sljit_create_compiler(NULL, NULL); + FAILED(!compiler, "cannot create compiler\n"); + + sljit_emit_enter(compiler, 0, SLJIT_ARGS1(F32, W), 0, 1, 1, 0, sizeof(sljit_f32)); + sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_S0), 0); + sljit_emit_return(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_SP), 0); + + code.code = sljit_generate_code(compiler); + CHECK(compiler); + sljit_free_compiler(compiler); + + sbuf[0] = -6.75; + FAILED(code.test81_f1((sljit_sw)sbuf) != -6.75, "test81 case 3 failed\n"); + + sljit_free_code(code.code, NULL); + + /* Next test. */ + + compiler = sljit_create_compiler(NULL, NULL); + FAILED(!compiler, "cannot create compiler\n"); + + sljit_emit_enter(compiler, 0, SLJIT_ARGS1(F64, W), 0, 1, 1, 0, 2 * sizeof(sljit_f64)); + sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_f64), SLJIT_MEM1(SLJIT_S0), 0); + sljit_emit_return(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_f64)); + + code.code = sljit_generate_code(compiler); + CHECK(compiler); + sljit_free_compiler(compiler); + + dbuf[0] = 45.125; + FAILED(code.test81_f2((sljit_sw)dbuf) != 45.125, "test81 case 4 failed\n"); + + sljit_free_code(code.code, NULL); + + /* Next test. */ + + compiler = sljit_create_compiler(NULL, NULL); + FAILED(!compiler, "cannot create compiler\n"); + + sljit_emit_enter(compiler, 0, SLJIT_ARGS0(VOID), 1, 0, 1, 0, 0); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)dbuf - 33); + jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS1(F64, W)); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)dbuf); + sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64), SLJIT_RETURN_FREG, 0); + sljit_emit_return_void(compiler); + + sljit_set_label(jump, sljit_emit_label(compiler)); + sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG, SLJIT_ARGS1(F64, W_R), 1, 0, 1, 0, 0); + sljit_emit_return(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 33); + + code.code = sljit_generate_code(compiler); + CHECK(compiler); + sljit_free_compiler(compiler); + + dbuf[0] = 2571.75; + dbuf[1] = 0; + code.func0(); + FAILED(dbuf[1] != 2571.75, "test81 case 5 failed\n"); + + sljit_free_code(code.code, NULL); + + /* Next test. */ + + compiler = sljit_create_compiler(NULL, NULL); + FAILED(!compiler, "cannot create compiler\n"); + + sljit_emit_enter(compiler, 0, SLJIT_ARGS0(VOID), 1, 0, 1, 0, 0); + jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS0(F32)); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)sbuf); + sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f32), SLJIT_RETURN_FREG, 0); + sljit_emit_return_void(compiler); + + sljit_set_label(jump, sljit_emit_label(compiler)); + sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG, SLJIT_ARGS0(F32), 0, 0, 1, 0, 0); + sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_RETURN_FREG, 0, SLJIT_MEM0(), (sljit_sw)sbuf); + sljit_emit_return(compiler, SLJIT_MOV_F32, SLJIT_RETURN_FREG, 0); + + code.code = sljit_generate_code(compiler); + CHECK(compiler); + sljit_free_compiler(compiler); + + sbuf[0] = 6310.25; + sbuf[1] = 0; + code.func0(); + FAILED(sbuf[1] != 6310.25, "test81 case 6 failed\n"); + + sljit_free_code(code.code, NULL); + + successful_tests++; +} + +static void test82(void) +{ + /* Test return_to operation. */ + executable_code code, code2; + struct sljit_compiler* compiler; + struct sljit_jump* jump; + struct sljit_label* label; + sljit_s32 i; + sljit_sw buf[3]; + + if (verbose) + printf("Run test82\n"); + + /* Next test. */ + + compiler = sljit_create_compiler(NULL, NULL); + FAILED(!compiler, "cannot create compiler\n"); + + sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 2, 1, 0, 0, 0); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -7602); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_S0, 0); + jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W)); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0); + label = sljit_emit_label(compiler); + /* buf[0] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_RETURN_REG, 0); + sljit_emit_op0(compiler, SLJIT_SKIP_FRAMES_BEFORE_RETURN); + sljit_emit_return_void(compiler); + + sljit_set_label(jump, sljit_emit_label(compiler)); + sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, W_R, W_R), 2, 0, 0, 0, 256); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, -1); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 256 - sizeof(sljit_sw), SLJIT_IMM, -1); + /* buf[1] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw), SLJIT_R0, 0); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 8945); + sljit_emit_return_to(compiler, SLJIT_MEM1(SLJIT_R1), 0); + + code.code = sljit_generate_code(compiler); + CHECK(compiler); + + buf[0] = (sljit_sw)sljit_get_label_addr(label); + buf[1] = 0; + + sljit_free_compiler(compiler); + + code.func1((sljit_sw)buf); + FAILED(buf[0] != 8945, "test82 case 1 failed\n"); + FAILED(buf[1] != -7602, "test82 case 2 failed\n"); + + sljit_free_code(code.code, NULL); + + /* Next test. */ + + for (i = 0; i < 3; i++) { + compiler = sljit_create_compiler(NULL, NULL); + FAILED(!compiler, "cannot create compiler\n"); + + sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 2, 1, 0, 0, 0); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 6032); + jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS1(W, W)); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0); + label = sljit_emit_label(compiler); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)buf); + /* buf[0] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_RETURN_REG, 0); + /* buf[2] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(sljit_sw), SLJIT_S0, 0); + sljit_emit_op0(compiler, SLJIT_SKIP_FRAMES_BEFORE_RETURN); + sljit_emit_return_void(compiler); + + sljit_set_label(jump, sljit_emit_label(compiler)); + sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(1), SLJIT_ARGS1(VOID, W_R), 2, i == 1 ? 2 : 1, 0, 0, SLJIT_MAX_LOCAL_SIZE); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, -1); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_R0, 0); + /* buf[1] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw)); + if (i == 2) + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 2 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), 0); + else + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S(i), 0, SLJIT_MEM1(SLJIT_S0), 0); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), SLJIT_MAX_LOCAL_SIZE - sizeof(sljit_sw), SLJIT_IMM, -1); + if (i != 0) + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, -3890); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 7145); + if (i == 2) + sljit_emit_return_to(compiler, SLJIT_MEM1(SLJIT_SP), 2 * sizeof(sljit_sw)); + else + sljit_emit_return_to(compiler, SLJIT_S(i), 0); + + code.code = sljit_generate_code(compiler); + CHECK(compiler); + + buf[0] = (sljit_sw)sljit_get_label_addr(label); + buf[1] = 0; + buf[2] = 0; + + sljit_free_compiler(compiler); + + code.func1((sljit_sw)buf); + FAILED(buf[0] != 7145, "test82 case 3 failed\n"); + FAILED(buf[1] != 6032, "test82 case 4 failed\n"); + if (i != 0) + FAILED(buf[2] != -3890, "test82 case 5 failed\n"); + + sljit_free_code(code.code, NULL); + } + + /* Next test. */ + + for (i = 0; i < 3; i++) { + compiler = sljit_create_compiler(NULL, NULL); + FAILED(!compiler, "cannot create compiler\n"); + + sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P_R), 2, 1, 0, 0, 0); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_R0, 0); + jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS1(W, W)); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0); + label = sljit_emit_label(compiler); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)buf); + /* buf[0] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_RETURN_REG, 0); + sljit_emit_op0(compiler, SLJIT_SKIP_FRAMES_BEFORE_RETURN); + sljit_emit_return_void(compiler); + + sljit_set_label(jump, sljit_emit_label(compiler)); + sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, W_R), 2, 1, 0, 0, (i == 0) ? 0 : (i == 1) ? 512 : 32768); + /* buf[1] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_sw), SLJIT_R0, 0); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, -1); + sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 0x1000); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, -4502); + sljit_emit_return_to(compiler, SLJIT_MEM1(SLJIT_R1), -0x1000); + + code.code = sljit_generate_code(compiler); + CHECK(compiler); + + buf[0] = (sljit_sw)sljit_get_label_addr(label); + buf[1] = 0; + + sljit_free_compiler(compiler); + + code.func1((sljit_sw)buf); + FAILED(buf[0] != -4502, "test82 case 6 failed\n"); + FAILED(buf[1] != (sljit_sw)buf, "test82 case 7 failed\n"); + + sljit_free_code(code.code, NULL); + } + + /* Next test. */ + + compiler = sljit_create_compiler(NULL, NULL); + FAILED(!compiler, "cannot create compiler\n"); + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + i = SLJIT_S2; +#else + i = SLJIT_S(SLJIT_NUMBER_OF_SAVED_REGISTERS - 1); +#endif + + sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 2, SLJIT_NUMBER_OF_SAVED_REGISTERS, 0, 0, 0); + sljit_emit_op1(compiler, SLJIT_MOV, i, 0, SLJIT_IMM, 2 * sizeof(sljit_sw)); + jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS0(W)); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0); + label = sljit_emit_label(compiler); + /* buf[2] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM2(SLJIT_S0, i), 0, SLJIT_RETURN_REG, 0); + sljit_emit_op0(compiler, SLJIT_SKIP_FRAMES_BEFORE_RETURN); + sljit_emit_return_void(compiler); + + sljit_set_label(jump, sljit_emit_label(compiler)); + sljit_emit_enter(compiler, 0, SLJIT_ARGS0(VOID), 2, SLJIT_NUMBER_OF_SAVED_REGISTERS, 0, 0, 16); + for (i = 0; i < SLJIT_NUMBER_OF_SAVED_REGISTERS; i++) + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S(i), 0, SLJIT_IMM, -1); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, (sljit_sw)(buf + 3)); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -3); + sljit_emit_return_to(compiler, SLJIT_MEM2(SLJIT_RETURN_REG, SLJIT_R1), SLJIT_WORD_SHIFT); + + code.code = sljit_generate_code(compiler); + CHECK(compiler); + + buf[0] = (sljit_sw)sljit_get_label_addr(label); + buf[1] = 0; + buf[2] = 0; + + sljit_free_compiler(compiler); + + code.func1((sljit_sw)buf); + FAILED(buf[2] != (sljit_sw)(buf + 3), "test82 case 8 failed\n"); + + sljit_free_code(code.code, NULL); + + /* Next test. */ + + compiler = sljit_create_compiler(NULL, NULL); + FAILED(!compiler, "cannot create compiler\n"); + + sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, P_R, P), 2, SLJIT_NUMBER_OF_SAVED_REGISTERS, 0, 0, 0); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_S0, 0); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 586000); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 392); + sljit_emit_icall(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS0(W), SLJIT_R0, 0); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0); + label = sljit_emit_label(compiler); + /* buf[0] */ + sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S2), 0, SLJIT_S0, 0, SLJIT_S1, 0); + /* buf[1] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_sw), SLJIT_RETURN_REG, 0); + sljit_emit_op0(compiler, SLJIT_SKIP_FRAMES_BEFORE_RETURN); + sljit_emit_return_void(compiler); + + code.code = sljit_generate_code(compiler); + CHECK(compiler); + + buf[0] = (sljit_sw)sljit_get_label_addr(label); + + sljit_free_compiler(compiler); + + compiler = sljit_create_compiler(NULL, NULL); + FAILED(!compiler, "cannot create compiler\n"); + + sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(2), SLJIT_ARGS0(VOID), 2, SLJIT_NUMBER_OF_SAVED_REGISTERS, 0, 0, 16); + for (i = 2; i < SLJIT_NUMBER_OF_SAVED_REGISTERS; i++) + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S(i), 0, SLJIT_IMM, -1); + /* buf[2] */ + sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM0(), (sljit_sw)(buf + 2), SLJIT_S0, 0, SLJIT_S1, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 416000); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 931); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 2906); + sljit_emit_return_to(compiler, SLJIT_IMM, buf[0]); + + code2.code = sljit_generate_code(compiler); + CHECK(compiler); + sljit_free_compiler(compiler); + + buf[0] = 0; + buf[1] = 0; + buf[2] = 0; + + code.func2(SLJIT_FUNC_ADDR(code2.func0), (sljit_sw)buf); + FAILED(buf[0] != 416931, "test82 case 9 failed\n"); + FAILED(buf[1] != 2906, "test82 case 10 failed\n"); + FAILED(buf[2] != 586392, "test82 case 11 failed\n"); + + sljit_free_code(code.code, NULL); + sljit_free_code(code2.code, NULL); + + successful_tests++; +} + +static void test83(void) +{ + /* Test rotate. */ + executable_code code; + struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); + sljit_sw buf[13]; + sljit_s32 ibuf[8]; + sljit_s32 i; +#ifdef SLJIT_PREF_SHIFT_REG + sljit_s32 shift_reg = SLJIT_PREF_SHIFT_REG; +#else + sljit_s32 shift_reg = SLJIT_R2; +#endif + + if (verbose) + printf("Run test83\n"); + + FAILED(!compiler, "cannot create compiler\n"); + + for (i = 0; i < 13; i++) + buf[i] = -1; + for (i = 0; i < 8; i++) + ibuf[i] = -1; + + ibuf[0] = 8; + + sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, W, W), 5, 5, 0, 0, 2 * sizeof(sljit_sw)); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0x1234567812345678, 0x12345678)); + sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 12); + sljit_emit_op2(compiler, SLJIT_ROTL, SLJIT_R0, 0, SLJIT_R0, 0, shift_reg, 0); + /* buf[0] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0xfedcba0987654321, 0x87654321)); + sljit_emit_op2(compiler, SLJIT_ROTL, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 1); + /* buf[1] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R1, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, WCONST(0xfedcba0987654321, 0x87654321)); + sljit_emit_op2(compiler, SLJIT_ROTL, SLJIT_S2, 0, SLJIT_R4, 0, SLJIT_IMM, 0xffff00); + /* buf[2] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_S2, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, -1); + /* buf[3] */ + sljit_emit_op2(compiler, SLJIT_ROTL, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_IMM, WCONST(0x9876543210abcdef, 0x87654321), shift_reg, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_IMM, WCONST(0x9876543210abcdc0, 0x876543e0)); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 4); + sljit_emit_op2(compiler, SLJIT_ROTL, SLJIT_R0, 0, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw)); + /* buf[4] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R0, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_IMM, WCONST(0x1234567812345678, 0x12345678)); + sljit_emit_op2(compiler, SLJIT_ROTR, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_IMM, 4); + /* buf[5] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_IMM, WCONST(0x1234567812345678, 0x12345678)); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 20); + sljit_emit_op2(compiler, SLJIT_ROTR, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_R0, 0); + /* buf[6] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0x1234567887654341, 0x17654321)); + sljit_emit_op2(compiler, SLJIT_ROTR, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R0, 0); + /* buf[7] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R0, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 8 * sizeof(sljit_sw)); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0xfedcba0987654321, 0x87654321)); + /* buf[8] */ + sljit_emit_op2(compiler, SLJIT_ROTR, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 0, SLJIT_R1, 0, SLJIT_IMM, 0xff00); + + sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 0xffc0); + sljit_emit_op2(compiler, SLJIT_ROTR, SLJIT_R1, 0, SLJIT_R1, 0, shift_reg, 0); + /* buf[9] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_R1, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, -7834); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0x87654321); + sljit_emit_op2(compiler, SLJIT_ROTL32, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), 0); + /* ibuf[0] */ + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_R0, 0); + /* buf[10] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), shift_reg, 0); + + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, (sljit_sw)0xabc89def); + sljit_emit_op2(compiler, SLJIT_ROTL32, SLJIT_S4, 0, SLJIT_R4, 0, SLJIT_IMM, 0xfffe1); + /* ibuf[1] */ + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32), SLJIT_S4, 0); + + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, (sljit_sw)0xabc89def); + sljit_emit_op2(compiler, SLJIT_ROTL32, SLJIT_S4, 0, SLJIT_R4, 0, SLJIT_IMM, 0xfffe0); + /* ibuf[2] */ + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_s32), SLJIT_S4, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, -6512); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, 0xfffe0); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_s32), SLJIT_IMM, (sljit_sw)0xabc89def); + /* ibuf[3] */ + sljit_emit_op2(compiler, SLJIT_ROTL32, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_s32), SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_s32), SLJIT_R4, 0); + /* buf[11] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), shift_reg, 0); + + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 30); + sljit_emit_op2(compiler, SLJIT_ROTR32, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0x87654321, SLJIT_R0, 0); + /* ibuf[4] */ + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_s32), SLJIT_R0, 0); + + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), SLJIT_IMM, (sljit_sw)0xfedccdef); + sljit_emit_op2(compiler, SLJIT_ROTR32, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), SLJIT_IMM, 4); + /* ibuf[5] */ + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_s32), SLJIT_MEM1(SLJIT_SP), 0); + + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 6 * sizeof(sljit_s32), SLJIT_IMM, (sljit_sw)0x89abcdef); + sljit_emit_op2(compiler, SLJIT_ROTR32, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), 6 * sizeof(sljit_s32), SLJIT_IMM, 0xfffe0); + /* ibuf[6] */ + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 6 * sizeof(sljit_s32), SLJIT_R0, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, -2647); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)0x89abcde0); + /* ibuf[7] */ + sljit_emit_op2(compiler, SLJIT_ROTR32, SLJIT_MEM1(SLJIT_S1), 7 * sizeof(sljit_s32), SLJIT_R1, 0, SLJIT_R1, 0); + /* buf[12] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), shift_reg, 0); + + sljit_emit_return_void(compiler); + + code.code = sljit_generate_code(compiler); + CHECK(compiler); + sljit_free_compiler(compiler); + + code.func2((sljit_sw)buf, (sljit_sw)ibuf); + + FAILED(buf[0] != WCONST(0x4567812345678123, 0x45678123), "test83 case 1 failed\n"); + FAILED(buf[1] != WCONST(0xfdb974130eca8643, 0xeca8643), "test83 case 2 failed\n"); + FAILED(buf[2] != WCONST(0xfedcba0987654321, 0x87654321), "test83 case 3 failed\n"); + FAILED(buf[3] != WCONST(0xcc3b2a190855e6f7, 0xc3b2a190), "test83 case 4 failed\n"); + FAILED(buf[4] != WCONST(0x9876543210abcdc0, 0x876543e0), "test83 case 5 failed\n"); + FAILED(buf[5] != WCONST(0x8123456781234567, 0x81234567), "test83 case 6 failed\n"); + FAILED(buf[6] != WCONST(0x4567812345678123, 0x45678123), "test83 case 7 failed\n"); + FAILED(buf[7] != WCONST(0x891a2b3c43b2a1a0, 0x8bb2a190), "test83 case 8 failed\n"); + FAILED(buf[8] != WCONST(0xfedcba0987654321, 0x87654321), "test83 case 9 failed\n"); + FAILED(buf[9] != WCONST(0xfedcba0987654321, 0x87654321), "test83 case 10 failed\n"); + FAILED(ibuf[0] != (sljit_s32)0x65432187, "test83 case 11 failed\n"); + FAILED(buf[10] != -7834, "test83 case 12 failed\n"); + FAILED(ibuf[1] != (sljit_s32)0x57913bdf, "test83 case 13 failed\n"); + FAILED(ibuf[2] != (sljit_s32)0xabc89def, "test83 case 14 failed\n"); + FAILED(ibuf[3] != (sljit_s32)0xabc89def, "test83 case 15 failed\n"); + FAILED(buf[11] != -6512, "test83 case 16 failed\n"); + FAILED(ibuf[4] != (sljit_s32)0x1d950c86, "test83 case 17 failed\n"); + FAILED(ibuf[5] != (sljit_s32)0xffedccde, "test83 case 18 failed\n"); + FAILED(ibuf[6] != (sljit_s32)0x89abcdef, "test83 case 19 failed\n"); + FAILED(ibuf[7] != (sljit_s32)0x89abcde0, "test83 case 20 failed\n"); + FAILED(buf[12] != -2647, "test83 case 21 failed\n"); + + sljit_free_code(code.code, NULL); + successful_tests++; +} + +static void test84(void) +{ + /* Test "shift into". */ + executable_code code; + struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); + sljit_sw buf[19]; + sljit_s32 ibuf[10]; + sljit_s32 i; +#ifdef SLJIT_PREF_SHIFT_REG + sljit_s32 shift_reg = SLJIT_PREF_SHIFT_REG; +#else + sljit_s32 shift_reg = SLJIT_R2; +#endif + + if (verbose) + printf("Run test84\n"); + + FAILED(!compiler, "cannot create compiler\n"); + + for (i = 0; i < 19; i++) + buf[i] = -1; + for (i = 0; i < 10; i++) + ibuf[i] = -1; + + sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, W, W), 5, 5, 0, 0, 2 * sizeof(sljit_sw)); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0x1234567812345678, 0x12345678)); + sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 12); + sljit_emit_shift_into(compiler, SLJIT_SHL, SLJIT_R0, SLJIT_R1, SLJIT_R1, shift_reg, 0); + /* buf[0] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, WCONST(0x1234567812345678, 0x12345678)); + sljit_emit_shift_into(compiler, SLJIT_MLSHR, SLJIT_R4, SLJIT_R3, SLJIT_R3, SLJIT_IMM, 0xffd4 /* 20 */); + /* buf[1] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R4, 0); + + sljit_emit_op1(compiler, SLJIT_MOV32, shift_reg, 0, SLJIT_IMM, (sljit_s32)0x86421357); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, 0xffeb /* 11 */); + sljit_emit_shift_into(compiler, SLJIT_MSHL32, SLJIT_R0, shift_reg, shift_reg, SLJIT_MEM1(SLJIT_SP), 0); + /* ibuf[0] */ + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_R0, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, -8762); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, (sljit_s32)0x89abcdef); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32), SLJIT_IMM, 0xffff); + sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_S1, 0, SLJIT_IMM, 16 * sizeof(sljit_s32)); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 17); + sljit_emit_shift_into(compiler, SLJIT_MLSHR32, SLJIT_S2, SLJIT_R4, SLJIT_R4, SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 2); + /* ibuf[1] */ + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32), SLJIT_S2, 0); + /* buf[2] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), shift_reg, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S4, 0, SLJIT_IMM, WCONST(0x1234567812345678, 0x12345678)); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0xabcd000000000000, 0xabcd0000)); + sljit_emit_shift_into(compiler, SLJIT_MSHL, SLJIT_S4, SLJIT_S4, SLJIT_R0, SLJIT_IMM, 12); + /* buf[3] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_S4, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0xaabbccddeeff8899, 0xabcdef89)); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, 0xfedcba); + sljit_emit_shift_into(compiler, SLJIT_LSHR, SLJIT_R1, SLJIT_R0, SLJIT_R4, SLJIT_IMM, 19); + /* buf[4] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R1, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0xfedcba0987654321, 0xfedcba09)); + sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, WCONST(0x7fffffffffffffff, 0x7fffffff)); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, 1); + sljit_emit_shift_into(compiler, SLJIT_SHL | SLJIT_SHIFT_INTO_NON_ZERO, SLJIT_R4, SLJIT_R1, shift_reg, SLJIT_MEM1(SLJIT_SP), 0); + /* buf[5] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R4, 0); + + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)0xdeadbeaf); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, (sljit_sw)0xfedcba09); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, -5); + sljit_emit_shift_into(compiler, SLJIT_MLSHR32 | SLJIT_SHIFT_INTO_NON_ZERO, shift_reg, SLJIT_R1, SLJIT_R4, SLJIT_R0, 0); + /* ibuf[2] */ + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_s32), shift_reg, 0); + + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R3, 0, SLJIT_IMM, (sljit_sw)0xabcd6543); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, (sljit_s32)0xc9000000); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0xffe8); + sljit_emit_shift_into(compiler, SLJIT_MSHL32, shift_reg, SLJIT_R3, SLJIT_R4, SLJIT_R0, 0); + /* ibuf[3] */ + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_s32), shift_reg, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, -6032); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, 0x7cadcad7); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_S3, 0, SLJIT_IMM, (sljit_s32)0xfffffff5); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 3); + sljit_emit_shift_into(compiler, SLJIT_LSHR32, SLJIT_R4, SLJIT_R4, SLJIT_S3, SLJIT_R0, 0); + /* ibuf[4] */ + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_s32), SLJIT_R4, 0); + /* buf[6] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), shift_reg, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -9740); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -5182); + sljit_emit_shift_into(compiler, SLJIT_SHL, SLJIT_R0, SLJIT_R0, SLJIT_R1, SLJIT_IMM, 0); + /* buf[7] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R0, 0); + /* buf[8] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R1, 0); + + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, -4072); + sljit_emit_op1(compiler, SLJIT_MOV32, shift_reg, 0, SLJIT_IMM, -2813); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 0); + sljit_emit_shift_into(compiler, SLJIT_LSHR32, SLJIT_R0, SLJIT_R0, shift_reg, SLJIT_R1, 0); + /* ibuf[5] */ + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_s32), SLJIT_R0, 0); + /* ibuf[6] */ + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 6 * sizeof(sljit_s32), shift_reg, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -3278); + sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 0); + sljit_emit_shift_into(compiler, SLJIT_LSHR, SLJIT_R1, SLJIT_R0, SLJIT_R0, shift_reg, 0); + /* buf[9] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_R1, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, WCONST(0x1234567890abcdef, 0x12345678)); + sljit_emit_shift_into(compiler, SLJIT_LSHR, SLJIT_R0, SLJIT_S3, SLJIT_S3, SLJIT_IMM, 0xfff8 /* 24/56 */); + /* buf[10] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_R0, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, WCONST(0x1234567890abcdef, 0x12345678)); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S4, 0, SLJIT_IMM, WCONST(0xba9876fedcba9800, 0xfedcba00)); + sljit_emit_shift_into(compiler, SLJIT_SHL, SLJIT_S3, SLJIT_S3, SLJIT_S4, SLJIT_IMM, 0xfff8 /* 24/56 */); + /* buf[11] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_S3, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0x1234567890abcdef, 0x12345678)); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -4986); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, 0); + sljit_emit_shift_into(compiler, SLJIT_SHL, SLJIT_R0, SLJIT_R0, SLJIT_R1, SLJIT_R4, 0); + /* buf[12] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_R0, 0); + /* buf[13] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_R1, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0x12345678fedcba09, 0x12348765)); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw), SLJIT_IMM, -1); + sljit_emit_shift_into(compiler, SLJIT_MLSHR, shift_reg, SLJIT_R0, SLJIT_R1, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw)); + /* buf[14] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw), shift_reg, 0); + /* buf[15] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 15 * sizeof(sljit_sw), SLJIT_R1, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0x8000000000000005, 0x80000005)); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_sw), SLJIT_R1, 0); + sljit_emit_shift_into(compiler, SLJIT_MSHL, SLJIT_R0, SLJIT_R0, SLJIT_R1, SLJIT_MEM0(), (sljit_sw)(buf + 16)); + /* buf[16] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_sw), SLJIT_R0, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0x2345678923456789, 0x23456789)); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, -1); + sljit_emit_shift_into(compiler, SLJIT_SHL, SLJIT_R0, SLJIT_R1, SLJIT_S2, SLJIT_R0, 0); + /* buf[17] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 17 * sizeof(sljit_sw), SLJIT_R0, 0); + + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0xabc23456); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)0xef000000); + sljit_emit_shift_into(compiler, SLJIT_SHL32, SLJIT_R0, SLJIT_R0, SLJIT_R1, SLJIT_IMM, 4); + /* ibuf[7] */ + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 7 * sizeof(sljit_s32), SLJIT_R0, 0); + + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0xabc23456); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)0xfe); + sljit_emit_shift_into(compiler, SLJIT_LSHR32, SLJIT_S2, SLJIT_R0, SLJIT_R1, SLJIT_IMM, 4); + /* ibuf[8] */ + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 8 * sizeof(sljit_s32), SLJIT_S2, 0); + +#if (defined SLJIT_MASKED_SHIFT && SLJIT_MASKED_SHIFT) + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 12344321); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -1); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, (8 * sizeof(sljit_sw)) + 1); + sljit_emit_shift_into(compiler, SLJIT_SHL, SLJIT_R0, SLJIT_R0, SLJIT_R1, SLJIT_R2, 0); + /* buf[18] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 18 * sizeof(sljit_sw), SLJIT_R0, 0); +#endif /* SLJIT_MASKED_SHIFT */ +#if (defined SLJIT_MASKED_SHIFT32 && SLJIT_MASKED_SHIFT32) + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 24688642); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 1); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R2, 0, SLJIT_IMM, (8 * sizeof(sljit_s32)) + 1); + sljit_emit_shift_into(compiler, SLJIT_LSHR32, SLJIT_R0, SLJIT_R0, SLJIT_R1, SLJIT_R2, 0); + /* ibuf[9] */ + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 9 * sizeof(sljit_s32), SLJIT_R0, 0); +#endif /* SLJIT_MASKED_SHIFT32 */ + + sljit_emit_return_void(compiler); + + code.code = sljit_generate_code(compiler); + CHECK(compiler); + sljit_free_compiler(compiler); + + code.func2((sljit_sw)buf, (sljit_sw)ibuf); + + FAILED(buf[0] != WCONST(0x4567812345678123, 0x45678123), "test84 case 1 failed\n"); + FAILED(buf[1] != WCONST(0x4567812345678123, 0x45678123), "test84 case 2 failed\n"); + FAILED(ibuf[0] != 0x109abc32, "test84 case 3 failed\n"); + FAILED(ibuf[1] != 0x13579bdf, "test84 case 4 failed\n"); + FAILED(buf[2] != -8762, "test84 case 5 failed\n"); + FAILED(buf[3] != WCONST(0x4567812345678abc, 0x45678abc), "test84 case 6 failed\n"); + FAILED(buf[4] != WCONST(0xdb975557799bbddf, 0xdb975579), "test84 case 7 failed\n"); + FAILED(buf[5] != WCONST(0xfdb974130eca8642, 0xfdb97412), "test84 case 8 failed\n"); + FAILED(ibuf[2] != (sljit_s32)0xdb97413b, "test84 case 9 failed\n"); + FAILED(ibuf[3] != (sljit_s32)0xcd6543c9, "test84 case 10 failed\n"); + FAILED(ibuf[4] != (sljit_s32)0xaf95b95a, "test84 case 11 failed\n"); + FAILED(buf[6] != -6032, "test84 case 12 failed\n"); + FAILED(buf[7] != -9740, "test84 case 13 failed\n"); + FAILED(buf[8] != -5182, "test84 case 14 failed\n"); + FAILED(ibuf[5] != -4072, "test84 case 15 failed\n"); + FAILED(ibuf[6] != -2813, "test84 case 16 failed\n"); + FAILED(buf[9] != -3278, "test84 case 17 failed\n"); + FAILED(buf[10] != WCONST(0x34567890abcdef12, 0x34567812), "test84 case 18 failed\n"); + FAILED(buf[11] != WCONST(0xefba9876fedcba98, 0x78fedcba), "test84 case 19 failed\n"); + FAILED(buf[12] != WCONST(0x1234567890abcdef, 0x12345678), "test84 case 20 failed\n"); + FAILED(buf[13] != -4986, "test84 case 21 failed\n"); + FAILED(buf[14] != WCONST(0x2468acf1fdb97413, 0x24690ecb), "test84 case 22 failed\n"); + FAILED(buf[15] != WCONST(0x12345678fedcba09, 0x12348765), "test84 case 23 failed\n"); + FAILED(buf[16] != 0x30, "test84 case 24 failed\n"); + FAILED(buf[17] != WCONST(0x8d159e248d159e27, 0x8d159e27), "test84 case 25 failed\n"); + FAILED(ibuf[7] != (sljit_s32)0xbc23456e, "test84 case 26 failed\n"); + FAILED(ibuf[8] != (sljit_s32)0xeabc2345, "test84 case 27 failed\n"); +#if (defined SLJIT_MASKED_SHIFT && SLJIT_MASKED_SHIFT) + FAILED(buf[18] != 24688643, "test84 case 28 failed\n"); +#endif /* SLJIT_MASKED_SHIFT */ +#if (defined SLJIT_MASKED_SHIFT32 && SLJIT_MASKED_SHIFT32) + FAILED(ibuf[9] != (sljit_s32)-2135139327, "test84 case 29 failed\n"); +#endif /* SLJIT_MASKED_SHIFT32 */ + + sljit_free_code(code.code, NULL); + successful_tests++; +} + +static void test85(void) +{ + /* Test count trailing zeroes. */ + executable_code code; + struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); + sljit_sw buf[5]; + sljit_s32 ibuf[7]; + sljit_s32 i; + + if (verbose) + printf("Run test85\n"); + + FAILED(!compiler, "cannot create compiler\n"); + + for (i = 0; i < 5; i++) + buf[i] = -1; + for (i = 0; i < 7; i++) + ibuf[i] = -1; + + buf[2] = 0; + ibuf[3] = 1; + + sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, W, W), 5, 5, 0, 0, 2 * sizeof(sljit_sw)); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x80); + /* buf[0] */ + sljit_emit_op1(compiler, SLJIT_CTZ, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, 0x654321); + sljit_emit_op1(compiler, SLJIT_CTZ, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_SP), 0); + /* buf[1] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R1, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, 2); + sljit_emit_op1(compiler, SLJIT_CTZ, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_MEM2(SLJIT_S0, SLJIT_S2), SLJIT_WORD_SHIFT); + /* buf[2] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw)); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, (sljit_sw)1 << (8 * sizeof(sljit_sw) - 3)); + sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 0x100000); + /* buf[3] */ + sljit_emit_op1(compiler, SLJIT_CTZ, SLJIT_MEM1(SLJIT_R1), 0x100000 + 3 * sizeof(sljit_sw), SLJIT_R4, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_IMM, WCONST(0xabcdef800, 0xcdef800)); + sljit_emit_op1(compiler, SLJIT_CTZ, SLJIT_S4, 0, SLJIT_MEM0(), (sljit_sw)(buf + 4)); + /* buf[4] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_S4, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 0xa400); + sljit_emit_op2(compiler, SLJIT_ASHR32, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_IMM, 4); + sljit_emit_op1(compiler, SLJIT_CTZ32, SLJIT_R1, 0, SLJIT_R0, 0); + /* ibuf[0] */ + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_R1, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -1); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0); + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_R0, 0); + /* ibuf[1] */ + sljit_emit_op1(compiler, SLJIT_CTZ32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32), SLJIT_R0, 0); + + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), SLJIT_IMM, 0xbcdefe0); + sljit_emit_op1(compiler, SLJIT_CTZ32, SLJIT_S4, 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32)); + /* ibuf[2] */ + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_s32), SLJIT_S4, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 3); + sljit_emit_op1(compiler, SLJIT_CTZ32, SLJIT_R0, 0, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), 2); + /* ibuf[3] */ + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_s32), SLJIT_R0, 0); + + sljit_emit_return_void(compiler); + + code.code = sljit_generate_code(compiler); + CHECK(compiler); + sljit_free_compiler(compiler); + + code.func2((sljit_sw)buf, (sljit_sw)ibuf); + + FAILED(buf[0] != 7, "test85 case 1 failed\n"); + FAILED(buf[1] != 0, "test85 case 2 failed\n"); + FAILED(buf[2] != WCONST(64, 32), "test85 case 3 failed\n"); + FAILED(buf[3] != WCONST(61, 29), "test85 case 4 failed\n"); + FAILED(buf[4] != 11, "test85 case 5 failed\n"); + FAILED(ibuf[0] != 6, "test85 case 6 failed\n"); + FAILED(ibuf[1] != 32, "test85 case 7 failed\n"); + FAILED(ibuf[2] != 5, "test85 case 8 failed\n"); + FAILED(ibuf[3] != 0, "test85 case 9 failed\n"); + + sljit_free_code(code.code, NULL); + successful_tests++; +} + +static void test86(void) +{ + /* Test get return address. */ + executable_code code; + struct sljit_compiler* compiler; + struct sljit_jump *jump; + struct sljit_label *label; + sljit_uw return_addr = 0; + sljit_uw buf[1]; + + if (verbose) + printf("Run test86\n"); + + /* Next test. */ + + buf[0] = 0; + + compiler = sljit_create_compiler(NULL, NULL); + FAILED(!compiler, "cannot create compiler\n"); + + sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, W), 1, 1, 0, 0, 0); + jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS0(W)); + label = sljit_emit_label(compiler); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_RETURN_REG, 0); + sljit_emit_return_void(compiler); + + sljit_set_label(jump, sljit_emit_label(compiler)); + sljit_emit_enter(compiler, 0, SLJIT_ARGS0(W), 1, 0, 0, 0, 0); + sljit_emit_op_dst(compiler, SLJIT_GET_RETURN_ADDRESS, SLJIT_RETURN_REG, 0); + sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); + + code.code = sljit_generate_code(compiler); + CHECK(compiler); + return_addr = sljit_get_label_addr(label); + sljit_free_compiler(compiler); + + code.func1((sljit_sw)buf); + + FAILED(buf[0] != return_addr, "test86 case 1 failed\n"); + sljit_free_code(code.code, NULL); + + /* Next test. */ + + buf[0] = 0; + + compiler = sljit_create_compiler(NULL, NULL); + FAILED(!compiler, "cannot create compiler\n"); + + sljit_emit_enter(compiler, 0, SLJIT_ARGS0(VOID), 2, 0, 0, 0, 0); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -1); + jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS2(VOID, W, W)); + label = sljit_emit_label(compiler); + sljit_emit_return_void(compiler); + + sljit_set_label(jump, sljit_emit_label(compiler)); + sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, W, W), 1, SLJIT_NUMBER_OF_SAVED_REGISTERS - 2, 0, 0, SLJIT_MAX_LOCAL_SIZE); + sljit_emit_op_dst(compiler, SLJIT_GET_RETURN_ADDRESS, SLJIT_MEM0(), (sljit_sw)buf); + sljit_emit_return_void(compiler); + + code.code = sljit_generate_code(compiler); + CHECK(compiler); + return_addr = sljit_get_label_addr(label); + sljit_free_compiler(compiler); + + code.func0(); + + FAILED(buf[0] != return_addr, "test86 case 2 failed\n"); + sljit_free_code(code.code, NULL); + + /* Next test. */ + + buf[0] = 0; + + compiler = sljit_create_compiler(NULL, NULL); + FAILED(!compiler, "cannot create compiler\n"); + + sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, W), 1, 3, 0, 0, 0); + sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_S2, 0, SLJIT_S0, 0, SLJIT_IMM, 16); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 8); + jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS1(VOID, W)); + label = sljit_emit_label(compiler); + sljit_emit_return_void(compiler); + + sljit_set_label(jump, sljit_emit_label(compiler)); + sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(3), SLJIT_ARGS1(VOID, W_R), 1, SLJIT_NUMBER_OF_SAVED_REGISTERS, 0, 0, SLJIT_MAX_LOCAL_SIZE >> 1); + sljit_emit_op_dst(compiler, SLJIT_GET_RETURN_ADDRESS, SLJIT_MEM2(SLJIT_S2, SLJIT_R0), 1); + sljit_emit_return_void(compiler); + + code.code = sljit_generate_code(compiler); + CHECK(compiler); + return_addr = sljit_get_label_addr(label); + sljit_free_compiler(compiler); + + code.func1((sljit_sw)buf); + + FAILED(buf[0] != return_addr, "test86 case 3 failed\n"); + sljit_free_code(code.code, NULL); + + /* Next test. */ + + buf[0] = 0; + + compiler = sljit_create_compiler(NULL, NULL); + FAILED(!compiler, "cannot create compiler\n"); + + sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, W_R), 1, 0, 0, 0, 0); + jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS1(VOID, W)); + label = sljit_emit_label(compiler); + sljit_emit_return_void(compiler); + + sljit_set_label(jump, sljit_emit_label(compiler)); + sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG, SLJIT_ARGS1(VOID, W_R), 1, SLJIT_NUMBER_OF_SAVED_REGISTERS >> 1, 0, 0, 64); + sljit_emit_op_dst(compiler, SLJIT_GET_RETURN_ADDRESS, SLJIT_MEM1(SLJIT_SP), 0); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_MEM1(SLJIT_SP), 0); + sljit_emit_return_void(compiler); + + code.code = sljit_generate_code(compiler); + CHECK(compiler); + return_addr = sljit_get_label_addr(label); + sljit_free_compiler(compiler); + + code.func1((sljit_sw)buf); + + FAILED(buf[0] != return_addr, "test86 case 4 failed\n"); + sljit_free_code(code.code, NULL); + + if (sljit_has_cpu_feature(SLJIT_HAS_FPU) && SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS > 0) { + /* Next test. */ + + buf[0] = 0; + + compiler = sljit_create_compiler(NULL, NULL); + FAILED(!compiler, "cannot create compiler\n"); + + sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, W), 1, 1, 0, 0, 0); + jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS0(W)); + label = sljit_emit_label(compiler); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_RETURN_REG, 0); + sljit_emit_return_void(compiler); + + sljit_set_label(jump, sljit_emit_label(compiler)); + sljit_emit_enter(compiler, 0, SLJIT_ARGS0(W), 1, 3, 0, SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS, 64); + sljit_emit_op_dst(compiler, SLJIT_GET_RETURN_ADDRESS, SLJIT_RETURN_REG, 0); + sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); + + code.code = sljit_generate_code(compiler); + CHECK(compiler); + return_addr = sljit_get_label_addr(label); + sljit_free_compiler(compiler); + + code.func1((sljit_sw)buf); + + FAILED(buf[0] != return_addr, "test86 case 5 failed\n"); + sljit_free_code(code.code, NULL); + } + + successful_tests++; +} + +static void test87(void) +{ + /* Test reverse bytes. */ + executable_code code; + struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); + sljit_sw buf[5]; + sljit_s32 ibuf[5]; + sljit_s32 i; + + if (verbose) + printf("Run test87\n"); + + FAILED(!compiler, "cannot create compiler\n"); + + for (i = 0; i < 5; i++) + buf[i] = -1; + for (i = 0; i < 5; i++) + ibuf[i] = -1; + + buf[3] = WCONST(0x8070605040302010, 0x40302010); + ibuf[1] = (sljit_s32)0xffeeddcc; + + sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, W, W), 5, 5, 0, 0, 2 * sizeof(sljit_sw)); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0xf1e2d3c4b5a69788, 0xf1e2d3c4)); + sljit_emit_op1(compiler, SLJIT_REV, SLJIT_R0, 0, SLJIT_R0, 0); + /* buf[0] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, WCONST(0xffeeddccbbaa9988, 0xffeeddcc)); + sljit_emit_op1(compiler, SLJIT_REV, SLJIT_R2, 0, SLJIT_R4, 0); + /* buf[1] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R2, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, WCONST(0x0102030405060708, 0x01020304)); + /* buf[2] */ + sljit_emit_op1(compiler, SLJIT_REV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_S2, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 3); + sljit_emit_op1(compiler, SLJIT_REV, SLJIT_R4, 0, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_WORD_SHIFT); + /* buf[3] */ + sljit_emit_op1(compiler, SLJIT_REV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R4, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, WCONST(0x1122334455667788, 0x11223344)); + /* buf[4] */ + sljit_emit_op1(compiler, SLJIT_REV, SLJIT_MEM0(), (sljit_sw)&buf[4], SLJIT_S2, 0); + + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, (sljit_s32)0xf1e2d3c4); + sljit_emit_op1(compiler, SLJIT_REV32, SLJIT_R1, 0, SLJIT_R0, 0); + /* ibuf[0] */ + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_R1, 0); + + sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S1, 0, SLJIT_IMM, 0x12340 + sizeof(sljit_s32)); + sljit_emit_op1(compiler, SLJIT_REV32, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R2), -0x12340); + /* ibuf[1] */ + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32), SLJIT_R2, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, (sljit_s32)0x01020304); + /* ibuf[2] */ + sljit_emit_op1(compiler, SLJIT_REV32, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), 2, SLJIT_R4, 0); + + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, (sljit_s32)0x11223344); + sljit_emit_op1(compiler, SLJIT_REV32, SLJIT_R4, 0, SLJIT_R4, 0); + /* ibuf[3] */ + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_s32), SLJIT_R4, 0); + + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, (sljit_s32)0xfeeddccb); + /* ibuf[4] */ + sljit_emit_op1(compiler, SLJIT_REV32, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_s32), SLJIT_MEM1(SLJIT_SP), 0); + + sljit_emit_return_void(compiler); + + code.code = sljit_generate_code(compiler); + CHECK(compiler); + sljit_free_compiler(compiler); + + code.func2((sljit_sw)buf, (sljit_sw)ibuf); + + FAILED(buf[0] != WCONST(0x8897a6b5c4d3e2f1, 0xc4d3e2f1), "test87 case 1 failed\n"); + FAILED(buf[1] != WCONST(0x8899aabbccddeeff, 0xccddeeff), "test87 case 2 failed\n"); + FAILED(buf[2] != WCONST(0x0807060504030201, 0x04030201), "test87 case 3 failed\n"); + FAILED(buf[3] != WCONST(0x8070605040302010, 0x40302010), "test87 case 4 failed\n"); + FAILED(buf[4] != WCONST(0x8877665544332211, 0x44332211), "test87 case 5 failed\n"); + FAILED(ibuf[0] != (sljit_s32)0xc4d3e2f1, "test87 case 6 failed\n"); + FAILED(ibuf[1] != (sljit_s32)0xccddeeff, "test87 case 7 failed\n"); + FAILED(ibuf[2] != (sljit_s32)0x04030201, "test87 case 8 failed\n"); + FAILED(ibuf[3] != (sljit_s32)0x44332211, "test87 case 9 failed\n"); + FAILED(ibuf[4] != (sljit_s32)0xcbdcedfe, "test87 case 10 failed\n"); + + sljit_free_code(code.code, NULL); + successful_tests++; +} + +static void test88(void) +{ + /* Test sljit_emit_fcopy. */ + executable_code code; + struct sljit_compiler* compiler; + sljit_f64 dbuf[4]; + sljit_f32 sbuf[2]; +#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) + sljit_sw wbuf[2]; + sljit_s32 ibuf[2]; +#else /* !SLJIT_64BIT_ARCHITECTURE */ + sljit_s32 ibuf[7]; +#endif /* SLJIT_64BIT_ARCHITECTURE */ + + if (verbose) + printf("Run test88\n"); + + if (!sljit_has_cpu_feature(SLJIT_HAS_FPU)) { + if (verbose) + printf("no fpu available, test88 skipped\n"); + successful_tests++; + return; + } + + compiler = sljit_create_compiler(NULL, NULL); + FAILED(!compiler, "cannot create compiler\n"); + + sbuf[0] = 12345.0; + sbuf[1] = -1.0; + ibuf[0] = -1; + ibuf[1] = (sljit_s32)0xc7543100; + dbuf[0] = 123456789012345.0; + dbuf[1] = -1.0; +#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) + wbuf[0] = -1; + wbuf[1] = (sljit_sw)0xc2fee0c29f50cb10; +#else /* !SLJIT_64BIT_ARCHITECTURE */ + ibuf[2] = -1; + ibuf[3] = -1; + ibuf[4] = -1; + ibuf[5] = (sljit_sw)0x9f50cb10; + ibuf[6] = (sljit_sw)0xc2fee0c2; +#endif /* SLJIT_64BIT_ARCHITECTURE */ + + sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, W, W), 5, 5, 5, 0, 0); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)ibuf); + sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S1), 0); + sljit_emit_fcopy(compiler, SLJIT_COPY32_FROM_F32, SLJIT_FR2, SLJIT_R0); + /* ibuf[0] */ + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0); + + sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R3, 0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_s32)); + sljit_emit_fcopy(compiler, SLJIT_COPY32_TO_F32, SLJIT_FR4, SLJIT_R3); + /* sbuf[1] */ + sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f32), SLJIT_FR4, 0); + +#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)wbuf); + sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), 0); + sljit_emit_fcopy(compiler, SLJIT_COPY_FROM_F64, SLJIT_FR1, SLJIT_S2); + /* wbuf[0] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_S2, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw)); + sljit_emit_fcopy(compiler, SLJIT_COPY_TO_F64, SLJIT_FR0, SLJIT_R3); + /* dbuf[1] */ + sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64), SLJIT_FR0, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0); + sljit_emit_fcopy(compiler, SLJIT_COPY_TO_F64, SLJIT_FR3, SLJIT_R2); + /* dbuf[2] */ + sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f64), SLJIT_FR3, 0); +#else /* !SLJIT_64BIT_ARCHITECTURE */ + sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), 0); + sljit_emit_fcopy(compiler, SLJIT_COPY_FROM_F64, SLJIT_FR1, SLJIT_REG_PAIR(SLJIT_S3, SLJIT_S2)); + /* ibuf[2-3] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(sljit_sw), SLJIT_S2, 0); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 3 * sizeof(sljit_sw), SLJIT_S3, 0); + + sljit_emit_fcopy(compiler, SLJIT_COPY_FROM_F64, SLJIT_FR1, SLJIT_R2); + /* ibuf[4] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 4 * sizeof(sljit_sw), SLJIT_R2, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_MEM1(SLJIT_R1), 5 * sizeof(sljit_sw)); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R1), 6 * sizeof(sljit_sw)); + sljit_emit_fcopy(compiler, SLJIT_COPY_TO_F64, SLJIT_FR0, SLJIT_REG_PAIR(SLJIT_R0, SLJIT_R3)); + /* dbuf[1] */ + sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64), SLJIT_FR0, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0); + sljit_emit_fcopy(compiler, SLJIT_COPY_TO_F64, SLJIT_FR3, SLJIT_REG_PAIR(SLJIT_R2, SLJIT_R2)); + /* dbuf[2] */ + sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f64), SLJIT_FR3, 0); + + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, (sljit_sw)0xc00c0000); + sljit_emit_fcopy(compiler, SLJIT_COPY_TO_F64, SLJIT_FR3, SLJIT_R2); + sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_f64), SLJIT_FR3, 0); +#endif /* SLJIT_64BIT_ARCHITECTURE */ + + sljit_emit_return_void(compiler); + + code.code = sljit_generate_code(compiler); + CHECK(compiler); + sljit_free_compiler(compiler); + + code.func2((sljit_sw)dbuf, (sljit_sw)sbuf); + + FAILED(ibuf[0] != (sljit_s32)0x4640e400, "test88 case 1 failed\n"); + FAILED(sbuf[1] != -54321.0, "test88 case 2 failed\n"); +#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) + FAILED(wbuf[0] != (sljit_sw)0x42dc12218377de40, "test88 case 3 failed\n"); + FAILED(dbuf[1] != -543210987654321.0, "test88 case 4 failed\n"); + FAILED(dbuf[2] != 0.0, "test88 case 5 failed\n"); +#else /* !SLJIT_64BIT_ARCHITECTURE */ + FAILED(ibuf[2] != (sljit_sw)0x8377de40, "test88 case 3 failed\n"); + FAILED(ibuf[3] != (sljit_sw)0x42dc1221, "test88 case 4 failed\n"); + FAILED(ibuf[4] != (sljit_sw)0x42dc1221, "test88 case 5 failed\n"); + FAILED(dbuf[1] != -543210987654321.0, "test88 case 6 failed\n"); + FAILED(dbuf[2] != 0.0, "test88 case 7 failed\n"); + FAILED(dbuf[3] != -3.5, "test88 case 8 failed\n"); +#endif /* SLJIT_64BIT_ARCHITECTURE */ + + sljit_free_code(code.code, NULL); successful_tests++; } @@ -9279,12 +11190,21 @@ int sljit_test(int argc, char* argv[]) test77(); test78(); test79(); + test80(); + test81(); + test82(); + test83(); + test84(); + test85(); + test86(); + test87(); + test88(); #if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) sljit_free_unused_memory_exec(); #endif -# define TEST_COUNT 79 +# define TEST_COUNT 88 printf("SLJIT tests: "); if (successful_tests == TEST_COUNT)