diff --git a/LICENSE b/LICENSE index b9c199c..fb039d6 100644 --- a/LICENSE +++ b/LICENSE @@ -1,8 +1,30 @@ -ISC License: +================================================================ -Copyright (c) 2004-2010 by Internet Systems Consortium, Inc. ("ISC") -Copyright (c) 1995-2003 by Internet Software Consortium + _ ___ ____ _____ _ _ ____ _____ + | | |_ _/ ___| ____| \ | / ___|| ____| + | | | | | | _| | \| \___ \| _| + | |___ | | |___| |___| |\ |___) | |___ + |_____|___\____|_____|_| \_|____/|_____| -Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. + Konilo & ilo -THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + Copyright (c) Charles Childers + +================================================================ + +Permission to use, copy, modify, and/or distribute this +software for any purpose with or without fee is hereby +granted, provided that the copyright notice and this +permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS +ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO +EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER +RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN +AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +OF THIS SOFTWARE. + +================================================================ diff --git a/README.md b/README.md index 1f1fa4d..8df0407 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,37 @@ -# ilo-vm +================================================================ -The ilo virtual computer. This is mostly used with Konilo, a Forth based computing system. \ No newline at end of file + crc's _ _ + (_) | ___ + | | |/ _ \ a tiny virtual computer + | | | (_) | 64kw RAM, 32-bit, Dual Stack, MISC + |_|_|\___/ (c) charles childers + +================================================================ + +# Welcome! + +This is ilo, a little virtual computer. ilo is mostly used with +Konilo, a personal computing system written in Forth. + +A brief overview: + +- 65,536 memory locations ("cells") +- 32 bits per cell +- block storage device +- stack based architecture +- minimal instruction set (30 instructions) +- easy to implement and exend + +This supports a variety of host architectures. Precompiled +(mostly static) binaries are included for Linux, OpenBSD, +NetBSD, FreeBSD, MS-DOS, macOS, Haiku, Classic Mac Systems 5-7, +and Windows. It has been tested and confirmed to work on x86 +(8088+), amd64, arm64, and 68000 processors. Physical RAM +requirements are around 384K. + +In addition to the provided binaries, many implementations of +ilo are included. These include Assembly, C, C++, C#, Common +Lisp, D, Go, Hare, JavaScript, Kotlin, Lua, Nim, Python, +RetroForth, Rust, Swift, and TypeScript. + +================================================================ diff --git a/binaries/CWSDPMI.exe b/binaries/CWSDPMI.exe new file mode 100644 index 0000000..6865892 Binary files /dev/null and b/binaries/CWSDPMI.exe differ diff --git a/binaries/ilo-68k-mac.bin b/binaries/ilo-68k-mac.bin new file mode 100644 index 0000000..a251dd9 Binary files /dev/null and b/binaries/ilo-68k-mac.bin differ diff --git a/binaries/ilo-aarch64-linux b/binaries/ilo-aarch64-linux new file mode 100755 index 0000000..871d449 Binary files /dev/null and b/binaries/ilo-aarch64-linux differ diff --git a/binaries/ilo-amd64-dragonfly b/binaries/ilo-amd64-dragonfly new file mode 100755 index 0000000..6ee6758 Binary files /dev/null and b/binaries/ilo-amd64-dragonfly differ diff --git a/binaries/ilo-amd64-freebsd b/binaries/ilo-amd64-freebsd new file mode 100755 index 0000000..dcbcf30 Binary files /dev/null and b/binaries/ilo-amd64-freebsd differ diff --git a/binaries/ilo-amd64-haiku b/binaries/ilo-amd64-haiku new file mode 100755 index 0000000..ef9954e Binary files /dev/null and b/binaries/ilo-amd64-haiku differ diff --git a/binaries/ilo-amd64-linux b/binaries/ilo-amd64-linux new file mode 100755 index 0000000..c8a4447 Binary files /dev/null and b/binaries/ilo-amd64-linux differ diff --git a/binaries/ilo-amd64-netbsd b/binaries/ilo-amd64-netbsd new file mode 100755 index 0000000..68749a8 Binary files /dev/null and b/binaries/ilo-amd64-netbsd differ diff --git a/binaries/ilo-amd64-openbsd b/binaries/ilo-amd64-openbsd new file mode 100755 index 0000000..6c14fd8 Binary files /dev/null and b/binaries/ilo-amd64-openbsd differ diff --git a/binaries/ilo-amd64-windows.exe b/binaries/ilo-amd64-windows.exe new file mode 100644 index 0000000..b1fc733 Binary files /dev/null and b/binaries/ilo-amd64-windows.exe differ diff --git a/binaries/ilo-arm64-darwin b/binaries/ilo-arm64-darwin new file mode 100755 index 0000000..c33ff25 Binary files /dev/null and b/binaries/ilo-arm64-darwin differ diff --git a/binaries/ilo-dotnet-windows.exe b/binaries/ilo-dotnet-windows.exe new file mode 100755 index 0000000..284b9f9 Binary files /dev/null and b/binaries/ilo-dotnet-windows.exe differ diff --git a/binaries/ilo-ipad-ish b/binaries/ilo-ipad-ish new file mode 100755 index 0000000..00a300b Binary files /dev/null and b/binaries/ilo-ipad-ish differ diff --git a/binaries/ilo-luna88k-openbsd b/binaries/ilo-luna88k-openbsd new file mode 100755 index 0000000..0dbff42 Binary files /dev/null and b/binaries/ilo-luna88k-openbsd differ diff --git a/binaries/ilo-pmax-netbsd b/binaries/ilo-pmax-netbsd new file mode 100755 index 0000000..68e5900 Binary files /dev/null and b/binaries/ilo-pmax-netbsd differ diff --git a/binaries/ilo-teensy41.hex b/binaries/ilo-teensy41.hex new file mode 100644 index 0000000..e971cbc --- /dev/null +++ b/binaries/ilo-teensy41.hex @@ -0,0 +1,4230 @@ +:0200000460009A +:100000004643464200000156000000000103030081 +:1000100000000000000000000000000000000000E0 +:1000200000000000000000000000000000000000D0 +:1000300000000000000000000000000000000000C0 +:1000400000000000010408000000000000000000A3 +:100050000000800000000000000000000000000020 +:100060000000000000000000000000000000000090 +:100070000000000000000000000000000000000080 +:10008000EB04180A063204260000000000000000FD +:10009000050404240000000000000000000000002F +:1000A0000000000000000000000000000000000050 +:1000B0000604000000000000000000000000000036 +:1000C0000000000000000000000000000000000030 +:1000D00020041808000000000000000000000000DC +:1000E0000000000000000000000000000000000010 +:1000F0000000000000000000000000000000000000 +:10010000D8041808000000000000000000000000F3 +:100110000204180804200000000000000000000095 +:1001200000000000000000000000000000000000CF +:10013000600400000000000000000000000000005B +:1001400000000000000000000000000000000000AF +:10015000000000000000000000000000000000009F +:10016000000000000000000000000000000000008F +:10017000000000000000000000000000000000007F +:10018000000000000000000000000000000000006F +:10019000000000000000000000000000000000005F +:1001A000000000000000000000000000000000004F +:1001B000000000000000000000000000000000003F +:1001C000000100000010000001000000000000001D +:1001D000000001000000000000000000000000001E +:1001E000000000000000000000000000000000000F +:1001F00000000000000000000000000000000000FF +:10020000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE +:10021000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEE +:10022000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDE +:10023000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCE +:10024000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBE +:10025000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAE +:10026000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9E +:10027000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8E +:10028000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7E +:10029000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6E +:1002A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5E +:1002B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4E +:1002C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3E +:1002D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E +:1002E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1E +:1002F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0E +:10030000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD +:10031000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED +:10032000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDD +:10033000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCD +:10034000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBD +:10035000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAD +:10036000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9D +:10037000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8D +:10038000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7D +:10039000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6D +:1003A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D +:1003B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D +:1003C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3D +:1003D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2D +:1003E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1D +:1003F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0D +:10040000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC +:10041000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEC +:10042000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC +:10043000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCC +:10044000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBC +:10045000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAC +:10046000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C +:10047000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8C +:10048000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7C +:10049000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C +:1004A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5C +:1004B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4C +:1004C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3C +:1004D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2C +:1004E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1C +:1004F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0C +:10050000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB +:10051000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEB +:10052000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDB +:10053000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCB +:10054000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBB +:10055000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAB +:10056000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9B +:10057000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8B +:10058000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7B +:10059000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6B +:1005A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5B +:1005B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4B +:1005C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3B +:1005D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2B +:1005E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1B +:1005F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +:10060000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA +:10061000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEA +:10062000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDA +:10063000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCA +:10064000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBA +:10065000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAA +:10066000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9A +:10067000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A +:10068000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7A +:10069000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6A +:1006A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5A +:1006B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4A +:1006C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3A +:1006D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2A +:1006E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1A +:1006F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0A +:10070000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9 +:10071000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9 +:10072000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD9 +:10073000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC9 +:10074000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB9 +:10075000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA9 +:10076000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF99 +:10077000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF89 +:10078000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF79 +:10079000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF69 +:1007A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF59 +:1007B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF49 +:1007C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF39 +:1007D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF29 +:1007E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF19 +:1007F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF09 +:10080000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8 +:10081000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE8 +:10082000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD8 +:10083000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC8 +:10084000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB8 +:10085000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA8 +:10086000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF98 +:10087000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF88 +:10088000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF78 +:10089000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF68 +:1008A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF58 +:1008B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF48 +:1008C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF38 +:1008D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF28 +:1008E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF18 +:1008F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF08 +:10090000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7 +:10091000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7 +:10092000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD7 +:10093000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7 +:10094000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB7 +:10095000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA7 +:10096000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF97 +:10097000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF87 +:10098000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF77 +:10099000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF67 +:1009A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF57 +:1009B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF47 +:1009C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF37 +:1009D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27 +:1009E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF17 +:1009F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF07 +:100A0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6 +:100A1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE6 +:100A2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6 +:100A3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC6 +:100A4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB6 +:100A5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA6 +:100A6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF96 +:100A7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF86 +:100A8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF76 +:100A9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF66 +:100AA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF56 +:100AB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF46 +:100AC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF36 +:100AD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF26 +:100AE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16 +:100AF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF06 +:100B0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5 +:100B1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5 +:100B2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD5 +:100B3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC5 +:100B4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB5 +:100B5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA5 +:100B6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF95 +:100B7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF85 +:100B8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF75 +:100B9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF65 +:100BA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF55 +:100BB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF45 +:100BC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF35 +:100BD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF25 +:100BE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF15 +:100BF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF05 +:100C0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4 +:100C1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE4 +:100C2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD4 +:100C3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC4 +:100C4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB4 +:100C5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA4 +:100C6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF94 +:100C7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF84 +:100C8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF74 +:100C9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF64 +:100CA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF54 +:100CB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF44 +:100CC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF34 +:100CD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF24 +:100CE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF14 +:100CF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF04 +:100D0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3 +:100D1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE3 +:100D2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD3 +:100D3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC3 +:100D4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB3 +:100D5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA3 +:100D6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF93 +:100D7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF83 +:100D8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF73 +:100D9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF63 +:100DA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF53 +:100DB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF43 +:100DC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF33 +:100DD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF23 +:100DE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF13 +:100DF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03 +:100E0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2 +:100E1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE2 +:100E2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD2 +:100E3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC2 +:100E4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB2 +:100E5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA2 +:100E6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF92 +:100E7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF82 +:100E8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF72 +:100E9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF62 +:100EA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF52 +:100EB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF42 +:100EC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF32 +:100ED000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF22 +:100EE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF12 +:100EF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF02 +:100F0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1 +:100F1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE1 +:100F2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD1 +:100F3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC1 +:100F4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB1 +:100F5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA1 +:100F6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF91 +:100F7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF81 +:100F8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF71 +:100F9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF61 +:100FA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF51 +:100FB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF41 +:100FC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF31 +:100FD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF21 +:100FE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11 +:100FF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01 +:10100000D10020432914006000000000000000000F +:10101000201000600010006000FC00600000000074 +:10102000000000600008010000000000FFFFFFFF5B +:10103000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0 +:10104000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0 +:10105000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA0 +:10106000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF90 +:10107000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80 +:10108000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70 +:10109000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF60 +:1010A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF50 +:1010B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF40 +:1010C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF30 +:1010D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF20 +:1010E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF10 +:1010F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +:10110000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF +:10111000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDF +:10112000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCF +:10113000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBF +:10114000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAF +:10115000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9F +:10116000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8F +:10117000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F +:10118000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6F +:10119000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5F +:1011A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4F +:1011B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F +:1011C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2F +:1011D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1F +:1011E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0F +:1011F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +:10120000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEE +:10121000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDE +:10122000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCE +:10123000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBE +:10124000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAE +:10125000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9E +:10126000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8E +:10127000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7E +:10128000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6E +:10129000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5E +:1012A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4E +:1012B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3E +:1012C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E +:1012D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1E +:1012E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0E +:1012F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE +:10130000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED +:10131000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDD +:10132000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCD +:10133000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBD +:10134000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAD +:10135000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9D +:10136000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8D +:10137000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7D +:10138000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6D +:10139000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D +:1013A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D +:1013B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3D +:1013C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2D +:1013D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1D +:1013E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0D +:1013F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD +:10140000884207D0904205D251F8043B40F8043B93 +:101410008242F9D8704700BF884204D2002340F8C6 +:10142000043B8142FBD87047664B4FF42A01664A61 +:1014300066482DE9F0475A641864654A99639546F1 +:10144000BFF34F8FBFF36F8F00F004F9614B08209B +:10145000614A6249C3F854016148FFF7D1FF614A0C +:1014600061496248FFF7CCFF61496248FFF7D4FF4A +:10147000614C62494FF470000023614A086044F8EF +:1014800023200133B02BFAD15E4B80215E4A03F852 +:10149000011B9342FBD14F4D4FF080385B494FF019 +:1014A000FF325B4B0026DFF8A4A1DFF8A4911C609B +:1014B000C5F80481C5F800A1C5F8F480C5F8F0901E +:1014C0000B68544F43F4E0230B60FB693D4923F064 +:1014D0007F0343F04003FB617B6A23F07F0343F00B +:1014E00040037B628A66CA660A674A6700F0B8F8FA +:1014F000494A4A4B6320A2630321E363484A494BAC +:10150000106000F160401E6042F8041C00F6A170FB +:101510004549464AC3F8082D0B68454A43F0807395 +:101520000B601368434943F00103136003680B60C9 +:1015300000F0E6FAC5F804813F48C5F800A1C5F8F7 +:10154000F480C5F8F09000F08BFCF96E3B4A41F452 +:1015500040513B4BF9661660C2F80861C2F8186149 +:10156000C2F82861C2F838619A6BD20708D442F6F3 +:101570001562344959651A659A6B42F001029A6303 +:101580002F4A314C936843F00113936000F0DAF86E +:1015900000F016FC00F05CFC00F0E4FA00F05CF8EF +:1015A0002368132BFCD900F06BFB2368B3F5967FFF +:1015B000FBD300F053F800F043FC00F04DFC30BFCB +:1015C000FDE700BF00C00A40AFAAAAAA070020009A +:1015D0000000072000800D40A8BF0000481F0060E9 +:1015E00000000000C01A0020F4DE006000000020AF +:1015F000C0280020C01A00200018002088ED00E05C +:10160000C998000000E400E0A0E400E024ED00E060 +:1016100008ED00E000C00F407DAC000081AC000090 +:1016200014E000E018E000E0FCED00E00000202005 +:10163000001000E0EC2700200046C32300400840D3 +:1016400000400D400000C056F02700201B1018205D +:101650000C0D1113704700BF704700BF704700BFEB +:10166000F0B5244A0020244B4FF0100C234C1126D7 +:10167000DFF8C8E0122720600125C2F800C0C3F8D7 +:1016800000E01660DFF8B8E01D4EC3F800E01D4929 +:1016900017601E6041F015011B4F1C4E17601E6045 +:1016A0001B4F1C4E17601E601B4F11601B4E1C49C8 +:1016B0001F6016601B4F19601B4E1C4917601E608F +:1016C0001B4F11601B4E1C491F601660196025607E +:1016D000BFF34F8FBFF36F8FC3F8B001BFF34F8FCE +:1016E000BFF36F8F52F8883C43F4403342F8883C94 +:1016F000F0BD00BF9CED00E0A0ED00E094ED00E047 +:1017000009001000C028002013002000210002075B +:1017100014000020250008130900001016002020E6 +:1017200027000B131700004033001013180000604F +:101730002F000B07190000702F000B133F00001043 +:1017400025000803F0B58D4B18228D4E01208D49E0 +:1017500048F20C7E8C4D4FF0FF378C4C83B0C3F8B1 +:101760005C12C3F860520025C3F86412C3F86842E3 +:101770004FF40054C3F86C628549C3F87062C3F833 +:101780007462C3F87862834EDA661A675A679A679A +:10179000DA67C3F88020C3F88420C3F8882040F2B9 +:1017A0000562C1F82C03C1F83003C1F83403C1F855 +:1017B0003803C1F83C03C1F850032946B3697648A1 +:1017C0001840764B03437648B361D6F8843043F033 +:1017D0000C03C6F8843002260368334303600368B1 +:1017E00003EA0E0E6F4B4EEA0303DFF8F0E10360ED +:1017F0006D4B4760DEF808703B406C4F43F0005380 +:101800008360C36823F07803C360036A1F40684B9A +:101810003B43664F0362036A1F40654B3B43654F82 +:1018200043628762C762DEF8B830634F23F03F033C +:1018300043F00103C0F8B830DEF8BC30DFF884E1D3 +:1018400023F03F0343F00103C0F8BC300561046698 +:101850000767C0F8802044664767C0F884200468A2 +:10186000564B24F00204564A0460C0F818E0C661E2 +:1018700043F8041B9342FBD1494B1A68194642F0C6 +:1018800001021A600B68464A13F00103FAD14D4E6B +:10189000022540F2F56440F2664040F299414A4F19 +:1018A000966142F20146D56140F23545C2F80042E8 +:1018B00042F20124C2F810020120C2F8201211469F +:1018C000C2F8307207F15A47C2F8346207F513774D +:1018D000C2F840523D4E3E4DC2F85072C2F85462BA +:1018E000C2F86052C2F86442C2F8A030C2F8A43014 +:1018F000C2F8B0004B692A4ADD07FBD5012300245A +:101900004FF4803011465361C2F8A040C2F8A400E1 +:10191000C2F8B0304B69224ADC07FBD50123002412 +:101920004FF4003011465361C2F8A040C2F8A40041 +:10193000C2F8B0304B691A4AD807FBD501230024FE +:10194000244811465361C2F8A040C2F8A400C2F86E +:10195000B0304B69124ADB07FBD5D2F8003145F6AF +:101960000D5121209BB250618B4239D01A4B00227D +:101970001A605A609A60DA6003B0F0BD00801F40C0 +:10198000F9700100F9B00100F9100100F90001003F +:1019900000841F4000C00F40FFFCFF1F000300A099 +:1019A00000402A401200FFFFFF37F70000FFF07CE5 +:1019B00040000080FF000F836300020000422A40C5 +:1019C00000432A40F05AF05A9F041830063201268C +:1019D0003806180A040003006428002000802A400A +:1019E00000244FF4802001231146C2F8A040C2F821 +:1019F000A400C2F8B0304B693B4ADF07FBD5012396 +:101A00004FF40004002011465361C2F8A040C2F810 +:101A1000A400C2F8B0304B69334ADE07FBD501237E +:101A20004FF400044FF4803011465361C2F8A040D7 +:101A3000C2F8A400C2F8B0304B692B4ADD07FBD5D1 +:101A400001234FF400044FF4003011465361C2F8F3 +:101A5000A040C2F8A400C2F8B0304B69224ADC07AB +:101A6000FBD501234FF40004204811465361C2F80E +:101A7000A040C2F8A400C2F8B0304B691A4AD80797 +:101A8000FBD5D2F8003145F60D5121209BB25061B3 +:101A90008B4210D0164B08224FF400041A701549DF +:101AA0000020154A01230090521A1448224400F0E5 +:101AB000BFF903B0F0BD4FF400044FF480210123BF +:101AC0001046C2F8A040C2F8A410C2F8B030436972 +:101AD0000549DB07FBD50120054B10224FF0807430 +:101AE00048611A70DBE700BF00402A400400030091 +:101AF0000D28002000000070000000706428002005 +:101B0000F0B4174A40274FF480314FF480564FF419 +:101B100000554FF4404443F24200136913F0020FA2 +:101B200006D0946151619061136913F0020FF8D1EE +:101B300013F4005F01D15561EFE713F4805F01D129 +:101B40005661EAE7002BE8DA13F4803F01D0916197 +:101B5000E3E75B0601D45761DFE7F0BC704700BFE5 +:101B600000800D40394A03203949F3EE095A1368C1 +:101B70009FED386A23F00103DFED376AF0B413609C +:101B800000241061D1F8E030344FD8B2C3F30B21F8 +:101B90001B0D334E07EE100A05EE101A07EE903AB1 +:101BA000304BB8EEC55A304DB8EEC77A3060F8EE1B +:101BB000E77A29602D4937EE466A2D4E77EEC57AD1 +:101BC0002C4877EE666A2C4D37EE657A26EE276A4A +:101BD000C7ED007A66EEA76A176867EE277A83ED8D +:101BE000007AC6EE075A86EE876AC7EE876A35EE38 +:101BF000857AFCEEC77A36EE057A17EE903ABCEE9F +:101C0000C77A47EA035376EE857A136017EE103AE7 +:101C1000D2F81071FCEEE77A01EA0341394317EE7E +:101C2000903AC2F81011C3F30B03D2F810110B4312 +:101C3000C2F81031136843F0020313603470C0F827 +:101C400040510E4B0122F0BC1A60704780810D405C +:101C500000441F400000AA420000B442E0270020D8 +:101C6000D8270020DC270020D42700200000FF0F09 +:101C700040E400E0001800208D9A000008E100E038 +:101C8000304B40F6617270B5C3F8202140F2044534 +:101C900000F0CAF82C492D48D1F880202C4C42F095 +:101CA00003022C4BC1F88020C0F860512268134019 +:101CB0001BB9D0F8A8319A071AD0244B4FF0004135 +:101CC000234A51631A46D3F8401141F00201C3F888 +:101CD0004011D2F840319B07FBD44FF400301E492D +:101CE0001B4B4FF00042086019209A6300F0A4F8E3 +:101CF0001A4D0022164B4FF08041144C0A2699636E +:101D000028461A601146C4F8A8614FF4207200F00A +:101D10009BF84FF4810640F243114FF48000104BC2 +:101D2000104A2E602864C4F85851C4F84811C3F80A +:101D300004220D4A4FF4003101231160C4F84031F0 +:101D400070BD00BF00800D4000C00F4000002E405D +:101D500000900D40001C1E008CE200E000000020FE +:101D600000180020599C00000CE100E008B50E4B63 +:101D70001B6E9B0700D4FBBE72B60C4B00200C4AB6 +:101D8000C3F8400103F160430A49A3F55F231164DE +:101D90009D46BFF34F8F084A03F5E0430749126899 +:101DA000184619609368984700441F4000002E4071 +:101DB00000C00A40030020001C002000000012EBBD +:101DC000114B1249D86E0A4640F4403030B4D86600 +:101DD00040F23765D86EA02440F44070D8664D6458 +:101DE0008C64936C1B06FCD4094B40F23760A02135 +:101DF0001A4658649964936C13F08003FBD1054A2A +:101E0000137030BC704700BF00C00F4000400C4052 +:101E100000800C400C280020F8B500BFF8BC08BCBE +:101E20009E467047000000005FF800F0F9A3000034 +:101E30005FF800F00DB300005FF800F06996000055 +:101E40005FF800F0C5B300005FF800F009BA0000C9 +:101E50005FF800F005B000005FF800F085AE00000C +:101E60005FF800F0A5930000450000005D2200002F +:101E70001603550053004200200053006500720015 +:101E8000690061006C0000001803540065006500E3 +:101E90006E00730079006400750069006E006F00C9 +:101EA0000403090409024B00020100C032080B00C0 +:101EB00002020201000904000001020201000524DF +:101EC0000010010524010101042402060524060076 +:101ED000010705820310001009040100020A000036 +:101EE00000070503024000000705840240000000CF +:101EF00009024B00020100C032080B00020202017D +:101F0000000904000001020201000524001001057F +:101F100024010101042402060524060001070582AC +:101F20000310000509040100020A00000007050370 +:101F30000200020007058402000200000A060002F7 +:081F4000EF0201400100010065 +:101F48000000000000000000000000000000000089 +:101F58000000000000000000000000000000000079 +:101F680010B5054C237833B9044B13B10448AFF3CB +:101F780000800123237010BD481C002000000000D1 +:101F8800A4BF0000084B10B51BB108490848AFF3BF +:101F980000800848036803B910BD074B002BFBD02D +:101FA800BDE81040184700BF000000004C1C00208E +:101FB800A4BF0000C01A00200000000000207047E5 +:101FC800704700BF036D0BB101207047406D0030B2 +:101FD80018BF0120704700BF10B50446806D18B1C6 +:101FE8000BF0C0F90023A365236D2BB104F1180091 +:101FF800BDE8104006F020BC636D002BF6D110BD83 +:10200800F0B5002395B04FF47A74234F1A4605466D +:10201800183104A88DF804308DF80C3012931393FE +:102028000294009706F05CFC129B53B35C200026D8 +:102038000AF0D0FE9DF804300446184A04A9183066 +:102048002373029B22602361154A9DF80C30A2601D +:102058002375666006F0AEFB63684FF47A71114A27 +:102068000133A760A6652E712E732C616360A96089 +:102078002A600D4B04A8009306F0DEFB284615B035 +:10208800F0BD139B002BD1D1064A2B71AC602B738A +:102098002B612A60EDE700BFFC0500202006002028 +:1020A8007C060020D005002014050020036D13B124 +:1020B800184604F0C3BC406D08B102F031BA4FF0C5 +:1020C800FF307047836C00B583B063B118460122B6 +:1020D8000DF1070104F0E4FB01280CD19DF807007D +:1020E80003B05DF804FBC06C28B101220DF10701B3 +:1020F80002F03CF9F0E74FF0FF30F1E700B5836CF0 +:1021080083B08DF8071043B1184601220DF107017D +:1021180004F0B2FF03B05DF804FBC06C0028F9D0EE +:1021280001220DF1070103F043F903B05DF804FB48 +:10213800036DF0B50C4683B02BB318460DF10602BB +:1021480001A904F0E3F9D8B1BDF80430BDF80620C0 +:1021580003B9AAB102F01F06C3F343155912C2F31B +:10216800451703F01F037600013D01F5EA61D2121D +:1021780026706571A17123716770A27003B0F0BDFC +:10218800002003B0F0BD406D0028F9D00DF1060223 +:1021980001A902F06BF8D6E7036D9BB11A7812F02B +:1021A800700F00D1704710B504460021184604F09E +:1021B8009BFD606D28B100220023BDE8104002F0AD +:1021C800C5B910BD406D0028ECD090F8313013F03F +:1021D800500FE7D00022002302F0B8B938B5846D5B +:1021E8000CB1204638BD05464FF480700BF0B2F8AC +:1021F8000146A86580B1286D0C7028B14FF4807233 +:1022080006F026F8AC6DECE7686D40B14FF48072CB +:1022180003F09EFDAC6DE4E7024CAC65E1E70C46CB +:10222800DFE700BF0B2800208A79A2F150031B06C4 +:1022380021D402F26C72F0B54B7985B0046D01338C +:102248000D798E784F78DBB209784CB1039120462E +:10225800029702210196009504F066FE05B0F0BDD4 +:10226800406D0028FAD0039102218DE8E00002F0C9 +:102278005FFF05B0F0BD0020704700BFD0B5046D0A +:102288008CB1012B08BF002A01D30020D0BD114614 +:10229800204604F029FD0028F7D0204604F0B0FEBF +:1022A8000028F2D0D0BD446D002CEED0204602F0BC +:1022B8004DF90028E9D02046BDE8D04003F006B823 +:1022C800036DF0B50C4683B02BB318460DF106022A +:1022D80001A904F02BF9D8B1BDF80430BDF80620E7 +:1022E80003B9AAB102F01F06C3F343155912C2F38A +:1022F800451703F01F037600013D01F5EA61D2128C +:1023080026706571A17123716770A27003B0F0BD6A +:10231800002003B0F0BD406D0028F9D00DF1060291 +:1023280001A901F0B5FFD6E7036D13B15869002183 +:102338007047436D13B193E8030070471846194678 +:10234800704700BF036D13B1D86900217047436D12 +:1023580013B118695969704718461946704700BF84 +:10236800036D13B1184604F09BBA406D08B101F033 +:10237800FDBF4FF0FF307047836C13B1184604F06F +:102388005DBBC06C08B102F0CBB84FF0FF307047AE +:10239800036D33B11B7813F0700F14BF01200020B8 +:1023A8007047406D30B190F8313013F0500F14BFC2 +:1023B80001200020704700BF8A79A2F150031B0654 +:1023C80021D402F26C72F0B54B7985B0046D0133FB +:1023D8000D798E784F78DBB209784CB1039120469D +:1023E800029704210196009504F09EFD05B0F0BD0A +:1023F800406D0028FAD0039104218DE8E00002F036 +:1024080097FE05B0F0BD0020704700BF00690028A6 +:102418002FD00368184A1B6993420ED1026D6AB126 +:10242800137803F0080303F0FF0013B3D36950696E +:10243800181A48BF6FF0004070471847416DC9B17E +:1024480091F8313003F0080303F0FF008BB1D1E9B4 +:102458000423D1E9000130B4101A4FF000056FF0E1 +:10246800004463EB01018D4208BF844200D220463C +:1024780030BC7047084670472D070000036963B1F8 +:102488001A68074992698A4208D1186D08B104F0A0 +:1024980045BD586D08B102F0D7BC704718461047C3 +:1024A80079050000836C13B1184604F037BDC06C81 +:1024B80008B102F0C9BC7047036D13B1184604F0A7 +:1024C8002DBD406D08B102F0BFBC7047036973B100 +:1024D8001A68084952698A4207D1186D08B104F090 +:1024E800ADBA586D18B102F01BB8184610474FF036 +:1024F800FF3070476D010000036D13B1184604F0FA +:10250800BBBD406D08B102F053BF7047836C13B177 +:10251800184604F0B1BDC06C08B102F049BF70475D +:1025280003698BB10E4810B41C68E468844211D169 +:10253800186D18B15DF8044B04F09EBD586D28B1B4 +:102548005DF8044B02F034BF0020704700205DF8AE +:10255800044B7047184623465DF8044B184700BFE4 +:10256800B905000010B5036982B08DF80710BBB13A +:102578001968104ACC68944215D1186D30B10122FF +:102588000DF1070104F078FD02B010BD586D002868 +:10259800FAD001220DF1070102F00AFF02B010BDC6 +:1025A800184602B010BD01220DF107011846A047D8 +:1025B80002B010BDB9050000036923B31968134AB6 +:1025C80010B58C6882B0944214D1186D48B10122BC +:1025D8000DF1070104F064F990B19DF8070002B00D +:1025E80010BD586D0028F8D001220DF1070101F047 +:1025F800BDFEF1E7184601220DF10701A047EBE700 +:102608004FF0FF30EBE74FF0FF3070472104000038 +:10261800826C62B1137803F0080303F0FF000BB378 +:10262800D3695069181A48BF6FF000407047C16CF1 +:10263800C9B191F8313003F0080303F0FF008BB102 +:10264800D1E90423D1E9000130B4101A4FF0000594 +:102658006FF0004463EB01018D4208BF844200D251 +:10266800204630BC70470846704700BF026D62B113 +:10267800137803F0080303F0FF000BB3D369506924 +:10268800181A48BF6FF000407047416DC9B191F802 +:10269800313003F0080303F0FF008BB1D1E90423C4 +:1026A800D1E9000130B4101A4FF000056FF0004472 +:1026B80063EB01018D4208BF844200D2204630BC42 +:1026C80070470846704700BFD0B4039C16461F46A3 +:1026D80034B1012C1ED0022C0DD00020D0BC704784 +:1026E800046DDCB1012B08BF002AF6D22046114642 +:1026F800D0BC04F0F9BA036DB3B1DA69B61847F182 +:102708000007012F08BF002EE7D231461846D0BC7B +:1027180004F0EABA036D93B15A69EFE7406D0028F7 +:10272800DBD0D0BC01F012BF436D002BD5D01846CA +:10273800D3E9042392197B41D0BC01F007BF436D54 +:10274800002BCAD01846D3E9002392197B41E8E749 +:1027580038B504460C4B806D236018B10AF002FEB0 +:102768000023A365236D04F118054BB1284606F034 +:1027780063F8064B2846A36006F05EF8204638BD8D +:10278800636D002BF2D1F4E7200600201405002029 +:1027980038B504460E4B806D236018B10AF0E2FD8F +:1027A8000023A365236D04F118056BB1284606F0D4 +:1027B80043F8084B2846A36006F03EF820465C2103 +:1027C8000AF00AFB204638BD636D002BEED1F0E716 +:1027D800200600201405002070B5254B0546046925 +:1027E80003601CB16668013E66600EB1284670BD84 +:1027F8002368204ADB6A93422CD1A06D10B10AF0FD +:10280800B1FDA665236D5BB304F1180006F014F85A +:102818002C69002CEAD02368174A5B6893421CD1C4 +:10282800164BA06D236018B10AF09CFD0023A36528 +:10283800236D04F11806BBB1304605F0FDFF104BBF +:102848003046A36005F0F8FF20465C210AF0C4FA80 +:10285800284670BD20469847DAE720469847C5E7DE +:10286800636D002BD0D1D3E7636D002BE4D1E6E78D +:10287800D005002099000000510800002006002023 +:102888001405002070B5294B0446056903601DB185 +:102898006E68013E6E602EB1204614210AF09CFA43 +:1028A800204670BD2B68224ADB6A934230D1A86D5E +:1028B80010B10AF057FDAE652B6D7BB305F118001A +:1028C80005F0BAFF2569002DE6D02B68194A5B6828 +:1028D800934220D1184BA86D2B6018B10AF042FD25 +:1028E8000023AB652B6D05F11806DBB1304605F00A +:1028F800A3FF124B3046AB6005F09EFF28465C21D3 +:102908000AF06AFA204614210AF066FA204670BDD9 +:1029180028469847D6E728469847BDE76B6D002BB1 +:10292800CCD1CFE76B6D002BE0D1E2E7D0050020DA +:10293800990000005108000020060020140500201E +:1029480038B5044608460D460BF07AF82368024667 +:10295800294620465B689847054620460AF056F9FE +:10296800284438BD2DE9F04395B000236E4A6846E7 +:102978006E4906F05BF8129B002B00F0BC805C20CF +:1029880000240AF027FA9DF804200546684B694997 +:1029980004AE2A731830029AAB609DF80C30296097 +:1029A80031462A612B756C6005F004FF6B68624A3A +:1029B8000133AC65AA606B60DFF89C913046002457 +:1029C8005E4FCDF8009005F037FF0D215C480AF006 +:1029D8000DF85C482646DFF884810AF017F919E0FB +:1029E8002B689B6843454FD1286D002843D00422AB +:1029F800694603F055FF0098A212C4F30903A4EB3B +:102A0800822157F8222042F8210043B10134B4F55D +:102A1800803F0CD00096002DE2D12846ECE7013427 +:102A28000121494809F0E2FFB4F5803FF2D1ADB188 +:102A38002B68464EDB6AB3425AD1A86D18B10AF02A +:102A480091FC0023AB652B6D002B5AD005F11800C3 +:102A580005F0F2FE6C68013C6C60DCB10A2008F0FD +:102A6800A3FD10213A4809F0C1FF36480AF0CEF814 +:102A780015B0BDE8F083686D0028BDD00422694612 +:102A880001F074FC0098B7E7042269462846984785 +:102A98000098B1E72B68DB6AB34236D1A86D10B154 +:102AA8000AF060FCAC652B6D002B34D005F11800E2 +:102AB80005F0C2FE2B68274A5B68934228D11D4B5C +:102AC800A86D2B6018B10AF04DFC0023AB652B6D87 +:102AD80005F118041BB3204605F0AEFEC5F80890B2 +:102AE800204605F0A9FE28465C210AF075F9B5E7ED +:102AF80028469847AEE7139D002D7FF440AF04AEFB +:102B08005AE76B6D002BA1D1A4E728469847D1E777 +:102B180028469847A2E76B6D002BC7D1CAE76B6DB3 +:102B2800002BD8D1DAE700BFBC0A0020681C0020BF +:102B38007C06002020060020FC05002098260020A6 +:102B4800C40A0020BC110020D40A0020990000000B +:102B5800D80A0020510800001405002021040000B4 +:102B68000D4B002103F1800243F8041F9342FBD16F +:102B78000A4B002010B403F50071094C43F8040F08 +:102B88008B424FF00002F9D10649074B22600A60D8 +:102B98001A605DF8044B7047FC250020FC210020DA +:102BA80094260020A0270020E82700202DE9F047E0 +:102BB80096B00023824A02A8824905F037FF149B89 +:102BC800002B00F0D4805C2000260AF003F97E4A2E +:102BD80005469DF80C709DF8143006A97B4C1830FA +:102BE8002A60049A2F73AC602A612B756E6005F019 +:102BF800E1FD6B68764A06A80133DFF8E8A1AA6010 +:102C08006B60AE65CDF808A005F016FE7148724AF3 +:102C18000368296803F1FF3E9C1E0F6A52F82E10C4 +:102C2800DFF8C4E109030460774552F823400A46F7 +:102C38004FEAE17340F0AE80286D002800F08D80E7 +:102C4800012B08BF002A01D204F04EF8DFF89C815E +:102C58000027DFF89C9104F5806619E02B689B68D3 +:102C68004B4523D1286DC0B1042202A903F018FEF8 +:102C78000298002C2346B8BF04F2FF339B12A4EB42 +:102C88008322013458F82330A64243F8220013D097 +:102C98000297002DE2D12846EBE7686D0028E8D0BE +:102CA800042202A901F062FB0298E2E7042202A9C9 +:102CB800284698470298DCE7ADB12B68474EDB6A97 +:102CC800B34251D1A86D18B10AF04CFB0023AB6593 +:102CD8002B6D002B62D005F1180005F0ADFD6C6876 +:102CE800013C6C602CB10A2008F05EFC16B0BDE80F +:102CF800F0872B68DB6AB34254D1A86D10B10AF093 +:102D080031FBAC652B6D002B52D005F1180005F096 +:102D180093FD2B68324A5B68934246D12A4BA86DD3 +:102D28002B6018B10AF01EFB0023AB652B6D05F173 +:102D38001804002B40D0204605F07EFDC5F808A0F9 +:102D4800204605F079FD28465C210AF045F80A205E +:102D580008F02AFC16B0BDE8F087686D00283FF43B +:102D680075AF01F0F3FB71E728469847B7E7159D63 +:102D7800002D7FF428AFDFF86CA006A8CDF808A0D6 +:102D880005F05AFD134B14481A68911E50F822405A +:102D980019605BE700962846B84757E76B6D002B2C +:102DA80099D19CE728469847B3E7284698479AE779 +:102DB8006B6D002BA9D1ACE76B6D002BBBD1BDE7C8 +:102DC800EC0A0020681C0020200600207C06002059 +:102DD800FC050020E82700200026002099000000BC +:102DE80051080000140500208907000098260020DB +:102DF800210400002DE9F04397B044F20223824AEF +:102E080002A8824905F012FE149B002B00F0D28024 +:102E18005C20002609F0DEFF7D4A05469DF80C700F +:102E28009DF8143006A97B4C18302A60049A2F7339 +:102E3800AC602A612B756E6005F0BCFC6B68764A45 +:102E480006A80133DFF8E891AA606B60AE65CDF89B +:102E5800089005F0F1FC7148714A0368296803F18C +:102E6800FF3E9C1E0F6A52F82E10DFF8C8E10903D6 +:102E78000460774552F823400A464FEAE17340F070 +:102E8800AC80286D002800F08B80012B08BF002A39 +:102E980001D203F029FF634F04F58066DFF89881BB +:102EA80004E004F0E9F80134A64223D0002C2346BC +:102EB800B8BF04F2FF339B12A4EB832257F82330E8 +:102EC80053F822300293002DEDD02B68042202A97A +:102ED800DB6843452BD12B6D1846002BE1D16B6D78 +:102EE800042202A91846002BDDD0013402F060FA52 +:102EF800A642DBD1ADB12B684B4EDB6AB34256D14B +:102F0800A86D18B10AF02EFA0023AB652B6D002BC3 +:102F180067D005F1180005F08FFC6C68013C6C6007 +:102F280054B10A2008F040FB17B0BDE8F083042232 +:102F380002A928469847B6E72B68DB6AB34254D102 +:102F4800A86D10B10AF00EFAAC652B6D002B52D0AB +:102F580005F1180005F070FC2B68344A5B68934251 +:102F680046D12B4BA86D2B6018B10AF0FBF9002352 +:102F7800AB652B6D05F11804002B40D0204605F0F9 +:102F88005BFCC5F80890204605F056FC28465C21F5 +:102F980009F022FF0A2008F007FB17B0BDE8F0830C +:102FA800686D00283FF477AF01F0D0FA73E7284640 +:102FB8009847B2E7159D002D7FF42AAFDFF870908F +:102FC80006A8CDF8089005F037FC144B14481A6889 +:102FD800911E50F8224019605DE700962846B847D0 +:102FE80059E76B6D002B94D197E728469847B3E7CC +:102FF8002846984795E76B6D002BA9D1ACE76B6D18 +:10300800002BBBD1BDE700BFEC0A0020681C0020E4 +:10301800200600207C060020FC050020E827002070 +:103028000026002098260020990000005108000082 +:103038001405002089070000B9050000F8B5584CB0 +:10304800584D226855F82230511E013B2160182B3B +:1030580015D8DFE803F0151E27331414141414458B +:103068004D6114141414141414777F878F970D006E +:1030780008F08CF82368013345F823002360F8BD75 +:10308800023A15F8210001212260BDE8F84008F055 +:1030980057BB023A15F8210000212260BDE8F8402C +:1030A80008F04EBB931E55F82110033A15F823007B +:1030B800C9B22260BDE8F84008F04EBB023A15F8E4 +:1030C8002100374D226008F041FB364A2B68002862 +:1030D80060D001334FF0FF312B6042F82310F8BD68 +:1030E800023A55F821002260BDE8F84008F05CBAC1 +:1030F8002D4B023A2D4F22601C4618682C4E3A6818 +:1031080055F82130A6FB0212920C03FB02F2236849 +:103118001B1A9A42FBD8F8BD234B023A234E226071 +:103128001C461868336855F821101B0C214A01FB0E +:1031380003F35B08A2FB0332120A23681B1A9A42A4 +:10314800FBD8F8BD07F0D2FF2368013345F8230008 +:103158002360F8BD07F0DAFF2368013345F8230040 +:103168002360F8BD07F0E2FF2368013345F8230028 +:103178002360F8BD07F0EAFF2368013345F8230010 +:103188002360F8BD07F0F2FF2368013345F82300F8 +:103198002360F8BD01332B6042F82300F8BD00BF5F +:1031A800E827002000260020041000E06811002015 +:1031B80083DE1B43112397082DE9F043612283B076 +:1031C800002301388DF804208DF805301C2836D8E6 +:1031D800DFE810F02C02220219020C02FD01EE01B8 +:1031E800E301D001B701A60190017F016F015E01E3 +:1031F8004D0138011F0112010501F700E600D90051 +:10320800CC00BF00B200A500680038001D00BE4D0C +:10321800BE4E2A6856F82230511E032B296000F052 +:10322800678240F31C82062B00F05D8240F35382D4 +:10323800072B00F06382642B01D1FFF7FFFE03B078 +:10324800BDE8F083B049B14A0B68DD1E5C1E981ECC +:1032580052F823600D6052F8247052F82030002E86 +:10326800EDD01E44FF1AAA4CFA18002B1846B8BF16 +:1032780003F2FF30002A11464FEAA020B8BF02F23D +:10328800FF31A3EB802554F820008912013350F850 +:103298002500A2EB8122B34254F8211041F8220004 +:1032A800E2D1CCE7984D994E2B68D81EA3F10208BD +:1032B800591E56F82320286056F8213056F8280061 +:1032C800002A00F0248202EB030EC3EB000C4FF03F +:1032D800FF378F4C0CEB0302002B1846B8BF03F2E4 +:1032E800FF30002A1146B8BF02F2FF31801289125E +:1032F800A3EB802954F82000A2EB812254F8211076 +:10330800013350F8290051F82220824218BF0027C3 +:103318007345DFD1C5F8008046F828708FE77A48F2 +:103328007A4B01684A1E53F8214053F82210026074 +:10333800214143F8221082E77348744B01684A1E02 +:1033480053F8214053F822100260A14043F822109C +:1033580075E76D486D4B01684A1E53F8214053F8D4 +:1033680022100260614043F8221068E76648674B04 +:1033780001684A1E53F8214053F822100260214385 +:1033880043F822105BE76048604B01684A1E53F817 +:10339800214053F822100260214043F822104EE7E2 +:1033A800594A5A4B1168481E53F8212053F82050A7 +:1033B80095FBF2F402FB145243F8214043F8202015 +:1033C8003DE75148514B01684A1E53F8211053F804 +:1033D8002240026001FB04F143F822102FE74A481B +:1033E8004A4B01684A1E53F8214053F822100260E4 +:1033F800091B43F8221022E74348444B01684A1E40 +:1034080053F8211053F822400260214443F8221057 +:1034180015E73D4D3D482A6850F82230511E002BD3 +:103428001A4650F82110B8BF03F2FF3238489212FA +:10343800A3EB822350F8222042F823102B68023B8A +:103448002B60FCE6304B314E1968314856F8213074 +:10345800002B1A46B8BF03F2FF329212A3EB822365 +:1034680050F8222052F8233046F82130E7E6264863 +:10347800264B01684A1E53F8214053F82210026077 +:10348800A1424FF0FF31D8BF002143F82210D6E601 +:103498001D481E4B01684A1E53F8214053F822105C +:1034A8000260A1424FF0FF31A8BF002143F822106B +:1034B800C5E61548154B01684A1E53F8214053F8D4 +:1034C80022100260091B18BF4FF0FF3143F8221089 +:1034D800B5E60D480D4B01684A1E53F8214053F8D4 +:1034E80022100260A1424FF0FF3118BF002143F8BB +:1034F8002210A4E6074B084C1A680849501E54F8D5 +:10350800222018600A609AE6E8270020002600209A +:1035180098260020A02700200022002094260020C2 +:103528007C4A7D4913685C1E981E51F8233051F877 +:103538002410106000293FF482AE013B774A1360E3 +:103548007DE6744A744913685C1E981E51F823304E +:1035580051F82410106000293FF471AE7049013B06 +:103568006E480A68056801326E4C03600A6044F8C8 +:10357800225064E6674D684A2B68694852F8231060 +:103588005A1E664C0368013927680133654E2A6064 +:103598002160036046F8237051E65E495E4A0B6875 +:1035A8005E4852F82320013B013A0B60026046E670 +:1035B8005B49584A086813685A4C451E013354F849 +:1035C800204055480D60136040F8234037E65449C1 +:1035D800504A0B681068504E0133451E514C56F83E +:1035E80020000B60156044F8230028E6494A4A4B3E +:1035F8001268511E53F8220053F8214043F8224024 +:1036080043F821001BE6434B002443481A68511E27 +:1036180040F82240196012E63E493F4B0868421CB8 +:1036280053F820000A6043F8220008E63B4A3E4867 +:1036380011684B1C002B13601A46B8BF01F5806255 +:1036480034499212A3EB822350F822000A6850F8FA +:103658002300531C304A0B6042F82300EFE5012B8E +:1036680021D048DC002B7FF4EAAD56F8213002ACBB +:10367800023A04F8043D20462A600AF0E1F90146BE +:10368800204609F0B3F99DF804300A2B7FF4D7AD32 +:103698000D2320468DF804300AF0D2F90146204661 +:1036A80009F0A4F9CBE509F07BF9041EFBDD02AFB4 +:1036B80007F8044D38460AF0C3F90146384609F0C0 +:1036C80095F92B680D2C03F1010308BF0A242B6020 +:1036D80046F82340B3E5052B7FF4B1AD0F4B4FF00F +:1036E800FF321A60ABE50D4B4FF480321A60A6E545 +:1036F800FFF780FBA3E5FFF759FAA0E50848531C3C +:1037080046F8221002682B6046F8232097E54FF010 +:10371800FF37FFE5E8270020002600209426002038 +:10372800A0270020002200209826002070B5002243 +:103738001A4E1B4D134632600DE0C4F30720F8B94A +:10374800C4F3074010BB200E24D133680133B3F50E +:10375800803F336021DA002B1A46B8BF03F2FF32EC +:103768009212A3EB822355F8222052F8234014F03A +:10377800FF00E2D0FFF720FDC4F307200028DFD0C8 +:10378800FFF71AFDC4F307400028DCD0FFF714FD4B +:10379800200EDAD0FFF710FDD7E770BD9426002081 +:1037A800982600202DE9F043584D8FB040F2EE29BD +:1037B800574C2E68DFF89881564F04E0B3F5FA6F3E +:1037C80015D809F01FFB09F01DFB237843B198F8C1 +:1037D8000030DB0704D52B683A689B1A0E2B06D8F5 +:1037E8002B6822789B1B002AE8D14B45E9D94A4C23 +:1037F80013214A4809F0FAF8494804F5807509F098 +:1038080005FA4FF4805009F0A5FD44F8040FAC42C6 +:10381800F7D11521434809F0E9F8414809F0F6F9CC +:10382800414B0121414E187807F096FF1621404878 +:1038380009F0DCF83A4809F0E9F93046FE2100F0D1 +:103848002BFC38B93B213B4809F0D0F8344809F043 +:10385800DDF9FEE71621384809F0C8F8304809F0C4 +:10386800D5F9D6F884444CB300272146334A684634 +:103878003B466D468DF800708DF801708DF802702A +:1038880002F0E4FFA8B12E492548FFF759F8D6F809 +:103898008444264B1CB3002621462846294A334631 +:1038A8008DF800608DF801608DF8026002F0CEFF9F +:1038B80023E025491A48FFF743F8FEE7D6F88814AD +:1038C8000029F6D023461D4A68466D468DF83140DA +:1038D8008DF832408DF8334001F016F9D2E7D3F86D +:1038E800881471B128462346164A8DF831408DF860 +:1038F80032408DF8334001F007F910B10FB0BDE840 +:10390800F08312490648FFF71BF8FEE7F02700206E +:10391800152800207C28002094260020F40A002086 +:10392800BC110020080B0020FC150020641C00209E +:10393800200B0020380B0020740B0020BC0A00204C +:10394800BC0B0020EC0A00208C0B0020D40B0020BC +:103958001428002008B5FFF703F9FFF703F8BDE8BE +:103968000840FFF7E3BE00BF2DE9F843DDF82080EB +:10397800099FB3B116460C46054603EB010904E05E +:1039880020460134C0474C450BD02B6832462146AF +:1039980028461B6998473A4631460028F0D1BDE8C9 +:1039A800F8830120BDE8F8832DE9F843DDF820808D +:1039B800AAB11F460C46054602EB010901E04C4539 +:1039C8000DD02B68414620465E6AB847214602461C +:1039D80028460134B0470028F1D1BDE8F88301201A +:1039E800BDE8F8830020704700207047002070472A +:1039F8004FF0FF30704700BF704700BF30B583B04D +:103A080005460C4607F0E8FE1C4B984204D80023F4 +:103A18002B80238003B030BD694609F007F99DF873 +:103A280005309DF8062001339DF80410503ADBB2AA +:103A380092B20C2B98BF1F291CD87F2A1AD841EAAA +:103A4800431343EA422292B29DF802009DF8011006 +:103A58002A80172898BF3B299DF800300CD83B2BAB +:103A68000AD8490141EAC02141EA53039BB22380A5 +:103A780003B030BD0022E7E70023F8E7FFA5CE1228 +:103A8800012BF0B5054695B03BD0022B01F104019E +:103A980040F20223684618BF002304F0C7FF129BB8 +:103AA800002B37D05C2004AF09F094F99DF804206E +:103AB80004461F4B0026DFF888E022733946029A35 +:103AC8001830A3609DF80C3022612375C4F800E01B +:103AD800666004F06FFE63684FF47A71154801332D +:103AE800154AA6652E712E732C61A0606360A960CB +:103AF8002A60124B3846009304F09EFE284615B003 +:103B0800F0BD44F202230431684604F08FFF129B93 +:103B1800002BC7D1139B002BC4D14FF47A71064AEE +:103B28002B7104AF2B732B61A9602A60E1E700BFFA +:103B38007C060020FC050020D0050020140500208C +:103B48002006002070B5D0F884448EB01646C4B163 +:103B5800002504F589640A46684621462B468DF8F7 +:103B680000508DF801508DF8025002F009FE08B996 +:103B78000EB070BD32462146684602F095FF0EB081 +:103B880070BDD0F888040028F2D000F589650A468F +:103B98002346684629468DF831408DF832408DF825 +:103BA800334000F033FF0028E2D032462946684609 +:103BB80001F066FA0EB070BD30B5D0F884448FB00D +:103BC800A4B100250A466846214601238DF8005015 +:103BD8008DF801508DF8025002F038FE08B90FB088 +:103BE80030BD684603F0FEFE0FB030BDD0F8880443 +:103BF8000028F4D00A460123014668468DF8314072 +:103C08008DF832408DF8334000F07EFF0028E6D072 +:103C1800684600F0E3FF0FB030BD00BF30B5D0F804 +:103C280084448FB0A4B100250A46684621462B4635 +:103C38008DF800508DF801508DF8025002F006FE04 +:103C480008B90FB030BD684603F020F80FB030BD9A +:103C5800D0F888040028F4D00A462346014668466E +:103C68008DF831408DF832408DF8334000F04CFF2C +:103C78000028E6D0684601F011F80FB030BD00BF4B +:103C880030B5D0F884448FB07CB100250A460123B2 +:103C980004F5896168468DF800508DF801508DF85B +:103CA800025002F005FD0FB030BDD0F8880400289E +:103CB800F9D00A46012300F5896168468DF831403C +:103CC8008DF832408DF8334001F06EF90FB030BDF9 +:103CD80030B5D0F884448FB074B100250A466846E0 +:103CE80021462B468DF800508DF801508DF8025072 +:103CF80002F0ACFD0FB030BDD0F888040028F9D030 +:103D08000A462346014668468DF831408DF8324010 +:103D18008DF8334000F0F8FE0FB030BDF8B590F8DC +:103D2800D034002B46D0D0F884240446002A46D04C +:103D3800D369D0F890045F1E00283ED00368DB6B7F +:103D4800984730B1D4F8900430B303681B6C984797 +:103D5800A0B1D4F884240026002A4AD0104604F0E2 +:103D680033FC05463EB1D4F89004A8B1036800219D +:103D78005B6C984780B1D4F8842410E0D4F89004A0 +:103D880050B1036801215B6C984728B1D4F88424AA +:103D98000126002AE2D12CE00025D4F884247B1BDC +:103DA800F2B190794FF4007202FA00F080B2A0FBF1 +:103DB8000301F8BD00200021F8BD0646CEE7D0F883 +:103DC8008834F3B1D3F83074D4F890040028B5D10E +:103DD8001946A3B10646084602F0CAF90546C1E7E6 +:103DE800D4F88824002AE5D0D2F83C04A3FB0001CB +:103DF800F8BDD4F888140029EDD11546B2E71D4660 +:103E0800CDE71F46E0E700BF90F8D03463B1D0F8A3 +:103E1800842462B191794FF40073D0698B400138E2 +:103E28009BB2A3FB00017047002000217047D0F827 +:103E38008824002AF8D0D2F83034D2F83C04A3FB06 +:103E4800000170472DE9F041D0F8905492B04DB17F +:103E58001F462B6804462846DB699847B0F5405F43 +:103E6800064603D8002012B0BDE8F0814FF4007078 +:103E780009F070FA80460028F4D0B6F1806F07AEDA +:103E880002463B462946304644D804F089F807469E +:103E9800404609F067FA002FE4D02B6828461B6AD1 +:103EA800984794F8C054FF2D38D094F8C18401AADB +:103EB800D4F8C4C404ABD4F8C8E404F594678DF806 +:103EC80004508DF80580CDF808C0CDF80CE007CA7D +:103ED80083E807008DF81180CDF814C0CDF818E0FC +:103EE8008DF8105093E8070086E80700384696E8F2 +:103EF8000E0005F0A9FA94F8B134C4F890742BB9FF +:103F080001233946201D1A4604F01CFD012012B079 +:103F1800BDE8F08101F024FC0746B9E704F29443B8 +:103F280084F8C05494F8CC141D46184605F0E4FFF4 +:103F3800C4F89054284605F05FFB0028E6D1012319 +:103F4800D4F89014201D1A4604F0FCFCDEE700BFEC +:103F58002DE9F041D0F890648AB00446002E48D08C +:103F680090F8D034002B4AD190F8D134FE2B5AD097 +:103F780090F8D204362835D994F8C064FF2E71D051 +:103F880094F8C18403ADD4F8C4C406ABD4F8C8E42B +:103F980004F594678DF800608DF80180CDF804C0B1 +:103FA800CDF808E09DE8070085E807008DF80D804A +:103FB800CDF810C0CDF814E08DF80C6095E8070036 +:103FC80083E8070038460ECB05F03EFA94F8B13482 +:103FD800C4F890746BB901233946201D1A4604F0C1 +:103FE800B1FC07E007F0B2FB003018BF0120002841 +:103FF800C2D1002084F8D0040AB0BDE8F08190F85E +:10400800D134FE2B16D094F8D204362805D807F000 +:104018009DFB003018BF0120ECE73368304606A945 +:104028009B6C9847E6E71B4B9868C0F34040002814 +:10403800DFD0A1E7336830465B6D9847431C0546DF +:10404800E1D048B994F8D134FE2BD2D12E200321E7 +:1040580007F082FB2846CDE7012084F8D0040AB097 +:10406800BDE8F08104F2944594F8CC1484F8C06457 +:10407800284605F041FFC4F89054284605F0BCFADC +:104088000028B6D10123D4F89014201D1A4604F054 +:1040980059FCAFE7008000422DE9F0410E46044686 +:1040A8008AB03C4806F0A4FBFE2E84F8D16439D0CF +:1040B800362E03D900200AB0BDE8F0810025DFF8CC +:1040C800D8E001AA8DF804608DF8055004AF039577 +:1040D80007ABCDF808E004F5946884F8C06484F868 +:1040E800C154C4F8C854C4F8C4E407CA87E8070030 +:1040F8008DF81150CDF814E006958DF8106097E80A +:10410800070083E8070040460ECB05F09DF994F8B8 +:10411800B134C4F890842BB3284684F8D0040AB08C +:10412800BDE8F081002304F29445FF22194684F883 +:10413800CC3484F8C024284605F0DEFEC4F8905438 +:10414800284605F059FAA0B12E2300250321184668 +:1041580084F8D05484F8D23407F0FEFA28460AB01E +:10416800BDE8F08101234146201D1A4604F0EAFB10 +:10417800D3E70123D4F89014201D1A4604F0E2FB7B +:104188000028E1D001222E2384F8D02484F8D234E8 +:1041980091E700BFBD1A000040787D01F0B4184BCC +:1041A8000024184EFF25072117482927174AC3F866 +:1041B8009464174E18601846C3F8A824C3F8AC14C2 +:1041C80083F8B174C3F8A064C3F88444C3F888447E +:1041D800C3F8904483F89C4483F89D4483F8B5441D +:1041E80083F8BC4483F8CC4483F8D04483F8D15492 +:1041F80083F8D254074A0849F0BC09F071B800BFE7 +:10420800641C0020D0060020A006002000093D0004 +:104218003805002060110020B91A0000F0B500F13F +:10422800240385B005460E4601AC174693E80700FF +:1042380084E8070072012146286A01F025FF012859 +:1042480006D13A462146286A01F0E2FE05B0F0BDE3 +:10425800002005B0F0BD00BF10B5044600F0F4FD25 +:10426800002384F8313084F8333010BD38B50D465A +:10427800144600F124010022006A01F0C9FE034639 +:1042880028B1428901202A801B89238038BD38BD86 +:1042980038B50D46144600F124010022006A01F0E9 +:1042A800B7FE034628B1C28901202A809B89238052 +:1042B80038BD38BD90F831200AB10020704738B5B4 +:1042C8000D4611463822044609F03EFB40230120E2 +:1042D800256284F8313084F8330038BDF0B40C78A6 +:1042E800202C03D111F8014F202CFBD00E461E4F75 +:1042F800116091603578344601362F2D18BF002D96 +:1043080022D0A5F122041F2DE4B28CBF0021012187 +:104318001D2C0ED90124A14213D205F0BF013C295E +:104328000FD05C2D0DD02E2DE4D0202DE2D096603C +:10433800E0E727FA04F404F0010484F00104A14240 +:10434800EBD30020F0BC7047202D01D02F2D05D1D4 +:1043580014F8011F2029FBD02F29F9D01C60114621 +:10436800F0BC01F05BBD00BF010100312DE9F04F49 +:1043780090F8333083B00546DE0760D55C060E46FC +:10438800914640F1BD80D5E90001D5E9042310EB41 +:10439800090A41F1000B5B4508BF5245C0F0B680E1 +:1043A800B9F1000F74D0AA464C4640F2FF17FAE85C +:1043B80006012B6AD3F8382402EA0008C8F3080B70 +:1043C800B8F1000F6AD150EA010279D195F831208D +:1043D80051064CBFD3F83414E969A9614FEA582053 +:1043E8000239D3F82C24BC4293F845E4024401FA7C +:1043F8000EF111442ED9BBF1000F2BD1D3F81C229A +:10440800914227D0B4F5806F61D34FF0010C4FEA89 +:1044180054280CFA0EFEC0EB0E00804528BF8046DB +:1044280091423DD801EB0800824239D203F504706D +:104438000191009306F0CAF9009B019980BB95F899 +:1044480032304FF0FF3043F0020385F8323003B0CA +:10445800BDE8F08F03F50470002206F087F9002804 +:10446800EDD0CBF5007800EB0B013046A04528BF16 +:10447800A046424606F09CFE404600214644D5E947 +:10448800002380185941B4EB0804C5E9000190D114 +:104498000024C4EB090003B0BDE8F08FA9699DE7CB +:1044A800D3F8140232464346D0F800E0DEF814B0E0 +:1044B800D8470028C3D04FEA482800214046DDE706 +:1044C80095F83320520610D5A969013185E7D3F84C +:1044D8001402324603681B6998470028AFD04FF48E +:1044E800007000214FF40078C8E718465246A969C1 +:1044F80001F0AAFD0028A2DB0BD02B6AA9696DE7A1 +:1045080090F8313018073FF53EAF49E7C0EB020994 +:1045180046E795F8313013F0500FBAD18FE700BF56 +:10452800F0B583B00122044685690DF10701D0E991 +:104538000067FFF71BFF0128A5610CBF9DF8070066 +:104548004FF0FF30C4E9006703B0F0BD2DE9F04F2C +:1045580090F831E085B004468569BEF1000F36D089 +:1045680016461F46D0E90001994208BF904265D01F +:1045780056EA070330D10023A3610120C4E900678C +:1045880005B0BDE8F08F10F1FF3241F1FF3322FA98 +:104598000CFC03FA08F823FA0AFA50EA01034CEA79 +:1045A800080C4CEA0A0C4BD0E34549D3CCEB0B0B77 +:1045B800A94604F118085D464246002DDDD0A169E0 +:1045C800013D206A01F040FD0028F5DC4D46002041 +:1045D800A56105B0BDE8F08F1EF0080F27D1236A4A +:1045E80016F1FF3893F845C447F1FF39C2460393E3 +:1045F8000CF1090CCB4694F833905FFA8CFC19F057 +:10460800400FCCF120082AFA0CF2CDE900AB019B4F +:10461800ACF1200A03FA08FB23FA0AF342EA0B0278 +:1046280042EA030BAFD0E3695B44A361A5E7D4E991 +:104638000423BB4208BFB242C9D3D0E70120C8E770 +:104648001EF0400F02D1E369A361B1E7039BD3F8E1 +:104658003434F9E72DE9F04F8FB08146019390F893 +:1046680031302BB991F831300C4613F0500F08D186 +:104678000023184689F8313089F833300FB0BDE887 +:10468800F08F019B154603F00303012B06D0022B84 +:1046980000F0FF80002BEBD1012200E00222019BF9 +:1046A80003F0080313430293002D40F0DD80032735 +:1046B8000026029BB34643F040030393202206A939 +:1046C8002046FFF753FEF0B12028D1D19DF81830CD +:1046D800180645D4BBF1000F04D12268D4F818A0FD +:1046E800A2F12008BB4503D20BF1010B5FFA8BFB4B +:1046F800002B00F0D080202206A920460026FFF7D4 +:1047080035FE0028E0D1019B9905B1D5029B9A0797 +:10471800AED5002DACD0BB4580F0C6802B465E469A +:1047280055469A460AE02028A2D11EB92268A569F2 +:10473800A2F12008DEB2B74240F2B380202206A9D7 +:104748002046FFF713FE731C0028ECD12046D4F84E +:1047580018B000F0A9FB00288AD0C4F818B0EAE71E +:1047680056BBBB4538BF4FF0000B852BA6D1314651 +:1047780038224846012609F0E7F89DF81C309DF8D4 +:104788001920D90689F8302003F0370258BF42F0C3 +:10479800080289F831202368226AA169203BC9F8F8 +:1047A8002020C9F82830C9F8241094F83330C3F30E +:1047B800801389F82C3081E7C02B29D0C12B9AD1DE +:1047C8002A4606A9484601F09DFA002867D0AB8919 +:1047D800002B7FF473AFAA686B689A427FF46EAFC0 +:1047E800019B1F053FF544AF019B13F4884F40F030 +:1047F800AB8099F833309E0700F1A680019B5B05DA +:104808003FF536AF019B580400F1BC80012035E725 +:104818009DF819309DF808209B0789F8332003D5A7 +:104828009DF80C3089F833300B99DDE90823C9F875 +:104838001C10DDE90C01C9E90423C9E90201002DB6 +:10484800CED09DF81B304FF000002A6929689A42A3 +:10485800A88169607FF44FAFBDF81C60AB8AF61A77 +:10486800B6FA86F6760929E72B69664F0E33A7FB59 +:104878000337D4E90023FF08134307F10207FFB207 +:104888003FF416AF002100220023A161C4E90023F0 +:104898000EE7032203E7002D7FF435AFE8E606466E +:1048A8000CE75346AA461D4694F833B03822002137 +:1048B800484609F049F8CBF3801B0823226A0026F2 +:1048C80089F82CB0C9F824A0C9F8288089F83130B3 +:1048D8002B68C9F820206B60AE818FB307F1FF38D1 +:1048E80034465FFA88F8012221464846FFF796FCCD +:1048F800834600283FF4BCAE90F90030002BFFF649 +:10490800B7AE2022002109F01FF8002E43D0012C59 +:104918005ED0C1235C460BF11E0A8BF80030AB89D0 +:1049280028461BB96A68AB689A4205D005F06CFF47 +:1049380024F8020FA245F2D10136F4B2BC42D2D318 +:10494800484600F081FA99E699F8313013F0110FD2 +:104958007FF48EAE019B5D057FF554AF99F8333037 +:104968009C077FF585AE002200234846FFF7EEFD41 +:1049780000283FF47DAE484600F0A8FC00283FF42C +:1049880077AE43E74846D9E90423FFF7DFFD00285F +:104998007FF43CAF6CE685238BF800301A4B89F81E +:1049A80030808BF801801B681BB30DF113020DF1E9 +:1049B800160105A89847BDF81410BDF816209DF8F3 +:1049C8001330ABF80A10ABF808208BF81430B3E7B3 +:1049D800029BC0228BF8014063F07F038BF8002014 +:1049E80089F833302B698BF80330AB8AABF8043085 +:1049F800A2E745F22163ABF80A30ABF80E30ABF80A +:104A0800123099E789888888882100202DE9F043A9 +:104A1800064697B000200D4696F8311001928DF8A1 +:104A280051008DF852008DF85300ADF8140029B9E3 +:104A3800994695F8313013F0500F03D1002017B084 +:104A4800BDE8F083137814462F2B32D04FF00008BE +:104A5800214601AB02AA3046FFF740FC0028EDD002 +:104A6800019B1B78002B39D02946002302AA304627 +:104A7800FFF7F0FD0028E1D0344608AF06F1300E0C +:104A88002068103454F80C1C3D4654F8082C103794 +:104A980054F8043C74450FC5F2D1206808AD38605D +:104AA800304600F0D1F986F8318086F83380019CD1 +:104AB800CEE70134019421782F29FAD0B9B108A89A +:104AC800382200212F6A054608F03EFF40220123C4 +:104AD80010978DF851208DF85330B7E74B4602AA4E +:104AE80029463046FFF7B6FD17B0BDE8F0833822F7 +:104AF80030462C6A08F028FF40230120346286F8EB +:104B0800313086F833009AE719B101F58961FFF76A +:104B18007DBF0846704700BFF0B490F8314024B913 +:104B280091F8313013F0500F02D10020F0BC7047DB +:104B3800D1E90067002706F01F0656EA0703F4D1FB +:104B480013462246F0BCFFF785BD00BF8169F8B562 +:104B58000446006A01B10131012201F0A9F90128D6 +:104B680006462ED901230146206A1A4601F0FAF9B1 +:104B7800074630B3A3693BB394F83320510612D5E6 +:104B8800591C8E4226D022F04002E16984F8332075 +:104B980005E0206A01F09CFA294690B1A3694D1CF2 +:104BA80099422A46F5D34FF0FF323146206A01F088 +:104BB8008FFA30B1A16969B13246206A01F088FAEA +:104BC80040B900273846F8BD94F8333043F0400325 +:104BD80084F83330A6613846F8BD00BF90F833300A +:104BE8009A073BD5C1692DE9F0410546A9B90024CA +:104BF80008E00378E4B203F07F03037095F83030DF +:104C0800A3422DD32146012228460134FFF706FB93 +:104C18000028EED10020BDE8F0815B06006A37D598 +:104C280090F845240023D5E90267093216F1FF36CA +:104C3800D2B247F1FF37C2F1200EA2F1200426FAC2 +:104C480002F207FA0EFE27FA04F442EA0E022243A1 +:104C5800013201F087F90028C9D1DBE7002070474D +:104C680000232C6A85F83130204685F8333005F06A +:104C7800ADFD0028CED004F5047005F0A7FD00288E +:104C8800C8D0D4F840040368BDE8F0411B6A18474F +:104C980001F030FA0028AAD1BCE700BF90F8313003 +:104CA800D90601D40020704710B5002288B000232F +:104CB8000446FFF74BFC06E0202819D19DF8003088 +:104CC8001A0615D433B1202269462046FFF74EFB59 +:104CD8000028F1D194F833300822204643F002032B +:104CE80084F8312084F83330FFF778FF08B010BD1E +:104CF800002008B010BD00BF2DE9F043002583B0A7 +:104D08000746DFF84091A846002229463846FFF7B3 +:104D180085FA044630B10378C02B74D0C12B2CD04F +:104D2800852B09D097F83230002043F0010387F82B +:104D3800323003B0BDE8F08397F83130D9F800601D +:104D480003F03703838086B10DF103020DF10601EC +:104D580001A8B047BDF80620BDF804309DF803103F +:104D6800A28161752282E38163823A6A92F81032E5 +:104D780043F0010382F8103223784FEAC830A3F1D8 +:104D880085060022012140EA5808B6FA86F613FA89 +:104D980088F376091FFA83F80A444FEAC8330321D7 +:104DA8001F2A43EA58030AD8A05C012A10FA83F3A1 +:104DB8001FFA83F801D1002EEED10121ECE701356D +:104DC80097F83030EDB2AB429ED2012207F12401B0 +:104DD800386A01F01DF90028A4D03C6AA0F80280C6 +:104DE800204605F0F3FC00289CD004F5047005F07B +:104DF800EDFC002896D0D4F8400403681B6A984755 +:104E080000288FD095E797F8333013F0400F437898 +:104E180014BF43F0020323F002034370386AF969B0 +:104E2800D7E904236161C4E90223D7E90223C4E96D +:104E3800062390F8103243F0010380F810322378EB +:104E48009BE700BF8821002090F8312092B138B547 +:104E580090F8332011060FD4056A0446284605F059 +:104E6800B5FC88B994F83230002043F0010384F887 +:104E7800323038BD0120704702F07F0280F83320BD +:104E8800BDE83840FFF738BF05F5047005F09EFC13 +:104E98000028E7D0D5F8400403681B6A9847002823 +:104EA800E0D0012038BD00BFF8B590F83130054694 +:104EB8005A064FD480682B6AD3F83C341844B0F1B2 +:104EC800806F01D30020F8BD2846FFF73FFE002879 +:104ED800F8D0286A0122AE6990F84534023ED0F82D +:104EE8002C149E4012FA03F30E4415D000243119F5 +:104EF800052200F50470013405F038FC4FF4007207 +:104F080000210028DED008F01FFD286A012390F850 +:104F180045249340A342EAD895F831305B0614D46F +:104F280095F83330002763F07F0385F83330D0F8E5 +:104F38003C64D5E90223D5E9040192197B41801923 +:104F48007941C5E90223C5E904012846BDE8F840CE +:104F5800FFF77ABF006A01F0B9F9ACE710B591F82C +:104F6800314014F0500F01D1002010BD40F602234B +:104F78000446FFF76FFB0028F6D01023204684F87C +:104F88003130FFF791FF0028EED0A16900232046B9 +:104F98000022E161FFF7DAFAC123204684F83330B2 +:104FA800BDE81040FFF750BF2DE9F041064696B026 +:104FB80000200C4696F831100192ADF814008DF8D7 +:104FC80051008DF852008DF8530029B9984694F88D +:104FD800313013F0500F03D1002016B0BDE8F08136 +:104FE800137811462F2B34D001AB02AA3046FFF7B5 +:104FF80075F90028F0D0019B1B78002B37D00023CF +:1050080002AA21463046FFF725FB48B9B8F1000F40 +:10501800E2D0214602AA3046FFF7A0FF0028DBD0E5 +:10502800344608AF06F1300E2068103454F80C1CD2 +:105038003D4654F8082C103754F8043C74450FC505 +:10504800F2D1206808AC38603046FFF705F90199BD +:10505800CAE7013101910B782F2BFAD0216A08A8F1 +:10506800FFF728F90028B7D008AC0199BCE702AAD5 +:1050780021463046FFF772FF16B0BDE8F08100BF49 +:10508800F0B590F831409DB0002314F0180F8DF85A +:1050980031308DF832308DF833308DF869308DF835 +:1050A8006A308DF86B3003D00B6A046A9C4202D0D8 +:1050B80000201DB0F0BD044640F601236846FFF706 +:1050C800A5FC0028F4D0254604F1300E0EAF286860 +:1050D800103555F80C1C3E4655F8082C103755F875 +:1050E800043C75450FC6F2D1286809AA04F12403C7 +:1050F80038609DF8305007CA83E8070094F83330C9 +:10510800204684F8305063F07F0384F83330FFF78B +:105118009BFE0028CCD00021022208230EA815915E +:105128008DF86B208DF86930FFF758FDC1E700BF97 +:105138002DE9F04F90F8314083B01F4624079DF8C1 +:1051480030A09DF834909DF838B09DF83C3004D5D7 +:10515800A2F2BC7294B27F2C04D90026304603B068 +:10516800BDE8F08F7A1E0B2AF7D80AF1FF321E2A03 +:10517800F3D8BBF13B0F98BFB9F1170F8CBF0126CD +:1051880000263B2B88BF46F00106002EE5D101938F +:1051980005468846FFF758FE019B0028DDD05910C8 +:1051A80013F0010F4AEA471708F0010341EA4B11CF +:1051B800B24647EA442708BF4FF0000B41EAC92925 +:1051C80018BF4FF0640B3446BFB21FFA89F9019338 +:1051D800002251462846FFF721F80028BDD0027862 +:1051E800852A4FD0BAD3A2F1C0010129B6D84FEA17 +:1051F800C43EA2F1850300214EEA5404B3FA83F3B6 +:105208004FF0010E12FA84F45B09A4B27144E20370 +:105218004FF0030E1F2942EA54020AD8445C0129C0 +:1052280014FA82F294B201D1002BEFD14FF0010EA3 +:10523800ECE70AF1010395F830205FFA83FA52454A +:10524800C6D2012205F12401286A00F0E1FE0028F7 +:1052580083D02D6A4480284605F0B8FA00283FF428 +:105268007CAF05F5047005F0B1FA00283FF475AF7E +:10527800D5F8400403681B6A9847064600283FF49F +:105288006CAF6BE795F83120296A02F03702019B71 +:10529800828091F8102242F0010281F8102213B1A5 +:1052A800A0F81090478218F0020F04D080F814B0CC +:1052B800A0F80890478118F0040F04D080F815B0C2 +:1052C800A0F80C90C781027891E700BF90F83330BE +:1052D8009A0718D5F0B5C56983B08DB103F04003BE +:1052E800044603F0FF0683B98169002942D101957C +:1052F800C1612946206A00F0FDFE38BB002000E0AD +:10530800012003B0F0BD00207047006AA16990F841 +:105318004524D4E90267093216F1FF36D2B247F1C3 +:10532800FF37C2F1200EA2F1200326FA02F207FA93 +:105338000EFE27FA03F342EA0E021A430132B1B114 +:10534800013D4B1C691A01930A4402BB94F833309F +:105358002046D4E9006763F07F03C4E9026784F854 +:105368003330C4E90467FFF76FFD03B0F0BD019562 +:10537800E161EAE702AA006A42F8046D00F064FEFF +:105388000028BBDB0AD1019D002DDFD0B1E7002347 +:10539800019900F0E7FD0028D8D1AFE74FF0FF32C0 +:1053A800A169206A00F094FE0028ECD1A6E700BFAE +:1053B8002DE9F04F90F8333083B004469D070092F2 +:1053C80040F1B3801A07884600F1A880009B002BA3 +:1053D80000F01D812146009D4FF0010AF1E80623E7 +:1053E80093460191206AA169D0F8386406EA0B0651 +:1053F800C6F3080956BB002900F0CC8094F8333076 +:105408005B0640F1E08090F84524E3690932D4E96D +:1054180002BCD2B21BF1FF3BC2F1200EA2F1200761 +:105428004CF1FF3C2BFA02F20CFA0EFE2CFA07F7AD +:1054380042EA0E023A431A449142C0F0C180204623 +:10544800FFF784FB002870D0206AA169760A023928 +:10545800D0F82C7490F845E4374401FA0EF1394439 +:10546800B9F1000F6BD1B5F5007F2CBF00220122E6 +:10547800002A64D1B5F5806FC0F090800AFA0EFE5C +:105488006B0AD0F81CC2C6EB0E06B34228BF3346DF +:1054980061454FEA432708D85E18B44505D24FF056 +:1054A800FF3680F81022C0F81C62D0F81402424679 +:1054B8000668B66AB047002837D038460021B84495 +:1054C800ED1BD4E90023D4E9046712EB000B43EB8E +:1054D800010C674508BF5E45C4E900BC07D294F8D3 +:1054E800331061F07F01C4E904BC84F83310002D47 +:1054F8007FF478AF5A466346D4E90201994208BF5F +:10550800904278D3434B1B68002B7ED094F83330FD +:10551800009863F07F0384F833300DE0D0E904236A +:10552800FFF714F800287FF451AF94F832300020C8 +:1055380043F0010384F8323003B0BDE8F08FB9F1CD +:10554800000F25D1D4E90423D4E900679F4208BF9E +:10555800964234BF0122052200F5047005F006F9D1 +:105568000028E2D0C9F5007748444146AF4228BF39 +:105578002F46B9443A4605F01BFEB9F5007F9CD189 +:10558800206A00F5047005F021F9002895D1CCE7D0 +:105598000122E1E7E169F1B1A16157E7D0F81C32D6 +:1055A800994221D0D0F81402424603685B6A9847B2 +:1055B8000028BAD04FF4007000214FF400777EE73E +:1055C8000131A16142E7019A00F03EFD0028ACDB01 +:1055D8007FF43AAF33E72046FFF7B8FA0028A4D0A3 +:1055E800A169206AE16131E74FF0FF3380F81022AA +:1055F800C0F81C32D6E794F83310009861F07F01A8 +:10560800C4E9022384F8331096E7009894E7D4E9B4 +:10561800002371E78821002070B5044608460D462E +:1056280008F00EFA23680246294620465B68BDE862 +:105638007040184783680146C3F3080363B100202C +:105648000A69D0540133B3F5007FF9D1C8680A69F3 +:10565800036809685B6A1847012070478268034637 +:105668000069C2F3080230B4815440F2FF145D6847 +:105678009868A24201EB750100F101005960986039 +:1056880002D0012030BC7047D868196802684D1CE8 +:10569800546A1D601A69234630BC184738B50C4651 +:1056A800C9B20546FFF7DAFF00B938BD210A284616 +:1056B800BDE83840FFF7D2BF2DE9F8430023804604 +:1056C80001601E4683604360B0B205F0ABF9B0429A +:1056D800814605460DD001464046FFF7DFFFA0B3DF +:1056E8000136B6F5803FEFD34046BDE8F843FFF7F3 +:1056F800A1BF741CB4F5803F14D1C6F580374FF4B0 +:105708008034B7F5007F1AD2A9B240460135FFF7B9 +:10571800C5FFD0B1A542F7D32E46E2E70134B4F570 +:10572800803FEAD0A0B205F07DF9A042F6D0A71BD1 +:10573800B7F5007F03D2A642E6D34E46C4E74FF63C +:10574800FF714046FFF7AAFF10B90020BDE8F883B3 +:10575800B9B24046FFF7A2FF0028F6D02646C0E7B8 +:105768002DE9F04F81461F460B6889B0C9F80C1027 +:105778000846C9F810200E46DB6915469847B0F56B +:10578800801F12D2002F69D03B681522AE493846D7 +:105798005B6898473B6838460F22AC495B68002431 +:1057A8009847204609B0BDE8F08F0446002301223F +:1057B80001E0944203D901335200DBB2F9D11C2B2A +:1057C80051D90122A3F10B0848FA02F85FFA88F1CF +:1057D80002FA08F20691049201220133134102FAF7 +:1057E80003F303FA02F205939B0001920293029BD2 +:1057F80000214FF400722846E31A8A464FF0010B45 +:1058080023FA08F3039303FA08F8019B984408F075 +:105818009BF8FF230722FE2085F8BFB185F8C22137 +:105828004AF6552E85F8C301514685F8C4312A46F3 +:1058380085F8C531304685F8C0B185F8C1A1019B0E +:10584800D6F800C0C5F8C631C5F8CA81DCF82430DE +:10585800A5F8FEE19847D0B9002F9BD10024204637 +:1058680009B0BDE8F08F1A2B4FF0080800F22D821E +:105878004FF40043CDF8188002934FF4804301930E +:105888004FF4807304934FF400530593AFE75146E8 +:105898004FF40072284608F057F8059B76220198C5 +:1058A8002B6590216B654FF0410C039B4FF0540E14 +:1058B8006A704FF04502EB659DF818302864A865BA +:1058C800202085F86D306FF01403EA704FF058020D +:1058D800C5F844A0C5F848804FF00908C5F84CA0A1 +:1058E8006C664FF04604A5F86AA085F86EB04FF0D4 +:1058F800040B85F870A04FF4807A2B7005F17703BC +:10590800A97005F2FD112A71F42228726872A87232 +:105918006FF07F006C7185F806C085F807E0C5F860 +:1059280060B0A5F868A085F86C8085F86F0003F86A +:10593800012F9942FBD14FF000084AF655234446FF +:10594800A5F8FE31A8F16A03012B06D9B8F1700F4A +:1059580003D015F8083003EB740408F10108B8F512 +:10596800007FEFD133682A46019930465B6A984731 +:1059780000283FF471AF33682A46019930465B6AC4 +:105988000C31984700283FF467AF019B424600213D +:10599800284603F1010A07F0D7FF019A4AF6552372 +:1059A800CDF81C9005F2FF1802F1090B6A1EA5F844 +:1059B800FE31914606924B4613F8012F984502EBAB +:1059C8007404F9D133682A46514630465B6A9847D1 +:1059D80000283FF441AF33682A460AF10C013046EB +:1059E8005B6A984700283FF437AF0AF1010AD345AC +:1059F800E1D1019B4FF4007200212846DDF81C908C +:105A080003F10B0A07F0A0FF069B13F8012F984536 +:105A180002EB7404F9D133682A46594630465B6A6A +:105A2800984700283FF418AF33682A460BF10C0159 +:105A380030465B6A984700283FF40EAF0BF101032C +:105A4800534505D09B46DFE7040C0020640C00207A +:105A58002B1F05F5FE7243F8044F9A42FBD13368B9 +:105A680051462A4630465B6A984700283FF4F4AE10 +:105A780033680BF10D012A4630465B6A98470446A5 +:105A880000283FF4E9AE2FB13B680C22974938460D +:105A98005B689847039B4FF40072002128464FEA41 +:105AA8008308059B08F207289B46019B9B4407F047 +:105AB8004BFF4FEA5823F82005F11301FF229E46B9 +:105AC8002B46287003F8012F9942FBD17346002B0F +:105AD80031D03B1C4FF0000ACDF818904FEA9838A7 +:105AE80018BF0123F1460593234654469A4605E01C +:105AF800002C00F0F0800134A14519D001227C4926 +:105B08003846B4FBF8F308FB134323B9059B13B1DC +:105B18003B685B68984733682A4604EB0B013046BC +:105B28005B6A98470028E3D1002F7FF433AE95E6EF +:105B38005446DDF81890002F35D03B6802226D4995 +:105B480038465B689847039B03F10708049B4FEAB4 +:105B5800D80808F2FF1A4FEA5A2A9A453FF61AAEB1 +:105B68004FF400720021284607F0EEFE07232B7041 +:105B7800BAF1000F7CD04FF0000B07E0BBF1000F2B +:105B880000F0B0800BF1010BDA456FD033682A467C +:105B9800029930465B6A594498470028EED1002F95 +:105BA8007FF4F8AD5AE6039B03F10708049B4FEA1C +:105BB800D80808F2FF1A4FEA5A2A9A453FF64EAE1D +:105BC8004FF400723946284607F0BEFE07232B70B3 +:105BD800BAF1000FCFD1019B48464FEA430A049B14 +:105BE8000AEB0301FFF768FD00283FF437AED9F848 +:105BF8000830049AB3EB422F3FF630AE049B4FF4C3 +:105C08000072002128460AEB430A07F09DFE032292 +:105C18008123822102202A7085F8203000236863BE +:105C280085F84010D9F804106A656964D9F8082025 +:105C3800C5F83880AA65049AEB65002A3DD09846D5 +:105C480007E0B8F1000F31D008F10108049B98452E +:105C580033D033682A460AEB080130465B6A984716 +:105C68000028EED1002F7FF495ADF7E5002FB2D0D4 +:105C7800019B384620494FEA430AFFF7CDFC049BB5 +:105C880048460AEB0301FFF717FD00283FF482ADF1 +:105C9800D9F80830049AB3EB422F3FF67BAD002FBA +:105CA800ACD016493846FFF7B7FCA7E74FF40072A7 +:105CB8004146284607F048FEC6E7002F3FF471AD7D +:105CC80038460F49FFF7A8FC6BE54FF48072CDF812 +:105CD8001880049280E54FF400722146284607F0A8 +:105CE80033FE08E785F800B04CE700BF1C0C002025 +:105CF800D40A0020400C00202C0C0020440C00206A +:105D0800540C00202DE9F0410C46154601F11E08FF +:105D1800AB89284634F8026F1BB96A68AB689A42A7 +:105D28000ED004F071FD04F07DFE0746304604F005 +:105D380079FE874209D14445EAD10120BDE8F081C6 +:105D4800B6FA86F04009BDE8F0810020BDE8F08190 +:105D58002DE9F84F90F831308946002B45D090F85E +:105D680030308046012B53D9013A8A4602274FF03A +:105D7800000B8E18002239464046FEF74FFAA0B3B2 +:105D88000378C12B31D1044600F11E0519E000F556 +:105D980010539BB2B3F5806F27D24FEA8B2B1E4B63 +:105DA800C0F309000BEA0303184300F5803051469D +:105DB800324604F0A1FD8246B8B1AC424FF0000B68 +:105DC8001FD034F8020FBBF1000FE0D100F52053CB +:105DD8009BB2B3F5006F0ED30028E8D1C9EB0A00D7 +:105DE80000238AF80030BDE8F88F0023184689F8A8 +:105DF8000030BDE8F88FB3F5806FF6D2AC42834629 +:105E0800DFD1013798F83030FFB2BB42B2D2E5E7B4 +:105E18008A460020E4E700BF00FC0F00F8B50D46F5 +:105E280000234FF6FF762A681946AB811C466A6044 +:105E38002B6116E004F0E8FCB04221D004F0F2FD3A +:105E48002B69E203A9890712013342EA54022B6144 +:105E580052FA80F0C0F34E0343EAC03017FA80F4D8 +:105E6800A4B228460029E5D16A68AB689A42E1D114 +:105E78002869AC820138FE288CBF00200120F8BDBB +:105E88000020F8BD38B50C46D0F82414154600F5A6 +:105E98000470012201EBD41104F068FC034628B118 +:105EA800A4000120C4F308041D5138BD38BD00BF4B +:105EB8002DE9F84F804691468B46002943D08F1E26 +:105EC800D8F830349F423AD207F007050123C7F3C8 +:105ED800C80A03FA05F5EDB23E463C46D8F82C143C +:105EE8000022404601EB143104F040FCC0B110F828 +:105EF8000A100AE04A4529D0A74210D0D8F8302421 +:105F0800944216D213F0FF050CD001340D424FEA2B +:105F18004503A4EB0602EDD0A7422646EED10120A8 +:105F2800BDE8F88F0AF1010A0125BAF5007FDED134 +:105F380001E0002634464FF0000A0125CEE700278D +:105F48000125BA46C8E7D0F82074B9E7BBF1000FBD +:105F580004D1B9F1010F08BFC8F82064B01CBDE82E +:105F6800F88F00BF2DE9F047023915469A46D0F858 +:105F780030244B19934238D88046BAF1000F37D1F4 +:105F8800D0F82034994238BFC0F8201401F0070433 +:105F98000122D8F82C34C1F3C80602FA04F403EB42 +:105FA8001139E4B2012249464046914404F0DEFB2F +:105FB800D8B1871900F5007017F8012B224282EA40 +:105FC80004024FEA440414BF0126002656450CD0AB +:105FD800013D07F8012C17D014F0FF04EED18742D9 +:105FE80026464FF00104E7D1DCE70020BDE8F08742 +:105FF800D0F820048342C9D98142C7D8934228BF28 +:106008000023C8F82034C1E70120BDE8F08700BFAD +:1060180070B50E460446D0F8385400F50470496847 +:1060280033682940D4F82C54023B94F8454405EBD6 +:106038005121A340194404F099FB18B17368C3F3C4 +:106048000803184470BD00BF38B5D0F830340133A8 +:106058008B4216D30C46D0F82414154600F504706C +:10606800002201EBD41104F081FB50B1A100C1F36F +:10607800080143585A1C02D02B60012038BD00206B +:1060880038BD4FF0FF3038BD70B54C680D46D0F8BC +:1060980038340646A1182340696090F845441A44EC +:1060A8000934E4B222FA04F43CB12B7A3BB12B68F0 +:1060B80001332B60013C002CF7D1012070BD2A462A +:1060C80029683046FFF7C0FF0128F3D070BD00BF34 +:1060D80001290DD9D0F830340133994210B403D9CD +:1060E80000205DF8044B70475DF8044BFFF7CABE0B +:1060F800002070472DE9F0410C4682B005468846DD +:10610800214601AA2846FFF79FFF012C0746C0F346 +:10611800C0162146284626D9324626BBD5F8303443 +:1061280001339C421FD8FFF7ADFE04F1010E414632 +:106138003346C8EB0E02B0B1284647B1019CA645CC +:10614800DED0FFF70FFF70B1019CA046D8E7621CB4 +:106158003B4641462846C8EB0202FFF703FF10B151 +:1061680002B0BDE8F081002002B0BDE8F08100BFB8 +:106178002DE9F84300248046D0F82C6400F5047714 +:106188002546314600223846013604F0EFFA28B396 +:1061980000F1FF3ED8F830C405F580591EF8010F0C +:1061A800FF2813D048B10822012318424FEA4301BF +:1061B80018BF0134013ACBB2F7D10835AC4509D93B +:1061C8004D45DED01EF8010FFF28EBD10835083405 +:1061D800AC45F5D8C4EB0C00BDE8F883BDE8F883FE +:1061E8002DE9F041002304464FF0FF3600F504770F +:1061F8001546C0F8401441601A46C4F814123846CF +:10620800194684F84434237084F81032E660C4F8E0 +:106218001C6204F0ABFA042D0DD8064658B16DB9CE +:1062280005222949F01C07F079FC034618B996F8AD +:106238006C20092A1AD00020BDE8F0816B1E00EB03 +:10624800031393F8BE2112F07F02F4D193F8C23100 +:10625800002BF0D000EB05153846D5F8B651294685 +:1062680004F084FA06460028DAD1E4E7326D4FF0EC +:1062780001080146204602EB050E4246C4F824E414 +:10628800776DC4F82874B76D3D44C4F82C54F56D87 +:10629800C4F83054356EC4F8345496F86D50C4F8C8 +:1062A800203405F1090384F8455408FA03F35D1E08 +:1062B800C4F83C34C4F83854FFF7FAFD402340468C +:1062C80084F84434BDE8F081740C002070B582B0C5 +:1062D800D0F834140546002402AE46F8041D01E047 +:1062E80009D0019932462846FFF7AEFE002804F18E +:1062F8000104F5DA002495F845040930C0B204FA1F +:1063080000F002B070BD00BF38B50D460446242227 +:10631800002107F019FBA560EB79102B05D0202B85 +:1063280008D00C2B01D0002038BD20230120237079 +:10633800A07038BD402301202370A07038BD00BF75 +:10634800024638B552F8105F04468068294602F0C4 +:10635800AFF850B155B123690135AB42A37818BFE6 +:1063680003F0BF0363F07F03A37038BDA37843F045 +:106378004003F7E7F8B5037803F020032BB903F0DF +:10638800FF044169194B994202D900263046F8BDED +:106398000546FFF7D5FF06460028F6D0A8682F69FE +:1063A8008379023F426901799F40174441B913E05C +:1063B80007F0CAFA0134A868E4B20379A3420AD9FB +:1063C8000522E119283004F0D1F94FF400720021B8 +:1063D8000028EDD1D9E783794FF40072696902FA90 +:1063E80003F311FA83F36B61D0E700BFFFFD1F00D1 +:1063F80010B5044680680A462830A16904F0B6F949 +:1064080020B1A38803F00F0300EB431010BD00BFB9 +:1064180030B590F9023083B00446002B19DBA5682B +:1064280005F1280004F0D2F930B96378002043F070 +:106438000103637003B030BD05F50E7004F0C6F9B2 +:106448000028F2D0286803681B6A98470028ECD017 +:10645800F0E70121FFF7CCFF05460028E5D00378D7 +:10646800E52BE2D023781B0701D5E369C361236AD2 +:106478000B491A0C6B830B68AA8263B10DF10302F6 +:106488000DF1060101A89847BDF80430BDF80620B3 +:106498002B836B82EA82A37803F07F03A370BEE7A5 +:1064A8008821002010B50378044623B90023012071 +:1064B8002370A37010BDFFF7ABFF00232370A370F8 +:1064C80010BD00BF70B5037805460C46BBB9284619 +:1064D8000021FFF78DFF0346A8B1066801205D681B +:1064E8009968DA6826606560A160E2601E695D6986 +:1064F8009969DA6926616561A161E26170BDFFF79A +:1065080087FF0028E3D1002070BD00BF30B589B0F7 +:106518000D4614466946FFF7D5FF28B1BDF810208F +:10652800BDF80E302A80238009B030BD30B589B05F +:106538000D4614466946FFF7C5FF28B1BDF8182077 +:10654800BDF816302A80238009B030BD2DE9F0410E +:106558000C7888B014F0700F03D1002008B0BDE8A3 +:10656800F08140F6022305460C4601F077F8002832 +:10657800F3D0012210232846AA702B70FFF7FAFEE9 +:106588000028EAD02A692B782A62002B7FD10121C2 +:106598002846FFF72DFF07460028DED010230068A5 +:1065A8007968EE46FB724FF02E0CBA6808AEFB68AD +:1065B800B7F81480AEE80F00BA69FB6938697969E1 +:1065C80006F820CD0DF10A0C7F8BAEE80F0033469C +:1065D800202203F8012F6345FBD1A86801222B6A0A +:1065E80090F806E02830023B50F8141C03FA0EF32A +:1065F800194404F0BBF886460028AED0ADF81480E4 +:106608004FF02E08ADF81A7037460FCECEF80000BE +:10661800CEF80410CEF80820CEF80C308DF80180A2 +:106628000FCECEF81000CEF81410CEF81820CEF801 +:106638001C30236A1A0CADF81A30ADF814200FCFAD +:10664800CEF82000CEF82410CEF82820CEF82C3032 +:106658000FCFCEF83000CEF83410CEF83820CEF870 +:106668003C30AC6804F1280004F0B0F800283FF48E +:1066780074AF04F50E7004F0A9F800283FF46DAF6C +:10668800206803681B6A08B0BDE8F04118476B69C9 +:1066980033B1AB78002223F020032A616A61AB7022 +:1066A8002846FFF7B5FE00283FF457AF6FE700BF55 +:1066B8002DE9F041064694B000200C46317801924D +:1066C800ADF814008DF82C008DF82D008DF82E00F3 +:1066D80021B99846237813F0700F03D1002014B025 +:1066E800BDE8F081137811462F2B2ED0002701AB7F +:1066F80002AA304601F004F902AA21460023002824 +:10670800ECD0019D30462D78002D30D000F0A6FF4A +:1067180048B9B8F1000FE1D0214602AA3046FFF788 +:1067280015FF0028DAD035460BAC96F800E00FCDFF +:106738000FC40FCD2D680FC42560BEF1000F12D114 +:1067480037700BACB7700199D1E7013101910B7823 +:106758002F2BFAD0A1680BA8FFF7D6FD0028BDD0D3 +:106768000BAC0199C2E73046FFF752FEE8E702AAF0 +:1067780021463046FFF7EAFE14B0BDE8F08100BFBD +:106788002DE9F041064694B000200D46317801927B +:106798008DF808008DF809008DF80A00ADF838006A +:1067A80021B998462B7813F0700F03D1002014B04C +:1067B800BDE8F081137811462F2B2AD0002702E07C +:1067C80001993770B77001AB0BAA304601F098F801 +:1067D8000BAA294600230028E8D0019C30462478DB +:1067E80034B300F03BFF354602AC0028DED096F803 +:1067F80000E00FCD0FC40FCDD5F800C002AD0FC417 +:10680800C4F800C0BEF1000FDAD03046FFF700FE32 +:10681800D6E7013101910B782F2BFAD08BB1A968FB +:1068280002A8FFF771FD0028C0D002AD0199C5E7A5 +:1068380043460BAA2946304600F010FF14B0BDE8C5 +:10684800F081A9683046FFF75FFDB0E719B101F59F +:106858008961FFF795BF0846704700BF38B5CB6818 +:1068680043B902780AB1184638BD8968BDE838408E +:10687800FFF74ABD0D4624220021044607F064F8BC +:1068880001231022A37018462270AA68EB68A26040 +:10689800236238BD03780BB100207047FFF734BD81 +:1068A8002DE9F04F837883B00546DF0740F19080EB +:1068B8000F46017891460E0700F193808C0608D5A3 +:1068C800826843695289C3EB42139BB2994528BF3A +:1068D8009946B9F1000F00F0AA806B6988064E4608 +:1068E8004FF0000805F1100AAA68C3F3080440D560 +:1068F800116A01EB5321002C54D1B6F5007F51D316 +:10690800536B99424ED0B6F5806F73D328784FEA0F +:10691800562B800605D41079C8EB0000834528BFA4 +:10692800834699424FEA4B240DD801EB0B00834272 +:1069380009D202F128000191009203F047FF009A62 +:106948000199002844D0D06A5B463A46D0F800E066 +:10695800DEF814B0D84700283AD06B69361B2744B4 +:1069680023446B6163D02978C3F30804AA688806B6 +:10697800BED492F8058008EA5328002C38D1B8F123 +:10698800000F35D1002B3FD148064CBF136A2B6A44 +:106998002B619179023B50698B4008EB0001194447 +:1069A800002CAAD002F12800002203F0DFFE78B103 +:1069B800C4F5007301193846B34228BF33461A4656 +:1069C8001C4604F0F5FBC8E72B7813F0700F2FD1A5 +:1069D8006B784FF0FF3043F002036B7003B0BDE8F3 +:1069E800F08FC36942699B1A994528BF994670E799 +:1069F8002B69CEE7D06A3A4603681B699847002896 +:106A0800E6D04FF40074A8E7090705D5AB785B0614 +:106A180002D52B690133BBE710462969524601F0BC +:106A2800CFFC0028D4DBCFD0AA682B69B1E70026B9 +:106A3800C6EB090003B0BDE8F08F00BF70B582B0A7 +:106A48000122044646690DF107010569FFF728FF91 +:106A5800012866610CBF9DF807004FF0FF302561E3 +:106A680002B070BD436930B5C3F3431583B0044623 +:106A7800B5FA85F252098A4207D220334361A068E9 +:106A8800383000EB451003B030BD01220DF107018D +:106A9800FFF706FF40B2012803D163691F33636122 +:106AA800EDE70020EFE700BF2DE9F04305789BB044 +:106AB800002415F0180F8DF820408DF821408DF82E +:106AC80022408DF844408DF845408DF8464004D06A +:106AD800866803468D68AE4203D000201BB0BDE82F +:106AE800F0831D4690460E46FFF792FCAE4611AF66 +:106AF800BEE80F000FC7BEE80F00DEF800E00FC7C2 +:106B080021462846C7F800E0FFF772FC86460028B1 +:106B1800E3D000686F46DEF80410DEF80820DEF8DF +:106B28000C3095F800C00FC70CF0080CDEF8100008 +:106B3800DEF81410DEF818200CF0FF09DEF81C301F +:106B48000FC7BCF1000F00F096804246314640F670 +:106B5800012308A8FFF714FE0028BED00E9A0026CD +:106B6800BDF824300121AA612846AB809DF8232076 +:106B78000B9BEA70EB608DF820608DF82260FFF7C0 +:106B880037FC0028A9D01AAB9DF80B2053F85B7D81 +:106B9800C272D3F804E0C0F80D709F68C0F811E025 +:106BA800C0F81570D3F80CE01F8A9B7CC0F819E078 +:106BB800A0F81D70C377002C3BD0AF68A31E3246E7 +:106BC800BE7907F128007969B340194403F0CEFD76 +:106BD800002882D006466F4656F8200F7168B268C2 +:106BE800F3680FC730697169B269F3690FC7214645 +:106BF800A86801F0BFFC00283FF46FAFA968012224 +:106C08002B6A8C7901F12800023B4969A340194499 +:106C180003F0ACFD074600283FF45FAF6C460FCC8D +:106C280038627962BA62FB620FCC38637963BA63FF +:106C3800FB6300210222082311A819918DF8462030 +:106C48008DF8443000F0CEFE00283FF446AFAC6823 +:106C580004F1280003F0BAFD00283FF43EAF04F524 +:106C68000E7003F0B3FD00283FF437AF20680368C7 +:106C78001B6A984732E74B464246314608A8FFF759 +:106C880017FD00283FF429AF109C67E70378DA0660 +:106C98001AD5436910B5044633B18378002223F02E +:106CA800200302614261837001212046FFF7DAFE6A +:106CB80060B103786BB1E52BF6D02E2BF4D0C37AF4 +:106CC8001B07F1D4002010BD002070476378002B0B +:106CD800F8D1A3780822204643F002032270A3705B +:106CE800BDE8104000F07EBE2DE9F041037804466F +:106CF8000769B3B10D464169A9422CD045B98378DB +:106D0800056123F0200365610120A370BDE8F081CF +:106D180018070AD49A060BD5A3685B89B5EB431FFD +:106D280030D927610020BDE8F081E2699542F8D8A2 +:106D3800D4F808E06E1EA2789EF8060012F0400F04 +:106D480000F10900C0B226FA00F607D0216A1346FE +:106D58000E442661D5E70120BDE8F0814A1E22FADB +:106D680000F0864210D379B1361A04F1100806E013 +:106D78002169013EA06801F023FB0028D1DD4246CD +:106D8800002EF5D1A378BCE75B064CBFDEF82030B7 +:106D9800236A2361E9E700BF2DE9F0410D469046DB +:106DA8000021242204461F469DF8186006F0CCFDF9 +:106DB800A86808F00F03296A00F13802A060E160B2 +:106DC80002EB4312A4F80480D17A0D0711D401F024 +:106DD80017012170D37A13F0180F02D141F008017E +:106DE800217007F00303E670012B08D0022B2AD08C +:106DF80023B3002323701846A370BDE8F081022353 +:106E0800A370217811F0110FF3D159B207F48065FE +:106E180007F008030B43DBB2A370B2F814E0518B00 +:106E2800466B41EA0E41A66185B1D1B963F07F0393 +:106E3800A3707B040ED40120BDE8F08117F48065AF +:106E4800D7D10121E4E70323A370DAE72162D369EC +:106E5800E361EEE7E1692046FFF746FF0028EAD143 +:106E6800C7E701F087FB0028C3D0A378DEE700BF9F +:106E780003781BB90B7813F0700F01D1002070470D +:106E88002DE9F0434D6983B015F01F0632D19046C5 +:106E98000C460746B14611E0A3F1E502B2FA82F2C8 +:106EA8005209A2B990F80BE00EF0080101F0FF0CAE +:106EB80079B1BEF10F0F21D0164665690021204631 +:106EC800FFF7D0FDB0B10378A3B12E2BE4D1002693 +:106ED800F3E7D6B1421E0A304FEACC1312F8011F6D +:106EE80043EA5C0C904251FA8CFC5FFA8CFCF3D1BB +:106EF800CC450AD0002003B0BDE8F0835A06DCD5A3 +:106F080003F01F0690F80D90D7E700964346C5F3A7 +:106F18004F1221463846FFF73FFFECE703780BB1E5 +:106F2800FFF776BA012070472DE9F04F90F800E09E +:106F380081B01EF0080F9DF828909DF82CA09DF8B0 +:106F480030B09DF8348004D0A2F2BC7294B27F2C89 +:106F580003D9002001B0BDE8F08F5A1E0B2AF8D8DB +:106F680009F1FF321E2AF4D8BBF13B0F98BFBAF1E2 +:106F7800170FEED8B8F13B0FEBD806461D460F4663 +:106F8800FFF746FA0028E4D001213046FFF730FA2F +:106F98000028DED04FEA6801FB0749EA451541EAB7 +:106FA8004B1B45EA44244BEACA2AA4B21FFA8AFAC0 +:106FB80000D54482B90709D518F001080482A0F861 +:106FC8000EA018BF4FF0640880F80D807A0702D52C +:106FD8000483A0F816A0B46804F1280003F0F6FBB7 +:106FE8000028B6D004F50E7003F0F0FB0028B0D0EE +:106FF800206803681B6A01B0BDE8F04F184700BF5E +:1070080083789B071AD5036AB3B1016910B50446A2 +:1070180082B0F1B9019301621946A06801F0AAFA99 +:10702800A8B1A378616963F07F032278E161A37056 +:10703800EAB9012002B010BD012070470020704756 +:107048006FF070422169A06801F084FA58B90020F5 +:10705800F0E7002302AA806842F8043D01F0B0F985 +:107068000028F4DBECD1019B002BDAD0D4E72046D2 +:10707800FFF7CEF9DEE700BF2DE9F84F8378054624 +:107088009C076DD590461A070F4664D46A69D343A6 +:10709800984565D8B8F1000F00F0D08046464FF00B +:1070A800000A4FF0FF393CE0BBF1000F40D12969DD +:1070B80000297ED0AB785B0640F19B80EB69934258 +:1070C80040F297804B1C01392B6190F806E0436928 +:1070D80001FA0EF123441944B6F5007F47D2B6F5FC +:1070E800007F344628BF4FF40074EB69934202D9FD +:1070F800AB789B062DD50522283003F037FB78B3F3 +:107108005844A3442246394604F052F8BBF5007FA0 +:1071180000F08C806A69361B274422446A6100F0BB +:107128008D80A868C2F3080B447914EA5224BBD0B6 +:107138002B6990F806E0991E436901FA0EFEE118E2 +:107148007144BBF1000FC7D0CBF50074B44228BF1F +:1071580034460122D0E7C169FFF7C6FD002895D162 +:107168006B78002043F001036B70BDE8F88FB6F52B +:10717800806F31D390F804E0730A426BC4EB0E04BD +:10718800A34228BF23468A424FEA432407D303EB8E +:10719800010E724503D280F828A0C0F83490C06A66 +:1071A8003A46D0F800E0DEF828B0D8470028B1D138 +:1071B800D6E7296A61B32961023982794369B6F54C +:1071C800007F01FA02F11944D1D2CBF500746A6943 +:1071D800B44228BF344688E7436B8B4221D0C06A4B +:1071E8003A4603685B6A98470028B9D04FF40074A0 +:1071F80090E705F1100201F0E3F80028B0DB04D1B4 +:107208002846FFF79DF80028AAD02969A868D3E77F +:107218002846FFF795F80028A2D02969A8682962AE +:10722800CAE780F828A0C0F83490D8E7A8682830C2 +:1072380003F0CCFA00287FF46DAF91E7EB69934235 +:107248000CD30A4B1B6833B1AB78404663F07F031D +:10725800AB70BDE8F88F4046BDE8F88FAB78404684 +:10726800EA6163F07F03AB70BDE8F88F88210020E6 +:107278002DE9F04F07468DB0154606468A469946D1 +:1072880003AC4FF0000E0FCF0FC40FCFD7F800C0DC +:107298002F68A5F80CE06F600FC4C4F800C0B9F1FE +:1072A800000F35D04FF00108CDF80490C8EB0A0163 +:1072B80003A889B24901FFF717FD58B3002103A8B5 +:1072C800FFF7D0FB074628B30024E2B23946304620 +:1072D800013400F0CDFEAB89834628461BB96B68A4 +:1072E800AA6893421AD003F08FFA8146584603F0F1 +:1072F80099FB8346484603F095FB83450AD10D2C3C +:10730800E3D108F10108019B5FFA88F84345CDD223 +:10731800012000E000200DB0BDE8F08FBBFA8BF033 +:1073280040090DB0BDE8F08F2DE9F04F06468DB04D +:107338001546994600910DF10C0E02F1150400272F +:107348000FCEAEE80F000FCED6F800C005F120062C +:10735800AEE80F003B46CEF800C0DA0114F8011F72 +:1073680042EA5303B44251FA83F3DBB2F5D11F4624 +:1073780000262B68AE816B60B9F1000F56D049F03A +:1073880040034FF00108B2460193009B03A8C8EBE5 +:10739800030189B24901FFF7A7FC002853D0002157 +:1073A80003A8FFF75FFB00284DD0059AC145019956 +:1073B8004FF00F0E92F8283014BFC4468C4600F1E7 +:1073C800040B43F00103002482F8283080F80CA055 +:1073D8004773A0F81AA080F800C080F80BE00CE012 +:1073E8000A2C04F101040BF1020BE4B294BF2BF850 +:1073F800020CABF800000D2C12D0AB891BB96A68DF +:10740800AB689A4216D0284603F0FEF9042CE7D858 +:1074180001342BF8030C0BF1020BE4B20D2CECD168 +:1074280008F101085FFA88F8C145AED201200DB015 +:10743800BDE8F08F16B930460126E7E701364FF66A +:10744800FF70F6B2E2E700200DB0BDE8F08F00BF94 +:107458008446202062460CEB00012DE9F04752F8E3 +:10746800153BDCF8085002F8010F8A42FBD11A7864 +:107478002E2A14BF0120002003D113F8012F2E2A31 +:10748800FBD0691E99420DD915F8012C2E2A09D076 +:10749800AA1E02E00C782E2C04D09342114602F169 +:1074A800FF32F7D19D424FF000087DD907264FF0F3 +:1074B800080E4446C14608E0994209D10A26082424 +:1074C8004FF0100E01339D4225D91A782E2AF3D099 +:1074D800222A0BD07C2A09D0A2F15B07022F05D9FA +:1074E800A2F12A07052F30D82D2A2ED002F0C0028B +:1074F800802A3DD0B4421ED800205F22671C0CEBC6 +:10750800040AFCB28AF81620062CDBD801338CF862 +:1075180014409D42D9D89CF81630202B41D068B32E +:1075280019EA080F4FF0010018BF4FF002088CF855 +:107538001580BDE8F0870A2E1CD099422CBF002385 +:107548000123BBB918464B1EBCE7A2F13A07052F29 +:10755800CCD9A2F121075D2FC8D8B442EBD8A2F14B +:107568006107192F16D8203A4EEA0808D2B2C5E7A3 +:107578000020A7E79CF81630202B12D09CF8143076 +:1075880001207E21312263448CF815009975DA7543 +:10759800BDE8F087A2F14107192F98BF4EEA090903 +:1075A800ACE70020BDE8F087C146B4E72DE9F84F05 +:1075B800884605464FF0620900240F7D01F1160642 +:1075C800DFF894B04FF07E0A032FDBF8002028BFC5 +:1075D800032714443B1DA4B2DBB204F00F02581E6B +:1075E8002409092A02F1370198BF02F1300108EB9A +:1075F8000302C3B291759F42EFD308EB0703002142 +:10760800284683F816A0FFF76FFB01212846FFF7ED +:1076180029FA0B220346A8B190F800E0014630464B +:10762800BEF1000F14D0DB7A1B07EED406F05AF92E +:107638000028EAD109F1FF3919F0FF09C4D14846F9 +:10764800BDE8F88F6878B0FA80F04009BDE8F88F97 +:107658000120BDE8F88F00BFF02700202DE9F04F8A +:107668000C788DB014F0700F01D004781CB1002094 +:107678000DB0BDE8F08F14699F4E0C34557DA6FB04 +:107688000464C4F387040394AC0745D101274FF081 +:1076980000080E4615460693C246B3684446C146DE +:1076A80005F1160B09904146304604920893CDF82F +:1076B8001C80CDF81480FFF717FB75690021304650 +:1076C800C5F34F15FFF7CEF9002800F08D80037839 +:1076D800A3F1E502B2FA82F2520973B36ABBBC4263 +:1076E80038BF00242E2B25D022BBC17A0F295AD0AF +:1076F8000B071FD4B9F1000F40F0DD800B2259466B +:1077080006F0F0F80028D8D1049B5B7DD80740F13B +:10771800E88001230593D0E7039C671CFFB2B6E716 +:107728000AF1FF3A5FFA8AFA534503D1437B079976 +:10773800994249D04FF00009BFE7002C08BFA8467E +:10774800BC4201D20134E4B2002BCBD1069A1346D5 +:107758009A058CD503F00303013B012B87D8002C35 +:1077680008BFA846BC4203D348E0DCB2A74245D9CB +:1077780000213046FFF776F9631C0028F5D17378AD +:10778800002B7FF474AFA74238D9089D05E02B7908 +:1077980004EB0314E4B2A74230D93046FEF7EAFD01 +:1077A8000028F4D163E7B9F1000FB9D103F01F0A3B +:1077B800039A524581D1590602D4DDF80CA07CE722 +:1077C800437B914692460793BAF1010F7FF475AF58 +:1077D800691C4B46049A304689B2FFF749FD0028D8 +:1077E80008BF4FF0000968E77378002B7FF43FAFBC +:1077F800069A13469A057FF53AAFABE7059B33B176 +:1078080004993046FFF7D2FE00283FF430AF013F1D +:10781800049A30465FFA87F908EB09054B46ADB282 +:107828002946FFF781FD00283FF421AF6901304662 +:10783800FFF75AFA00283FF41AAF00213046FFF745 +:1078480011F9044600283FF412AF2022002106F067 +:107858007BF8049F294A3B4653F8160F5968206065 +:10786800616019899B7A2181A3727B7D176803F077 +:1078780018032373002F38D00DF12B020DF12E01C0 +:107888000BA8B847BDF82C10BDF82E209DF82B305A +:107898002182E2816373089A92F8283043F0010349 +:1078A80082F82830CDF800902A46069B3146099880 +:1078B800FFF772FADCE6BAF1010F7FF4D8AE441E86 +:1078C80013460A30D90114F8012F41EA5303A042A4 +:1078D80052FA83F3DBB2F5D11A46079B93427FF441 +:1078E800C6AE069B1905DDD5C1E645F221632382A4 +:1078F80023836382CFE700BF4FECC44E882100206A +:107908002DE9F0411F460B7882B00846202B14461B +:1079180003D110F8013F202BFBD0206005782F2DD4 +:1079280018BF002D0CBF012500253ED0A8462C4EBF +:1079380023E07F2A08F1010814D8D1B2A1F122036B +:107948001F29DBB28CBF4FF0000E4FF0010E1D2B2C +:107958001FD901239E4524D201F0BF013C2920D024 +:107968005C2A1ED02E2A04D0202A02D0C4F8108007 +:10797800A0600378CBB12F2B17D001AA011D03F00B +:107988000BF870B1019AB2F5803FD2D308F1020822 +:10799800E8E726FA03F303F0010383F001039E45A9 +:1079A800DAD3284602B0BDE8F0812369013BFE2BFB +:1079B80011D80378202B03D110F8013F202BFBD0DE +:1079C8002F2BF9D038602046FFF742FD05462846A0 +:1079D80002B0BDE8F0810025284602B0BDE8F0817C +:1079E800012100312DE9F04182788AB00023920705 +:1079F8008DF804308DF805308DF8063020D5016AF1 +:107A0800054611BB01212846FEF7F2FCC0B1411E14 +:107A180000F10A070024E20111F8016F42EA540359 +:107A28008F4256FA83F3DCB2F5D1E52700230770BD +:107A3800AE682B7006F12800AB7002F0C7FE50B993 +:107A4800002630460AB0BDE8F081806800F092FD5B +:107A58000028D7D1F4E706F50E7002F0B7FE00282B +:107A6800EED0306803681B6A984706460028E7D0BE +:107A7800EB78002BE5D0294601A8FEF7EFFE002899 +:107A8800DED0EB78002BDBD04FF0010820E001A816 +:107A9800FEF7E8FF08F101010028D1D0C37A0F2BC7 +:107AA800CED1027802F01F0398455FFA81F8C7D15A +:107AB800437BA342C4D10770A96891F8283043F0EA +:107AC800010381F8283053060ED4EB784345B7D329 +:107AD800A98801A8C8EB010189B24901FFF704F997 +:107AE80000210028D3D1ABE7AC6804F1280002F0EC +:107AF8006DFE0028A4D004F50E7002F067FE002881 +:107B08009ED0206803681B6A9847002898D098E799 +:107B1800486810B50C4668B10B894A8901339BB295 +:107B28009A420B8106D80368012203495B6898478B +:107B380000232381206810BDD40A0020F0B5044634 +:107B480087B00E4615460021406A4FF4007205F0D2 +:107B5800FBFE206A28B103680C2222495B6898471B +:107B6800206AE36903AA616A002704901846039112 +:107B780019686B0900926A1ECD6AE168ADF8163083 +:107B8800ADF814700131184BA847E8B1206A20B14C +:107B98000368022215495B689847102E626A4FF005 +:107BA800F8054FF0010314BF0C200420FF211570C5 +:107BB800626AD15401339842FAD1E069626A036873 +:107BC800E1685B6A984710B9002007B0F0BDE0692A +:107BD800A268E16803681144626A5B6A984707B063 +:107BE800F0BD00BF1C0C0020D15B0000400C002041 +:107BF800F8B5446A4FF40072002105462046EB2789 +:107C080005F0A2FE76262346902004F10A012022E0 +:107C18002770667003F8020F03F8012F8B42FBD11F +:107C28004FF40071F82302204AF65522A4F80B10ED +:107C380095F82B106173298D207463752B69E18188 +:107C4800E361AB69A4F8FE212362F8BD2DE9F04198 +:107C580004464FF400720021406A05F075FE656A1B +:107C680022694AF6552605F2BF10216802F0F6FD92 +:107C7800A369226905F2C31021681A44013A02F087 +:107C8800EDFD94F82A30002185F8C2312369E069B6 +:107C9800C5F8C6310368A769626A5B6AC5F8CA7124 +:107CA800A5F8FE61BDE8F041184700BFD0F814C040 +:107CB8004FF48071F8B5ACF5807390F82B600446EA +:107CC800456A4160B3FBF6F303F20112120A500051 +:107CD800A26000F1A1078F4274D94FF4C07200E08E +:107CE8007246C2EB0C0302F1800EB3FBF6F303F20B +:107CF8000111090A480000F1A1079742F0D8626013 +:107D0800A160D21BA3F6F57102F18007B1F5704F9F +:107D1800276108D3206A20B1036813222A495B68C7 +:107D280098470020F8BD21308132012103FB06006D +:107D3800E260B0F5803FA0612185204634BF04236E +:107D4800062384F82A30FFF781FF0028E9D020466F +:107D58008027FFF74DFFA2684FF4007129261B48C2 +:107D680005F12A03A5F8111005F13501EA82202250 +:107D780085F8247085F82660C5F8270003F8012FD8 +:107D88008B42FBD14120542131223623462685F8E7 +:107D9800370085F8381085F8366085F8392085F879 +:107DA8003A30E069626A036821695B6A984700288B +:107DB800B7D062682046E3681021D21ABDE8F840BF +:107DC800FFF7BCBE0A469CE77C0C002087D6120051 +:107DD800F8B504464FF4005242F209004FF48041CE +:107DE800D4F814C094F82BE0ACF580432261656A9E +:107DF8006160B3FBFEF303F18102D2095600A26071 +:107E08003044884214D94FF4C04100E03946C1EBF0 +:107E18000C0342F2090001F50057B3FBFEF303F12E +:107E28008102D209560030448842EFD86160A260CE +:107E38004FF6F472934208D8206A20B103681322DF +:107E480051495B6898470020F8BDA1F5005203FB33 +:107E58000E134E492046961BA3F500528B42B6B22C +:107E6800A26194BF0B230C2306F50052268584F8E3 +:107E78002A30E260FFF7EAFE0028E4D02046802797 +:107E8800FFF7B6FEA368022101224FF0060E29264D +:107E98006B6205F146033E48E96205F151012A8605 +:107EA8002022A5F832E085F8407085F84260C5F8D0 +:107EB800430003F8012F9942FBD14120542133227A +:107EC8003223462685F8530085F8541085F8526009 +:107ED80085F8552085F85630E069626A036821699B +:107EE8005B6A98470028AED0E069216903680631CB +:107EF800626A5B6A98470028A5D04FF40072002197 +:107F0800606A05F021FD234BE069C5F8FC31036880 +:107F180021695B6A0231626A9847002893D0E06958 +:107F2800216903680831626A5B6A984700288AD029 +:107F3800E3694FF0FF321848184928601846C5F819 +:107F4800E821C5F8EC21C5F8E4111B6821695B6AD2 +:107F58000131626A984700283FF475AFE0692169EA +:107F680003680731626A5B6A984700283FF46BAF81 +:107F7800A268204694F82B30202103EB4202BDE88A +:107F8800F840FFF7DBBD00BF7C0C00200004FB00BD +:107F980087D61200000055AA52526141727241619F +:107FA80038B504460D680846E16162622362EB69F0 +:107FB800984700F2FF736061DB0A062B236008D83C +:107FC800206A20B10368142226495B68984700207C +:107FD80038BD102B13D8022384F82B30B0F5800F4E +:107FE800204614D2FFF762FE0546206AADB108B3F9 +:107FF80003680D221C495B689847012038BD202B77 +:1080080014D9402B18D8082384F82B30E6E7FFF75B +:10801800DFFE0546206A002DE9D10028D7D0036885 +:108028000F2212495B689847284638BD042384F814 +:108038002B30D3E7012038BD802B06D9B3F5806FEC +:1080480007D8202384F82B30C8E7102384F82B3076 +:10805800C4E7B3F5004F94BF4023802384F82B3046 +:10806800BCE700BF900C0020A80C0020B80C002032 +:10807800042A0BD90A2A05D90C2A0CD801EB42028A +:10808800D088704701EB42029088704701EB4202AA +:10809800B2F8010070470020704700BFF0B50378C0 +:1080A80083B00D465BB113F060040DD0012A06D9E8 +:1080B8002F22002301200A704B7003B0F0BD00236B +:1080C80018462B7003B0F0BD21460192FEF790F9D7 +:1080D8000028F4D0214603464FF0080C2646019AA2 +:1080E8000FE0077B1CEA070F01D02034E4B2771CAD +:1080F800B646BA42E3D9FEB205F80E4001310C2962 +:108108000AD008291C780BD0A4F141070133192F94 +:10811800E7D9202CF2D0EAE700233046AB55D1E767 +:10812800202CF9D04FF0100C2E24E0E72DE9F04F69 +:108138004FF0000B8BB0037889468DF804B08DF8AA +:1081480005B08DF806B0002B61D0C3780546002B2A +:1081580064D0014601A81746FEF780FB002856D0D8 +:10816800E878002870D0013F4C464FF001084F4492 +:10817800A98801A8C8EB010189B24901FEF7B4FD3D +:10818800002844D0002101A8FEF76CFC0646002810 +:108198003DD0C37A0F2B3AD1037803F01F039845DB +:1081A80035D14FF0000A1CE000F510539BB2B3F52F +:1081B800806F2CD24FEA8B2B244BC0F309000BEABB +:1081C8000303184300F5803021463A4602F094FB39 +:1081D8000446E0B10AF1010A4FF0000BBAF10D0FA5 +:1081E8002AD05FFA8AF231462846FFF741FFBBF1F1 +:1081F800000FD9D100F520539BB2B3F5006F12D30D +:108208000028E1D1C9EB04000023237003E0002318 +:10821800184689F800300BB0BDE8F08FFFF73EFF35 +:108228000BB0BDE8F08FB3F5806FF0D20AF1010A08 +:108238008346BAF10D0FD4D108F10108EB785FFA43 +:1082480088F8434594D2DDE74C46DDE700FC0F0093 +:10825800FFF76CBF30B41468B4F5807F254628BF9B +:108268004FF4807501EB4500814207D231F8023B9B +:1082780013B95368013353608842F7D8641B1460FC +:1082880030BC704730B41468802C254628BF802540 +:1082980001EB8500814207D251F8043B13B95368BA +:1082A800013353608842F7D8641B146030BC7047B0 +:1082B8002DE9F843C37905460C461646202B06D00F +:1082C800102B1AD00C2B2FD00020BDE8F883037A8E +:1082D80000F50E70A969022B01EBD4110CBF032223 +:1082E800012202F043FA03460028EDD0A400012041 +:1082F80004F4FE741E51BDE8F883027AC1F3072125 +:10830800836900F50E70022A19440CBF032201226A +:1083180002F02CFA03460028D6D06400012004F4A9 +:10832800FF741E53BDE8F883C1F34E03027A8169D6 +:1083380000F50E7813FA84F3022A40469FB20CBF68 +:108348000322012201EB5729494602F00FFA0028BF +:10835800BAD014F00104C7F3080310D0C25C591C4A +:1083680002F00F02B1F5007F42EA0612C2540BD0A8 +:10837800C6F30716084406700120BDE8F8835A1CA6 +:10838800C654B2F5007F15D12B7A09F10101404698 +:10839800022B0CBF0322012202F0E8F9002893D037 +:1083A800360954B9035DC6F30316204423F00F03BE +:1083B8001E43E0E736091446F4E7F6B2DBE700BFF0 +:1083C800012972D92DE9F843C369994269D8C3795B +:1083D800174605460C46202B31D0102B41D00C2BCC +:1083E8005FD1C1F34E06037A816900F50E7816FA5B +:1083F80084F6022B4046B6B20CBF0222002201EBE3 +:108408005629494602F0B2F900284AD0C6F30806B0 +:10841800731C865DB3F5007F36D0C35CE20746EA7D +:1084280003234CBF1B11C3F30B03EA69934203D820 +:108438003B600120BDE8F8830020BDE8F883037A9B +:1084480000F50E70A969022B01EBD4110CBF0222B2 +:10845800002202F08BF920B3A40004F4FE7403593F +:10846800E3E7027AC1F30721836900F50E70022A57 +:1084780019440CBF0222002202F078F988B1640086 +:1084880004F4FF74035BD0E72B7A09F1010140463D +:10849800022B0CBF0222002202F068F908B1002367 +:1084A800BBE74FF0FF30BDE8F8834FF0FF3070476F +:1084B8002DE9F041C46882B005460F468C429046CB +:1084C80027D20C4600260134EB6901AA28469C42B3 +:1084D800214608D9C6B9EC68012601AA2846013404 +:1084E8009C422146F6D8A7420ED0FFF769FF002824 +:1084F8000ADBE8D0019B002BE5D106B1EC60012C2A +:1085080002D9EB699C4206D90026304602B0BDE884 +:10851800F0810126D7E76FF0704221462846FFF721 +:10852800C7FE06460028EFD05FB1012FECD9EB69F2 +:108538009F42E9D8394622462846FFF7B9FE002867 +:10854800E2D06B6A002B01DB013B6B62C8F800408C +:10855800DBE700BF01290BD910B4C469A14203D8D5 +:108568005DF8044BFFF7A4BE00205DF8044B70478C +:108578000020704770B5054682B00C460FE0FFF743 +:1085880097FE621EE0B16B6A002B03F10103A8BFDE +:108598006B62EB689C42019C38BFEA608EB1214651 +:1085A80001AA2846FFF70CFF012C0646C0F3C013AA +:1085B8002146284604D91A4613B9EB699C42DED9EC +:1085C800002002B070BD00BF436A002B01DB1846D3 +:1085D8007047F0B5C17985B005460C2924D0C36928 +:1085E800002490F838025A1C0394C3072C6902929D +:1085F80036D400204FF0FF33202905F5127285F894 +:108608003802C5F8443233D0286802AF1B4E2346DF +:108618000468A9698DE8C000A469A047C8B1039B94 +:108628006B62184605B0F0BDC7690137022F23D920 +:108638000224002605E002D0029B03B90136A742B6 +:108648000CD0214602AA28460134FFF7B9FE0028BB +:10865800F1DA4FF0FF33184605B0F0BD3346E0E7D6 +:1086680005F50E7002F0B2F80028F2D0E979C0E7FB +:10867800286802AF024ECAE70023D2E7156300005C +:1086880045630000F8B5044600234FF0FF3001268B +:1086980021601546E162C4F83C12E660E37184F893 +:1086A800283084F838326063C4F84402DAB1042A06 +:1086B80001D90020F8BD04F128061A4619463046AB +:1086C80002F054F86FF0704300F5DF712B441B0182 +:1086D800CA180028EDD010790028EAD0CB5C5B06D8 +:1086E800E7D1956801E004F12806304600222946C2 +:1086F80002F03CF80028DCD0B0F80B30B3F5007F6E +:10870800D7D1037C5A1E2372012AD2D8467B002374 +:10871800721E012E2671A371627149D001210A4689 +:1087280000E0194652004B1CD2B2DBB2964203D08D +:10873800092BF6D1A171BCE7A171C68A26610EB9D1 +:10874800466A2661C789B0F8113007EB050E6381C8 +:108758005B01C4F818E0077C03F2FF13B0F813209C +:1087680006FB07E707EB53232762636102B9026A36 +:10877800ED1A4FF0FF3340F6F4771544636225FA9B +:1087880001F35A1CBB42E26106D80C23E37126634D +:108798000120C4F84062F8BD4FF6F472934202D843 +:1087A8001023E371F3E7C26A20232262E371EEE744 +:1087B8001946C2E7F8B5002506460F4685638C6B57 +:1087C800C5638CB10146242000F0BAF805704570E5 +:1087D80004468570B063BD6B0FCD0FC40FCD0FC4B9 +:1087E8002B6823603046F8BDCB6B002BFAD00146CE +:1087F800382000F0A5F880F8314080F83240024671 +:1088080080F83340F063FB6B03F130011F681033CD +:1088180053F80C5C103253F8084C53F8040C8B4294 +:1088280042F8107C42F80C5C42F8084C42F8040C00 +:10883800ECD11B681360D5E710B50446806B28B1EE +:10884800FDF730FE10B10023A36310BDE06B28B123 +:10885800FBF702FD10B10023E36310BD002010BD3B +:10886800C9B32DE9F0410C46054698461746FFF76F +:10887800E3FFD4F88064AEB100262946242000F036 +:108888005FF8434606703A4646708670A863D4F887 +:108898008014FDF7DBFF10B10120BDE8F081A8636B +:1088A800BDE8F081D4F88434BBB12946382000F003 +:1088B80047F8434680F831603A4680F8326080F8DD +:1088C8003360E863D4F88414FCF71EF90028E3D178 +:1088D800E863BDE8F081002070470020BDE8F08122 +:1088E800F8B50D4617460446FFF7A6FFAE6B8EB1E6 +:1088F8002146242000F024F800213A4601704170F6 +:108908008170A063A96BFEF7B3FA08B10120F8BD26 +:10891800A063F8BDE86B88B12146382000F010F854 +:108928003A4680F8316080F8326080F83360E0635E +:10893800E96BFCF7F1F80028E8D1E063F8BD00BF67 +:10894800084670472DE9F041044600261F464FF4BB +:108958009060C4F888142146C4F880649046FFF7F4 +:10896800EFFF3A4680F84464054680F8796480F859 +:108978007A6480F87B64C4F88404D4F88814FDF71A +:108988002FFC08BB0026214640F26C40C4F88464E2 +:10899800FFF7D6FF0223C6713A4680F848640546B9 +:1089A80080F8496480F84A640372C4F88004D4F8F3 +:1089B8008814FFF767FEF0B90023194A1846C4F86F +:1089C80080341360BDE8F08105F589663046FBF711 +:1089D80043FC29463046FBF76DFC0028D2D0114BEA +:1089E8001A68BAB10E4BB8F1000F15D11A689AB1CE +:1089F8000120BDE8F08105F589663046FDF752FD96 +:108A080029463046FDF746FF0028D5D0064B1A68A0 +:108A1800002AE7D11D60E5E71C600120BDE8F08170 +:108A2800C421002090210020C8210020F8B500258D +:108A38004FF47A77064E044687600571057385649E +:108A4800C56440F8106BFFF70BFF2046F8BD00BF68 +:108A5800FC050020407C7047007D7047407D7047D2 +:108A680001207047007F704710B4046801236469CF +:108A7800A4465DF8044B604738B5036804460D46C4 +:108A88001B6A984700B1257738BD00BF2DE9F0472C +:108A98001E46C37C05460C46022B9146089F23D0F0 +:108AA8002B68214628461B6E984798B1AC61B9F1EE +:108AB800000F12D004EB090801E0A0450DD039469B +:108AC8002046B0472B6801462846DB6D013498479D +:108AD8000028F2D10020BDE8F087AB69287F4B441D +:108AE800AB6128B1BDE8F08783698B42D8D1DEE756 +:108AF8002B6828465B6EBDE8F0471847704700BFF3 +:108B0800043001F0BDBD00BF10B50446202104F0BB +:108B180063F9204610BD00BF2DE9F0411F46C37C14 +:108B280006460D46022B14461FD0336829463046A8 +:108B38001B6E984778B1B56187B1002501E0AF4257 +:108B48000CD03368214630460135DB6D04F50074DE +:108B580098470028F3D10020BDE8F081B369307F41 +:108B68001F44B76128B1BDE8F08183698B42DCD12D +:108B7800E2E7336830465B6EBDE8F041184700BF56 +:108B880038B5051D0446284601F0B2FC207C0021BA +:108B980001F0ACFC2846FF2101F092FD0123A374EB +:108BA80038BD00BF03685B6E184700BF38B5051DA8 +:108BB80004460121007C01F099FCFF21284601F0C0 +:108BC8007FFD284601F030FD0023A37438BD00BFA7 +:108BD800F8B5164E0746051D346804F51674A4B298 +:108BE80003E03368E31A1B040ED4284601F04CFD59 +:108BF800FF28F6D12846FD2101F062FDBB7C6BB948 +:108C080000230120FB74F8BD1E23B87C7B7400B9D7 +:108C1800F8BD3846FFF7CAFF0020F8BD3846FFF711 +:108C2800C5FF00230120FB74F8BD00BFF02700201A +:108C380038B5C37C012B16D0837C044663B9FFF793 +:108C48009FFF201D01F020FDA37CB0F1FF0518BF98 +:108C5800012553B9284638BD043001F015FDFF3809 +:108C680018BF012038BD002038BD2046FFF79EFF01 +:108C7800284638BD2DE9F041036882B0064688468B +:108C880001921B6A984718B9FF2002B0BDE8F0812D +:108C9800B37C002B3ED0B8F10C0F3FD0204F341DD1 +:108CA8003D6805F59675ADB203E03B68EB1A1A040A +:108CB8002CD4204601F0E8FCFF28F6D148F040010A +:108CC800204601AF02AD01F0FBFC15F8011D20465E +:108CD80001F0F6FCAF42F8D1B8F1000F20464FF092 +:108CE8000A0514BF8721952101F0EAFC204601F00E +:108CF800CBFC204601F0C8FC03063075C5D5013D04 +:108D0800ADB2002DF5D102B0BDE8F081B8F1000F89 +:108D1800BAD1D3E73046FFF733FFBCE7341DCDE7C0 +:108D2800F02700202DE9F04788B000250646071DEA +:108D380001AC85744574457584E80E009DF80400FF +:108D4800DDF80880307401F0CDFB307C012101F0A2 +:108D5800CDFB5949072205ABB160F26094E80700E2 +:108D680083E8070038460ECB01F044FCB37CF57469 +:108D7800002B67D00121307C0A2401F0B7FBFF21CA +:108D8800384601F09DFC611E11F0FF04F7D1214621 +:108D9800307C0A2501F0AAFB002230461146FFF775 +:108DA80069FF0128044605F1FF330DD013F0FF05D4 +:108DB800F2D101237374B07C18B13046FFF7F6FE88 +:108DC800002008B0BDE8F0874FF4D572082130467E +:108DD800FFF750FF420739D574753368DFF8E0A014 +:108DE8009B6D534545D1707D344D02282C680CBFCE +:108DF8004FF080494FF0000904F5FA64A4B203E08B +:108E08002B68E31A1B0431D4002237213046FFF7C0 +:108E180031FF4A4629213046FFF72CFF0028EFD1C1 +:108E280033689B6D534527D1707D022827D0B37CCA +:108E380013B13046FFF7BAFE0723C6F808800120B1 +:108E4800F360BEE73046FFF79BFE93E70223042456 +:108E58007375384601F018FC631E307513F0FF0473 +:108E6800F7D1AA28B9D006237374A4E7172373741B +:108E7800A1E730469847B7E730469847D5E700223C +:108E88003A213046FFF7F6FE10B11223737492E7C9 +:108E9800384601F0F9FB00F0C000C02809D0384678 +:108EA80001F0F2FB384601F0EFFB384601F0ECFB2D +:108EB800BDE703237375F2E7801A0600F027002048 +:108EC8001D6B0000F8B500220D463A210646FFF753 +:108ED800D1FE68B9371D2C1D384601F0D5FB04F8C2 +:108EE800010DA542F8D1B47C6CB901242046F8BD27 +:108EF8001223B47C7374002CF8D000243046FFF79A +:108F080055FE2046F8BD3046FFF750FE2046F8BD16 +:108F180003680A4630B59B6D83B0114D0446AB42D9 +:108F280014D1407D03284FF01901204618BF520282 +:108F3800FFF7A0FE28B10E23A07C637450B903B0DC +:108F480030BD02230120E37403B030BD019198477E +:108F5800019AE7E72046FFF729FE002003B030BD5D +:108F68001D6B00002DE9F8431A4E054688469146C8 +:108F78003468071D04F59674A4B203E03368E31A55 +:108F88001B0411D4384601F07FFBFF282875F5D063 +:108F9800FE280CD018236B74A87C18B12846FFF75C +:108FA80005FE0020BDE8F8831D236B74F4E74A46EC +:108FB8004146384601F074FB287510B125236B74BF +:108FC800EAE7384601F060FB384601F05DFB012016 +:108FD800BDE8F883F027002038B51546002204467E +:108FE800FFF748FE40B11B236374A07C18B12046EC +:108FF800FFF7DCFD002038BD294610222046FFF788 +:10900800B1FF0028F1D0A57C002DF4D02046FFF751 +:10901800CDFD284638BD00BF0A460921FFF7DCBF51 +:109028000A460A21FFF7D8BF0368244ADB6C93423B +:1090380030B585B02FD16A460921FFF7CDFF38B189 +:109048009DF8003013F0C00304D0402B26D0002038 +:1090580005B030BD9DF809409DF806309DF8072001 +:1090680004F003049DF80A0003F0030364009DF86C +:10907800051092009DF8085044EAD01001F00F0145 +:1090880042EA8323084443EA95130738013303FA75 +:1090980000F005B030BD69469847D0E79DF8093023 +:1090A8009DF807105A1C9DF8080001F03F0302EBD9 +:1090B800034303EB0020800205B030BDD9700000E7 +:1090C80003682DE9F041DB6C84B0324C05460F464D +:1090D8001646A3422ED16A460921FFF77DFF0446B2 +:1090E80084B19DF80A305A0616D56B7D032B01D042 +:1090F8007F0276023A4620212846FFF7BBFDE8B1F9 +:1091080026236B74AC7C1CB128460024FFF74EFD67 +:10911800204604B0BDE8F08103F03F039DF80B1032 +:10912800721C5B003A4343EAD1131342DDD0272374 +:109138006B74E7E7694698470446D1E73246212130 +:109148002846FFF797FD0028DAD10246262128464F +:10915800FFF790FD0028D3D10F4F42F2107605F1AA +:1091680004083B681E44B6B203E03B68F31A1B04CC +:109178000CD4404601F088FAFF28F6D1AB7C002BCE +:10918800C6D028461C46FFF711FDC1E728236B749B +:10919800B8E700BFD9700000F027002003680A462E +:1091A80030B59B6D83B0114D0446AB4214D1407D60 +:1091B80003284FF01201204618BF5202FFF75AFD4C +:1091C80028B10C23A07C637450B903B030BD0123CF +:1091D8001846E37403B030BD01919847019AE7E758 +:1091E8002046FFF7E3FC002003B030BD1D6B0000F4 +:1091F80070B500260C210446C6743246FFF73AFDC6 +:1092080028B10923A57C63745DB9284670BDA57C87 +:1092180015B90125284670BD2046FFF7C7FC28462A +:1092280070BD35462046FFF7C1FC284670BD00BF1B +:10923800C37C022B05D0012B01D001207047FFF71A +:10924800D7BFFFF7AFBC00BF2DE9F0479A46C37CF4 +:1092580006460C46012B1546DDF82080099F24D0D0 +:1092680021463046FFF79AFFA8B1B461BAF1000F62 +:1092780014D004EB0A0904E020460134C047A14594 +:109288000CD04FF4007229463046FFF76BFE3A4681 +:1092980029460028F0D10020BDE8F087B369307F67 +:1092A8005344B36128B1BDE8F08783698B42D7D1B5 +:1092B800DCE73046BDE8F047FFF79ABFF8B51F4630 +:1092C800C37C06460D46012B14461CD02946304661 +:1092D800FFF764FF78B1B5617FB1002501E0AF42C7 +:1092E8000BD04FF400722146304601351444FFF785 +:1092F80039FE0028F3D10020F8BDB369307F1F4440 +:10930800B76120B1F8BD83698B42DFD1E4E730460D +:10931800BDE8F840FFF76CBF70B5041D164605465A +:10932800204601F0CDF94FF400723146204601F095 +:10933800D1F92046FF2101F0C3F92046FF2101F0B1 +:10934800BFF9204601F0A0F900F01F032875052B8E +:1093580009D02023A87C6B7400B970BD2846FFF79C +:1093680025FC002070BD012070BD00BF2DE9F04133 +:10937800144D07468846061D2C6804F51674A4B2D9 +:1093880003E02B68E31A1B040ED4304601F07CF985 +:10939800FF28F6D14246FC213846FFF7BDFF70B9D9 +:1093A800B87C30B9BDE8F0812423B87C7B740028F0 +:1093B800F8D03846FFF7FAFB0020BDE8F081BDE899 +:1093C800F08100BFF0270020036870B59B6D82B064 +:1093D800154D04461646AB4222D1407D032820464F +:1093E80018BF49020A461821FFF744FC48B10D236B +:1093F8006374A07C18B12046FFF7D8FB002002B0A8 +:1094080070BD3246FE212046FFF786FF0028F0D0C7 +:10941800A57C002DF3D02046FFF7C8FB2846EEE7D1 +:10942800019198470199D9E71D6B000010B4047F9A +:109438001CB95DF8044BFFF7C7BF04680123A46A91 +:10944800A4465DF8044B604730B585B0054601ACCD +:1094580084E80E0094E80E00FFF764FC20B19DF844 +:10946800053003F001032B7705B030BD704700BF0E +:10947800084B0021084A094810B499631C6B146012 +:1094880012685DF8044B1A639A6C22F081029A64A0 +:109498000170704700002C4084210020072800201C +:1094A800034B04481B6B1840B0FA80F04009704722 +:1094B80000002C4001000F00024B586A00F0010028 +:1094C800704700BF00002C40034B586A80F0807042 +:1094D800C0F30060704700BF00002C40014B1878B3 +:1094E800704700BF07280020034B586A80F40060CB +:1094F800C0F3C020704700BF00002C40034B586ADF +:1095080080F48060C0F38020704700BF00002C40CA +:10951800034B04481B6B1840B0FA80F040097047B1 +:1095280000002C4002007F114FF47A722B4B2C491B +:1095380002FB00F0496AD3F800212A4BC1F3C2218B +:1095480002F03F020131A3FB0223F0B49B08264D31 +:10955800B5FBF3F5B5FBF1F5B0EB151F38D20122D9 +:1095680001E0FF2A05D852001301B5FBF3F3984236 +:10957800F7D351080F02B5FBF2F398422BD25400EF +:10958800012100E01C464E1CB5FBF4F3984202EBA7 +:1095980004031BD2102E3146F4D1F0234FF47A7213 +:1095A800124E134902FB04F412483246B5FBF4F597 +:1095B8000D60F16A084040F4602040EA0701194351 +:1095C800F162536A1B07FCD5F0BC70470B01E5E755 +:1095D80000270122CFE714460023DFE700800D4073 +:1095E80000C00F40ABAAAAAA00EC695E00002C409C +:1095F800382100200F00F0FF014B1878704700BF9A +:1096080016160020014B1868704700BF84210020FF +:1096180030B4054C0D460FCC286001206960AA6063 +:10962800EB6030BC704700BF5021002030B4054CBF +:109638000D460FCC286001206960AA60EB6030BC41 +:10964800704700BF60210020024B01201B680B609F +:10965800704700BF70210020704700BFF8B505466D +:10966800074F02F007F8064604E002F003F8801BF3 +:10967800B84203D8A84704460028F6D12046F8BDCA +:1096880040420F002DE9F041DFF8408005460E4FBB +:10969800C8F8000001F0EEFF064606E001F0EAFF18 +:1096A800801BB8420AD803F0ADFBA847044600283F +:1096B800F4D1C8F800002046BDE8F0810023204618 +:1096C800C8F80030BDE8F08140420F00802100203A +:1096D80010B504460C2103F07FFB204610BD00BFE7 +:1096E8000F4B002247F2B80141F2B800C3F8CC2171 +:1096F800C3F8D021C3F8BC21C3F8C021C3F8C421E2 +:10970800C3F8C821C3F8BC13C3F8C013C3F8AC131B +:10971800C3F8B003C3F8B413C3F8B813704700BF55 +:1097280000801F40054B1B7833B1054B1B78002B7D +:1097380014BF03200220704701207047032800202F +:109748000428002038B5044614480D46FFF786FF64 +:1097580008BB134BA1029D6007D5996CE2B221F0BA +:10976800FF019964996C0A439A6424F0FF040C4D34 +:109778000C48EC60FFF772FF68B92A6B0A4B1A6055 +:109788001A682A631A68D20705D51B6813F4702F64 +:1097980001D1012038BD002038BD00BF7975000017 +:1097A80000002C40617500008421002008B5074B9B +:1097B80007481968FFF7C6FF30B1064B186980F4EF +:1097C8008070C0F3002008BD012008BD742100206E +:1097D80000001A0D00002C4008B5044B0448196815 +:1097E800FFF7B0FF08B1034B186908BD74210020CA +:1097F80000001A0D00002C40144B70B50E4684B0C2 +:109808001968FFF79FFFF0B1114906F10F05002312 +:109818000A6900924C6901948C690294C9690391A0 +:1098280001E054F8102C03F003010133C90023F0C0 +:1098380003040F2B22FA01F204A905F8012D0C44A8 +:10984800EFD10023F37304B070BD00BF7421002072 +:1098580000002C40054B186810F0020005D01B686A +:1098680003481840B0FA80F040097047842100206E +:1098780000007F11F8B512F0030418BF0124002B73 +:1098880008BF44F0010444B11E4925201E4B40F294 +:10989800F51208701A600020F8BD06461B481D46E0 +:1098A8000F461446FFF7EEFE10BB2B04184A194D5D +:1098B8004FF0010E1A40184985F800E0174B42F4A2 +:1098C80000720860164D17491C605A609D630B783A +:1098D800B3B979023046FFF735FF0028DBD01248CC +:1098E800FFF7D0FE0028D6D1BDE8F840FFF7B2BF99 +:1098F80004490A20044B4FF4FC7208701A60CAE746 +:109908003946E7E716160020402100206D78000050 +:109918000000FF1F072800208421002000002C40A1 +:1099280002007F11042800209D750000194970B4B9 +:109938000B7813F0C00311D0402B02D0002070BC6C +:1099480070474B7ACC795A1C087A04F03F0302EB33 +:10995800034303EB002070BC800270474D7A8B797B +:10996800CA7905F00305887A03F003036D004C7982 +:1099780092000E7A45EAD01004F00F0142EA8323E0 +:10998800084443EA96130738013370BC03FA00F021 +:10999800704700BF60210020037ADB0703D50E4B18 +:1099A8001B6893B118470D4B1B7833B90C4B586A99 +:1099B80080F08070C0F300607047094B09481B6B4A +:1099C8001840B0FA80F040097047074B1878002813 +:1099D800F2D0FFF7EBBE00BF802100200528002051 +:1099E80000002C4002007F11022800202C4838B5C6 +:1099F800837A154603F040025AB903F03F0302F098 +:109A0800FF04C27A681C5B00084343EAD21303428E +:109A180021D1244B1B780BB949026D022248FFF76C +:109A280091FE044640B921490F20214B40F2EB2218 +:109A380008701A60204638BD29461E48FFF782FE86 +:109A4800044688B919491020194B40F2EE220870D3 +:109A580020461A6038BD15492720154B40F2E322ED +:109A6800087020461A6038BD00211348FFF76AFEC7 +:109A7800044638B90D4911200D4B40F2F122087007 +:109A88001A60D7E70D48FFF7E9FD0028D2D007494B +:109A98002820074B4FF43D72002408701A60C9E76C +:109AA800602100200428002000001A20161600203B +:109AB8004021002000001A2100001B266D780000BC +:109AC80010B50E480024FFF7C9FD0D490D4A0E4B8D +:109AD8000C70116B19601968116318B91A680B4B6F +:109AE800134043B10A491F240A4B40F27A2200204E +:109AF8000C701A6010BD012010BD00BFD1750000A8 +:109B08000528002000002C408421002000007F113F +:109B1800161600204021002038B5184C002118489E +:109B2800A36A23F48033A362FFF70CFE054640B90D +:109B380014490920144B40F23D2208701A60284647 +:109B480038BD1248FFF79EFD70B9636A9B07F6D5CA +:109B5800616B2846A36AE26A23F4803342F080628C +:109B6800E2626163A36238BD06490A20064B4FF4DE +:109B78001072002508701A60284638BD00002C4075 +:109B88000000DB0C1616002040210020897500001B +:109B980070B51E4E0D463378002B31D11C4B5A6AD6 +:109BA800D10507D49A6A22F480329A629A6A42F4FA +:109BB80000329A62164C1748A36A43F48033A362B2 +:109BC800FFF74CFD98B920462B1F05F5FE74426A35 +:109BD8005205FCD503F1400153F8042F9942026263 +:109BE800FAD18C420B46F2D10120307070BD0A497F +:109BF80021240A4B40F2D93200200C701A6070BD43 +:109C0800FFF75EFF0028C9D170BD00BF05280020FE +:109C180000002C40BD7500001616002040210020D1 +:109C280010B514480C46FFF72DFDC8B9124B4FF478 +:109C3800007012499A6A22F480329A6258600B784E +:109C480063B961020E48FFF77DFD30B90D490E2456 +:109C58000D4B4FF487620C701A6010BD2146F1E776 +:109C680008490A20084B40F22C42087000201A606C +:109C780010BD00BF6D78000000002C4004280020B3 +:109C880020003A191616002040210020F8B5064693 +:109C9800007A0C461546C0071F4613D483B10F44FB +:109CA80001E0BC420CD033682A46214630465B6A44 +:109CB80005F50075013498470028F2D10020F8BD59 +:109CC8000120F8BD900712D0002BF9D00F4401E015 +:109CD800A742F5D033682A46214630465B6A05F527 +:109CE8000075013498470028F2D10020F8BD0648D5 +:109CF800FFF7C0FD0028E3D104490E24044B40F2CD +:109D08001E420C701A60F8BD27003A19161600207A +:109D18004021002070B5037A1546ADF5007D0E464A +:109D2800DA0719D5AB0706D029464FF40072684602 +:109D38006D4601F03DFA2A46314601232148FFF7D6 +:109D480099FD30B920490D24204B40F2F2320C70B5 +:109D58001A600DF5007D70BD1D4B04461B78ABB92C +:109D6800637A022B08D0236820461B6A984798B963 +:109D780000200DF5007D70BD63689E4216D02368F3 +:109D880020461B6A98470028F2D005E0FFF798FEA6 +:109D98000028E5D10020ECE72368314620461B6EF9 +:109DA80098470028E4D00223666063722368294636 +:109DB8002046DB6D98470028DAD06368013363607A +:109DC800C7E700BF01003A181616002040210020FE +:109DD80005280020F8B50646007A0C461546C00747 +:109DE8001F4613D483B10F4401E0BC420CD0336842 +:109DF8002A46214630461B6905F500750134984707 +:109E08000028F2D10020F8BD0120F8BD900712D03B +:109E1800002BF9D00F4401E0A742F5D033682A4659 +:109E2800214630461B6905F500750134984700281E +:109E3800F2D10020F8BD0648FFF71CFD0028E3D149 +:109E480004490C24044B40F282320C701A60F8BDAD +:109E580037003A121616002040210020F8B50546B2 +:109E68001B480C46FFF7FAFB40B11A490A201A4B67 +:109E78004FF4CC72087000201A60F8BD174A012709 +:109E8800174B29461770174E174D184A30601C603B +:109E980017485D609A63FFF755FC38B90D490424EB +:109EA8000D4B40F29F120C701A60F8BD1148FFF775 +:109EB800E9FB18B9FFF7CEFC00B1F8BD054925202C +:109EC800054B4FF4D172087000201A60F8BD00BF2E +:109ED8006D78000016160020402100200728002079 +:109EE80000002C40842100204000010002007F1166 +:109EF80011003A069D7500002DE9F043B74A00238A +:109F0800B74D0524017291B02B704372D2F800014D +:109F1800B44F40F08000B44EDFF834833B703370A8 +:109F280088F80030C2F80001D2F80001AF4B20F0E9 +:109F38003F00AF49C2F80001D2F8000140F0180014 +:109F4800C2F80001D2F8000120F08000C2F8000138 +:109F5800D3F88020A74842F00C02C3F880205A6A40 +:109F680022F460525A62DA6942F48032DA615A6A3B +:109F780042F400625A620246C1F8CC41C1F8D041AD +:109F8800C1F8BC41C1F8C041C1F8C441C1F8C841D9 +:109F9800816C994B41F000418164C16A0B43C362F3 +:109FA800D36A944CD901FBD44FF4C870FFF7BCFABC +:109FB800FFF796FB9149924B924A6163C3F8F821E7 +:109FC800914B6020914A4FF48041187023461160EC +:109FD800E26A42F00062E262D96A11F00061FBD1E4 +:109FE8000846FFF7AFFB044600284DD003244FF482 +:109FF800D5718748FFF7A6FB00285CD1013CF6D154 +:10A0080098F80030834C002B08BF4FF4401401F03F +:10A0180031FBDFF84082814600217F48FFF792FB41 +:10A0280050B917217D4B40F29F22002429701A60F5 +:10A03800204611B0BDE8F08321467948FFF782FB3E +:10A048000028EED001F016FBC9EB0000694A404534 +:10A05800E7D81369002BDFDA1169724B19601369AD +:10A068005A0001D50123337000216F48FFF76AFBBE +:10A07800044698B90221694B4FF42A722046297088 +:10A088001A6011B0BDE8F0830121644B40F28E22C2 +:10A09800204629701A6011B0BDE8F083002163489A +:10A0A800FFF750FB0446C0B903215C4B40F2AB22DA +:10A0B80029701A60BCE74F4B1B69B3F5D57F07D0F1 +:10A0C8000621564B4FF42572002429701A60AFE719 +:10A0D8000123504C88F8003099E7464E544B3269BA +:10A0E800DFF87481134053495348C8F80030FFF72C +:10A0F80083FB044630B90721484B4FF42C72297072 +:10A108001A6095E74D494E48FFF776FB044630B98B +:10A118000821424B40F2B32229701A6088E7D8F828 +:10A1280000104848FFF70EFB044630B905213B4BA9 +:10A1380040F2B62229701A607AE7D8F8001036483B +:10A14800FFF700FB38B91421344B40F2BA2200243F +:10A1580029701A606CE702213B48FFF7F3FA0446BE +:10A168000028F0D0B36A4FF010126FF07F406946B4 +:10A1780023F00603B362B36A43F00203B362726466 +:10A18800FFF76CFE18B19DF80D309B0716D446F208 +:10A19800A810174B0522C3F8CC21C3F8D021C3F867 +:10A1A800BC21C3F8C021C3F8C421C3F8C821FFF7F4 +:10A1B800BBF9FFF795FA01233B7039E76946234855 +:10A1C800FFF74CFE0028E2D09DF8103003F00F0393 +:10A1D800012BDCD14CF25030DBE700BF00800D4092 +:10A1E80016160020022800200428002000C00F4076 +:10A1F80000801F4000002C40008000010B007F11F0 +:10A2080000180020317500006EE400E00CE100E069 +:10A2180000001A080000304000001A3740210020D2 +:10A2280000000229702100200000090200001A0322 +:10A238000000FFFF602100200000090950210020D4 +:10A248000000090A00001B0700001A06F1FFFF8042 +:10A258000328002040420F007421002038B5274B06 +:10A268000D465A6A94050DD49A6A22F480329A628D +:10A2780072B69A6A42F400329A629A6A42F480325A +:10A288009A6262B61E48FFF7E9F900282DD12B1F04 +:10A298001A4905F5FE754A6A1005FCD503F1400018 +:10A2A8000A6A164C43F8042F9842F9D185420346AE +:10A2B800F1D11448FFF7D2F970B9226B124B1A602A +:10A2C8001A6822631A68920717D51B680F48184046 +:10A2D800B0FA80F0400938BD0D491D200D4B40F201 +:10A2E8004232087000201A6038BD09491A24094B07 +:10A2F80040F2373200200C701A6038BD00002C4044 +:10A30800A9750000D17500008421002000007F118C +:10A31800161600204021002010B514480C46FFF7FF +:10A32800B1F9C8B9124B4FF4007012499A6A42F455 +:10A3380080329A6258600B7863B961020E48FFF761 +:10A3480001FA30B90D490C240D4B40F29E320C70C5 +:10A358001A6010BD2146F1E708490A20084B40F26F +:10A368009232087000201A6010BD00BF6D7800009E +:10A3780000002C400428002030003A121616002055 +:10A388004021002070B5037AADF5007D1546DC0745 +:10A3980011D5930720D0012329486A46FFF76AFAA6 +:10A3A80000B3694628464FF4007200F001FF01200F +:10A3B8000DF5007D70BD234B04460E461B7833BB5C +:10A3C800637A012B19D0236820461B6A984720BB63 +:10A3D80000200DF5007D70BD01231948FFF74AFAEA +:10A3E8000028E4D10B201849184B40F25532087068 +:10A3F80000201A600DF5007D70BD63689E4215D07F +:10A40800236820461B6A98470028E1D005E0FFF73B +:10A4180057FB0028D4D10020DBE731462046FFF760 +:10A428007BFF0028D4D0012366606372294620464A +:10A43800FFF714FF0028CBD0636801336360D9E7C6 +:10A4480011003A110528002016160020402100208E +:10A4580070B5144A00250E4645722946936A12487B +:10A4680023F480339362FFF76DF9044688B10EB97F +:10A47800204670BD0D48FFF705F90028F8D02C4696 +:10A488000B490A200B4B4FF46E72087020461A6075 +:10A4980070BD07490920074B4FF46D7208702046BC +:10A4A8001A6070BD00002C400000DB0C89750000AC +:10A4B8001616002040210020094B1B7810B50446D1 +:10A4C8004BB9637A0BB9012010BD20460121BDE8C4 +:10A4D8001040FFF7BDBFFFF7F3FA0028F1D110BD18 +:10A4E80005280020012101F037B900BF01F028B983 +:10A4F8000368416830B4DA7C8468002A28D072B6D0 +:10A50800DA7CD50706D533485A6905682A409A6225 +:10A518000260DA7C900706D52F489A6905682A40B8 +:10A52800DA620260DA7C550706D52C48DA690568D4 +:10A538002A401A630260DA7C100706D528481A6A8E +:10A5480005682A405A630260DA7CD2062BD462B6C8 +:10A558009A688A422ED0234A996092692248C2F3A7 +:10A568000115C2F3826250F825000132B0FBF2F007 +:10A57800B9B1B0FBF1F242B1B0FBF2F0884288BF4A +:10A588000132B2F5817F17D3184ADA601B680025BB +:10A59800032001211D6158621A641C66196130BCD0 +:10A5A80070470246E7E712485A6A05682A409A63E4 +:10A5B8000260CCE7DA68E9E7022A98BF0022E4D90A +:10A5C800023A5008010442EA002201F47F010A43DA +:10A5D800DBE700BF80E100E084E100E088E100E023 +:10A5E8008CE100E000C00F4038070020FF7F7F00AB +:10A5F80090E100E000B585B00DF1100E0EE90E00F7 +:10A60800039B33B10360184605B05DF804EB00F016 +:10A6180007BB044A13460260184605B05DF804EB10 +:10A6280000F0FEBA6C1100200268D37CE3B1D807B1 +:10A6380003D50E4B916A1960D37C990703D50C4B4F +:10A64800D16A1960D37C580703D50A4B116B19607E +:10A65800D37C190703D5084B516B1960D37CDB06F3 +:10A6680002D5926B054B1A60704700BF00E100E00D +:10A6780004E100E008E100E00CE100E010E100E0A6 +:10A68800006800F0E9BB00BF0268FF231268536648 +:10A69800D36D13F4F81FFBD0506FC0B2704700BFE2 +:10A6A80070B50C4616460546FF21204603F04CF9C6 +:10A6B800286833462246214600F0CAFB002070BDB8 +:10A6C80003681A685166D36D13F4F81FFBD0536FF3 +:10A6D800704700BF30B5551EADF5017D1346B5F581 +:10A6E800007F10D362B10268C818126811F8013BE4 +:10A6F8005366D36D13F4F81FFBD08142536FF5D125 +:10A708000DF5017D30BD14460546684600F050FD44 +:10A7180023466A466946286800F09AFB0DF5017DD4 +:10A7280030BD00BF70B50446406804F110060368E8 +:10A73800E16832465B6A984740B1237805469A0734 +:10A7480007D423F001032846237070BD002528464E +:10A7580070BD60683246A168E668036831445B6A88 +:10A7680098470028F2D02378EBE700BFF8B5436894 +:10A77800FBB1C368044615460F468B420ED00378DA +:10A78800DA0712D46B0716D504F11006002205F07B +:10A7980003053046E76015432570F8BD10F9102B06 +:10A7A80005F0030515432570F8BDFFF7BBFF00282A +:10A7B800E8D10020F8BD606804F110063946036846 +:10A7C80032461B6998470028E0D1F2E70378DB0797 +:10A7D80001D401207047FFF7A5BF00BF10B4034B99 +:10A7E800002414705DF8044B1B6818478C21002066 +:10A7F800024A0349034B1160186070478821002002 +:10A808009D8800008C2100208389B3B94268816843 +:10A818008A4201D31846704710B582B004461046E4 +:10A8280001AA00F0B9F860B1019A6060B2F5803F02 +:10A838000AD293B2184602B010BD0022828118468F +:10A8480070474FF6FF73F5E7930AC2F30902A3F5C1 +:10A858002153A2F510529BB2A281EBE7B1F5807F9C +:10A8680070B41DD810293FD840232026B2FBF3F13D +:10A87800B1F5806F1DD203FB11238C08C9B224F0F7 +:10A888003F048170B2FBF6F506FB1522B3FBF6F325 +:10A898000132DBB222430370D2B270BC42707047FF +:10A8A8003F231E4680290CD9B1F5FC7F0BD81B012C +:10A8B800DCE7FF21FE230A4603708170427070BCFA +:10A8C8007047DB00D2E7B1F57C7F04D9B1F5FC6FA6 +:10A8D80003D89B01CAE75B01C8E7B1F57C6F94BF59 +:10A8E800DB01C3EB0323C1E7202902D880232026FC +:10A8F800BCE720231E46D5E77F28A2EB010230B42F +:10A9080005D8002A44D00870481C30BC7047B0F500 +:10A91800006F0FD2012A3DD9840900F03F030A468F +:10A9280064F03F0063F07F0302F8020B10464B709F +:10A9380030BC7047B0F5803F12D2022A2AD9040BE6 +:10A94800C0F3851200F03F03C81C64F01F0462F0D6 +:10A958007F0263F07F030C704A708B7030BC7047C5 +:10A96800032A17D9850CC0F30534C0F3851200F00B +:10A978003F0065F00F0564F07F0460F07F0362F02C +:10A988007F020D70081D4C708A70CB7030BC704708 +:10A998001046BAE70020B8E788423BD2034630B4F5 +:10A9A8000478200603D41460581C30BC704704F0A7 +:10A9B800E000C02830D004F0F000E02823D004F0F4 +:10A9C800F800F0281CD104F0070404201844814240 +:10A9D80016D3591C11F8013B03F0C00503F03F03DF +:10A9E800802D43EA84140BD18142F3D1A4F1800174 +:10A9F8000B4B994204D8A4F55843B3F5006F06D21F +:10AA0800002030BC704704F00F040320DEE7146018 +:10AA180030BC70470020704704F01F040220D5E7BF +:10AA28007FFF10007E2808D8A0F16103192B8CBF86 +:10AA380000232023C01A80B2704730B40023352485 +:10AA4800234D04E035F82120824234D80B46E21A1F +:10AA5800012A03EB5201F5D89BB21D4935F8232092 +:10AA6800904218D24B2400231A4D04E035F82120D7 +:10AA7800824222D80B46E21A012A03EB5201F5D88A +:10AA88009BB2144A35F82310814202D102EB8303AA +:10AA9800588830BC704701EB8303821AD9788A4200 +:10AAA800E0DA93F90230012B0CD043B19BB2184481 +:10AAB80030BC80B270470C46C9E70C46DBE74EF263 +:10AAC800A033F4E702F00102801A80B2E1E700BF88 +:10AAD800B00300208402002010B4047F4160022CDF +:10AAE800C26003D05DF8044B02F006B883685DF8D5 +:10AAF800044B184770B440F20125046825611BB364 +:10AB08001E46F1B10D780131013B6566256FAD0731 +:10AB180006D4656F013EEDB212B1157001320468BA +:10AB28006569ED07F2D5002BEBD16EB101680B6FAB +:10AB38009B07FCD44B6FDBB20AB113700132013EA4 +:10AB4800F3E790F83C50DFE770BC7047F0B5304C45 +:10AB5800304BA06C656C0179226CD977297919770B +:10AB680001791977FAB1B2F5004F18D22B6892B271 +:10AB7800D98B0E043BD4DA83D98B89B2D982036886 +:10AB8800D98B09042CD4DA830021DA8B92B2DA82C9 +:10AB9800216402791F4BDA762A79DA76F0BD1E4BEA +:10ABA80013442364F5E7E06C0F25236840F2013E67 +:10ABB80001684FF47C579D6503260D681749DA61D3 +:10ABC8008D42C3F810E05F6184F83D6017D1037FC0 +:10ABD8004260022BC26017D0BDE8F04001F08CBF84 +:10ABE800D98BC2F3080201F47E410A43CBE7D98B23 +:10ABF800C2F3080601F47E413143D983BCE72B46F2 +:10AC08001146BDE8F04018478368BDE8F040184792 +:10AC18006C11002000800E400180FFFF998B00001E +:10AC28004368F0B593E88200DFF8FCE1B8260A68CB +:10AC38000225754C22EA0702744F0A60DEF81820D4 +:10AC48001440734A27430F24CEF81870077C1F441A +:10AC58003F7C02EB0717BF683E60477C1F4497F8AC +:10AC6800247002EB0717BF683E60877C1F4497F883 +:10AC7800387002EB0717BF683E600F685E683E4396 +:10AC88000E60017C5E1803EB8101367C4F6902EB94 +:10AC9800061149680F60417C5E180A3196F82460F5 +:10ACA80053F8217002EB061149680F60817CD3F8D4 +:10ACB80048E05E1803EB81011F6A96F83860C96B9B +:10ACC80002EB06125E6B52681160817C02681944BF +:10ACD80091F84410CEF80010017C1944097F3960BE +:10ACE800417C0B4493F83030336015619465C37C24 +:10ACF800002B29D072B6C37CDC0706D5454A4369C8 +:10AD080011680B4083621360C37C990706D5424AD9 +:10AD1800836911680B40C3621360C37C5A0706D568 +:10AD28003E4AC36911680B4003631360C37C1F0765 +:10AD380006D53B4A036A11680B4043631360C37C22 +:10AD4800DE064BD462B60268364D8368AB424CD0FF +:10AD5800354B85609B69354CC3F30116C3F382619B +:10AD6800334B54F826400131B4FBF1F1A3FB014306 +:10AD78001B0D29D1C3600026032507240121166174 +:10AD88005562136414661161C37CE3B1DD0703D512 +:10AD9800284B826A1A60C37C9C0703D5264BC26A7B +:10ADA8001A60C37C590703D5244B026B1A60C37C15 +:10ADB8001A0703D5224B426B1A60C37CDB0602D507 +:10ADC800826B204B1A60F0BDB1FBF3F1A94288BF3A +:10ADD8000133B3F5817F0AD31B4BCBE71B4A436A88 +:10ADE80011680B4083631360ACE7C368C3E7022BA9 +:10ADF80098BF0023BED9023B5C08210443EA042320 +:10AE080001F47F010B43B5E7CFFFFFE31000000813 +:10AE18004C07002080E100E084E100E088E100E0E8 +:10AE28008CE100E000093D0000C00F403807002019 +:10AE380083DE1B4300E100E004E100E008E100E0FC +:10AE48000CE100E010E100E0FF7F7F0090E100E00E +:10AE58000BB1FFF74FBE7047436893E806000968D7 +:10AE6800114200D1704710B5026804460020052140 +:10AE78001061227C1344187C00F06EFC6268637CCD +:10AE88000521134493F8240000F066FC6268A37C53 +:10AE980005211344BDE8104093F8380000F05CBC6D +:10AEA800624B634AA3FB003C624B4FEA1C4C2DE902 +:10AEB800F04FA3FB00480CF1040E5F4EA2FB0042CA +:10AEC8004FEA5818DFF87C91AEFB0667D20AA3FB5D +:10AED80008430025C7EB0E04A9FB02965B09DFF8BF +:10AEE8005C9107EB54044FF0640B36094FF4C87AB1 +:10AEF800A408C3EB0313C4EBC40406EB4606C4EB77 +:10AF08000E04C8EB0817A2EBC6062A46A8EB830373 +:10AF18000134A0EB87008E704B700870CC70EFB2D4 +:10AF280040F26D1407F2B27389FB030E13F00308A5 +:10AF38004FEAE370C0EB6E160DD1C0EBEE100BFBC1 +:10AF480016364FF4B7740AFB103026B9002840F2C1 +:10AF58006D1018BF0446224401359445DFD28F7125 +:10AF6800B8F1000F0CD13548DE17642580FB03408B +:10AF7800C6EB601405FB1434C4B34FF4B77402E095 +:10AF880040F26D14DE172D48121B64254FF4C87467 +:10AF980080FB0370C2EB0C0C0022C6EB6017C6EBFB +:10AFA800E016012005FB1737254D04FB163602E095 +:10AFB80001300132C0B2012AD4B224D0535D6345B6 +:10AFC8000BD80C28C3EB0C0CF2D10D240CF1010C9E +:10AFD8004C7181F804C0BDE8F08F01340CF1010C0C +:10AFE800E4B281F804C04C71BDE8F08FC6EBE01004 +:10AFF8004FF4C87540F26D1405FB1030002808BFE7 +:10B008004FF4B774BFE7B8F1000F09D167B9002E44 +:10B0180014BF1C231D239C4504D3C3EB0C0CC7E7AA +:10B028001C23F8E70224D1E71D23F4E707452EC2C5 +:10B03800C5B3A29189888888254992241F85EB5138 +:10B0480084040020ABAAAAAA10B503490446FFF756 +:10B0580027FF024B1C6010BD482100207C210020E6 +:10B06800F8B51B4C1B4D23682A681B4F9B1A386880 +:10B07800B3F57A7F0CD3013000E0084602F57A7206 +:10B088002368411C9B1AB3F57A7FF6D238602A6090 +:10B09800124E336898420FD3114B1B6863B198471F +:10B0A800104B50B910491A680B78386800330244BD +:10B0B80018BF012332600B70F8BD1B680221246899 +:10B0C800094A034438602C6033601170F8BD00BF32 +:10B0D800F02700203C210020782100204421002076 +:10B0E80090260020CC1100200628002008B5FFF784 +:10B0F800B7FF044B1B68984201D0FFF7A5FF024B2E +:10B10800987808BD7C2100204821002008B5FFF769 +:10B11800A7FF044B1B68984201D0FFF795FF024B2D +:10B12800587808BD7C2100204821002008B5FFF789 +:10B1380097FF044B1B68984201D0FFF785FF024B2D +:10B14800187808BD7C2100204821002008B5FFF7A9 +:10B1580087FF044B1B68984201D0FFF775FF024B2D +:10B16800187908BD7C2100204821002008B5FFF788 +:10B1780077FF044B1B68984201D0FFF765FF024B2D +:10B18800587908BD7C2100204821002008B5FFF728 +:10B1980067FF054B1B68984201D0FFF755FF034B2B +:10B1A800987900F2B27008BD7C2100204821002067 +:10B1B800844641EA000313F003036DD1403A41D3BA +:10B1C80051F8043B40F8043B51F8043B40F8043B79 +:10B1D80051F8043B40F8043B51F8043B40F8043B69 +:10B1E80051F8043B40F8043B51F8043B40F8043B59 +:10B1F80051F8043B40F8043B51F8043B40F8043B49 +:10B2080051F8043B40F8043B51F8043B40F8043B38 +:10B2180051F8043B40F8043B51F8043B40F8043B28 +:10B2280051F8043B40F8043B51F8043B40F8043B18 +:10B2380051F8043B40F8043B51F8043B40F8043B08 +:10B24800403ABDD2303211D351F8043B40F8043BA8 +:10B2580051F8043B40F8043B51F8043B40F8043BE8 +:10B2680051F8043B40F8043B103AEDD20C3205D3B8 +:10B2780051F8043B40F8043B043AF9D2043208D0B0 +:10B28800D2071CBF11F8013B00F8013B01D30B8822 +:10B2980003806046704700BF082A13D38B078DD000 +:10B2A80010F003038AD0C3F10403D21ADB071CBFD2 +:10B2B80011F8013B00F8013B80D331F8023B20F83C +:10B2C800023B7BE7043AD9D3013A11F8013B00F875 +:10B2D800013BF9D20B7803704B7843708B788370FD +:10B2E80060467047964A974B90422DE9F043964C3A +:10B2F800D3F814E09969E6681CD9944B984240F257 +:10B308001581934B40F22765924F0344924C1A0AD9 +:10B31800A7FB0232D30903EB830303EB830202F298 +:10B32800E243AB4228BF2B46A3F54873A4FB033581 +:10B33800ED0804E0894DA84294BF06250E25814AF0 +:10B3480006F01F07D2F88030AF4243F0C003C2F8BE +:10B3580080300AD27C4B26F01F061A462E43DE6048 +:10B368001368002BFCDA06F01F071EF0007331D1BA +:10B378007B4C7C4AD4F810C014460CEA0202A24264 +:10B388000ABF4FF0C0534FF4805200228EEA0304E4 +:10B3980014F0605F08D02EF0605E03F06053694CD3 +:10B3A80043EA0E0EC4F814E081EA020313F4405F86 +:10B3B80008D0644B21F4405111431A469961936CAB +:10B3C8001C07FCD44EF0007E5E4AC2F814E0936C71 +:10B3D8009906FCD40121644C0A4601FB02F300FBE8 +:10B3E80003F3A34209D8072A00F29580013201FB32 +:10B3F80002F300FB03F3A342F5D95C485C4C184404 +:10B40800A4FB00031B0D6C2B00F28B80352B00F284 +:10B418008F80DFF8888136235648DFF844C1564CC0 +:10B42800DCF80090B0FBF2F009EA04044445B0FBF4 +:10B43800F1F00BD043F400534FF480586446CCF835 +:10B448000080CCF800302368002BFCDADFF8F4C069 +:10B45800013ADCF8103003F00703934207D002F0FA +:10B4680007026446CCF81020A36CDB03FCD4013936 +:10B4780089028EEA010313F4E05F0CD0314B2EF4FD +:10B48800E05E01F4E0511A4641EA0E0EC3F814E0FA +:10B49800936C9907FCD4394B39490344DB09A1FB68 +:10B4A8000331090B042928BF04214B1E1B028EEA15 +:10B4B800030212F4407F07D02EF4407E03F4407359 +:10B4C800204A43EA0E0353611E4B5C691A4624F076 +:10B4D80000745C61936C9B06FCD42A4B4FF0FF32DE +:10B4E800294CBD42A3FB00E320604FEA9343274C5D +:10B4F800B2FBF3F3B0FBF1F1254A2160136008D2E7 +:10B50800114B26F01F061A462E43DE601368002BE7 +:10B51800FCDABDE8F08304293FF66FAF0131012260 +:10B528005BE7DFF87C806C231A4876E7122506E78C +:10B538001948DFF8708000FB03F043EA08086CE75D +:10B5480000A4781F00C00F40000008400046C32335 +:10B5580000BA3CDC23B24C001F85EB5100366E016B +:10B5680000800D4040300080FFB19F26808D5B0039 +:10B57800819F5E1600B29F267F3001807FD1F00840 +:10B588009F10E50083DE1B43681100206411002032 +:10B59800E427002000643F4D001BB70036200080E0 +:10B5A8006C20008000200080002857D001222DE95F +:10B5B800F04F85B083462A4C2A4D2B4EDDE902898F +:10B5C80054E8003F2868336844E800210029F7D18F +:10B5D800264FCDE902893A68D31A254A4FF47A7E74 +:10B5E800019712680127A3FB02234FF47A72984649 +:10B5F80000238B4208BF42452CBFC246F2460EFBD1 +:10B6080000AA54E8003F2A68316844E80073002B18 +:10B61800F7D101980068411A15484FF47A7E0068FE +:10B628000EFB02F2A1FB00014FF47A70CAEB020292 +:10B6380088460021994208BF40452CBF43467346BF +:10B648001A44724507D3BBF1010B0AF57A7AD8D1AF +:10B6580005B0BDE8F08F01F0D5FBD2E7704700BF19 +:10B6680060280020F0270020EC270020041000E0CC +:10B67800E42700202DE9F003124A0126124D134C4D +:10B6880052E8003F2968206842E80063002BF7D1A0 +:10B698000F4A16680F4F321A4FF000094FF47A78A4 +:10B6A8003E684FF47A709945A2FB066708BFB84513 +:10B6B8003C462CBF3C46044600FB0140BDE8F00375 +:10B6C800704700BF60280020F0270020EC270020EA +:10B6D800041000E0E427002000010F4B1A181B5843 +:10B6E80010B4D0685C68044205D059B1C3F884002E +:10B6F8005DF8044B7047936849B9084A5DF8044BF4 +:10B708001A607047C3F888005DF8044B7047044A14 +:10B718005DF8044B1A6070474C0700203830010070 +:10B7280038F001000001054B1A5819189268CB68C7 +:10B738001A4214BF01200020704700BF4C070020A8 +:10B74800362801D8FFF7C8BF704700BF362801D890 +:10B75800FFF7E8BF0020704736281CD800011A4AB6 +:10B76800012902EB0003105810B415D0042913D096 +:10B77800DC68426822EA040242609A68E9B1022958 +:10B788001ED003295B685DF8044B0CBF0F491049B4 +:10B79800116015221A607047DA680129446842EA84 +:10B7A800040242609A6808D040F6380111605B686C +:10B7B80015225DF8044B1A60704738211160F6E7CE +:10B7C80004491160F3E700BF4C070020383001003E +:10B7D8003800010038F001000A4B30B4586A1C46A2 +:10B7E800996A626AA36A994208BF9042104619464C +:10B7F8000CBF01250025002DF3D0D90B30BC41EA40 +:10B808004240704700400D4072B6EFF30583494D42 +:10B818006B60EFF30883484C2E4648484849494A2C +:10B8280024680068096812682961AC60E8606A6188 +:10B838009A69454CAA61DB69444FEB6100F0C8F88E +:10B8480085ED080AFFF7C8FF0B234FF0FF32686247 +:10B8580019462B604A40202102F00103013904FBFC +:10B8680003F383EA5202F7D1BE4202D056F8041F0E +:10B87800F0E730498A62BFF34F8F354B354A19607C +:10B888001A60BFF34F8FBFF36F8F334A0225334CD3 +:10B89800D36E334943F440533248D3662560D369A5 +:10B8A80023F07F0343F04003D3610B6883423ED803 +:10B8B8002A4A002101202C4E11604FF0FF33C2F8B4 +:10B8C80008110C46C2F800611546C2F8080107467F +:10B8D800DFF8C0E0254E26482649274ACEF8003032 +:10B8E800336003600B60136001E000F055F9D5F890 +:10B8F8000C211A4B002AF8D00134C5F80C714F2CD2 +:10B90800F3D91E4A02241E484FF00041C0F84041B6 +:10B918005163D3F80C2132B91A491B4A0A63D3F888 +:10B928000C010028FAD0194B194A1A60FEE7FFF7F4 +:10B93800D9FCBDE780FF272028ED00E02CED00E0D2 +:10B9480034ED00E038ED00E02083B8EDA4FF2720B7 +:10B9580070EF00E0A0FF272000C00F400040084023 +:10B9680068110020803DCD0B009F240084E100E099 +:10B9780088E100E08CE100E090E100E000900D40FB +:10B9880000002E4000800F40F100AD0B0CED00E0F0 +:10B998000400FA0580E100E0094A08B5136820B1FF +:10B9A80018440849884202D81060184608BD01F0BA +:10B9B800A3FC0C224FF0FF330260184608BD00BFFD +:10B9C800D01100200000282030BFFDE7FFF71CBF82 +:10B9D80012490B68114A5B07FBD513681049C3F37A +:10B9E8000B23104A07EE903A0B6892ED006AB8EE06 +:10B9F800E77A07EE903A0C4AF8EE677A0B4BD2EDED +:10BA0800006A77EE677A93ED007AB8EE477A67EEC8 +:10BA1800867A87EEA60A37EE400A704780810D4085 +:10BA2800D4270020DC270020E0270020D82700208A +:10BA3800836BF0B41BB1536843F40043536072B690 +:10BA4800446B5CB31C4B2260D3F8B0410C4215D157 +:10BA58001A4E376804E03468E41BB4F5166F0BD24D +:10BA6800D3F8404144F48044C3F84041D3F8B85176 +:10BA7800D3F840416404EED50D4003D0426362B66A +:10BA8800F0BC70470C4C8260C560D4F8B0311943E3 +:10BA9800C4F8B011426362B6F0BC7047064D8260CC +:10BAA800C460D5F8B0311943C5F8B01102634263D8 +:10BAB80062B6F0BC704700BF00002E40041000E0E2 +:10BAC80070B50646006B90B10246002403E0126888 +:10BAD8000134012A0CD0536813F08003F7D0326385 +:10BAE8002CB1B36B05689847013C2846F9D170BD65 +:10BAF80033637363F4E700BFF0B5E1B9214C224921 +:10BB08000020224B01224FF0011580260A601A46B8 +:10BB1800A1604E60E060C3F8BC51D3F8B0411C4D41 +:10BB280044F001048860C3F8B0412860D2F8B0310D +:10BB3800002BFBD1F0BD0904164B144D0126114C06 +:10BB480041F0800100221E60596000F5805CE264CB +:10BB580000F5005EA36400F54057D5F8B01100F574 +:10BB680080462A46986041F48031C3F80CC0C3F877 +:10BB780010E05F619E61C5F8B011D2F8B031002BBA +:10BB8800FBD1BCE7000000204028002000002E4028 +:10BB980088260020202800202DE9F04FB94C83B0DA +:10BBA800D4F8448118F0010FC4F844815ED0D4F869 +:10BBB800AC31002B55D04FF0011BDFF8EC92B24EA0 +:10BBC8002546DA46C4F8AC31B06AF26AD4F8403196 +:10BBD80043F40053C4F84031D4F840319F04F5D5FC +:10BBE800D5F8403123F40053C5F84031C5F8B4A165 +:10BBF800D4F8B43113F00113FAD181B240F281675D +:10BC0800C9F80030B94200F2AD80B1F5D06F80F0CC +:10BC1800DE81B1F5817F00F0608100F2E880802943 +:10BC280000F04E81822940F0DA8092B202F07F0162 +:10BC3800072900F2D48089009448954F0844016888 +:10BC480010063B707B7040F10182CA0301D50123C5 +:10BC58003B7002218E48FFF74FFFD4F8AC31002B20 +:10BC6800B0D1884AD2F8BC31002B49D118F0400F26 +:10BC780018D0844BD3F8AC111A46C3F8AC11D3F8DA +:10BC8800BC11C3F8BC11D2F8B0417E4B002CFAD1DC +:10BC98004FF0FF32C3F8B421D3F8843100F01EFD11 +:10BCA8007C4B1C6018F0807F03D07B4B1B6803B172 +:10BCB800984718F0007F03D0784B1B6803B198476A +:10BCC80018F0040F08D06F4BD3F8843113F40073C5 +:10BCD80045D0734B01221A706A4BD3F848211206DB +:10BCE8000BD518F0800F08D06E490A782AB1013AAE +:10BCF800D2B20A70002A00F0428203B0BDE8F08F89 +:10BD08006949C2F8BC310868034240F0E281614ADF +:10BD180015681D40AAD02F0C0FD05B4E4FF00109BB +:10BD280097FAA7F4B4FA84F406EBC41009FA04F4F9 +:10BD38004030FFF7C5FEA743F2D1ADB2002D95D034 +:10BD4800514E012795FAA5F4B4FA84F406EBC41011 +:10BD580007FA04F4FFF7B4FEA543F3D186E7504A87 +:10BD68001370B9E742F22107B94234D067D8B1F568 +:10BD7800086F00F01E81B1F5106F30D1C0F3074095 +:10BD88004A4A4B4910704B4F4B4A0193C5F8C8714A +:10BD9800C5F8CC11C5F8D02100F0A2FC474A019B98 +:10BDA80080210120B26451601060F364C5F8BCB111 +:10BDB800D5F8B011936041F48032C5F8B0213A4A01 +:10BDC8001360D4F8B031002BFBD1D4F8AC31002B80 +:10BDD8007FF4F8AE45E7110C072900F03B81C4F861 +:10BDE800C0B1D4F8AC31002B7FF4ECAE39E740F2A7 +:10BDF8000237B94200F0AD80B1F5A06FEFD12F4AFC +:10BE080080210127F364B26417605160C5F8BCB1A2 +:10BE1800D5F8B011936041F48033C5F8B031D4F847 +:10BE2800B031002BFBD1030C5B0643F08073C5F8DF +:10BE38005431D4F8AC31002B7FF4C4AE11E742F290 +:10BE48002123994279D042F221339942C7D11B4B21 +:10BE5800802200210120B36418605A60F164C4F89C +:10BE6800BCB1D4F8B021996042F48033C4F8B03141 +:10BE7800D4F8B031002BFBD1D4F8AC31002B7FF4CF +:10BE8800A1AEEEE600002E4000000020C0012E40CA +:10BE9800982700208C260020F4270020F82700206F +:10BEA80016280020172800208826002015280020A2 +:10BEB800C80002000200CC000200C8004028002090 +:10BEC800B64A0221104613705370FFF715FED4F8D6 +:10BED800AC31002B7FF476AEC3E692B202F07F035A +:10BEE800072B3FF67CAF12F0800F4FEA8303AC4A72 +:10BEF8004FF000014FF001001A44136814BF23F4F7 +:10BF0800803323F0010313608022A64BF164B364ED +:10BF180018605A60C4F8BCB1D4F8B021996042F4F2 +:10BF28008033C4F8B031D4F8B031002BFBD1D4F849 +:10BF3800AC31002B7FF446AE93E692B2002A86D14C +:10BF4800994BC0F30740994A1968994B11601870CA +:10BF58007DE792B202F07F03072B3FF640AF12F065 +:10BF6800800F4FEA83038E4A4FF000014FF0010023 +:10BF78001A44136814BF43F4803343F00103136079 +:10BF88008022884BF164B36418605A60C4F8BCB16D +:10BF9800D4F8B021996042F48033C4F8B031D4F8B1 +:10BFA800B031002BFBD1D4F8AC31002B7FF40AAEB2 +:10BFB80057E6804A0121794B127818461A70FFF724 +:10BFC8009BFDD4F8AC31002B7FF4FCAD49E67A4BED +:10BFD800596800293FF403AF000C1FFA82FE04E001 +:10BFE8000C33596800293FF4FAAE1F888742F7D10D +:10BFF8005F887745F4D1070A032F00F0BA801B89C0 +:10C00800120C934228BF1346B0F5007F00F0A280BF +:10C01800B0F5E06F00F08B80684F1A460193384600 +:10C02800FFF7C6F8019B27F01F021F44BFF34F8F8D +:10C0380063490A6020329742FAD8BFF34F8FBFF3A3 +:10C048006F8F5E481946FFF757FD06E6CB077FF569 +:10C0580000AEFCE55B4F4FF0010EF3605A495B4BB5 +:10C068003860C3F800E05960B3605949D5F8B001A9 +:10C078007A6001F5805740EA0E02996001F5005E8A +:10C0880001F5405001F58041C5F8B021DF60C3F8E3 +:10C0980010E058619961D4F8B031002BFBD1414AC6 +:10C0A800012048F28001F36410604FF48030B264DC +:10C0B8005160C5F8BCB1D5F8B011936041EA0003EE +:10C0C800C5F8B031C9F80000D4F8B031002BFBD165 +:10C0D800C3E53C4842F22104002605880E60A542CB +:10C0E80040687FF414AE81B200297FF410AE38495D +:10C0F800384C03C90D0C86282060A180A5717FF4F7 +:10C1080006AE72B63448017841F004010170D2F8E5 +:10C118004811080606D441F080018020C2F8440185 +:10C12800C2F8481162B62D4A50211170EFE52C482B +:10C138001A46224F90F800E02A492B480193BEF195 +:10C14800000F08BF01463846FFF732F80722019B67 +:10C158007A7068E722481A462349077821480193EC +:10C16800002F08BF01461548FFF722F8134F019B1F +:10C1780059E7120C0B78934228BF134648E7164933 +:10C188000A7802F0FB020A702AB9D3F8482122F093 +:10C198008002C3F8482101F09BFE00BF98270020C9 +:10C1A800C0012E4040280020F02700207C280020D5 +:10C1B8001428002015280020C80C0020000020208A +:10C1C80070EF00E0401C00208000070020280020BD +:10C1D800802600207428002010280020172800201E +:10C1E80016280020A41E0060F01E0060002AA0F19E +:10C1F80002022DE9F04714BF00274FF00057022A2A +:10C2080001D9BDE8F0874FEAC019DFF840A00D4614 +:10C2180004460AEB0906002140229846304601F000 +:10C2280093FB012047EA05414AF80910C6F838800F +:10C23800B060B8F1000FE4D0034BA0401C68204365 +:10C248001860BDE8F08700BF8C26002000000020A1 +:10C25800002AA0F102022DE9F04714BF00274FF091 +:10C268000057022A01D9BDE8F0874022C501DFF84E +:10C27800449088461544002104461E4609EB050AE9 +:10C28800504601F061FB012247EA084149F80510D0 +:10C29800CAF83860CAF80820002EE4D004F110006B +:10C2A800034B8240186802431A60BDE8F08700BF5C +:10C2B8008C2600200000002012048160C36142F037 +:10C2C8008002F0B44260012701F5805601F500555F +:10C2D80001F5405401F580420760C660056144617C +:10C2E8008261F0BC704700BF831E022B00D97047E3 +:10C2F800064B0A4630B400F11004012503EBC010C8 +:10C3080005FA04F1403030BCFFF792BB0000002072 +:10C31800831E022B00D9704710B4054B01240A462E +:10C3280004FA00F103EBC0105DF8044BFFF780BB83 +:10C338000000002040687047124A134BD2F82002D0 +:10C3480020F07F40984210B584B002D800EB8000FE +:10C3580040000E4C01A90A2200F0CCFD01A90023DF +:10C36800204611F8012B01333AB10A2B20F8022F8D +:10C37800F7D11623237004B010BD5B00DBB2237025 +:10C3880004B010BD00441F407F969800001600209E +:10C39800F8B514494FF40037134D034601EB402418 +:10C3A800124E134A05EB401521461760284632887D +:10C3B800FFF782FF318824F01F032144BFF34F8F1A +:10C3C8000C4A136020339942FBD8BFF34F8FBFF359 +:10C3D8006F8F03202946FFF79BFF074B4FF400326E +:10C3E8001A60F8BD60002020C01A0020FC27002039 +:10C3F8008CE100E05CEF00E00CE100E0244A4368D7 +:10C408002DE9F041C3F30E431488C569E41A002CE2 +:10C4180038DD2049204A0B781278DBB21F48204EBD +:10C42800934207D010F8038036F81870C7F50072E9 +:10C43800944212D9013300221A4F082B26F81540CE +:10C4480027F81520184E94BFDAB213460A703268DE +:10C45800C55414443460BDE8F081144B07EB482000 +:10C468002246274403EB45211844FEF7A1FE0E4A55 +:10C47800284626F8187013681C441460BDE8F0417B +:10C48800FFF786BF2846BDE8F041FFF781BF00BF30 +:10C49800FC2700200E2800200F280020C827002095 +:10C4A800A8270020B8270020A4270020600020200B +:10C4B8001E4B1A785AB902F0FF031D4A127832B19E +:10C4C8002DE9F0411B4D2A8812B9BDE8F08170476B +:10C4D800194EC2F50068194F31784246184C07EBDF +:10C4E800411704EBC12438462146FFF7E5FE08EB67 +:10C4F800040224F01F01BFF34F8F124B1960203143 +:10C508008A42FBD8BFF34F8FBFF36F8F04203946A1 +:10C51800FFF7EAFE3378084A0133DBB2032B88BF02 +:10C528000023137000232B80BDE8F081132800201E +:10C5380015280020FE27002012280020C01B0020FC +:10C548006010202070EF00E02DE9F04F85B00290D8 +:10C558000091002900F0AB800023564DDFF874816C +:10C56800DFF860A1544FDFF870B101930122534BFB +:10C578002A701C78524AB8F8003002EB441923BBE1 +:10C588001E461C464846FFF7D5FE10F080007ED0B8 +:10C59800BFF34F8F00229AF800304A492A7004B935 +:10C5A8003E68002B5AD13B689B1B782B79D89BF8A7 +:10C5B8000030002B52D000F025FC0124B8F80030E0 +:10C5C8002C70002BDED03D4A14781A46C3F5006063 +:10C5D800E402009E3C4920449642084442D30C445D +:10C5E8000299FEF7E5FD002321464FF40062484614 +:10C5F800FFF762FE24F01F0304F50064BFF34F8FBA +:10C60800324A136020339C42FAD8BFF34F8FBFF3EE +:10C618006F8F04204946FFF767FE284B274A1B788F +:10C62800009801332A49DBB2032B88BF002313701B +:10C638000022B8F80030A8F80020C01A009001982D +:10C6480018440190029818440290C1F88420BFF35E +:10C658004F8F00232B70009B002B87D1019805B0CA +:10C66800BDE8F08F009C0393019B22460299234466 +:10C678000193FEF79DFD039B4FF04041144A0020B3 +:10C688001B1B0090A8F80030C2F88410DFE74FF4B5 +:10C6980000630A4A8AF8000014781A46A8F800309D +:10C6A80096E7012301980B7005B0BDE8F08F00985C +:10C6B800D5E700BF13280020F0270020122800200B +:10C6C800C01B0020112800206010202070EF00E01F +:10C6D80000002E40FE27002015280020704700BFCC +:10C6E800314B2DE9F0411B78304F002B54D04FF4DB +:10C6F8000073DFF8EC803B80A8F80030002180222E +:10C708002B480D462B4E01F01FF92B4C2B4B29467D +:10C718004FF480722A4825702C461D8001F014F9C8 +:10C7280035602B4675602A46B560F5602549264E6A +:10C738002648DFF8B0E00D70102105700220356042 +:10C748007560B560F560CEF80050FFF781FDB8F868 +:10C7580000102A461E4B0320FFF748FD2B46398858 +:10C7680001220420FFF774FD20460134FFF710FE74 +:10C77800082CF9D1174B4A2217480021174C04609E +:10C78800C3F88410C3F88020D3F8482142F080729F +:10C79800C3F84821BDE8F0814023DFF844803B809E +:10C7A800A8F80030AAE700BF1628002000280020BB +:10C7B800C01B0020A827002012280020FE270020E8 +:10C7C800C01A00200E280020B82700200F280020BB +:10C7D800BDA4000000002E40F427002071A5000031 +:10C7E800FC270020A4270020314B4FF400322DE90C +:10C7F800F04F1A6083B02F4B89461C78002953D01C +:10C808002D4BE4B21B789C4250D082460027DFF8BB +:10C81800C0B00134294BC7EB09085046092C0193D5 +:10C82800274B28BF00241D5D244B33F815E0254B0A +:10C838000EEB452133F81560234BCEEB0606194461 +:10C84800B0453246374419D20EEB452142461944C9 +:10C85800FEF7AEFC019BDBF80010484633F81520C4 +:10C86800C8EB01019044CBF8001023F81580174B52 +:10C878004FF400321A6003B0BDE8F08FFEF798FC61 +:10C88800DBF80020E3B22846921BB244CBF8002024 +:10C89800084A1370FFF77CFDB94503D9064B1B788E +:10C8A8009C42B6D13846E2E70846E0E70020DEE7DA +:10C8B8008CE100E00F2800200E280020B827002077 +:10C8C800C8270020A8270020600020200CE100E0F5 +:10C8D800A42700200B4B0C4A1B781278DBB293423A +:10C8E8000DD0013309480A4A092B0A4928BF0023F9 +:10C8F800C35C31F8131002EB4323585C70474FF0C8 +:10C90800FF3070470F2800200E280020C82700207D +:10C9180060002020B8270020034B10B51C680CB914 +:10C9280000F070FA204610BDA42700202DE9F84F2A +:10C93800154E164D34782B78E4B29C4221D0DFF89E +:10C948005490DFF854B0DFF85480114F0134082CAC +:10C958005FFA84FA01D90024A24619F80410DBF81A +:10C96800002038F81130084637F811105B1AD31A2E +:10C97800CBF80030FFF70CFD86F800A02B789C421E +:10C98800E4D1BDE8F88F00BF0F2800200E28002052 +:10C99800B8270020C8270020A4270020A8270020A7 +:10C9A80000B583B001210DF10700FFF71DFF20B18D +:10C9B8009DF8070003B05DF804FB4FF0FF30F9E77E +:10C9C800094B00B583B01B788DF8070023B903F035 +:10C9D800FF0003B05DF804FB01210DF10700FFF72C +:10C9E800B3FD03B05DF804FB15280020044B1B7849 +:10C9F80003F0FF020BB1FFF7A7BD1046704700BF59 +:10CA0800152800202DE9F0410024DFF84480012397 +:10CA18000D4D27460D4E88F80030337828462035CE +:10CA2800A34204F1010405D0FFF784FC030658BFB4 +:10CA380007F50067042CF0D1BFF34F8F0023384669 +:10CA480088F80030BDE8F081C01B002012280020C3 +:10CA5800132800202DE9F843204B1B7813B1204DF3 +:10CA68002A880AB9BDE8F883DFF88880C2F500692A +:10CA78001C4E4FF0010E98F800104A461A4C00233D +:10CA880006EB4116194F04EBC124304687F800E045 +:10CA98002146FFF711FC09EB040224F01F01BFF344 +:10CAA8004F8F134B196020318A42FBD8BFF34F8F49 +:10CAB800BFF36F8F04203146FFF716FC98F800305B +:10CAC8000C4A0133DBB2032B88BF00231370002309 +:10CAD8002B80BFF34F8F3B70BDE8F88315280020EB +:10CAE800FE270020C01B00206010202013280020F3 +:10CAF80070EF00E01228002010B4EFF3108272B635 +:10CB0800437F33B9017F012908D0032910D00123BD +:10CB1800437702B962B65DF8044B7047114C21683F +:10CB2800A1B1114943610B68086083615861EEE760 +:10CB38000E4C216881B10E4943610B68086083611E +:10CB480058610C4B4FF080511960E0E7064B41618A +:10CB5800816120601860DAE7054B416181612060DE +:10CB68001860EEE794210020A02100209C210020DD +:10CB78009821002004ED00E070B5EFF3108172B643 +:10CB88000C4C23688BB10C4E00255A6922607AB18F +:10CB9800956101B962B65D7718469B689847EFF3CF +:10CBA800108172B62368002BEFD101B962B670BD4F +:10CBB8003260EEE79C21002098210020FFF7DCBFBF +:10CBC800044A054B1168054A19601368013313605C +:10CBD800704700BF041000E0EC270020F027002079 +:10CBE800F8B50E4671B17AB10746144600253B6880 +:10CBF800384616F8011B1B689847013C0544F6D1D6 +:10CC08002846F8BD0846F8BD1046F8BD10B5064CD4 +:10CC180082B003680222248801A95B68ADF8044049 +:10CC2800984702B010BD00BF800200205E4A5F4BEB +:10CC3800A2FB002C5E4A2DE9F04F4FEA1C4CA3FBE7 +:10CC48000074A2FB00725B4E64090CF1040ED20A58 +:10CC5800DFF86C81A3FB04730025AEFB06674FF079 +:10CC6800640BA8FB02865B09C7EB0E084FF4C87A71 +:10CC78003609DFF8449107EB5807C3EB0313BF08E5 +:10CC8800A4EB830306EB4606C7EBC7074B70C4EB60 +:10CC98000414A2EBC606C7EB0E0EA0EB84002A46CE +:10CCA8008E70087081F803E0EFB240F26D1407F25D +:10CCB800B27389FB030E13F003084FEAE370C0EB6D +:10CCC8006E160DD1C0EBEE100BFB16364FF4B77491 +:10CCD8000AFB103026B9002840F26D1018BF044630 +:10CCE800224401359445DFD246378F71B8F1000FE1 +:10CCF8000CD13148DE17642580FB0340C6EB601475 +:10CD080005FB14347CB34FF4B77402E040F26D14A1 +:10CD1800DE172948121B64254FF4C87480FB037082 +:10CD2800C2EB0C0C0022C6EB6017C6EBE016012024 +:10CD380005FB1737214D04FB163602E0013001329E +:10CD4800C0B2012AD4B21BD0535D634504D80C2865 +:10CD5800C3EB0C0CF2D104460CF1010C4C7181F8B8 +:10CD680004C0BDE8F08FC6EBE0104FF4C87540F280 +:10CD78006D1405FB1030002808BF4FF4B774C8E7DE +:10CD8800B8F1000F09D167B9002E14BF1C231D2369 +:10CD98009C4504D3C3EB0C0CD0E71C23F8E7012413 +:10CDA800DAE71D23F4E700BF07452EC28988888883 +:10CDB800C5B3A291254992241F85EB519004002008 +:10CDC800ABAAAAAA08B5F6F7EDFCF6F7C3FD00F082 +:10CDD80019F8FAE700F0BEBA00F0C4BAFFF7A6BD2A +:10CDE800FFF778BDFFF7DCBDFFF796BDFFF732BE52 +:10CDF800FFF708BE08461146FFF7F8BD0846FFF7DB +:10CE0800DFBD00BF2DE9F843324E337893B1324F7E +:10CE18003A787AB90122D9073A7037D49A0719D4DF +:10CE280000225B073A7005D52C4B1A6812B1EFF354 +:10CE380005820AB1BDE8F883EFF3108072B61A686C +:10CE48001AB1274C217800292FD00028F2D162B6D8 +:10CE5800BDE8F883DFF8948098F80020002ADFD036 +:10CE68000024DFF88C9005E0013498F80030E4B233 +:10CE7800A34213D959F824502B6828461B699847B0 +:10CE88000028F1D06B699B689847EDE7FFF744FDF0 +:10CE9800D0B9144B1B781BB93378BFE73378BFE799 +:10CEA800337803F0FE033370B8E70126556926701E +:10CEB8001D6065B1A96100B962B600259368104686 +:10CEC800557798472570B5E700F008FAE1E7064B73 +:10CED8001D60F0E7171600200A2800209421002082 +:10CEE80008280020461F0060A021002009280020F3 +:10CEF800A4210020F0B44E1E0025374600E001357D +:10CF0800B0FBF2F302FB130000F13704092800F12B +:10CF18003000E4B298BFC4B2184607F8014F002B9E +:10CF2800EDD14A1953704DB1013316F8014F1778F6 +:10CF3800E81A3770834202F80149F5DB0846F0BC6D +:10CF4800704700BFA4484FF00F0CA44B826F42F407 +:10CF58007F02F0B582670025D0F880204FF4704634 +:10CF68009F4C4FF4604E29464FF4806714432A467D +:10CF7800C0F88040A3F88C6148F2B826A3F88EC1A7 +:10CF8800A3F89051B3F8880180B240F0F000A3F8FC +:10CF9800880101EB4100914B0131002540011C46FD +:10CFA80004290344A3F804E0DF805A841A865A80CF +:10CFB8005A81DE815A82DA825A83DA83E9D1B4F857 +:10CFC80088014FF00F0C874B4FF4704680B229460A +:10CFD8004FF460472A4640EA0C004FF4806EA4F8EC +:10CFE8008801B4F8880180B240F47060A4F8880120 +:10CFF800A3F88C6148F2B826A3F88EC1A3F8905123 +:10D00800B3F8880180B240F0F000A3F8880101EB82 +:10D018004100744B0131002540011C46042903449A +:10D028009F80A3F806E05A841A865A805A81DE81C6 +:10D038005A82DA825A83DA83E9D1B4F888014FF048 +:10D048000F0C694B4FF4704680B229464FF4604785 +:10D058002A4640EA0C004FF4806EA4F88801B4F820 +:10D06800880180B240F47060A4F88801A3F88C614C +:10D0780048F2B826A3F88EC1A3F89051B3F88801F6 +:10D0880080B240F0F000A3F8880101EB4100564B54 +:10D098000131002540011C46042903449F80A3F860 +:10D0A80006E05A841A865A805A81DE815A82DA82C8 +:10D0B8005A83DA83E9D1B4F888014FF00F0C4B4B4F +:10D0C8004FF4704780B229464FF460462A4640EA3A +:10D0D8000C004FF4806EA4F88801B4F8880180B27F +:10D0E80040F47060A4F88801A3F88C7148F2B8275E +:10D0F800A3F88EC1A3F89051B3F8880180B240F02C +:10D10800F000A3F8880101EB4100384B01314001E0 +:10D118001C46042903449E80A3F806E05A841A8614 +:10D128005A805A81DF815A82DA825A83DA83EAD1B5 +:10D13800B4F888310F27002241F201069BB245F668 +:10D14800C05E114643F226053B43A4F88831B4F883 +:10D1580088319BB243F47063A4F888315001244BA2 +:10D1680001320344042A99815981DF819E82A3F800 +:10D1780006E0198019829D81F0D100220F2741F223 +:10D18800010645F6C055114643F226045001194BD5 +:10D1980001320344042A99815981DF819E82DD800E +:10D1A800198019829C81F1D100220F2741F20106D2 +:10D1B80045F6C055114643F2260450010E4B013284 +:10D1C8000344042A99815981DF819E82DD80198078 +:10D1D80019829C81F1D1F0BD00C00F4000C03D40D4 +:10D1E800000003FC00003E4000403E4000803E40FE +:10D1F80000C01D4000001E4000401E4008B50368E6 +:10D208004268BBB17AB1104BA3FB0213DB0803EBF6 +:10D218004303B2EB830303D0D21A4260F02A02D947 +:10D228000123184608BD00F067F81C22002302609D +:10D23800184608BD044BA3FB0213DB0803EB4303AA +:10D24800B2EB8303E8D1E9E7ABAAAAAA70B5044612 +:10D2580000283AD019B1B2FA82F56D09FDB12068FB +:10D2680008B1626832B900F047F81623002203605B +:10D27800104670BD1849A1FB0231C90801EB4101F4 +:10D28800B2EB8101EFD1A3680BB100F05DFB002385 +:10D298000122236010466360A360E36070BD1E46F0 +:10D2A800049B80E80600C360FFF7A8FF0246002839 +:10D2B800DED016B90122104670BD94E80500A660BC +:10D2C800294600F041FB0122D2E700F015F81623A9 +:10D2D80022460360CCE700BFABAAAAAA704700BFEA +:10D2E8000B460146184600F001B800BF13460A462F +:10D2F8000146022000F062BC014B1868704700BF6D +:10D30800E415002070B50F4E0F4D761BB61018BFF0 +:10D31800002405D0013455F8043B9847A642F9D1BA +:10D328000A4E0B4D761B00F0D7FDB61018BF00242F +:10D3380006D0013455F8043B9847A642F9D170BD90 +:10D3480070BD00BF681E0060681E0060701E00602F +:10D35800681E0060024B0146186800F00BB800BF59 +:10D36800E4150020024B0146186800F0C7BC00BF56 +:10D37800E41500202DE9F04F01F10B05162D83B0BF +:10D38800064640F29F8035F0070500F1BF80A942AC +:10D3980000F2BC8000F026FBB5F5FC7FC0F09C8253 +:10D3A8006B0A00F0BA80042B00F28381A80900F10F +:10D3B800390E4FEA4E033830C44F07EB8303A3F10D +:10D3C80008015C68A14207D1ACE0002A80F2AC8079 +:10D3D800E468A14200F0A680636823F003035A1BA7 +:10D3E8000F2AF2DDB9493C6901F1080E744500F0D5 +:10D3F800B381636823F003035A1B0F2A00F3998152 +:10D40800002AC1F814E0C1F810E080F29E80B3F55C +:10D41800007F80F06781DB0803F1010C01229B107B +:10D4280002FA03F34A6851F83C80C4F8088001EB1B +:10D43800CC091A43A9F10803E3604A6041F83C406B +:10D44800C8F80C40831001249C40944200F28A8062 +:10D45800144206D120F003006400144200F10400D5 +:10D46800FAD007EBC009CC468046DCF80C108C4596 +:10D4780007D173E1002A80F28181C9688C4500F0E8 +:10D488006D814B6823F003035A1B0F2AF2DD0C460B +:10D49800D1F80CC054F8088F4B1945F001054D60C0 +:10D4A80042F00101C8F80CC03046CCF808807B6116 +:10D4B8003B61C3F80CE0C3F808E059609A5000F0EB +:10D4C80093FA1FE0102921D800F08CFA10250623C2 +:10D4D80002207E4F07EB8303A3F108025C689442A5 +:10D4E80000F045816368E168A56823F003032344DD +:10D4F80030465A68E96042F001028D605A6000F0D7 +:10D5080073FA0834204603B0BDE8F08F00240C23DA +:10D518002046336003B0BDE8F08F80234FF0400E03 +:10D528003F2049E770465DE72344E1685A68A568EB +:10D5380042F00102E96030468D605A6000F054FA0A +:10D548000834204603B0BDE8F08F234430465A68BB +:10D5580042F001025A6000F047FA0834204603B04E +:10D56800BDE8F08FBC68636823F00308A84504D3BE +:10D57800C5EB08030F2B00F38C80554BDFF8609147 +:10D588001A68D9F8003001332A4404EB080A00F07D +:10D59800608102F580520F3222F47F6222F00F027E +:10D5A80011463046019200F021FAB0F1FF3F834660 +:10D5B800019A00F05881824500F2FC80454B1968B9 +:10D5C800DA451144196000F05381D9F80000DFF8FA +:10D5D80010E101301BBFCAEB0B0A5144CEF800B072 +:10D5E80019601BF0070100F01781C1F10800C1F5AF +:10D5F8008051834408315A44C2F30B02C2EB01093B +:10D6080049463046019300F0F1F9431C019B00F0B4 +:10D618003F81CBEB00024A4442F001021968C7F887 +:10D6280008B04944BC42CBF804201960DFF8A49044 +:10D6380016D0B8F10F0F40F2FD806268A8F10C0314 +:10D6480023F00703E01802F001024FF0050E1A4319 +:10D658000F2B6260C0F804E0C0F808E000F21C81FB +:10D668001D4BBC681A68914288BF19601B4B1A6829 +:10D678009142626888BF196022F003029542A2EBCA +:10D68800050301D80F2B04DC304600F0ADF9002467 +:10D6980038E7621943F0010345F00105656030463B +:10D6A800BA60536000F0A0F90834204603B0BDE822 +:10D6B800F08F142B71D9542B00F2A480280B00F1A1 +:10D6C8006F0E4FEA4E036E3076E600BFD41100208D +:10D6D800FC210020CC210020F4210020F82100208A +:10D6E800DC1500205A0A042A5ED9142A00F2B380F5 +:10D6F80002F15C0149005B3207EB810C57F82110FD +:10D70800DFF8DC81ACF1080C8C4500F088804A68B1 +:10D7180022F00302934202D289688C45F7D1D1F8EE +:10D728000CC07A68C4F80CC0A160CCF80840CC6082 +:10D7380088E6631942F0010745F001056560304647 +:10D748004B610B61C3F80CE0C3F808E05F609A50C6 +:10D75800083400F049F9D5E64A6873E608F101088B +:10D7680018F0030F0CF1080C7FF47FAE30E0DC6892 +:10D77800A34208BF02303FF435AEB3E60B440C4673 +:10D788005A68C96854F8085F42F001025A60304686 +:10D79800E9608D6000F028F9B4E603F15C0E03F14E +:10D7A8005B004FEA4E0307E69A0902F13901490086 +:10D7B8003832A1E7BC424A4B3FF400AF9C6862682C +:10D7C80022F003025AE759F80839994540F0828057 +:10D7D80010F0030F00F1FF30F5D17B6823EA040352 +:10D7E8007B6064009C423FF6BDAE002C3FF4BAAEAD +:10D7F8001C4240467FF435AE64001C4200F1040030 +:10D80800FAD02EE6B3F5AA7F18D8E80B00F1780E07 +:10D818004FEA4E037730CFE54FF48051EBE6012114 +:10D82800D8F80430921001FA02F21A43C8F804201A +:10D83800614677E70123CBF8043025E740F25452DC +:10D84800934220D8A80C00F17D0E4FEA4E037C309D +:10D85800B2E51032A4E6542A26D81A0B02F16F0159 +:10D8680049006E3248E7BC68626822F0030205E7A7 +:10D87800CAF30B0000287FF4A8AE4244BB6842F00C +:10D8880001025A60ECE6FE234FF07F0E7E2093E5FE +:10D8980001224FF00009C1E604F10801304600F00A +:10D8A8002DFAD9F80010DBE6B2F5AA7F05D8DA0B15 +:10D8B80002F17801490077321EE740F254518A425A +:10D8C80005D89A0C02F17D0149007C3214E7FE214B +:10D8D8007E2211E77B6884E7E808431C5B00F8E5D3 +:10D8E800D4110020032A70B426D940EA01039B070B +:10D8F80011D004780D78AC4222D10244431C05E0D3 +:10D9080013F8014B11F8015FAC4219D19342F7D1DA +:10D91800002070BC70470C4603461E682568AE425E +:10D928001846214603F1040304F10404E1D1043A42 +:10D93800032A18462146F0D8002ADAD11046E8E72B +:10D94800601B70BC704700BF70B4840746D0541E7B +:10D95800002A41D0CDB2034602E0621EE4B3144669 +:10D9680003F8015B9A07F8D1032C2ED9CDB245EA0A +:10D9780005250F2C45EA054519D903F1100226465D +:10D98800103E0F2E42F8105C42F80C5C42F8085C1E +:10D9980042F8045C02F11002F2D8A4F1100222F05D +:10D9A8000F0204F00F041032032C13440DD91E4645 +:10D9B8002246043A032A46F8045BFAD8221F22F0CA +:10D9C80003020432134404F003042CB1C9B21C440A +:10D9D80003F8011BA342FBD170BC704714460346F1 +:10D9E800C2E700BF704700BF704700BF38B5074C9B +:10D9F8000023054608462360FDF7CEFF431C00D0F0 +:10DA080038BD2368002BFBD02B6038BD8028002050 +:10DA180000000000000000000000000000000000FE +:10DA280000000000000000000000000000000000EE +:10DA380000000000000000000000000000000000DE +:10DA480090F800F06DE9024520F007016FF0000C36 +:10DA580010F0070491F820F040F049804FF00004DE +:10DA68006FF00700D1E9002391F840F000F10800B9 +:10DA780082FA4CF2A4FA8CF283FA4CF3A2FA8CF3F1 +:10DA88004BBBD1E9022382FA4CF200F10800A4FA58 +:10DA98008CF283FA4CF3A2FA8CF3E3B9D1E90423AC +:10DAA80082FA4CF200F10800A4FA8CF283FA4CF3E3 +:10DAB800A2FA8CF37BB9D1E9062301F1200182FA9D +:10DAC8004CF200F10800A4FA8CF283FA4CF3A2FAA3 +:10DAD8008CF3002BC6D0002A04BF04301A4612BAB1 +:10DAE800B2FA82F2FDE8024500EBD2007047D1E9B4 +:10DAF800002304F00305C4F100004FEAC50514F043 +:10DB0800040F91F840F00CFA05F562EA05021CBF13 +:10DB180063EA050362464FF00004A9E7002A41D0F2 +:10DB280040EA010313F00303F0B425D1032A23D9F3 +:10DB380004680D68AC421FD1043A35D0A4F1013510 +:10DB480025EA040414F0803F31D1071D0D1D0DE0B6 +:10DB580057F8043B0E68A3F10134B34224EA0304E6 +:10DB68000AD1043A20D014F0803F23D1032A294651 +:10DB7800384605F10405EBD803780C789C4202F18D +:10DB8800FF320CD182B114B916E06AB17BB110F83A +:10DB9800013F11F8014FA34202F1FF32F5D0181BE3 +:10DBA800F0BC7047104670471046F0BC70471846E6 +:10DBB800F0BC70470020F3E72046F1E72DE9F04775 +:10DBC800254C2568D5F84841064688469246994628 +:10DBD800C4B360681F2817DC431C76B104EB8005CA +:10DBE8000122C5F888A0D4F8881182401143022E7A +:10DBF800C4F88811C5F808911ED00230636044F853 +:10DC080020800020BDE8F087144B03B34FF4C870A0 +:10DC1800FFF7A0FB0446D0B1D5F84831002780E8CB +:10DC28008800C5F8484138460123C4F88871C4F80B +:10DC38008C71002EE1D0D1E7D4F88C110A43C4F8D6 +:10DC48008C21DAE705F5A674C5F84841C1E74FF01D +:10DC5800FF30BDE8F08700BF4807002015B400007A +:10DC6800F8B5234F0C460646FFF7BCFEBB685D6857 +:10DC780025F00305291B01F6EF7121F47F6121F0DE +:10DC88000F01A1F58054B4F5805F07DB0021304611 +:10DC9800FFF7ACFEBB682B44984204D03046FFF730 +:10DCA800A3FE0020F8BD61423046FFF79FFE013019 +:10DCB8000DD0104BBA6819682D1B45F00105304688 +:10DCC800091B55601960FFF78FFE0120F8BD002180 +:10DCD8003046FFF78BFEBA68831A0F2BDEDD064C41 +:10DCE8000449246843F00103001B53600860D5E72A +:10DCF800D4110020CC210020DC150020002945D0BB +:10DD08002DE9F0410D468046FFF76CFE55F8047C7E +:10DD18006A4927F00103A5F10804E2188E685068E3 +:10DD2800B24220F0030062D0FE0750600BD455F8D1 +:10DD3800087CE41B01F1080EA56875453B446FD0CB +:10DD4800E768EF60BD6015186D68ED0742D543F0D0 +:10DD580001026260E350B3F5007F18D2DB085A1C59 +:10DD68004D6851F83270A76001209B1000FA03F348 +:10DD780001EBC2001D430838E0604D6041F83240B5 +:10DD8800FC604046BDE8F041FFF72EBE70475A0AD6 +:10DD9800042A53D89A0902F139077F0002F138059D +:10DDA80001EB870051F827204449083890424DD0AC +:10DDB800516821F003018B4202D292689042F7D158 +:10DDC800D068E060A2608460D4604046BDE8F0415D +:10DDD800FFF70ABE95683A4FBD4203443FD0D0686A +:10DDE800E86043F0010285606260E350B3E7FF0733 +:10DDF800034407D455F8082CA41A1344A068E26811 +:10DE0800C26090602F4A126843F00100934260603C +:10DE18008C60B6D32C4B40461968FFF721FFB0E75A +:10DE280011184968C90744D49168D268CA60034484 +:10DE380043F0010091606060E350A2E7142A17D80C +:10DE480002F15C077F0002F15B05A9E7AA104B68A5 +:10DE5800012505FA02F213434B600246B1E743F08D +:10DE680001024C610C61E560A5606260E35088E7DF +:10DE7800542A06D81A0B02F16F077F0002F16E05CB +:10DE88008EE7B2F5AA7F06D8DA0B02F178077F0091 +:10DE980002F1770584E740F25450824206D89A0C82 +:10DEA80002F17D077F0002F17C0579E7FE277E25D8 +:10DEB80076E743F001026260E35062E7D411002084 +:10DEC800DC110020E0150020FC21002000000000EB +:10DED8005FF800F06D1D00605FF800F0191E00602B +:04DEE800F8B500BFCA +:08DEEC00FCF3FF7F01000000C0 +:10DEF400000000000000000000000000000000001E +:10DF0400000000000000000000000000000000000D +:10DF140000000000000000000000000000000000FD +:10DF240000000000000000000000000000000000ED +:10DF340000000000000000000000000000000000DD +:10DF440000000000000000000000000000000000CD +:10DF540000000000000000000000000000000000BD +:10DF640000000000000000000000000000000000AD +:10DF7400000000000000000000000000000000009D +:10DF8400000000000000000000000000000000008D +:10DF9400000000000000000000000000000000007D +:10DFA400000000000000000000000000000000006D +:10DFB400000000000000000000000000000000005D +:10DFC400000000000000000000000000000000004D +:10DFD400000000000000000000000000000000003D +:10DFE400000000000000000000000000000000002D +:10DFF400000000000000000000000000000000001D +:10E00400000000000000000000000000000000000C +:10E0140000000000000000000000000000000000FC +:10E0240000000000000000000000000000000000EC +:10E0340000000000000000000000000000000000DC +:10E0440000000000000000000000000000000000CC +:10E0540000000000000000000000000000000000BC +:10E0640000000000000000000000000000000000AC +:10E07400000000000000000000000000000000009C +:10E08400000000000000000000000000000000008C +:10E09400000000000000000000000000000000007C +:10E0A400000000000000000000000000000000006C +:10E0B400000000000000000000000000000000005C +:10E0C400000000000000000000000000000000004C +:10E0D400000000000000000000000000000000003C +:10E0E400000000000000000000000000000000002C +:10E0F400000000000000000000000000000000001C +:10E10400000000000000000000000000000000000B +:10E1140000000000000000000000000000000000FB +:10E1240000000000000000000000000000000000EB +:10E1340000000000000000000000000000000000DB +:10E1440000000000000000000000000000000000CB +:10E1540000000000000000000000000000000000BB +:10E1640000000000000000000000000000000000AB +:10E174000D0A0000FF007801800143028801870135 +:10E184008C018B01920191019501F601990198018D +:10E194009A013D029E012002A801A701AD01AC0134 +:10E1A400B001AF01B901B801BD01BC01BF01F70164 +:10E1B400C601C401C901C701CC01CA01DD018E0138 +:10E1C400F301F101F501F4013A02652C3C023B0232 +:10E1D4003E02662C4202410253028101540286012E +:10E1E4005602890157028A0159028F015B0290018C +:10E1F4006002930163029401680297016902960127 +:10E204006B02622C6F029C0172029D0175029F01D8 +:10E214007D02642C8002A6018302A9018802AE015A +:10E22400890244028A02B1018B02B2018C024502C6 +:10E234009202B7017B03FD037C03FE037D03FF030E +:10E24400AC038603C203A303CC038C03CD038E0368 +:10E25400CE038F03F203F903F803F703FB03FA0376 +:10E26400CF04C0047D1D632C511F591F531F5B1F16 +:10E27400551F5D1F571F5F1F781FF81F791FF91F58 +:10E28400B31FBC1FCC1FC31FE51FEC1FFC1FF31FD4 +:10E294004E21322184218321612C602C762C752C13 +:10E2A4006100E01AE000E017F800E0070001013027 +:10E2B40032010106390101104A01012E79010106DA +:10E2C40082010104A0010106B3010104CD01011082 +:10E2D400DE010112F8010128220201124602010A9C +:10E2E400AD03DB03B103E011C303E009D803011854 +:10E2F4003004E0205004B010600401228A04013686 +:10E30400C104010ED00401446105D026001E01960B +:10E31400A01E015A001F0808101F0806201F080825 +:10E32400301F0808401F0806601F0808701F4A02B3 +:10E33400721F5604761F64027A1F70027C1F7E02CD +:10E34400801F0808901F0808A01F0808B01F0802B3 +:10E35400D01F0802E01F08027021F010D024E61A32 +:10E36400302CD02F672C0106802C0164002D002650 +:10E3740041FFE01A1F1C1F1E1F1E1F1F1E1F1E1FF2 +:10E384001F1C1F1E1F1E1F1F1E1F1E1F6CC00F40A1 +:10E39400C0000000504F00000D8C00000CFF000076 +:10E3A40013000000000000000000000024851F404E +:10E3B4000BFF00001300000000000000000000003C +:10E3C40028851F400DFF000013000000000000001E +:10E3D4000000000020851F400A25240013000000CF +:10E3E40012000000120000000102030000000000FF +:10E3F4001C851F4000000000000000000000000019 +:10E4040000000000BD010000CD0500007D000000FB +:10E4140065050000D10600008501000039040000F4 +:10E424000000000000000000BD6B0000C96B00008C +:10E43400C16B0000F16C0000296B00007D730000CB +:10E4440009730000E9700000F1720000ED7400002F +:10E45400D96B00004D6B000081710000156B00004A +:10E46400196B0000216B0000256B0000396B000064 +:10E47400E1700000D9700000856F0000B11A00003F +:10E484001D6B00002D740000D16F0000916C000022 +:10E494000000000000000000BDAE0000B5AE0000AA +:10E4A400B1AE0000ADAE0000A9AE0000A5AE000004 +:10E4B400A1AE00009DAE00000000000000000000BE +:10E4C40025060000E10500007D0000003D05000078 +:10E4D400CD040000790600008D05000099080000B5 +:10E4E400450900000000000000000000BD0100001C +:10E4F400CD0500007D00000065050000D106000088 +:10E504008501000039040000000000000000000044 +:10E51400110800005108000021040000B9050000A2 +:10E524002D0700006D010000790500003D03000087 +:10E5340089070000E90300000504000099000000B9 +:10E54400850000009D02000051040000C10000008D +:10E5540059020000F101000081030000E9020000FB +:10E56400790400000000000000000000899A000007 +:10E57400A1AC00007D00000081000000899A000029 +:10E58400899A0000899A0000000000000000000041 +:10E59400411B0000911D0000411D0000051C0000EE +:10E5A400791C0000DD1C0000DD1D0000C91E0000F8 +:10E5B400051F000011200000000000000000000002 +:10E5C40019770000917700002D750000597A00003A +:10E5D40045840000957E0000291A0000ED790000B2 +:10E5E40079850000D57D00004D7D0000691A00008A +:10E5F400AD7A0000B9760000C5760000A51A0000C7 +:10E60400A91A0000AD1A0000D1760000ED760000D2 +:10E614000977000099780000E5770000517C00003C +:10E62400E17C0000D97B0000D8399D270054EA2AF8 +:10E6340000A4781F007B9A17380D002000000042C8 +:10E64400C8801F40B8821F4008000000000000423C +:10E65400C4801F40B4821F400400000000C0004278 +:10E6640024801F4014821F401000000000C000429C +:10E6740028801F4018821F402000000000C0004274 +:10E684002C801F401C821F404000000000C000423C +:10E6940034801F4024821F400001000000400042DB +:10E6A40064811F4054831F40000400000040004266 +:10E6B40080811F4070831F40000002000040004220 +:10E6C4007C811F406C831F40000001000040004219 +:10E6D40068811F4058831F4000080000004000422A +:10E6E4003C811F402C831F40010000000040004279 +:10E6F40044811F4034831F40040000000040004256 +:10E7040040811F4030831F4002000000004000424F +:10E7140048811F4038831F40080000000000004269 +:10E7240004811F40F4821F400000040000000042E6 +:10E7340008811F40F8821F400000080000000042CA +:10E7440018811F4008831F40000080000000004221 +:10E7540014811F4004831F40000040000000004259 +:10E7640000811F40F0821F400000020000000042B0 +:10E77400FC801F40EC821F400000010000000042AA +:10E7840024811F4014831F40000000040000004245 +:10E7940028811F4018831F40000000080000004229 +:10E7A4001C811F400C831F40000000010000004238 +:10E7B40020811F4010831F4000000002000000421F +:10E7C400EC801F40DC821F4000100000000000426B +:10E7D400F0801F40E0821F40002000000000004243 +:10E7E40034811F4024831F40000000400000004289 +:10E7F40038811F4028831F400000008000800042B1 +:10E8040094801F4084821F400000040000C0004226 +:10E8140090801F4080821F400000008000800042E2 +:10E82400A8801F4098821F400000800000800042A2 +:10E83400A4801F4094821F4000004000004000421A +:10E844006C811F405C831F400010000000C0004228 +:10E8540030801F4020821F408000000000400042A2 +:10E86400B0811F40A0831F400000002000400042F0 +:10E87400AC811F409C831F400000001000400042F8 +:10E8840084811F4074831F40000004000040004244 +:10E8940088811F4078831F40000008000000004268 +:10E8A4002C811F401C831F40000000100000004208 +:10E8B40030811F4020831F400000002000000042E0 +:10E8C4000C811F40FC821F40000010000000004229 +:10E8D40010811F4000831F40000020000080004280 +:10E8E400C8811F40B8831F400080000000800042A0 +:10E8F400C4811F40B4831F400040000000800042D8 +:10E90400C0811F40B0831F400020000000800042EF +:10E91400BC811F40AC831F400010000000800042F7 +:10E92400D0811F40C0831F400000020000800042CD +:10E93400CC811F40BC831F400000010000C0004286 +:10E9440074801F4064821F400000000100C0004228 +:10E9540080801F4070821F400000000800C00042F9 +:10E9640084801F4074821F400000001000C00042D9 +:10E974006C801F405C821F400000400000C00042C9 +:10E984007C801F406C821F400000000400C00042D5 +:10E9940078801F4068821F400000000200C00042CF +:10E9A40088801F4078821F4000000020696C6F2E11 +:10E9B400726F6D00696C6F3A206C6F616420726FC6 +:10E9C4006D0000002E0000000A696C6F3A20726F1F +:10E9D4006D206C6F6164656400000000696C6F2ECB +:10E9E400626C6F00696C6F3A207072657061726559 +:10E9F400206D656D6F727900696C6F3A2070726575 +:10EA04007061726520692F6F2070696E7300000059 +:10EA1400696C6F3A20636865636B20666F7220537C +:10EA2400442063617264000021212121206361720A +:10EA340064206661696C65642C206F72206E6F744B +:10EA44002070726573656E743B20636865636B2028 +:10EA54005344206361726420616E64207265737430 +:10EA640061727400696C6F3A20636865636B206639 +:10EA74006F7220696C6F2E726F6D0000212121214D +:10EA8400206D697373696E6720696C6F2E726F6D88 +:10EA94003B20636865636B20534420636172642088 +:10EAA400616E64207265737461727400696C6F3A8C +:10EAB40020636865636B20666F7220696C6F2E62D9 +:10EAC4006C6F000021212121206D697373696E67C9 +:10EAD40020696C6F2E626C6F3B20636865636B20EA +:10EAE4005344206361726420616E642072657374A0 +:10EAF4006172740044657669636520697320746F7C +:10EB04006F20736D616C6C0D0A000000577269749C +:10EB1400696E6720464154200000000057726974F2 +:10EB2400696E6720757063617365207461626C65DA +:10EB34000D0A000057726974696E6720726F6F74F2 +:10EB44000D0A0000466F726D617420646F6E650D6E +:10EB54000A000000466F726D6174206661696C651D +:10EB6400640D0A0045584641540000004261642087 +:10EB7400636C757374657220636F756E740D0A002F +:10EB84004361726420697320746F6F20736D616CCC +:10EB94006C2E0D0A00000000466F726D61742044F3 +:10EBA4006F6E650D0A000000466F726D6174204639 +:10EBB40061696C65640D0A0000010000E81500201D +:10EBC40012000000000600003C1F00600A00000064 +:10EBD40000020000F01E00604B000000000700006F +:10EBE400A41E00604B00000000030000A01E006093 +:10EBF4000000000001030904881E006000000000FA +:10EC040002030904701E00600000000003030904ED +:10EC140000160020000000000000000000000000BA +:10EC2400000000000000000000000000241000208C +:10EC34008C100020F41000200000000000000000F0 +:10EC440000000000000000000000000000000000C0 +:10EC540000000000000000000000000000000000B0 +:10EC640000000000000000000000000000000000A0 +:10EC74000000000000000000000000000000000090 +:10EC84000000000000000000000000000000000080 +:10EC94000000000000000000000000000000000070 +:10ECA4000000000000000000000000000000000060 +:10ECB4000000000000000000000000000000000050 +:10ECC4000000000000000000000000000000000040 +:10ECD40001000000000000000E33CDAB34126DE6DD +:10ECE400ECDE05000B000000000000000000000046 +:10ECF4000000000000000000000000000000000010 +:10ED040000000000000000000000000000000000FF +:10ED140000000000000000000000000000000000EF +:10ED240000000000000000000000000000000000DF +:10ED340000000000000000000000000000000000CF +:10ED440000000000000000000000000000000000BF +:10ED540000000000000000000000000000000000AF +:10ED6400000000000000000000000000000000009F +:10ED7400000000000000000000000000000000008F +:10ED8400000000000000000000000000000000007F +:10ED9400000000000000000000000000000000006F +:10EDA400000000000000000000000000000000005F +:10EDB400000000000000000000000000000000004F +:10EDC400000000000000000000000000000000003F +:10EDD400000000000000000000000000000000002F +:10EDE400000000000000000000000000000000001F +:10EDF400000000000000000000000000000000000F +:10EE040000000000000000000000000000000000FE +:10EE140000000000000000000000000000000000EE +:10EE240000000000000000000000000000000000DE +:10EE340000000000000000000000000000000000CE +:10EE440000000000000000000000000000000000BE +:10EE540000000000000000000000000000000000AE +:10EE6400000000000000000000000000000000009E +:10EE7400000000000000000000000000000000008E +:10EE8400000000000000000000000000000000007E +:10EE9400000000000000000000000000000000006E +:10EEA400000000000000000000000000000000005E +:10EEB400000000000000000000000000000000004E +:10EEC400000000000000000000000000000000003E +:10EED400000000000000000000000000000000002E +:10EEE400000000000000000000000000000000001E +:10EEF400000000000000000000000000000000000E +:10EF040000000000000000000000000000000000FD +:10EF140000000000000000000000000000000000ED +:10EF240000000000000000000000000000000000DD +:10EF340000000000000000000000000000000000CD +:10EF440000000000000000000000000000000000BD +:10EF540000000000000000000000000000000000AD +:10EF6400000000000000000000000000000000009D +:10EF7400000000000000000000000000000000008D +:10EF8400000000000000000000000000000000007D +:10EF9400000000000000000000000000000000006D +:10EFA400000000000000000000000000000000005D +:10EFB400000000000000000000000000000000004D +:10EFC400000000000000000000000000000000003D +:10EFD400000000000000000000000000000000002D +:10EFE400000000000000000000000000000000001D +:10EFF400000000000000000000000000000000000D +:10F0040000000000000000000000000000000000FC +:10F0140000000000000000000000000000000000EC +:10F0240000000000000000000000000000000000DC +:10F0340000000000000000000000000000000000CC +:10F0440000000000000000000000000000000000BC +:10F05400000000000029DE07007B9A1700003A40F8 +:10F064009C040020000000000000000000000000DC +:10F07400000000000000000000000000000000008C +:10F08400000000000000000000000000000000007C +:10F09400000000000000000000000000000000006C +:10F0A400000000000000000000000000A80500208F +:10F0B40000000000E8030000000000002C01000034 +:10F0C400603020200000000000000000D411002067 +:10F0D400D4110020DC110020DC110020E4110020F8 +:10F0E400E4110020EC110020EC110020F4110020A8 +:10F0F400F4110020FC110020FC1100200412002057 +:10F10400041200200C1200200C1200201412002003 +:10F11400141200201C1200201C12002024120020B3 +:10F12400241200202C1200202C1200203412002063 +:10F13400341200203C1200203C1200204412002013 +:10F14400441200204C1200204C12002054120020C3 +:10F15400541200205C1200205C1200206412002073 +:10F16400641200206C1200206C1200207412002023 +:10F17400741200207C1200207C12002084120020D3 +:10F18400841200208C1200208C1200209412002083 +:10F19400941200209C1200209C120020A412002033 +:10F1A400A4120020AC120020AC120020B4120020E3 +:10F1B400B4120020BC120020BC120020C412002093 +:10F1C400C4120020CC120020CC120020D412002043 +:10F1D400D4120020DC120020DC120020E4120020F3 +:10F1E400E4120020EC120020EC120020F4120020A3 +:10F1F400F4120020FC120020FC1200200413002052 +:10F20400041300200C1300200C13002014130020FE +:10F21400141300201C1300201C13002024130020AE +:10F22400241300202C1300202C130020341300205E +:10F23400341300203C1300203C130020441300200E +:10F24400441300204C1300204C13002054130020BE +:10F25400541300205C1300205C130020641300206E +:10F26400641300206C1300206C130020741300201E +:10F27400741300207C1300207C13002084130020CE +:10F28400841300208C1300208C130020941300207E +:10F29400941300209C1300209C130020A41300202E +:10F2A400A4130020AC130020AC130020B4130020DE +:10F2B400B4130020BC130020BC130020C41300208E +:10F2C400C4130020CC130020CC130020D41300203E +:10F2D400D4130020DC130020DC130020E4130020EE +:10F2E400E4130020EC130020EC130020F41300209E +:10F2F400F4130020FC130020FC130020041400204D +:10F30400041400200C1400200C14002014140020F9 +:10F31400141400201C1400201C14002024140020A9 +:10F32400241400202C1400202C1400203414002059 +:10F33400341400203C1400203C1400204414002009 +:10F34400441400204C1400204C14002054140020B9 +:10F35400541400205C1400205C1400206414002069 +:10F36400641400206C1400206C1400207414002019 +:10F37400741400207C1400207C14002084140020C9 +:10F38400841400208C1400208C1400209414002079 +:10F39400941400209C1400209C140020A414002029 +:10F3A400A4140020AC140020AC140020B4140020D9 +:10F3B400B4140020BC140020BC140020C414002089 +:10F3C400C4140020CC140020CC140020D414002039 +:10F3D400D4140020DC140020DC140020E4140020E9 +:10F3E400E4140020EC140020EC140020F414002099 +:10F3F400F4140020FC140020FC1400200415002048 +:10F40400041500200C1500200C15002014150020F4 +:10F41400141500201C1500201C15002024150020A4 +:10F42400241500202C1500202C1500203415002054 +:10F43400341500203C1500203C1500204415002004 +:10F44400441500204C1500204C15002054150020B4 +:10F45400541500205C1500205C1500206415002064 +:10F46400641500206C1500206C1500207415002014 +:10F47400741500207C1500207C15002084150020C4 +:10F48400841500208C1500208C1500209415002074 +:10F49400941500209C1500209C150020A415002024 +:10F4A400A4150020AC150020AC150020B4150020D4 +:10F4B400B4150020BC150020BC150020C415002084 +:10F4C400C4150020CC150020CC150020FFFFFFFF41 +:10F4D40000000200380D002012010002EF0201407A +:10F4E400C016830480020102030100000D00000025 +:10F4F4000C030000000000000000000000000000F9 +:10F5040000000000000029010000000000000000CD +:10F5140000000000000000000000000000000000E7 +:10F5240000000000000000000000000000000000D7 +:10F5340000000000000000000000000000000000C7 +:10F5440000000000000000000000000000000000B7 +:10F5540000000000000000000000000000000000A7 +:10F564000000000000000000000000000000000097 +:10F574000000000000000000000000000000000087 +:10F584000000000000000000000000000000000077 +:10F594000000000000000000000000000000000067 +:10F5A4000000000000000000000000000000000057 +:10F5B4000000000000000000000000000000000047 +:10F5C4000000000000000000000000000000000037 +:10F5D4000000000000000000000000000000000027 +:10F5E4000000000000000000000000000000000017 +:10F5F4000000000000000000000000000000000007 +:10F6040000000000000000000000000000000000F6 +:10F6140000000000000000000000000000000000E6 +:10F6240000000000000000000000000000000000D6 +:10F6340000000000000000000000000000000000C6 +:10F6440000000000000000000000000000000000B6 +:10F6540000000000000000000000000000000000A6 +:10F664000000000000000000000000000000000096 +:10F674000000000000000000000000000000000086 +:10F684000000000000000000000000000000000076 +:10F694000000000000000000000000000000000066 +:10F6A4000000000000000000000000000000000056 +:10F6B4000000000000000000000000000000000046 +:10F6C4000000000000000000000000000000000036 +:10F6D4000000000000000000000000000000000026 +:10F6E4000000000000000000000000000000000016 +:10F6F4000000000000000000000000000000000006 +:10F7040000000000000000000000000000000000F5 +:10F7140000000000000000000000000000000000E5 +:10F7240000000000000000000000000000000000D5 +:10F7340000000000000000000000000000000000C5 +:10F7440000000000000000000000000000000000B5 +:10F7540000000000000000000000000000000000A5 +:10F764000000000000000000000000000000000095 +:10F774000000000000000000000000000000000085 +:10F784000000000000000000000000000000000075 +:10F794000000000000000000000000000000000065 +:10F7A4000000000000000000000000000000000055 +:10F7B4000000000000000000000000000000000045 +:10F7C4000000000000000000000000000000000035 +:10F7D4000000000000000000000000000000000025 +:10F7E4000000000000000000000000000000000015 +:10F7F4000000000000000000000000000000000005 +:10F8040000000000000000000000000000000000F4 +:10F8140000000000000000000000000000000000E4 +:10F8240000000000000000000000000000000000D4 +:10F8340000000000000000000000000000000000C4 +:10F8440000000000000000000000000000000000B4 +:10F8540000000000000000000000000000000000A4 +:10F864000000000000000000000000000000000094 +:10F874000000000000000000000000000000000084 +:10F884000000000000000000000000000000000074 +:10F894000000000000000000000000000000000064 +:10F8A4000000000000000000000000000000000054 +:10F8B4000000000000000000000000000000000044 +:10F8C4000000000000000000000000000000000034 +:10F8D4000000000000000000000000000000000024 +:10F8E4000000000000000000000000000000000014 +:10F8F4000000000000000000000000000000000004 +:10F9040000000000000000000000000000000000F3 +:10F9140000000000000000000000000000000000E3 +:10F9240000000000000000000000000000000000D3 +:10F9340000000000000000000000000000000000C3 +:10F9440000000000000000000000000000000000B3 +:10F9540000000000000000000000000000000000A3 +:10F964000000000000000000000000000000000093 +:10F974000000000000000000000000000000000083 +:10F984000000000000000000000000000000000073 +:10F994000000000000000000000000000000000063 +:10F9A4000000000000000000000000000000000053 +:10F9B400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF53 +:10F9C400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF43 +:10F9D400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF33 +:10F9E400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF23 +:10F9F400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF13 +:10FA0400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF02 +:10FA1400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2 +:10FA2400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE2 +:10FA3400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD2 +:10FA4400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC2 +:10FA5400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB2 +:10FA6400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA2 +:10FA7400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF92 +:10FA8400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF82 +:10FA9400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF72 +:10FAA400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF62 +:10FAB400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF52 +:10FAC400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF42 +:10FAD400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF32 +:10FAE400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF22 +:10FAF400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF12 +:10FB0400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01 +:10FB1400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1 +:10FB2400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE1 +:10FB3400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD1 +:10FB4400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC1 +:10FB5400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB1 +:10FB6400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA1 +:10FB7400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF91 +:10FB8400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF81 +:10FB9400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF71 +:10FBA400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF61 +:10FBB400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF51 +:10FBC400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF41 +:10FBD400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF31 +:10FBE400FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF21 +:10FBF400FFFFFFFFFFFFFFFFFFFFFFFF000000000D +:10FC040000000000000000000000000000000000F0 +:10FC140000000000000000000000000000000000E0 +:10FC240000000000000000000000000000000000D0 +:10FC340000000000000000000000000000000000C0 +:10FC440000000000000000000000000000000000B0 +:10FC540000000000000000000000000000000000A0 +:10FC64000000000000000000000000000000000090 +:10FC74000000000000000000000000000000000080 +:10FC84000000000000000000000000000000000070 +:10FC94000000000000000000000000000000000060 +:10FCA4000000000000000000000000000000000050 +:10FCB4000000000000000000000000000000000040 +:10FCC4000000000000000000000000000000000030 +:10FCD4000000000000000000000000000000000020 +:10FCE4000000000000000000000000000000000010 +:10FCF4000000000000000000000000000000000000 +:10FD040000000000000000000000000000000000EF +:10FD140000000000000000000000000000000000DF +:10FD240000000000000000000000000000000000CF +:10FD340000000000000000000000000000000000BF +:10FD440000000000000000000000000000000000AF +:10FD5400000000000000000000000000000000009F +:10FD6400000000000000000000000000000000008F +:10FD7400000000000000000000000000000000007F +:10FD8400000000000000000000000000000000006F +:10FD9400000000000000000000000000000000005F +:10FDA400000000000000000000000000000000004F +:10FDB400000000000000000000000000000000003F +:10FDC400000000000000000000000000000000002F +:10FDD400000000000000000000000000000000001F +:10FDE400000000000000000000000000000000000F +:10FDF40000000000000000000000000000000000FF +:10FE040000000000000000000000000000000000EE +:10FE140000000000000000000000000000000000DE +:10FE240000000000000000000000000000000000CE +:10FE340000000000000000000000000000000000BE +:10FE440000000000000000000000000000000000AE +:10FE5400000000000000000000000000000000009E +:10FE6400000000000000000000000000000000008E +:10FE7400000000000000000000000000000000007E +:10FE8400000000000000000000000000000000006E +:10FE9400000000000000000000000000000000005E +:10FEA400000000000000000000000000000000004E +:10FEB400000000000000000000000000000000003E +:10FEC400000000000000000000000000000000002E +:10FED400000000000000000000000000000000001E +:10FEE400000000000000000000000000000000000E +:10FEF40000000000000000000000000000000000FE +:10FF040000000000000000000000000000000000ED +:10FF140000000000000000000000000000000000DD +:10FF240000000000000000000000000000000000CD +:10FF340000000000000000000000000000000000BD +:10FF440000000000000000000000000000000000AD +:10FF5400000000000000000000000000000000009D +:10FF6400000000000000000000000000000000008D +:10FF7400000000000000000000000000000000007D +:10FF8400000000000000000000000000000000006D +:10FF9400000000000000000000000000000000005D +:10FFA400000000000000000000000000000000004D +:10FFB400000000000000000000000000000000003D +:10FFC400000000000000000000000000000000002D +:10FFD400000000000000000000000000000000001D +:10FFE400000000000000000000000000000000000D +:0CFFF40000000000000000000000000001 +:02000004600199 +:1000000000000000000000000000000000000000F0 +:1000100000000000000000000000000000000000E0 +:1000200000000000000000000000000000000000D0 +:1000300000000000000000000000000000000000C0 +:1000400000000000000000000000000000000000B0 +:1000500000000000000000000000000000000000A0 +:100060000000000000000000000000000000000090 +:100070000000000000000000000000000000000080 +:100080000000000000000000000000000000000070 +:100090000000000000000000000000000000000060 +:1000A0000000000000000000000000000000000050 +:1000B0000000000000000000000000000000000040 +:1000C0000000000000000000000000000000000030 +:1000D0000000000000000000000000000000000020 +:1000E0000000000000000000000000000000000010 +:1000F0000000000000000000000000000000000000 +:1001000000000000000000000000000000000000EF +:1001100000000000000000000000000000000000DF +:1001200000000000000000000000000000000000CF +:1001300000000000000000000000000000000000BF +:1001400000000000000000000000000000000000AF +:10015000000000000000000000000000000000009F +:10016000000000000000000000000000000000008F +:10017000000000000000000000000000000000007F +:10018000000000000000000000000000000000006F +:10019000000000000000000000000000000000005F +:1001A000000000000000000000000000000000004F +:1001B000000000000000000000000000000000003F +:1001C000000000000000000000000000000000002F +:1001D000000000000000000000000000000000001F +:1001E000000000000000000000000000000000000F +:1001F00000000000000000000000000000000000FF +:1002000000000000000000000000000000000000EE +:1002100000000000000000000000000000000000DE +:1002200000000000000000000000000000000000CE +:1002300000000000000000000000000000000000BE +:1002400000000000000000000000000000000000AE +:10025000000000000000000000000000000000009E +:10026000000000000000000000000000000000008E +:10027000000000000000000000000000000000007E +:10028000000000000000000000000000000000006E +:10029000000000000000000000000000000000005E +:1002A000000000000000000000000000000000004E +:1002B000000000000000000000000000000000003E +:1002C000000000000000000000000000000000002E +:1002D000000000000000000000000000000000001E +:1002E000000000000000000000000000000000000E +:1002F00000000000000000000000000000000000FE +:1003000000000000000000000000000000000000ED +:1003100000000000000000000000000000000000DD +:1003200000000000000000000000000000000000CD +:1003300000000000000000000000000000000000BD +:1003400000000000000000000000000000000000AD +:10035000000000000000000000000000000000009D +:10036000000000000000000000000000000000008D +:10037000000000000000000000000000000000007D +:10038000000000000000000000000000000000006D +:10039000000000000000000000000000000000005D +:1003A000000000000000000000000000000000004D +:1003B000000000000000000000000000000000003D +:1003C000000000000000000000000000000000002D +:1003D000000000000000000000000000000000001D +:1003E000000000000000000000000000000000000D +:1003F00000000000000000000000000000000000FD +:1004000000000000000000000000000000000000EC +:1004100000000000000000000000000000000000DC +:1004200000000000000000000000000000000000CC +:1004300000000000000000000000000000000000BC +:1004400000000000000000000000000000000000AC +:10045000000000000000000000000000000000009C +:10046000000000000000000000000000000000008C +:10047000000000000000000000000000000000007C +:10048000000000000000000000000000000000006C +:10049000000000000000000000000000000000005C +:1004A000000000000000000000000000000000004C +:1004B000000000000000000000000000000000003C +:1004C000000000000000000000000000000000002C +:1004D000000000000000000000000000000000001C +:1004E000000000000000000000000000000000000C +:1004F00000000000000000000000000000000000FC +:1005000000000000000000000000000000000000EB +:1005100000000000000000000000000000000000DB +:1005200000000000000000000000000000000000CB +:1005300000000000000000000000000000000000BB +:1005400000000000000000000000000000000000AB +:10055000000000000000000000000000000000009B +:10056000000000000000000000000000000000008B +:10057000000000000000000000000000000000007B +:10058000000000000000000000000000000000006B +:10059000000000000000000000000000000000005B +:1005A000000000000000000000000000000000004B +:1005B000000000000000000000000000000000003B +:1005C000000000000000000000000000000000002B +:1005D000000000000000000000000000000000001B +:1005E000000000000000000000000000000000000B +:1005F00000000000000000000000000000000000FB +:1006000000000000000000000000000000000000EA +:1006100000000000000000000000000000000000DA +:1006200000000000000000000000000000000000CA +:1006300000000000000000000000000000000000BA +:1006400000000000000000000000000000000000AA +:10065000000000000000000000000000000000009A +:10066000000000000000000000000000000000008A +:10067000000000000000000000000000000000007A +:10068000000000000000000000000000000000006A +:10069000000000000000000000000000000000005A +:1006A000000000000000000000000000000000004A +:1006B000000000000000000000000000000000003A +:1006C000000000000000000000000000000000002A +:1006D000000000000000000000000000000000001A +:1006E000000000000000000000000000000000000A +:1006F00000000000000000000000000000000000FA +:1007000000000000000000000000000000000000E9 +:1007100000000000000000000000000000000000D9 +:1007200000000000000000000000000000000000C9 +:1007300000000000000000000000000000000000B9 +:1007400000000000000000000000000000000000A9 +:100750000000000000000000000000000000000099 +:100760000000000000000000000000000000000089 +:100770000000000000000000000000000000000079 +:100780000000000000000000000000000000000069 +:100790000000000000000000000000000000000059 +:1007A0000000000000000000000000000000000049 +:1007B0000000000000000000000000000000000039 +:1007C0000000000000000000000000000000000029 +:1007D0000000000000000000000000000000000019 +:1007E0000000000000000000000000000000000009 +:1007F00000000000000000000000000000000000F9 +:040000056000100087 +:00000001FF diff --git a/binaries/ilo-universal-darwin b/binaries/ilo-universal-darwin new file mode 100755 index 0000000..d856431 Binary files /dev/null and b/binaries/ilo-universal-darwin differ diff --git a/binaries/ilo-x86-dos-32bit.exe b/binaries/ilo-x86-dos-32bit.exe new file mode 100644 index 0000000..5cc785c Binary files /dev/null and b/binaries/ilo-x86-dos-32bit.exe differ diff --git a/binaries/ilo-x86-dos.exe b/binaries/ilo-x86-dos.exe new file mode 100644 index 0000000..b8c88f5 Binary files /dev/null and b/binaries/ilo-x86-dos.exe differ diff --git a/binaries/ilo-x86-freebsd b/binaries/ilo-x86-freebsd new file mode 100755 index 0000000..f584b0c Binary files /dev/null and b/binaries/ilo-x86-freebsd differ diff --git a/binaries/ilo-x86-linux b/binaries/ilo-x86-linux new file mode 100755 index 0000000..95c77e6 Binary files /dev/null and b/binaries/ilo-x86-linux differ diff --git a/binaries/ilo-x86-netbsd b/binaries/ilo-x86-netbsd new file mode 100644 index 0000000..b8de689 Binary files /dev/null and b/binaries/ilo-x86-netbsd differ diff --git a/binaries/ilo-x86-openbsd b/binaries/ilo-x86-openbsd new file mode 100755 index 0000000..4b6c824 Binary files /dev/null and b/binaries/ilo-x86-openbsd differ diff --git a/binaries/ilo-x86-windows.exe b/binaries/ilo-x86-windows.exe new file mode 100644 index 0000000..4969bd7 Binary files /dev/null and b/binaries/ilo-x86-windows.exe differ diff --git a/binaries/ilo.jar b/binaries/ilo.jar new file mode 100644 index 0000000..cda7b31 Binary files /dev/null and b/binaries/ilo.jar differ diff --git a/source/ilo-68k-mac.c b/source/ilo-68k-mac.c new file mode 100644 index 0000000..55fd8e8 --- /dev/null +++ b/source/ilo-68k-mac.c @@ -0,0 +1 @@ +/* ilo for System 6 / Mac 68k Copyright (c) 2022, Charles Childers Deriving from the ilo for MS-DOS, this makes use of an internally segmented memory model. The 68k CPU is big endian. Since the ilo images and blocks are stored in little endian a fix() function has been written and is used to convert between the formats as needed. As with all ilo systems, this needs an ilo.rom and ilo.blocks. It's likely to crash if these are not present. I'm building this using Think C 5.0.2, using the ANSI library. It's not tested with any other compiler on 68k. */ #include #include #define SLICES 8 #define SLICESIZE 8192 long ip, sp, rp, data[32], address[256]; long *memory[SLICES]; #define TOS data[sp] #define NOS data[sp-1] #define TORS address[rp] unsigned long fix(unsigned long v) { return (((v & 0x000000FF) << 24)| ((v & 0x0000FF00) << 8) | ((v & 0x00FF0000) >> 8) | ((v & 0xFF000000) >> 24)); } long pop() { sp--; return data[sp + 1]; } void push(long value) { sp++; data[sp] = value; } void store(long a, long v) { long slice = a / SLICESIZE; long actual = a - (slice * SLICESIZE); memory[slice][actual] = v; } long fetch(long a) { long slice = a / SLICESIZE; long actual = a - (slice * SLICESIZE); return memory[slice][actual]; } void prepare_vm() { for (ip = 0; ip < 32; ip++) data[ip] = 0; for (ip = 0; ip < 128; ip++) address[ip] = 0; ip = sp = rp = 0; } void load_image() { FILE *fp; long x, y, z; fp = fopen("ilo.rom", "rb"); for (y = 0; y < 65536; y++) { x = 0; fread(&x, 4, 1, fp); store(y, fix(x)); } fclose(fp); prepare_vm(); } void save_image() { FILE *fp; long i, x; fp = fopen("ilo.rom", "wb"); for (i = 0; i < 65536; i++) { x = fix(fetch(i)); fwrite(&x, 4, 1, fp); } fclose(fp); } void read_block() { FILE *f; long block, buffer, x, c; buffer = pop(); block = pop(); f = fopen("ilo.blocks", "r+b"); fseek(f, 4096 * block, SEEK_SET); for (x = 0; x < 1024; x++) { c = 0; fread(&c, 4, 1, f); store(buffer + x, fix(c)); } fclose(f); } void write_block() { FILE *f; long block, buffer, x, c; buffer = pop(); block = pop(); f = fopen("ilo.blocks", "r+b"); fseek(f, 4096 * block, SEEK_SET); for (x = 0; x < 1024; x++) { c = fix(fetch(buffer + x)); fwrite(&c, 4, 1, f); } fclose(f); } void process(long o) { long a, b, target, flag; long src, dest, len; switch (o) { case 0: break; case 1: ip++; push(fetch(ip)); break; case 2: push(TOS); break; case 3: data[sp] = 0; sp--; break; case 4: a = TOS; TOS = NOS; NOS = a; break; case 5: rp++; TORS = pop(); break; case 6: push(TORS); rp--; break; case 7: ip = pop() - 1; break; case 8: rp++; TORS = ip; ip = pop() - 1; break; case 9: target = pop(); flag = pop(); if (flag != 0) { rp++; TORS = ip; ip = target - 1; } break; case 10: target = pop(); flag = pop(); if (flag != 0) ip = target - 1; break; case 11: ip = TORS; rp--; break; case 12: NOS = (NOS == TOS) ? -1 : 0; sp--; break; case 13: NOS = (NOS != TOS) ? -1 : 0; sp--; break; case 14: NOS = (NOS < TOS) ? -1 : 0; sp--; break; case 15: NOS = (NOS > TOS) ? -1 : 0; sp--; break; case 16: TOS = fetch(TOS); break; case 17: store(TOS, NOS); sp--; sp--; break; case 18: NOS += TOS; sp--; break; case 19: NOS -= TOS; sp--; break; case 20: NOS *= TOS; sp--; break; case 21: a = TOS; b = NOS; TOS = b / a; NOS = b % a; break; case 22: NOS = TOS & NOS; sp--; break; case 23: NOS = TOS | NOS; sp--; break; case 24: NOS = TOS ^ NOS; sp--; break; case 25: NOS = NOS << TOS; sp--; break; case 26: NOS = NOS >> TOS; sp--; break; case 27: len = pop(); dest = pop(); src = pop(); flag = -1; while (len) { if (fetch(dest) != fetch(src)) flag = 0; len -= 1; src += 1; dest += 1; }; push(flag); break; case 28: len = pop(); dest = pop(); src = pop(); while (len) { store(dest, fetch(src)); len -= 1; src += 1; dest += 1; }; break; case 29: switch (pop()) { case 0: putc(pop(), stdout); break; case 1: push(getc(stdin)); break; case 2: read_block(); break; case 3: write_block(); break; case 4: save_image(); break; case 5: load_image(); ip = -1; break; case 6: ip = 65536; break; case 7: push(sp); push(rp); break; default: break; } break; default: break; } } void execute(long address) { long opcode, o; ip = address; while (ip < 65536) { opcode = fetch(ip); switch (opcode) { case 0: break; case 1793: ip = fetch(ip + 1) - 1; break; case 2049: process(1); process(8); break; case 67502597: push(NOS); break; default: o = opcode & 0xFF; if (o != 0) process(o); o = (opcode >> 8) & 0xFF; if (o != 0) process(o); o = (opcode >> 16) & 0xFF; if (o != 0) process(o); o = (opcode >> 24) & 0xFF; if (o != 0) process(o); break; } ip++; } } void main(long argc, char **argv) { long i; for (i = 0; i < SLICES; i++) memory[i] = malloc(SLICESIZE * sizeof(long)); load_image(); execute(0); for (i = 0; i < SLICES; i++) free(memory[i]); for (i = 1; sp >= i; i++) printf(" %d", data[i]); printf("\n"); } \ No newline at end of file diff --git a/source/ilo-aarch64-linux.s b/source/ilo-aarch64-linux.s new file mode 100644 index 0000000..4b0505c --- /dev/null +++ b/source/ilo-aarch64-linux.s @@ -0,0 +1,1120 @@ +/*************************************************************** + + crc's _ _ + (_) | ___ + | | |/ _ \ a tiny virtual computer + | | | (_) | 64kw RAM, 32-bit, Dual Stack, MISC + |_|_|\___/ (c) charles childers + + This is an implementation of ilo in aarch64 assembly. + + To build: + + as ilo-aarch64-linux.s -o ilo.o + ld -nostdlib -s ilo.o -o ilo + + **************************************************************/ + + .text + .globl _start + +// ------------------------------------------------------------- +// System Call Interface +// +// ilo makes use of a small number of system calls. These are: +// +// +-------------+--------+ +// | System Call | Number | +// +=============+========+ +// | openat (*) | 56 | +// | close | 57 | +// | read | 63 | +// | write | 64 | +// | lseek | 62 | +// | exit | 93 | +// +-------------+--------+ +// +// (*) On most systems, I use the open() system call. But, on +// aarch64, Linux does not implement open() as a system +// call. Instead, it uses openat(). I implement an os_open() +// to wrap the actual openat() call. +// ------------------------------------------------------------- + +os_openat: + mov x8, #56 + svc #0 + ret + +os_close: + mov x8, #57 + svc #0 + ret + +os_lseek: + mov x8, #62 + svc #0 + ret + +os_read: + mov x8, #63 + svc #0 + ret + +os_write: + mov x8, #64 + svc #0 + ret + +os_exit: + mov x0, #0 // exit, with return code 0 + mov x8, #93 + svc #0 + +os_open: + sub sp, sp, #32 + stp x29, x30, [sp, #16] // 16-byte Folded Spill + add x29, sp, #16 + str x0, [sp, #8] + str w1, [sp, #4] + ldr x1, [sp, #8] + ldr w2, [sp, #4] + mov w0, #-100 + bl os_openat + ldp x29, x30, [sp, #16] // 16-byte Folded Reload + add sp, sp, #32 + ret +// ------------------------------------------------------------- +pop: + adrp x8, sp + ldr w9, [x8, :lo12:sp] + subs w9, w9, #1 + str w9, [x8, :lo12:sp] + ldr w8, [x8, :lo12:sp] + add w9, w8, #1 + adrp x8, data + add x8, x8, :lo12:data + ldr w0, [x8, w9, sxtw #2] + ret +// ------------------------------------------------------------- +push: + sub sp, sp, #16 + str w0, [sp, #12] + adrp x9, sp + ldr w8, [x9, :lo12:sp] + add w8, w8, #1 + str w8, [x9, :lo12:sp] + ldr w8, [sp, #12] + ldrsw x10, [x9, :lo12:sp] + adrp x9, data + add x9, x9, :lo12:data + str w8, [x9, x10, lsl #2] + add sp, sp, #16 + ret +// ------------------------------------------------------------- +prepare_vm: + adrp x8, rp + str wzr, [x8, :lo12:rp] + adrp x8, sp + str wzr, [x8, :lo12:sp] + adrp x8, ip + str wzr, [x8, :lo12:ip] + ret +// ------------------------------------------------------------- +load_image: + sub sp, sp, #32 + stp x29, x30, [sp, #16] // 16-byte Folded Spill + add x29, sp, #16 + adrp x8, rom + ldr x0, [x8, :lo12:rom] + mov w1, wzr + mov w2, #438 + bl os_open + adrp x8, fp + str w0, [x8, :lo12:fp] + ldr w8, [x8, :lo12:fp] + subs w8, w8, #0 + cset w8, ne + tbnz w8, #0, .image_found + b .load_image_done +.image_found: + adrp x8, fp + str x8, [sp, #8] // 8-byte Folded Spill + ldr w0, [x8, :lo12:fp] + adrp x1, m + add x1, x1, :lo12:m + mov x2, #262144 + bl os_read + ldr x8, [sp, #8] // 8-byte Folded Reload + ldr w0, [x8, :lo12:fp] + bl os_close + bl prepare_vm +.load_image_done: + ldp x29, x30, [sp, #16] // 16-byte Folded Reload + add sp, sp, #32 + ret +// ------------------------------------------------------------- +save_image: + sub sp, sp, #32 + stp x29, x30, [sp, #16] // 16-byte Folded Spill + add x29, sp, #16 + adrp x8, rom + ldr x0, [x8, :lo12:rom] + mov w1, #1 + mov w2, #438 + bl os_open + adrp x8, fp + str x8, [sp, #8] // 8-byte Folded Spill + str w0, [x8, :lo12:fp] + ldr w0, [x8, :lo12:fp] + adrp x1, m + add x1, x1, :lo12:m + mov x2, #262144 + bl os_write + ldr x8, [sp, #8] // 8-byte Folded Reload + ldr w0, [x8, :lo12:fp] + bl os_close + ldp x29, x30, [sp, #16] // 16-byte Folded Reload + add sp, sp, #32 + ret +// ------------------------------------------------------------- +block_common: + stp x29, x30, [sp, #-16]! // 16-byte Folded Spill + mov x29, sp + bl pop + adrp x8, buffer + str w0, [x8, :lo12:buffer] + bl pop + adrp x8, block + str w0, [x8, :lo12:block] + adrp x9, fp + ldr w0, [x9, :lo12:fp] + ldr w9, [x8, :lo12:block] + mov w8, #4096 + mul w9, w8, w9 + // implicit-def: $x8 + mov w8, w9 + sxtw x1, w8 + mov w2, wzr + bl os_lseek + ldp x29, x30, [sp], #16 // 16-byte Folded Reload + ret +// ------------------------------------------------------------- +read_block: + sub sp, sp, #32 + stp x29, x30, [sp, #16] // 16-byte Folded Spill + add x29, sp, #16 + adrp x8, blocks + ldr x0, [x8, :lo12:blocks] + mov w1, wzr + mov w2, #438 + bl os_open + adrp x8, fp + str x8, [sp, #8] // 8-byte Folded Spill + str w0, [x8, :lo12:fp] + bl block_common + ldr x8, [sp, #8] // 8-byte Folded Reload + ldr w0, [x8, :lo12:fp] + adrp x8, buffer + ldrsw x9, [x8, :lo12:buffer] + adrp x8, m + add x8, x8, :lo12:m + add x1, x8, x9, lsl #2 + mov x2, #4096 + bl os_read + ldr x8, [sp, #8] // 8-byte Folded Reload + ldr w0, [x8, :lo12:fp] + bl os_close + ldp x29, x30, [sp, #16] // 16-byte Folded Reload + add sp, sp, #32 + ret +// ------------------------------------------------------------- +write_block: + sub sp, sp, #32 + stp x29, x30, [sp, #16] // 16-byte Folded Spill + add x29, sp, #16 + adrp x8, blocks + ldr x0, [x8, :lo12:blocks] + mov w1, #1 + mov w2, #438 + bl os_open + adrp x8, fp + str x8, [sp, #8] // 8-byte Folded Spill + str w0, [x8, :lo12:fp] + bl block_common + ldr x8, [sp, #8] // 8-byte Folded Reload + ldr w0, [x8, :lo12:fp] + adrp x8, buffer + ldrsw x9, [x8, :lo12:buffer] + adrp x8, m + add x8, x8, :lo12:m + add x1, x8, x9, lsl #2 + mov x2, #4096 + bl os_write + ldr x8, [sp, #8] // 8-byte Folded Reload + ldr w0, [x8, :lo12:fp] + bl os_close + ldp x29, x30, [sp, #16] // 16-byte Folded Reload + add sp, sp, #32 + ret +// ------------------------------------------------------------- +save_ip: + adrp x9, rp + ldr w8, [x9, :lo12:rp] + add w8, w8, #1 + str w8, [x9, :lo12:rp] + adrp x8, ip + ldr w8, [x8, :lo12:ip] + ldrsw x10, [x9, :lo12:rp] + adrp x9, address + add x9, x9, :lo12:address + str w8, [x9, x10, lsl #2] + ret +// ------------------------------------------------------------- +li: + stp x29, x30, [sp, #-16]! // 16-byte Folded Spill + mov x29, sp + adrp x8, ip + ldr w9, [x8, :lo12:ip] + add w9, w9, #1 + str w9, [x8, :lo12:ip] + ldrsw x9, [x8, :lo12:ip] + adrp x8, m + add x8, x8, :lo12:m + ldr w0, [x8, x9, lsl #2] + bl push + ldp x29, x30, [sp], #16 // 16-byte Folded Reload + ret +// ------------------------------------------------------------- +du: + stp x29, x30, [sp, #-16]! // 16-byte Folded Spill + mov x29, sp + adrp x8, sp + ldrsw x9, [x8, :lo12:sp] + adrp x8, data + add x8, x8, :lo12:data + ldr w0, [x8, x9, lsl #2] + bl push + ldp x29, x30, [sp], #16 // 16-byte Folded Reload + ret +// ------------------------------------------------------------- +dr: + adrp x9, sp + ldrsw x11, [x9, :lo12:sp] + adrp x10, data + add x10, x10, :lo12:data + mov w8, wzr + str w8, [x10, x11, lsl #2] + ldr w8, [x9, :lo12:sp] + subs w8, w8, #1 + str w8, [x9, :lo12:sp] + ret +// ------------------------------------------------------------- +sw: + adrp x10, sp + ldrsw x8, [x10, :lo12:sp] + adrp x9, data + add x9, x9, :lo12:data + ldr w11, [x9, x8, lsl #2] + adrp x8, a + str w11, [x8, :lo12:a] + ldr w11, [x10, :lo12:sp] + subs w11, w11, #1 + ldr w11, [x9, w11, sxtw #2] + ldrsw x12, [x10, :lo12:sp] + str w11, [x9, x12, lsl #2] + ldr w8, [x8, :lo12:a] + ldr w10, [x10, :lo12:sp] + subs w10, w10, #1 + str w8, [x9, w10, sxtw #2] + ret +// ------------------------------------------------------------- +pu: + sub sp, sp, #32 + stp x29, x30, [sp, #16] // 16-byte Folded Spill + add x29, sp, #16 + adrp x9, rp + str x9, [sp, #8] // 8-byte Folded Spill + ldr w8, [x9, :lo12:rp] + add w8, w8, #1 + str w8, [x9, :lo12:rp] + bl pop + ldr x8, [sp, #8] // 8-byte Folded Reload + ldrsw x9, [x8, :lo12:rp] + adrp x8, address + add x8, x8, :lo12:address + str w0, [x8, x9, lsl #2] + ldp x29, x30, [sp, #16] // 16-byte Folded Reload + add sp, sp, #32 + ret +// ------------------------------------------------------------- +po: + sub sp, sp, #32 + stp x29, x30, [sp, #16] // 16-byte Folded Spill + add x29, sp, #16 + adrp x8, rp + str x8, [sp, #8] // 8-byte Folded Spill + ldrsw x9, [x8, :lo12:rp] + adrp x8, address + add x8, x8, :lo12:address + ldr w0, [x8, x9, lsl #2] + bl push + ldr x9, [sp, #8] // 8-byte Folded Reload + ldr w8, [x9, :lo12:rp] + subs w8, w8, #1 + str w8, [x9, :lo12:rp] + ldp x29, x30, [sp, #16] // 16-byte Folded Reload + add sp, sp, #32 + ret +// ------------------------------------------------------------- +ju: + stp x29, x30, [sp, #-16]! // 16-byte Folded Spill + mov x29, sp + bl pop + subs w8, w0, #1 + adrp x9, ip + str w8, [x9, :lo12:ip] + ldp x29, x30, [sp], #16 // 16-byte Folded Reload + ret +// ------------------------------------------------------------- +ca: + stp x29, x30, [sp, #-16]! // 16-byte Folded Spill + mov x29, sp + bl save_ip + bl pop + subs w8, w0, #1 + adrp x9, ip + str w8, [x9, :lo12:ip] + ldp x29, x30, [sp], #16 // 16-byte Folded Reload + ret +// ------------------------------------------------------------- +cc: + stp x29, x30, [sp, #-16]! // 16-byte Folded Spill + mov x29, sp + bl pop + adrp x8, t + str w0, [x8, :lo12:t] + bl pop + subs w8, w0, #0 + cset w8, eq + tbnz w8, #0, .cc_skip_call +// if true + bl save_ip + adrp x8, t + ldr w8, [x8, :lo12:t] + subs w8, w8, #1 + adrp x9, ip + str w8, [x9, :lo12:ip] +.cc_skip_call: + ldp x29, x30, [sp], #16 // 16-byte Folded Reload + ret +// ------------------------------------------------------------- +cj: + stp x29, x30, [sp, #-16]! // 16-byte Folded Spill + mov x29, sp + bl pop + adrp x8, t + str w0, [x8, :lo12:t] + bl pop + subs w8, w0, #0 + cset w8, eq + tbnz w8, #0, .cj_done // flag is false, skip branch + // if flag is true + adrp x8, t + ldr w8, [x8, :lo12:t] + subs w8, w8, #1 + adrp x9, ip + str w8, [x9, :lo12:ip] +.cj_done: + ldp x29, x30, [sp], #16 // 16-byte Folded Reload + ret +// ------------------------------------------------------------- +re: + adrp x9, rp + ldrsw x10, [x9, :lo12:rp] + adrp x8, address + add x8, x8, :lo12:address + ldr w8, [x8, x10, lsl #2] + adrp x10, ip + str w8, [x10, :lo12:ip] + ldr w8, [x9, :lo12:rp] + subs w8, w8, #1 + str w8, [x9, :lo12:rp] + ret +// ------------------------------------------------------------- +eq: + adrp x9, sp + ldr w8, [x9, :lo12:sp] + subs w8, w8, #1 + adrp x10, data + add x10, x10, :lo12:data + ldr w8, [x10, w8, sxtw #2] + ldrsw x11, [x9, :lo12:sp] + ldr w11, [x10, x11, lsl #2] + subs w8, w8, w11 + cset w8, eq + and w11, w8, #0x1 + mov w8, wzr + ands w11, w11, #0x1 + csinv w8, w8, wzr, eq + ldr w11, [x9, :lo12:sp] + subs w11, w11, #1 + str w8, [x10, w11, sxtw #2] + ldr w8, [x9, :lo12:sp] + subs w8, w8, #1 + str w8, [x9, :lo12:sp] + ret +// ------------------------------------------------------------- +ne: + adrp x9, sp + ldr w8, [x9, :lo12:sp] + subs w8, w8, #1 + adrp x10, data + add x10, x10, :lo12:data + ldr w8, [x10, w8, sxtw #2] + ldrsw x11, [x9, :lo12:sp] + ldr w11, [x10, x11, lsl #2] + subs w8, w8, w11 + cset w8, ne + and w11, w8, #0x1 + mov w8, wzr + ands w11, w11, #0x1 + csinv w8, w8, wzr, eq + ldr w11, [x9, :lo12:sp] + subs w11, w11, #1 + str w8, [x10, w11, sxtw #2] + ldr w8, [x9, :lo12:sp] + subs w8, w8, #1 + str w8, [x9, :lo12:sp] + ret +// ------------------------------------------------------------- +lt: // @lt + adrp x9, sp + ldr w8, [x9, :lo12:sp] + subs w8, w8, #1 + adrp x10, data + add x10, x10, :lo12:data + ldr w8, [x10, w8, sxtw #2] + ldrsw x11, [x9, :lo12:sp] + ldr w11, [x10, x11, lsl #2] + subs w8, w8, w11 + cset w8, lt + and w11, w8, #0x1 + mov w8, wzr + ands w11, w11, #0x1 + csinv w8, w8, wzr, eq + ldr w11, [x9, :lo12:sp] + subs w11, w11, #1 + str w8, [x10, w11, sxtw #2] + ldr w8, [x9, :lo12:sp] + subs w8, w8, #1 + str w8, [x9, :lo12:sp] + ret +// ------------------------------------------------------------- +gt: + adrp x9, sp + ldr w8, [x9, :lo12:sp] + subs w8, w8, #1 + adrp x10, data + add x10, x10, :lo12:data + ldr w8, [x10, w8, sxtw #2] + ldrsw x11, [x9, :lo12:sp] + ldr w11, [x10, x11, lsl #2] + subs w8, w8, w11 + cset w8, gt + and w11, w8, #0x1 + mov w8, wzr + ands w11, w11, #0x1 + csinv w8, w8, wzr, eq + ldr w11, [x9, :lo12:sp] + subs w11, w11, #1 + str w8, [x10, w11, sxtw #2] + ldr w8, [x9, :lo12:sp] + subs w8, w8, #1 + str w8, [x9, :lo12:sp] + ret +// ------------------------------------------------------------- +fe: + adrp x10, sp + ldrsw x8, [x10, :lo12:sp] + adrp x9, data + add x9, x9, :lo12:data + ldrsw x11, [x9, x8, lsl #2] + adrp x8, m + add x8, x8, :lo12:m + ldr w8, [x8, x11, lsl #2] + ldrsw x10, [x10, :lo12:sp] + str w8, [x9, x10, lsl #2] + ret +// ------------------------------------------------------------- +st: + adrp x9, sp + ldr w8, [x9, :lo12:sp] + subs w8, w8, #1 + adrp x10, data + add x10, x10, :lo12:data + ldr w8, [x10, w8, sxtw #2] + ldrsw x11, [x9, :lo12:sp] + ldrsw x11, [x10, x11, lsl #2] + adrp x10, m + add x10, x10, :lo12:m + str w8, [x10, x11, lsl #2] + ldr w8, [x9, :lo12:sp] + subs w8, w8, #2 + str w8, [x9, :lo12:sp] + ret +// ------------------------------------------------------------- +ad: + adrp x9, sp + ldrsw x10, [x9, :lo12:sp] + adrp x8, data + add x8, x8, :lo12:data + ldr w11, [x8, x10, lsl #2] + ldr w10, [x9, :lo12:sp] + subs w10, w10, #1 + add x10, x8, w10, sxtw #2 + ldr w8, [x10] + add w8, w8, w11 + str w8, [x10] + ldr w8, [x9, :lo12:sp] + subs w8, w8, #1 + str w8, [x9, :lo12:sp] + ret +// ------------------------------------------------------------- +su: + adrp x9, sp + ldrsw x10, [x9, :lo12:sp] + adrp x8, data + add x8, x8, :lo12:data + ldr w11, [x8, x10, lsl #2] + ldr w10, [x9, :lo12:sp] + subs w10, w10, #1 + add x10, x8, w10, sxtw #2 + ldr w8, [x10] + subs w8, w8, w11 + str w8, [x10] + ldr w8, [x9, :lo12:sp] + subs w8, w8, #1 + str w8, [x9, :lo12:sp] + ret +// ------------------------------------------------------------- +mu: + adrp x9, sp + ldrsw x10, [x9, :lo12:sp] + adrp x8, data + add x8, x8, :lo12:data + ldr w11, [x8, x10, lsl #2] + ldr w10, [x9, :lo12:sp] + subs w10, w10, #1 + add x10, x8, w10, sxtw #2 + ldr w8, [x10] + mul w8, w8, w11 + str w8, [x10] + ldr w8, [x9, :lo12:sp] + subs w8, w8, #1 + str w8, [x9, :lo12:sp] + ret +// ------------------------------------------------------------- +di: + adrp x10, sp + ldrsw x8, [x10, :lo12:sp] + adrp x9, data + add x9, x9, :lo12:data + ldr w8, [x9, x8, lsl #2] + adrp x11, a + str w8, [x11, :lo12:a] + ldr w8, [x10, :lo12:sp] + subs w8, w8, #1 + ldr w12, [x9, w8, sxtw #2] + adrp x8, b + str w12, [x8, :lo12:b] + ldr w12, [x8, :lo12:b] + ldr w13, [x11, :lo12:a] + sdiv w12, w12, w13 + ldrsw x13, [x10, :lo12:sp] + str w12, [x9, x13, lsl #2] + ldr w8, [x8, :lo12:b] + ldr w12, [x11, :lo12:a] + sdiv w11, w8, w12 + mul w11, w11, w12 + subs w8, w8, w11 + ldr w10, [x10, :lo12:sp] + subs w10, w10, #1 + str w8, [x9, w10, sxtw #2] + ret +// ------------------------------------------------------------- +an: + adrp x9, sp + ldrsw x8, [x9, :lo12:sp] + adrp x10, data + add x10, x10, :lo12:data + ldr w8, [x10, x8, lsl #2] + ldr w11, [x9, :lo12:sp] + subs w11, w11, #1 + ldr w11, [x10, w11, sxtw #2] + and w8, w8, w11 + ldr w11, [x9, :lo12:sp] + subs w11, w11, #1 + str w8, [x10, w11, sxtw #2] + ldr w8, [x9, :lo12:sp] + subs w8, w8, #1 + str w8, [x9, :lo12:sp] + ret +// ------------------------------------------------------------- +or: + adrp x9, sp + ldrsw x8, [x9, :lo12:sp] + adrp x10, data + add x10, x10, :lo12:data + ldr w8, [x10, x8, lsl #2] + ldr w11, [x9, :lo12:sp] + subs w11, w11, #1 + ldr w11, [x10, w11, sxtw #2] + orr w8, w8, w11 + ldr w11, [x9, :lo12:sp] + subs w11, w11, #1 + str w8, [x10, w11, sxtw #2] + ldr w8, [x9, :lo12:sp] + subs w8, w8, #1 + str w8, [x9, :lo12:sp] + ret +// ------------------------------------------------------------- +xo: + adrp x9, sp + ldrsw x8, [x9, :lo12:sp] + adrp x10, data + add x10, x10, :lo12:data + ldr w8, [x10, x8, lsl #2] + ldr w11, [x9, :lo12:sp] + subs w11, w11, #1 + ldr w11, [x10, w11, sxtw #2] + eor w8, w8, w11 + ldr w11, [x9, :lo12:sp] + subs w11, w11, #1 + str w8, [x10, w11, sxtw #2] + ldr w8, [x9, :lo12:sp] + subs w8, w8, #1 + str w8, [x9, :lo12:sp] + ret +// ------------------------------------------------------------- +sl: + adrp x9, sp + ldr w8, [x9, :lo12:sp] + subs w8, w8, #1 + adrp x10, data + add x10, x10, :lo12:data + ldr w8, [x10, w8, sxtw #2] + ldrsw x11, [x9, :lo12:sp] + ldr w11, [x10, x11, lsl #2] + lsl w8, w8, w11 + ldr w11, [x9, :lo12:sp] + subs w11, w11, #1 + str w8, [x10, w11, sxtw #2] + ldr w8, [x9, :lo12:sp] + subs w8, w8, #1 + str w8, [x9, :lo12:sp] + ret +// ------------------------------------------------------------- +sr: + adrp x9, sp + ldr w8, [x9, :lo12:sp] + subs w8, w8, #1 + adrp x10, data + add x10, x10, :lo12:data + ldr w8, [x10, w8, sxtw #2] + ldrsw x11, [x9, :lo12:sp] + ldr w11, [x10, x11, lsl #2] + asr w8, w8, w11 + ldr w11, [x9, :lo12:sp] + subs w11, w11, #1 + str w8, [x10, w11, sxtw #2] + ldr w8, [x9, :lo12:sp] + subs w8, w8, #1 + str w8, [x9, :lo12:sp] + ret +// ------------------------------------------------------------- +cp: + stp x29, x30, [sp, #-16]! // 16-byte Folded Spill + mov x29, sp + bl pop + adrp x8, len + str w0, [x8, :lo12:len] + bl pop + adrp x8, dest + str w0, [x8, :lo12:dest] + bl pop + adrp x8, src + str w0, [x8, :lo12:src] + mov w0, #-1 + bl push +// b .LBB35_1 +.LBB35_1: // =>This Inner Loop Header: Depth=1 + adrp x8, len + ldr w8, [x8, :lo12:len] + subs w8, w8, #0 + cset w8, eq + tbnz w8, #0, .LBB35_5 +// b .LBB35_2 +.LBB35_2: // in Loop: Header=BB35_1 Depth=1 + adrp x8, dest + ldrsw x8, [x8, :lo12:dest] + adrp x9, m + add x9, x9, :lo12:m + ldr w8, [x9, x8, lsl #2] + adrp x10, src + ldrsw x10, [x10, :lo12:src] + ldr w9, [x9, x10, lsl #2] + subs w8, w8, w9 + cset w8, eq + tbnz w8, #0, .LBB35_4 +// b .LBB35_3 +.LBB35_3: // in Loop: Header=BB35_1 Depth=1 + adrp x8, sp + ldrsw x10, [x8, :lo12:sp] + adrp x9, data + add x9, x9, :lo12:data + mov w8, wzr + str w8, [x9, x10, lsl #2] +// b .LBB35_4 +.LBB35_4: // in Loop: Header=BB35_1 Depth=1 + adrp x9, len + ldr w8, [x9, :lo12:len] + subs w8, w8, #1 + str w8, [x9, :lo12:len] + adrp x9, src + ldr w8, [x9, :lo12:src] + add w8, w8, #1 + str w8, [x9, :lo12:src] + adrp x9, dest + ldr w8, [x9, :lo12:dest] + add w8, w8, #1 + str w8, [x9, :lo12:dest] + b .LBB35_1 +.LBB35_5: + ldp x29, x30, [sp], #16 // 16-byte Folded Reload + ret +// ------------------------------------------------------------- +cy: + stp x29, x30, [sp, #-16]! // 16-byte Folded Spill + mov x29, sp + bl pop + adrp x8, len + str w0, [x8, :lo12:len] + bl pop + adrp x8, dest + str w0, [x8, :lo12:dest] + bl pop + adrp x8, src + str w0, [x8, :lo12:src] +// b .LBB36_1 +.LBB36_1: // =>This Inner Loop Header: Depth=1 + adrp x8, len + ldr w8, [x8, :lo12:len] + subs w8, w8, #0 + cset w8, eq + tbnz w8, #0, .LBB36_3 +// b .LBB36_2 +.LBB36_2: // in Loop: Header=BB36_1 Depth=1 + adrp x10, src + ldrsw x8, [x10, :lo12:src] + adrp x11, m + add x11, x11, :lo12:m + ldr w8, [x11, x8, lsl #2] + adrp x9, dest + ldrsw x12, [x9, :lo12:dest] + str w8, [x11, x12, lsl #2] + adrp x11, len + ldr w8, [x11, :lo12:len] + subs w8, w8, #1 + str w8, [x11, :lo12:len] + ldr w8, [x10, :lo12:src] + add w8, w8, #1 + str w8, [x10, :lo12:src] + ldr w8, [x9, :lo12:dest] + add w8, w8, #1 + str w8, [x9, :lo12:dest] + b .LBB36_1 +.LBB36_3: + ldp x29, x30, [sp], #16 // 16-byte Folded Reload + ret +// ------------------------------------------------------------- +io: + sub sp, sp, #32 + stp x29, x30, [sp, #16] // 16-byte Folded Spill + add x29, sp, #16 + bl pop + subs w8, w0, #0 + // kill: def $x8 killed $w8 + str x8, [sp, #8] // 8-byte Folded Spill + subs x8, x8, #7 + cset w8, hi + tbnz w8, #0, .LBB37_10 + + ldr x11, [sp, #8] // 8-byte Folded Reload + adrp x10, .LJTI37_0 + add x10, x10, :lo12:.LJTI37_0 +.Ltmp1: + adr x8, .Ltmp1 + ldrsw x9, [x10, x11, lsl #2] + add x8, x8, x9 + br x8 +.LBB37_2: + bl pop + adrp x8, iob + adrp x1, iob + add x1, x1, :lo12:iob + strb w0, [x8, :lo12:iob] + mov w0, #1 + mov x2, #1 + bl os_write + b .LBB37_11 +.LBB37_3: + mov w0, wzr + adrp x8, iob + str x8, [sp] // 8-byte Folded Spill + adrp x1, iob + add x1, x1, :lo12:iob + mov x2, #1 + bl os_read + ldr x8, [sp] // 8-byte Folded Reload + ldrb w0, [x8, :lo12:iob] + bl push + b .LBB37_11 +.LBB37_4: + bl read_block + b .LBB37_11 +.LBB37_5: + bl write_block + b .LBB37_11 +.LBB37_6: + bl save_image + b .LBB37_11 +.LBB37_7: + bl load_image + mov w8, #-1 + adrp x9, ip + str w8, [x9, :lo12:ip] + b .LBB37_11 +.LBB37_8: + adrp x9, ip + mov w8, #65536 + str w8, [x9, :lo12:ip] + b .LBB37_11 +.LBB37_9: + adrp x8, sp + ldr w0, [x8, :lo12:sp] + bl push + adrp x8, rp + ldr w0, [x8, :lo12:rp] + bl push + b .LBB37_11 +.LBB37_10: + b .LBB37_11 +.LBB37_11: + ldp x29, x30, [sp, #16] // 16-byte Folded Reload + add sp, sp, #32 + ret +.LJTI37_0: + .word .LBB37_2-.Ltmp1 + .word .LBB37_3-.Ltmp1 + .word .LBB37_4-.Ltmp1 + .word .LBB37_5-.Ltmp1 + .word .LBB37_6-.Ltmp1 + .word .LBB37_7-.Ltmp1 + .word .LBB37_8-.Ltmp1 + .word .LBB37_9-.Ltmp1 +// ------------------------------------------------------------- +process: + sub sp, sp, #32 + stp x29, x30, [sp, #16] // 16-byte Folded Spill + add x29, sp, #16 + stur w0, [x29, #-4] + ldur w8, [x29, #-4] + subs w8, w8, #0 + // kill: def $x8 killed $w8 + str x8, [sp] // 8-byte Folded Spill + subs x8, x8, #29 + cset w8, hi + tbnz w8, #0, .LBB38_32 + + ldr x11, [sp] // 8-byte Folded Reload + adrp x10, .LJTI38_0 + add x10, x10, :lo12:.LJTI38_0 +.Ltmp2: + adr x8, .Ltmp2 + ldrsw x9, [x10, x11, lsl #2] + add x8, x8, x9 + br x8 +.LBB38_2: b .LBB38_33 +.LBB38_3: b li +.LBB38_4: b du +.LBB38_5: b dr +.LBB38_6: b sw +.LBB38_7: b pu +.LBB38_8: b po +.LBB38_9: b ju +.LBB38_10: b ca +.LBB38_11: b cc +.LBB38_12: b cj +.LBB38_13: b re +.LBB38_14: b eq +.LBB38_15: b ne +.LBB38_16: b lt +.LBB38_17: b gt +.LBB38_18: b fe +.LBB38_19: b st +.LBB38_20: b ad +.LBB38_21: b su +.LBB38_22: b mu +.LBB38_23: b di +.LBB38_24: b an +.LBB38_25: b or +.LBB38_26: b xo +.LBB38_27: b sl +.LBB38_28: b sr +.LBB38_29: b cp +.LBB38_30: b cy +.LBB38_31: b io +.LBB38_32: b .LBB38_33 +.LBB38_33: + ldp x29, x30, [sp, #16] // 16-byte Folded Reload + add sp, sp, #32 + ret + +.LJTI38_0: + .word .LBB38_2-.Ltmp2 + .word .LBB38_3-.Ltmp2 + .word .LBB38_4-.Ltmp2 + .word .LBB38_5-.Ltmp2 + .word .LBB38_6-.Ltmp2 + .word .LBB38_7-.Ltmp2 + .word .LBB38_8-.Ltmp2 + .word .LBB38_9-.Ltmp2 + .word .LBB38_10-.Ltmp2 + .word .LBB38_11-.Ltmp2 + .word .LBB38_12-.Ltmp2 + .word .LBB38_13-.Ltmp2 + .word .LBB38_14-.Ltmp2 + .word .LBB38_15-.Ltmp2 + .word .LBB38_16-.Ltmp2 + .word .LBB38_17-.Ltmp2 + .word .LBB38_18-.Ltmp2 + .word .LBB38_19-.Ltmp2 + .word .LBB38_20-.Ltmp2 + .word .LBB38_21-.Ltmp2 + .word .LBB38_22-.Ltmp2 + .word .LBB38_23-.Ltmp2 + .word .LBB38_24-.Ltmp2 + .word .LBB38_25-.Ltmp2 + .word .LBB38_26-.Ltmp2 + .word .LBB38_27-.Ltmp2 + .word .LBB38_28-.Ltmp2 + .word .LBB38_29-.Ltmp2 + .word .LBB38_30-.Ltmp2 + .word .LBB38_31-.Ltmp2 + +process_bundle: + sub sp, sp, #32 + stp x29, x30, [sp, #16] // 16-byte Folded Spill + add x29, sp, #16 + stur w0, [x29, #-4] + ldurb w0, [x29, #-4] + bl process + + ldur w8, [x29, #-4] + asr w8, w8, #8 + and w0, w8, #0xff + bl process + + ldur w8, [x29, #-4] + asr w8, w8, #16 + and w0, w8, #0xff + bl process + + ldur w8, [x29, #-4] + asr w8, w8, #24 + and w0, w8, #0xff + bl process + + ldp x29, x30, [sp, #16] // 16-byte Folded Reload + add sp, sp, #32 + ret +// ------------------------------------------------------------- +execute: + sub sp, sp, #32 + stp x29, x30, [sp, #16] // 16-byte Folded Spill + add x29, sp, #16 +// b .LBB40_1 +.LBB40_1: // =>This Inner Loop Header: Depth=1 + adrp x8, ip + ldr w8, [x8, :lo12:ip] + subs w8, w8, #16, lsl #12 // =65536 + cset w8, ge + tbnz w8, #0, .LBB40_3 +// b .LBB40_2 +.LBB40_2: // in Loop: Header=BB40_1 Depth=1 + adrp x8, ip + str x8, [sp, #8] // 8-byte Folded Spill + ldrsw x9, [x8, :lo12:ip] + adrp x8, m + add x8, x8, :lo12:m + ldr w0, [x8, x9, lsl #2] + bl process_bundle + ldr x9, [sp, #8] // 8-byte Folded Reload + ldr w8, [x9, :lo12:ip] + add w8, w8, #1 + str w8, [x9, :lo12:ip] + b .LBB40_1 +.LBB40_3: + ldp x29, x30, [sp, #16] // 16-byte Folded Reload + add sp, sp, #32 + ret +// ------------------------------------------------------------- +_start: + sub sp, sp, #32 + stp x29, x30, [sp, #16] // 16-byte Folded Spill + add x29, sp, #16 + stur w0, [x29, #-4] + str x1, [sp] + adrp x9, blocks + adrp x8, .blocks_name + add x8, x8, :lo12:.blocks_name + str x8, [x9, :lo12:blocks] + adrp x9, rom + adrp x8, .rom_name + add x8, x8, :lo12:.rom_name + str x8, [x9, :lo12:rom] + bl load_image + bl execute +// mov w0, wzr +// ldp x29, x30, [sp, #16] // 16-byte Folded Reload +// add sp, sp, #32 + b os_exit + +// ------------------------------------------------------------- +.blocks_name: .asciz "ilo.blocks" +.rom_name: .asciz "ilo.rom" +// ------------------------------------------------------------- + .bss + +sp: .word 0 // stack pointer +data: .zero 132 // data stack +rp: .word 0 // address pointer +address:.zero 1028 // address stack +ip: .word 0 // instruction pointer +m: .zero 262144 // memory + +fp: .word 0 // file id +buffer: .word 0 // address of block buffer +block: .word 0 // block number to read/write +a: .word 0 // scratch +t: .word 0 // scratch +b: .word 0 // scratch +len: .word 0 // scratch +dest: .word 0 // scratch +src: .word 0 // scratch +iob: .zero 2 // io buffr + + .p2align 3 +rom: .xword 0 // file name for rom + .p2align 3 +blocks: .xword 0 // file name for blocks diff --git a/source/ilo-amd64-dragonfly.s b/source/ilo-amd64-dragonfly.s new file mode 100644 index 0000000..04f0754 --- /dev/null +++ b/source/ilo-amd64-dragonfly.s @@ -0,0 +1,422 @@ +/* AMD64 ilo, (c) 2023 Christopher Leonard, MIT License */ + +/* cc -c ilo-amd64-freebsd.s -o ilo.o + ld -nostdlib ilo.o -o ilo +*/ + .global _start + + /* rax: top of stack */ + /* rbx: data stack */ + /* rbp: jump table address */ + /* r12: address stack */ + /* r13: instruction pointer */ + /* r14: opcode shift register */ + /* r15: memory */ + + .bss + + .align 8 +blocks: .skip 8 /* name of blocks file (ilo.blocks) */ +rom: .skip 8 /* name of image (ilo.rom) */ +dstack: .skip 32*4 +astack: .skip 256*4 +a: .skip 4 /* other variables for misc. purposes */ +b: .skip 4 +f: .skip 4 +s: .skip 4 +d: .skip 4 +l: .skip 4 +memory: .skip 65536*4 + + .section .rodata + +default_blocks: + .asciz "ilo.blocks" +default_rom: + .asciz "ilo.rom" + +io_table: + .byte 0 + .byte iob-ioa + .byte ioc-ioa + .byte iod-ioa + .byte ioe-ioa + .byte iof-ioa + .byte iog-ioa + .byte ioh-ioa + + .text + +dosys: push %r8 + push %r9 + push %r10 + push %r11 + push %rdx + syscall + pop %rdx + pop %r11 + pop %r10 + pop %r9 + pop %r8 + ret + +rdonly: mov $5, %eax /* sys_open */ + xor %esi, %esi /* O_RDONLY */ + mov $0666, %edx + call dosys + mov %eax, %edi + ret + +wronly: mov $5, %eax /* sys_open */ + mov $1, %esi /* O_WRONLY */ + mov $0666, %edx + call dosys + mov %eax, %edi + ret + +close: mov $6, %eax /* sys_close */ + call dosys + ret + +load_image: + mov rom(%rip), %rdi + call rdonly + or %eax, %eax + jz 1f + mov %r15, %rsi + mov $65536 * 4, %edx + mov $3, %eax /* sys_read */ + call dosys + call close + xor %eax, %eax + lea dstack-4(%rip), %rbx + lea astack-4(%rip), %r12 + xor %r13d, %r13d +1: ret + +save_image: + push %rax + mov rom(%rip), %rdi + call wronly + or %eax, %eax + jz 1f + mov %r15, %rsi + mov $65536 * 4, %edx + mov $4, %eax + call dosys + call close +1: pop %rax + ret + +block_common: + mov $199, %eax /* sys_lseek */ + mov (%rbx), %edx + shl $12, %edx + //xor %edx, %edx /* SEEK_SET */ + call dosys + mov $3, %eax /* sys_read */ + or %r10b, %r10b + jz 1f + mov $4, %al /* sys_write */ +1: lea (%r15,%r8,4), %rsi + mov $4096, %edx + call dosys + mov -4(%rbx), %esi + sub $8, %rbx + ret + + .align 32 +table: ret + .align 32 +li: add $4, %rbx + inc %r13d + mov %eax, (%rbx) + mov (%r15,%r13,4), %eax + ret + .align 32 +du: add $4, %rbx + mov %eax, (%rbx) + ret + .align 32 +dr: mov (%rbx), %eax + sub $4, %rbx + ret + .align 32 +sw: xchg (%rbx), %eax + ret + .align 32 +pu: add $4, %r12 + mov %eax, (%r12) + mov (%rbx), %eax + sub $4, %rbx + ret + .align 32 +po: add $4, %rbx + mov %eax, (%rbx) + mov (%r12), %eax + sub $4, %r12 + ret + .align 32 +ju: lea -1(%eax), %r13d + mov (%rbx), %eax + sub $4, %rbx + ret + .align 32 +ca: add $4, %r12 + mov %r13d, (%r12) + lea -1(%eax), %r13d + mov (%rbx), %eax + sub $4, %rbx + ret + .align 32 +cc: cmpl $0, (%rbx) + jz 1f + add $4, %r12 + mov %r13d, (%r12) + lea -1(%eax), %r13d +1: mov -4(%rbx), %eax + sub $8, %rbx + ret + .align 32 +cj: cmpl $0, (%rbx) + jz 1f + lea -1(%eax), %r13d +1: mov -4(%rbx), %eax + sub $8, %rbx + ret + .align 32 +re: mov (%r12), %r13d + sub $4, %r12 + ret + .align 32 +eq: cmp %eax, (%rbx) + sete %al + movzbl %al, %eax + neg %eax + sub $4, %rbx + ret + .align 32 +ne: cmp %eax, (%rbx) + setne %al + movzbl %al, %eax + neg %eax + sub $4, %rbx + ret + .align 32 +lt: cmp %eax, (%rbx) + setl %al + movzbl %al, %eax + neg %eax + sub $4, %rbx + ret + .align 32 +gt: cmp %eax, (%rbx) + setg %al + movzbl %al, %eax + neg %eax + sub $4, %rbx + ret + .align 32 +fe: mov (%r15,%rax,4), %eax + ret + .align 32 +st: mov (%rbx), %ecx + mov %ecx, (%r15,%rax,4) + mov -4(%rbx), %eax + sub $8, %rbx + ret + .align 32 +ad: add (%rbx), %eax + sub $4, %rbx + ret + .align 32 +su: sub (%rbx), %eax + neg %eax + sub $4, %rbx + ret + .align 32 +mu: mull (%rbx) + sub $4, %rbx + ret + .align 32 +di: mov %eax, %ecx + mov (%rbx), %eax + cdq + idiv %ecx + mov %edx, (%rbx) + ret + .align 32 +an: and (%rbx), %eax + sub $4, %rbx + ret + .align 32 +or: or (%rbx), %eax + sub $4, %rbx + ret + .align 32 +xo: xor (%rbx), %eax + sub $4, %rbx + ret + .align 32 +sl: mov %eax, %ecx + mov (%rbx), %eax + sub $4, %rbx + shl %cl, %eax + ret + .align 32 +sr: mov %eax, %ecx + mov (%rbx), %eax + sub $4, %rbx + sar %cl, %eax + ret + .align 32 +cp: mov %eax, %ecx + mov (%rbx), %edi + mov -4(%rbx), %esi + sub $8, %rbx + lea (%r15,%rdi,4), %rdi + lea (%r15,%rsi,4), %rsi + cmp %eax, %eax + .byte 0xF3, 0xA7 /* repe cmpsd */ + sete %al + movzbl %al, %eax + neg %eax + ret + .align 32 +cy: mov %eax, %ecx + mov (%rbx), %edi + mov -4(%rbx), %esi + mov -8(%rbx), %eax + sub $12, %rbx + lea (%r15,%rdi,4), %rdi + lea (%r15,%rsi,4), %rsi + repe movsd + ret + .align 32 +io: mov %eax, %ecx + mov (%rbx), %eax + sub $4, %rbx + cmp $7, %ecx + ja 1f + lea io_table(%rip), %rdx + movzbl (%rdx,%rcx), %ecx + lea ioa(%rip), %rdx + add %rdx, %rcx + jmp *%rcx +1: ret + +ioa: push %rax + mov $4, %eax /* sys_write */ + mov $1, %edi + mov %rsp, %rsi + mov $1, %edx + call dosys + pop %rax + mov (%rbx), %eax + sub $4, %rbx + ret +iob: add $4, %rbx + mov %eax, (%rbx) + mov $3, %eax /* sys_read */ + push %rax + xor %edi, %edi + mov %rsp, %rsi + mov $1, %edx + call dosys + pop %rax + ret +ioc: mov %eax, %r8d + mov blocks(%rip), %rdi + call rdonly + xor %r10d, %r10d + call block_common + call close + mov %esi, %eax + ret +iod: mov %eax, %r8d + mov blocks(%rip), %rdi + call wronly + mov $1, %r10b + call block_common + call close + mov %esi, %eax + ret +ioe: jmp save_image +iof: call load_image + xor %rax, %rax + xor %r13, %r13 + jmp _execute +iog: mov $65536, %r13d + ret +ioh: add $8, %rbx + mov %eax, -4(%rbx) + lea astack-4(%rip), %rdx + neg %edx + lea 4*32-8(%rbx,%rdx), %rax + shr $2, %eax + mov %eax, (%rbx) + lea (%r12,%rdx), %rax + shr $2, %eax + ret + +_start: xor %eax, %eax + add $8, %rsp + lea memory(%rip), %r15 + lea dstack-4(%rip), %rbx + lea astack-4(%rip), %r12 + xor %r13d, %r13d + lea table(%rip), %rbp + mov 8(%rsp), %rcx + or %rcx, %rcx + jz 1f + mov 16(%rsp), %rcx + or %rcx, %rcx + jz 1f + mov %rcx, blocks(%rip) + mov 24(%rsp), %rcx + or %rcx, %rcx + jz 2f + mov %rcx, rom(%rip) + jmp 3f +1: lea default_blocks(%rip), %rcx + mov %rcx, blocks(%rip) +2: lea default_rom(%rip), %rcx + mov %rcx, rom(%rip) +3: call load_image +_execute: + jmp 3f + .align 64 +2: mov (%r15,%r13,4), %r14d + movzbl %r14b, %edi + shr $8, %r14d + cmp $29, %edi + ja 1f + shl $5, %edi + add %rbp, %rdi + call *%rdi +1: movzbl %r14b, %edi + shr $8, %r14d + cmp $29, %edi + ja 1f + shl $5, %edi + add %rbp, %rdi + call *%rdi +1: movzbl %r14b, %edi + shr $8, %r14d + cmp $29, %edi + ja 1f + shl $5, %edi + add %rbp, %rdi + call *%rdi +1: mov %r14d, %edi + cmp $29, %edi + ja 1f + shl $5, %edi + add %rbp, %rdi + call *%rdi +1: inc %r13 +3: cmp $65536, %r13 + jl 2b + mov $1, %eax /* sys_exit */ + xor %edi, %edi + call dosys diff --git a/source/ilo-amd64-freebsd.s b/source/ilo-amd64-freebsd.s new file mode 100644 index 0000000..f0297a1 --- /dev/null +++ b/source/ilo-amd64-freebsd.s @@ -0,0 +1,420 @@ +/* AMD64 ilo, (c) 2023 Christopher Leonard, MIT License */ + +/* cc -c ilo-amd64-freebsd.s -o ilo.o + ld -nostdlib ilo.o -o ilo +*/ + .global _start + + /* rax: top of stack */ + /* rbx: data stack */ + /* rbp: jump table address */ + /* r12: address stack */ + /* r13: instruction pointer */ + /* r14: opcode shift register */ + /* r15: memory */ + + .bss + + .align 8 +blocks: .skip 8 /* name of blocks file (ilo.blocks) */ +rom: .skip 8 /* name of image (ilo.rom) */ +dstack: .skip 32*4 +astack: .skip 256*4 +a: .skip 4 /* other variables for misc. purposes */ +b: .skip 4 +f: .skip 4 +s: .skip 4 +d: .skip 4 +l: .skip 4 +memory: .skip 65536*4 + + .section .rodata + +default_blocks: + .asciz "ilo.blocks" +default_rom: + .asciz "ilo.rom" + +io_table: + .byte 0 + .byte iob-ioa + .byte ioc-ioa + .byte iod-ioa + .byte ioe-ioa + .byte iof-ioa + .byte iog-ioa + .byte ioh-ioa + + .text + +dosys: push %r8 + push %r9 + push %r10 + push %rdx + syscall + pop %rdx + pop %r10 + pop %r9 + pop %r8 + ret + +rdonly: mov $5, %eax /* sys_open */ + xor %esi, %esi /* O_RDONLY */ + mov $0666, %edx + call dosys + mov %eax, %edi + ret + +wronly: mov $5, %eax /* sys_open */ + mov $1, %esi /* O_WRONLY */ + mov $0666, %edx + call dosys + mov %eax, %edi + ret + +close: mov $6, %eax /* sys_close */ + call dosys + ret + +load_image: + mov rom(%rip), %rdi + call rdonly + or %eax, %eax + jz 1f + mov %r15, %rsi + mov $65536 * 4, %edx + mov $3, %eax /* sys_read */ + call dosys + call close + xor %eax, %eax + lea dstack-4(%rip), %rbx + lea astack-4(%rip), %r12 + xor %r13d, %r13d +1: ret + +save_image: + push %rax + mov rom(%rip), %rdi + call wronly + or %eax, %eax + jz 1f + mov %r15, %rsi + mov $65536 * 4, %edx + mov $4, %eax + call dosys + call close +1: pop %rax + ret + +block_common: + mov $0x1DE, %eax /* sys_lseek */ + mov (%rbx), %esi + shl $12, %esi + xor %edx, %edx /* SEEK_SET */ + call dosys + mov $3, %eax /* sys_read */ + or %r10b, %r10b + jz 1f + mov $4, %al /* sys_write */ +1: lea (%r15,%r8,4), %rsi + mov $4096, %edx + call dosys + mov -4(%rbx), %esi + sub $8, %rbx + ret + + .align 32 +table: ret + .align 32 +li: add $4, %rbx + inc %r13d + mov %eax, (%rbx) + mov (%r15,%r13,4), %eax + ret + .align 32 +du: add $4, %rbx + mov %eax, (%rbx) + ret + .align 32 +dr: mov (%rbx), %eax + sub $4, %rbx + ret + .align 32 +sw: xchg (%rbx), %eax + ret + .align 32 +pu: add $4, %r12 + mov %eax, (%r12) + mov (%rbx), %eax + sub $4, %rbx + ret + .align 32 +po: add $4, %rbx + mov %eax, (%rbx) + mov (%r12), %eax + sub $4, %r12 + ret + .align 32 +ju: lea -1(%eax), %r13d + mov (%rbx), %eax + sub $4, %rbx + ret + .align 32 +ca: add $4, %r12 + mov %r13d, (%r12) + lea -1(%eax), %r13d + mov (%rbx), %eax + sub $4, %rbx + ret + .align 32 +cc: cmpl $0, (%rbx) + jz 1f + add $4, %r12 + mov %r13d, (%r12) + lea -1(%eax), %r13d +1: mov -4(%rbx), %eax + sub $8, %rbx + ret + .align 32 +cj: cmpl $0, (%rbx) + jz 1f + lea -1(%eax), %r13d +1: mov -4(%rbx), %eax + sub $8, %rbx + ret + .align 32 +re: mov (%r12), %r13d + sub $4, %r12 + ret + .align 32 +eq: cmp %eax, (%rbx) + sete %al + movzbl %al, %eax + neg %eax + sub $4, %rbx + ret + .align 32 +ne: cmp %eax, (%rbx) + setne %al + movzbl %al, %eax + neg %eax + sub $4, %rbx + ret + .align 32 +lt: cmp %eax, (%rbx) + setl %al + movzbl %al, %eax + neg %eax + sub $4, %rbx + ret + .align 32 +gt: cmp %eax, (%rbx) + setg %al + movzbl %al, %eax + neg %eax + sub $4, %rbx + ret + .align 32 +fe: mov (%r15,%rax,4), %eax + ret + .align 32 +st: mov (%rbx), %ecx + mov %ecx, (%r15,%rax,4) + mov -4(%rbx), %eax + sub $8, %rbx + ret + .align 32 +ad: add (%rbx), %eax + sub $4, %rbx + ret + .align 32 +su: sub (%rbx), %eax + neg %eax + sub $4, %rbx + ret + .align 32 +mu: mull (%rbx) + sub $4, %rbx + ret + .align 32 +di: mov %eax, %ecx + mov (%rbx), %eax + cdq + idiv %ecx + mov %edx, (%rbx) + ret + .align 32 +an: and (%rbx), %eax + sub $4, %rbx + ret + .align 32 +or: or (%rbx), %eax + sub $4, %rbx + ret + .align 32 +xo: xor (%rbx), %eax + sub $4, %rbx + ret + .align 32 +sl: mov %eax, %ecx + mov (%rbx), %eax + sub $4, %rbx + shl %cl, %eax + ret + .align 32 +sr: mov %eax, %ecx + mov (%rbx), %eax + sub $4, %rbx + sar %cl, %eax + ret + .align 32 +cp: mov %eax, %ecx + mov (%rbx), %edi + mov -4(%rbx), %esi + sub $8, %rbx + lea (%r15,%rdi,4), %rdi + lea (%r15,%rsi,4), %rsi + cmp %eax, %eax + .byte 0xF3, 0xA7 /* repe cmpsd */ + sete %al + movzbl %al, %eax + neg %eax + ret + .align 32 +cy: mov %eax, %ecx + mov (%rbx), %edi + mov -4(%rbx), %esi + mov -8(%rbx), %eax + sub $12, %rbx + lea (%r15,%rdi,4), %rdi + lea (%r15,%rsi,4), %rsi + repe movsd + ret + .align 32 +io: mov %eax, %ecx + mov (%rbx), %eax + sub $4, %rbx + cmp $7, %ecx + ja 1f + lea io_table(%rip), %rdx + movzbl (%rdx,%rcx), %ecx + lea ioa(%rip), %rdx + add %rdx, %rcx + jmp *%rcx +1: ret + +ioa: push %rax + mov $4, %eax /* sys_write */ + mov $1, %edi + mov %rsp, %rsi + mov $1, %edx + call dosys + pop %rax + mov (%rbx), %eax + sub $4, %rbx + ret +iob: add $4, %rbx + mov %eax, (%rbx) + mov $3, %eax /* sys_read */ + push %rax + xor %edi, %edi + mov %rsp, %rsi + mov $1, %edx + call dosys + pop %rax + ret +ioc: mov %eax, %r8d + mov blocks(%rip), %rdi + call rdonly + xor %r10d, %r10d + call block_common + call close + mov %esi, %eax + ret +iod: mov %eax, %r8d + mov blocks(%rip), %rdi + call wronly + mov $1, %r10b + call block_common + call close + mov %esi, %eax + ret +ioe: jmp save_image +iof: call load_image + xor %rax, %rax + xor %r13, %r13 + jmp _execute +iog: mov $65536, %r13d + ret +ioh: add $8, %rbx + mov %eax, -4(%rbx) + lea astack-4(%rip), %rdx + neg %edx + lea 4*32-8(%rbx,%rdx), %rax + shr $2, %eax + mov %eax, (%rbx) + lea (%r12,%rdx), %rax + shr $2, %eax + ret + +_start: xor %eax, %eax + add $8, %rsp + lea memory(%rip), %r15 + lea dstack-4(%rip), %rbx + lea astack-4(%rip), %r12 + xor %r13d, %r13d + lea table(%rip), %rbp + mov 8(%rsp), %rcx + or %rcx, %rcx + jz 1f + mov 16(%rsp), %rcx + or %rcx, %rcx + jz 1f + mov %rcx, blocks(%rip) + mov 24(%rsp), %rcx + or %rcx, %rcx + jz 2f + mov %rcx, rom(%rip) + jmp 3f +1: lea default_blocks(%rip), %rcx + mov %rcx, blocks(%rip) +2: lea default_rom(%rip), %rcx + mov %rcx, rom(%rip) +3: call load_image +_execute: + jmp 3f + .align 64 +2: mov (%r15,%r13,4), %r14d + movzbl %r14b, %edi + shr $8, %r14d + cmp $29, %edi + ja 1f + shl $5, %edi + add %rbp, %rdi + call *%rdi +1: movzbl %r14b, %edi + shr $8, %r14d + cmp $29, %edi + ja 1f + shl $5, %edi + add %rbp, %rdi + call *%rdi +1: movzbl %r14b, %edi + shr $8, %r14d + cmp $29, %edi + ja 1f + shl $5, %edi + add %rbp, %rdi + call *%rdi +1: mov %r14d, %edi + cmp $29, %edi + ja 1f + shl $5, %edi + add %rbp, %rdi + call *%rdi +1: inc %r13 +3: cmp $65536, %r13 + jl 2b + mov $1, %eax /* sys_exit */ + xor %edi, %edi + call dosys diff --git a/source/ilo-amd64-linux.s b/source/ilo-amd64-linux.s new file mode 100644 index 0000000..0be7ca7 --- /dev/null +++ b/source/ilo-amd64-linux.s @@ -0,0 +1,405 @@ +/* AMD64 ilo, (c) 2023 Christopher Leonard, MIT License */ + + .global _start + + /* rax: top of stack */ + /* rbx: data stack */ + /* rbp: jump table address */ + /* r12: address stack */ + /* r13: instruction pointer */ + /* r14: opcode shift register */ + /* r15: memory */ + + .bss + + .align 8 +blocks: .skip 8 /* name of blocks file (ilo.blocks) */ +rom: .skip 8 /* name of image (ilo.rom) */ +dstack: .skip 32*4 +astack: .skip 256*4 +a: .skip 4 /* other variables for misc. purposes */ +b: .skip 4 +f: .skip 4 +s: .skip 4 +d: .skip 4 +l: .skip 4 +memory: .skip 65536*4 + + .section .rodata + +default_blocks: + .asciz "ilo.blocks" +default_rom: + .asciz "ilo.rom" + +io_table: + .byte 0 + .byte iob-ioa + .byte ioc-ioa + .byte iod-ioa + .byte ioe-ioa + .byte iof-ioa + .byte iog-ioa + .byte ioh-ioa + + .text + +rdonly: mov $2, %eax /* sys_open */ + xor %esi, %esi /* O_RDONLY */ + mov $0666, %edx + syscall + mov %eax, %edi + ret + +wronly: mov $2, %eax /* sys_open */ + mov $1, %esi /* O_WRONLY */ + mov $0666, %edx + syscall + mov %eax, %edi + ret + +close: mov $3, %eax /* sys_close */ + syscall + ret + +load_image: + mov rom(%rip), %rdi + call rdonly + or %eax, %eax + jz 1f + mov %r15, %rsi + mov $65536 * 4, %edx + xor %eax, %eax /* sys_read */ + syscall + call close + xor %eax, %eax + lea dstack-4(%rip), %rbx + lea astack-4(%rip), %r12 + xor %r13d, %r13d +1: ret + +save_image: + push %rax + mov rom(%rip), %rdi + call wronly + or %eax, %eax + jz 1f + mov %r15, %rsi + mov $65536 * 4, %edx + mov $1, %eax + syscall + call close +1: pop %rax + ret + +block_common: + mov $8, %eax /* sys_lseek */ + mov (%rbx), %esi + shl $12, %esi + xor %edx, %edx /* SEEK_SET */ + syscall + xor %eax, %eax /* sys_read */ + or %r10b, %r10b + jz 1f + mov $1, %al /* sys_write */ +1: lea (%r15,%r8,4), %rsi + mov $4096, %edx + syscall + mov -4(%rbx), %esi + sub $8, %rbx + ret + + .align 32 +table: ret + .align 32 +li: add $4, %rbx + inc %r13d + mov %eax, (%rbx) + mov (%r15,%r13,4), %eax + ret + .align 32 +du: add $4, %rbx + mov %eax, (%rbx) + ret + .align 32 +dr: mov (%rbx), %eax + sub $4, %rbx + ret + .align 32 +sw: xchg (%rbx), %eax + ret + .align 32 +pu: add $4, %r12 + mov %eax, (%r12) + mov (%rbx), %eax + sub $4, %rbx + ret + .align 32 +po: add $4, %rbx + mov %eax, (%rbx) + mov (%r12), %eax + sub $4, %r12 + ret + .align 32 +ju: lea -1(%eax), %r13d + mov (%rbx), %eax + sub $4, %rbx + ret + .align 32 +ca: add $4, %r12 + mov %r13d, (%r12) + lea -1(%eax), %r13d + mov (%rbx), %eax + sub $4, %rbx + ret + .align 32 +cc: cmpl $0, (%rbx) + jz 1f + add $4, %r12 + mov %r13d, (%r12) + lea -1(%eax), %r13d +1: mov -4(%rbx), %eax + sub $8, %rbx + ret + .align 32 +cj: cmpl $0, (%rbx) + jz 1f + lea -1(%eax), %r13d +1: mov -4(%rbx), %eax + sub $8, %rbx + ret + .align 32 +re: mov (%r12), %r13d + sub $4, %r12 + ret + .align 32 +eq: cmp %eax, (%rbx) + sete %al + movzbl %al, %eax + neg %eax + sub $4, %rbx + ret + .align 32 +ne: cmp %eax, (%rbx) + setne %al + movzbl %al, %eax + neg %eax + sub $4, %rbx + ret + .align 32 +lt: cmp %eax, (%rbx) + setl %al + movzbl %al, %eax + neg %eax + sub $4, %rbx + ret + .align 32 +gt: cmp %eax, (%rbx) + setg %al + movzbl %al, %eax + neg %eax + sub $4, %rbx + ret + .align 32 +fe: mov (%r15,%rax,4), %eax + ret + .align 32 +st: mov (%rbx), %ecx + mov %ecx, (%r15,%rax,4) + mov -4(%rbx), %eax + sub $8, %rbx + ret + .align 32 +ad: add (%rbx), %eax + sub $4, %rbx + ret + .align 32 +su: sub (%rbx), %eax + neg %eax + sub $4, %rbx + ret + .align 32 +mu: mull (%rbx) + sub $4, %rbx + ret + .align 32 +di: mov %eax, %ecx + mov (%rbx), %eax + cdq + idiv %ecx + mov %edx, (%rbx) + ret + .align 32 +an: and (%rbx), %eax + sub $4, %rbx + ret + .align 32 +or: or (%rbx), %eax + sub $4, %rbx + ret + .align 32 +xo: xor (%rbx), %eax + sub $4, %rbx + ret + .align 32 +sl: mov %eax, %ecx + mov (%rbx), %eax + sub $4, %rbx + shl %cl, %eax + ret + .align 32 +sr: mov %eax, %ecx + mov (%rbx), %eax + sub $4, %rbx + sar %cl, %eax + ret + .align 32 +cp: mov %eax, %ecx + mov (%rbx), %edi + mov -4(%rbx), %esi + sub $8, %rbx + lea (%r15,%rdi,4), %rdi + lea (%r15,%rsi,4), %rsi + cmp %eax, %eax + repe cmpsd + sete %al + movzbl %al, %eax + neg %eax + ret + .align 32 +cy: mov %eax, %ecx + mov (%rbx), %edi + mov -4(%rbx), %esi + mov -8(%rbx), %eax + sub $12, %rbx + lea (%r15,%rdi,4), %rdi + lea (%r15,%rsi,4), %rsi + repe movsd + ret + .align 32 +io: mov %eax, %ecx + mov (%rbx), %eax + sub $4, %rbx + cmp $7, %ecx + ja 1f + lea io_table(%rip), %rdx + movzbl (%rdx,%rcx), %ecx + lea ioa(%rip), %rdx + add %rdx, %rcx + jmp *%rcx +1: ret + +ioa: push %rax + mov $1, %eax /* sys_write */ + mov %eax, %edi + mov %rsp, %rsi + mov $1, %edx + syscall + pop %rax + mov (%rbx), %eax + sub $4, %rbx + ret +iob: add $4, %rbx + mov %eax, (%rbx) + xor %eax, %eax /* sys_read */ + push %rax + xor %edi, %edi + mov %rsp, %rsi + mov $1, %edx + syscall + pop %rax + ret +ioc: mov %eax, %r8d + mov blocks(%rip), %rdi + call rdonly + xor %r10d, %r10d + call block_common + call close + mov %esi, %eax + ret +iod: mov %eax, %r8d + mov blocks(%rip), %rdi + call wronly + mov $1, %r10b + call block_common + call close + mov %esi, %eax + ret +ioe: jmp save_image +iof: call load_image + xor %rax, %rax + xor %r13, %r13 + jmp _execute +iog: mov $65536, %r13d + ret +ioh: add $8, %rbx + mov %eax, -4(%rbx) + lea astack-4(%rip), %rdx + neg %edx + lea 4*32-8(%rbx,%rdx), %rax + shr $2, %eax + mov %eax, (%rbx) + lea (%r12,%rdx), %rax + shr $2, %eax + ret + +_start: xor %eax, %eax + lea memory(%rip), %r15 + lea dstack-4(%rip), %rbx + lea astack-4(%rip), %r12 + xor %r13d, %r13d + lea table(%rip), %rbp + mov 8(%rsp), %rcx + or %rcx, %rcx + jz 1f + mov 16(%rsp), %rcx + or %rcx, %rcx + jz 1f + mov %rcx, blocks(%rip) + mov 24(%rsp), %rcx + or %rcx, %rcx + jz 2f + mov %rcx, rom(%rip) + jmp 3f +1: lea default_blocks(%rip), %rcx + mov %rcx, blocks(%rip) +2: lea default_rom(%rip), %rcx + mov %rcx, rom(%rip) +3: call load_image +_execute: + jmp 3f + .align 64 +2: mov (%r15,%r13,4), %r14d + movzbl %r14b, %edi + shr $8, %r14d + cmp $29, %edi + ja 1f + shl $5, %edi + add %rbp, %rdi + call *%rdi +1: movzbl %r14b, %edi + shr $8, %r14d + cmp $29, %edi + ja 1f + shl $5, %edi + add %rbp, %rdi + call *%rdi +1: movzbl %r14b, %edi + shr $8, %r14d + cmp $29, %edi + ja 1f + shl $5, %edi + add %rbp, %rdi + call *%rdi +1: mov %r14d, %edi + cmp $29, %edi + ja 1f + shl $5, %edi + add %rbp, %rdi + call *%rdi +1: inc %r13 +3: cmp $65536, %r13 + jl 2b + mov $60, %eax /* sys_exit */ + xor %edi, %edi + syscall diff --git a/source/ilo-amd64-netbsd.s b/source/ilo-amd64-netbsd.s new file mode 100644 index 0000000..cc37aa5 --- /dev/null +++ b/source/ilo-amd64-netbsd.s @@ -0,0 +1,414 @@ +/* AMD64 ilo, (c) 2023 Christopher Leonard, MIT License */ + + .global _start + + /* rax: top of stack */ + /* rbx: data stack */ + /* rbp: jump table address */ + /* r12: address stack */ + /* r13: instruction pointer */ + /* r14: opcode shift register */ + /* r15: memory */ + +.section ".note.netbsd.ident", "a" +.long 2f-1f +.long 4f-3f +.long 1 +1: .asciz "NetBSD" +2: .p2align 2 +3: .long 199905 +4: .p2align 2 + + .bss + + .align 8 +blocks: .skip 8 /* name of blocks file (ilo.blocks) */ +rom: .skip 8 /* name of image (ilo.rom) */ +dstack: .skip 32*4 +astack: .skip 256*4 +a: .skip 4 /* other variables for misc. purposes */ +b: .skip 4 +f: .skip 4 +s: .skip 4 +d: .skip 4 +l: .skip 4 +memory: .skip 65536*4 + + .section .rodata + +default_blocks: + .asciz "ilo.blocks" +default_rom: + .asciz "ilo.rom" + +io_table: + .byte 0 + .byte iob-ioa + .byte ioc-ioa + .byte iod-ioa + .byte ioe-ioa + .byte iof-ioa + .byte iog-ioa + .byte ioh-ioa + + .text + +rdonly: mov $5, %eax /* sys_open */ + xor %esi, %esi /* O_RDONLY */ + mov $0666, %edx + syscall + mov %eax, %edi + ret + +wronly: mov $5, %eax /* sys_open */ + mov $1, %esi /* O_WRONLY */ + mov $0666, %edx + syscall + mov %eax, %edi + ret + +close: mov $6, %eax /* sys_close */ + syscall + ret + +load_image: + mov rom(%rip), %rdi + call rdonly + or %eax, %eax + jz 1f + mov %r15, %rsi + mov $65536 * 4, %edx + mov $3, %eax /* sys_read */ + syscall + call close + xor %eax, %eax + lea dstack-4(%rip), %rbx + lea astack-4(%rip), %r12 + xor %r13d, %r13d +1: ret + +save_image: + push %rax + mov rom(%rip), %rdi + call wronly + or %eax, %eax + jz 1f + mov %r15, %rsi + mov $65536 * 4, %edx + mov $4, %eax + syscall + call close +1: pop %rax + ret + +block_common: + mov $19, %eax /* sys_lseek */ + mov (%rbx), %esi + shl $12, %esi + xor %edx, %edx /* SEEK_SET */ + syscall + mov $3, %eax /* sys_read */ + or %r10b, %r10b + jz 1f + mov $4, %al /* sys_write */ +1: lea (%r15,%r8,4), %rsi + mov $4096, %edx + syscall + mov -4(%rbx), %esi + sub $8, %rbx + ret + + .align 32 +table: ret + .align 32 +li: add $4, %rbx + inc %r13d + mov %eax, (%rbx) + mov (%r15,%r13,4), %eax + ret + .align 32 +du: add $4, %rbx + mov %eax, (%rbx) + ret + .align 32 +dr: mov (%rbx), %eax + sub $4, %rbx + ret + .align 32 +sw: xchg (%rbx), %eax + ret + .align 32 +pu: add $4, %r12 + mov %eax, (%r12) + mov (%rbx), %eax + sub $4, %rbx + ret + .align 32 +po: add $4, %rbx + mov %eax, (%rbx) + mov (%r12), %eax + sub $4, %r12 + ret + .align 32 +ju: lea -1(%eax), %r13d + mov (%rbx), %eax + sub $4, %rbx + ret + .align 32 +ca: add $4, %r12 + mov %r13d, (%r12) + lea -1(%eax), %r13d + mov (%rbx), %eax + sub $4, %rbx + ret + .align 32 +cc: cmpl $0, (%rbx) + jz 1f + add $4, %r12 + mov %r13d, (%r12) + lea -1(%eax), %r13d +1: mov -4(%rbx), %eax + sub $8, %rbx + ret + .align 32 +cj: cmpl $0, (%rbx) + jz 1f + lea -1(%eax), %r13d +1: mov -4(%rbx), %eax + sub $8, %rbx + ret + .align 32 +re: mov (%r12), %r13d + sub $4, %r12 + ret + .align 32 +eq: cmp %eax, (%rbx) + sete %al + movzbl %al, %eax + neg %eax + sub $4, %rbx + ret + .align 32 +ne: cmp %eax, (%rbx) + setne %al + movzbl %al, %eax + neg %eax + sub $4, %rbx + ret + .align 32 +lt: cmp %eax, (%rbx) + setl %al + movzbl %al, %eax + neg %eax + sub $4, %rbx + ret + .align 32 +gt: cmp %eax, (%rbx) + setg %al + movzbl %al, %eax + neg %eax + sub $4, %rbx + ret + .align 32 +fe: mov (%r15,%rax,4), %eax + ret + .align 32 +st: mov (%rbx), %ecx + mov %ecx, (%r15,%rax,4) + mov -4(%rbx), %eax + sub $8, %rbx + ret + .align 32 +ad: add (%rbx), %eax + sub $4, %rbx + ret + .align 32 +su: sub (%rbx), %eax + neg %eax + sub $4, %rbx + ret + .align 32 +mu: mull (%rbx) + sub $4, %rbx + ret + .align 32 +di: mov %eax, %ecx + mov (%rbx), %eax + cdq + idiv %ecx + mov %edx, (%rbx) + ret + .align 32 +an: and (%rbx), %eax + sub $4, %rbx + ret + .align 32 +or: or (%rbx), %eax + sub $4, %rbx + ret + .align 32 +xo: xor (%rbx), %eax + sub $4, %rbx + ret + .align 32 +sl: mov %eax, %ecx + mov (%rbx), %eax + sub $4, %rbx + shl %cl, %eax + ret + .align 32 +sr: mov %eax, %ecx + mov (%rbx), %eax + sub $4, %rbx + sar %cl, %eax + ret + .align 32 +cp: mov %eax, %ecx + mov (%rbx), %edi + mov -4(%rbx), %esi + sub $8, %rbx + lea (%r15,%rdi,4), %rdi + lea (%r15,%rsi,4), %rsi + cmp %eax, %eax + repe cmpsd + sete %al + movzbl %al, %eax + neg %eax + ret + .align 32 +cy: mov %eax, %ecx + mov (%rbx), %edi + mov -4(%rbx), %esi + mov -8(%rbx), %eax + sub $12, %rbx + lea (%r15,%rdi,4), %rdi + lea (%r15,%rsi,4), %rsi + repe movsd + ret + .align 32 +io: mov %eax, %ecx + mov (%rbx), %eax + sub $4, %rbx + cmp $7, %ecx + ja 1f + lea io_table(%rip), %rdx + movzbl (%rdx,%rcx), %ecx + lea ioa(%rip), %rdx + add %rdx, %rcx + jmp *%rcx +1: ret + +ioa: push %rax + mov $4, %eax /* sys_write */ + mov $1, %edi + mov %rsp, %rsi + mov $1, %edx + syscall + pop %rax + mov (%rbx), %eax + sub $4, %rbx + ret +iob: add $4, %rbx + mov %eax, (%rbx) + mov $3, %eax /* sys_read */ + push %rax + xor %edi, %edi + mov %rsp, %rsi + mov $1, %edx + syscall + pop %rax + ret +ioc: mov %eax, %r8d + mov blocks(%rip), %rdi + call rdonly + xor %r10d, %r10d + call block_common + call close + mov %esi, %eax + ret +iod: mov %eax, %r8d + mov blocks(%rip), %rdi + call wronly + mov $1, %r10b + call block_common + call close + mov %esi, %eax + ret +ioe: jmp save_image +iof: call load_image + xor %rax, %rax + xor %r13, %r13 + jmp _execute +iog: mov $65536, %r13d + ret +ioh: add $8, %rbx + mov %eax, -4(%rbx) + lea astack-4(%rip), %rdx + neg %edx + lea 4*32-8(%rbx,%rdx), %rax + shr $2, %eax + mov %eax, (%rbx) + lea (%r12,%rdx), %rax + shr $2, %eax + ret + +_start: xor %eax, %eax + lea memory(%rip), %r15 + lea dstack-4(%rip), %rbx + lea astack-4(%rip), %r12 + xor %r13d, %r13d + lea table(%rip), %rbp + mov 8(%rsp), %rcx + or %rcx, %rcx + jz 1f + mov 16(%rsp), %rcx + or %rcx, %rcx + jz 1f + mov %rcx, blocks(%rip) + mov 24(%rsp), %rcx + or %rcx, %rcx + jz 2f + mov %rcx, rom(%rip) + jmp 3f +1: lea default_blocks(%rip), %rcx + mov %rcx, blocks(%rip) +2: lea default_rom(%rip), %rcx + mov %rcx, rom(%rip) +3: call load_image +_execute: + jmp 3f + .align 64 +2: mov (%r15,%r13,4), %r14d + movzbl %r14b, %edi + shr $8, %r14d + cmp $29, %edi + ja 1f + shl $5, %edi + add %rbp, %rdi + call *%rdi +1: movzbl %r14b, %edi + shr $8, %r14d + cmp $29, %edi + ja 1f + shl $5, %edi + add %rbp, %rdi + call *%rdi +1: movzbl %r14b, %edi + shr $8, %r14d + cmp $29, %edi + ja 1f + shl $5, %edi + add %rbp, %rdi + call *%rdi +1: mov %r14d, %edi + cmp $29, %edi + ja 1f + shl $5, %edi + add %rbp, %rdi + call *%rdi +1: inc %r13 +3: cmp $65536, %r13 + jl 2b + mov $1, %eax /* sys_exit */ + xor %edi, %edi + syscall diff --git a/source/ilo-amd64-openbsd.s b/source/ilo-amd64-openbsd.s new file mode 100644 index 0000000..cd2ef07 --- /dev/null +++ b/source/ilo-amd64-openbsd.s @@ -0,0 +1,439 @@ +/* AMD64 ilo, (c) 2023 Christopher Leonard, MIT License */ + + .global _start + + /* rax: top of stack */ + /* rbx: data stack */ + /* rbp: jump table address */ + /* r12: address stack */ + /* r13: instruction pointer */ + /* r14: opcode shift register */ + /* r15: memory */ + +.section ".note.openbsd.ident", "a" + + .p2align 2 + .long 0x8 + .long 0x4 + .long 0x1 + .ascii "OpenBSD\0" + .long 0x0 + .p2align 2 + +.section ".openbsd.syscalls" +.long rd0 +.long $5 +.long rd1 +.long $5 +.long rd2 +.long $6 +.long rd3 +.long $3 +.long rd4 +.long $4 +.long rd5 +.long $0xA6 +.long rd6 +.long $3 +.long rd6 +.long $4 +.long rd7 +.long $4 +.long rd8 +.long $3 +.long rd9 +.long $1 + + .bss + + .align 8 +blocks: .skip 8 /* name of blocks file (ilo.blocks) */ +rom: .skip 8 /* name of image (ilo.rom) */ +dstack: .skip 32*4 +astack: .skip 256*4 +a: .skip 4 /* other variables for misc. purposes */ +b: .skip 4 +f: .skip 4 +s: .skip 4 +d: .skip 4 +l: .skip 4 +memory: .skip 65536*4 + + .section .rodata + +default_blocks: + .asciz "ilo.blocks" +default_rom: + .asciz "ilo.rom" + +io_table: + .byte 0 + .byte iob-ioa + .byte ioc-ioa + .byte iod-ioa + .byte ioe-ioa + .byte iof-ioa + .byte iog-ioa + .byte ioh-ioa + + .text + +rdonly: mov $5, %eax /* sys_open */ + xor %esi, %esi /* O_RDONLY */ + mov $0666, %edx +rd0: syscall + mov %eax, %edi + ret + +wronly: mov $5, %eax /* sys_open */ + mov $1, %esi /* O_WRONLY */ + mov $0666, %edx +rd1: syscall + mov %eax, %edi + ret + +close: mov $6, %eax /* sys_close */ +rd2: syscall + ret + +load_image: + mov rom(%rip), %rdi + call rdonly + or %eax, %eax + jz 1f + mov %r15, %rsi + mov $65536 * 4, %edx + mov $3, %eax /* sys_read */ +rd3: syscall + call close + xor %eax, %eax + lea dstack-4(%rip), %rbx + lea astack-4(%rip), %r12 + xor %r13d, %r13d +1: ret + +save_image: + push %rax + mov rom(%rip), %rdi + call wronly + or %eax, %eax + jz 1f + mov %r15, %rsi + mov $65536 * 4, %edx + mov $4, %eax +rd4: syscall + call close +1: pop %rax + ret + +block_common: + mov $0xA6, %eax /* sys_lseek */ + mov (%rbx), %esi + shl $12, %esi + xor %edx, %edx /* SEEK_SET */ +rd5: syscall + mov $3, %eax /* sys_read */ + or %r10b, %r10b + jz 1f + mov $4, %al /* sys_write */ +1: lea (%r15,%r8,4), %rsi + mov $4096, %edx +rd6: syscall + mov -4(%rbx), %esi + sub $8, %rbx + ret + + .align 32 +table: ret + .align 32 +li: add $4, %rbx + inc %r13d + mov %eax, (%rbx) + mov (%r15,%r13,4), %eax + ret + .align 32 +du: add $4, %rbx + mov %eax, (%rbx) + ret + .align 32 +dr: mov (%rbx), %eax + sub $4, %rbx + ret + .align 32 +sw: xchg (%rbx), %eax + ret + .align 32 +pu: add $4, %r12 + mov %eax, (%r12) + mov (%rbx), %eax + sub $4, %rbx + ret + .align 32 +po: add $4, %rbx + mov %eax, (%rbx) + mov (%r12), %eax + sub $4, %r12 + ret + .align 32 +ju: lea -1(%eax), %r13d + mov (%rbx), %eax + sub $4, %rbx + ret + .align 32 +ca: add $4, %r12 + mov %r13d, (%r12) + lea -1(%eax), %r13d + mov (%rbx), %eax + sub $4, %rbx + ret + .align 32 +cc: cmpl $0, (%rbx) + jz 1f + add $4, %r12 + mov %r13d, (%r12) + lea -1(%eax), %r13d +1: mov -4(%rbx), %eax + sub $8, %rbx + ret + .align 32 +cj: cmpl $0, (%rbx) + jz 1f + lea -1(%eax), %r13d +1: mov -4(%rbx), %eax + sub $8, %rbx + ret + .align 32 +re: mov (%r12), %r13d + sub $4, %r12 + ret + .align 32 +eq: cmp %eax, (%rbx) + sete %al + movzbl %al, %eax + neg %eax + sub $4, %rbx + ret + .align 32 +ne: cmp %eax, (%rbx) + setne %al + movzbl %al, %eax + neg %eax + sub $4, %rbx + ret + .align 32 +lt: cmp %eax, (%rbx) + setl %al + movzbl %al, %eax + neg %eax + sub $4, %rbx + ret + .align 32 +gt: cmp %eax, (%rbx) + setg %al + movzbl %al, %eax + neg %eax + sub $4, %rbx + ret + .align 32 +fe: mov (%r15,%rax,4), %eax + ret + .align 32 +st: mov (%rbx), %ecx + mov %ecx, (%r15,%rax,4) + mov -4(%rbx), %eax + sub $8, %rbx + ret + .align 32 +ad: add (%rbx), %eax + sub $4, %rbx + ret + .align 32 +su: sub (%rbx), %eax + neg %eax + sub $4, %rbx + ret + .align 32 +mu: mull (%rbx) + sub $4, %rbx + ret + .align 32 +di: mov %eax, %ecx + mov (%rbx), %eax + cdq + idiv %ecx + mov %edx, (%rbx) + ret + .align 32 +an: and (%rbx), %eax + sub $4, %rbx + ret + .align 32 +or: or (%rbx), %eax + sub $4, %rbx + ret + .align 32 +xo: xor (%rbx), %eax + sub $4, %rbx + ret + .align 32 +sl: mov %eax, %ecx + mov (%rbx), %eax + sub $4, %rbx + shl %cl, %eax + ret + .align 32 +sr: mov %eax, %ecx + mov (%rbx), %eax + sub $4, %rbx + sar %cl, %eax + ret + .align 32 +cp: mov %eax, %ecx + mov (%rbx), %edi + mov -4(%rbx), %esi + sub $8, %rbx + lea (%r15,%rdi,4), %rdi + lea (%r15,%rsi,4), %rsi + cmp %eax, %eax + repe cmpsd + sete %al + movzbl %al, %eax + neg %eax + ret + .align 32 +cy: mov %eax, %ecx + mov (%rbx), %edi + mov -4(%rbx), %esi + mov -8(%rbx), %eax + sub $12, %rbx + lea (%r15,%rdi,4), %rdi + lea (%r15,%rsi,4), %rsi + repe movsd + ret + .align 32 +io: mov %eax, %ecx + mov (%rbx), %eax + sub $4, %rbx + cmp $7, %ecx + ja 1f + lea io_table(%rip), %rdx + movzbl (%rdx,%rcx), %ecx + lea ioa(%rip), %rdx + add %rdx, %rcx + jmp *%rcx +1: ret + +ioa: push %rax + mov $4, %eax /* sys_write */ + mov $1, %edi + mov %rsp, %rsi + mov $1, %edx +rd7: syscall + pop %rax + mov (%rbx), %eax + sub $4, %rbx + ret +iob: add $4, %rbx + mov %eax, (%rbx) + mov $3, %eax /* sys_read */ + push %rax + xor %edi, %edi + mov %rsp, %rsi + mov $1, %edx +rd8: syscall + pop %rax + ret +ioc: mov %eax, %r8d + mov blocks(%rip), %rdi + call rdonly + xor %r10d, %r10d + call block_common + call close + mov %esi, %eax + ret +iod: mov %eax, %r8d + mov blocks(%rip), %rdi + call wronly + mov $1, %r10b + call block_common + call close + mov %esi, %eax + ret +ioe: jmp save_image +iof: call load_image + xor %rax, %rax + xor %r13, %r13 + jmp _execute +iog: mov $65536, %r13d + ret +ioh: add $8, %rbx + mov %eax, -4(%rbx) + lea astack-4(%rip), %rdx + neg %edx + lea 4*32-8(%rbx,%rdx), %rax + shr $2, %eax + mov %eax, (%rbx) + lea (%r12,%rdx), %rax + shr $2, %eax + ret + +_start: xor %eax, %eax + lea memory(%rip), %r15 + lea dstack-4(%rip), %rbx + lea astack-4(%rip), %r12 + xor %r13d, %r13d + lea table(%rip), %rbp + mov 8(%rsp), %rcx + or %rcx, %rcx + jz 1f + mov 16(%rsp), %rcx + or %rcx, %rcx + jz 1f + mov %rcx, blocks(%rip) + mov 24(%rsp), %rcx + or %rcx, %rcx + jz 2f + mov %rcx, rom(%rip) + jmp 3f +1: lea default_blocks(%rip), %rcx + mov %rcx, blocks(%rip) +2: lea default_rom(%rip), %rcx + mov %rcx, rom(%rip) +3: call load_image +_execute: + jmp 3f + .align 64 +2: mov (%r15,%r13,4), %r14d + movzbl %r14b, %edi + shr $8, %r14d + cmp $29, %edi + ja 1f + shl $5, %edi + add %rbp, %rdi + call *%rdi +1: movzbl %r14b, %edi + shr $8, %r14d + cmp $29, %edi + ja 1f + shl $5, %edi + add %rbp, %rdi + call *%rdi +1: movzbl %r14b, %edi + shr $8, %r14d + cmp $29, %edi + ja 1f + shl $5, %edi + add %rbp, %rdi + call *%rdi +1: mov %r14d, %edi + cmp $29, %edi + ja 1f + shl $5, %edi + add %rbp, %rdi + call *%rdi +1: inc %r13 +3: cmp $65536, %r13 + jl 2b + mov $1, %eax /* sys_exit */ + xor %edi, %edi +rd9: syscall diff --git a/source/ilo-banked.c b/source/ilo-banked.c new file mode 100644 index 0000000..56154e0 --- /dev/null +++ b/source/ilo-banked.c @@ -0,0 +1,205 @@ +/*************************************************************** + crc's _ _ + (_) | ___ + | | |/ _ \ a tiny virtual computer + | | | (_) | 64kw RAM, 32-bit, Dual Stack, MISC + |_|_|\___/ ilo.c (c) charles childers + **************************************************************/ + +/* This implementation uses memory separated into multiple + banks. This makes it easier to run on systems with less + RAM. */ + +#include +#include + +#define SLICES 64 +#define SLICESIZE (65536/SLICES) + +int ip, sp, rp, data[33], address[257]; +char *blocks, *rom; + +#ifdef MALLOC +int *memory[SLICES]; +#else +int memory[SLICES][SLICESIZE]; +#endif + +#define TOS data[sp] +#define NOS data[sp-1] +#define TORS address[rp] + +int stack_pop() { + sp--; + return data[sp + 1]; +} + +void stack_push(int value) { + sp++; + data[sp] = value; +} + +void store(int a, int v) { + int slice = a / SLICESIZE; + int actual = a - (slice * SLICESIZE); + memory[slice][actual] = v; +} + +int fetch(int a) { + int slice = a / SLICESIZE; + int actual = a - (slice * SLICESIZE); + return memory[slice][actual]; +} + +void prepare_vm() { + for (ip = 0; ip < 32; ip++) data[ip] = 0; + for (ip = 0; ip < 128; ip++) address[ip] = 0; + ip = sp = rp = 0; +} + +void load_image() { + FILE *fp; + int x, y; + fp = fopen(rom, "rb"); + for (y = 0; y < 65536; y++) { + x = 0; + fread(&x, 4, 1, fp); + store(y, x); + } + fclose(fp); + prepare_vm(); +} + +void save_image() { + FILE *fp; + int i; + fp = fopen(rom, "wb"); + for (i = 0; i < SLICES; i++) + fwrite(&memory[i], sizeof(int), SLICESIZE, fp); + fclose(fp); +} + +void read_block() { + FILE *f; + int block, buffer, x, c; + buffer = stack_pop(); + block = stack_pop(); + f = fopen(blocks, "r+b"); + fseek(f, 4096 * block, SEEK_SET); + for (x = 0; x < 1024; x++) { + c = 0; + fread(&c, 4, 1, f); + store(buffer + x, c); + } + fclose(f); +} + +void write_block() { + FILE *f; + int block, buffer, x, c; + buffer = stack_pop(); + block = stack_pop(); + f = fopen(blocks, "r+b"); + fseek(f, 4096 * block, SEEK_SET); + for (x = 0; x < 1024; x++) { + c = fetch(buffer + x); + fwrite(&c, 4, 1, f); + } + fclose(f); +} + +void process(int o) { + int a, b, target, flag; + int src, dest, len; + switch (o) { + case 0: break; + case 1: ip++; stack_push(fetch(ip)); break; + case 2: stack_push(TOS); break; + case 3: data[sp] = 0; sp--; break; + case 4: a = TOS; TOS = NOS; NOS = a; break; + case 5: rp++; TORS = stack_pop(); break; + case 6: stack_push(TORS); rp--; break; + case 7: ip = stack_pop() - 1; break; + case 8: rp++; TORS = ip; ip = stack_pop() - 1; break; + case 9: target = stack_pop(); flag = stack_pop(); + if (flag != 0) { rp++; TORS = ip; ip = target - 1; } + break; + case 10: target = stack_pop(); flag = stack_pop(); + if (flag != 0) ip = target - 1; break; + case 11: ip = TORS; rp--; break; + case 12: NOS = (NOS == TOS) ? -1 : 0; sp--; break; + case 13: NOS = (NOS != TOS) ? -1 : 0; sp--; break; + case 14: NOS = (NOS < TOS) ? -1 : 0; sp--; break; + case 15: NOS = (NOS > TOS) ? -1 : 0; sp--; break; + case 16: TOS = fetch(TOS); break; + case 17: store(TOS, NOS); sp--; sp--; break; + case 18: NOS += TOS; sp--; break; + case 19: NOS -= TOS; sp--; break; + case 20: NOS *= TOS; sp--; break; + case 21: a = TOS; b = NOS; TOS = b / a; NOS = b % a; break; + case 22: NOS = TOS & NOS; sp--; break; + case 23: NOS = TOS | NOS; sp--; break; + case 24: NOS = TOS ^ NOS; sp--; break; + case 25: NOS = NOS << TOS; sp--; break; + case 26: NOS = NOS >> TOS; sp--; break; + case 27: len = stack_pop(); dest = stack_pop(); + src = stack_pop(); flag = -1; + while (len) { + if (fetch(dest) != fetch(src)) flag = 0; + len -= 1; src += 1; dest += 1; + }; stack_push(flag); break; + case 28: len = stack_pop(); dest = stack_pop(); + src = stack_pop(); + while (len) { + store(dest, fetch(src)); + len -= 1; src += 1; dest += 1; + }; break; + case 29: switch (stack_pop()) { + case 0: putc(stack_pop(), stdout); break; + case 1: stack_push(getc(stdin)); break; + case 2: read_block(); break; + case 3: write_block(); break; + case 4: save_image(); break; + case 5: load_image(); ip = -1; break; + case 6: ip = 65536; break; + case 7: stack_push(sp); stack_push(rp); break; + default: break; + } break; + default: break; + } +} + +void process_opcode_bundle(int opcode) { + process(opcode & 0xFF); + process((opcode >> 8) & 0xFF); + process((opcode >> 16) & 0xFF); + process((opcode >> 24) & 0xFF); +} + +void execute(int address) { + ip = address; + while (ip < 65536) { + process_opcode_bundle(fetch(ip)); + ip++; + } +} + +int main(int argc, char **argv) { + int i; + + blocks = (argc > 1) ? argv[1] : "ilo.blocks"; + rom = (argc > 2) ? argv[2] : "ilo.rom"; + +#ifdef MALLOC + for (i = 0; i < SLICES; i++) + memory[i] = malloc(SLICESIZE * sizeof(int)); +#endif + load_image(); + execute(0); +#ifdef MALLOC + for (i = 0; i < SLICES; i++) + free(memory[i]); +#endif + for (i = 1; sp >= i; i++) printf(" %d", data[i]); + printf("\n"); +} diff --git a/source/ilo-be.c b/source/ilo-be.c new file mode 100644 index 0000000..5709929 --- /dev/null +++ b/source/ilo-be.c @@ -0,0 +1,215 @@ +/*************************************************************** + crc's _ _ + (_) | ___ + | | |/ _ \ a tiny virtual computer + | | | (_) | 64kw RAM, 32-bit, Dual Stack, MISC + |_|_|\___/ ilo-be.c (c) charles childers + + ilo was developed on little endian hosts, and both the ROM and + blocks are stored in little endian. This implementation adds + alternative ROM & block functions to handle the byteswapping + needed on big endian hosts. + **************************************************************/ + +#include +#include +#include + +#define T ds[sp] /* Top of Data Stack */ +#define N ds[sp-1] /* Next on Data Stack */ +#define R as[rp] /* Top of Address Stack */ +#define V void +#define I int +#define C char + +I ip, /* instruction pointer */ + sp, /* data stack pointer */ + rp, /* address stack pointer */ + ds[33], /* data stack */ + as[257], /* address stack */ + m[65536]; /* memory */ + +C *blocks, /* name of block file (ilo.blocks) */ + *rom; /* name of image (ilo.rom) */ + +/* the other variables are used by the various + functions for misc. purposes */ + +I a, b, f, s, d, l; +C i[1]; + +unsigned long byteswap(unsigned long v) { + return (((v & 0x000000FF) << 24)| + ((v & 0x0000FF00) << 8) | + ((v & 0x00FF0000) >> 8) | + ((v & 0xFF000000) >> 24)); +} + +V push(I v) { ds[sp + 1] = v; sp += 1; } +I pop() { sp -= 1; return ds[sp + 1]; } + +V load_image() { + FILE *fp; + long x, y, z; + fp = fopen(rom, "rb"); + for (y = 0; y < 65536; y++) { + x = 0; + fread(&x, 4, 1, fp); + m[y] = byteswap(x); + } + fclose(fp); + ip = sp = rp = 0; +} + +V save_image() { + FILE *fp; + long i, x; + fp = fopen(rom, "wb"); + for (i = 0; i < 65536; i++) { + x = byteswap(m[i]); + fwrite(&x, 4, 1, fp); + } + fclose(fp); +} + +V read_block() { + FILE *f; + long block, buffer, x, c; + buffer = pop(); + block = pop(); + f = fopen(blocks, "r+b"); + fseek(f, 4096 * block, SEEK_SET); + for (x = 0; x < 1024; x++) { + c = 0; + fread(&c, 4, 1, f); + m[buffer + x] = byteswap(c); + } + fclose(f); +} + +V write_block() { + FILE *f; + long block, buffer, x, c; + buffer = pop(); + block = pop(); + f = fopen(blocks, "r+b"); + fseek(f, 4096 * block, SEEK_SET); + for (x = 0; x < 1024; x++) { + c = byteswap(m[buffer + x]); + fwrite(&c, 4, 1, f); + } + fclose(f); +} + +V save_ip() { rp += 1; R = ip; } +V symmetric() { if (b >= 0 && N < 0) { T += 1; N -= b; } } + +V li() { ip += 1; push(m[ip]); } +V du() { push(T); } +V dr() { ds[sp] = 0; sp -= 1; } +V sw() { a = T; T = N; N = a; } +V pu() { rp += 1; R = pop(); } +V po() { push(R); rp -= 1; } +V ju() { ip = pop() - 1; } +V ca() { save_ip(); ip = pop() - 1; } +V cc() { a = pop(); if (pop()) { save_ip(); ip = a - 1; } } +V cj() { a = pop(); if (pop()) { ip = a - 1; } } +V re() { ip = R; rp -= 1; } +V eq() { N = (N == T) ? -1 : 0; sp -= 1; } +V ne() { N = (N != T) ? -1 : 0; sp -= 1; } +V lt() { N = (N < T) ? -1 : 0; sp -= 1; } +V gt() { N = (N > T) ? -1 : 0; sp -= 1; } +V fe() { T = m[T]; } +V st() { m[T] = N; sp -= 2; } +V ad() { N += T; sp -= 1; } +V su() { N -= T; sp -= 1; } +V mu() { N *= T; sp -= 1; } +V di() { a = T; b = N; T = b / a; N = b % a; symmetric(); } +V an() { N = T & N; sp -= 1; } +V or() { N = T | N; sp -= 1; } +V xo() { N = T ^ N; sp -= 1; } +V sl() { N = N << T; sp -= 1; } +V sr() { N = N >> T; sp -= 1; } +V cp() { l = pop(); d = pop(); s = T; T = -1; + while (l) { if (m[d] != m[s]) { T = 0; } + l -= 1; s += 1; d += 1; } } +V cy() { l = pop(); d = pop(); s = pop(); + while (l) { m[d] = m[s]; l -= 1; s += 1; d += 1; } } +V ioa() { i[0] = (char)pop(); write(1, &i, 1); } +V iob() { read(0, &i, 1); push(i[0]); } +V ioc() { read_block(); } +V iod() { write_block(); } +V ioe() { save_image(); } +V iof() { load_image(); ip = -1; } +V iog() { ip = 65536; } +V ioh() { push(sp); push(rp); } +V io() { + switch (pop()) { + case 0: ioa(); break; case 1: iob(); break; + case 2: ioc(); break; case 3: iod(); break; + case 4: ioe(); break; case 5: iof(); break; + case 6: iog(); break; case 7: ioh(); break; + default: break; + } +} + +/* Using a switch here instead of a jump table to avoid */ +/* some issues w/relocation stuff when building w/o libc */ + +V process(I o) { + switch (o) { + case 0: break; case 1: li(); break; + case 2: du(); break; case 3: dr(); break; + case 4: sw(); break; case 5: pu(); break; + case 6: po(); break; case 7: ju(); break; + case 8: ca(); break; case 9: cc(); break; + case 10: cj(); break; case 11: re(); break; + case 12: eq(); break; case 13: ne(); break; + case 14: lt(); break; case 15: gt(); break; + case 16: fe(); break; case 17: st(); break; + case 18: ad(); break; case 19: su(); break; + case 20: mu(); break; case 21: di(); break; + case 22: an(); break; case 23: or(); break; + case 24: xo(); break; case 25: sl(); break; + case 26: sr(); break; case 27: cp(); break; + case 28: cy(); break; case 29: io(); break; + default: break; + } +} + +V process_bundle(I opcode) { + process(opcode & 0xFF); + process((opcode >> 8) & 0xFF); + process((opcode >> 16) & 0xFF); + process((opcode >> 24) & 0xFF); +} + +V execute() { + while (ip < 65536) { + process_bundle(m[ip]); + ip += 1; + } +} + +#ifndef NOSTDLIB + +I main(I argc, C **argv) { + blocks = (argc > 1) ? argv[1] : "ilo.blocks"; + rom = (argc > 2) ? argv[2] : "ilo.rom"; + load_image(); + execute(); + for (; sp > 0; sp -= 1) printf(" %d", ds[sp]); printf("\n"); + return 0; +} + +#else + +I main(I argc, C **argv) { + blocks = "ilo.blocks"; + rom = "ilo.rom"; + load_image(); + execute(); + return 0; +} + +#endif diff --git a/source/ilo-dos.c b/source/ilo-dos.c new file mode 100644 index 0000000..d3fb668 --- /dev/null +++ b/source/ilo-dos.c @@ -0,0 +1,191 @@ +/*************************************************************** + crc's _ _ + (_) | ___ + | | |/ _ \ a tiny virtual computer + | | | (_) | 64kw RAM, 32-bit, Dual Stack, MISC + |_|_|\___/ ilo.c (c) charles childers + **************************************************************/ + +/* This implementation uses memory separated into multiple + banks. This makes it easier to run on systems with less + RAM. */ + +#include +#include + +#define SLICES 8 +#define SLICESIZE 8192 + +long ip, sp, rp, data[33], address[257]; +long *memory[SLICES]; + +#define TOS data[sp] +#define NOS data[sp-1] +#define TORS address[rp] + +long pop() { + sp--; + return data[sp + 1]; +} + +void push(long value) { + sp++; + data[sp] = value; +} + +void store(long a, long v) { + long slice = a / SLICESIZE; + long actual = a - (slice * SLICESIZE); + memory[slice][actual] = v; +} + +long fetch(long a) { + long slice = a / SLICESIZE; + long actual = a - (slice * SLICESIZE); + return memory[slice][actual]; +} + +void prepare_vm() { + for (ip = 0; ip < 32; ip++) data[ip] = 0; + for (ip = 0; ip < 128; ip++) address[ip] = 0; + ip = sp = rp = 0; +} + +void load_image() { + FILE *fp; + long x, y; + fp = fopen("ilo.rom", "rb"); + for (y = 0; y < 65536; y++) { + x = 0; + fread(&x, 4, 1, fp); + store(y, x); + } + fclose(fp); + prepare_vm(); +} + +void save_image() { + FILE *fp; + long i; + fp = fopen("ilo.rom", "wb"); + for (i = 0; i < SLICES; i++) + fwrite(&memory[i], sizeof(long), SLICESIZE, fp); + fclose(fp); +} + +void read_block() { + FILE *f; + long block, buffer, x, c; + buffer = pop(); + block = pop(); + f = fopen("ilo.blo", "r+b"); + fseek(f, 4096 * block, SEEK_SET); + for (x = 0; x < 1024; x++) { + c = 0; + fread(&c, 4, 1, f); + store(buffer + x, c); + } + fclose(f); +} + +void write_block() { + FILE *f; + long block, buffer, x, c; + buffer = pop(); + block = pop(); + f = fopen("ilo.blo", "r+b"); + fseek(f, 4096 * block, SEEK_SET); + for (x = 0; x < 1024; x++) { + c = fetch(buffer + x); + fwrite(&c, 4, 1, f); + } + fclose(f); +} + +void process(long o) { + long a, b, target, flag; + long src, dest, len; + switch (o) { + case 0: break; + case 1: ip++; push(fetch(ip)); break; + case 2: push(TOS); break; + case 3: data[sp] = 0; sp--; break; + case 4: a = TOS; TOS = NOS; NOS = a; break; + case 5: rp++; TORS = pop(); break; + case 6: push(TORS); rp--; break; + case 7: ip = pop() - 1; break; + case 8: rp++; TORS = ip; ip = pop() - 1; break; + case 9: target = pop(); flag = pop(); + if (flag != 0) { rp++; TORS = ip; ip = target - 1; } + break; + case 10: target = pop(); flag = pop(); + if (flag != 0) ip = target - 1; break; + case 11: ip = TORS; rp--; break; + case 12: NOS = (NOS == TOS) ? -1 : 0; sp--; break; + case 13: NOS = (NOS != TOS) ? -1 : 0; sp--; break; + case 14: NOS = (NOS < TOS) ? -1 : 0; sp--; break; + case 15: NOS = (NOS > TOS) ? -1 : 0; sp--; break; + case 16: TOS = fetch(TOS); break; + case 17: store(TOS, NOS); sp--; sp--; break; + case 18: NOS += TOS; sp--; break; + case 19: NOS -= TOS; sp--; break; + case 20: NOS *= TOS; sp--; break; + case 21: a = TOS; b = NOS; TOS = b / a; NOS = b % a; break; + case 22: NOS = TOS & NOS; sp--; break; + case 23: NOS = TOS | NOS; sp--; break; + case 24: NOS = TOS ^ NOS; sp--; break; + case 25: NOS = NOS << TOS; sp--; break; + case 26: NOS = NOS >> TOS; sp--; break; + case 27: len = pop(); dest = pop(); + src = pop(); flag = -1; + while (len) { + if (fetch(dest) != fetch(src)) flag = 0; + len -= 1; src += 1; dest += 1; + }; push(flag); break; + case 28: len = pop(); dest = pop(); + src = pop(); + while (len) { + store(dest, fetch(src)); + len -= 1; src += 1; dest += 1; + }; break; + case 29: switch (pop()) { + case 0: putc(pop(), stdout); break; + case 1: push(getc(stdin)); break; + case 2: read_block(); break; + case 3: write_block(); break; + case 4: save_image(); break; + case 5: load_image(); ip = -1; break; + case 6: ip = 65536; break; + case 7: push(sp); push(rp); break; + default: break; + } break; + default: break; + } +} + +void process_opcode_bundle(long opcode) { + process(opcode & 0xFF); + process((opcode >> 8) & 0xFF); + process((opcode >> 16) & 0xFF); + process((opcode >> 24) & 0xFF); +} + +void execute(long address) { + ip = address; + while (ip < 65536) { + process_opcode_bundle(fetch(ip)); + ip++; + } +} + +int main(long argc, char **argv) { + long i; + for (i = 0; i < SLICES; i++) + memory[i] = malloc(SLICESIZE * sizeof(long)); + load_image(); + execute(0); + for (i = 0; i < SLICES; i++) + free(memory[i]); + for (i = 1; sp >= i; i++) printf(" %d", data[i]); + printf("\n"); +} diff --git a/source/ilo-js.html b/source/ilo-js.html new file mode 100644 index 0000000..b57fe37 --- /dev/null +++ b/source/ilo-js.html @@ -0,0 +1,701 @@ + + + +ilo.js :: Konilo in the Browser + + + + + + + + + + + (using default image & blocks) +
+ +
+ + +
+ Use your own image & blocks.


+ ROM ::::
+ Blocks :
+
+ +
+ --CONFIG--


+ Max lines ::::::::::::::
+ Cycles Between Updates :
+
COLORS + + + + + + + +
+
+
+ + +
+ + + + + + + + diff --git a/source/ilo-min.c b/source/ilo-min.c new file mode 100644 index 0000000..2b1d959 --- /dev/null +++ b/source/ilo-min.c @@ -0,0 +1,71 @@ +/* ilo-min.c (c) charles childers */ +#include +#include +#include +#define V void +#define I int +#define C char +#define T s[sp] +#define N s[sp-1] +#define R r[rp] +#define G s[(--sp)+1] +#define D sp-- +#define P(x) s[++sp]=x +#define F(x,y) f=open(rf,x,0666);y;close(f) +#define B(x,y) f=open(bf,x,0666);b_s();y;close(f) +#define W(x) while(c){x;c--;a++;b++;} +#define X(x) inst[(o>>x)&0xFF]() +#define RUN while(ip<65536) +#define DR "ilo.rom" +#define DB "ilo.blocks" +I ip,sp,rp,s[33],r[257],m[65536],a,b,c,f,o; C *bf,*rf; +V rst() {ip=sp=rp=0;} +V i_l() {F(O_RDONLY,read(f,&m,262144)); rst();} +V i_w() {F(O_WRONLY,write(f,&m,262144));} +V b_s() {a=G; b=G; lseek(f,4096*b,SEEK_SET);} +V b_l() {B(O_RDONLY,read(f,m+a,4096));} +V b_w() {B(O_WRONLY,write(f,m+a,4096));} +V p() {c=G; b=G; a=G;} +V no() {} +V li() {ip++; P(m[ip]);} +V du() {a=T; P(a);} +V dr() {s[sp]=0; D;} +V sw() {a=T; T=N; N=a;} +V pu() {rp++; R=G;} +V po() {P(R); rp--;} +V ju() {ip=G-1;} +V ca() {rp++; R=ip; ip=G-1;} +V cc() {a=G; if (G != 0) {rp++; R=ip; ip=a-1;}} +V cj() {a=G; if (G != 0) ip=a-1;} +V re() {ip=R; rp--;} +V eq() {N=(N == T) ? -1 : 0; D;} +V ne() {N=(N != T) ? -1 : 0; D;} +V lt() {N=(N < T) ? -1 : 0; D;} +V gt() {N=(N > T) ? -1 : 0; D;} +V fe() {T = m[T];} +V st() {m[T]=N; D; D;} +V ad() {N += T; D;} +V su() {N -= T; D;} +V mu() {N *= T; D;} +V di() {a=T; b=N; T=b/a; N=b%a;} +V an() {N=T & N; D;} +V or() {N=T | N; D;} +V xo() {N=T ^ N; D;} +V sl() {N=T << N; D;} +V sr() {N=T >> N; D;} +V cp() {p(); P(-1); W(if(m[b]!=m[a])T=0);} +V cy() {p(); W(m[b]=m[a])} +V i0() {putc(G,stdout);} +V i1() {P(getc(stdin));} +V i5() {i_l(); ip=-1;} +V i6() {ip=65536;} +V i7() {a=sp; P(a); P(rp);} +V (*ix[8])() = {i0, i1, b_l, b_w, i_w, i5, i6, i7}; +V io() {ix[G]();} +V (*inst[30])()={ + no, li, du, dr, sw, pu, po, ju, ca, cc, cj, re, eq, ne, lt, + gt, fe, st, ad, su, mu, di, an, or, xo, sl, sr, cp, cy, io}; +V execute() {RUN{o=m[ip]; X(0); X(8); X(16); X(24); ip++;}} +V ds() {for (;sp>0;D) printf("#%d: %d\n", sp, s[sp]);} +V run() {i_l(); execute(); ds();} +I main(I n, C **v) {bf=(n>1)?v[1]:DB; rf=(n>2)?v[2]:DR; run();} diff --git a/source/ilo-plan9.c b/source/ilo-plan9.c new file mode 100644 index 0000000..d43a6d5 --- /dev/null +++ b/source/ilo-plan9.c @@ -0,0 +1,205 @@ +/*********************************** + ilo-plan9.c (C) Jim Taylor + + Example compilation (amd64): + 6c ilo-plan9.c + 6l -o ilo ilo-plan9.6 + + May want to run it with vt. +***********************************/ + +#include +#include + +#define T ds[sp] /* Top of Data Stack */ +#define N ds[sp-1] /* Next on Data Stack */ +#define R as[rp] /* Top of Address Stack */ +#define INST(c_name); void c_name(void) /* Shorthand for VM INSTructions */ + +int ip, /* instruction pointer */ + sp, /* data stack pointer */ + rp, /* address stack pointer */ + ds[33], /* data stack */ + as[257], /* address stack */ + m[65536]; /* memory */ + +char *blocks, /* name of block file (ilo.blocks) */ + *rom; /* name of image (ilo.rom) */ + +int a, b, fd, s, d, l; +char i[1]; + +void +push(int v) +{ + ds[sp+1] = v; + sp += 1; +} + +int +pop(void) +{ + sp -= 1; + return ds[sp+1]; +} + +void +load_image(void) +{ + fd = open(rom, OREAD); + if(!fd) + return; + read(fd, &m, 65536*4); + close(fd); + ip = sp = rp = 0; +} + +void +save_image(void) +{ + fd = open(rom, OWRITE); + write(fd, &m, 65536*4); + close(fd); +} + +void +block_common(void) +{ + b = pop(); /* block buffer */ + a = pop(); /* block number */ + seek(fd, 4096*a, 0); +} + +void +read_block(void) +{ + fd = open(blocks, OREAD); + block_common(); + read(fd, m+b, 4096); + close(fd); +} + +void +write_block(void) +{ + fd = open(blocks, OWRITE); + block_common(); + write(fd, m+b, 4096); + close(fd); +} + +void save_ip(void) { rp += 1; R = ip; } +void symmetric(void) { if (b >= 0 && N < 0) { T += 1; N -= b; } } + +INST(li) { ip += 1; push(m[ip]); } +INST(du) { push(T); } +INST(dr) { ds[sp] = 0; sp -= 1; } +INST(sw) { a = T; T = N; N = a; } +INST(pu) { rp += 1; R = pop(); } +INST(po) { push(R); rp -= 1; } +INST(ju) { ip = pop() - 1; } +INST(ca) { save_ip(); ip = pop() - 1; } +INST(cc) { a = pop(); if (pop()) { save_ip(); ip = a - 1; } } +INST(cj) { a = pop(); if (pop()) { ip = a - 1; } } +INST(re) { ip = R; rp -= 1; } +INST(eq) { N = (N == T) ? -1 : 0; sp -= 1; } +INST(ne) { N = (N != T) ? -1 : 0; sp -= 1; } +INST(lt) { N = (N < T) ? -1 : 0; sp -= 1; } +INST(gt) { N = (N > T) ? -1 : 0; sp -= 1; } +INST(fe) { T = m[T]; } +INST(st) { m[T] = N; sp -= 2; } +INST(ad) { N += T; sp -= 1; } +INST(su) { N -= T; sp -= 1; } +INST(mu) { N *= T; sp -= 1; } +INST(di) { a = T; b = N; T = b / a; N = b % a; symmetric(); } +INST(an) { N = T & N; sp -= 1; } +INST(or) { N = T | N; sp -= 1; } +INST(xo) { N = T ^ N; sp -= 1; } +INST(sl) { N = N << T; sp -= 1; } +INST(sr) { N = N >> T; sp -= 1; } +INST(cp) +{ + l = pop(); d = pop(); + s = T; T = -1; + while(l) { + if (m[d] != m[s]) + T = 0; + l -= 1; s += 1; d += 1; + } +} +INST(cy) +{ + l = pop(); d = pop(); s = pop(); + while(l) { + m[d] = m[s]; l -= 1; s += 1; d += 1; + } +} +INST(ioa) { i[0] = (char)pop(); write(1, &i, 1); } +INST(iob) { read(0, &i, 1); push(i[0]); } +INST(ioc) { read_block(); } +INST(iod) { write_block(); } +INST(ioe) { save_image(); } +INST(iof) { load_image(); ip = -1; } +INST(iog) { ip = 65536; } +INST(ioh) { push(sp); push(rp); } +INST(io) +{ + switch (pop()) { + case 0: ioa(); break; case 1: iob(); break; + case 2: ioc(); break; case 3: iod(); break; + case 4: ioe(); break; case 5: iof(); break; + case 6: iog(); break; case 7: ioh(); break; + default: break; + } +} + +void +process(int o) +{ + switch (o) { + case 0: break; case 1: li(); break; + case 2: du(); break; case 3: dr(); break; + case 4: sw(); break; case 5: pu(); break; + case 6: po(); break; case 7: ju(); break; + case 8: ca(); break; case 9: cc(); break; + case 10: cj(); break; case 11: re(); break; + case 12: eq(); break; case 13: ne(); break; + case 14: lt(); break; case 15: gt(); break; + case 16: fe(); break; case 17: st(); break; + case 18: ad(); break; case 19: su(); break; + case 20: mu(); break; case 21: di(); break; + case 22: an(); break; case 23: or(); break; + case 24: xo(); break; case 25: sl(); break; + case 26: sr(); break; case 27: cp(); break; + case 28: cy(); break; case 29: io(); break; + default: break; + } +} + +void +process_bundle(int opcode) +{ + process(opcode & 0xFF); + process((opcode >> 8) & 0xFF); + process((opcode >> 16) & 0xFF); + process((opcode >> 24) & 0xFF); +} + +void +execute(void) +{ + while(ip < 65536) { + process_bundle(m[ip]); + ip += 1; + } +} + +void +main() +{ + blocks = "ilo.blocks"; + rom = "ilo.rom"; + load_image(); + execute(); + exits(nil); +} diff --git a/source/ilo-pthread.c b/source/ilo-pthread.c new file mode 100644 index 0000000..15e0a49 --- /dev/null +++ b/source/ilo-pthread.c @@ -0,0 +1,183 @@ +/*************************************************************** + crc's _ _ + (_) | ___ + | | |/ _ \ a tiny virtual computer + | | | (_) | 64kw RAM, 32-bit, Dual Stack, MISC + |_|_|\___/ ilo.c (c) charles childers + **************************************************************/ + +/* cc -lpthread ilo-pthread.c -o ilo */ + +#include +#include +#include +#include +#include + +int ip, sp, rp, data[33], address[257], memory[65536]; +int a, b, t, fp, block, buffer, src, dest, len; +char *blocks, *rom, iob[2]; + +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + +#define T data[sp] +#define N data[sp-1] +#define R address[rp] +#define V void + +int pop() { return data[(--sp) + 1]; } +V push(int value) { data[++sp] = value; } + +V prepare_vm() { ip = sp = rp = 0; } + +V load_image() { + fp = open(rom, O_RDONLY, 0666); + if (!fp) { return; }; + read(fp, &memory, 65536 * 4); + close(fp); + prepare_vm(); +} + +V save_image() { + fp = open(rom, O_WRONLY, 0666); + write(fp, &memory, 65536 * 4); + close(fp); +} + +V read_block() { + buffer = pop(); + block = pop(); + fp = open(blocks, O_RDONLY, 0666); + lseek(fp, 4096 * block, SEEK_SET); + read(fp, memory + buffer, 4096); + close(fp); +} + +V write_block() { + buffer = pop(); + block = pop(); + fp = open(blocks, O_WRONLY, 0666); + lseek(fp, 4096 * block, SEEK_SET); + write(fp, memory + buffer, 4096); + close(fp); +} + +V li() { ip++; push(memory[ip]); } +V du() { push(T); } +V dr() { data[sp] = 0; sp--; } +V sw() { a = T; T = N; N = a; } +V pu() { rp++; R = pop(); } +V po() { push(R); rp--; } +V ju() { ip = pop() - 1; } +V ca() { rp++; R = ip; ip = pop() - 1; } +V cc() { t = pop(); if (pop()) { rp++; R = ip; ip = t - 1; } } +V cj() { t = pop(); if (pop()) { ip = t - 1; } } +V re() { ip = R; rp--; } +V eq() { N = (N == T) ? -1 : 0; sp--; } +V ne() { N = (N != T) ? -1 : 0; sp--; } +V lt() { N = (N < T) ? -1 : 0; sp--; } +V gt() { N = (N > T) ? -1 : 0; sp--; } +V fe() { T = memory[T]; } +V st() { memory[T] = N; sp--; sp--; } +V ad() { N += T; sp--; } +V su() { N -= T; sp--; } +V mu() { N *= T; sp--; } +V di() { a = T; b = N; T = b / a; N = b % a; } +V an() { N = T & N; sp--; } +V or() { N = T | N; sp--; } +V xo() { N = T ^ N; sp--; } +V sl() { N = N << T; sp--; } +V sr() { N = N >> T; sp--; } +V cp() { len = pop(); dest = pop(); src = pop(); push(-1); + while (len) { + if (memory[dest] != memory[src]) T = 0; + len -= 1; src += 1; dest += 1; + } + } +V cy() { len = pop(); dest = pop(); src = pop(); + while (len) { + memory[dest] = memory[src]; + len -= 1; src += 1; dest += 1; + } + } +V io() { + switch (pop()) { + case 0: + iob[0] = pop(); write(1, &iob, 1); + break; + case 1: push(getchar()); break; + case 2: read_block(); break; + case 3: write_block(); break; + case 4: save_image(); break; + case 5: load_image(); ip = -1; break; + case 6: ip = 65536; exit(0); break; + case 7: push(sp); push(rp); break; + default: break; + } +} + +V process(int o) { + switch (o) { + case 0: break; case 1: li(); break; + case 2: du(); break; case 3: dr(); break; + case 4: sw(); break; case 5: pu(); break; + case 6: po(); break; case 7: ju(); break; + case 8: ca(); break; case 9: cc(); break; + case 10: cj(); break; case 11: re(); break; + case 12: eq(); break; case 13: ne(); break; + case 14: lt(); break; case 15: gt(); break; + case 16: fe(); break; case 17: st(); break; + case 18: ad(); break; case 19: su(); break; + case 20: mu(); break; case 21: di(); break; + case 22: an(); break; case 23: or(); break; + case 24: xo(); break; case 25: sl(); break; + case 26: sr(); break; case 27: cp(); break; + case 28: cy(); break; case 29: io(); break; + default: break; + } +} + +V process_bundle(int opcode) { + process(opcode & 0xFF); + process((opcode >> 8) & 0xFF); + process((opcode >> 16) & 0xFF); + process((opcode >> 24) & 0xFF); +} + +V *execute(V *unused) { + while (ip < 65536) { + pthread_mutex_lock(&mutex); + process_bundle(memory[ip]); + ip++; + pthread_mutex_unlock(&mutex); + pthread_yield(); + } + return 0; +} + +V *guard(V *unused) { + while (1) { + if (sp < 0) { printf("E: data stack underflow\n"); exit(1); } + if (sp > 31) { printf("E: data stack overflow\n"); exit(2); } + if (rp < 0) { printf("E: address stack underflow\n"); exit(3); } + if (rp > 255) { printf("E: address stack overflow\n"); exit(4); } + pthread_yield(); + } + return 0; +} + +int main(int argc, char **argv) { + blocks = (argc > 1) ? argv[1] : "ilo.blocks"; + rom = (argc > 2) ? argv[2] : "ilo.rom"; + load_image(); + + pthread_t cpu, stack_guard; + int e1 = pthread_create(&cpu, NULL, execute, NULL); + int e2 = pthread_create(&stack_guard, NULL, guard, NULL); +// while(1) {pthread_yield();}; + + if (!e2) { + pthread_join(stack_guard, NULL); + pthread_join(cpu, NULL); + } +} diff --git a/source/ilo-safer.c b/source/ilo-safer.c new file mode 100644 index 0000000..97bc5a2 --- /dev/null +++ b/source/ilo-safer.c @@ -0,0 +1,197 @@ +/*************************************************************** + crc's _ _ + (_) | ___ + | | |/ _ \ a tiny virtual computer + | | | (_) | 64kw RAM, 32-bit, Dual Stack, MISC + |_|_|\___/ ilo.c (c) charles childers + **************************************************************/ + +#include +#include +#include +#include + +#define T ds[sp] /* Top of Data Stack */ +#define N ds[sp-1] /* Next on Data Stack */ +#define R as[rp] /* Top of Address Stack */ +#define V void +#define I int +#define C char + +I ip, /* instruction pointer */ + sp, /* data stack pointer */ + rp, /* address stack pointer */ + ds[33], /* data stack */ + as[257], /* address stack */ + m[65536]; /* memory */ + +C *blocks, /* name of block file (ilo.blocks) */ + *rom; /* name of image (ilo.rom) */ + +/* the other variables are used by the various + functions for misc. purposes */ + +I a, b, f, s, d, l; +C i[1]; + +V p(char *s) { while(*s) putchar(*s++); } +V e(char *s) { p("E:"); p(s); p("\n"); exit(1); } +V dso() { if ((sp + 1) > 32) { e("DSO"); } } +V dsu() { if ((sp - 1) < 0) { e("DSU"); } } +V rso() { if ((rp + 1) > 256) { e("RSO"); } } +V rsu() { if ((rp - 1) < 0) { e("RSU"); } } +V dbz() { if (T == 0) { e("DBZ"); } } +V mem() { if (T < 0 || T > 65535) { e("MEM"); } } +V uli() { if (f == -1) { e("ULI"); } } +V usi() { if (f == -1) { e("URI"); } } +V urb() { if (f == -1) { e("URB"); } } +V uwb() { if (f == -1) { e("UWB"); } } +V push(I v) { dso(); ds[sp + 1] = v; sp += 1; } +I pop() { dsu(); sp -= 1; return ds[sp + 1]; } + +V load_image() { + f = open(rom, O_RDONLY, 0666); + uli(); + read(f, &m, 65536 * 4); + close(f); + ip = sp = rp = 0; +} + +V save_image() { + f = open(rom, O_WRONLY, 0666); + usi(); + write(f, &m, 65536 * 4); + close(f); +} + +V block_common() { + b = pop(); /* block buffer */ + a = pop(); /* block number */ + lseek(f, 4096 * a, SEEK_SET); +} + +V read_block() { + f = open(blocks, O_RDONLY, 0666); + urb(); + block_common(); + read(f, m + b, 4096); + close(f); +} + +V write_block() { + f = open(blocks, O_WRONLY, 0666); + uwb(); + block_common(); + write(f, m + b, 4096); + close(f); +} + +V save_ip() { rso(); rp += 1; R = ip; } +V symmetric() { if (b >= 0 && N < 0) { T += 1; N -= b; } } + +V li() { ip += 1; push(m[ip]); } +V du() { push(T); } +V dr() { ds[sp] = 0; sp -= 1; } +V sw() { a = T; T = N; N = a; } +V pu() { rso(); rp += 1; R = pop(); } +V po() { rsu(); push(R); rp -= 1; } +V ju() { ip = pop() - 1; } +V ca() { save_ip(); ip = pop() - 1; } +V cc() { a = pop(); if (pop()) { save_ip(); ip = a - 1; } } +V cj() { a = pop(); if (pop()) { ip = a - 1; } } +V re() { rsu(); ip = R; rp -= 1; } +V eq() { N = (N == T) ? -1 : 0; sp -= 1; } +V ne() { N = (N != T) ? -1 : 0; sp -= 1; } +V lt() { N = (N < T) ? -1 : 0; sp -= 1; } +V gt() { N = (N > T) ? -1 : 0; sp -= 1; } +V fe() { mem(); T = m[T]; } +V st() { mem(); m[T] = N; sp -= 2; } +V ad() { N += T; sp -= 1; } +V su() { N -= T; sp -= 1; } +V mu() { N *= T; sp -= 1; } +V di() { dbz(); + a = T; b = N; T = b / a; N = b % a; symmetric(); } +V an() { N = T & N; sp -= 1; } +V or() { N = T | N; sp -= 1; } +V xo() { N = T ^ N; sp -= 1; } +V sl() { N = N << T; sp -= 1; } +V sr() { N = N >> T; sp -= 1; } +V cp() { l = pop(); d = pop(); s = T; T = -1; + while (l) { if (m[d] != m[s]) { T = 0; } + l -= 1; s += 1; d += 1; } } +V cy() { l = pop(); d = pop(); s = pop(); + while (l) { m[d] = m[s]; l -= 1; s += 1; d += 1; } } +V ioa() { i[0] = (char)pop(); write(1, &i, 1); } +V iob() { read(0, &i, 1); push(i[0]); } +V ioc() { read_block(); } +V iod() { write_block(); } +V ioe() { save_image(); } +V iof() { load_image(); ip = -1; } +V iog() { ip = 65536; } +V ioh() { push(sp); push(rp); } +V io() { + switch (pop()) { + case 0: ioa(); break; case 1: iob(); break; + case 2: ioc(); break; case 3: iod(); break; + case 4: ioe(); break; case 5: iof(); break; + case 6: iog(); break; case 7: ioh(); break; + default: break; + } +} + +/* Using a switch here instead of a jump table to avoid */ +/* some issues w/relocation stuff when building w/o libc */ + +V process(I o) { + switch (o) { + case 0: break; case 1: li(); break; + case 2: du(); break; case 3: dr(); break; + case 4: sw(); break; case 5: pu(); break; + case 6: po(); break; case 7: ju(); break; + case 8: ca(); break; case 9: cc(); break; + case 10: cj(); break; case 11: re(); break; + case 12: eq(); break; case 13: ne(); break; + case 14: lt(); break; case 15: gt(); break; + case 16: fe(); break; case 17: st(); break; + case 18: ad(); break; case 19: su(); break; + case 20: mu(); break; case 21: di(); break; + case 22: an(); break; case 23: or(); break; + case 24: xo(); break; case 25: sl(); break; + case 26: sr(); break; case 27: cp(); break; + case 28: cy(); break; case 29: io(); break; + default: break; + } +} + +#define INST(n) ((opcode >> n) & 0xFF) != 0 + +V process_bundle(I opcode) { + if (INST(0)) process(opcode & 0xFF); + if (INST(8)) process((opcode >> 8) & 0xFF); + if (INST(16)) process((opcode >> 16) & 0xFF); + if (INST(24)) process((opcode >> 24) & 0xFF); +} + +V execute() { + while (ip < 65536) { + process_bundle(m[ip]); + ip += 1; + } +} + +V add_restrictions() { +#ifdef __OpenBSD__ + unveil(blocks, "rw"); + unveil(rom, "rw"); + pledge("stdio rpath wpath", NULL); +#endif +} + +I main(I argc, C **argv) { + blocks = (argc > 1) ? argv[1] : "ilo.blocks"; + rom = (argc > 2) ? argv[2] : "ilo.rom"; + add_restrictions(); + load_image(); + execute(); + return 0; +} diff --git a/source/ilo-teensy41.ino b/source/ilo-teensy41.ino new file mode 100644 index 0000000..11c1f28 --- /dev/null +++ b/source/ilo-teensy41.ino @@ -0,0 +1,267 @@ +// ============================================================= +// crc's _ _ +// (_) | ___ +// | | |/ _ \ a tiny virtual computer +// | | | (_) | 64kw RAM, 32-bit, Dual Stack, MISC +// |_|_|\___/ ilo-teensy41.ino (c) charles childers +// ============================================================ +// This is an ilo for the Teensy 4.1. It derives from the +// ilo-banked.c, as with the DOS & Mac System 5/6/7 ports. +// +// Requirements: +// +// - Teensy 4.1 +// - FAT formatted SD card containing these files: +// - ilo.rom (the system image) +// - ilo.blo (the data blocks) +// - A serial terminal interface +// +// ============================================================ + +#include +#include + +#define VERBOSE + +#define SLICES 64 +#define SLICESIZE (65536/SLICES) + +int ip, sp, rp, data[33], address[257]; +char *blocks, *rom; +extern int image[]; + +int *memory[SLICES]; + +#define TOS data[sp] +#define NOS data[sp-1] +#define TORS address[rp] + +#define I int +#define V void + +I pop() { sp--; return data[sp + 1]; } +V push(int value) { sp++; data[sp] = value; } + +V store(int a, int v) { + int slice = a / SLICESIZE; + int actual = a - (slice * SLICESIZE); + memory[slice][actual] = v; +} + +int fetch(int a) { + int slice = a / SLICESIZE; + int actual = a - (slice * SLICESIZE); + return memory[slice][actual]; +} + +V xlog(const char *s, int eol) { +#ifdef VERBOSE + if (eol) + Serial.println(s); + else + Serial.print(s); +#endif +} + +V load_image() { + File rom = SD.open("ilo.rom", FILE_READ); + int data; + xlog("ilo: load rom", 1); + for (int x = 0; x < 65536; x++) { + data = 0; + rom.read(&data, 4); + store(x, data); + if ((x % 1024) == 0) xlog(".", 0); + } + rom.close(); + delay(10); + xlog("\nilo: rom loaded", 1); +} + +V prepare_vm() { + for (ip = 0; ip < 32; ip++) data[ip] = 0; + for (ip = 0; ip < 128; ip++) address[ip] = 0; + ip = sp = rp = 0; +} + +V read_block() { + File blocks = SD.open("ilo.blo", FILE_READ); + int data; + int buf = pop(); + int blk = pop(); + blocks.seek(4096 * blk); + for (int x = 0; x < 1024; x++) { + data = 0; + blocks.read(&data, 4); + store(buf + x, data); + } + blocks.close(); + delay(10); +} + +V write_block() { + File blocks = SD.open("ilo.blo", FILE_WRITE); + int data; + int buf = pop(); + int blk = pop(); + blocks.seek(4096 * blk); + for (int x = 0; x < 1024; x++) { + data = fetch(buf + x); + blocks.write(&data, 4); + } + blocks.close(); + delay(10); +} + +int led = 13; + +V teensy_io() { + int a, b, c, d, e, f; + switch (pop()) { + case 1: digitalWrite(pop(), HIGH); + break; + case 2: digitalWrite(pop(), LOW); + break; + case 3: a = pop(); + b = pop(); + pinMode(b, a); + break; + case 4: digitalRead(pop()) ? push(-1) : push(0); + break; + case 10: delay(pop()); + break; + case 11: delayMicroseconds(pop()); + break; + case 12: delayNanoseconds(pop()); + break; + case 20: push(hour()); + break; + case 21: push(minute()); + break; + case 22: push(second()); + break; + case 23: push(day()); + break; + case 24: push(month()); + break; + case 25: push(year()); + break; + } +} + +V process(int o) { + int a, b, target, flag; + int src, dest, len, kkk; + char outstr[2] = {'a', 0}; + switch (o) { + case 0: break; + case 1: ip++; push(fetch(ip)); break; + case 2: push(TOS); break; + case 3: data[sp] = 0; sp--; break; + case 4: a = TOS; TOS = NOS; NOS = a; break; + case 5: rp++; TORS = pop(); break; + case 6: push(TORS); rp--; break; + case 7: ip = pop() - 1; break; + case 8: rp++; TORS = ip; ip = pop() - 1; break; + case 9: target = pop(); flag = pop(); + if (flag != 0) { rp++; TORS = ip; ip = target - 1; } + break; + case 10: target = pop(); flag = pop(); + if (flag != 0) ip = target - 1; break; + case 11: ip = TORS; rp--; break; + case 12: NOS = (NOS == TOS) ? -1 : 0; sp--; break; + case 13: NOS = (NOS != TOS) ? -1 : 0; sp--; break; + case 14: NOS = (NOS < TOS) ? -1 : 0; sp--; break; + case 15: NOS = (NOS > TOS) ? -1 : 0; sp--; break; + case 16: TOS = fetch(TOS); break; + case 17: store(TOS, NOS); sp--; sp--; break; + case 18: NOS += TOS; sp--; break; + case 19: NOS -= TOS; sp--; break; + case 20: NOS *= TOS; sp--; break; + case 21: a = TOS; b = NOS; TOS = b / a; NOS = b % a; break; + case 22: NOS = TOS & NOS; sp--; break; + case 23: NOS = TOS | NOS; sp--; break; + case 24: NOS = TOS ^ NOS; sp--; break; + case 25: NOS = NOS << TOS; sp--; break; + case 26: NOS = NOS >> TOS; sp--; break; + case 27: len = pop(); dest = pop(); + src = pop(); flag = -1; + while (len) { + if (fetch(dest) != fetch(src)) flag = 0; + len -= 1; src += 1; dest += 1; + }; push(flag); break; + case 28: len = pop(); dest = pop(); + src = pop(); + while (len) { + store(dest, fetch(src)); + len -= 1; src += 1; dest += 1; + }; break; + case 29: switch (pop()) { + case 0: outstr[0] = pop(); Serial.print(outstr); + if (outstr[0] == 10) { outstr[0] = 13; Serial.print(outstr); } break; + case 1: kkk = 0; while (kkk <= 0) { kkk = Serial.read(); } + outstr[0] = kkk; Serial.print(outstr); + if (kkk == 13) { kkk = 10; } + push(kkk); break; + case 2: read_block(); break; + case 3: write_block(); break; + case 4: break; + case 5: ip = -1; break; + case 6: ip = 65536; break; + case 7: push(sp); push(rp); break; + case 100: teensy_io(); break; + default: break; + } break; + default: break; + } +} + +V execute() { + int opcode, o; + ip = 0; + while (ip < 65536) { + opcode = fetch(ip); + o = opcode & 0xFF; if (o) process(o); + o = (opcode >> 8) & 0xFF; if (o) process(o); + o = (opcode >> 16) & 0xFF; if (o) process(o); + o = (opcode >> 24) & 0xFF; if (o) process(o); + ip++; + } +} + +// the setup routine runs once when you press reset: +V setup() { + Serial.begin(9600); + xlog("ilo: prepare memory", 1); + int i; + for (i = 0; i < SLICES; i++) + memory[i] = (int *)malloc(SLICESIZE * sizeof(int)); + + xlog("ilo: prepare i/o pins", 1); + pinMode(led, OUTPUT); + + xlog("ilo: check for SD card", 1); + if (!SD.begin(BUILTIN_SDCARD)) { + xlog("!!!! card failed, or not present; check SD card and restart", 1); + while (1); + } + + xlog("ilo: check for ilo.rom", 1); + if (!SD.exists("ilo.rom")) { + xlog("!!!! missing ilo.rom; check SD card and restart", 1); + while (1); + } + + xlog("ilo: check for ilo.blo", 1); + if (!SD.exists("ilo.blo")) { + xlog("!!!! missing ilo.blo; check SD card and restart", 1); + while (1); + } +} + +// the loop routine runs over and over again forever: +V loop() { + prepare_vm(); + load_image(); + execute(); +} diff --git a/source/ilo-windows.c b/source/ilo-windows.c new file mode 100644 index 0000000..5c38865 --- /dev/null +++ b/source/ilo-windows.c @@ -0,0 +1,141 @@ +/* ilo-windows.c (c) 2022, charles childers */ + +#include +#include + +int ip, sp, rp, data[33], address[257], memory[65536]; +char *blocks, *rom; + +#define T data[sp] +#define N data[sp-1] +#define R address[rp] + +int pop() { return data[(--sp) + 1]; } +void push(int value) { data[++sp] = value; } + +void prepare_vm() { ip = sp = rp = 0; } + +void load_image() { + int fp; + fp = open(rom, O_RDONLY, 0666); + if (!fp) return; + read(fp, &memory, 65536 * sizeof(int)); + close(fp); + prepare_vm(); +} + +void save_image() { + int fp; + fp = open(rom, O_WRONLY, 0666); + write(fp, &memory, 65536 * sizeof(int)); + close(fp); +} + +void read_block() { + int f, block, buffer; + buffer = pop(); + block = pop(); + f = open(blocks, O_RDONLY, 0666); + lseek(f, 4096 * block, SEEK_SET); + read(f, memory + buffer, 1024 * 4); + close(f); +} + +void write_block() { + int f, block, buffer; + buffer = pop(); + block = pop(); + f = open(blocks, O_WRONLY, 0666); + lseek(f, 4096 * block, SEEK_SET); + write(f, memory + buffer, 4096); + close(f); +} + +void process(int o) { + int a, b, target, src, dest, len; + switch (o) { + case 0: break; + case 1: ip++; push(memory[ip]); break; + case 2: push(T); break; + case 3: data[sp] = 0; sp--; break; + case 4: a = T; T = N; N = a; break; + case 5: rp++; R = pop(); break; + case 6: push(R); rp--; break; + case 7: ip = pop() - 1; break; + case 8: rp++; R = ip; ip = pop() - 1; break; + case 9: target = pop(); + if (pop() != 0) { rp++; R = ip; ip = target - 1; } + break; + case 10: target = pop(); + if (pop() != 0) ip = target - 1; break; + case 11: ip = R; rp--; break; + case 12: N = (N == T) ? -1 : 0; sp--; break; + case 13: N = (N != T) ? -1 : 0; sp--; break; + case 14: N = (N < T) ? -1 : 0; sp--; break; + case 15: N = (N > T) ? -1 : 0; sp--; break; + case 16: T = memory[T]; break; + case 17: memory[T] = N; sp--; sp--; break; + case 18: N += T; sp--; break; + case 19: N -= T; sp--; break; + case 20: N *= T; sp--; break; + case 21: a = T; b = N; T = b / a; N = b % a; break; + case 22: N = T & N; sp--; break; + case 23: N = T | N; sp--; break; + case 24: N = T ^ N; sp--; break; + case 25: N = N << T; sp--; break; + case 26: N = N >> T; sp--; break; + case 27: len = pop(); dest = pop(); + src = pop(); push(-1); + while (len) { + if (memory[dest] != memory[src]) T = 0; + len -= 1; src += 1; dest += 1; + } + break; + case 28: len = pop(); dest = pop(); + src = pop(); + while (len) { + memory[dest] = memory[src]; + len -= 1; src += 1; dest += 1; + } + break; + case 29: switch (pop()) { + case 0: putc(pop(), stdout); break; + case 1: push(getc(stdin)); break; + case 2: read_block(); break; + case 3: write_block(); break; + case 4: save_image(); break; + case 5: load_image(); ip = -1; break; + case 6: ip = 65536; break; + case 7: push(sp); push(rp); break; + default: break; + } + break; + default: break; + } +} + +void process_bundle(int opcode) { + process(opcode & 0xFF); + process((opcode >> 8) & 0xFF); + process((opcode >> 16) & 0xFF); + process((opcode >> 24) & 0xFF); +} + +void execute() { + while (ip < 65536) { + process_bundle(memory[ip]); + ip++; + } +} + +void dump_stack() { + for (; sp > 0; sp--) printf(" %d", data[sp]); printf("\n"); +} + +int main(int argc, char **argv) { + blocks = (argc > 1) ? argv[1] : "ilo.blocks"; + rom = (argc > 2) ? argv[2] : "ilo.rom"; + load_image(); + execute(); + dump_stack(); +} diff --git a/source/ilo.c b/source/ilo.c new file mode 100644 index 0000000..01a8d46 --- /dev/null +++ b/source/ilo.c @@ -0,0 +1,184 @@ +/*************************************************************** + crc's _ _ + (_) | ___ + | | |/ _ \ a tiny virtual computer + | | | (_) | 64kw RAM, 32-bit, Dual Stack, MISC + |_|_|\___/ ilo.c (c) charles childers + **************************************************************/ + +#include +#include +#include + +#define T ds[sp] /* Top of Data Stack */ +#define N ds[sp-1] /* Next on Data Stack */ +#define R as[rp] /* Top of Address Stack */ +#define V void +#define I int +#define C char + +I ip, /* instruction pointer */ + sp, /* data stack pointer */ + rp, /* address stack pointer */ + ds[33], /* data stack */ + as[257], /* address stack */ + m[65536]; /* memory */ + +C *blocks, /* name of block file (ilo.blocks) */ + *rom; /* name of image (ilo.rom) */ + +/* the other variables are used by the various + functions for misc. purposes */ + +I a, b, f, s, d, l; +C i[1]; + +V push(I v) { ds[sp + 1] = v; sp += 1; } +I pop() { sp -= 1; return ds[sp + 1]; } + +V load_image() { + f = open(rom, O_RDONLY, 0666); + if (!f) { return; }; + read(f, &m, 65536 * 4); + close(f); + ip = sp = rp = 0; +} + +V save_image() { + f = open(rom, O_WRONLY, 0666); + write(f, &m, 65536 * 4); + close(f); +} + +V block_common() { + b = pop(); /* block buffer */ + a = pop(); /* block number */ + lseek(f, 4096 * a, SEEK_SET); +} + +V read_block() { + f = open(blocks, O_RDONLY, 0666); + block_common(); + read(f, m + b, 4096); + close(f); +} + +V write_block() { + f = open(blocks, O_WRONLY, 0666); + block_common(); + write(f, m + b, 4096); + close(f); +} + +V save_ip() { rp += 1; R = ip; } +V symmetric() { if (b >= 0 && N < 0) { T += 1; N -= b; } } + +V li() { ip += 1; push(m[ip]); } +V du() { push(T); } +V dr() { ds[sp] = 0; sp -= 1; } +V sw() { a = T; T = N; N = a; } +V pu() { rp += 1; R = pop(); } +V po() { push(R); rp -= 1; } +V ju() { ip = pop() - 1; } +V ca() { save_ip(); ip = pop() - 1; } +V cc() { a = pop(); if (pop()) { save_ip(); ip = a - 1; } } +V cj() { a = pop(); if (pop()) { ip = a - 1; } } +V re() { ip = R; rp -= 1; } +V eq() { N = (N == T) ? -1 : 0; sp -= 1; } +V ne() { N = (N != T) ? -1 : 0; sp -= 1; } +V lt() { N = (N < T) ? -1 : 0; sp -= 1; } +V gt() { N = (N > T) ? -1 : 0; sp -= 1; } +V fe() { T = m[T]; } +V st() { m[T] = N; sp -= 2; } +V ad() { N += T; sp -= 1; } +V su() { N -= T; sp -= 1; } +V mu() { N *= T; sp -= 1; } +V di() { a = T; b = N; T = b / a; N = b % a; symmetric(); } +V an() { N = T & N; sp -= 1; } +V or() { N = T | N; sp -= 1; } +V xo() { N = T ^ N; sp -= 1; } +V sl() { N = N << T; sp -= 1; } +V sr() { N = N >> T; sp -= 1; } +V cp() { l = pop(); d = pop(); s = T; T = -1; + while (l) { if (m[d] != m[s]) { T = 0; } + l -= 1; s += 1; d += 1; } } +V cy() { l = pop(); d = pop(); s = pop(); + while (l) { m[d] = m[s]; l -= 1; s += 1; d += 1; } } +V ioa() { i[0] = (char)pop(); write(1, &i, 1); } +V iob() { read(0, &i, 1); push(i[0]); } +V ioc() { read_block(); } +V iod() { write_block(); } +V ioe() { save_image(); } +V iof() { load_image(); ip = -1; } +V iog() { ip = 65536; } +V ioh() { push(sp); push(rp); } +V io() { + switch (pop()) { + case 0: ioa(); break; case 1: iob(); break; + case 2: ioc(); break; case 3: iod(); break; + case 4: ioe(); break; case 5: iof(); break; + case 6: iog(); break; case 7: ioh(); break; + default: break; + } +} + +/* Using a switch here instead of a jump table to avoid */ +/* some issues w/relocation stuff when building w/o libc */ + +V process(I o) { + switch (o) { + case 0: break; case 1: li(); break; + case 2: du(); break; case 3: dr(); break; + case 4: sw(); break; case 5: pu(); break; + case 6: po(); break; case 7: ju(); break; + case 8: ca(); break; case 9: cc(); break; + case 10: cj(); break; case 11: re(); break; + case 12: eq(); break; case 13: ne(); break; + case 14: lt(); break; case 15: gt(); break; + case 16: fe(); break; case 17: st(); break; + case 18: ad(); break; case 19: su(); break; + case 20: mu(); break; case 21: di(); break; + case 22: an(); break; case 23: or(); break; + case 24: xo(); break; case 25: sl(); break; + case 26: sr(); break; case 27: cp(); break; + case 28: cy(); break; case 29: io(); break; + default: break; + } +} + +V process_bundle(I opcode) { + process(opcode & 0xFF); + process((opcode >> 8) & 0xFF); + process((opcode >> 16) & 0xFF); + process((opcode >> 24) & 0xFF); +} + +V execute() { + while (ip < 65536) { + process_bundle(m[ip]); + ip += 1; + } +} + +#ifndef NOSTDLIB + +I main(I argc, C **argv) { + blocks = (argc > 1) ? argv[1] : "ilo.blocks"; + rom = (argc > 2) ? argv[2] : "ilo.rom"; + load_image(); + execute(); + for (; sp > 0; sp -= 1) printf(" %d", ds[sp]); printf("\n"); + return 0; +} + +#else + +I main(I argc, C **argv) { + blocks = "ilo.blocks"; + rom = "ilo.rom"; + load_image(); + execute(); + return 0; +} + +#endif diff --git a/source/ilo.cl b/source/ilo.cl new file mode 100644 index 0000000..90bb02f --- /dev/null +++ b/source/ilo.cl @@ -0,0 +1,327 @@ +;; ************************************************************* +;; crc's _ _ +;; (_) | ___ +;; | | |/ _ \ a tiny virtual computer +;; | | | (_) | 64kw RAM, 32-bit, Dual Stack, MISC +;; |_|_|\___/ ilo.cl (c) charles childers +;; ************************************************************* + +(declaim (optimize (speed 3) (space 0) (safety 0) (debug 0))) + +(defvar ip 0) ; instruction pointer +(defvar sp 0) ; data stack pointer +(defvar rp 0) ; address stack pointer +(defvar ds (make-array 33)) ; data stack +(defvar as (make-array 257)) ; address stack +(defvar m (make-array 65536)) ; memory + +(defvar blk (make-array 1024)) ; block buffer (i/o) +(defvar blocks "ilo.blocks") ; block file name +(defvar rom "ilo.rom") ; rom file name + +(defvar a 0) +(defvar b 0) +(defvar f 0) +(defvar s 0) +(defvar d 0) +(defvar l 0) +(defvar i (make-array 4)) +(defvar z 0) + +(defun fixint (n) + (let* ((max-value (expt 2 31)) + (unsigned-n (logand n #xffffffff))) + (cond ((> unsigned-n max-value) + (- unsigned-n (* max-value 2))) + ((< unsigned-n (- max-value)) + (+ unsigned-n (* max-value 2))) + (t unsigned-n)))) + +(defun _push (v) + (setf (aref ds (1+ sp)) (fixint v)) + (incf sp)) + +(defun _pop () + (decf sp) + (aref ds (1+ sp))) + +(defun read-integers-into-array (array filename offset) + (with-open-file (stream filename + :element-type '(unsigned-byte 8) + :direction :input) + (file-position stream offset) + (loop for i below (length array) + do (setf (svref array i) + (let ((bytes (make-array 4 + :element-type '(unsigned-byte 8)))) + (read-sequence bytes stream) + (fixint (logior (ash (aref bytes 0) 0) + (ash (aref bytes 1) 8) + (ash (aref bytes 2) 16) + (ash (aref bytes 3) 24)))))))) + +(defun load-image () + (read-integers-into-array m rom 0)) + +(defun save-image ()) + +(defun read-block () + (setq b (_pop) + a (_pop)) + (read-integers-into-array blk blocks (* 4096 a)) + (replace m blk :start1 b :end1 (+ b 1024))) + +(defun copy-block-from-m (org start-index) + (let ((end-index (+ start-index 1024))) + (copy-seq (subseq org start-index end-index)))) + +(defun little-endian (integer) + (let ((bytes (make-array 4 + :element-type '(unsigned-byte 8)))) + (setf (aref bytes 0) (ldb (byte 8 0) integer)) + (setf (aref bytes 1) (ldb (byte 8 8) integer)) + (setf (aref bytes 2) (ldb (byte 8 16) integer)) + (setf (aref bytes 3) (ldb (byte 8 24) integer)) + bytes)) + +(defun write-block () + (setq b (_pop) + a (_pop)) + (with-open-file + (out-stream blocks + :direction :output + :if-exists :append + :element-type '(unsigned-byte 8)) + (file-position out-stream (* 4096 a)) + (loop for integer across (copy-block-from-m m b) do + (write-sequence (little-endian integer) out-stream)))) + +(defun save-ip () + (incf rp) + (setf (aref as rp) ip)) + +(defun symmetric () + (when (and (>= b 0) (< (aref ds (1- sp)) 0)) + (progn + (incf (aref ds sp)) + (decf (aref ds (1- sp)) b)))) + +(defun li () + (incf ip) + (_push (aref m ip))) + +(defun du () + (_push (aref ds sp))) + +(defun dr () + (setf (aref ds sp) 0) + (decf sp)) + +(defun sw () + (setq a (aref ds sp)) + (setf (aref ds sp) (aref ds (1- sp)) + (aref ds (1- sp)) a)) + +(defun pu () + (incf rp) + (setf (aref as rp) (_pop))) + +(defun po () + (_push (aref as rp)) + (decf rp)) + +(defun ju () + (setq ip (- (_pop) 1))) + +(defun ca () + (save-ip) + (setq ip (- (_pop) 1))) + +(defun cc () + (setq a (_pop)) + (when (not (zerop (_pop))) + (save-ip) + (setq ip (- a 1)))) + +(defun cj () + (setq a (_pop)) + (when (not (zerop (_pop))) + (setq ip (- a 1)))) + +(defun re () + (setq ip (aref as rp)) + (decf rp)) + +(defun _eq () + (setf (aref ds (1- sp)) (if (= (aref ds (1- sp)) (aref ds sp)) -1 0)) + (decf sp)) + +(defun ne () + (setf (aref ds (1- sp)) (if (/= (aref ds (1- sp)) (aref ds sp)) -1 0)) + (decf sp)) + +(defun lt () + (setf (aref ds (1- sp)) (if (< (aref ds (1- sp)) (aref ds sp)) -1 0)) + (decf sp)) + +(defun gt () + (setf (aref ds (1- sp)) (if (> (aref ds (1- sp)) (aref ds sp)) -1 0)) + (decf sp)) + +(defun fe () + (setf (aref ds sp) (aref m (aref ds sp)))) + +(defun st () + (setf (aref m (aref ds sp)) (aref ds (1- sp))) + (decf sp 2)) + +(defun ad () + (setf (aref ds (1- sp)) (fixint (+ (aref ds (1- sp)) (aref ds sp)))) + (decf sp)) + +(defun su () + (setf (aref ds (1- sp)) (fixint (- (aref ds (1- sp)) (aref ds sp)))) + (decf sp)) + +(defun mu () + (setf (aref ds (1- sp)) (fixint (* (aref ds (1- sp)) (aref ds sp)))) + (decf sp)) + +(defun di () + (setf a (aref ds sp) + b (aref ds (1- sp)) + (aref ds sp) (fixint (floor b a)) + (aref ds (1- sp)) (fixint (mod b a))) + (symmetric)) + +(defun an () + (setf (aref ds (1- sp)) (fixint (logand (aref ds (1- sp)) (aref ds sp)))) + (decf sp)) + +(defun _or () + (setf (aref ds (1- sp)) (fixint (logior (aref ds (1- sp)) (aref ds sp)))) + (decf sp)) + +(defun xo () + (setf (aref ds (1- sp)) (fixint (logxor (aref ds (1- sp)) (aref ds sp)))) + (decf sp)) + +(defun sl () + (setf (aref ds (1- sp)) (fixint (ash (aref ds (1- sp)) (aref ds sp)))) + (decf sp)) + +(defun sr () + (setf (aref ds (1- sp)) (fixint (ash (aref ds (1- sp)) (- (aref ds sp))))) + (decf sp)) + +(defun cp () + (setf l (_pop) + d (_pop) + s (aref ds sp) + (aref ds sp) -1) + (loop repeat l do + (when (not (= (aref m d) (aref m s))) + (setf (aref ds sp) 0)) + (decf l) + (decf s) + (decf d))) + +(defun cy () + (setf l (_pop) + d (_pop) + s (_pop)) + (loop repeat l do + (setf (aref m d) (aref m s)) + (incf d) + (incf s))) + +(defun ioa () + (setf d (_pop)) + (write-char (code-char d) *standard-output*)) + +(defun iob () + (setf d (read-char *standard-input*)) + (_push (char-code d))) + +(defun ioc () + (read-block)) + +(defun iod () + (write-block)) + +(defun ioe () + (save-image)) + +(defun iof () + (load-image) + (setf ip -1)) + +(defun iog () + (setf ip 65536)) + +(defun ioh () + (_push sp) + (_push rp)) + +(defun io () + (case (_pop) + (0 (ioa)) + (1 (iob)) + (2 (ioc)) + (3 (iod)) + (4 (ioe)) + (5 (iof)) + (6 (iog)) + (7 (ioh)))) + +(defun process (o) + (case o + (0) + (1 (li)) + (2 (du)) + (3 (dr)) + (4 (sw)) + (5 (pu)) + (6 (po)) + (7 (ju)) + (8 (ca)) + (9 (cc)) + (10 (cj)) + (11 (re)) + (12 (_eq)) + (13 (ne)) + (14 (lt)) + (15 (gt)) + (16 (fe)) + (17 (st)) + (18 (ad)) + (19 (su)) + (20 (mu)) + (21 (di)) + (22 (an)) + (23 (_or)) + (24 (xo)) + (25 (sl)) + (26 (sr)) + (27 (cp)) + (28 (cy)) + (29 (io)) + (otherwise nil))) + +(defun process-bundle (opcode) + (process (logand opcode #xFF)) + (process (logand (ash opcode -8) #xFF)) + (process (logand (ash opcode -16) #xFF)) + (process (logand (ash opcode -24) #xFF))) + +(defun _execute () + (loop while (< ip 65536) do + (process-bundle (aref m ip)) + (incf ip))) + +(defun main () + (load-image) + (_execute)) + +(main) +(quit) diff --git a/source/ilo.cs b/source/ilo.cs new file mode 100644 index 0000000..24e77cb --- /dev/null +++ b/source/ilo.cs @@ -0,0 +1,161 @@ +// ilo.cs, (c) charles childers + +using System; +using System.IO; +using System.Text; + +namespace ilo { + class VM { + + public int sp, rp, ip; + public int[] d, a, m; + + public VM() { + sp = 0; + rp = 0; + ip = 0; + d = new int[33]; + a = new int[257]; + m = new int[65536]; + load_rom(); + } + + public void load_rom() { + int i = 0; + if (!File.Exists("ilo.rom")) { + Console.Write("ilo.rom missing"); + Environment.Exit(1); + } + BinaryReader rom = new BinaryReader(File.Open("ilo.rom", FileMode.Open)); + while (i < 65536) { m[i] = rom.ReadInt32(); i++; } + rom.Close(); + } + + public void read_block() { + int buffer = d[sp]; sp--; + int block = d[sp]; sp--; + int i = 0; + BinaryReader blocks = new BinaryReader(File.Open("ilo.blocks", FileMode.Open)); + blocks.BaseStream.Seek(4096 * block, SeekOrigin.Begin); + while (i < 1024) { m[buffer + i] = blocks.ReadInt32(); i++; } + blocks.Close(); + } + + public void write_block() { + int buffer = d[sp]; sp--; + int block = d[sp]; sp--; + int i = 0; + BinaryWriter blocks = new BinaryWriter(File.Open("ilo.blocks", FileMode.Open, FileAccess.ReadWrite)); + blocks.BaseStream.Seek(4096 * block, SeekOrigin.Begin); + while (i < 1024) { blocks.Write(m[buffer + i]); i++; } + blocks.Close(); + } + + public void push(int x) { sp++; d[sp] = x; } + public int pop() { sp--; return d[sp + 1]; } + + public void no() { } + public void li() { ip++; sp++; d[sp] = m[ip]; } + public void du() { sp++; d[sp] = d[sp - 1]; } + public void dr() { sp--; } + public void sw() { int x = d[sp], y = d[sp - 1]; d[sp] = y; d[sp - 1] = x; } + public void pu() { rp++; a[rp] = d[sp]; sp--; } + public void po() { sp++; d[sp] = a[rp]; rp--; } + public void ju() { ip = d[sp] - 1; sp--; } + public void ca() { rp++; a[rp] = ip; ju(); } + public void cc() { if (d[sp - 1] != 0) { rp++; a[rp] = ip; ip = d[sp] - 1; } sp -= 2; } + public void cj() { if (d[sp - 1] != 0) { ip = d[sp] - 1; } sp -= 2; } + public void re() { ip = a[rp]; rp--; } + public void eq() { d[sp - 1] = (d[sp - 1] == d[sp]) ? -1 : 0; sp--; } + public void ne() { d[sp - 1] = (d[sp - 1] != d[sp]) ? -1 : 0; sp--; } + public void lt() { d[sp - 1] = (d[sp - 1] < d[sp]) ? -1 : 0; sp--; } + public void gt() { d[sp - 1] = (d[sp - 1] > d[sp]) ? -1 : 0; sp--; } + public void fe() { d[sp] = m[d[sp]]; } + public void st() { m[d[sp]] = d[sp - 1]; sp -= 2; } + public void ad() { d[sp - 1] += d[sp]; sp--; } + public void su() { d[sp - 1] -= d[sp]; sp--; } + public void mu() { d[sp - 1] *= d[sp]; sp--; } + public void di() { int x = d[sp], y = d[sp - 1]; d[sp] = y / x; d[sp - 1] = y % x; } + public void an() { d[sp - 1] = d[sp] & d[sp - 1]; sp--; } + public void or() { d[sp - 1] = d[sp] | d[sp - 1]; sp--; } + public void xo() { d[sp - 1] = d[sp] ^ d[sp - 1]; sp--; } + public void sl() { d[sp - 1] = d[sp] << d[sp - 1]; sp--; } + public void sr() { d[sp - 1] = d[sp] >>= d[sp - 1]; sp--; } + public void cp() { + int len = d[sp]; sp--; + int dest = d[sp]; sp--; + int src = d[sp]; sp--; + sp++; d[sp] = -1; + while (len > 0) { + if (m[dest] != m[src]) { d[sp] = 0; } + len -= 1; src += 1; dest += 1; + } + } + public void cy() { + int len = d[sp]; sp--; + int dest = d[sp]; sp--; + int src = d[sp]; sp--; + while (len > 0) { + m[dest] = m[src]; + len -= 1; src += 1; dest += 1; + } + } + + public void iowr() { Console.Write((char)d[sp]); sp--; } + public void iord() { ConsoleKeyInfo x = Console.ReadKey(); sp++; d[sp] = (int)x.KeyChar; if (d[sp] == 13) { d[sp] = 10; } } + public void iorb() { read_block(); } + public void iowb() { write_block(); } + public void iosi() { } + public void ioli() { load_rom(); ip = -1; } + public void ioen() { ip = 65536; } + public void iost() { sp++; d[sp] = sp - 1; sp++; d[sp] = rp; } + + public void io() { + int act = d[sp]; sp--; + switch (act) { + case 0: iowr(); break; case 1: iord(); break; + case 2: iorb(); break; case 3: iowb(); break; + case 4: iosi(); break; case 5: ioli(); break; + case 6: ioen(); break; case 7: iost(); break; + } + } + + public void process(int o) { + switch(o) { + case 0: no(); break; case 1: li(); break; + case 2: du(); break; case 3: dr(); break; + case 4: sw(); break; case 5: pu(); break; + case 6: po(); break; case 7: ju(); break; + case 8: ca(); break; case 9: cc(); break; + case 10: cj(); break; case 11: re(); break; + case 12: eq(); break; case 13: ne(); break; + case 14: lt(); break; case 15: gt(); break; + case 16: fe(); break; case 17: st(); break; + case 18: ad(); break; case 19: su(); break; + case 20: mu(); break; case 21: di(); break; + case 22: an(); break; case 23: or(); break; + case 24: xo(); break; case 25: sl(); break; + case 26: sr(); break; case 27: cp(); break; + case 28: cy(); break; case 29: io(); break; + } + } + + public void execute() { + int raw = 0; + ip = 0; + while (ip < 65536) { + raw = m[ip]; + for (int i = 0; i < 4; i++) { + process(raw & 0xFF); + raw = raw >> 8; + } + ip++; + } + } + + public static void Main(string[] args) { + VM ilo = new VM(); + ilo.execute(); + } + } +} diff --git a/source/ilo.cxx b/source/ilo.cxx new file mode 100644 index 0000000..3ec4b4c --- /dev/null +++ b/source/ilo.cxx @@ -0,0 +1,187 @@ +/*************************************************************** + crc's _ _ + (_) | ___ + | | |/ _ \ a tiny virtual computer + | | | (_) | 64kw RAM, 32-bit, Dual Stack, MISC + |_|_|\___/ ilo.cxx (c) charles childers + **************************************************************/ + +#include +#include +#include +#include + +/* ip instruction pointer + sp data stack pointer + rp address stack pointer + ds data stack (32 values) + as address stack (256 values) + m memory (65,536 values) + rom name of image (default to ilo.rom) + blocks name of block file (default to ilo.blocks) + + the other variables are used by the various functions for + misc. purposes +*/ + +int ip, sp, rp, ds[33], as[257], m[65536]; +int a, b, t, fp, block, buffer, src, dest, len; +char *blocks, *rom, iob[2]; + +/* T is top of stack + N is next on stack + R is top of address stack + V is void +*/ + +#define T ds[sp] +#define N ds[sp-1] +#define R as[rp] +#define V void + +int pop() { sp -= 1; return ds[sp + 1]; } +V push(int value) { sp += 1; ds[sp] = value; } + +V prepare_vm() { ip = sp = rp = 0; } + +V load_image() { + fp = open(rom, O_RDONLY, 0666); + if (!fp) { return; }; + read(fp, &m, 65536 * 4); + close(fp); + prepare_vm(); +} + +V save_image() { + fp = open(rom, O_WRONLY, 0666); + write(fp, &m, 65536 * 4); + close(fp); +} + +V block_common() { + buffer = pop(); + block = pop(); + lseek(fp, 4096 * block, SEEK_SET); +} + +V read_block() { + fp = open(blocks, O_RDONLY, 0666); + block_common(); + read(fp, m + buffer, 4096); + close(fp); +} + +V write_block() { + fp = open(blocks, O_WRONLY, 0666); + block_common(); + write(fp, m + buffer, 4096); + close(fp); +} + +V save_ip() { rp += 1; R = ip; } +V symmetric() { if (b >= 0 && N < 0) { T++; N -= b; } } + +V li() { ip += 1; push(m[ip]); } +V du() { push(T); } +V dr() { ds[sp] = 0; sp -= 1; } +V sw() { a = T; T = N; N = a; } +V pu() { rp += 1; R = pop(); } +V po() { push(R); rp -= 1; } +V ju() { ip = pop() - 1; } +V ca() { save_ip(); ip = pop() - 1; } +V cc() { t = pop(); if (pop()) { save_ip(); ip = t - 1; } } +V cj() { t = pop(); if (pop()) { ip = t - 1; } } +V re() { ip = R; rp -= 1; } +V eq() { N = (N == T) ? -1 : 0; sp -= 1; } +V ne() { N = (N != T) ? -1 : 0; sp -= 1; } +V lt() { N = (N < T) ? -1 : 0; sp -= 1; } +V gt() { N = (N > T) ? -1 : 0; sp -= 1; } +V fe() { T = m[T]; } +V st() { m[T] = N; sp -= 2; } +V ad() { N += T; sp -= 1; } +V su() { N -= T; sp -= 1; } +V mu() { N *= T; sp -= 1; } +V di() { a = T; b = N; T = b / a; N = b % a; symmetric(); } +V an() { N = T & N; sp -= 1; } +V or_() { N = T | N; sp -= 1; } +V xo() { N = T ^ N; sp -= 1; } +V sl() { N = N << T; sp -= 1; } +V sr() { N = N >> T; sp -= 1; } +V cp() { len = pop(); dest = pop(); src = pop(); push(-1); + while (len) { + if (m[dest] != m[src]) { T = 0; } + len -= 1; src += 1; dest += 1; + } + } +V cy() { len = pop(); dest = pop(); src = pop(); + while (len) { + m[dest] = m[src]; + len -= 1; src += 1; dest += 1; + } + } +V iowr() { iob[0] = pop(); write(1, &iob, 1); } +V iord() { read(0, &iob, 1); push(iob[0]); } +V iorb() { read_block(); } +V iowb() { write_block(); } +V iosi() { save_image(); } +V ioli() { load_image(); ip = -1; } +V ioen() { ip = 65536; } +V iost() { push(sp); push(rp); } +V io() { + switch (pop()) { + case 0: iowr(); break; case 1: iord(); break; + case 2: iorb(); break; case 3: iowb(); break; + case 4: iosi(); break; case 5: ioli(); break; + case 6: ioen(); break; case 7: iost(); break; + default: break; + } +} + +/* Using a switch here instead of a jump table to avoid */ +/* some issues w/relocation stuff when building w/o libc */ + +V process(int o) { + switch (o) { + case 0: break; case 1: li(); break; + case 2: du(); break; case 3: dr(); break; + case 4: sw(); break; case 5: pu(); break; + case 6: po(); break; case 7: ju(); break; + case 8: ca(); break; case 9: cc(); break; + case 10: cj(); break; case 11: re(); break; + case 12: eq(); break; case 13: ne(); break; + case 14: lt(); break; case 15: gt(); break; + case 16: fe(); break; case 17: st(); break; + case 18: ad(); break; case 19: su(); break; + case 20: mu(); break; case 21: di(); break; + case 22: an(); break; case 23: or_(); break; + case 24: xo(); break; case 25: sl(); break; + case 26: sr(); break; case 27: cp(); break; + case 28: cy(); break; case 29: io(); break; + default: break; + } +} + +V process_bundle(int opcode) { + process(opcode & 0xFF); + process((opcode >> 8) & 0xFF); + process((opcode >> 16) & 0xFF); + process((opcode >> 24) & 0xFF); +} + +V execute() { + while (ip < 65536) { + process_bundle(m[ip]); + ip += 1; + } +} + +int main(int argc, char **argv) { + blocks = (argc > 1) ? argv[1] : (char *)"ilo.blocks"; + rom = (argc > 2) ? argv[2] : (char *)"ilo.rom"; + load_image(); + execute(); + for (; sp > 0; sp -= 1) + std::cout << ds[sp] << ' '; + std::cout << '\n'; + return 0; +} diff --git a/source/ilo.d b/source/ilo.d new file mode 100644 index 0000000..5d5b534 --- /dev/null +++ b/source/ilo.d @@ -0,0 +1,232 @@ +/*************************************************************** + crc's _ _ + (_) | ___ + | | |/ _ \ a tiny virtual computer + | | | (_) | 64kw RAM, 32-bit, Dual Stack, MISC + |_|_|\___/ ilo.d (c) charles childers + **************************************************************/ + +import std.stdio; + +Stack data, addr; /* data & address stacks */ +RAM memory; /* system memory */ +int ip; /* instruction pointer */ +string blocks; /* name of block file (ilo.blocks) */ +string rom; /* name of image (ilo.rom) */ + +void load_image() { + data = new Stack(33); + addr = new Stack(257); + memory = new RAM(); + FILE *file = fopen(rom.ptr, "rb"); + if (file is null) { return; } + fread(memory.pointer(), 1, 65536 * 4, file); + fclose(file); + ip = 0; +} + +void save_image() { + FILE *file = fopen(rom.ptr, "wb"); + fwrite(memory.pointer(), 1, 65536 * 4, file); + fclose(file); +} + +void read_block() { + int[1024] block; + FILE *file = fopen(blocks.ptr, "rb"); + if (file is null) { return; } + int b = data.pop(); /* block buffer */ + int a = data.pop(); /* block number */ + fseek(file, 4096 * a, SEEK_SET); + fread(block.ptr, 1, 4096, file); + foreach(i; 0 .. 1024) { memory.store(b + i, block[i]); } + fclose(file); +} + +void write_block() { + int[1024] block; + FILE *file = fopen(blocks.ptr, "r+b"); + if (file is null) { return; } + int b = data.pop(); /* block buffer */ + int a = data.pop(); /* block number */ + fseek(file, 4096 * a, SEEK_SET); + foreach(i; 0 .. 1024) { block[i] = memory.fetch(b + i); } + fwrite(block.ptr, 1, 4096, file); + fclose(file); +} + +void li() { ip += 1; data.push(memory.fetch(ip)); } +void du() { data.dup(); } +void dr() { data.pop(); } +void sw() { data.swap(); } +void pu() { addr.push(data.pop()); } +void po() { data.push(addr.pop()); } +void ju() { ip = data.pop() - 1; } +void ca() { addr.push(ip); ip = data.pop() - 1; } +void cc() { int a = data.pop(); if (data.pop()) { addr.push(ip); ip = a - 1; } } +void cj() { int a = data.pop(); if (data.pop()) { ip = a - 1; } } +void re() { ip = addr.pop(); } +void eq() { data.swap(); data.push((data.pop() == data.pop()) ? -1 : 0); } +void ne() { data.swap(); data.push((data.pop() != data.pop()) ? -1 : 0); } +void lt() { data.swap(); data.push((data.pop() < data.pop()) ? -1 : 0); } +void gt() { data.swap(); data.push((data.pop() > data.pop()) ? -1 : 0); } +void fe() { data.push(memory.fetch(data.pop())); } +void st() { int a = data.pop(); memory.store(a, data.pop()); } +void ad() { data.swap(); data.push(data.pop() + data.pop()); } +void su() { data.swap(); data.push(data.pop() - data.pop()); } +void mu() { data.swap(); data.push(data.pop() * data.pop()); } +void di() { int a = data.pop(); int b = data.pop(); data.push(b % a); data.push(b / a); } +void an() { data.push(data.pop() & data.pop()); } +void or() { data.push(data.pop() | data.pop()); } +void xo() { data.push(data.pop() ^ data.pop()); } +void sl() { data.swap(); data.push(data.pop() << data.pop()); } +void sr() { data.swap(); data.push(data.pop() >> data.pop()); } +void cp() { int l = data.pop(); int d = data.pop(); int s = data.pop(); data.push(-1); + while (l) { if (memory.fetch(d) != memory.fetch(s)) { data.pop(); data.push(0); } + l -= 1; s += 1; d += 1; } } +void cy() { int l = data.pop(); int d = data.pop(); int s = data.pop(); + while (l) { memory.store(d, memory.fetch(s)); l -= 1; s += 1; d += 1; } } +void ioa() { writef("%c", cast(char)data.pop()); } +void iob() { data.push(getchar()); } +void ioc() { read_block(); } +void iod() { write_block(); } +void ioe() { save_image(); } +void iof() { load_image(); ip = -1; } +void iog() { ip = 65536; } +void ioh() { data.push(data.depth()); data.push(addr.depth()); } +void io() { + switch (data.pop()) { + case 0: ioa(); break; case 1: iob(); break; + case 2: ioc(); break; case 3: iod(); break; + case 4: ioe(); break; case 5: iof(); break; + case 6: iog(); break; case 7: ioh(); break; + default: break; + } +} + +void process(int o) { + switch (o) { + case 0: break; case 1: li(); break; + case 2: du(); break; case 3: dr(); break; + case 4: sw(); break; case 5: pu(); break; + case 6: po(); break; case 7: ju(); break; + case 8: ca(); break; case 9: cc(); break; + case 10: cj(); break; case 11: re(); break; + case 12: eq(); break; case 13: ne(); break; + case 14: lt(); break; case 15: gt(); break; + case 16: fe(); break; case 17: st(); break; + case 18: ad(); break; case 19: su(); break; + case 20: mu(); break; case 21: di(); break; + case 22: an(); break; case 23: or(); break; + case 24: xo(); break; case 25: sl(); break; + case 26: sr(); break; case 27: cp(); break; + case 28: cy(); break; case 29: io(); break; + default: break; + } +} + +void process_bundle(int opcode) { + process(opcode & 0xFF); + process((opcode >> 8) & 0xFF); + process((opcode >> 16) & 0xFF); + process((opcode >> 24) & 0xFF); +} + +void execute() { + while (ip < 65536) { + process_bundle(memory.fetch(ip)); + ip += 1; + } +} + +void main(string[] args) { + blocks = "ilo.blocks"; + rom = "ilo.rom"; + load_image(); + execute(); + data.print(); + writef("\n"); +} + +class RAM { + private int[65536] data; + + this() { + } + + int fetch(int a) { + if (a < 0 || a > 65535) + throw new Exception("Invalid memory access"); + return data[a]; + } + + void store(int a, int v) { + if (a < 0 || a > 65535) + throw new Exception("Invalid memory access"); + data[a] = v; + } + + int* pointer() { + return data.ptr; + } +} + +class Stack { + private int[] stack; + private int top; + private int capacity; + + this(int capacity) { + this.capacity = capacity; + stack = new int[capacity]; + top = -1; + } + + bool isEmpty() { + return top == -1; + } + + bool isFull() { + return top == capacity - 1; + } + + void push(int value) { + if (isFull()) + throw new Exception("Stack overflow"); + stack[++top] = value; + } + + int pop() { + if (isEmpty()) + throw new Exception("Stack underflow"); + return stack[top--]; + } + + void dup() { + if (isEmpty()) + throw new Exception("Stack is empty"); + + if (isFull()) + throw new Exception("Stack overflow"); + push(stack[top]); + } + + void swap() { + if (top < 1) + throw new Exception("Insufficient elements to swap"); + + int temp = stack[top]; + stack[top] = stack[top - 1]; + stack[top - 1] = temp; + } + + int depth() { + return top + 1; + } + + void print() { + for (int i = top; i >= 0; i--) { + writeln(stack[i]); + } + } +} diff --git a/source/ilo.fnt b/source/ilo.fnt new file mode 100644 index 0000000..9a98ece Binary files /dev/null and b/source/ilo.fnt differ diff --git a/source/ilo.go b/source/ilo.go new file mode 100644 index 0000000..d0781fb --- /dev/null +++ b/source/ilo.go @@ -0,0 +1,193 @@ +// ilo.go, (c) charles childers + +package main + +import ( + "encoding/binary" + "fmt" + "os" +) + +var d [33]int32 +var a [257]int32 +var m [65536]int32 +var sp = 0 +var rp = 0 +var ip = 0 + +func pop() int32 { sp--; return d[sp + 1] } +func push(x int32) { sp++; d[sp] = x } + +func prepare_vm() { ip = 0; sp = 0; rp = 0; } + +func load_image() { + f, err := os.OpenFile("ilo.rom", os.O_RDONLY, 0) + if err != nil { + return + } + defer f.Close() + buf := make([]byte, 4) + var i int = 0 + for i < 65536 { + f.Read(buf) + m[i] = int32(binary.LittleEndian.Uint32(buf[:4])) + i++ + } + prepare_vm() +} + +func save_image() { +} + +func read_block() { + var buffer = pop() + var block = pop() + var blocks = "ilo.blocks" + if f, err := os.OpenFile(blocks, os.O_RDWR, 0666); err == nil { + f.Seek(int64(block * 4096), 0) + buf := make([]byte, 4) + var i int = 0 + for i < 1024 { + f.Read(buf) + m[int(buffer) + i] = int32(binary.LittleEndian.Uint32(buf[:4])) + i++ + } + f.Close() + } +} + +func write_block() { + var buffer = pop() + var block = pop() + var blocks = "ilo.blocks" + if f, err := os.OpenFile(blocks, os.O_RDWR, 0666); err == nil { + f.Seek(int64(block * 4096), 0) + var buf = m[buffer:buffer+1024] + binary.Write(f, binary.LittleEndian, buf) + f.Close() + } +} + +func no() { } +func li() { ip++; push(m[ip]) } +func du() { push(d[sp]) } +func dr() { sp-- } +func sw() { var y = pop(); var x = pop(); push(y); push(x); } +func pu() { rp++; a[rp] = pop() } +func po() { push(a[rp]); rp-- } +func ju() { ip = int(pop() - 1) } +func ca() { rp++; a[rp] = int32(ip); ju() } +func cc() { sw(); if (pop() != 0) { ca() } else { dr() } } +func cj() { sw(); if (pop() != 0) { ju() } else { dr() } } +func re() { ip = int(a[rp]); rp-- } +func eq() { var y = pop(); var x = pop(); if (x == y) { push(-1) } else { push(0) } } +func ne() { var y = pop(); var x = pop(); if (x != y) { push(-1) } else { push(0) } } +func lt() { var y = pop(); var x = pop(); if (x < y) { push(-1) } else { push(0) } } +func gt() { var y = pop(); var x = pop(); if (x > y) { push(-1) } else { push(0) } } +func fe() { var t = pop(); push(m[t]) } +func st() { var t = pop(); m[t] = pop() } +func ad() { var y = pop(); var x = pop(); push(x + y) } +func su() { var y = pop(); var x = pop(); push(x - y) } +func mu() { var y = pop(); var x = pop(); push(x * y) } +func di() { var y = pop(); var x = pop(); push(x % y); push(x / y) } +func an() { var y = pop(); var x = pop(); push(x & y) } +func or() { var y = pop(); var x = pop(); push(x | y) } +func xo() { var y = pop(); var x = pop(); push(x ^ y) } +func sl() { var y = pop(); var x = pop(); push(x << y) } +func sr() { var y = pop(); var x = pop(); push(x >> y) } +func cp() { + var len = pop() + var dest = pop() + var src = pop() + push(-1) + for len > 0 { + if m[dest] != m[src] { d[sp] = 0 } + len--; src++; dest++ + } +} +func cy() { + var len = pop() + var dest = pop() + var src = pop() + for len > 0 { + m[dest] = m[src] + len--; src++; dest++ + } +} +func iowr() { fmt.Printf("%c", pop()) } +func iord() { + var b []byte = make([]byte, 1) + os.Stdin.Read(b) + var c int = int(b[0]) + push(int32(c)) +} +func iorb() { read_block() } +func iowb() { write_block() } +func iosi() { save_image() } +func ioli() { load_image(); ip = -1 } +func ioen() { ip = 65536 } +func iost() { push(int32(sp)); push(int32(rp)) } +func io() { + var o = pop() + if o == 0 { iowr() } + if o == 1 { iord() } + if o == 2 { iorb() } + if o == 3 { iowb() } + if o == 4 { iosi() } + if o == 5 { ioli() } + if o == 6 { ioen() } + if o == 7 { iost() } +} + +func process(o int32) { + if o == 0 { no() } + if o == 1 { li() } + if o == 2 { du() } + if o == 3 { dr() } + if o == 4 { sw() } + if o == 5 { pu() } + if o == 6 { po() } + if o == 7 { ju() } + if o == 8 { ca() } + if o == 9 { cc() } + if o == 10 { cj() } + if o == 11 { re() } + if o == 12 { eq() } + if o == 13 { ne() } + if o == 14 { lt() } + if o == 15 { gt() } + if o == 16 { fe() } + if o == 17 { st() } + if o == 18 { ad() } + if o == 19 { su() } + if o == 20 { mu() } + if o == 21 { di() } + if o == 22 { an() } + if o == 23 { or() } + if o == 24 { xo() } + if o == 25 { sl() } + if o == 26 { sr() } + if o == 27 { cp() } + if o == 28 { cy() } + if o == 29 { io() } +} + +func process_bundle(o int32) { + process(o & 0xFF) + process((o >> 8) & 0xFF) + process((o >> 16) & 0xFF) + process((o >> 24) & 0xFF) +} + +func execute() { + for ip < 65536 { + process_bundle(m[ip]) + ip++ + } +} + + +func main() { + load_image() + execute() +} diff --git a/source/ilo.ha b/source/ilo.ha new file mode 100644 index 0000000..e6fe36d --- /dev/null +++ b/source/ilo.ha @@ -0,0 +1,239 @@ +// ilo.ha, an ilo in hare + +use bufio; +use fmt; +use fs; +use io; +use math; +use os; + +let ds: [33]i32 = [0...]; +let rs: [257]i32 = [0...]; +let m: [65536]i32 = [0...]; +let sp: i32 = 0; +let rp: i32 = 0; +let ip: i32 = 0; +let a: i32 = 0; +let b: i32 = 0; +let c: i32 = 0; + +fn initialize() void = { + sp = 0; + rp = 0; + ip = 0; + load(); +}; + +fn load() void = { + const input = match (os::open("ilo.rom")) { + case let file: io::file => + yield file; + case let err: fs::error => + fmt::fatalf("Error opening {}: {}", + os::args[1], fs::strerror(err)); + }; + defer io::close(input)!; + let rdbuf: [os::BUFSZ]u8 = [0...]; + let input = &bufio::init(input, rdbuf, []); + let i = 0; + let buf: [4]u8 = [0, 0, 0, 0]; + for (!(io::read(input, buf)! is io::EOF)) { + let x: u32 = m[i]:u32; + x = x + (buf[3]:u32 << 24); + x = x + (buf[2]:u32 << 16); + x = x + (buf[1]:u32 << 8); + x = x + (buf[0]:u32 << 0); + m[i] = x:i32; + i = i + 1; + }; +}; + +fn read_block(block:i32, buffer:i32) void = { + const block_store = match (os::open("ilo.blocks")) { + case let file: io::file => + yield file; + case let err: fs::error => + fmt::fatalf("Error opening {}: {}", + "ilo.blocks", fs::strerror(err)); + }; + defer io::close(block_store)!; + + let rdbuf: [os::BUFSZ]u8 = [0...]; + let block_store = &bufio::init(block_store, rdbuf, []); + + let i: i32 = 0; + let buf: [4096]u8 = [0...]; + + // this is not an optimal way, need to figure out + // io::seek + // io::seek(block_store, block * 4096, io::whence::SET)!; + let za:i32 = 0; + for (za < block) { + io::read(block_store, buf)!; + za = za + 1; + }; + + let cell: [4]u8 = [0...]; + + // read in the block + for (i < 1024) { + io::read(block_store, cell)!; + let x: u32 = 0; + x = x + (cell[3]:u32 << 24); + x = x + (cell[2]:u32 << 16); + x = x + (cell[1]:u32 << 8); + x = x + (cell[0]:u32 << 0); + let t:i32 = buffer + i; + m[t] = x:i32; + i = i + 1; + }; +}; + +fn write_block(block:i32, buffer:i32) void = { + const block_store = match (os::open("ilo.blocks", fs::flag::RDWR)) { + case let file: io::file => + yield file; + case let err: fs::error => + fmt::fatalf("Error opening {}: {}", + "ilo.blocks", fs::strerror(err)); + }; + defer io::close(block_store)!; + + let rdbuf: [os::BUFSZ]u8 = [0...]; + let wrbuf: [os::BUFSZ]u8 = [0...]; + let block_store = &bufio::init(block_store, rdbuf, wrbuf); + + let i: i32 = 0; + let buf: [4096]u8 = [0...]; + + let za:i32 = 0; + for (za < block) { + io::read(block_store, buf)!; + za = za + 1; + }; + + let cell: [4]u8 = [0...]; + + // read in the block + for (i < 1024) { + let t:i32 = buffer + i; + let x: u32 = m[t]:u32; + cell[3] = ((x >> 24) & 0xFF):u8; + cell[2] = ((x >> 16) & 0xFF):u8; + cell[1] = ((x >> 8) & 0xFF):u8; + cell[0] = ((x >> 0) & 0xFF):u8; + io::write(block_store, cell)!; + i = i + 1; + }; + io::close(block_store)!; +}; + +fn push(v: i32) void = { sp = sp + 1; ds[sp] = v; }; +fn pop() i32 = { sp = sp - 1; return ds[sp + 1]; }; +fn save_ip() void = { rp = rp + 1; rs[rp] = ip; }; + +fn no() void = { return; }; +fn li() void = { ip = ip + 1; push(m[ip]); }; +fn du() void = { push(ds[sp]); }; +fn dr() void = { pop(); }; +fn sw() void = { a = pop(); b = pop(); push(a); push(b); }; +fn pu() void = { rp = rp + 1; rs[rp] = pop(); }; +fn po() void = { push(rs[rp]); rp = rp - 1; }; +fn ju() void = { ip = pop() - 1; }; +fn ca() void = { save_ip(); ip = pop() - 1; }; +fn cc() void = { a = pop(); if (pop() != 0) { save_ip(); ip = a - 1; }; }; +fn cj() void = { a = pop(); if (pop() != 0) { ip = a - 1; }; }; +fn re() void = { ip = rs[rp]; rp = rp - 1; }; +fn eq() void = { a = pop(); b = pop(); + if (a == b) { push(-1); } else { push(0); }; }; +fn ne() void = { a = pop(); b = pop(); + if (a != b) { push(-1); } else { push(0); }; }; +fn lt() void = { a = pop(); b = pop(); + if (b < a) { push(-1); } else { push(0); }; }; +fn gt() void = { a = pop(); b = pop(); + if (b > a) { push(-1); } else { push(0); }; }; +fn fe() void = { ds[sp] = m[ds[sp]]; }; +fn st() void = { m[ds[sp]] = ds[sp - 1]; sp = sp - 2; }; +fn ad() void = { ds[sp - 1] = ds[sp - 1] + ds[sp]; pop(); }; +fn su() void = { ds[sp - 1] = ds[sp - 1] - ds[sp]; pop(); }; +fn mu() void = { ds[sp - 1] = ds[sp - 1] * ds[sp]; pop(); }; +fn di() void = { a = ds[sp]; b = ds[sp - 1]; + ds[sp] = b / a; ds[sp - 1] = b % a; }; +fn an() void = { ds[sp - 1] = ds[sp - 1] & ds[sp]; pop(); }; +fn or() void = { ds[sp - 1] = ds[sp - 1] | ds[sp]; pop(); }; +fn xo() void = { ds[sp - 1] = ds[sp - 1] ^ ds[sp]; pop(); }; +fn sl() void = { ds[sp - 1] = ds[sp - 1] << ds[sp]; pop(); }; +fn sr() void = { ds[sp - 1] = ds[sp - 1] >> ds[sp]; pop(); }; +fn cp() void = { + a = pop(); b = pop(); c = pop(); push(-1); + for (a > 0; a = a - 1) { + if (m[b] != m[c]) { ds[sp] = 0; }; + b = b + 1; + c = c + 1; + }; +}; +fn cy() void = { + a = pop(); b = pop(); c = pop(); + for (a > 0; a = a - 1) { + m[b] = m[c]; + b = b + 1; + c = c + 1; + }; +}; +fn io() void = { + switch (pop()) { + case => return; + case 0 => fmt::printf("{}", pop():rune)!; return; + case 1 => let buf: [1]u8 = [0]; + io::read(os::stdin, buf)!; + let z:i32 = buf[0]:i32; + push(z); return; + case 2 => let buf = pop(); let blk = pop(); + read_block(blk, buf); + return; + case 3 => let buf = pop(); let blk = pop(); + write_block(blk, buf); + return; + case 4 => return; + case 5 => initialize(); ip = -1; return; + case 6 => fmt::fatal("BYE!"); + case 7 => push(sp); push(rp); return; + }; +}; + +fn process(o: i32) void = { + switch (o) { + case => return; + case 0 => return; case 1 => return li(); + case 2 => return du(); case 3 => return dr(); + case 4 => return sw(); case 5 => return pu(); + case 6 => return po(); case 7 => return ju(); + case 8 => return ca(); case 9 => return cc(); + case 10 => return cj(); case 11 => return re(); + case 12 => return eq(); case 13 => return ne(); + case 14 => return lt(); case 15 => return gt(); + case 16 => return fe(); case 17 => return st(); + case 18 => return ad(); case 19 => return su(); + case 20 => return mu(); case 21 => return di(); + case 22 => return an(); case 23 => return or(); + case 24 => return xo(); case 25 => return sl(); + case 26 => return sr(); case 27 => return cp(); + case 28 => return cy(); case 29 => return io(); + }; +}; + +fn execute() void = { + for (ip < 65536) { + let opcode = m[ip]; + process(opcode & 0xFF); + process((opcode >> 8) & 0xFF); + process((opcode >> 16) & 0xFF); + process((opcode >> 24) & 0xFF); + ip = ip + 1; + }; +}; + +export fn main() void = { + initialize(); + execute(); +}; diff --git a/source/ilo.kt b/source/ilo.kt new file mode 100644 index 0000000..bbf0cd0 --- /dev/null +++ b/source/ilo.kt @@ -0,0 +1,280 @@ +// ------------------------------------------------------------- +// ilo.kt, (c) charles childers +// +// build: +// +// kotlinc ilo.kt -include-runtime -d ilo.jar +// +// run: +// +// kotlin ilo.jar +// ------------------------------------------------------------- + +import java.io.File + +var blocks = IntArray(1024*1024*4) +var input = "" +var ip = 0 +var m = IntArray(65536) +var d = Stack() +var a = Stack() + +fun ino() {} +fun ili() { ip++; d.push(m[ip]) } +fun idu() { d.push(d.tos()) } +fun idr() { d.pop() } +fun isw() { var x = d.pop(); var y = d.pop(); d.push(x); d.push(y) } +fun ipu() { a.push(d.pop()) } +fun ipo() { d.push(a.pop()) } +fun iju() { ip = d.pop() - 1 } +fun ica() { a.push(ip); iju() } +fun icc() { val t = d.pop(); if (d.pop() != 0) { a.push(ip); ip = t - 1 } } +fun icj() { val t = d.pop(); if (d.pop() != 0) { ip = t - 1 } } +fun ire() { ip = a.pop() } +fun ieq() { val x = d.pop(); val y = d.pop(); if (y == x) { d.push(-1) } else { d.push(0) } } +fun ine() { val x = d.pop(); val y = d.pop(); if (y != x) { d.push(-1) } else { d.push(0) } } +fun ilt() { val x = d.pop(); val y = d.pop(); if (y < x) { d.push(-1) } else { d.push(0) } } +fun igt() { val x = d.pop(); val y = d.pop(); if (y > x) { d.push(-1) } else { d.push(0) } } +fun ife() { val t = d.pop(); d.push(m[t]) } +fun ist() { val t = d.pop(); m[t] = d.pop() } +fun iad() { val x = d.pop(); val y = d.pop(); d.push(y + x) } +fun isu() { val x = d.pop(); val y = d.pop(); d.push(y - x) } +fun imu() { val x = d.pop(); val y = d.pop(); d.push(y * x) } +fun idi() { val x = d.pop(); val y = d.pop(); d.push(y % x); d.push(y / x) } +fun ian() { val x = d.pop(); val y = d.pop(); d.push(y and x) } +fun ior() { val x = d.pop(); val y = d.pop(); d.push(y or x) } +fun ixo() { val x = d.pop(); val y = d.pop(); d.push(y xor x) } +fun isl() { val x = d.pop(); val y = d.pop(); d.push(y shl x) } +fun isr() { val x = d.pop(); val y = d.pop(); d.push(y shr x) } +fun icp() { + var l = d.pop() + var t = d.pop() + var s = d.pop() + d.push(-1) + while (l > 0) { + if (m[t] != m[s]) { d.pop(); d.push(0) } + t++; s++; l-- + } +} +fun icy() { + var l = d.pop() + var t = d.pop() + var s = d.pop() + while (l > 0) { + m[t] = m[s] + t++; s++; l-- + } +} +fun iio() { + when (d.pop()) { + 0 -> io_co() + 1 -> io_ci() + 2 -> io_rb() + 3 -> io_wb() + 4 -> io_si() + 5 -> io_pc() + 6 -> io_of() + 7 -> io_sd() + } +} + +fun io_co() { print(d.pop().toChar()) } +fun io_ci() { + if (input.length > 0) { + val c = input.first() + val v = c.code + d.push(v) + input = input.drop(1) + } else { + d.push(32) + } +} +fun io_rb() { read_block() } +fun io_wb() { write_block() } +fun io_si() { } +fun io_pc() { boot(); ip = -1 } +fun io_of() { ip = 65536 } +fun io_sd() { d.push(d.depth()); d.push(a.depth()) } + +// ------------------------------------------------------------- +// ------------------------------------------------------------- + +fun load_blocks() { + val bs = File("./ilo.blocks") + val bytes:ByteArray = bs.readBytes() + var i = 0 + var o = 0 + while (i < (1024*1024)) { + val x = (bytes[o++].toInt() and 0xff shl 24) or + (bytes[o++].toInt() and 0xff shl 16) or + (bytes[o++].toInt() and 0xff shl 8) or + (bytes[o++].toInt() and 0xff) + blocks[i] = fix(x.toLong()) + i++ + } +} + +fun read_block() { + load_blocks() + val buffer = d.pop() + val block = d.pop() + var i = 0 + while (i < 1024) { + m[buffer + i] = blocks[(block * 1024) + i] + i++ + } +} + +fun write_block() { + val buffer = d.pop() + val block = d.pop() + + // update `blocks` cache + var i = 0 + while (i < 1024) { + blocks[(block * 1024) + i] = m[buffer + i] + i++ + } + + // write `blocks` cache back to disk + val bs = File("./ilo.blocks") + var dump: ByteArray = ByteArray(1024*1024*4) + + i = 0 + var o = 0 + while (i < (1024*1024)) { + val cell = fix(blocks[i].toLong()) + dump[o++] = ((cell shr 24) and 0xFF).toByte() + dump[o++] = ((cell shr 16) and 0xFF).toByte() + dump[o++] = ((cell shr 8) and 0xFF).toByte() + dump[o++] = (cell and 0xFF).toByte() + i++ + } + bs.writeBytes(dump) +} + +fun process_instruction(op: Int) { + when (op) { + 0 -> ino() + 1 -> ili() + 2 -> idu() + 3 -> idr() + 4 -> isw() + 5 -> ipu() + 6 -> ipo() + 7 -> iju() + 8 -> ica() + 9 -> icc() + 10 -> icj() + 11 -> ire() + 12 -> ieq() + 13 -> ine() + 14 -> ilt() + 15 -> igt() + 16 -> ife() + 17 -> ist() + 18 -> iad() + 19 -> isu() + 20 -> imu() + 21 -> idi() + 22 -> ian() + 23 -> ior() + 24 -> ixo() + 25 -> isl() + 26 -> isr() + 27 -> icp() + 28 -> icy() + 29 -> iio() + else -> { + println("Invalid instruction!") + print("IP:") + print(ip) + print(" OC:") + println(op) + } + } +} + +fun process() { + while (input.length > 0 && ip < 65536) { + val cur = ip + process_instruction(m[cur] and 0xFF) + process_instruction((m[cur] shr 8) and 0xFF) + process_instruction((m[cur] shr 16) and 0xFF) + process_instruction((m[cur] shr 24) and 0xFF) + ip++ + } +} + +fun boot() { + load_image() + load_blocks() + ip = 0 + d.empty() + a.empty() + input = " " + process() +} + +fun load_image() { + val bs = File("./ilo.rom") + val bytes:ByteArray = bs.readBytes() + var i = 0 + var o = 0 + while (i < 65536) { + val x = (bytes[o++].toInt() and 0xff shl 24) or + (bytes[o++].toInt() and 0xff shl 16) or + (bytes[o++].toInt() and 0xff shl 8) or + (bytes[o++].toInt() and 0xff) + m[i] = fix(x.toLong()) + i++ + } +} + +// The JVM is a big endian system. ilo stores data & rom in +// little endian. This routine converts the data between these +// when necessary. + +fun fix(v: Long): Int { + return (((v and 0x000000FF) shl 24) or + ((v and 0x0000FF00) shl 8) or + ((v and 0x00FF0000) shr 8) or + ((v and 0xFF000000) shr 24)).toInt() +} + +fun main(args: Array) { + boot() + while (ip < 65536) { + input = readln() + input = " " + input + " \n" + process() + } +} + + +class Stack { + var sp = 0 + var data = IntArray(256) + + fun push(v: Int) { + sp++ + data[sp] = v + } + + fun pop(): Int { + sp-- + return data[sp + 1] + } + + fun tos(): Int { + return data[sp] + } + + fun empty() { + sp = 0 + } + + fun depth(): Int { + return sp + } +} diff --git a/source/ilo.lua b/source/ilo.lua new file mode 100644 index 0000000..8d21f83 --- /dev/null +++ b/source/ilo.lua @@ -0,0 +1,343 @@ +-- ilo.lua +-- Partially derived from Ngaro in Lua +-- Copyright (c) 2010 - 2023, Charles Childers +-- +-- This is only tested on Lua 5.4 and requires 32-bit +-- integers. (set `#define LUA_32BITS 1` in luaconf.h when +-- building Lua) + +-- Variables +local ip = 0 -- instruction pointer +local sp = 0 -- stack pointer +local rp = 0 -- return pointer +local stack = {} -- data stack +local address = {} -- return stack +local memory = {} -- simulated ram + +-- Support Code +local function file_size(filename) + local fh = assert(io.open(filename, 'rb')) + local len = assert(fh:seek('end')) + fh:close() + return len +end + +local function constrain(n) + return (n > 0x7FFFFFFF) and (n - 0x100000000) or n +end + +local function save_image() + local image = io.open('ilo.rom', 'wb') + local i = 0 + while i < 65536 do + image:write(string.pack(' stack[sp] then + stack[sp - 1] = -1 + else + stack[sp - 1] = 0 + end + sp = sp - 1 + end, + [16] = function() -- fe (fetch) + stack[sp] = memory[stack[sp]] + end, + [17] = function() -- st (store) + memory[stack[sp]] = stack[sp - 1] + sp = sp - 2 + end, + [18] = function() -- ad (add) + stack[sp - 1] = stack[sp - 1] + stack[sp] + sp = sp - 1 + end, + [19] = function() -- su (subtract) + stack[sp - 1] = stack[sp - 1] - stack[sp] + sp = sp - 1 + end, + [20] = function() -- mu (multiply) + stack[sp - 1] = stack[sp - 1] * stack[sp] + sp = sp - 1 + end, + [21] = function() -- di (divide & remainder) + local b = stack[sp] + local a = stack[sp - 1] + local x = math.abs(b) + local y = math.abs(a) + local q = constrain(y // x) + local r = constrain(y % x) + if a < 0 and b < 0 then + r = r * -1 + elseif a > 0 and b < 0 then + q = q * -1 + elseif a < 0 and b > 0 then + r = r * -1 + q = q * -1 + end + stack[sp] = q + stack[sp - 1] = r + end, + [22] = function() -- an (and) + stack[sp - 1] = stack[sp - 1] & stack[sp] + sp = sp - 1 + end, + [23] = function() -- or (or) + stack[sp - 1] = stack[sp - 1] | stack[sp] + sp = sp - 1 + end, + [24] = function() -- xo (xor) + stack[sp - 1] = stack[sp - 1] ~ stack[sp] + sp = sp - 1 + end, + [25] = function() -- sl (shift left) + stack[sp - 1] = stack[sp - 1] << stack[sp] + sp = sp - 1 + end, + [26] = function() -- sr (shift right) + stack[sp - 1] = stack[sp - 1] >> stack[sp] + sp = sp - 1 + end, + [27] = function() -- cp (compare) + local a = stack[sp] -- length + local b = stack[sp - 1] -- dest + local c = stack[sp - 2] -- source + local d = -1 -- flag + sp = sp - 3 + while a > 0 do + if memory[b] ~= memory[c] then + d = 0 + end + a = a - 1 + b = b + 1 + c = c + 1 + end + sp = sp + 1 + stack[sp] = d + end, + [28] = function() -- cy (copy) + local a = stack[sp] -- length + local b = stack[sp - 1] -- dest + local c = stack[sp - 2] -- source + sp = sp - 3 + while a > 0 do + memory[b] = memory[c] + a = a - 1 + b = b + 1 + c = c + 1 + end + end, + [29] = function() -- io + local d = stack[sp] + sp = sp - 1 + if d == 0 then + io.write(string.char(stack[sp])) + sp = sp - 1 + elseif d == 1 then + sp = sp + 1 + stack[sp] = string.byte(io.read(1)) + elseif d == 2 then + read_block() + elseif d == 3 then + write_block() + elseif d == 4 then + save_image() + elseif d == 5 then + load_image("ilo.rom") + ip = -1 + sp = 0 + rp = 0 + elseif d == 6 then + ip = 65536 + elseif d == 7 then + sp = sp + 1 + stack[sp] = sp - 1 + sp = sp + 1 + stack[sp] = rp + end + end +} + +-- ------------------------------------------------------------- +-- process opcodes +local function process_opcode(opcode) + if opcode == 0 then return end -- skip NOP instructions + local op_fn = opcodes[opcode] + if op_fn then op_fn() end +end + +local function process_opcodes() + local opcode = memory[ip] + process_opcode(opcode & 0xFF) + process_opcode(opcode>>8 & 0xFF) + process_opcode(opcode>>16 & 0xFF) + process_opcode(opcode>>24 & 0xFF) +end + +-- Load image into memory +-- \ cells = size of image file (in cells) +-- \ image = pointer to retroImage file +local function load_image(file) + local cells = file_size(file) / 4 + local image = io.open(file, 'rb') + local i = 0 + while i < cells do + memory[i] = string.unpack(' 0 do + print(stack[sp]) + sp = sp - 1 + end +end + +local function process_instructions() + while ip < 65536 do + process_opcodes() + ip = ip + 1 + end +end + +local function main() + load_image("ilo.rom") + process_instructions() + dump_stack() +end + +main() diff --git a/source/ilo.nim b/source/ilo.nim new file mode 100644 index 0000000..abe775f --- /dev/null +++ b/source/ilo.nim @@ -0,0 +1,241 @@ +# ************************************************************** +# crc's _ _ +# (_) | ___ +# | | |/ _ \ a tiny virtual computer +# | | | (_) | 64kw RAM, 32-bit, Dual Stack, MISC +# |_|_|\___/ ilo.nim (c) charles childers +# ************************************************************** + +# nim c -r vm/ilo.nim + +{.push overflowChecks: off.} + +var + ip, sp, rp: int32 + s: array[33, int32] + r: array[257, int32] + m: array[65536, int32] + +let + rom = "ilo.rom" + blocks = "ilo.blocks" + +proc load_image() = + let f = open(rom) + defer: f.close() + discard f.readBuffer(addr m[0], sizeof(m)) + +proc read_block() = + let f = open(blocks) + let buf = s[sp] + let blk = s[sp - 1] + sp = sp - 2 + defer: f.close() + f.setFilePos(blk * 4096) + discard f.readBuffer(addr m[buf], 4096) + +proc write_block() = + let f = open(blocks, fmReadWriteExisting) + let buf = s[sp] + let blk = s[sp - 1] + sp = sp - 2 + defer: f.close() + f.setFilePos(blk * 4096) + discard f.writeBuffer(addr m[buf], 4096) + +proc save_image() = + return + +proc opcode(o: int32) = + case o: + of 0: # .. + return + of 1: # li + ip = ip + 1 + sp = sp + 1 + s[sp] = m[ip] + of 2: # du + sp = sp + 1 + s[sp] = s[sp - 1] + of 3: # dr + sp = sp - 1 + of 4: # sw + let a = s[sp] + let b = s[sp - 1] + s[sp] = b + s[sp - 1] = a + of 5: # pu + rp = rp + 1 + r[rp] = s[sp] + sp = sp - 1 + of 6: # po + sp = sp + 1 + s[sp] = r[rp] + rp = rp - 1 + of 7: # ju + ip = s[sp] - 1 + sp = sp - 1 + of 8: # ca + rp = rp + 1 + r[rp] = ip + ip = s[sp] - 1 + sp = sp - 1 + of 9: # cc + let target = s[sp] + let flag = s[sp - 1] + sp = sp - 2 + if flag != 0: + rp = rp + 1 + r[rp] = ip + ip = target - 1 + of 10: # cj + let target = s[sp] + let flag = s[sp - 1] + sp = sp - 2 + if flag != 0: + ip = target - 1 + of 11: # re + ip = r[rp] + rp = rp - 1 + of 12: # eq + let b = s[sp] + let a = s[sp - 1] + sp = sp - 1 + if a == b: + s[sp] = -1 + else: + s[sp] = 0 + of 13: # ne + let b = s[sp] + let a = s[sp - 1] + sp = sp - 1 + if a != b: + s[sp] = -1 + else: + s[sp] = 0 + of 14: # lt + let b = s[sp] + let a = s[sp - 1] + sp = sp - 1 + if a < b: + s[sp] = -1 + else: + s[sp] = 0 + of 15: # gt + let b = s[sp] + let a = s[sp - 1] + sp = sp - 1 + if a > b: + s[sp] = -1 + else: + s[sp] = 0 + of 16: # fe + s[sp] = m[s[sp]] + of 17: # st + m[s[sp]] = s[sp - 1] + sp = sp - 2 + of 18: # ad + s[sp - 1] = s[sp - 1] + s[sp] + sp = sp - 1 + of 19: # su + s[sp - 1] = s[sp - 1] - s[sp] + sp = sp - 1 + of 20: # mu + s[sp - 1] = s[sp - 1] * s[sp] + sp = sp - 1 + of 21: # di + let b = s[sp] + let a = s[sp - 1] + s[sp] = a div b + s[sp - 1] = a mod b + of 22: # an + s[sp - 1] = s[sp - 1] and s[sp] + sp = sp - 1 + of 23: # or + s[sp - 1] = s[sp - 1] or s[sp] + sp = sp - 1 + of 24: # xo + s[sp - 1] = s[sp - 1] xor s[sp] + sp = sp - 1 + of 25: # sl + s[sp - 1] = s[sp - 1] shl s[sp] + sp = sp - 1 + of 26: # sr + s[sp - 1] = s[sp - 1] shr s[sp] + sp = sp - 1 + of 27: # cp + var length: int32 = s[sp] + var dest: int32 = s[sp - 1] + var src: int32 = s[sp - 2] + var flag: int32 = -1 + sp = sp - 2 + while length != 0: + if m[dest] != m[src]: + flag = 0 + dest = dest + 1 + src = src + 1 + length = length - 1 + s[sp] = flag + of 28: # cy + var length: int32 = s[sp] + var dest: int32 = s[sp - 1] + var src: int32 = s[sp - 2] + sp = sp - 3 + while length != 0: + m[dest] = m[src] + dest = dest + 1 + src = src + 1 + length = length - 1 + of 29: # io + let dev = s[sp] + sp = sp - 1 + case dev: + of 0: + if s[sp] != 0: + stdout.write $(char(s[sp])) + sp = sp - 1 + of 1: + var buf: array[1, byte] + discard stdin.readBytes(buf, 0, 1) + sp = sp + 1 + s[sp] = int32(buf[0]) + of 2: + read_block() + of 3: + write_block() + of 4: + echo "save_image()" + of 5: + load_image() + ip = 0 + sp = 0 + rp = 0 + of 6: + ip = 65536 + of 7: + sp = sp + 1 + s[sp] = sp - 1 + sp = sp + 1 + s[sp] = rp + else: + echo "unsupported io:", dev + else: + echo "wtf?" + +proc process() = + while ip < 65536: + let a = m[ip] and 255 + let b = (m[ip] shr 8) and 255 + let c = (m[ip] shr 16) and 255 + let d = (m[ip] shr 24) and 255 + opcode(a) + opcode(b) + opcode(c) + opcode(d) + ip = ip + 1 + +ip = 0 +sp = 0 +rp = 0 +load_image() +process() diff --git a/source/ilo.py b/source/ilo.py new file mode 100644 index 0000000..bbcd155 --- /dev/null +++ b/source/ilo.py @@ -0,0 +1,515 @@ +# ************************************************************** +# crc's _ _ +# (_) | ___ +# | | |/ _ \ a tiny virtual computer +# | | | (_) | 64kw RAM, 32-bit, Dual Stack, MISC +# |_|_|\___/ ilo.py (c) charles childers +# (c) arland childers +# ************************************************************** + +#Ilo.py v2.2b + +#Changes: +# Split debug modes: +# 'instrs': Counts overall time, and counts each instruction/bundle. +# 'timing': Just gives elapsed time. +# 'cProfile': Using cProfile, measure time & time for all instructions+overhead. Does not count time for unoptimised bundles. +# Added more optimised instruction bundles, focusing on DTC. +# Optimised many instructions, removing uneeded vars. Added raw_lit to not limit it when it is not needed. +# Faster block unpacking. The uncached blocks seem to only be ~1.7x slower instead of ~2x, now. +# Sorted some of the instructions listing, in the hopes it may make an improvement. It did not seem to. +# Added calls to limit the rom and blocks as they get put into memory. + + +#--- CONFIG +BLOCK_FILE = 'ilo.blocks' +ROM_FILE = 'ilo.rom' +BLOCK_CACHE = True + +DEBUG = False +# False for nothing +# 'timing' just gives elapsed time. Negligible time loss +# 'Instrs' counts instructions & bundles, but ~2.3x slower +# 'cProfile' for cProfile, but ~3.25x slower + + +#--- ILO + +import os + +def limit(val): + val &= 0xffffffff + if val & 0x80000000: + val -= 0x100000000 + return val + +def div_mod(a, b): + x = abs(a) + y = abs(b) + q, r = divmod(x, y) + if a < 0 and b < 0: + r *= -1 + elif a > 0 and b < 0: + q *= -1 + elif a < 0 and b > 0: + r *= -1 + q *= -1 + return q, r + + +class Stack: + def __init__(self, size): + self.sp = 0 + self.data = [0] * size + self.max = size + + def lit(self, val): + self.sp += 1 + self.data[self.sp] = ((val & 0xffffffff)-0x100000000) if val & 0x80000000 else (val & 0xffffffff) + + def raw_lit(self, val): + self.sp += 1 + self.data[self.sp] = val + + def pop(self): + self.sp -= 1 + return self.data[self.sp + 1] + + def top(self): + return self.data[self.sp] + + def second(self): + return self.data[self.sp - 1] + + def depth(self): + return self.sp + + +class BlockTools_NoCache: + def __init__(self, block_file, rom_file, data_stack, memory): + self.BLOCK_FILE = block_file + self.ROM_FILE = rom_file + self.data_stack = data_stack + self.memory = memory + + def block_unpack(self, block): + return [(limit(block[i] | (block[i + 1] << 8) | (block[i + 2] << 16) | (block[i + 3] << 24))) for i in range(0, len(block), 4)] + + def block_pack(self, *values): + return b''.join(val.to_bytes(4, 'little', signed=True) for val in values) + + def read_block(self): + buffer = self.data_stack.pop() + block = self.data_stack.pop() + with open(self.BLOCK_FILE, 'r+b') as f: + f.seek(4096 * block) + self.memory[buffer: buffer + 1024] = list(self.block_unpack(f.read(4096))) + + def block_write(self): + buffer = self.data_stack.pop() + block = self.data_stack.pop() + with open(self.BLOCK_FILE, 'r+b') as f: + f.seek(4096 * block) + f.write(self.block_pack(*self.memory[buffer: buffer + 1024])) + + def load_image(self): + with open(self.ROM_FILE, 'rb') as f: + raw_data = f.read(4 * 65536) + self.memory[:] = [limit(int.from_bytes(raw_data[i:i + 4], 'little')) for i in range(0, len(raw_data), 4)] + + def save_image(self): + with open(self.ROM_FILE, 'wb') as f: + for value in self.memory[:65536]: + f.write(value.to_bytes(4, 'little')) + + + +class BlockTools(BlockTools_NoCache): # caches blocks. + def __init__(self, block_file, rom_file, data_stack, memory): + self.BLOCK_FILE = block_file + self.ROM_FILE = rom_file + self.data_stack = data_stack + self.memory = memory + self.block_time = os.path.getmtime(block_file) + self.blocks = [] + + def read_block(self): + if self.block_time != os.path.getmtime(self.BLOCK_FILE): + self.read_all_blocks() + self.block_time = os.path.getmtime(self.BLOCK_FILE) + buffer = self.data_stack.pop() + self.memory[buffer: buffer + 1024] = self.blocks[self.data_stack.pop()] + + def read_all_blocks(self): + with open(self.BLOCK_FILE, 'rb') as f: + all_block_data = f.read() + self.blocks = [list(self.block_unpack(all_block_data[i:i+4096])) for i in range(0, len(all_block_data), 4096)] + return self.blocks + + +class ilo: + def __init__(self, block_file='ilo.blocks', rom_file='ilo.rom', cache_blocks=False): + self.ip = 0 + self.memory = [0] + self.input_buffer = [] + self.data = Stack(33) + self.address = Stack(257) + if cache_blocks: + self.block_tools = BlockTools(block_file, rom_file, self.data, self.memory) + else: + self.block_tools = BlockTools_NoCache(block_file, rom_file, self.data, self.memory) + self.instructions = { + 1: self.i01, + 4: self.i04, + 11: self.i11, + 6: self.i06, + 2: self.i02, + 5: self.i05, + 18: self.i18, + 2049: self.i2049, + 2832: self.i2832, + 10: self.i10, + 68288770: self.i68288770, + 8: self.i08, + 17563906: self.i17563906, + 7: self.i07, + 524545: self.i524545, + 3: self.i03, + 459014: self.i459014, + 9: self.i09, + 12: self.i12, + 13: self.i13, + 14: self.i14, + 15: self.i15, + 16: self.i16, + 17: self.i17, + 19: self.i19, + 20: self.i20, + 21: self.i21, + 22: self.i22, + 23: self.i23, + 24: self.i24, + 25: self.i25, + 26: self.i26, + 27: self.i27, + 28: self.i28, + 29: self.i29, + 1793: self.i1793, + 459009: self.i459009, + 67502597: self.i67502597, + 100926722: self.i100926722, + 302059522: self.i302059522, + 2818: self.i2818, + 219156993: self.i219156993, + 33689603: self.i33689603, + 167840769: self.i167840769, + 525572: self.i525572, + 134284806: self.i134284806 + } + + def i00(self): # nop + pass + + def i01(self): # lit + self.ip += 1 + self.data.lit(self.memory[self.ip]) + + def i02(self): # dup + self.data.raw_lit(self.data.top()) + + def i03(self): # drop + self.data.pop() + + def i04(self): # swap + a = self.data.pop() + b = self.data.pop() + self.data.raw_lit(a) + self.data.raw_lit(b) + + def i05(self): # push + self.address.raw_lit(self.data.pop()) + + def i06(self): # pop + self.data.raw_lit(self.address.pop()) + + def i07(self): # jump + self.ip = self.data.pop() - 1 + + def i08(self): # call + self.address.raw_lit(self.ip) + self.ip = self.data.pop() - 1 + + def i09(self): # ccall + target = self.data.pop() + flag = self.data.pop() + if flag != 0: + self.address.raw_lit(self.ip) + self.ip = target - 1 + + def i10(self): # cjump + target = self.data.pop() + flag = self.data.pop() + if flag != 0: + self.ip = target - 1 + + def i11(self): # return + self.ip = self.address.pop() + + def i12(self): # equal + self.data.raw_lit(-(self.data.pop() == self.data.pop())) + + def i13(self): # not equal + self.data.raw_lit(-(self.data.pop() != self.data.pop())) + + def i14(self): # less than + b = self.data.pop() + a = self.data.pop() + self.data.raw_lit(-(a < b)) + + def i15(self): # greater than + b = self.data.pop() + a = self.data.pop() + self.data.raw_lit(-(a > b)) + + def i16(self): # fetch + self.data.raw_lit(self.memory[self.data.pop()]) + + def i17(self): # store + a = self.data.pop() + self.memory[a] = self.data.pop() + + def i18(self): # add + self.data.lit(self.data.pop() + self.data.pop()) + + def i19(self): # subtract + b = self.data.pop() + self.data.lit(self.data.pop() - b) + + def i20(self): # multiply + self.data.lit(self.data.pop() * self.data.pop()) + + def i21(self): # divmod + a = self.data.pop() + a, b = div_mod(self.data.pop(), a) + self.data.raw_lit(b) + self.data.raw_lit(a) + + def i22(self): # and + self.data.raw_lit(self.data.pop() & self.data.pop()) + + def i23(self): # or + self.data.raw_lit(self.data.pop() | self.data.pop()) + + def i24(self): # xor + self.data.raw_lit(self.data.pop() ^ self.data.pop()) + + def i25(self): # shift left + b = self.data.pop() + self.data.lit(self.data.pop() << b) + + def i26(self): # shift right + b = self.data.pop() + self.data.raw_lit(self.data.pop() >> b) + + def i27(self): # compare memory + l = self.data.pop() + dest = self.data.pop() + src = self.data.pop() + self.data.raw_lit(-(self.memory[dest: dest + l] == self.memory[src: src + l])) + + def i28(self): # copy memory + l = self.data.pop() + dest = self.data.pop() + src = self.data.pop() + self.memory[dest: dest + l] = self.memory[src: src + l] + + def i29(self): # io + i = self.data.pop() + if i == 0: + print(chr(self.data.pop()), end='') + elif i == 1: + if not len(self.input_buffer): + self.input_buffer = ['\n'] + list(input())[::-1] + self.data.lit(ord(self.input_buffer.pop())) + elif i == 2: + self.block_tools.read_block() + elif i == 3: + self.block_tools.block_write() + elif i == 4: + self.block_tools.save_image() + elif i == 5: + self.block_tools.load_image() + self.ip = -1 + elif i == 6: + self.ip = 65535 + elif i == 7: + self.data.lit(self.data.depth()) + self.data.lit(self.address.depth()) + + def i2049(self): # lica.... + self.address.lit(self.ip + 1) + self.ip = self.memory[self.ip + 1] - 1 + + def i1793(self): # liju.... + self.ip = self.memory[self.ip + 1] - 1 + + def i524545(self): # lilica.. + self.data.lit(self.memory[self.ip + 1]) + self.address.lit(self.ip + 2) + self.ip = self.memory[self.ip + 2] - 1 + + def i459009(self): # liliju.. + self.data.lit(self.memory[self.ip + 1]) + self.ip = self.memory[self.ip + 2] - 1 + + def i67502597(self): # puduposw 'over' + self.data.lit(self.data.second()) + + def i17563906(self): # dulieqli + self.data.lit(-(self.memory[self.ip + 1] == self.data.top())) + self.data.lit(self.memory[self.ip + 2]) + self.ip += 2 + + def i100926722(self): # dupuswpo 'tuck' + a = self.data.pop() + b = self.data.pop() + self.data.lit(a) + self.data.lit(b) + self.data.lit(a) + + def i302059522(self): # dufeliad + self.data.lit(self.memory[self.data.top()] + self.memory[self.ip + 1]) + self.ip += 1 + + def i2818(self): # dure.... + self.data.raw_lit(self.data.top()) + self.ip = self.address.pop() + + def i219156993(self): # liadfene + self.ip += 1 + self.data.lit(-(limit(self.memory[self.memory[self.ip] + self.data.pop()]) != self.data.pop())) + + def i33689603(self): # drfedudu + self.data.pop() + m = self.memory[self.data.pop()] + self.data.lit(m) + self.data.lit(m) + self.data.lit(m) + + def i167840769(self): # lieqlicj + self.ip += 2 + if -(self.memory[self.ip-1] == self.data.pop()) != 0: + self.ip = self.memory[self.ip] - 1 + + def i2832(self): # fere.... + self.data.raw_lit(self.memory[self.data.pop()]) + self.ip = self.address.pop() + + def i68288770(self): #duliadsw + self.data.raw_lit(self.data.top()) + self.ip += 1 + self.data.lit(limit(self.memory[self.ip]) + self.data.pop()) + a = self.data.pop() + b = self.data.pop() + self.data.raw_lit(a) + self.data.raw_lit(b) + + def i525572(self): # swpuca.. + a = self.data.pop() + self.address.raw_lit(self.data.pop()) + self.data.raw_lit(a) + self.address.raw_lit(self.ip) + self.ip = self.data.pop() - 1 + + def i459014(self): # poliju.. + self.data.raw_lit(self.address.pop()) + self.ip = self.memory[self.ip+1] - 1 + + def i134284806(self): # popolica + self.data.raw_lit(self.address.pop()) + self.data.raw_lit(self.address.pop()) + self.ip += 1 + self.address.lit(self.ip) + self.ip = self.memory[self.ip] - 1 + + def print_opcode_bundle(self, opcode): + print(opcode & 0xFF, end=' ') + print((opcode >> 8) & 0xFF, end=' ') + print((opcode >> 16) & 0xFF, end=' ') + print((opcode >> 24) & 0xFF, end=': ') + + def process(self, c): + if c in self.instructions: + self.instructions[c]() + + def execute(self, start): + self.ip = start + while self.ip < 65536: + m = self.memory[self.ip] + if m in self.instructions: + self.instructions[m]() + else: + self.process(m & 0xFF) + self.process((m >> 8) & 0xFF) + self.process((m >> 16) & 0xFF) + self.process((m >> 24) & 0xFF) + self.ip += 1 + + def debug_execute(self, start): + data = {} + self.ip = start + while self.ip < 65536: + m = self.memory[self.ip] + if m in self.instructions: + self.instructions[m]() + else: + self.process(m & 0xFF) + self.process((m >> 8) & 0xFF) + self.process((m >> 16) & 0xFF) + self.process((m >> 24) & 0xFF) + data[str(m & 0xFF)] = data.get(str(m & 0xFF), 0) + 1 + data[str((m >> 8) & 0xFF)] = data.get(str((m >> 8) & 0xFF), 0) + 1 + data[str((m >> 16) & 0xFF)] = data.get(str((m >> 16) & 0xFF), 0) + 1 + data[str((m >> 24) & 0xFF)] = data.get(str((m >> 24) & 0xFF), 0) + 1 + data[str(m)] = data.get(str(m), 0) + 1 + self.ip += 1 + return data + + def main(self, debug=False): + self.block_tools.load_image() + if BLOCK_CACHE: + self.block_tools.read_all_blocks() + if debug: + return self.debug_execute(0) + else: + self.execute(0) + +def sort_dict(input_dict): + sorted_items = sorted(input_dict.items(), key=lambda x: x[1], reverse=True) + sorted_dict = dict(sorted_items) + return sorted_dict + +if __name__ == '__main__': + if DEBUG: + if DEBUG.lower() == 'instrs': + import time + start_time = time.time() + k = ilo(BLOCK_FILE, ROM_FILE, BLOCK_CACHE) + data = k.main(True) + end_time = time.time() + print(str(sort_dict(data)).replace(',', '\n').strip('{}')) + print('\nElapsed Time: ', end_time - start_time) + elif DEBUG.lower() == 'timing': + import time + start_time = time.time() + ilo(BLOCK_FILE, ROM_FILE, BLOCK_CACHE).main() + end_time = time.time() + print('\nElapsed Time: ', end_time - start_time) + elif DEBUG.lower() == 'cprofile': + import cProfile + cProfile.run('ilo(BLOCK_FILE, ROM_FILE, BLOCK_CACHE).main()', sort='tottime') + else: + print('Unknown debug mode') + else: + ilo(BLOCK_FILE, ROM_FILE, BLOCK_CACHE).main() + diff --git a/source/ilo.retro b/source/ilo.retro new file mode 100644 index 0000000..57040d0 --- /dev/null +++ b/source/ilo.retro @@ -0,0 +1,181 @@ +This is an implementation of the ilo computer. It's written in +RetroForth. I wrote this mostly to satisfy a personal desire to +run Konilo under RetroForth. + +The ilo computer is quite similar to the nga computer that Retro +runs on. Both are dual stack minimal instruction set computers +with similar instruction sets. But ilo is, by design, a smaller, +simpler system. + +ilo presents the following: + +- 65,5536 cells of memory +- 32-bit cells are the only addressable memory unit +- data stack of 32 values +- address stack of 256 addresses +- keyboard input +- serial display +- block storage +- blocks are 1,024 cells in size +- 30 instructions + + +# Memory And Loading The ROM + +A standard ilo system will provide exactly 65,536 cells of RAM. +I create a label pointing to this and allocate the space. + +~~~ +'IMAGE d:create #65536 allot +~~~ + +On startup, ilo loads a ROM (typically named "ilo.rom") into +memory. This will always be a full memory image, so the size +will be 65,536 cells. Loading this takes advantage of Retro's +`block:` vocabulary, reading in the ROM as a series of 64 1K +blocks. Doing this is significantly faster than reading the +ROM in byte by byte and assembling the bytes into cells. + +~~~ +:load-image (s-) + block:set-file + #64 [ I IMAGE I #1024 * + block:read ] indexed-times ; + +'ilo.rom load-image +~~~ + +# Stacks & Registers + +I create labels and allocate space for the two stacks. And also +create registers for the stack pointers and instruction pointer. +Using these, I then implement several words for moving values +to and from these. The `>s` and `s>` operate on the data stack +whereas `>r` and `r>` operate on the address stack. + +It'd be faster to just use the RetroForth stacks directly, but +this is cleaner and less error prone. It also makes debugging +easier as the ilo stacks are now separate entities. + +The last thing I define here is `[IP]`, which returns the value +in memory at the instruction pointer. This is strictly for +readability and could be inlined in the two places it's used. + +~~~ +'DataStack d:create #33 allot +'ReturnStack d:create #257 allot + +'SP var +'RP var +'IP var + +:>s (n-) &DataStack @SP + store &SP v:inc ; +:s> (-n) &SP v:dec &DataStack @SP + fetch ; +:>r (n-) &ReturnStack @RP + store &RP v:inc ; +:r> (-n) &RP v:dec &ReturnStack @RP + fetch ; + +:[IP] IMAGE @IP + fetch ; +~~~ + +# A Utility Word + +RetroForth doesn't have a word to directly compare two blocks +of memory. Until I rectify this, I define one here. + +~~~ +:compare (sdl-f) + #-1 swap + [ [ dup-pair &fetch bi@ eq? ] dip and [ &n:inc bi@ ] dip ] + times &drop-pair dip ; +~~~ + +# The ilo Instructions + +Now I'm ready to implement the ilo instruction set. I chose to +follow my (very) similar approach from retro-extend(1) and the +Autopsy debugger. This creates one word per instruction and then +fills in a jump table of pointers. + +If you are familiar with Retro, it should be pretty easy to +follow these. Mostly just move values onto the RetroForth stack, +do an operation, then put results back. + +The longest one of these is the I/O instruction, which has 8 +possible actions. I implemented this using a `case` structure. + +~~~ +:i:no ; +:i:li &IP v:inc [IP] >s ; +:i:du s> dup >s >s ; +:i:dr s> drop ; +:i:sw s> s> swap >s >s ; +:i:pu s> >r ; +:i:po r> >s ; +:i:ju s> n:dec !IP ; +:i:ca @IP >r i:ju ; +:i:cc s> s> [ >s i:ca ] &drop choose ; +:i:cj s> s> [ >s i:ju ] &drop choose ; +:i:re r> !IP ; +:i:eq s> s> eq? >s ; +:i:ne s> s> -eq? >s ; +:i:lt s> s> swap lt? >s ; +:i:gt s> s> swap gt? >s ; +:i:fe s> IMAGE + fetch >s ; +:i:st s> s> swap IMAGE + store ; +:i:ad s> s> + >s ; +:i:su s> s> swap - >s ; +:i:mu s> s> * >s ; +:i:di s> s> swap /mod swap >s >s ; +:i:an s> s> and >s ; +:i:or s> s> or >s ; +:i:xo s> s> xor >s ; +:i:sl s> s> swap n:abs n:negate shift >s ; +:i:sr s> s> swap n:abs shift >s ; +:i:cp s> s> s> [ IMAGE + ] bi@ 'abc 'cba reorder compare >s ; +:i:cy s> s> s> [ IMAGE + ] bi@ 'abc 'cba reorder copy ; +:i:io s> + #0 [ s> c:put ] case + #1 [ c:get >s ] case + #2 [ s> s> swap IMAGE + block:read ] case + #3 [ s> s> swap IMAGE + block:write ] case + #4 [ dump-stack ] case + #5 [ #-1 !IP ] case + #6 [ #65536 !IP ] case + #7 [ @SP >s @RP >s ] case + drop ; + +'Instructions d:create + &i:no , &i:li , &i:du , &i:dr , &i:sw , &i:pu , + &i:po , &i:ju , &i:ca , &i:cc , &i:cj , &i:re , + &i:eq , &i:ne , &i:lt , &i:gt , &i:fe , &i:st , + &i:ad , &i:su , &i:mu , &i:di , &i:an , &i:or , + &i:xo , &i:sl , &i:sr , &i:cp , &i:cy , &i:io , +~~~ + +# Instruction Processor + +~~~ +{{ + :mask #255 and ; + :next #8 shift ; +---reveal--- + :unpack (n-dcba) + dup mask swap next + dup mask swap next + dup mask swap next + 'abcd 'dcba reorder ; +}} + +:process-opcodes (n-) + unpack + &Instructions + fetch call + &Instructions + fetch call + &Instructions + fetch call + &Instructions + fetch call ; + +:process (-) + [ [IP] process-opcodes &IP v:inc @IP #0 #65535 n:between? ] while ; + +'ilo.blocks block:set-file + +process +~~~ diff --git a/source/ilo.rs b/source/ilo.rs new file mode 100644 index 0000000..b78a2ea --- /dev/null +++ b/source/ilo.rs @@ -0,0 +1,368 @@ +// ilo.rs, (c) charles childers, (c) 2024 Matt Keeter + +use std::convert::TryInto; +use std::fs::{File, OpenOptions}; +use std::io; +use std::io::{Read, Seek, SeekFrom, Write}; + +struct Ilo { + /// memory + memory: [i32; 65536], + /// data stack + data: [i32; 33], + /// address stack + addr: [i32; 257], + /// data stack pointer + sp: usize, + /// address stack pointer + rp: usize, + /// instruction pointer + ip: usize, +} + +impl Default for Ilo { + fn default() -> Self { + Self { + memory: [0; 65536], + data: [0; 33], + addr: [0; 257], + sp: 0, + rp: 0, + ip: 0, + } + } +} + +impl Ilo { + fn load_image(&mut self) { + match std::fs::read("ilo.rom") { + Ok(image) => { + for (i, c) in image.chunks(4).enumerate() { + self.store(i32::from_le_bytes(c.try_into().unwrap()), i); + } + } + Err(e) => { + panic!("could not load 'ilo.rom': {}", e); + } + } + } + + fn read_block(&mut self, block: i32, buffer: i32) -> io::Result<()> { + let mut f = File::open("ilo.blocks")?; + let mut data = [0; 4096]; + f.seek(SeekFrom::Start(4096 * (block as u64)))?; + f.read_exact(&mut data)?; + for (i, c) in data.chunks(4).enumerate() { + let x = c[0] as i32; + self.store(x, (buffer as usize) + i); + } + Ok(()) + } + + fn write_block(&self, block: i32, buffer: i32) -> io::Result<()> { + let mut f = OpenOptions::new() + .read(true) + .write(true) + .open("ilo.blocks")?; + let mut data = [0; 4096]; + for x in 0..1024 { + let v = self.fetch((buffer as usize) + x); + data[(x * 4)..][..4].copy_from_slice(&v.to_le_bytes()); + } + f.seek(SeekFrom::Start(4096 * (block as u64)))?; + f.write_all(&data)?; + Ok(()) + } + + fn push(&mut self, x: i32) { + self.sp += 1; + self.data[self.sp] = x; + } + fn pop(&mut self) -> i32 { + self.sp -= 1; + self.data[self.sp + 1] + } + + fn fetch(&self, a: usize) -> i32 { + self.memory[a] + } + fn store(&mut self, v: i32, a: usize) { + self.memory[a] = v; + } + + fn reset(&mut self) { + self.ip = 0; + self.sp = 0; + self.rp = 0; + } + fn next(&mut self) { + self.ip += 1; + } + + fn li(&mut self) { + self.next(); + self.push(self.fetch(self.here())); + } + fn du(&mut self) { + self.push(self.data[self.sp]); + } + fn dr(&mut self) { + self.pop(); + } + fn sw(&mut self) { + let x = self.pop(); + let y = self.pop(); + self.push(x); + self.push(y); + } + fn pu(&mut self) { + self.rp += 1; + self.addr[self.rp] = self.pop(); + } + fn po(&mut self) { + self.push(self.addr[self.rp]); + self.rp -= 1; + } + fn ju(&mut self) { + self.ip = (self.pop() - 1) as usize; + } + fn ca(&mut self) { + self.rp += 1; + self.addr[self.rp] = (self.ip) as i32; + self.ip = (self.pop() - 1) as usize; + } + fn cc(&mut self) { + let t = self.pop(); + if self.pop() != 0 { + self.push(t); + self.ca(); + } + } + fn cj(&mut self) { + let t = self.pop(); + if self.pop() != 0 { + self.push(t); + self.ju(); + } + } + fn re(&mut self) { + self.ip = (self.addr[self.rp]) as usize; + self.rp -= 1; + } + fn eq(&mut self) { + let y = self.pop(); + let x = self.pop(); + self.push(if x == y { -1 } else { 0 }); + } + fn ne(&mut self) { + let y = self.pop(); + let x = self.pop(); + self.push(if x != y { -1 } else { 0 }); + } + fn lt(&mut self) { + let y = self.pop(); + let x = self.pop(); + self.push(if x < y { -1 } else { 0 }); + } + fn gt(&mut self) { + let y = self.pop(); + let x = self.pop(); + self.push(if x > y { -1 } else { 0 }); + } + fn fe(&mut self) { + let x = self.pop() as usize; + self.push(self.fetch(x)); + } + fn st(&mut self) { + let x = self.pop() as usize; + let v = self.pop(); + self.store(v, x); + } + fn ad(&mut self) { + let y = self.pop(); + let x = self.pop(); + self.push(x.wrapping_add(y)); + } + fn su(&mut self) { + let y = self.pop(); + let x = self.pop(); + self.push(x.wrapping_sub(y)); + } + fn mu(&mut self) { + let y = self.pop(); + let x = self.pop(); + self.push(x.wrapping_mul(y)); + } + fn di(&mut self) { + let y = self.pop(); + let x = self.pop(); + self.push(x.wrapping_rem(y)); + self.push(x.wrapping_div(y)); + } + fn an(&mut self) { + let y = self.pop(); + let x = self.pop(); + self.push(x & y); + } + fn or(&mut self) { + let y = self.pop(); + let x = self.pop(); + self.push(x | y); + } + fn xo(&mut self) { + let y = self.pop(); + let x = self.pop(); + self.push(x ^ y); + } + fn sl(&mut self) { + let y = self.pop(); + let x = self.pop(); + self.push(x.wrapping_shl(y.try_into().unwrap())); + } + fn sr(&mut self) { + let y = self.pop(); + let x = self.pop(); + self.push(x.wrapping_shr(y.try_into().unwrap())); + } + fn cp(&mut self) { + let len = self.pop() as usize; + let dest = self.pop() as usize; + let src = self.pop() as usize; + let slice1 = &self.memory[src..(src + len)]; + let slice2 = &self.memory[dest..(dest + len)]; + if slice1 == slice2 { + self.push(-1); + } else { + self.push(0); + } + } + fn cy(&mut self) { + let mut len = self.pop(); + let mut dest = self.pop() as usize; + let mut src = self.pop() as usize; + while len > 0 { + self.store(self.fetch(src), dest); + len -= 1; + src += 1; + dest += 1; + } + } + fn io(&mut self) { + let dev = self.pop(); + match dev { + 0 => { + let mut c = self.pop(); + if c == 0 { + c = 32; + } + let mut stdout = std::io::stdout().lock(); + stdout.write_all(&[c as u8]).unwrap(); + stdout.flush().unwrap(); + } + 1 => match std::io::stdin().lock().bytes().next().unwrap() { + Ok(127) => self.push(8), + Ok(val) => self.push(val as i32), + Err(_) => std::process::exit(1), + }, + 2 => { + let buffer = self.pop(); + let block = self.pop(); + if let Err(e) = self.read_block(block, buffer) { + panic!("could not read 'ilo.blocks': {}", e); + } + } + 3 => { + let buffer = self.pop(); + let block = self.pop(); + if let Err(e) = self.write_block(block, buffer) { + panic!("could not write 'ilo.blocks': {}", e); + } + } + 4 => {} + 5 => { + self.load_image(); + self.ip = 70000; + } + 6 => { + self.ip = 65536; + } + 7 => { + self.push(self.sp as i32); + self.push(self.rp as i32); + } + _ => (), + } + } + + fn process(&mut self, inst: u8) { + match inst { + 0 => (), // nop + 1 => self.li(), + 2 => self.du(), + 3 => self.dr(), + 4 => self.sw(), + 5 => self.pu(), + 6 => self.po(), + 7 => self.ju(), + 8 => self.ca(), + 9 => self.cc(), + 10 => self.cj(), + 11 => self.re(), + 12 => self.eq(), + 13 => self.ne(), + 14 => self.lt(), + 15 => self.gt(), + 16 => self.fe(), + 17 => self.st(), + 18 => self.ad(), + 19 => self.su(), + 20 => self.mu(), + 21 => self.di(), + 22 => self.an(), + 23 => self.or(), + 24 => self.xo(), + 25 => self.sl(), + 26 => self.sr(), + 27 => self.cp(), + 28 => self.cy(), + 29 => self.io(), + _ => (), + } + } + + fn not_done(&self) -> bool { + self.ip < 65536 + } + fn here(&self) -> usize { + self.ip + } + + fn execute(&mut self) { + self.reset(); + while self.not_done() { + let opcode = self.fetch(self.here()); + for op in opcode.to_le_bytes() { + self.process(op); + } + if self.here() == 70000 { + self.reset(); + } else { + self.next(); + } + } + } + + fn dump_stack(&mut self) { + while self.sp > 0 { + let x = self.pop(); + println!("{x}"); + } + } +} + +fn main() { + let mut ilo = Ilo::default(); + ilo.load_image(); + ilo.execute(); + ilo.dump_stack(); +} diff --git a/source/ilo.swift b/source/ilo.swift new file mode 100644 index 0000000..3fd75d3 --- /dev/null +++ b/source/ilo.swift @@ -0,0 +1,310 @@ +// ------------------------------------------------------------- +// ilo.swift, (c) charles childers +// ------------------------------------------------------------- +// compile with: +// +// swiftc -O vm/ilo.swift -o ilo +// ------------------------------------------------------------- + +import Foundation + + +// ------------------------------------------------------------- +// Configuration +// ------------------------------------------------------------- + +let imageSize: Int = 65536 +let stackSize: Int = 33 +let addressSize: Int = 257 + + +// ------------------------------------------------------------- +// Globals +// ------------------------------------------------------------- + +// +----------+------------------------------------------------+ +// | Name | Contains | +// +==========+================================================+ +// | input | input buffer ("keyboard") | +// | ip | instruction pointer | +// | memory | random access memory | +// | data | data stack | +// | address | address stack | +// +----------+------------------------------------------------+ + +var input: String = "" +var ip: Int = 0 +var memory = [Int32](repeating: 0, count: imageSize) +var data = Stack(stackSize) +var address = Stack(addressSize) + + +// ------------------------------------------------------------- +// Support Functions +// ------------------------------------------------------------- + +func getInt32FromData(data: NSData, offset: Int) -> Int32 { + let raw = NSRange(location: offset * 4, length: 4) + var i = [Int32](repeating: 0, count: 1) + data.getBytes(&i, range: raw) + return Int32(i[0]) +} + + +// ------------------------------------------------------------- +// Instructions +// ------------------------------------------------------------- + +func inst_no() { } +func inst_li() { ip += 1; data.push(memory[ip]) } +func inst_du() { data.push(data.tos()) } +func inst_dr() { data.drop() } +func inst_sw() { data.swap() } +func inst_pu() { address.push(data.pop()) } +func inst_po() { data.push(address.pop()) } +func inst_ju() { ip = Int(data.pop() - 1) } +func inst_ca() { address.push(Int32(ip)); ip = Int(data.pop() - 1) } +func inst_cc() { let dest = data.pop(); if (data.pop() != 0) { address.push(Int32(ip)); ip = Int(dest - 1) } } +func inst_cj() { let dest = data.pop(); if (data.pop() != 0) { ip = Int(dest - 1) } } +func inst_re() { ip = Int(address.pop()) } +func inst_eq() { let tos = data.pop(), nos = data.pop(); data.push((nos == tos) ? -1 : 0) } +func inst_ne() { let tos = data.pop(), nos = data.pop(); data.push((nos != tos) ? -1 : 0) } +func inst_lt() { let tos = data.pop(), nos = data.pop(); data.push((nos < tos) ? -1 : 0) } +func inst_gt() { let tos = data.pop(), nos = data.pop(); data.push((nos > tos) ? -1 : 0) } +func inst_fe() { let target = Int(data.pop()); data.push(memory[target]) } +func inst_st() { let addr = data.pop(), value = data.pop(); memory[Int(addr)] = value } +func inst_ad() { let tos = data.pop(), nos = data.pop(); data.push(nos &+ tos) } +func inst_su() { let tos = data.pop(), nos = data.pop(); data.push(nos &- tos) } +func inst_mu() { let tos = data.pop(), nos = data.pop(); data.push(nos &* tos) } +func inst_di() { let a = data.pop(), b = data.pop(); data.push(b % a); data.push(b / a) } +func inst_an() { let tos = data.pop(), nos = data.pop(); data.push(tos & nos) } +func inst_or() { let tos = data.pop(), nos = data.pop(); data.push(nos | tos) } +func inst_xo() { let tos = data.pop(), nos = data.pop(); data.push(nos ^ tos) } +func inst_sl() { let tos = data.pop(), nos = data.pop(); data.push(nos << tos) } +func inst_sr() { let tos = data.pop(), nos = data.pop(); data.push(nos >> tos) } +func inst_cp() { + var len = Int(data.pop()) + var dest = Int(data.pop()) + var src = Int(data.pop()) + while (len != 0) { + if (memory[dest] != memory[src]) { data.push(0); return } + len -= 1 + dest += 1 + src += 1 + } + data.push(-1) +} +func inst_cy() { + var len = Int(data.pop()) + var dest = Int(data.pop()) + var src = Int(data.pop()) + while (len != 0) { + memory[dest] = memory[src] + len -= 1 + dest += 1 + src += 1 + } +} +func inst_io() { + let device = Int(data.pop()) + let devices: [(()->Void)] = [ + io_cput, io_cget, io_rb, io_wb, + io_si, io_pc, io_of, io_sd] + if device < 0 || device > 7 { return } + devices[device]() +} + + +// ------------------------------------------------------------- +// I/O Operations +// ------------------------------------------------------------- + +// +----------+------------------------------------------------+ +// | Function | Action | +// +==========+================================================+ +// | io_cput | Display a character to standard output | +// | io_cget | Read character from standard input source | +// | io_rb | Read block from storage | +// | io_wb | Write block to storage | +// | io_si | Save image (not implemented) | +// | io_pc | Reset ilo to default state, restarting | +// | io_of | Power off (exit) ilo | +// | is_sd | Return stack depths | +// +----------+------------------------------------------------+ + +func io_cput() { + let v = UnicodeScalar(Int(data.pop())) ?? UnicodeScalar(32) + print(Character(v!), terminator: "") +} +func io_cget() { + if (input.count > 0) { + let c = input.first! + guard let v = c.asciiValue else { return } + data.push(Int32(v)) + input = String(input.dropFirst()) + } else { + data.push(32) + } +} +func io_rb() { + let buffer = data.pop(), block = data.pop() + load_block(Int(block), to: Int(buffer)) +} +func io_wb() { + let buffer = data.pop(), block = data.pop() + write_block(Int(block), to: Int(buffer)) +} +func io_si() { } +func io_pc() { + load_image() + data.empty() + address.empty() + ip = -1 +} +func io_of() { ip = 65536; exit(0) } +func io_sd() { + data.push(Int32(data.depth())) + data.push(Int32(address.depth())) +} + + +// ------------------------------------------------------------- +// Block I/O +// ------------------------------------------------------------- + +func blocks() -> URL { + return URL(fileURLWithPath: "./ilo.blocks") +} + +func load_block(_ block: Int, to: Int) { + let storage = blocks() + let fd = try! FileHandle(forReadingFrom: storage) + fd.seek(toFileOffset: UInt64(block * 4096)) + let data = fd.readData(ofLength: 4096) as NSData + for i in 0 ... 1023 { + memory[to + i] = getInt32FromData(data: data, offset: i) + } + fd.closeFile() +} + +func write_block(_ block: Int, to: Int) { + let storage = blocks() + let fd = try! FileHandle(forUpdating: storage) + fd.seek(toFileOffset: UInt64(block * 4096)) + for i in 0 ... 1023 { + let word = Data(bytes: &memory[to + i], count: 4) + fd.write(word) + } + fd.closeFile() +} + + +// ------------------------------------------------------------- +// Instruction Processing +// ------------------------------------------------------------- + +func process_instruction(opcode: Int32) { + let instructions: [(()->Void)] = [ + inst_no, inst_li, inst_du, inst_dr, inst_sw, + inst_pu, inst_po, inst_ju, inst_ca, inst_cc, + inst_cj, inst_re, inst_eq, inst_ne, inst_lt, + inst_gt, inst_fe, inst_st, inst_ad, inst_su, + inst_mu, inst_di, inst_an, inst_or, inst_xo, + inst_sl, inst_sr, inst_cp, inst_cy, inst_io] + // skip `no` and invalid opcodes + if opcode < 1 || opcode > 29 { return } + instructions[Int(opcode)]() +} + +func process() { + while input.count > 0 { + for inst in memory[ip].bytes { + process_instruction(opcode: Int32(inst)) + } + ip += 1 + } +} + + +// ------------------------------------------------------------- +// Initialization +// ------------------------------------------------------------- + +func load_image() { + let fileURL = URL(fileURLWithPath: "./ilo.rom") + let data = NSData(contentsOf: fileURL)! + var i: Int = 0 + while (i < 65536) { + memory[i] = getInt32FromData(data: data, offset: i) + i += 1 + } +} + +func bootstrap() { + if memory[0] == 0 { + load_image() + ip = 0 + data.empty() + address.empty() + } + input = " " + process() +} + + +// ------------------------------------------------------------- +// Stacks +// ------------------------------------------------------------- + +class Stack { + private var limit: Int + private var data: [Int32] + private var sp: Int = 0 + init(_ size: Int) { + data = [Int32](repeating: 0, count: size) + limit = size + } + public func tos() -> Int32 { return data[sp] } + public func nos() -> Int32 { return data[sp - 1] } + public func push(_ n: Int32) { sp += 1; data[sp] = n } + public func pop() -> Int32 { sp -= 1; return data[sp + 1] } + public func drop() { sp -= 1 } + public func swap() { let a = data[sp]; let b = data[sp - 1]; data[sp] = b; data[sp - 1] = a } + public func depth() -> Int { return sp } + public func item(_ n: Int) -> Int32 { return data[n] } + public func empty() { sp = 0 } +} + + +// ------------------------------------------------------------- +// Extensions to Existing Classes +// ------------------------------------------------------------- + +extension FixedWidthInteger where Self: SignedInteger { + var bytes: [Int8] { + var _endian = littleEndian + let bytePtr = withUnsafePointer(to: &_endian) { + $0.withMemoryRebound(to: Int8.self, capacity: MemoryLayout.size) { + UnsafeBufferPointer(start: $0, count: MemoryLayout.size) + } + } + return [Int8](bytePtr) + } +} + + +// ------------------------------------------------------------- +// Top-level System +// ------------------------------------------------------------- + +func main() { + bootstrap() + while ip < 65535 { + input = readLine() ?? "" + input = " \(input) \n" + process() + } +} + +main() + diff --git a/source/ilo.ts b/source/ilo.ts new file mode 100644 index 0000000..d6ba37b --- /dev/null +++ b/source/ilo.ts @@ -0,0 +1,516 @@ +/* ilo.ts, an ilo in TypeScript. (c) Rick Carlino */ + +/* Run via `npx ts-node ilo.ts`. + + If you get errors, try running `npx tsc --init` first. */ + +type OutputCallback = (char: string) => void; + +function enforce32BitSignedInteger(value: number) { + const int32Max = Math.pow(2, 31) - 1; + const int32Min = -Math.pow(2, 31); + value = value | 0; + value = ((value - int32Min) % (int32Max - int32Min + 1)) + int32Min; + return value; +} + +export class Konilo { + private m: Int32Array; + private blocks: Int32Array; + private ds: Int32Array; + private as: Int32Array; + + private ip: number; + private sp: number; + private rp: number; + + private a: number; + private b: number; + private f: number; + private s: number; + private d: number; + private l: number; + + private cycles: number; + + private input: string; + private outputHandler: OutputCallback; + + constructor(public romURL: string, public blockURL: string) { + this.m = new Int32Array(65536); + this.blocks = new Int32Array(1024 * 1024); + this.ds = new Int32Array(33); + this.as = new Int32Array(257); + + this.ip = 0; + this.sp = 0; + this.rp = 0; + + this.a = 0; + this.b = 0; + this.f = 0; + this.s = 0; + this.d = 0; + this.l = 0; + this.cycles = 25000; + + this.input = ""; + this.outputHandler = (char: string) => {}; + } + + async initialize(): Promise { + await Promise.all([ + this.loadFile(this.romURL, this.m), + this.loadFile(this.blockURL, this.blocks), + ]); + } + + async loadFile(url: string, target: Int32Array): Promise { + await fetch(url) + .then((response) => response.arrayBuffer()) + .then((buffer) => { + const dataView = new DataView(buffer); + for (let i = 0; i < target.length; i++) { + target[i] = dataView.getInt32(i * 4, true); + } + }) + .catch((error) => { + console.error("Error loading the file:", error); + }); + } + + async execute(): Promise { + console.log("Hello from Konilo!"); + let ticks = 0; + while (this.ip < 65536 && this.input.length >= 1 && !isNaN(this.ip)) { + const o = this.m[this.ip]; + this.process(o & 0xff); + this.process((o >> 8) & 0xff); + this.process((o >> 16) & 0xff); + this.process((o >> 24) & 0xff); + this.ip = this.ip + 1; + ticks += 1; + if (ticks % this.cycles === 0) { + ticks = 0; + await this.sleep(0); + } + } + await this.sleep(0); + console.log("Goodbye from Konilo!"); + } + + async sleep(ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)); + } + + loadROM(): void { + this.loadFile(this.romURL, this.m); + } + + loadBlocks(): void { + this.loadFile(this.blockURL, this.blocks); + } + + setOutputHandler(callback: OutputCallback): void { + this.outputHandler = callback; + } + + send(str: string): void { + this.input += str; + } + + process(o: number) { + switch (o) { + case 0: + break; + case 1: + this.li(); + break; + case 2: + this.du(); + break; + case 3: + this.dr(); + break; + case 4: + this.sw(); + break; + case 5: + this.pu(); + break; + case 6: + this.po(); + break; + case 7: + this.ju(); + break; + case 8: + this.ca(); + break; + case 9: + this.cc(); + break; + case 10: + this.cj(); + break; + case 11: + this.re(); + break; + case 12: + this.eq(); + break; + case 13: + this.ne(); + break; + case 14: + this.lt(); + break; + case 15: + this.gt(); + break; + case 16: + this.fe(); + break; + case 17: + this.st(); + break; + case 18: + this.ad(); + break; + case 19: + this.su(); + break; + case 20: + this.mu(); + break; + case 21: + this.di(); + break; + case 22: + this.an(); + break; + case 23: + this.or(); + break; + case 24: + this.xo(); + break; + case 25: + this.sl(); + break; + case 26: + this.sr(); + break; + case 27: + this.cp(); + break; + case 28: + this.cy(); + break; + case 29: + this.io(); + break; + default: + break; + } + this.guard(); + } + + guard() { + this.ds[this.sp] = enforce32BitSignedInteger(this.ds[this.sp]); + if (this.sp >= 2) { + this.ds[this.sp - 1] = enforce32BitSignedInteger(this.ds[this.sp - 1]); + } + } + + save_ip() { + this.rp += 1; + this.as[this.rp] = this.ip; + } + pop() { + this.sp -= 1; + return this.ds[this.sp + 1]; + } + + push(v: number) { + this.ds[this.sp + 1] = v; + this.sp += 1; + } + + symmetric() { + if (this.b >= 0 && this.ds[this.sp - 1] < 0) { + this.ds[this.sp] += 1; + this.ds[this.sp - 1] -= this.b; + } + } + + li() { + this.ip += 1; + this.push(this.m[this.ip]); + } + + du() { + this.push(this.ds[this.sp]); + } + + dr() { + this.ds[this.sp] = 0; + this.sp -= 1; + } + + sw() { + const a = this.ds[this.sp]; + this.ds[this.sp] = this.ds[this.sp - 1]; + this.ds[this.sp - 1] = a; + } + + pu() { + this.rp += 1; + this.as[this.rp] = this.pop(); + } + + po() { + this.push(this.as[this.rp]); + this.rp -= 1; + } + + ju() { + this.ip = this.pop() - 1; + } + + ca() { + this.save_ip(); + this.ip = this.pop() - 1; + } + + cc() { + const a = this.pop(); + if (this.pop()) { + this.save_ip(); + this.ip = a - 1; + } + } + + cj() { + const a = this.pop(); + if (this.pop()) { + this.ip = a - 1; + } + } + + re() { + this.ip = this.as[this.rp]; + this.rp -= 1; + } + + eq() { + this.ds[this.sp - 1] = this.ds[this.sp - 1] == this.ds[this.sp] ? -1 : 0; + this.sp -= 1; + } + + ne() { + this.ds[this.sp - 1] = this.ds[this.sp - 1] != this.ds[this.sp] ? -1 : 0; + this.sp -= 1; + } + + lt() { + this.ds[this.sp - 1] = this.ds[this.sp - 1] < this.ds[this.sp] ? -1 : 0; + this.sp -= 1; + } + + gt() { + this.ds[this.sp - 1] = this.ds[this.sp - 1] > this.ds[this.sp] ? -1 : 0; + this.sp -= 1; + } + + fe() { + this.ds[this.sp] = this.m[this.ds[this.sp]]; + } + + st() { + this.m[this.ds[this.sp]] = this.ds[this.sp - 1]; + this.sp -= 2; + } + + ad() { + this.ds[this.sp - 1] += this.ds[this.sp]; + this.sp -= 1; + } + + su() { + this.ds[this.sp - 1] -= this.ds[this.sp]; + this.sp -= 1; + } + + mu() { + this.ds[this.sp - 1] *= this.ds[this.sp]; + this.sp -= 1; + } + + di() { + this.a = this.ds[this.sp]; + this.b = this.ds[this.sp - 1]; + this.ds[this.sp] = Math.floor(this.b / this.a); + this.ds[this.sp - 1] = this.b % this.a; + this.symmetric(); + } + + an() { + this.ds[this.sp - 1] = this.ds[this.sp] & this.ds[this.sp - 1]; + this.sp -= 1; + } + + or() { + this.ds[this.sp - 1] = this.ds[this.sp] | this.ds[this.sp - 1]; + this.sp -= 1; + } + + xo() { + this.ds[this.sp - 1] = this.ds[this.sp] ^ this.ds[this.sp - 1]; + this.sp -= 1; + } + + sl() { + this.ds[this.sp - 1] = this.ds[this.sp - 1] << this.ds[this.sp]; + this.sp -= 1; + } + + sr() { + this.ds[this.sp - 1] = this.ds[this.sp - 1] >> this.ds[this.sp]; + this.sp -= 1; + } + + cp() { + let l = this.pop(); + let d = this.pop(); + let s = this.ds[this.sp]; + this.ds[this.sp] = -1; + + while (l) { + if (this.m[d] !== this.m[s]) { + this.ds[this.sp] = 0; + } + l -= 1; + s += 1; + d += 1; + } + } + + io() { + const dev = this.pop(); + switch (dev) { + case 0: + this.ioa(); + break; + case 1: + this.iob(); + break; + case 2: + this.ioc(); + break; + case 3: + this.iod(); + break; + case 4: + this.ioe(); + break; + case 5: + this.iof(); + break; + case 6: + this.iog(); + break; + case 7: + this.ioh(); + break; + default: + console.log("wtf? " + dev); + break; + } + } + + cy() { + let l = this.pop(); + let d = this.pop(); + let s = this.pop(); + + while (l) { + this.m[d] = this.m[s]; + l -= 1; + s += 1; + d += 1; + } + } + + ioa() { + const c = String.fromCharCode(this.pop()); + this.outputHandler(c); + } + + iob() { + this.a = this.input.charCodeAt(0); + this.input = this.input.slice(1); + this.push(this.a); + } + + ioc() { + const buf = this.pop(); + const blk = this.pop(); + let i = 0; + while (i < 1024) { + this.m[buf + i] = this.blocks[blk * 1024 + i]; + i += 1; + } + } + + iod() { + const buf = this.pop(); + const blk = this.pop(); + let i = 0; + while (i < 1024) { + this.blocks[blk * 1024 + i] = this.m[buf + i]; + i += 1; + } + } + + ioe() {} + + iof() { + this.ip = -1; + this.sp = 0; + this.rp = 0; + this.loadFile(this.romURL, this.m); + } + + iog() { + this.ip = 65536; + this.input = ""; + } + + ioh() { + this.push(this.sp); + this.push(this.rp); + } +} + +(async () => { + const vm = new Konilo( + "http://forth.works/demo/ilo.rom", + "http://forth.works/demo/ilo.blocks" + ); + + let outputBuffer = ""; + + vm.setOutputHandler((char: string) => { + if (char === "\n") { + console.log(outputBuffer); + outputBuffer = ""; + } else { + outputBuffer += char; + } + }); + + await vm.initialize(); + vm.send("list\n\n"); + vm.execute(); +})(); diff --git a/source/mult-ilo.c b/source/mult-ilo.c new file mode 100644 index 0000000..6e4c6e8 --- /dev/null +++ b/source/mult-ilo.c @@ -0,0 +1,264 @@ +/*************************************************************** + crc's _ _ ___ _ + _ __ ___ _ _| | |_ / (_) | ___ + | '_ ` _ \| | | | | __| / /| | |/ _ \ + | | | | | | |_| | | |_ / / | | | (_) | + |_| |_| |_|\__,_|_|\__/_/ |_|_|\___/ + (c) charles childers + + This is a special implementation of my ilo computer, with many + copies of ilo running under a single process. Under this you + can quickly switch between ilo instances. + + - `bye` will act like `restart` on the current computer + - ctrl+c restarts the current computer + - ctrl+n switches to the next ilo + - ctrl+p switches to the previous ilo + - ctrl+a shuts down mult/ilo + - switching can only be done when the system is waiting for + input + + **************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define V void +#define I int +#define C char + +#define ILOS 5 + +struct termios old_term, new_term; +typedef struct ilo ilo; + +struct ilo { + I ip, /* instruction pointer */ + sp, /* data stack pointer */ + rp, /* address stack pointer */ + ds[33], /* data stack */ + as[257], /* address stack */ + m[65536]; /* memory */ + C *blocks, /* name of block file (ilo.blocks) */ + *rom; /* name of image (ilo.rom) */ + I a, b, f, s, d, l; + C i[1]; +}; + +struct ilo systems[ILOS]; + +I cur, cancel; + +#define DS v->ds +#define AS v->as +#define SP v->sp +#define RP v->rp +#define IP v->ip +#define M v->m +#define A v->a +#define B v->b +#define S v->s +#define D v->d +#define L v->l +#define T DS[SP] /* Top of Data Stack */ +#define N DS[SP-1] /* Next on Data Stack */ +#define R AS[RP] /* Top of Address Stack */ + +V iof(ilo *); + +V push(ilo *v, I n) { DS[SP + 1] = n; SP += 1; } +I pop(ilo *v) { SP -= 1; return DS[SP + 1]; } + +V load_image(ilo *v) { + v->f = open(v->rom, O_RDONLY, 0666); + if (!v->f) { return; }; + read(v->f, &M, 65536 * 4); + close(v->f); + v->i[0] = 32; + IP = SP = RP = 0; +} + +V save_image(ilo *v) { + v->f = open(v->rom, O_WRONLY, 0666); + write(v->f, &M, 65536 * 4); + close(v->f); +} + +V block_common(ilo *v) { + B = pop(v); /* block buffer */ + A = pop(v); /* block number */ + lseek(v->f, 4096 * A, SEEK_SET); +} + +V read_block(ilo *v) { + v->f = open(v->blocks, O_RDONLY, 0666); + block_common(v); + read(v->f, M + B, 4096); + close(v->f); +} + +V write_block(ilo *v) { + v->f = open(v->blocks, O_WRONLY, 0666); + block_common(v); + write(v->f, M + B, 4096); + close(v->f); +} + +V save_ip(ilo *v) { RP += 1; R = IP; } +V symmetric(ilo *v) { + if (B >= 0 && N < 0) { T += 1; N -= B; } } + +V li(ilo *v) { IP += 1; push(v, M[IP]); } +V du(ilo *v) { push(v, T); } +V dr(ilo *v) { DS[SP] = 0; SP -= 1; } +V sw(ilo *v) { A = T; T = N; N = A; } +V pu(ilo *v) { RP += 1; R = pop(v); } +V po(ilo *v) { push(v, R); RP -= 1; } +V ju(ilo *v) { IP = pop(v) - 1; } +V ca(ilo *v) { save_ip(v); IP = pop(v) - 1; } +V cc(ilo *v) { A = pop(v); + if (pop(v)) { save_ip(v); + IP = A - 1; } } +V cj(ilo *v) { A = pop(v); + if (pop(v)) { IP = A - 1; } } +V re(ilo *v) { IP = R; RP -= 1; } +V eq(ilo *v) { N = (N == T) ? -1 : 0; SP -= 1; } +V ne(ilo *v) { N = (N != T) ? -1 : 0; SP -= 1; } +V lt(ilo *v) { N = (N < T) ? -1 : 0; SP -= 1; } +V gt(ilo *v) { N = (N > T) ? -1 : 0; SP -= 1; } +V fe(ilo *v) { T = M[T]; } +V st(ilo *v) { M[T] = N; SP -= 2; } +V ad(ilo *v) { N += T; SP -= 1; } +V su(ilo *v) { N -= T; SP -= 1; } +V mu(ilo *v) { N *= T; SP -= 1; } +V di(ilo *v) { A = T; B = N; + if (A == 0) { cancel = 1; iof(v); return; } + T = B / A; N = B % A; + symmetric(v); } +V an(ilo *v) { N = T & N; SP -= 1; } +V or(ilo *v) { N = T | N; SP -= 1; } +V xo(ilo *v) { N = T ^ N; SP -= 1; } +V sl(ilo *v) { N = N << T; SP -= 1; } +V sr(ilo *v) { N = N >> T; SP -= 1; } +V cp(ilo *v) { L = pop(v); D = pop(v); S = T; T = -1; + while (L) { + if (M[D] != M[S]) { T = 0; } + L -= 1; S += 1; D += 1; } } +V cy(ilo *v) { L = pop(v); D = pop(v); S = pop(v); + while (L) { + M[D] = M[S]; + L -= 1; S += 1; D += 1; } } + +V pre(V) { cur -= 1; if (cur < 0) cur = ILOS - 1; } +V nxt(V) { cur += 1; if (cur > (ILOS - 1)) cur = 0; } + +V msgs(V) { printf("\n*** SWITCH TO %d ***\n", cur); } +V msgx(V) { printf("\n*** SHUTDOWN REQUESTED ***\n"); + tcsetattr(STDIN_FILENO,TCSANOW, &old_term); + exit(1); } +V msgr(V) { printf("\n*** RESTART %d ***\n", cur); } + +V ioa(ilo *v) { v->i[0] = (char)pop(v); write(1, &v->i, 1); } +V iob(ilo *v) { read(0, &v->i, 1); push(v, v->i[0]); + if (v->i[0] == 14) { T = 32; nxt(); msgs(); } + if (v->i[0] == 16) { T = 32; pre(); msgs(); } + if (v->i[0] == 3) { T = 32; msgr(); iof(v); + cancel = 1; } + if (v->i[0] == 1) { T = 32; msgx(); } + if (v->i[0] == 8 || v->i[0] == 127) { + v->i[0] = '\b'; write(1, &v->i, 1); + v->i[0] = ' '; write(1, &v->i, 1); + v->i[0] = '\b'; write(1, &v->i, 1); + } else { write(1, &v->i, 1); } } +V ioc(ilo *v) { read_block(v); } +V iod(ilo *v) { write_block(v); } +V ioe(ilo *v) { save_image(v); } +V iof(ilo *v) { load_image(v); IP = -1; } +V iog(ilo *v) { iof(v); } +V ioh(ilo *v) { push(v, SP); push(v, RP); } + +V io(ilo *v) { + switch (pop(v)) { + case 0: ioa(v); break; case 1: iob(v); break; + case 2: ioc(v); break; case 3: iod(v); break; + case 4: ioe(v); break; case 5: iof(v); break; + case 6: iog(v); break; case 7: ioh(v); break; + default: break; + } +} + +V process(ilo *v, I o) { + switch (o) { + case 0: break; case 1: li(v); break; + case 2: du(v); break; case 3: dr(v); break; + case 4: sw(v); break; case 5: pu(v); break; + case 6: po(v); break; case 7: ju(v); break; + case 8: ca(v); break; case 9: cc(v); break; + case 10: cj(v); break; case 11: re(v); break; + case 12: eq(v); break; case 13: ne(v); break; + case 14: lt(v); break; case 15: gt(v); break; + case 16: fe(v); break; case 17: st(v); break; + case 18: ad(v); break; case 19: su(v); break; + case 20: mu(v); break; case 21: di(v); break; + case 22: an(v); break; case 23: or(v); break; + case 24: xo(v); break; case 25: sl(v); break; + case 26: sr(v); break; case 27: cp(v); break; + case 28: cy(v); break; case 29: io(v); break; + default: break; + } +} + +V process_bundle(ilo *v, I opcode) { + if (cancel) return; process(v, opcode & 0xFF); + if (cancel) return; process(v, (opcode >> 8) & 0xFF); + if (cancel) return; process(v, (opcode >> 16) & 0xFF); + if (cancel) return; process(v, (opcode >> 24) & 0xFF); +} + +V execute(V) { + ilo *v = &systems[cur]; + while (IP < 65536) { + cancel = 0; + process_bundle(v, M[IP]); + IP += 1; + v = &systems[cur]; + } +} + +V handle_sigint(I sig) { + printf("\n*** SIGINT (%d) : RESTARTING %d ***\n", sig, cur); + cancel = 1; + iof(&systems[cur]); +} + +I main(I argc, C **argv) { + ilo *v; + I i; + + cur = 0; + for (i = 0; i < ILOS; i++) { + v = &systems[i]; + v->blocks = (argc > 1) ? argv[1] : "ilo.blocks"; + v->rom = (argc > 2) ? argv[2] : "ilo.rom"; + load_image(v); + } + if (signal(SIGINT, handle_sigint) == SIG_ERR) { + perror("signal"); + return 1; + } + + tcgetattr(STDIN_FILENO, &old_term); + new_term = old_term; + new_term.c_lflag &=(~ICANON & ~ECHO); + tcsetattr(STDIN_FILENO, TCSANOW, &new_term); + + execute(); + + tcsetattr(STDIN_FILENO, TCSANOW, &old_term); + + return 0; +} diff --git a/source/x11-ilo.c b/source/x11-ilo.c new file mode 100644 index 0000000..1c37fab --- /dev/null +++ b/source/x11-ilo.c @@ -0,0 +1,466 @@ +/*************************************************************** + crc's _ _ __ + (_) | ___ / /_ __ + | | |/ _ \ / /\ \/ / a tiny virtual computer + | | | (_) / / > < 64kw RAM, 32-bit, Dual Stack, MISC + |_|_|\___/_/ /_/\_\ ilo-x.c (c) charles childers + **************************************************************/ + +/* cc -o ilo-x vm/ilo-x.c `pkg-config --cflags x11 --libs` */ + +/* Local Configuration */ + +#define BLOCKS "ilo.blocks" +#define ROM "ilo.rom" +#define FONT "ilo.fnt" +#define FG 0xFFFFFF +#define BG 0x000000 +#define CURSOR 0x00FFFF +#define FW 640 +#define FH 384 +#define FONT_H 16 +#define FONT_W 8 + +#include +#include +#include +#include +#include +#include + +#define T ds[sp] /* Top of Data Stack */ +#define N ds[sp-1] /* Next on Data Stack */ +#define R as[rp] /* Top of Address Stack */ +#define V void +#define I int +#define C char + +I ip, /* instruction pointer */ + sp, /* data stack pointer */ + rp, /* address stack pointer */ + ds[33], /* data stack */ + as[257], /* address stack */ + m[65536], /* memory */ + ok; + +C *blocks, /* name of block file (ilo.blocks) */ + *rom; /* name of image (ilo.rom) */ + +I a, b, f, s, d, l; /* these others are used */ +C i[1]; /* for misc. purposes */ + +#define TERM_W (FW / FONT_W) +#define TERM_H (FH / FONT_H) + +I frame[(FW * FH)/32]; /* frame buffer for display */ +I font[4096]; /* font bitmap */ +I tx, ty; /* text cursor location */ + +/* variables for Arland's DEC subset */ +I acc[32], acc_i = 0, ground = 0, on = 0; + +/* variables for X11 stuff */ +Display *disp; +Window win; +GC gc; +XEvent event; +C text[255]; + +V dputc(I); +V redraw(); +V iof(); + +V p(char *s) { while(*s) dputc(*s++); } +V e(char *s) { p("E:"); p(s); p("\n"); ok = 1; iof(); } +V dso() { if ((sp + 1) > 32) { e("DSO"); } } +V dsu() { if ((sp - 1) < 0) { e("DSU"); } } +V rso() { if ((rp + 1) > 256) { e("RSO"); } } +V rsu() { if ((rp - 1) < 0) { e("RSU"); } } +V dbz() { if (T == 0) { e("DBZ"); } } +V mem() { if (T < 0 || T > 65535) { e("MEM"); } } +V uli() { if (f == -1) { e("ULI"); } } +V ulf() { if (f == -1) { e("ULF"); } } +V usi() { if (f == -1) { e("URI"); } } +V urb() { if (f == -1) { e("URB"); } } +V uwb() { if (f == -1) { e("UWB"); } } +V push(I v) { dso(); ds[sp + 1] = v; sp += 1; } +I pop() { dsu(); sp -= 1; return ds[sp + 1]; } + +V cursor() { + XSetForeground(disp, gc, CURSOR); + XFillRectangle(disp, win, gc, tx, ty, FONT_W, FONT_H); + XFlush(disp); +} + +I wait_key() { + while (1) { + XNextEvent(disp, &event); + if (event.type == KeyPress) { + KeySym key = XLookupKeysym(&event.xkey, 0); + XLookupString(&event.xkey, text, 255, &key, 0); + if (text[0] == 13) text[0] = 10; + if (text[0] != 0) return (I) text[0]; + } + if (event.type == Expose) { redraw(); } + } +} + +V load_font() { + f = open(FONT, O_RDONLY, 0666); + ulf(); + if (!f) { return; }; + read(f, &font, 4096); + close(f); +} + +V pixel(I x, I y, I c) { + I index = y * FW + x; + if (c == 0) { + frame[(index / 32)] &= ~(1 << (31 - index % 32)); + XSetForeground(disp, gc, BG); + } else { + frame[(index / 32)] |= 1 << (31 - index % 32); + XSetForeground(disp, gc, FG); + } + XDrawPoint(disp, win, gc, x, y); +} + +I get_pixel(I x, I y) { + I index = y * FW + x; + I bit_pos = 31 - index % 32; + I mask = 1 << bit_pos; + return (frame[(index / 32)] & mask) >> bit_pos; +} + +V redraw() { + for (I x = 0; x < FW; x++) { + for (I y = 0; y < FH; y++) { + XSetForeground(disp, gc, get_pixel(x, y) ? FG : BG); + XDrawPoint(disp, win, gc, x, y); + } + } + cursor(); +} + +V scroll() { + I memsize = (FH * FW) / 32; + I last_row = (FW * FONT_H) / 32; + for (I i = 0; i < memsize - last_row; i++) { + frame[i] = frame[i + last_row]; + } + for (I i = memsize - last_row; i < memsize; i++) { + frame[i] = 0; + } + redraw(); +} + +unsigned C reverse(unsigned C b) { + b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; + b = (b & 0xCC) >> 2 | (b & 0x33) << 2; + b = (b & 0xAA) >> 1 | (b & 0x55) << 1; + return b; +} + +V handle_special_character(I c) { + if (c == 8 || c == 127) { /* BACKSPACE/DELETE */ + if (tx - FONT_W >= 0) { + tx -= FONT_W ; + dputc(' '); + tx -= FONT_W; + redraw(); + } + } else if (c == 9) { /* TAB */ + I ts = tx / FONT_W; + for (I i = ts; i < ((ts + 7) / 8) * 8; i++) { dputc(' '); } + } else if (c == 10 || c == 13) { /* CR or LF */ + ty += FONT_H; + tx = 0; + redraw(); + } +} + +V handle_regular_character(C *bitmap) { + I x, y, set; + for (x = 0; x < FONT_H; x++) { + for (y = 0; y < FONT_W; y++) { + set = reverse(bitmap[x]) & 1 << y; + pixel(tx + y, ty + x, set ? 1 : 0); + } + } + tx += FONT_W; +} + +V advance_cursor_and_scroll() { + if (tx >= FW) { tx = 0; ty += FONT_H; } + if (ty > (FH - FONT_H)) { ty -= FONT_H; scroll(); } +} + +V dputc(I c) { + C *bitmap = (C *)font + (c * ((FONT_H * FONT_W) / 8)); + + handle_special_character(c); + + if (!(c == 8 || c == 127 || c == 9 || c == 10 || c == 13)) { + handle_regular_character(bitmap); + } + + advance_cursor_and_scroll(); + cursor(); +} + +I acc_pop() { + I k = acc_i; + if (acc_i > 0) { + acc_i -= 1; + if (acc_i == -1) { + acc_i = 0; + } + } + return acc[k]; +} + +V acc_reset() { + for (I x = 0; x < 32; x++) { acc[x] = 0; } + ground = on = 0; +} + +V gt_up(I n) { ty -= FONT_H; if (ty < 0) ty = 0; } +V gt_down(I n) { ty += FONT_H; if (ty > 24 * FONT_H) ty = 24 * FONT_H; } +V gt_left(I n) { tx -= FONT_W; if (tx < 0) tx = 0; } +V gt_right(I n) { tx += FONT_W; if (tx > 79 * FONT_W) ty = 79 * FONT_W; } +V gt_move_cursor() { + if (acc_i >= 1) { + I a = (acc_pop() - 1) * FONT_W; + I b = (acc_pop() - 1) * FONT_H; + ty = b; if (ty < 0) ty = 0; if (ty > FONT_H * 24) ty = FONT_H * 24; + tx = a; if (tx < 0) tx = 0; if (tx > FONT_W * 79) tx = FONT_W * 79; + acc_reset(); + return; + } + /* home */ + tx = 0; ty = 0; + acc_reset(); +} + +V gt_reset() { acc_reset(); } +V gt_next() { acc_i += 1; acc[acc_i] = 0; } +V gt_clear() { + acc_reset(); + for (I x = 0; x < (FW * FH) / 32; x++) frame[x] = 0; + tx = ty = 0; + redraw(); +} +V gt_set_attr() { acc_reset(); } + +V term_putc(I c) { + if (c == 27) { + on = -2; + return; + } + switch (on) { + case 0: + dputc(c); + return; + case -2: + if (c == '[') { + on = -1; + return; + } + on = 0; + dputc(c); + return; + } + if (c >= '0' && c <= '9') { + acc[acc_i] *= 10; + acc[acc_i] += c - 48; + if (c == '3') { + ground = 0; + } + if (c == '4') { + ground = 1; + } + } else { + switch (c) { + case 'A': gt_up(acc_pop()); break; + case 'B': gt_down(acc_pop()); break; + case 'C': gt_left(acc_pop()); break; + case 'D': gt_right(acc_pop()); break; + case 'm': gt_set_attr(); break; + case ';': gt_next(); break; + case 'H': gt_move_cursor(); break; + case 'J': gt_clear(); break; + default: on = 0; + dputc(c); + } + } +} + +V load_image() { + f = open(rom, O_RDONLY, 0666); + uli(); + if (!f) { return; }; + read(f, &m, 65536 * 4); + close(f); + ip = sp = rp = 0; +} + +V save_image() { + f = open(rom, O_WRONLY, 0666); + usi(); + write(f, &m, 65536 * 4); + close(f); +} + +V block_common() { + b = pop(); /* block buffer */ + a = pop(); /* block number */ + lseek(f, 4096 * a, SEEK_SET); +} + +V read_block() { + f = open(blocks, O_RDONLY, 0666); + urb(); + block_common(); + read(f, m + b, 4096); + close(f); +} + +V write_block() { + f = open(blocks, O_WRONLY, 0666); + uwb(); + block_common(); + write(f, m + b, 4096); + close(f); +} + +V save_ip() { rso(); rp += 1; R = ip; } +V symmetric() { if (b >= 0 && N < 0) { T += 1; N -= b; } } + +V li() { ip += 1; push(m[ip]); } +V du() { push(T); } +V dr() { pop(); } +V sw() { a = T; T = N; N = a; } +V pu() { rp += 1; R = pop(); } +V po() { push(R); rp -= 1; } +V ju() { ip = pop() - 1; } +V ca() { save_ip(); ip = pop() - 1; } +V cc() { a = pop(); if (pop()) { save_ip(); ip = a - 1; } } +V cj() { a = pop(); if (pop()) { ip = a - 1; } } +V re() { ip = R; rp -= 1; } +V eq() { N = (N == T) ? -1 : 0; sp -= 1; } +V ne() { N = (N != T) ? -1 : 0; sp -= 1; } +V lt() { N = (N < T) ? -1 : 0; sp -= 1; } +V gt() { N = (N > T) ? -1 : 0; sp -= 1; } +V fe() { mem(); T = m[T]; } +V st() { mem(); m[T] = N; sp -= 2; } +V ad() { N += T; sp -= 1; } +V su() { N -= T; sp -= 1; } +V mu() { N *= T; sp -= 1; } +V di() { dbz(); + a = T; b = N; T = b / a; N = b % a; symmetric(); } +V an() { N = T & N; sp -= 1; } +V or() { N = T | N; sp -= 1; } +V xo() { N = T ^ N; sp -= 1; } +V sl() { N = N << T; sp -= 1; } +V sr() { N = N >> T; sp -= 1; } +V cp() { l = pop(); d = pop(); s = T; T = -1; + while (l) { if (m[d] != m[s]) { T = 0; } + l -= 1; s += 1; d += 1; } } +V cy() { l = pop(); d = pop(); s = pop(); + while (l) { m[d] = m[s]; l -= 1; s += 1; d += 1; } } +V ioa() { term_putc(pop()); } +V iob() { push(wait_key()); term_putc(T); } +V ioc() { read_block(); } +V iod() { write_block(); } +V ioe() { save_image(); } +V iof() { load_image(); ip = -1; } +V iog() { ip = 65536; } +V ioh() { push(sp); push(rp); } +V iox() { I c = pop(); I y = pop(); I x = pop(); + pixel(x, y, c); } +V ioy() { I y = pop(); I x = pop(); push(get_pixel(x, y)); } +V ioz() { I x, y, wx, wy, mask; Window w; + XQueryPointer(disp, win, &w, &w, &x, &y, &wx, &wy, &mask); + push(x); push(y); if (mask & Button1Mask) push(-1); else push(0); } +V io() { + switch (pop()) { + case 0: ioa(); break; case 1: iob(); break; + case 2: ioc(); break; case 3: iod(); break; + case 4: ioe(); break; case 5: iof(); break; + case 6: iog(); break; case 7: ioh(); break; + case 33: iox(); break; case 34: ioy(); break; + case 35: ioz(); break; + default: break; + } +} + +V process(I o) { + switch (o) { + case 0: break; case 1: li(); break; + case 2: du(); break; case 3: dr(); break; + case 4: sw(); break; case 5: pu(); break; + case 6: po(); break; case 7: ju(); break; + case 8: ca(); break; case 9: cc(); break; + case 10: cj(); break; case 11: re(); break; + case 12: eq(); break; case 13: ne(); break; + case 14: lt(); break; case 15: gt(); break; + case 16: fe(); break; case 17: st(); break; + case 18: ad(); break; case 19: su(); break; + case 20: mu(); break; case 21: di(); break; + case 22: an(); break; case 23: or(); break; + case 24: xo(); break; case 25: sl(); break; + case 26: sr(); break; case 27: cp(); break; + case 28: cy(); break; case 29: io(); break; + default: break; + } +} + +#define VALID(n) (ok == 0) && ((opcode >> n) & 0xFF) + +V execute() { + I opcode; + while (ip < 65536) { + opcode = m[ip]; + ok = 0; + if (VALID(0)) process(opcode & 0xFF); + if (VALID(8)) process((opcode >> 8) & 0xFF); + if (VALID(16)) process((opcode >> 16) & 0xFF); + if (VALID(24)) process((opcode >> 24) & 0xFF); + ip += 1; + } +} + +I main(I argc, C **argv) { + blocks = (argc > 1) ? argv[1] : BLOCKS; + rom = (argc > 2) ? argv[2] : ROM; + ok = 0; + +/* +#ifdef __OpenBSD__ + pledge("stdio rpath wpath unix video", NULL); +#endif +*/ + + load_image(); + + load_font(); + + disp = XOpenDisplay(NULL); + win = XCreateSimpleWindow(disp, RootWindow(disp, 0), + 0, 0, FW, FH, 0, 0x0, 0x0); + XSelectInput(disp, win, ExposureMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask); + XStoreName(disp, win, "x/ilo"); + gc = DefaultGC(disp, DefaultScreen(disp)); + XMapWindow(disp, win); + XFlush(disp); + XMoveWindow(disp, win, (DisplayWidth(disp, DefaultScreen(disp)) - FW) / 2, + (DisplayHeight(disp, DefaultScreen(disp)) - FH) / 2); + + execute(); + + XUnmapWindow(disp, win); + XDestroyWindow(disp, win); + XCloseDisplay(disp); + + return 0; +} diff --git a/source/x11-mult-ilo.c b/source/x11-mult-ilo.c new file mode 100644 index 0000000..e6c42ce --- /dev/null +++ b/source/x11-mult-ilo.c @@ -0,0 +1,522 @@ +/*************************************************************** + crc's _ _ ___ _ __ + _ __ ___ _ _| | |_ / (_) | ___ / /_ __ + | '_ ` _ \| | | | | __| / /| | |/ _ \ / /\ \/ / + | | | | | | |_| | | |_ / / | | | (_) / / > < + |_| |_| |_|\__,_|_|\__/_/ |_|_|\___/_/ /_/\_\ + (c) charles childers + + This is a special implementation of my ilo computer, with many + copies of ilo running under a single process. Under this you + can quickly switch between ilo instances. + + - `bye` will act like `restart` on the current computer + - ctrl+c restarts the current computer + - ctrl+n switches to the next ilo + - ctrl+p switches to the previous ilo + - ctrl+a shuts down mult/ilo + - switching can only be done when the system is waiting for + input + + **************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#define BLOCKS "ilo.blocks" +#define ROM "ilo.rom" +#define FONT "ilo.fnt" +#define FG 0xFFFFFF +#define BG 0x000000 +/* Orange = 0xFFAA00, Red = 0xFF0000, Cyan = 0x00FFFF */ +#define CURSOR 0xFFAA00 +#define FW 640 +#define FH 384 +#define FONT_H 16 +#define FONT_W 8 + +#define V void +#define I int +#define C char + +#define ILOS 3 + +typedef struct ilo ilo; + +struct ilo { + I ip, /* instruction pointer */ + sp, /* data stack pointer */ + rp, /* address stack pointer */ + ds[33], /* data stack */ + as[257], /* address stack */ + m[65536]; /* memory */ + C *blocks, /* name of block file (ilo.blocks) */ + *rom; /* name of image (ilo.rom) */ + I a, b, f, s, d, l, ok; + C i[1]; +}; + +#define TERM_W (FW / FONT_W) +#define TERM_H (FH / FONT_H) + +I frame[(FW * FH)/32]; /* frame buffer for display */ +I font[4096]; /* font bitmap */ +I tx, ty; /* text cursor location */ + +/* variables for Arland's DEC subset */ +I acc[32], acc_i = 0, ground = 0, on = 0; + +/* variables for X11 stuff */ +Display *disp; +Window win; +GC gc; +XEvent event; +C text[255]; + +V dputc(I); +V redraw(); + +struct ilo systems[ILOS]; + +I cur; + +#define DS v->ds +#define AS v->as +#define SP v->sp +#define RP v->rp +#define IP v->ip +#define M v->m +#define A v->a +#define B v->b +#define S v->s +#define D v->d +#define L v->l +#define T DS[SP] /* Top of Data Stack */ +#define N DS[SP-1] /* Next on Data Stack */ +#define R AS[RP] /* Top of Address Stack */ +#define F v->f + +V iof(ilo *); + +V p(char *s) { while(*s) dputc(*s++); } +V e(ilo *v, char *s) { p("E:"); p(s); p("\n"); v->ok = 1; iof(v); } +V dso(ilo *v) { if ((SP + 1) > 32) { e(v, "DSO"); } } +V dsu(ilo *v) { if ((SP - 1) < 0) { e(v, "DSU"); } } +V rso(ilo *v) { if ((RP + 1) > 256) { e(v, "RSO"); } } +V rsu(ilo *v) { if ((RP - 1) < 0) { e(v, "RSU"); } } +V dbz(ilo *v) { if (T == 0) { e(v, "DBZ"); } } +V mem(ilo *v) { if (T < 0 || T > 65535) { e(v, "MEM"); } } +V uli(ilo *v) { if (F == -1) { e(v, "ULI"); } } +V ulf(ilo *v) { if (F == -1) { e(v, "ULF"); } } +V usi(ilo *v) { if (F == -1) { e(v, "URI"); } } +V urb(ilo *v) { if (F == -1) { e(v, "URB"); } } +V uwb(ilo *v) { if (F == -1) { e(v, "UWB"); } } + +V push(ilo *v, I n) { dso(v); DS[SP + 1] = n; SP += 1; } +I pop(ilo *v) { dsu(v); SP -= 1; return DS[SP + 1]; } + +V cursor() { + XSetForeground(disp, gc, CURSOR); + XFillRectangle(disp, win, gc, tx, ty, FONT_W, FONT_H); + XFlush(disp); +} + +I wait_key() { + while (1) { + XNextEvent(disp, &event); + if (event.type == KeyPress) { + KeySym key = XLookupKeysym(&event.xkey, 0); + XLookupString(&event.xkey, text, 255, &key, 0); + if (text[0] == 13) text[0] = 10; + if (text[0] != 0) return (I) text[0]; + } + if (event.type == Expose) { redraw(); cursor(); } + } +} + +V load_font(ilo *v) { + F = open(FONT, O_RDONLY, 0666); + ulf(v); + if (!F) { return; }; + read(F, &font, 4096); + close(F); +} + +V pixel(I x, I y, I c) { + I index = y * FW + x; + if (c == 0) { + frame[(index / 32)] &= ~(1 << (31 - index % 32)); + XSetForeground(disp, gc, BG); + } else { + frame[(index / 32)] |= 1 << (31 - index % 32); + XSetForeground(disp, gc, FG); + } + XDrawPoint(disp, win, gc, x, y); +} + +I get_pixel(I x, I y) { + I index = y * FW + x; + I bit_pos = 31 - index % 32; + I mask = 1 << bit_pos; + return (frame[(index / 32)] & mask) >> bit_pos; +} + +V redraw() { + for (I x = 0; x < FW; x++) { + for (I y = 0; y < FH; y++) { + XSetForeground(disp, gc, get_pixel(x, y) ? FG : BG); + XDrawPoint(disp, win, gc, x, y); + } + } +} + +V scroll() { + I memsize = (FH * FW) / 32; + I last_row = (FW * FONT_H) / 32; + for (I i = 0; i < memsize - last_row; i++) { + frame[i] = frame[i + last_row]; + } + for (I i = memsize - last_row; i < memsize; i++) { + frame[i] = 0; + } + redraw(); +} + +unsigned C reverse(unsigned C b) { + b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; + b = (b & 0xCC) >> 2 | (b & 0x33) << 2; + b = (b & 0xAA) >> 1 | (b & 0x55) << 1; + return b; +} + +V handle_special_character(I c) { + if (c == 8 || c == 127) { /* BACKSPACE/DELETE */ + if (tx - FONT_W >= 0) { + tx -= FONT_W ; + dputc(' '); + tx -= FONT_W; + } + } else if (c == 9) { /* TAB */ + I ts = tx / FONT_W; + for (I i = ts; i < ((ts + 7) / 8) * 8; i++) { dputc(' '); } + } else if (c == 10 || c == 13) { /* CR or LF */ + ty += FONT_H; + tx = 0; + } +} + +V handle_regular_character(C *bitmap) { + I x, y, set; + for (x = 0; x < FONT_H; x++) { + for (y = 0; y < FONT_W; y++) { + set = reverse(bitmap[x]) & 1 << y; + pixel(tx + y, ty + x, set ? 1 : 0); + } + } + tx += FONT_W; +} + +V advance_cursor_and_scroll() { + if (tx >= FW) { tx = 0; ty += FONT_H; } + if (ty > (FH - FONT_H)) { ty -= FONT_H; scroll(); } +} + +V dputc(I c) { + C *bitmap = (C *)font + (c * ((FONT_H * FONT_W) / 8)); + + handle_special_character(c); + + if (!(c == 8 || c == 127 || c == 9 || c == 10 || c == 13)) { + handle_regular_character(bitmap); + } + + advance_cursor_and_scroll(); +} + +I acc_pop() { + I k = acc_i; + if (acc_i > 0) { + acc_i -= 1; + if (acc_i == -1) { + acc_i = 0; + } + } + return acc[k]; +} + +V acc_reset() { + for (I x = 0; x < 32; x++) { acc[x] = 0; } + ground = on = 0; +} + +V gt_up(I n) { ty -= FONT_H; if (ty < 0) ty = 0; } +V gt_down(I n) { ty += FONT_H; if (ty > 24 * FONT_H) ty = 24 * FONT_H; } +V gt_left(I n) { tx -= FONT_W; if (tx < 0) tx = 0; } +V gt_right(I n) { tx += FONT_W; if (tx > 79 * FONT_W) ty = 79 * FONT_W; } +V gt_move_cursor() { + if (acc_i >= 1) { + I a = (acc_pop() - 1) * FONT_W; + I b = (acc_pop() - 1) * FONT_H; + ty = b; if (ty < 0) ty = 0; if (ty > FONT_H * 24) ty = FONT_H * 24; + tx = a; if (tx < 0) tx = 0; if (tx > FONT_W * 79) tx = FONT_W * 79; + acc_reset(); + return; + } + /* home */ + tx = 0; ty = 0; + acc_reset(); +} + +V gt_reset() { acc_reset(); } +V gt_next() { acc_i += 1; acc[acc_i] = 0; } +V gt_clear() { + acc_reset(); + for (I x = 0; x < (FW * FH) / 32; x++) frame[x] = 0; + tx = ty = 0; + redraw(); +} +V gt_set_attr() { acc_reset(); } + +V term_putc(I c) { + if (c == 27) { + on = -2; + return; + } + switch (on) { + case 0: + dputc(c); + return; + case -2: + if (c == '[') { + on = -1; + return; + } + on = 0; + dputc(c); + return; + } + if (c >= '0' && c <= '9') { + acc[acc_i] *= 10; + acc[acc_i] += c - 48; + if (c == '3') { + ground = 0; + } + if (c == '4') { + ground = 1; + } + } else { + switch (c) { + case 'A': gt_up(acc_pop()); break; + case 'B': gt_down(acc_pop()); break; + case 'C': gt_left(acc_pop()); break; + case 'D': gt_right(acc_pop()); break; + case 'm': gt_set_attr(); break; + case ';': gt_next(); break; + case 'H': gt_move_cursor(); break; + case 'J': gt_clear(); break; + default: on = 0; + dputc(c); + } + } +} + +V load_image(ilo *v) { + F = open(v->rom, O_RDONLY, 0666); + if (!F) { return; }; + read(F, &M, 65536 * 4); + close(F); + IP = SP = RP = 0; +} + +V save_image(ilo *v) { + v->f = open(v->rom, O_WRONLY, 0666); + write(v->f, &M, 65536 * 4); + close(v->f); +} + +V block_common(ilo *v) { + B = pop(v); /* block buffer */ + A = pop(v); /* block number */ + lseek(v->f, 4096 * A, SEEK_SET); +} + +V read_block(ilo *v) { + v->f = open(v->blocks, O_RDONLY, 0666); + block_common(v); + read(v->f, M + B, 4096); + close(v->f); +} + +V write_block(ilo *v) { + v->f = open(v->blocks, O_WRONLY, 0666); + block_common(v); + write(v->f, M + B, 4096); + close(v->f); +} + +V save_ip(ilo *v) { RP += 1; R = IP; } +V symmetric(ilo *v) { + if (B >= 0 && N < 0) { T += 1; N -= B; } } + +V li(ilo *v) { IP += 1; push(v, M[IP]); } +V du(ilo *v) { push(v, T); } +V dr(ilo *v) { DS[SP] = 0; SP -= 1; } +V sw(ilo *v) { A = T; T = N; N = A; } +V pu(ilo *v) { RP += 1; R = pop(v); } +V po(ilo *v) { push(v, R); RP -= 1; } +V ju(ilo *v) { IP = pop(v) - 1; } +V ca(ilo *v) { save_ip(v); IP = pop(v) - 1; } +V cc(ilo *v) { A = pop(v); + if (pop(v)) { save_ip(v); + IP = A - 1; } } +V cj(ilo *v) { A = pop(v); + if (pop(v)) { IP = A - 1; } } +V re(ilo *v) { IP = R; RP -= 1; } +V eq(ilo *v) { N = (N == T) ? -1 : 0; SP -= 1; } +V ne(ilo *v) { N = (N != T) ? -1 : 0; SP -= 1; } +V lt(ilo *v) { N = (N < T) ? -1 : 0; SP -= 1; } +V gt(ilo *v) { N = (N > T) ? -1 : 0; SP -= 1; } +V fe(ilo *v) { T = M[T]; } +V st(ilo *v) { M[T] = N; SP -= 2; } +V ad(ilo *v) { N += T; SP -= 1; } +V su(ilo *v) { N -= T; SP -= 1; } +V mu(ilo *v) { N *= T; SP -= 1; } +V di(ilo *v) { A = T; B = N; + if (A == 0) { v->ok = 1; iof(v); return; } + T = B / A; N = B % A; + symmetric(v); } +V an(ilo *v) { N = T & N; SP -= 1; } +V or(ilo *v) { N = T | N; SP -= 1; } +V xo(ilo *v) { N = T ^ N; SP -= 1; } +V sl(ilo *v) { N = N << T; SP -= 1; } +V sr(ilo *v) { N = N >> T; SP -= 1; } +V cp(ilo *v) { L = pop(v); D = pop(v); S = T; T = -1; + while (L) { + if (M[D] != M[S]) { T = 0; } + L -= 1; S += 1; D += 1; } } +V cy(ilo *v) { L = pop(v); D = pop(v); S = pop(v); + while (L) { + M[D] = M[S]; + L -= 1; S += 1; D += 1; } } + +V pre(V) { cur -= 1; if (cur < 0) cur = ILOS - 1; } +V nxt(V) { cur += 1; if (cur > (ILOS - 1)) cur = 0; } + +V msgs(V) { printf("\n*** SWITCH TO %d ***\n", cur); } +V msgx(V) { printf("\n*** SHUTDOWN REQUESTED ***\n"); + exit(1); } +V msgr(V) { printf("\n*** RESTART %d ***\n", cur); } + +V term_putc(I c); + +V ioa(ilo *v) { term_putc(pop(v)); } +V iob(ilo *v) { redraw(); cursor(); + v->i[0] = wait_key(); push(v, v->i[0]); term_putc(T); + if (v->i[0] == 14) { T = 32; nxt(); msgs(); } + if (v->i[0] == 16) { T = 32; pre(); msgs(); } + if (v->i[0] == 3) { T = 32; msgr(); iof(v); + v->ok = 1; } + if (v->i[0] == 1) { T = 32; msgx(); } } +V ioc(ilo *v) { read_block(v); } +V iod(ilo *v) { write_block(v); } +V ioe(ilo *v) { save_image(v); } +V iof(ilo *v) { load_image(v); IP = -1; } +V iog(ilo *v) { iof(v); } +V ioh(ilo *v) { push(v, SP); push(v, RP); } +V iox(ilo *v) { I c = pop(v); I y = pop(v); I x = pop(v); + pixel(x, y, c); } +V ioy(ilo *v) { I y = pop(v); I x = pop(v); push(v, get_pixel(x, y)); } +V ioz(ilo *v) { I x, y, wx, wy, mask; Window w; + XQueryPointer(disp, win, &w, &w, &x, &y, &wx, &wy, &mask); + push(v, x); push(v, y); if (mask & Button1Mask) push(v, -1); else push(v, 0); } + +V io(ilo *v) { + switch (pop(v)) { + case 0: ioa(v); break; case 1: iob(v); break; + case 2: ioc(v); break; case 3: iod(v); break; + case 4: ioe(v); break; case 5: iof(v); break; + case 6: iog(v); break; case 7: ioh(v); break; + case 33: iox(v); break; case 34: ioy(v); break; + case 35: ioz(v); break; + default: break; + } +} + +V process(ilo *v, I o) { + switch (o) { + case 0: break; case 1: li(v); break; + case 2: du(v); break; case 3: dr(v); break; + case 4: sw(v); break; case 5: pu(v); break; + case 6: po(v); break; case 7: ju(v); break; + case 8: ca(v); break; case 9: cc(v); break; + case 10: cj(v); break; case 11: re(v); break; + case 12: eq(v); break; case 13: ne(v); break; + case 14: lt(v); break; case 15: gt(v); break; + case 16: fe(v); break; case 17: st(v); break; + case 18: ad(v); break; case 19: su(v); break; + case 20: mu(v); break; case 21: di(v); break; + case 22: an(v); break; case 23: or(v); break; + case 24: xo(v); break; case 25: sl(v); break; + case 26: sr(v); break; case 27: cp(v); break; + case 28: cy(v); break; case 29: io(v); break; + default: break; + } +} + +#define VALID(n) (v->ok == 0) && ((opcode >> n) & 0xFF) + +V execute() { + I opcode; + ilo *v = &systems[cur]; + while (IP < 65536) { + opcode = M[IP]; + v->ok = 0; + if (VALID(0)) process(v, opcode & 0xFF); + if (VALID(8)) process(v, (opcode >> 8) & 0xFF); + if (VALID(16)) process(v, (opcode >> 16) & 0xFF); + if (VALID(24)) process(v, (opcode >> 24) & 0xFF); + IP += 1; + v = &systems[cur]; + } +} + +V load_font(ilo *); + +I main(I argc, C **argv) { + ilo *v; + I i; + + cur = 0; + for (i = 0; i < ILOS; i++) { + v = &systems[i]; + v->blocks = (argc > 1) ? argv[1] : BLOCKS; + v->rom = (argc > 2) ? argv[2] : ROM; + load_image(v); + } + + load_font(&systems[0]); + + disp = XOpenDisplay(NULL); + win = XCreateSimpleWindow(disp, RootWindow(disp, 0), + 0, 0, FW, FH, 0, 0x0, 0x0); + XSelectInput(disp, win, ExposureMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask); + XStoreName(disp, win, "x/ilo"); + gc = DefaultGC(disp, DefaultScreen(disp)); + XMapWindow(disp, win); + XFlush(disp); + XMoveWindow(disp, win, (DisplayWidth(disp, DefaultScreen(disp)) - FW) / 2, + (DisplayHeight(disp, DefaultScreen(disp)) - FH) / 2); + + execute(); + + XUnmapWindow(disp, win); + XDestroyWindow(disp, win); + XCloseDisplay(disp); + + return 0; +}