OpenCores
URL https://opencores.org/ocsvn/lxp32/lxp32/trunk

Subversion Repositories lxp32

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /lxp32
    from Rev 9 to Rev 10
    Reverse comparison

Rev 9 → Rev 10

/tags/1.2/.gitattributes
0,0 → 1,5
# Convert line endings for text files on Windows
* text=auto
 
# Prevent the GitHub parser from ignoring the "tools" directory contents
/tools/* linguist-vendored=false
/tags/1.2/LICENSE.md
0,0 → 1,7
Copyright (c) 2016-2019 by Alex I. Kuznetsov
 
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/tags/1.2/README.md
0,0 → 1,18
# lxp32-cpu
 
LXP32 is a small and FPGA friendly 32-bit CPU IP core based on a simple, original instruction set. Its key features include:
 
* portability (described in behavioral VHDL, not tied to any particular vendor);
* 3-stage hazard-free pipeline;
* 256 registers implemented as a RAM block;
* only 30 distinct opcodes;
* separate instruction and data buses, optional instruction cache;
* WISHBONE compatibility;
* 8 interrupts with hardwired priorities;
* optional divider.
 
The LXP32 processor was successfully used in commercial projects, is [well documented](https://github.com/lxp32/lxp32-cpu/raw/develop/doc/lxp32-trm.pdf) and comes with a verification environment.
 
LXP32 lacks some features of more advanced processors, such as nested interrupt handling, debugging support, floating-point and memory management units. LXP32 ISA (Instruction Set Architecture) does not currently have a C compiler, only assembly based workflow is supported.
 
Project website: [https://lxp32.github.io/](https://lxp32.github.io/)
/tags/1.2/doc/lxp32-trm.pdf Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
tags/1.2/doc/lxp32-trm.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2/doc/src/logo/lxp32-logo.svg =================================================================== --- tags/1.2/doc/src/logo/lxp32-logo.svg (nonexistent) +++ tags/1.2/doc/src/logo/lxp32-logo.svg (revision 10) @@ -0,0 +1,104 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + Index: tags/1.2/doc/src/trm/.gitignore =================================================================== --- tags/1.2/doc/src/trm/.gitignore (nonexistent) +++ tags/1.2/doc/src/trm/.gitignore (revision 10) @@ -0,0 +1,6 @@ +/*.aux +/*.log +/*.gz +/*.toc +/*.pdf +/*.out Index: tags/1.2/doc/src/trm/frontmatter.tex =================================================================== --- tags/1.2/doc/src/trm/frontmatter.tex (nonexistent) +++ tags/1.2/doc/src/trm/frontmatter.tex (revision 10) @@ -0,0 +1,68 @@ +\frontmatter + +% Title page + +\thispagestyle{empty} +\pdfbookmark{Title}{bmk:title} +\calccentering{\unitlength} +\begin{adjustwidth*}{\unitlength}{-\unitlength} + \vspace*{\fill} + \begin{center} + \DoubleSpacing + \includegraphics[scale=0.2]{images/lxp32-logo.pdf}\par + \vspace{\onelineskip} + \huge \lxp{}\par + \Large a lightweight open source 32-bit CPU core\par + \LARGE \textbf{Technical Reference Manual}\par + \vspace{1.2\onelineskip} + \large Version 1.2\par + \vspace*{4\onelineskip} + \end{center} + \vspace*{\fill} +\end{adjustwidth*} + +\clearpage + +% Copyright page + +\thispagestyle{empty} + +{ +\small +\setlength{\parindent}{0pt} +\nonzeroparskip + +\vspace*{\fill} + +Copyright \textcopyright{} 2016--2019 by Alex I. Kuznetsov. + +The entire \lxp{} IP core package, including the synthesizable RTL description, verification environment, documentation and software tools, is distributed under the terms of the MIT license reproduced below: + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ``Software''), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +\vspace{4\baselineskip} + +Mentor Graphics and ModelSim are trademarks of Mentor Graphics Corporation. + +Microsemi and IGLOO are trademarks of Microsemi Corporation. + +Microsoft, Windows and Visual Studio are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries. + +Verilog is a registered trademark of Cadence Design Systems, Inc. + +Xilinx, Artix and Vivado are trademarks of Xilinx in the United States and other countries. + +All other trademarks are the property of their respective owners. +} + +\cleardoublepage + +% Table of contents + +\pdfbookmark{\contentsname}{bmk:contents} + +\tableofcontents* Index: tags/1.2/doc/src/trm/images/blockdiagram.svg =================================================================== --- tags/1.2/doc/src/trm/images/blockdiagram.svg (nonexistent) +++ tags/1.2/doc/src/trm/images/blockdiagram.svg (revision 10) @@ -0,0 +1,782 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + Fetch + + Decode + + Execute + + Scratchpad + + + + + read + write + + Interruptmultiplexer + + + + Instructioncache(LXP32C) + + + + + irq_i + clk_i + rst_i + + + Instruction busLow LatencyInterface(LXP32U) + Instruction busWISHBONE(LXP32C) + + Data busWISHBONE + + + enter + return + + + + jump + + + + + Index: tags/1.2/doc/src/trm/images/dbustiming.svg =================================================================== --- tags/1.2/doc/src/trm/images/dbustiming.svg (nonexistent) +++ tags/1.2/doc/src/trm/images/dbustiming.svg (revision 10) @@ -0,0 +1,1003 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + clk_i + dbus_cyc_o + dbus_stb_o + dbus_we_o + dbus_sel_o + dbus_ack_i + dbus_adr_o + dbus_dat_o + dbus_dat_i + + + + + + + + + + + + + + + + + + + + + + + SEL + + ADDR + + WDATA + + + + + + + + + + + + + + + + + + SEL + + ADDR + + RDATA + + + + + + + + + + + SINGLE WRITE + SINGLE READ + + Index: tags/1.2/doc/src/trm/images/ibustiming.svg =================================================================== --- tags/1.2/doc/src/trm/images/ibustiming.svg (nonexistent) +++ tags/1.2/doc/src/trm/images/ibustiming.svg (revision 10) @@ -0,0 +1,712 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + clk_i + + + + + + + + + + + + + + + + + + + + + + ibus_cyc_o + ibus_stb_o + ibus_cti_o + ibus_bte_o + ibus_ack_i + ibus_adr_o + ibus_dat_i + + + + + + 010 + + 111 + + 00 + + ADDR0 + + ADDR1 + + ADDRn-2 + + ADDRn-1 + + DATA1 + + DATAn-2 + + DATAn-1 + + DATA0 + + + + 010 + + 00 + + + + + Index: tags/1.2/doc/src/trm/images/instructionformat.svg =================================================================== --- tags/1.2/doc/src/trm/images/instructionformat.svg (nonexistent) +++ tags/1.2/doc/src/trm/images/instructionformat.svg (revision 10) @@ -0,0 +1,310 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + OPCODE + + + + + + + T1 + T2 + DST + RD1 + RD2 + 31 + 26 + 25 + 24 + 23 + 16 + 15 + 8 + 7 + 0 + + Index: tags/1.2/doc/src/trm/images/llitiming.svg =================================================================== --- tags/1.2/doc/src/trm/images/llitiming.svg (nonexistent) +++ tags/1.2/doc/src/trm/images/llitiming.svg (revision 10) @@ -0,0 +1,334 @@ + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + ADDR0 + + + + + + + ADDR1 + + ADDR2 + + DATA0 + + DATA2 + clk_i + lli_re_o + lli_adr_o + lli_dat_i + lli_busy_i + + + Slave wait state + + DATA1 + + Index: tags/1.2/doc/src/trm/images/resetsync.svg =================================================================== --- tags/1.2/doc/src/trm/images/resetsync.svg (nonexistent) +++ tags/1.2/doc/src/trm/images/resetsync.svg (revision 10) @@ -0,0 +1,289 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + CLK + + + + D + Q + + + D + Q + RST + PRE + PRE + + + + + + + Asynchronous reset (active high) + C + C + + Index: tags/1.2/doc/src/trm/images/symbols.svg =================================================================== --- tags/1.2/doc/src/trm/images/symbols.svg (nonexistent) +++ tags/1.2/doc/src/trm/images/symbols.svg (revision 10) @@ -0,0 +1,662 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + clk_i + rst_i + lli_dat_i[31:0] + lli_busy_i + dbus_ack_i + dbus_dat_i[31:0] + irq_i[7:0] + lli_re_o + lli_adr_o[29:0] + dbus_cyc_o + dbus_stb_o + dbus_we_o + dbus_adr_o[31:2] + dbus_sel_o[3:0] + dbus_dat_o[31:0] + lxp32u_top + + + + + + + + + + + + + + + + + + + + clk_i + rst_i + ibus_dat_i[31:0] + ibus_ack_i + dbus_ack_i + dbus_dat_i[31:0] + irq_i[7:0] + ibus_cyc_o + ibus_adr_o[29:0] + dbus_cyc_o + dbus_stb_o + dbus_we_o + dbus_adr_o[31:2] + dbus_sel_o[3:0] + dbus_dat_o[31:0] + lxp32c_top + + ibus_stb_o + + ibus_cti_o[2:0] + + ibus_bte_o[1:0] + + Index: tags/1.2/doc/src/trm/images/ibustiming.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2/doc/src/trm/images/ibustiming.pdf =================================================================== --- tags/1.2/doc/src/trm/images/ibustiming.pdf (nonexistent) +++ tags/1.2/doc/src/trm/images/ibustiming.pdf (revision 10)
tags/1.2/doc/src/trm/images/ibustiming.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2/doc/src/trm/images/blockdiagram.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2/doc/src/trm/images/blockdiagram.pdf =================================================================== --- tags/1.2/doc/src/trm/images/blockdiagram.pdf (nonexistent) +++ tags/1.2/doc/src/trm/images/blockdiagram.pdf (revision 10)
tags/1.2/doc/src/trm/images/blockdiagram.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2/doc/src/trm/images/resetsync.pdf =================================================================== --- tags/1.2/doc/src/trm/images/resetsync.pdf (nonexistent) +++ tags/1.2/doc/src/trm/images/resetsync.pdf (revision 10) @@ -0,0 +1,220 @@ +%PDF-1.5 +%µí®û +3 0 obj +<< /Length 4 0 R + /Filter /FlateDecode +>> +stream +xœ•½Í®&½Î6¯«Ø7íÒ¿tx`gxì¤ý"èØøö­µIiw7¾“/ÎÙM–•$RüÅúïÏûÿþËüøÿ×ûñßþ¿çýœÿscÿ÷ý¿ÿ÷ù?ÿëÇûù~üßOýøOÿý#±ñÿ†?)÷Ï··žçÇׯ'Íú™[ýhåsÌôñë#ïÇcGüüø?>þó“w¯ÿF'c¿»²>û»>jþlù£õϾÒÇÿøØÁûowRù,sœQ¤š>Ä¿ñ{{YJïg¿Ïã³µ˜Ÿ™ù3å„^°†‰ÿþÇûhó3í©¤öÙæÚý9\?ç;?Ú`§J£ùL +úúhí3ÀPV[þÒ õûpÿ,£ú/ÇçûŽèVÐóoµÇ6"ûå·ñ~}üóü>ƒOZŸimÌü\­cÖç[ àYÿTüÿ¨ +[Ž·ïÞö? +ŸõÖ>6Ë|¾cÜ«¿‡3ßåÐà:Êõ4í—šœælì-Ÿ +¶Î¦+ÎíQÍH@IAûœ#n›Y7ÔŸ²»=ÅQŸü~æœÕ¸Ö¸M>kåôù¦uA--µ%œ?ß2ùËV€•Ð^…ýïY‡šŽ½ ¹ð5ZûφZæàS#4ZA[e=@¬ ¨×ô‘7KTB ý`ã­XÞ]l¸ô¨í)o¨ææ«ûHR€]ýñ&ÌbÇõÍF5öSÔt¬AXô]SÛ¯¡73dþÒÖl?î +ãíµbw€ö…ê¤n)œYe`Ý9ƒ^Æõ¸¦ÉŸNqÀ¦ ñÒžýäÓžÉobOujÔ­aíüebKŽ`cv@X±-hÖPËTHÄònFïl¯Ú`ôv0•¿{÷BeïtsÍë$̇­0šM®½nFÐLv{-Ùv€ÕÄ)r‰k#As¶YN—½>•?ÎXÚ¡m¾ô–A2D²ä·ÄÓ¹Wö!T“oÒEzŠÜàŸýšÒ´©&¡5c«ïLñð»0øñìe¿é¦L lø§Ãà¦Íž„ÿµ_ÀêmÙã~ï~¿oï¼½{7)ÐäºÚ#5ð§çõÔøÖûŸhÆã½ë6Ø Á6Ý hrZïe_ýî­k{lz—~?ņ¶žOvXÔáïœÑ +lÈç þùcº?ŽÿךՔÔ/W +¡´~S|¦Åh ü»Ô%”Uþ÷v3 +ÅðظÊî¥oÅ°Wc[àáß4ê¨T¿£m¸Ûn°o غyWЖòš[&ô…¼Éžn™Ê.ÿ¨4¨AllWßVÕæe}Í ‡mç&Æy¼¶p¨sËô"ê<ƒýo9²‡$!·¾¤Ì†[ÑDö–â„:f75HpÎŽ¬3@½·‡$ú^Ú¹Õú†êæË +QS ìø 3ŸZÂ-ßzAeà¹àw ÿåæß-÷¼ÛôI• +sz÷üÙm®Èü`¸y,ͦÆ5ÛÖåu˜è^¥¾5ñ̾ ijÍ0ÿ­ýp¡Ú¹àƒD‹±®§›¨éµh“OtkŽÆZ¤;66¡e¬³…¢Á ÏL*çåO[‚nv²§¢OÓkH‰ð‡8·g2t£1xÈ:8F*€ƒÍaòsj+f´n_›@{«Ã`îb'[´]ÚÞZ˜P†ÀZè50ƒle +Û'„ADz7+àjt-T^$û«óMòC…Œ1K´Р8½x:ôVþ{bu6гz]owP=çÕ¶SœzÛ-Ð:Ÿ&tØ©û6”«±lì·LmÖm›„- ÞÔ˜Bâ¥ßÐÀRîRÁà0&6C³1ß´Õ h¿¡ýBl9¬Y@Åa`ßzИ¡_žè¸¸Ä3‰Q´Ìƒ¶Ä-Æ-?Âú­ä½ÙQNäØXˆIIó6­Ù(S¬ÌÝX‚)¿só2øv ¶zÈ{µ·œÇ0Q_À€¢‚d´uÉ»(Å»ü/"áwî)„€ ¯æ]¤ƒjöç“û˺8j·¡Y0@Àžw§-Õ=”wºŸp79nîÇAöU¨ÀðÕ¶– |¬ýåÌœo»ÁåÍÙzÈ\ôÇ[LW•ŒÕI7!ü7 ŠL'80M/Pëlss.Õé÷WVØ.Ó½8€ý„`®&Z‹­Åú<~œ 'ìÆó~\üTŽ\ôlž_<Ü“”RyÜ—ã¸W;¾ç%cÎ@ÙT'¶(áÍqÕÊ#wNKšÝ_ãúPô¡vž»·éùJ WE¯6¦ôpòÈy¸[Gî™ùøu`/så€xÈnor׎Ü9úqíȼ-|=ò¶LŠXcuzwv*8(÷cþr†2hÒa~s}!·ÜÇã„szî­,÷òÈßm?ó7ÁÆN;È<=.G™!ÆÔ>Ét \« +X™³çëÞ^ äî=?õ‹TC°Wwøì…ÇãӀ¯#8wG\Í[‹öœïyÞ“=´Òñæ¸|Cœ + û¸†ë¼Û+fÏoiîÿ‘Qg{ŽH^–Ê-ÆÚæìò8»½Šé¼Gûß½@@#s­9¿ær›Áζ”–õXsCÀŒ_Ó<½—¤&|ä rl^Èäž• +š>SÊÑ[úÝB¬Ì¬—KDM?Ú¦6¶3¦½6Á_÷Åv gb4ò¸…ñ¾ÕÝÂù*²#·pCCn¹…ÑËåN˜=áöm¨ÈÓ2¾š/ÝŸoeÆ“¹…¤/tÜÂ! éná€HáŽéc3‰ˆ°Y9Žá D|äL+]~!üøQÂ/„§.™ËW]¾ …ÁÐÿs7«Ä=çý—_èˆp Ø¢gˆŸß®¡bÇ3<Ã1dࠅ߇@‡,pÓ‘ÃŽu¢Át™«Î§<³p S<~á˜T©ò ò¸éø…C'îŽ%?S~!è6úånÄJ|LË +T‡sâ~߆±Ž_.Ú›äzËÆýÂár ŸÍÈ_ +«Þò Gça{†£K„gˆØÊåb©WÇAÝy9†à«œî竧p ‡bÇ1Ü8ùîŽ%aŽ!g”Ë1äò„_ˆ=³)õ¸_h{(Ì,ÞœábÕæ~áÌ/âø…è­äð 1–Ü/¿pX ÇÃ1#ÎÛ²/Ìí‚íêy®utÅ|v€ÙçCâÇÃAErÃÑ. +ßqBÅ&iGŒî¡@ý˜:1CÅpcèažáwŽ¡4dàñæ!‡éSsæ"þÖêå">žºù…&—Â/Üs¥ÔÌ/D³‡[(Ùá^!Ø6ïÇÅw“ɦ•qþ ¯Û7_ÏåH•)* +iæŠmX÷ +!†5z…¯ð`è:C›WP:ϼ±Bç-‰uóåBxÔty…CncøRsô +Áƒrú|á)¬ŽWQöÎðú|uÂ+Äb–ë9å®»… Sï·[BËÔS˜WøeþÆD?žœ3#°Õ&ÏF7bl‡;7 +‚á™Ì)#Ö ¨ƒQïeá6Çöq2 x5‚ ™h^hLÅóÂx»›¿×«kO·ñ¥fÍ©2ô³ÁÌ#R˜|["m€¨ìîålåÔ0Ę„·‡ +§´ÏbÍ1Õ!Gà„™Š3ïv@H•jÍ'9Uq ö·xÊÉ—7ÁÍní÷ò1ÌŸ +ç²A’jUaôÒ|mx(¸i¼õs#ÚÞvò O†1¡:n_—·x~Š6iéÐáã‚OsÑ:ÿßõ:¬=•³ºgžD¦x!˜k_àhc¬ÇŸCQÅìV,wLéOšÿ¬õ¹1…2Þ¤ÁËW…F“V†ã\a¬~â ŠL2ƒÉÅÙ‰ePY_qWWïÆ]ÌúÝ…9–-°b¹ËYêß…m‹*¦`l ] °Æ‘Z‡ý>AÆ¢:'þEDCþô²‰˜w%æãΚ:øÞjÀ¶Ê\ÛÜ†ì… +RŠ2ù€ ÷?Uj³öÙŽ¼æ"ø–¥ã%´ïìàÌ¿ˆèUY[<€á4šõ€¸2÷{sÒÑ)Ñ5Z${Àˆöc­ +Óª^ž§gj«Þ2¤óhBèÕÈKél“ª©N¤EÔJšHÓóiÉ0Ó-/ÛÞz%ºWø®‚U/ÏcX{då€k–XxÉËZTôd„Ź‰è<ÿT²šÆVËÙp“J}Cuj"¶ß6øˆfí{’PnI8¦D Ù|-+øÒûØaÐ!Öå)5‰å5ÈÏIYÙ˜' Z fs§õ¼Ç©Ügµñ^’aÓtÀDV 9Ów©yà{úY‹Ò%FÅ™Sƒ„3`’ðÒÀ4ëSê2ÓŽŠ mµ¯•gž³‰¾\Ón: À’Ëcí +óΤŸwÆ2µè»{%ôü0u:? !’‚àbI½¢ ÖÔ$,}“´ë%œ' +ª XeÏ‹¦Å°5_´cuáPR€@ÛßézÞ=L©Ü¥Žækš/ÛÂÔeË€YM«kϾJHx«ó +OÁqøҥܺÔ20‹¶mø +¤nBÒ‚Ë+åÙP×îÁZjâ"d 1 +v’STÊ2Ò¯›Öêµæ¦i¦l_&‰‡Pص +-]䈦Ä4ºâ$…ò{FËñØ ÅZ6—dÇÝo’_ºá7e°õ@¥kA_äZom[ñó Â:@›Î7¾!žû7:ýiV +zo þùs(?žÙèTÎÎüõ1u*p@´À"„}³!…pf§I8o×n +C€ s_‰gÓž¡;…›ñ +œg#ì§HÜ“ñ”Ç0'ycC3¡ñ”?½aäÏEwCÌó™ò®7È ùq +»A¼h..g¢j>"û~Pœrƒ]À¿·¨‚Náp§D*½ãÄñ,B˜§øä£r°mv‘p;x˜gãcøyS©ô¯’VlÙÇ{±mýè +@™qÎe£ÚÁË4ˆ'.W[ÙEöðÍ#zš]Þb´U¾à=‘©X? íåL„n`Ó-ø +8‘WÎèíô|™é0 +•Í—Æ‚ÿó€}ö«@I&*b @ŽQ+¥¿iÌ[ÇA˜[lðÃw-µmþbåŒc*†ñÓ +â­?|\y¦œxõšÔž¹€ç ­JÈh‰¸¨à'†¯Ç˜Z*ßC§§fÐ8ÔNGl\ï§ým1$Ã99úÖS!KÀiku²-iO+:<'áèjê)“¦T4¹««-þ†Añý™4 €lWܵ;¶ÒÚÀÌì”HTA_ϵíáC“hgˆªr¾ÃB<8\þ‰%¦’VpÖ”2C_ÙÅ¡~±ú][{¯ ÆD‚t|.ÐfðÜ‹‚ŸJׂõѱ²×³¸pÓyqiè¨n2.Võ"À×_H²7a#ÐH!‘¦ä¢àŸg +° +Ë‚ÿ†Ùi;í¼ûw›ìtðÈÃfh\—ÞŽ…Ä°pîjùªšõÄEWÄÎŽõ€Èé~Îœ¥ LÞü1š^Ö@7ÆÌõî^‡f¬ìÌZ’…F¸\Mïçf³„h͆ ¶ú±ÙžÀ8 »^,Í®k§rR=¶6gd¶š „ËC(rˆ[ý?†áL¶‘‹º€Ýzó˜ýf¿~Übï9 ŽˆYïçÈ\1Žëû†•f €1ÃÄd.pžæœú±ÍzoOð·æH¼¿šWYk›nu„12L&q52ƒ°WËeË‘‹-êµ´yÍ•ajX~š5ç{\A{îlîd£ +ÐvãAôj¿•À%(ô +™Qw ˆ´åZ·Ú0ð>õÜÙÇì:Ny43ì´$ÆkÊÆØ\¾1- +°Ü¬7•Äwé•?Øu‹àžd ¹ fm&)|eÛÃ=óä‘&L#@‚vCãØxW_ñ°h0&…7X¼j·ó€1{ñ¥-Œ3˜¡· +`Š°ô€ !Sïl¦Ÿ.®êîèYîàL³\_dî]CI_7†œîÊt“/—ód×b E™³+¦ÒDžݘ™¯nø±Á¬ÇðK½IX†ðÙoàO,ØýS«[û1þHÞÌú»W'¢ö-¬—#ÂzÖ9˜ñ(j—ƒy®‚W‰¯ÅAF#jflÍ%Þm‡"nn¦ŸÚÓ0‚ ˆ.fì"ò¬ÍÁdžìCò`sQ„ƒ©þŠ‹XKÜðÿc6!™~u’È= ¯F `òçÒõºÃ^ÀCÏ1 )òì™wÓå+œ¥¼Hóõ7jawrJØU©ëÊs‡pk?åwø9Ö`êJfþBö wñ,sðñ—¶| Ä@fìßYüŸ?çòïº<Eêb\ Š*Üe^üË" ªë`­ã*êÿï_«¬ÄÈ´v÷ϳ<.ÁÿòçvC57Š—_tŒ2üÓaKþ—Ý}ÿ¹v7vÑŸ#¾u¹Ñðk™n.íùËk±V|  ËkÇ« ’Ë·åµàž'â&þKAÞñ×A(ûÆ~œÞÌ< +ëÛÀÇܯtžû8í×߇MŸê÷™ Ÿî,¯dd. +Á?yƒVñ[IП,¡À›CJîåuâ.BqVÎÐõ‹EW÷ ÀótùuÕŠ$š Å:B½]A€áJüVÝ\\s·K³ý½[„åmüÂé×G öLUf ]YÁYV¶¡v&~Њև¥#^¿Ñ¢èÓúª:¦øz +틲£Ú}1^/· !½Øiû¶‰ì¶ S3è´ëNWÃ{¿@2Ì0\Â5”>Ø vèÃ!m²´)© ê—jT݂Ȭƒ :'=àhƒ‡ãŽÑ©ÞK«œ72pWþU +#ÿ¾ºbwçË«çæ8îÒ¯ä°Ú¯pV0€`aŽªÆÈûâªwëmàÔ'+ø¥Ul¾ì`OF%{üN’ЈÒT&»_⥄D~Ð<ùí˜äTžvß„Cív¡ëeëg‚s0Cpª¥«’¨\ù²¡Ã¥è\§I Þ`áu s¤¿n Nâøs]fQ +Œqèà¡'›‹‡Þˆ&dƒkÓîV£RÁÈ&ƒµ2æÔÍ™”H⩪•Q} pÝZÚ=âJ¤™Zƒ<šn]?2{Ót’å=†Ý³«F¶eû…g©åÓî4^@c–ã×íÓ5ym¨àˆÆ}ù¥wé®R2³"ºÆæÈoãm°Í†_d VÚ2Š÷™±q€„XûÒ:™T$ÉYªæÅ +’%æÏËa£Q®…{_¿ÌÚ¾:W´™/Ç‘56fO‚YøFÌ»G:ú½Ï¥«uèõ¸67µuò†4‹]»+ÙøÓ®Ýå®äˆFŽ j‡XHNÞ‘.[yÙXïæKe[DˆÚðµsÙoÂYw3þØ,&’†]Ñ(”rKoæc¦Ï߈žŠÝêjªé±ò˜À**ã!Uˆf„à­&« ÂkpÆ͸†…ÀZÜ"™ +i ¸·ÄŒé-ð²sc¬‘·£3´A±T‘À­ÆÑÅÅN•š} ­ð +ò~@”Ω*Ì$ðQû|0,O” lK¥‹ôsúø×ãAƒ/W%'SX{E[ hkW#«@v íÏ;÷kὧ +Ž2_ Ífˆ§“ +"i8÷¢°¶°¶TÅfg¤R¡£w\ÄûçO.ùñ”×F©Ž~}Bòíç@"AyCºBZáI\^ÆìÔ$Ç¥ò + +j4[6${®<Þ¢„y‘uR¦{h>Í`®3d9KS)ÔAEàÍ7âù8†UVŽØ_Áã3F-ïL<†1Ë ·(ˆðiÁ}ÌÓÄËT¢Ù´]3iÅpÒ̘ÕåO.’uGÍ¿lc†a°ÂТ¼faÉ2(¯"ŽmŠµ° +ºnÇ~(nM +C6Ç$IÝx© ¼1ú—‹º+°;a2š.0-fºæض0ÝæÃjslLß|XC”€Ò¬ÆþP7[÷bÿ +K+C_ì)”OÛP&jø„ýÚËN«Ü—ÅUreôî ñœ$«ØFºEßó¸„ÿ†q L9»y d¡MAö’L¡7}û"Â.AïÝ^¾™ËdÓtLÊíÁ¬œr¬6ê­ +ãÒ)¿&ÚŽÅYÊÍgÖeŽ«Aý´Rs»H¾ä“âŠK^Í‚ +ƒ©²¥ÆÎíL +sY&(;ÐÛpÿ Ô°Eïc>Fáä{Ž#m9ĦrIÎÜí_>×Y1yvåçÀ±°L.€îNÒØ]@9XØmÐææ(Ù¼T¥K•lŠ¨Ù†´12ø@ˆ$‚ù±ÁÔŸË"ØѱÙ\‘ì,V¤m.Ž+aÙñ8Ùd¬×JfË`™m(œZµKö6”†QËvô­¹wë4MZá5&™ŸfRƒgÊ Ò_QwÒˆv_«¸ VÚ:À£eÔÜ9—7Ë`öÓ#"v‘%µè¾3[•aª×¸ƒ~òÅ=Oß´R‘?)ÖœEi.@éæï :Õ¥šì¸ÖR”eÈÉÓ +„KÄÒŒ}~G¤—ñÓ~òüñ½.x¬op3-0Zéámv0[é&I}¢z‡¶+×eÜ©Œß4R·FzH[%éšà¥‘æw4¿k¤yk$c‡K%¼5Òü]#é¨¤É +ñ„Nš¶AÜïÄ¥’~çèOuQ´ 6bºPÚ®OMæÊÉGÞ I$mËš˜"lÃÉ䌯úFïb¢@¢›L>—üŒu4Ißx*ŸC}¿™„bDûfÎW\|>ŽSßà’@øÊ#WƒN&Ô_NÙ·a—²Ç$—½b[t¦D„Kä!ŽfkäJžáp+² ÊCJÇ6ƒ0úƒ(?—9„ù¯@PKGGÖ> +åa-L¥7ù6{¬^kXzâüè¥ÜϧÍÛ¦¶3`ʵÚâ÷ˆÃà¾)1”À-ý«ÍÖÓYE.šZ¸\›Í|˜B­*£ba +»àN ¼9@×p‚ÎX@@‚~?·jªcã6w~{LSS¬Šyó\–·ž‹hm´Ó®UAZâ÷°¨j±ðOS¦EuƒÌ5\Í=MUuØa6@UȤIÿnT] ²ö»©Š¤‚ƒ‚«cö¢¬ŒÞŠ`Iœ¡Æ/2?7è"„aµÚ®a ÔñµXµ#iàZBÛYeµX°ÖÀ^i·/)uœ±Vî$7”U´Â +Q9lq{g²šX”Q-ü)&d ¡VÙî‰PFA ¶£µ›Ej‰%µ2#Ï•v­¡CR0Q·Í›åZòñ¯­(-]ýŠØ˜ÑŒRêoDý+·ðXŸýhi +²c çµHBѪ#ÌÎ`…žƒó[•ƒ3˜¡?l3²=ç½e×su†4¡š«ƒ Iîü¢–Á{œß:Ž†ðæ#s~ëø]EŒßUÄø]EŒKD=†ø®"FÌ +¾/içàû¢ƒE!Œûç9”€ïË,GžÎï&oW˜|¾,ô&Côhß|ߺxí×-ºÂO€¥±Áe~º|ߦzfg56$}XI$ÂËúŸ6Wî’aÛB·‘¦h|'>›Áˆ(iÆÏK5'k¸Ç«•ý:W¤ÈÚ+ùÄãÛþn¢<‚&߶3Üfœ½Ø„gXÅLŽjÓ&Té@¶)v©g¢^=ð(SaBAcæù†ð­ìK,Ñ°z‘IKj"Q2q0µ ýoº‚\ï:¶õ˜&p»ÿÜ{ë›…Pª½o8·ªÞø‘Î2F:ð#èÃ+½Þ,"ÐèZ´f6 +Y±±VŸ–©æÎ,x_óc¬ÎÚßX$Z„y" +ÅþÇ^üñôoÕ9] ”XÑíØœyð—(fÕSø)`“žLµ*¯¢§³Ó­µ4³Â>=Y„Q‰Ýcø‘Y±1ÖB½ŸR›6 ·Üâ΄H.·< ˜ºn•6ŠÙ¼æS{€¹îCbòÍ—ЃqhÔBñ»Êî,qç|x¹—”XÑßM΃{XæžTÝô˜F"ãÚèÀŒjðr-`Ó•~B’s=™ÃÀvwÓ@JbƒÞ¹6}ÉböB#d©ØOG© ¬õŽèS÷R+.ÐR+. R+øsóø2—º›‡§Ô +¬½j—Y¦„Æ–\ýÆLS¯¡ÁÂæk&REòÜó*@&Ëœ`‰©î§êÊ«èÇŒ¡ôéº)æ‰ÝÓg”XÑóµ]5·Ô!è^&«ÚV¼ Ϭ¸Ì=‡SM3"XÂS+,»ÕS+8ý©Ý£Z.¬,{úñStÌ´ÉMÃYWH—äXªÉ`‘UBöäg‹.hA£~Ž¿º'Cè×ï·¸'[¿&ˆ‚{¸7ÍŽ^Ø©â^O­ˆî©ø½Ù¾° ¸y5w¦V`ïæÄ’CnJò\©Î@í0P®aWK&³(æ˜~ŒÂ$u)ÚðUbÅwᬓŽ?ö–áã¤|1ÞØÇ9 +/Œ“U™ +ê¢Ë†,k퉭±ýÙ{ônLß}O@…÷~ÎÚ±8,0¢òì”›B\*½7;·úáV2ià +y„H~¶A¾÷8ûD6‘ƒpï–³!qܻʣ¿w÷èî*ê!Þ~"¦Z†ÍQ.¸ù£Ðc#"ÆnÿA‘Ïp)Ù(‚¡—/U;«î +êÃÆÑ’øÃÏ˱#棚a׆ñã÷ØPËSñ<Ûþ*Íæù¡:?îö‘¯ˆš|À{U+±~s€º>6f®bׇuÀ´UõÿœA%i¦YÍg¨}ÚæëÚ|´ÍíˆA1ØÏ©›Šú‘ji6n,°b}¦D×÷ ®âûžã +çgZåQg*2Ö5%ÞYôm$3pVÍÜmµ'«ƒ¢Ö;˜%ã²EA^~€ÂÕ¤ÌïÁ›¤Ú*¨í¸zÆà7P‹ ‘T ÝS^!Oo]§e(¤è>8ܬ ®ªÂ8šåÈvR|ZÀìùÅ…Ÿæ3/ûx@DiÉP…±l²r]ú²(fS¾F_Ÿ&nËLéÆô¦î8b°ñ~—© “…Ÿ)SA(w³F9dòÞYŽo†²oxQUEÜ×qMªV +óKû'à¾Ü ÆÙ*æn\gq†±8—vÀ0“«+?õçœ,ƒ2ÜU<°×«·ñ†¯×÷¤öè*‚µ±Îo1è¿Ìã +^j$²ûQ(϶eRiwKñ”áϪÙö•ŒÌ¯83}üÈÓöªµ®]¤M%‹YI0üG‰äl3üG6R–?ªn›ÕÔ ¹"é<²lËðnù˜á?rdÖÊð94 ÿ +¦u"¤(Ãßnøº†ÿÈÎ'²ûQ¡³¸2àÜÞr"™£\ånKã±`kàÁß©JÔ®øL +ÔOûí~ÔF´³º®*BýN¨ÕÌ(7ûñs;ë´*BÙø:Yit?+µWÌZ¦Ýoßs6B­Ò÷„ŽØ:`DrEzO¨iœØ’ì~ÐÕz‡ÝÐ + }õÂA³û/ ìþ‘#Ѩ‰Ž~ö(»kßýë +*äþvÿðô•q¦*ßU†?Yج“¾p厰9"C‘Q +JyZ¿j|û)­s,¼éÀ¡ÊÌþ +}<¤§reT£Ôk‡yú Ù°ÎnÈ-ÿ Ë ŽTs¦pÃx” ÿq’kø]¦ê‚ZvÿàÕ=™êT3ö}L³ûC0¸iŽ…2K°øg;'®XsÏt”•Ý +<'I?Αg}{Öº™ýÜ™fÅè“NnOÑìW ˜fÿ8>,‘cæúæTþ CYd1Û—Ò¥£®ü'g ÝÒq%U>MËäyä¥ÛýØj–ì—4î"Â%œ¥¡þØ?ðÙ·n¡/3)g$ .Vrs·‰&åÛøR¡êöÜÏÅn•Ÿ—ž'uoɼZq•TinFŠP3PVˆ™)‡!Ä —OÅÓ‰ß9ˆå§ÝŽyy!y#d»~*cž«9,Ö,žZL2Oä5-Y㬚F¯Ì75‚ͳZJ§l¡YC<@«LœåÛa˜Ô +0æyÀø›aÕ¡¸åT*Î@ˆ¨d¿ô¯ë[ÛµN5×»e ÇÈPy$Ÿ‘›¥ÿœ©MÖ žaµÈzX2¦êÍpet3N‘Ói©uéUZÈÔ‡¡ô­a®¤is5ø`ù=@,ªwü€·'ËÅ5³¤j¤ÚwÍBü‹·\ñz¿ ÔùkwKªÑ-ûy*´pØ&K4‹¤Xˆqžœ.Z¶ØJ$2ˆàÒ¼.Ír:vž-‚¹M=GÌÜ@³?×è6͈Mìª=ƒ¬,‹Ý?T«6aQ¤;»VŒðEËcÿü¹#~<³ŸÜ¦ÑUñ½Î¢X‡ðX3s¸–1!1,×aêLΓdm…/=;¶X½ÁnÁd{>íÚ,"©sÛxYK²Xï–¯o,åé_°ÃŽ]‘¤´ó¹ìò +šG›84W„ZßbuB=]¥éVDNP\÷åœ_fŠ.ŠSÀe˜+Â_ÂÎkXébÅ‹WuHÃ(}«ÍÕ1,î¸â´ŸÁ»í±¾EYöjG,/áȸŸ_7ð¥BWœc0Ÿ>VŸðó“%N]‘VîÐXÅǸ(ùzÉÇá‡>,;Ù§Yð*éî˜lðy¼ +ºä”ÒtÎß.Û¢ò#>éMLa9GåVÐÙ³ +˜}y}ÌóTF°ò­æðX§û2(ÄykF–J +ÍieG9±× ‚f›ùR½P×Ûlí¹ºòÕ¬–.¥@b±Q?ÃAq± œ&ìzœŠ¿*Ô*í’ÅžrÒçO¹«Ü‘+9j¿6%5ì’ª#`?Û):Rï戔|›*?³4 +ÊM€.–û’Æ~éèµòœ®vôt˜ 5ÈNv¼í¬×ÃeñãåתȾ"ÙAk"dc©Æ\~«´—éeƒ=Á)¸v^\[ì‚€ +ùzzÓ SzÐ=º©çqc ÅwP»Ûúj¶zqt]ù<²QNl¡§…Á§fF{õØb—ÕTKÙ£mïU=–ÒlX­_‰61ð‡eí¢®$Ë›º½•iÙ†rÄŒSxvsFÞT±âËžU¨Cgà« +;ûèðJ±Õò¿ {sψ‚mÚÁGóÜúyt•V¶·QI¬H}1Ñáˆn¾¹çq„s–æ’6çPó1©’§ÅélóL÷!º[:3òD¬¬ZåN¿¤ÕÍi›Ã¬T~<±:¿Ï0GleůÝ'±£$Ž.£n +º_$Ø}öÆîÂA®ý€~IàB ±vþ#sDBÑŽ\b0FS¶çˆ+äïüóW–úÁZ3&Ít‘Îʶzgƒ.ÖAÙeõ\ȯ;‚Çj¡íø+ßW2Ôú:Ã\)Îí1ÛåΑG”Ö)¿À‘$ùÒžë·sø削(-¯|bw\×Á>­5ŠûµóDÈ ÝoȦù†ÙÁ;®èíº¿³¼2„å?¯S[!ž•NHHõWãر{ !YÖsJéKîñ$” +vG»“@q +2v(½šW‰$0 +¬i€`JôßÂOóZEqÇU€í£ÂYeh¯T •»¥¸Òç}éÕŠçR²C) {ØžëdÁ€^)6”äíRÞyÜqEé^ÏŠ)ä(?ìÞÞ#¦H Çõ“¼’IWüàOÏ‘æ\¥9Åb+ÿv(¾ÎÞqu²)|¼ò÷z«œ“…—ó8¾&ˆä‰Ÿ~Çõ­Éݺ"ËŒ%®ëo¹°¨ËrÇ£.BÜQ—Õ-nüDNw¿Ãu¹0ˆº¬vEâÀ(&¢½×Îyîv"VãÕË'Vº}ÏT_Í×ñx1ë¤YJ̱¬È y°ÇØtY=‚4Šº¬ÉVÔeõsÏ >ûê–"ƨ ÞnVððÑù©ÅÞ«EÊ8¯p·ÒV‹,Q6¨,ÆìQ—UO.eü:—ŸuYq{AJ ÈíìÅ¢Õá »üÁC›­Æoy¢kDàÒXÂõ "ød×H–›7‹F {!A„ÝvYx6©P겤%Ü–ìú|-1“íy#A Hô1 ÙÑËtõyÎÔãóëÅïÒþí@Äßo!RGL—Ýç¾Óþsì$ÈÝa˸\¹Ùû_UðóÑi#®SMWe}rñXWˆâ·Ú0Wß²bâݾÒÚ÷•ÿú1~<¨'WÇñD~}°Âœí%xÀ?‰ñªcYä`¸Ÿà½£Ï¬TÜ›#eÁ1oøwUy€iùB¬éÙïÁd‘ƒçþò“ý–XÍc0rs0"ƒ0mõû$Œ»©y$5y&áÉçßoµ Ó¹ŠAáoÔ’ÊVqÇS²¸)û…%‚Ž÷Ϙ¦ß +¢ QÍŸa÷²Š +½–¨¨LûMv50n¾&2_6K½ËP¹Ò¸ã1¾#ÅÙcO~ñMÃF7QåôÄ>¯,£0¬Bß[øëj'Õö™4’ÍqF&ÅáyfÔ™P£O ŒñNí⇖×,l³‚ä{ãܼ^™‹tåá ²qÉÁ$Ë_q×|™â‰nà ÞÏË óáfŠ\Ÿ3Âbš±Ü~FS,a¹ò‹¥ —§n?ñ8Oµë¯çGS›ÊoAÔú-£ +päg™¾šßN»IÃuˆˆóê¢Ô^ÒÎq‡‡ÉF iFã$.°hìÅL:iâP¯ªœ]h8-©WPèK¸,ÑnúyUhâ‡Þƒ*v”&CÅáŸ7ܽ +J­éê°……äïlÆ>ªêv´ºûíþ9×-ÜR²Ýé—1ƯÿÞ2Qòë5KLÖüJ&”²œ[ØÅLwË‚’!ÆÇ»ù@xEV•N)låˆãijCïˆ-Y ¾¬@KÕë÷Ôäú \Äô×¥ù/’¥éLyË̱aÂiE] +Y …MqHrå—æ.e?ûóZ5"üx—ˆôF _ÓÔ0?0©/O–ÀH¯ðé¦+àyÕÛäz€ÊdkJ‘‹l-Ü!ƒDÂÚ$ÄðYÚ“B†1e¿^L9³AJéú10~—Û6åjñsíü©%µ)æHÔ8—{ÓF“ïÀr䦞ëJ2?6Dùfl`CÔëª +ɘ hüªzé¹ØU¿M"G˜Hp­0Ó† ’Ýöñ„‘ 3ÍÅHn #úBW‹R½ƒGcw>³—èä0Fa}Œòxx¾U«>¦`ö`ô`Öb¼"ÌI„™›1F£OÌBð×™¦¶ ×ï=[î¼ èg ±öá7R|ý: ý¹=Ødé]˜—ëî +V°" +‹‘“¸_‹›à†CMXÎhD…Dãånpíy·-ZxÁöÂ_‘èÙ“ +o·§n©Åö‹I)nX¤î×Á +£j?Õ‡ýá«’€uÃÞ*k%¿ÖZ,´Á-™½Qvus% #?˜Y2+²Û@=@yZ49¿¡bÍ^=Òß2äÝú0¼Üƒ +Dbu½^¤ ÒäAê¢Ø@J–—âÃï V‹¸'û,,é_‘Ð#Ž +ßHöuúË|&×-~ +cnËÁx´ü5:{6ÄÔÆ!"Ì +MžTù½IÀ^N–&f†Sºgrz“IˆÝ‘öž4a?iá`Q×¥v*ÇuÃV¨]µƒšº¨ž8+^ù~$óH;NY¥t*k!‡:©xÀFg·É›V=Ž…™]šæ·(‘¨àЇJ3Ò…á:ž½ê¹ÒØäã®LøK#)çÆ5w§±iȧñ-ÍD¯}› Íd@2`0^0ï4´oü2¹e¾µï“êµåœFúµ>%ÚãªùÄýÙÍæR€™Thæa²Ù\ÞET~i.z¢ÄYÞ%K§IͽÊOuIbsàø¦†ö0¸ê¢W³nŽÓ.h7“+~T4 +›cŒ~²bi­§·ÎbߊMþ…Ê[”Gíæ°kví…¡]˺ԇísv:ÌÚ¨8nfmö‰fÖæcw˜®Ì9Œ™µ9G}šµQ4:ÌÚìÕ3ͮͧº ­Öæv¶(¿ì;ÒšxA/êôœÂ[0ÃåeŸË®eÙø(ØGØÓ<Í°L=øÆìú æ›]ë?ûfl~݆ Ø+¬É¬eÍ{sÏ!4rŠL®dÓ¯VŠf-ª—§ËhÍù¸fÖÞ¥å­IMž–²DI¯ +¤™½â–¶ù\/ e›Ïý³ló¹ À}’O1 jê\\Õ„e›½4Y¶ùÜ# e{ÁfÙæ¶lÿ`l +cIWØUJž¦_%,©´xõð²° <ÿÌ/ïÈÌ*\éÙ7¸¥Ø=(SY¨vínAT¿žúÚ,ž"`6@ö´&^¬ xnÚ_pÈ1aü‚C½z°0U¼£Y–цr.Î0›2ÎLª«¬˜+VÍÖB†EâRIo„e‚ÅT"w‘ÞÈf%ƒÂ„Ì:”—ú*vçM^' &\ºŠuãC!€Í +1ñŒWØ-NJÔ×î¶C‹Ø«>¼Æ£5*làLùLk*°ƒwS3ÀØe«üÚ¨Ä÷]ê¹`§O +§ù%×H¹@¶¡øÌîôJƒb}\‚õDøø +4.®ö^5A[í ÄòÌ´Ür*’¬#¯Å1ý$»Sab½‡Ü~ÍP‘4“5õÏ_vïIàø•…uK|‚Ú—U_D‰¯Ä‚êHƒn‚˜³:˜Ž†’ƒéâÈ´‡…dî1bºvW‰M{Šð0 jêö*Ý%îãG÷óZ£·\¿i4T°®ò#$_ú +ýbÙÉ®Žc*™ù¯Ï@@1Áb·J +Q³ßI·¡¸_)´ŠÝìi*›ÈÏâ§9©Š¢.5ÖÚÓ·ÒíóóUŸ•¬™ÇêŒýV ‡b™¨üz;k=–Åo¹#s¤v~3‹ŸbgcÔ¯QŠûf|wˆùïÈ7«þñõíöuw¬þ +˜êì—5²uºrºcÑY`r ¥¹ð•¯éÊÛ‡¤EÓç•Q|²a_}:°*'/¿3;Rj¥@lo0ø÷f¨ÜxºÜÀñ&cÔøð…vâ7굆oÖ*5@ƒß:5D)ÎÂ5ä3~Ù¾¨"’ˆÙ® (\ulá¬S™®èP<à¦;0H&A¹Á·[Ç9' +5Æy”qÆ“Y¤ÒhŠ”QT>õË8ø.Ù†1*N4³–¬.Ïà$ Ü<ŒâøVêÒbq;OdR‘„HNfO=×c|±Pk×NíËn3ÁÅ‹ª.;Í®j¸Ùv¼†4;åÄo2a«ßºøu7Ç~õ:Ð6U}ÑÐäÀž[ +ÀEY·²ˆ& êÖzd.Xì9¼`“ \-ŸŸú"ç&0õÇïD’ÇZˆŒD®ê.3ò¶¨I +À¤K +  LlÌÙåÆŠ ñ˜è°ŸOì>·#;øþᲃƒkåǎ\\ ÄÀÔ3¦’I€Ü8.B°vÙöþÔÂÂ41+ïR„”éõ> + >> +>> +endobj +5 0 obj +<< /Type /Page + /Parent 1 0 R + /MediaBox [ 0 0 240.944885 126.065628 ] + /Contents 3 0 R + /Group << + /Type /Group + /S /Transparency + /I true + /CS /DeviceRGB + >> + /Resources 2 0 R +>> +endobj +1 0 obj +<< /Type /Pages + /Kids [ 5 0 R ] + /Count 1 +>> +endobj +6 0 obj +<< /Creator (cairo 1.14.1 (http://cairographics.org)) + /Producer (cairo 1.14.1 (http://cairographics.org)) +>> +endobj +7 0 obj +<< /Type /Catalog + /Pages 1 0 R +>> +endobj +xref +0 8 +0000000000 65535 f +0000015956 00000 n +0000015656 00000 n +0000000015 00000 n +0000015632 00000 n +0000015728 00000 n +0000016021 00000 n +0000016148 00000 n +trailer +<< /Size 8 + /Root 7 0 R + /Info 6 0 R +>> +startxref +16200 +%%EOF Index: tags/1.2/doc/src/trm/images/gtkwave.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2/doc/src/trm/images/gtkwave.png =================================================================== --- tags/1.2/doc/src/trm/images/gtkwave.png (nonexistent) +++ tags/1.2/doc/src/trm/images/gtkwave.png (revision 10)
tags/1.2/doc/src/trm/images/gtkwave.png Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2/doc/src/trm/images/llitiming.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2/doc/src/trm/images/llitiming.pdf =================================================================== --- tags/1.2/doc/src/trm/images/llitiming.pdf (nonexistent) +++ tags/1.2/doc/src/trm/images/llitiming.pdf (revision 10)
tags/1.2/doc/src/trm/images/llitiming.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2/doc/src/trm/images/symbols.pdf =================================================================== --- tags/1.2/doc/src/trm/images/symbols.pdf (nonexistent) +++ tags/1.2/doc/src/trm/images/symbols.pdf (revision 10) @@ -0,0 +1,858 @@ +%PDF-1.5 +%µí®û +3 0 obj +<< /Length 4 0 R + /Filter /FlateDecode +>> +stream +xœ”½ÍŽ%»Î%6§Èètè_z‚ ôÀöÐðÀØvuÁ¨t{ЯïàZ‹”vf^ßóáà ‹Üñ£)’"—¤ÿvÝößÿúŸ?þ§ÿóþø¯ÿïuÎÿñpÿççÿÿçúßÿûóþø¿®úñ_>þÛGÂÅÿÉþäY>g¯­—×ß+ÏÏRçGªŸe´”Çgkë#§üÙÖüøïÿ÷Çÿöñ¿\ÿ?÷?7¦‘æg«ãã'úÏ?¼½æÏ‘Ö¾]ô¿½]—·þ9W{nO­}®»;ƒ÷§ÏþtÌ¿oÄHŸwﻢùöî¿ÈlŸ¹ÌýÑÿôKÖú¬©_"Æ¿ïH]‘Æ#ÿñå+þ}Wè1ñþ˜·ïø§‘RùlóèRgüÇcZ9ÚÑ©Îø§­ÑGíæøW½·çŸ<"šxkË?yDMŸ«Ôóâüe”-Ow;$Î?oËscã|„8ÿü³~ÖVÎGˆó¥ã2]ó³çs;ç?¦,fºÆ:M‘jnÿïÿõ£Ôçá¥k<·ý5FŒÚª‘y6¥O#m|Úöú(Ï»Ÿ§_ÆɵÝÓÀÏ,c‰ëýø=Î;‘| îC¶™/>ÿé»—qÊH»9ù3-5÷±léOÝ~.7½zþ¸r–§3ÚÓ)ÏW<ä êc•qõ¸Éw5²r=O ²Ù·^¼Þ9kf#§=¼Ö§c­i©€œÞt³Y¹çS;>Õäðõ²~¨‰{¥wý†.DyÞ]þ­~DR3Ÿ»ìQÏçÜ¢ ®oN½ñúÒÙ°žl„ÚÊ$c.#Ósÿeô WøYú4è^ü²„öõÊÛçÓ û’Q‚|=½þhZÞ¡®/¹o²¹ +mFºy9šûH!µ ôjRžê×RÁ F´›TP(óØFf¿º¯ƽÒE£A†YûüT +±ø§–»…~=d+A^¼žŸPt¹8Zt½TâéêEm~¾ +’ÉÞ +2Sÿîf=óûú6<]¥?_ÆþÉ+tº ÈV5º‘%q„Ì Uë1"§uGáŽèê¾PŽôóç¸x5õì±.^<ýnûüþ|É™Ÿ®Ÿ÷Ìgo˜†ÆXÿƒ FÕèO¸]¢yL~˜ +6­ñy&jkºDËò|XºNËó8…>÷ïÏÖ·àé-¾¥&|xóofß²©ñøt'Ùé¯Í˜Ÿ°…PHþþ&µGŽó±ÚEjoŽãaÔ9ƒñg3hlÑA4!ïŒk¿ÖïøB¶ÇBé‰üÊçãðŠzoãb6vóðw,}ÙsüÇà†=O}ÄFçCìËóˆGî×Ñ·ãzOÆïïŸÿëªIÉèg~¨ÿtšg{Bðç‚& +bÛþ~< ?ol0Êf¸Òù›ëcX`{Ÿàžö`<Ó(váx̨Ý6MY·‡‘ªº8=ZÿÐÏ¿I?.ç!i­Hâú–ÏŸ{N~7š „§_¼œÝ¯Ÿz›5mSÖò×ɨç­ð ÇÃ9Ž—§Çþï–™Ž†S£{×ùáºÛ;FO~{Þ~öéñ´û‚eû&…gD›i¿ÑèW8R”R®ûW¸#¿·Ò1îg?Û<,8¡wíü”Ü00¡¿ÖvŸda ? 3;b¢lŒôqaè’Äœ©FÏuŠíѱÉû{†ŠS +#ï*Dòâõ˜–ì Öb{0|h3ñ¶¬ÑYn6¡5M0ºjQ§~1}7Û%rF´÷ˆ@ïþŠñ¢3C½i.ãaÔ£nÂ{cÌ9ÌñoŒÛf×;ç6Í™°ÆD[Ø{š¤<ÑÔ­î4/¸èQ¼w¡o)úöe Wtö£¿õP뎾SwDÞ…Xlœý5Õ[Œdc˜X£¥;y4õ@ãÍ0_öLº CÞ¨hžwÇó1q‘¢OŽoP?¾×óçš\ñBöÆžHÓ6?¥æ6!pñZûàý\ÜafXVIjDüBÆïïZôÄé·ž;é„¿ò•Óì¸çaŒV¥qFW~K0ž²ÈÔUL Ÿ§l†™ÞçÏ2Èö(‘‘‹ºK¯c$=êcª¥ºi\É8)\Œ´JüŠ¹'ïEkK<úâåÐÑýnšéh™“Ls ºûÂ8{Æ÷ñ|ؾx='ùÑ6ÓhzQèÊ/»Î Ò<ïö~ñ‡{·áÝ»SÑ4×ÑöñËr@ÝÄ•&û?ÆPf8ñÑ7æ*©Ô\ƈè2òå‘/h¦”`nE2¶ðß5Ê"Ÿ‘], ÒÓZQÞ²NòÁJS9k¤´Rò©Ba§Žñ®0Agæ9‘d}ÈÚ"Oá•-È*`ŒÅ‰I%5š’ WÐœk þ %æOÏúœÛcµ_Ÿ’%uå៿I…[ÎxrÏšv¤“ñû»™ÏCBfËt3 ÓRiŠÃÔ*É´a_’*/Kvm¡jJº¯½í¯j&“Ë¥ª”M)[¨Ê¸P•áÙBmœ®Q¨ð:rÂ.T…ÛÞí~!3“2GUóeÊìŠ(s µÒK¹P«T^O¯[Å(ÔŠ¯¿$ÕQüó7Ù#Í FÕ¥CÆõ‡ùÄwb>ÇnzlNÇ|nHÛÈø³·3üg ¼@Dó¼ÌÂTÌ +¡trÉ& +˜nðãû§"?DSF"ªDbê˜vZ˜ŠžïÊ{(s¸Î=ûÝhnåÍtƒîÝ_=˜ó†mòæüÔsnÞ}=Ÿ®‹§7«¿ÝÒ-)šÖ8$¼åÍ¥„/»öþåºÛû¥ùWô›ÞÆuÕK¢õ?H©FøÎ{AQÌ«Yðœ2üþßHî$3'5òIÕ¥DÑmSò‡‘Mñ-Qts?1GÝÃ`º« åAÚ×½—&™Š Lì +ôŽi ±¾ù+9°3ÕÌhó±æžP“ÒÀ«ÛV³-Ù™é÷Ì*1Å`³È¾¿î¹D›3*¡Žù°\3²<Å]óŵ’¹»fûö71žb~ý$ùÇŠôèÖªF%m…ƒªD†i÷3®J.˜ÂQ:á„;~ö2ªN)s2 +Y‘ÏÅ6³ØŒ‡Ì’,:cªg«yê‹×Ó(^æ“•/·´ºæ“Öp¦Õ§â3«¬Nzz¶BW]œß™"b‚h Xù‚Ù·‘’ŸO3ÒúáåŒ+TÃn_¸ölqÜgåbŽ×£Õýv³KKä¥AóÚ?'8”¸ùü£Ýþld¼:!lä` j‰²‡„ßض{*jÛ=ß"å?»ë•î‡Qã#³ly‡$Ü$vÎÄÜÄè IÞlÞ£ôÐ +F˜žî}Ù­²‰÷'ˆhlŸ¼¸Ý +Ò3u¬4]`žjì “凉ÿÞßÜJí;~cº«öˆÚa;ëÔÖøç#jðV/ì˜lÆÑóâÖQ¯CåÊz’•¤î²ƒÛilÃÚlRî¡©gz2Ð\êh¦ñ{Þ–…p£ÎûèÍÈ`Yk/×·³òЋWDÛe‚°Á ©•Oud¡}úyñWKw˜\:4¶À›PÛ’ƒ[ã!qxR 79ú¾ü‚Õ~^@ +cMÄ42‰âëšj)#3ï­6›8h–+†¥øíá†ÄS¡¾õPßgdÑiÀp¹•C¯ícB%óù3ÛV1±~Ký"ÝÔ“9Ñ°a, +EZ†#ÈÂäíYBB&Úè§Íf =b0 HU¾v·½Gˆ~´¿~§>ºû}âJñF8삹C ±ß[4öÍÐ +¹LŸ‚ÙðEÞÒ8­r|ÓXÝè\4Í¡°såÅàÔ&énêÌ Ð*®›1ââ̘äËgÈPÉ”ˆfâϵõˆœÐ² ©†^Ã0†ì¶%Þ­ñ{<ÑtùóθOÓ€ +ôíy0^ +tõ¾FgZÂÄ··…›}p3°òñ˜‘™7EЗXUËô ‘,ª: K†W•zÌrÔ|’ +tzän&ÕŽ¶ 1ùeo«g”×]¨õékx˧†œô£R=¡…2®1Gm÷—9j08­zI~°!¾pÆuÞ“ea`,ùÆÈ'1ddaßXåÊÈC£_Æ@2×>náw‹Â/÷È-}‰´F[ÇÏž&+ZbÅ?:¯¡Í1Pñ9jZ}ìiË2ù>q3œÅÿô‡¤ð_ÏÞx×s\/Ÿr—Þ¶˜W=im/;«eŸVŽiÖe2:Ó^Íê¿Uþ¤O‘†|hÚNúBÀ¦U×I2]rh„[gùñU~]M©µ55n*›lÍ>+“ΈöTHÜ°s#M…®˜‘ KA9˜ ±…=¡+gÖY}ôÜH³(c'C Ä·ÒÇÎ4¡²öï4LŽXs¡JŽ­L Þ=4[WË6ÉôB0˜ÐÝ‘‰§{ú"ÞÎôF´£4ÚîÙ‘+>..¨zn÷AgÏéõÞ¯hÝõñ¥ã_?ÉâñÔ˜ã¼öÏRPéÝ`4¥Û’gzg\Ð#‹ö=?1nÀyý½Áøý½)¿®ž# äD«çÈ~ã!}˜XÌг|¸»Ø‡a:Oû´¹[&}hU##7ŒË ˜H&#éåpxÈ\TÞY×—›q¤ÍFz °±Å°I“s0žÑqñÚËoFnÖ.ÌŽEcÏ[ì[ºYÙÎzfiÊÜ‹¶ºàÏÉ0OõÇî‘Ütr,TgüÞè$šê¾ýV÷áÚÑËç?ÒÏÄýŠ‡~x˜†Ï”oèÆɺ¢*”cµ«£@Bïe#“›ìÅ¡›Hø™® |Átà¡"ˆ­ªRç>%}8´Å†ÂLàÕ–^EÔ홊逑>јI$C‘á—{"ƒ-ešê‘^B˦b´¡vâìþΕ AöâAëÚö™Jsx7ÍÀ¤ë^X!úÕD¡9[‚ò3£CêB“Gb°'ÅMd\=%‡×ãþ°'I‘¦¿'å(X42½‰ü¾´ÕGv«TV/‡X°'V7™*çèÜm»¼üam»öÅl˜éûfIãÒÂxÐÞô¾s±Tfg4Üp6àV{÷YŠãAã©(•‚NºÅ4· Úi.Šê>dfÀ¸NN4dz°òN»›—n¿ûíëž&TÕ;üÞ mNÝU—·†g£4[b: /Íÿ«¡.£iRjÜš¦zŽÊ–´yþœo7’¦>®§•åo7J#ÚšvÌ ³´ÇÍO_çã +”û:_—²W0ý‰Æ͆ôq—sŽ·ÛwßðéGÏ™ˆw·Â umÿrH*8lÚ–<ÄÓ¦/þ2ŸF[ÌgÕC Ö,¾%ɸŷÆïE#å¹}÷T¢î‚à룧ٸƒdbö`®Nw_é3ïçßÈœÄÛÍÍÝ6š˜h{˜ |Û® +Ç·óvï>;úoÞjí +)x»¿Ká×eËä2ýB7¸§Ó³™‡â l˜~Œ•2Àáó¬ôx”Ð+çÓÐ]‚Å@„û÷¢{ŽoxuÀ‚;ø÷Q•aoHR5­uõ ‹¢É`dàtìî¢ãõŸÙû5yd`«»wÉØÇ¥£jÿ|YFÀ¦‰ì°\A–_F„12Ñؚɡ©å]Æ.8ÐÿŒ‰^$F Ocý3Š¦fÌb%„jÔÈoÌGC‚,· ãŸ!‹"®± ?€áñ^.áX©2£išT0ëöÐ]jÿGÑðöI-šÌøΪ©ÅX£DÕ -ÛcàŽn¬ëü]$ P†5àZ/Iuò}V +¨î¿èÌjô r­¤ÑÄãÑ,!/b&r08yynÁÈÿ ×çÈïùÎðÀØß{¿5%Ci϶ÖF£‚È!#3±1–12--»¢ +ƒ-äÑ÷,Žr2Cñ;‘C$‡#‡@®u ‡ðü{8rdqਞ>8”–¿Ò'Mi‰<‡@"£#à¥;rdNr:CÇ¥—ýø¬Ï1Gýä1ž t ‡âó7i]¿‘C·=hÈ¡`üþ.À@2ÝŒJl‹K2m!“ä¨~ ‡$UG…Шi‡P‰:~7äP|•C’êG ‡B¨D¹P :„Jà õ +àP•À¡èu‡¡8B%rH2 äÐ!T"‡B¨U*¯Ç×Ð1 UÈ!IÕ‘Añù›”P…ÚBJHŒ9ô&UÁ€îûùêv ‡Ääû¥mäÐfl¼ÊPVÛÈ¡Û<Ô Ìm³³ÈÜ–›¢Uš‹Æ6tÈè‘€#2 Cûg€wn-9¸‡O?ÁCz»°AÞ´MZÓ_'cÜsßœDöÇ'¬¿ž9o[â ð¦'—“×þtÝí]O÷žãB…£_Ѹ·~g=ç›,;”V£®~%Îï¥,EÈëP§`ô¼ŠÑßéaøãl{RÉCÙÂjƒ&èö†Ñm›–›šuày€Ë{Hû.ƒ Ø¬ÀiÂLFÙT{ãÒ4¾*óÚ†ü|ZÄýÛª8ØE\h®É*³’1FUNu1¶„ žÛ½J1wÁúÈZ·õð¥óS-‡¿g=–"·,]‘¼ø8TIJdÇ•Ü’ÌB]‚q ”ó|¿ +'x0=‹‡2È›”ð Ϭ$¾@eãXÔˆK.h¼¾£; žy}WÿØð£èiim¼=®5Zæ4º+ɪþHuʻʥÞ7C.PJØõË1>q!Ax]†ðÃ’ØŸÃVþ@S`ˆ±äñ:龄es1á™ß~/€¬m,IËSÝN/‚nL/hl[寴âÖ¸\©‰-ÐMèúžÜd‚)]ž%-7f_žO9žrþQô@ð /] û¾R€÷ØŒÄÒßœìðU`ïÍ®ºâªäô¢B zÛ†5Í›‘e9ÜÂ…ƒhaù «|k$Ñ [•P¯Æç>n)íƒ# °Bó‘ÕØ"źY¬õ€ƒz61Yc²öÛùôLøP‘šNÁ^èSq}ãåªcSº5`4è¨LA_TÒ‰ÚîÄTÎ{õåŒíWëâ¬ã+Ol›Á‘dKA«É +8 úö½ È3 +.}Ž€ˆªaþÝmâiûqÃP)¦I'¦ê¤=L¿½™È’xˆ¢RýŽa€£Ø+€)" “v ò’:”|^`0 h—0³Ë¡ùý“H‡Î·í ÑùÛì‚ÆØZ1tq<ñwedCÊäÅ®*Íf •'—¸’S¡­[”¿¿C–)õÒ'{0P<Í[jÃ*»zËÍÂp&¸ï}Zm¥aX5 lìÃfÚJ½üµtTr +jh¤Á¬Î —8e5­Ò[3椬æ=µoÍ#r«úÖtÍvk,Nš «¯$#jUàEsÃ㦴S»eâmÔ8ÉÆùÙÁAOÜ\qkþ1A‰é³…Z^¾G_£†Í·ŠšfÏKXQ|ÝT·¹¹”¹åOÅ-]õu®¸µPà +è™ø#3®F!ÉÚÒ$¤1¹¢O3±LïìáXqk&Å}í·LD̦%"•yoÄ!‡ý7™bÅíþ¸&x‘Êâ܈% +·Påùëp\œSÅ(‰öáøÝj¸›_b@Aà§ZCõ]´ö¦bº^sWªoM€ƒ‘ñ~:Aƒ¤BkþØ ?drJT9«5n* +4¥È´ÖÓ9Ê­Sßm¾Ö<èšôÛýe´dY—gl=ÖPSÄP´yP4l›n†hl;a^P:!³ùâ»<ÀIl +­¦Õ·¬¡#,•>Ô§ÿmÜ‚fî˜7ã9?ØÅÁŠ[·¢¦ýy'(§¼ÓvÄí7r[ûñ— +m™áNˆ‡R ¯ ²!#<Ó<Çú€Ýª'ÂÅuqô®ßÚ}ǘÀÔlºW‡’–¹S?¡EŠ—ñèØ¢[Üž³ÛL¼íÖøôhÓ/Œ¤D¥4N +´ÁW³ýXò†LLóÓ…%ß¹Š ×mûªÈ9ƒ • ›HŒÉ’a¡Óh>W F“,^ÆèykF ÕiééŒÖÔ9]Ñ*öŒábMñƒe:²‘ ÇškRc¸fû1,<ŽŠÕhv«Ôº¹ù©ÈûÃ’á­"yœÖsÝãRZU +äÅëóæé“RË}·"E°·f^“ÖhSeºœG"­j$4ñ*É6ehZ•‰ß;Fíó¹f*={oð{ Tc¦• zëV窷´ÀâºØ@0à›¦<Ê3þÍd¼§˜+3tèa÷ùXÒ;nÓ +gB¦ßšÐ{à`ØÇYÝ:O‰Ø”¤h±ÚNÈtºTϸXÑ\ *š¶{?ÇVhÊÈt•5vFÆ +ÝÊÑðõDÕDÛœdFæ`ØŒ›•‘‰Ç{Î$^ÏœJ4Ž9˜h¼§dzÄ qAÒët;;çx<ûŽ)™£gÑ:ß8)šÿƒ4˜MµÁй9³©bh“>'‘,ur¢ÚÁtâÝ-ªÇ¦#¤-ñä«؛҃0ÂbüñMMðÀ¤½ªM\Þ8æÏíÜv³){Ãðý匲*"7Qkl€Ë™ç§r½°rä$3ü¹ì߉âÀó¸6N‰ŸgIÛ—ÇÎnk!šïâgd+±Ív|lÊq;[ÌXÇi=IûTnGgFf€¦‹¸Õ˸Ø‚Nr§?sQd\Ü?‘d‰­÷@&¥roÒ™õ™§@Y•»ÇY'©­œSP&û¢vôAJ¶Û ]›,•ÍІŽå4yHë naÇ΃µ½ÈÌ +ïÐëÚ±ÎÙ8’bÀðZYªR3L·¬¬us/C¼ÎèâûK]С;Ã9”Á +U%(îµ*þ ¾ÍTyGHòö+.ÙaZ?n>|“¹a’ypÌkyqÅjò\ÃG®aÉÇgö•ö®DÇ.Ä2Úo +ƒ´ùF…ú]Òz› +&W$+q^Û`åhôSŒ§˜_?I|”›¤ȽÏw +r€dØSNŒ–é!Nˆ(À†’R ¶âÁU)òQ4@:rÞËêPNc ++3ÇS¯Ï˜?®PBkxùbho +gy1Û[C +eÆ o@ ^Á0¡áq®¿–.´½6æôóÍ6 +,íŒNO¶”Ò"™ß—eÃï\ ™q×|»QS›&!沧·â›*Álfä÷!¬‡´½¤^Ü{ƒµ~­ÝÆT]ŒÂN 3–>SÜɇ'ÃÆ CB[.&Þnvÿ±„Më´§ìúÊEÂ/ÔRËnXƒ÷Ñ!¨ÓY®Éõ†óPïs·»Â¬)u·)yü>¦ÙÓm»-fÙlemnÂþ\\ð?eɶ§tÒD_µkŒ3löbd¦j`GŸÉYŸ}{Ö^(6 ÑWRŽ¾Ø·™mëÒDC ½Ø:Úl˜ÅuD0E6.¦ + ƒ;‰½B——p®9$yJúGásÅ©ÑÖ±WŒÎ}þœ •ldözÂh2ƒU–Ö:c0›Ñ²´ª&X0ZFeõ÷]'¯vù ¬ù”Æ/äQ®—²ØÛRi³í²O•x•mÁjŽ8£Û{I¹ZóåÔ[×l;°®0¥p=nçãQ§ð‘º”ªV²Å>¦sëõ¬ª§(¼X?t/|H¹ +/· +í…®¤ÛˆŽ}C’ùƒªÕš?0ì ÷¼Þ9™…-LBÆh½òñ½…õ³,†t¤ü`> +hÙ*}B‘øænuƒ"¥9ãb¹F&k–¸È˜iE5ÊÌ×ÄJÑ+M26 +PÜ}o郀%‹¶Ê…w[1+…­eœV ÂÛ ;… +Ù†G²í)ü–ðµ7“:ÖôŠŸ›룋Ff÷½/§¶p0#mNnòÌo$½±3Bš¿¿EÔWš_»=ÖJ®²”3ŠPËÐÐ"{Ú|ùRÐ+û‚QŒu.¼j4ή$,ð¤ªå)«`Ãܵ÷(²nƙ؜HÄ?Ë7rØö³jÞ`ÇÂ-Ž€:=­šâ[® +¶0¸ +Ë°°¦÷:( ·­óXP©´¥†-ªš^[ıԔìqòÀ®©íÞAEm\µƒ +[ýêa7søÕƒv®ìeÏdùeKÈ›™šÒª5´²v(†ÍاåÕ¹Ù?¾"ŽA/ÔÉsôUXpÈGÌ‹µ·b T'P’–¯-ž®qß8 +ÉÀþmÈ`ÏØ*²m×áO‡™P{$}ÖJ+œ“¸M¬>Å’U¹*Í•p5TxpQ—)™‡Ôj›{U}«é(•D‹”'§^¶[å^ÖШªâ +ÊT¦rÞsƒ ì&t‰©hÒÒCÆÿ†4ðõ± Æc¼¨ˆ”43Ô‚ð,`.û eÞ6ö™ÑÕåþÐõ"æÝu„ýª–.M’ÓŒÒjX,¬×í¼ ²7l¹ \^Û:„=Wå öÖÃC1ZÛ±[rE@€âÖ¶}ŠÂÝG€O¯˜¨ÚË“Já2§XÙ[?ÖÕq uë‰4¸UGŽöé5>}ZZÎl‹üŠ"!¤<4hX¡´h‡ý˜ qi³À¹QÛ†sj–`zã³ÚVO3œ( ìªãvúŚܻéþeëTÉ LœÅi™ÞD.³Õ<±À +N—3í™RSü‚ÉÿD©sÁmNÛŽ(8•Á>è›a9FÍÃH…MȽqÞn)Í‚…zh[EÓçáŒ~1•ö¸‘e=fe(¿ªi—®§Eæz•&ô‚™•7Šö›Œ+¦ÞF'š•Ê‡/Rœ*ã8ÓVâÝæD™«eªW9‰×y{¿Û6ùHñðÐ%·CÛh¥ñ¸Æøò,Ý£§ÂFú;.ùƒ®®-”ùúþzç4|Q0òiª$Eiƒ©Øä+Ìzlîe‚v»Àz“Þ_`fZ‰Ö šJé»…jV4—ÞôJa`ž,†m;Ðr$ +ò­ŠTšõüýV..VîÜŠå(Õ)*+…C€}SY^õqÈ)-†Œr“–Ÿ5Z­,T{Œ?£â³RÄÄX]­ ý¤j{ 'µ¤ÉéÂ\´ùäe¹Êûðå¤ÖÖ,_b©*­Å½|ñõ”÷Y™ã™*ÌšdÑTZ_šé¥o.gβ7òd­(¤ ɱ­¡ß³Ü¨HÏKµ^5ºÝQêhB3 vX®ð«8N…£ï®¤xó¬VÌÙôb¹ÖØ da +ÅÞ3Ý­¿÷¢±@Õ¼ÈÒ1§çõU‘TH¥)ô{[1/nXy‰VObš‰\Ô.Š5¼~L²QðTèE +Yö…f¶šš®)Šò—Õ™À}ˆ-z],ùùf ìßÃKƒPÒÈY¢ÞŽ¯•ð»XôÒ”Ñ4kÅ®ó9–6Y×ƼÔÛЕ˜?  à”í² r:ÝF}Dø8·$®'w—ݪ«_Á9Ôì~×Ã;Ôv”˜rØÇœ# +‡­\A¿¶OÓKXø<Œ¡®QÁ|Cãnú`ع>Ⱥ&||36Õˆì„vzµ³)˜¢¥d­r}¨†óiT•éÆ£žTu\ˆ3¾à\;ø^´’;‰nj)©NVš½‚á +¨Ðë'­Â²uYƆºÐC{¦Þbá6ÂÎC¶C¹çpºÐr;~qeÿŒh°uŸè3Xl=î×ÏEñ\ÆI©ˆ’hëÞ˜æNæ§Å³ärqJ+Z­YyuÔüZ ˬÎn‘xÂ(n[Ð&Ÿ Þþ©d`fjÑgÛ3 ˜æFk¼g°Çð|²Ø€i‰Àö‘O¤ zD^øÖN§*=³íýT»½Ž ª"Cxš¡ +MØæuG|Ý}àœ¦yéB“ž÷sx£¿¬œ û.‰Í&¼Ú(»ÞòtÜ[Bcÿd˜z•&òq#DÄ®· +,Äu…RLO]äxV…ïéL¡Ùd'ûõ;&ûùÁ~GýæJïì±··Õ +änf”ûÖØä‚qÝ¿šJõþ™wöëÔ×™nëa®‚ö Öß*ݲe8üð`X®¡{–¥`ýd÷P42l™û£#úxÉÙUÉꚊÄåŒãwfüf%¤Ž§³ïõva£½m›Dœq2ŠmÑsÜn~ÏIë}¼Þƒ£q&£ñ7ÃÇãëtò¸ûvï›x¼÷^o={©y_ºþõ“46ªÁ¼C;Q +f¾Ç:É;dG¨;n¨†Æ­ÕÕ`Ó½~¢Äبœ3÷†j89æôìe£ì +3J÷6?l'ªSåÕ€™ôF5ˆÜ¨ÿ]1Aã榎jà稞“¨ Ç6ªÁLj?Q +‹?Õ`Þ¡oTC{a lsF£ªÁwjÕ r£ÈTC›~&$»f¢ª¨†ÆľÃ`,7¬ÁH˜âœ…J÷†5c·$;a +b8¬Ád™6¬Á´§°ý°DÖLÜÙ ®Ù¨†F°½£Ú ¼+Þ6Жj0Æب#W DmTÕ¨“d:Q +æïFœ·˜°ÙR9ÉÔßP +{6ªÁb¶ Ê +j@ÖBO¬£ÒF5Ø í'ªÁ:¶nTC«~4$û¡"W} Lls£¶O)¿~üF5H=6ªa+3°Rå@5œ ¢a8ªÁDTƒéh=Q +mú:BT¢ªAôF5øB5èð5G5 Ð;Q +m‚쨋EK;ɬKH7H´B{ï{ƒØa'¨ Ë…hœ˜¹A +"7¨ÁwPƒº äÕNPƒ=½oPCã®Ì!«*DÝ®k7Í:¨A 5 òÝ ë›Ó€ñP¹J˜‹|ËÆ44_ÝŒ +€ÝÆ4˜R|¿åÑñ}£¤gÆžëϱ! +Fö€4ˆrDõ¤Á7Ò`¢*'¤ÁÆ×Ú†¦Ýâ'„àÛ‰ih\bï˜û­¦ñi€©¸‰‘@eªQí˜ ”ç‰i@¤¼1 +fˆrÛß2|1F¨ÒÀ¦–ŽiØ‚<ý£ì7¦ÁÆÆ81 +˜lœ˜›ÈÍÀ4˜òßÓ`öª¾a _»6¦&+0 +f¯Ú‰i0õhÓå80 +ŠÓñnLƒ¬“cÂ~9¦Á£cϨqLC(›cšö±¦Á—Ô`Ôz5Ø׌ +j°OÕqóS1NPƒ"®5XßÍ +jPÏnPƒD³ ße£7j-5(ŠqPÃþ`,î¹PÌÇ5 Å‚ÄØ ʼnÔ@Æj°W¬ +j€EÚ äýOPƒ½¡Õ50lÛ †ˆëÔ †@ +@¨oPC„¥54mãä ÔÔ`MË'¨ÁšÞ6¨AÊ(P]ï j°¾ïÅ ƒ\’Î8.Íßßã5@iNPƒ=6oPœÑ5Ø`UmÝ£§ÍÔЭwPƒ‘]¥~Zç\¤ƒt$·ƒXx5gmPŸ +jê ¤Pƒ ªƒZ,$T¥³õX1Ì Ç»VÌ$\Ì@Ö54,û Pòx'¨ÁúznPƒB†5DLá ¿@ ájhÇÂCÌ ›/n&¨é§ +jhS ÀÔ@7»1 +y7¦Á,ý½1 +ñ:¦ÁscdçÓžÀ1 +d¦~dcìÝóÄ44-¸máˆÎEû +‹ÊOLƒù½˜DSÓÐ|™¼ct ºcŒ¼L²O¦ÁtdnLCÓÊTMžM¡Ú‰i0Æ]7¦AÇ¥;¦©°Ó`\Óи}c8\NLƒ¯´1 +6s;IY·Í€yvLƒüa¨…ϺÓ`‹•töÍ £àñ= +V`ZlYLf¹Û6„5¤Ö²¤!lm‹Ðíž'¤Ám-! +~÷‘¤ÅçÒ`ô +Hg÷Ç@¯Zé j|9Vµ:¤a‚4xd HƒG®Du˜=ªÒ€‰Ñ†4 9! +Ö.iv#|S„4ÈJŸ†0ÜÒИèùÒP·1G’æ`d®«rÒ^dÝë¤l·Ëóö‡}R´ÌJÞ_ újt"“4&Øíàþ ¾Žø %*÷˜XŒÌi$ÆV\¦´ö*Ÿ1EƒbÛ-™Ü,ÎÍ´I.#Û•£ÊãÊ;bµdSêå‹j=¸ñe¯JÑé)šƒa†GµðK9.z•‘ôÅ¡ØJIVF?<+ã•ÄHÒ7PûyA½s8ïOÒ4O 0KÓ<…, +újzÖÆ×´‘á“ìþÎÒx¹3&ë^õÄOÒ´¢d‚'i LÊYšV4™¦‰(M´§iŒá–Á»fŽHÓÄûÜiyUiT3å…V¡¶œy+W¦FáÛxïÃÓ4Z+¾ó4&¾Äûon¯¾èup¯Q×»r,†M‹º³”…,ez`Þ´~Ÿ£‚I*ŠFÿ|'ø¥Áúhv<žžcŽ>‰ q³ŒÀð"xAVŸÐ%ŸóCŠïR~ý$x,„õÞŸ“ë`çÚñÜ›”{%-yýØ—Öe­M=çŲܒ6{iGJ7-—ãWFRíÁ®µ@ÃvÊ ðøÒÆc& ²rážårmŒ©q™p9Œct‚z^õÀ©êú¦l ù™6=R2c@Ð×ÖŠ©°ÃšM +øîbô¬Rãºvs#.cj +—×yq{eUzÆÔVÃÁߎÍ/Ð…ÏvØo3fRYmµ­7ÏÀ8Œõ–ŒÙdP¬Dý^¢Gý +sÁF©zrÑ&0ƵÄÛ=£¯…ú#r…0ØCö°Ò|ŒÝ\†‰¦Sê;Ž½ueSO@ƒz±yþúæZúžè-ÔïìΣDÁÜÚšXH½Ï´F‹&¾v“¯ ·Ž*¨yûÔÄòm o±_e!nf+’Í=á¾Ç´È Âòµ˜´Kç}ðÚ9Õ6–=Ϥo¿=y«¬¬ ç»"¡N¿Öå7;·5ÃåâÖ†ñISÐaÇM¬¹ÉÁ­Q¡ßM¯ƒîšãÅõLÊÄïCñ:–ñŬ _°PlN²bi:À2±“sõúƽƒ`'”Ÿ·Œrhñ8´øÖÔ)A +‹Ï¤Tp/ƒ¨µE¾Uh&åØZW 9|7 nnc4$ãó(”Û¥C³Ù¶gip]„óÕÖ5YŽ–w…p°WT÷.-ÐÍwxÂñ 4÷¡£0|ˆék“ŠZ°w>ñ ºq=&c;.`­£Ä3v¼)¨…O/T¢ïžê»!9.ãÇúü"ÑÝTëDù°º£msâ Û”àú³U‰œP´ {Ý$wç.0³ÎSrÄ °‚hÓ +3FGLZb¦JÚ€1ÂÚ'ć¶¢*Ž×XrÖ7ØYóÁJ¦kt&õJëýI'©(g3R C Ú.D[\žØ!¤GöÏUýОê ,ÖΛPÇ–®ñ<ÖÁXC航‚¢EθŽ{l'€–~b ßJáGÿ…a{gôëƒCYâ¡ß;Þå®êÚ>ÅzãÆï‚Ç”P'QlV0úN.ÚÜÜãè<ƒftU¤µ7BUE}hëÔ9w³½å™hÙ+<˜í=Qå>äø8@oœ&W¶9‹5þÞswû¶;fî?Þ3íº iîf ‘È]Rq–l¦}kOÎa]{¦@ëŠ +`÷\¨5#6Âø¦HØ_ƒ·ý« r×¾+qOï1+“ÞôðÌb´(M{šµ7õÆ‚åüûq0,‰d$ óÂæܽíú&ümo¨y]à°ÁºË‚û\#(À78­Ÿiü^„x¸öGó—{bQMÛ$þÁȃX¿Ýl,Ÿ’6øx½éhǪ·}úÎ0ñmú½©Ú§»wÏèé»çðvöë¥Ö}|éø×O²x„<4ð¼ÀŒU!' á`p‹S@ÀÚ7†õkV+îùÁÝã½Îøý½)ØÃßcAεFŠˆ1FŠ¡bÃÈ‘£YpI“[¿Ë,µÂ +Ë5WlÚ8¾5å|:÷Waâfœ[#m92ö6+ždid’V'Q¹=yx–¸ =ƒ·®§{zÇ+$Í +;{Œ$Ý©³–î· þlö~þƒ +ٕמfYÚ”›´s„Xlg¥B¾1¨ÃËT?0ZCUJ{¿+Vûã{»{4õΘºAÁM4Ùô¡zNÈ"°rÞÈáÀ誇Oã¹ñ”õ¼Ç±Ø ÿÎ|§¦ÃQ)KÿýŠ¬8öÅW™;ßÒ+)­mKl‡öjE|07Ù¹´M¢‡çªO;Ѿ¯¦r¬4HšxÚÝv96Ì„ÛêmS‹¬ {B[œñe¤{®†-„ÓÉ k{¦ñ^àÃýyÿ~ápeKrñÖÐ3m€(`M½f*p`ˆÜ쌃b¼Î‹Z VOr„XâUÀ‚óGï±Ô¼ÔˆŠ¤¬Ãi=t„À»AylL +B³3z$f©Ï¢'n!½¨ßÉOÀžÏv b°xä„kËÉ-ë™Ìy€Ÿ4MÑ×ɈVŒY¾1èkqçûíÛžÏ]èÒçn†M¯T2ÊÒÞ™ÿaj`¬O@—Ù°…“•KyåªÆ’¹ö_UÔ3pøXÄ8nÞ*XòÕóŽ)™5ì ™8fnu7“UO'Çó‡ +6þz€ivÓ¸^´|hFĻΠdénGÉÅÃÙmñò€Í•*ò:ÿ{ ¢ªþp0¬,O¬˜ËÄ5ôöTžrh°iñ9ÍMœnü®z‘mì]U¡}‡$øîèi¶ì ™£=õ>%Ó{§3…²_n«¢e2A+Ro2A!ˆ¸À³Q¼Û»%ž¢ôuö©µlËÁ›þƒ~]Ïx6Ò±¿Á˜ÝÃ4ëÈ4÷ï^v\Nf +Ðub¦(…XRÜb ¶W—ŸèØ\K¡IÇ_­ÏB'.S+ª¾0"sú÷üÀ «ö×îêá׆ଠÃrYðW¦Ž +Ýé?NÛz"§íú _…“¡Q±ôßM[ÜŽ»)<9Œü›ÇŒuM3ü•»UÖЭ¿@Õ¢›~¢ùý«ÕÏx«Üzîõrô~«uŒ·((kïë ±ub܉-]âÁwUðV;( Tˆ VsI½âc +ˆþ©~'?[O>2ײûíyë]¬ýÚá¹JÌ‚ðŒ³ ÒÒз +\›õñ`4šÒ±µù¤¹æ£aFkéêRý¹†ãjßv<À:¼ê‡èØ©`1È@ìkŸ½œ±§¾+Žè­h¦ø¤±äßZÖ´BÀ†ÄI[Âf&\Ìb‘±­3–®TžÆL†òµ‡÷ä‡Ù|+ueä.Ægů6Õ°;¹ý)V+·ýÒ÷4˜ëLùÿ}%§ÿ½º¿‘†Ià)[–O»( Íܹ•;áÄ<§çM %°{ +°Ê6a ¥“xlîî?È´õ +0ÞÞ|ƒ+í ÍBü!¶ˆ!d‚µ|ôÄþw–\ÐB’›Ìfc ¬&l-ÈõÞÕÓ5@‚˜Ðbý¸Pìƒ×a- š?SÜÓ ÐJR HlÂmÛ’Êk¢j ºð( £Fq48V8`Y€é•-“54Vð¸Ì6]®X0¨‹AgÖñ’ä1›ß™Ï¢:_]qíFOÙÚjѶ"%W2äf¯Þx†¾^[%mJÒmÉcbñ3/ž›³Žo žmj9áôís‰Ë¯<6õÎj…¥´•–¡öO9”´ôv$­ö°ÝžµÑ§i*mƒ$pÈç'‰ýº¬í\KòýD%®D ¯fÀµuÑaŒtýáÕt°MÙM›1ª5÷/8‘(m·Ü[ ·f¨¸Ž‹Õðj‚Çî!uzµÊM¯·[«ÜÏÚ_Û(;5)(ºµM›Ùw­í'Óù{á¼Iôdj¯»5ÿ¹5ÿT¿QýOU/%¢sÕƒ™0ߣ¯×]N`taç›"Ù™3 + +€èA›QmQãWÚR¼vDJÜðmí#­ƒþý­ O£Ü\SµKD¶,5cgyœ2m_™DÚuêÎS\†Èë¤ùEçMý@ÛÀÇ¡43õ7E}oÎ/èž>ÊoK®™D4sÈí-”ë¾+ GmÓܸ$Ñ 0ÑkSNóÖ¦=KæùÆ@÷Ò¾[{qC 6ý¥Ü)ÞÛ”µöuж}Ⱦ±öÒœ‘s|ù[31jPæ~ùÅÍ~æI"úЗiÜY™ÃÔc£äˆþC‹Þzz+v ,»ÃaÛ¢ÃÍò 18i$kŠç†9ÑãFöîŸ *zÜÅ·k«uŒ»{ÜßÊNõeí}4 ?q'¶lÞOfÀ¯µxc·Èün/‡ÿþÄñ©ºSý ÇF/Y”³{°ôöñÞ¿?v9`µæ`þýp:õ0i=ÅnƒÉd@q8d›-hÍ +:a­MAœ£àWƒCðN +Üe¨Fã™WöÖJ0{f‘H²ª"o‚¦{áLè6ËÀKBXØlµs?ÙQÜM|Éáq³ˆ?6œŠ]½@J²ôDÈÂÑ×ßùc÷§Qï½ûâÑ +û=$ië°9üAbæг:;e8®ÆS3´ËBã™öéU’ÌçcKµæ¡0dJèLç±yq~J7ᎌ…q„Rt cŠÆµþ«¥§ž¸ô†0G¸‘ΰžÁ "örÜ„ä(‘J…–ƒº²d÷„}éœ0&ny‚~(@«µá†¹K•i‚—Yj¯9Ý嘻­Ì"ÍíP¦Áe©ì„ËIöõ?kª#h6ñi¶Â-8\ã”ÊBAÈû¢ìoÊðƒv`ÓŽ–ݯOÙ¹ŸÝ4ý²°_i:ökßž~Óô›|_¿¿6àוòô£ÛY8]Ôaæv…ÑÃßÆ:*ã<ÎXÂ/кÁŠ)/¨„gÍ·+¬ÿI[~8¯8â›k Œc¥crh‹ºÑ +K‰eÌ|x&xÑ +ÍöÁùöH.•xâ½QtƽY¼´è\öÍ$m¸`|N•¿QÿÂwë wÖÃÐWw{»¢¦ã +°hj@Æò®¸Õwwöž8I.O +†A.|”¤Õ?}è#㢳ɶ¤l´„)—í’”‹¥ó¶KÚ"2nÏrH¹èˆ“ã +v¿K¹tH¹ ©B.ic 7X.Uô¥;øÑûÍ™¸2&ÕÛòxÓ)ã¯âzD¨uê°$8=Ý8Í¢f#qœ£Ÿ'À2š¾UhL¶8?Ë +Y\`Œ6¶=«<î°x•;î+°«Œèed»kXaÞ`X;4Ê*P¶:]ŽÌæÂöµ8~{ [ŸnGÐ0,i´Å± 3iÖÒŒƒ#µRF„ + +a{,å`°O7§°‡ÎJÕ\|é’ +Ê/Y—„ŸøíY‚œGg `Œ:Þ~ïMªaž¤ƒ®©:¼£Ð§$gdšÔ¶¾ª4:ìtê!…Æb+¶:SäÔ_PbœÁgX#gâ€ûd)Éæ$=sâ;3ª²ñÄ,¬:êF£²–àˆE¨ÀèL:j…HîcŒ’%b3 5É'zVí‘p=kÔ [G@ÙÐÚôÁè9¤T.O.u„æˆØ6ƨ=4â›;6å¶>Lœ‹ã§O(£ù+ÜGx+¸™)èÉ®¬ŒZ’ ü}zdÞí/ë¢ùê¡ 3‡øvÚ*6åÌïçÇÙ +ÌCE+3¡knŠŠ§'îZxð\<2käî·fi†·++ÄòvgP㌟?×L›Ÿ\ø/ý—ÞŒ ({pœ‚]Rå9?h.FÆ”5¬3ÚÙÉ­;ÆçL1`Wx +è °ÿÞnä @fÛƯÝRR‡½Çúü +”Fë¹i¬ñœc6 ƒ­¥ÂÚÀƒí"LCÒù©°“WõpŒ›¶ïà$ R8Œ9Û¥p}N6»ÞÏOw7à]µÅâÞ06¸!H:Ëût3AG1?5:é'¦üȶ¶rœ~bò ÄĘM#ܵ,`à#‹nÀfɧU6ë]­¨ óÍwüý89è/£-¢Áh“g‡uc”`—M¢!cÀé0tbÖæ-îð)NTç¥+äÒ–†câfÆûµ*蚎yYÈ(zÐôµj"W¥ž2WPW§·æl¼dÛ^3-à•oÅTE­‚êp6iŽ-ðDÈ—I×FKÄÍXЪ‘d»ÕÑ°7é¤A•BÙ–¯ƒŸ:ïå6åzÊš1Xÿj¬ZúfË´À•úÏšð¢»=^dàP\Ã=Úqp äÚ ñkè´Ûjï‰gñ|ñméWë= œÈXC§7ÐÕ¬hÞRýXb]ÀBZøY¹À +ù0N--ˆsÏ‚Ù­ŒzP£t%i×Õ¥½<÷[ÂÖF+:'1È`3@Y´l -­uï”G2Ö°º-§–uýBùÂqÜ%ÅΦÞ؇Íœ²IwvA¹kM3¤ÒÖvÖ4³þ¦jÛÌYwÜEm³s M‰¾Òµ-\øRH`maÔyEu‡Œ¦±²¿¶ª‚·¤º9¦õ~Z=r66 +ª^šØ.›t5oWáÀÑ—XÌæHò,–fàX»h½QxCžrš +Í2Œ‰ú|é­mZ.Ï  '=è™É¡‚Ý7N¥æb¼£S'}¤Ð@KMâ˜Üñõ–?Ép¬\ž»xVl¢· x¡ÑŒÿf|{ÓÒÎ…SZŒ´ÙH³ˆ&e úEËDøPÒ¹9)ÝBøwÞÕÑÇTÇ©aÐe 'fÔ¼£!²6Â"Z¬ÛtM®Àαs@Û_3#¨ºHçÍÎl·_`y +•[Ф¾€Ç!)ýmýz»¢5]2iPkÓ¦÷/23÷­¡Èã@@7j¼i +hN Lf´É·T ¹›'@Ä©¼}†í@µØYì_"Ç@·*Ï!Ú}’µœÎø#†æØß>Ž ÞôBCAõ–•ëÀš+VI˜Ä@³UøˆêÝ=>Y"%iPJȃiy[hÊRìÔ(ÔÄ+Ü=5ÅÑÛ*)žpéÞÔ­Jý\ƒN›VKËÔÈKlYêÇHìšy‘~…'ÝW4î@†gJQVU³†Ë¹ê%RÚcÓ0àÐ îÒC34šqt +tC_f(èÆ"í§rE²YA2dÚdtä_ŒãëíŠÞ‹¢9ì/g»U.và˜ð!s½©ÒV¬Ÿ”Ï I‚žØí×0)DoÇNœ´vÒ…¢7ÎÐäÇv&7M@§õ3ºŽÓ¿æ´gt¯ÙÊÅõür–¦]ò¯gJ +mm“Ñ]¾DźÛþ|³(N+sCŸ˜¤ÅiEÌ\Ò’¿ñ ¦Ï}ÌÑ^F79¬¤;´ÑW8¤)å¢6=#´‡VÃ$‰GEY“t×ÅG¼REìÁ4-ÌG¢¨˜”C }zšÁ0‹Ûá +wØËÁwä›È†œìZYmXëú¬”Bp4årÍس2Ó8;~qE,ö—-Ë›ƒ¦UM¦ _ÜN5·†4™;ƒÂçÒwÔ:øu´Ìí2gs¬v·§ºù7?‡·ÒYxÿ•ÃA•»fÙ4)©»²âŸ´S\’¸3ÞiIÅä³ÈC~rµÛZÄåAß*}'áô©=Ωү©Xh£±[š´Þ¢aĈ’ÚÄþC³né´Çä+jf&mXH&R4Wú#-®÷ì‡uÅØé-iÁŒ×ªaæ¨Æ<ÇúÌÔ¥†®#VÈ8tÃ%ed¸qI®pÏã}IÁÊÎs +h†íË£ž¬µ|‹g…ÍPGR!…’§ +N$ ²­ù‰©>(i^çqêZ#Ž2›cK 1™ƒ=-Øð/f¤í£'ÿ"Ÿ£b0—7û€N¼Ë6 /°|Öë—´¢'†`'Z ~“%ÈìÉ¿œ_rªÑí+œ…­˜‰µ:,¢¡³î7‹˜—*’Ö›Éå…|šKÐM| LBá.JÇïC½>p`“ÔC2o†‚Ò#,J(ÜÓŸY`J:G?Îa‹0™1xÒ”R%ÞâcÛöå-œ·­ +ZÝ€ƒ6cúDîàhu÷³HËÁÇG¤˜“NuøÀ¼>Ïô^¦UãÔñ:O>ñaçÜ[Ç 0É0(]äòT8²âd±òäl‹;ÊÑ%-¥iȤÙCp~èPA*ñ‹RQ=—‚Œ­h›ƒîÊK©„‰Í)AûÜPÉ,±5Ç¡øÜ¡…EV¬Ç-U‘ j†M”¿*püÙfJ +u–îÀî0ŸBÁzr7Ÿ!¤èBSWÕ’´Óë ¨”}jNÌ@oÝ1¨l ¥ +c×ÆÐ*0±3IŽ›+èPƒ”–Öªž4!2PxöÆÔõÆ—»)Ö¸Ô@DÏ°q2uØoûÉÊhZÿj¨"B]ŠÞÅþ³*bÊ–èEÊØSõˆ_€ª‘·TöÜŒR^òsÁàUlZâ·ýÄáîH¼Í^¾9¿¿7ÈÚ8ÙûlÒù÷cs¹mA?ì’åì4•éó\ôð$ŒÞÍ„0vÔÑAºÊÌEjaT¥ó +¬ê·ÎÃF¶f.-}ºÛZ,žM”ì¼Ù¥ PdGJ˜#œö²%²<Ñ'{Þšè휠ÿ!žË'_ðºS6e‘ÂÃä`¯%ŸHíÞ#ÐVȪuþ‰ûÚ't4 +ÛýøŒØ¯¦*ª(ÚxéðTt‚2Mâv¥ç å …Öñ•’b½g1ÅÂÆBQÖ:Ôñ,¾)ûb²ê;‰kt«ãÍQð”ŒîŒq„)'­’@p¶Õ}s\Øxi+ÌÍ»x¹`“EŸ2™ðG2°ô¨"ÈÄî4/»‹7aù†ÑI­PƱ0·ß3%8UQhp¿-Ú\Kº$ÁªZ‡ÂT~‹!ñŒ,»Ë¤†R'ªØ4*: kÍ&zqŇ°„ú•‹Kq¯ÉÈdSÒåž×£¯òMÒêa4¨ð KJS¬€®þM×1þy´+ìC{“ÌDÖƒÞ&Æü:É+LÑŠ_ͧÍËwàÔ9£Ë"Üî² Pá¬jòŸ!'«jMˆd +:ÙrÈ8Õ›Ÿ&8Ò‰ >¿ÒwŠ @ïOÊËÎÂi[ZU jÊ£&Ú’Våq‡þ«=dêiÂ>õòÖnÒÆ›½4´˜ÊMðvAß R^Á¢Ï\„\É#‘d”éŽiëJúÚæ.°];Á€f~(kÄnMÅJݸ9¦,†pwa /}÷­˜ÐÖä¢Ó’ híêæ· +¯ bªV]>Ñ÷L>³˜•o½•¸‘9µÎWTÔ¯¨Ã+óÁ®TÿŒ[|îk»½;Š}# yÊ\º^3§ Ì˳¿™ +]h8°j>±c^Þ×Rýª±¿5Áªâ݆ÇÁVõ3-oÒÜ{Ëç1¥Êj@È–ë¸äæVóxÃM‘•æð&ÍHQÅ +@oˆ‡e<±Â_-žqÚÜúœŽ‚¸æ®',]ÞoM*¡(Çh†æ}ïÄÏÜpz^úüûqr2q»ECÅû2é¿*ÿöíY> +zát½¦…M%höxopÆi +¬—ô‚2Š1áuLÄLB(FDdô V¨rbœY4›ë´^ÄH¹¿ÓÓÇ9Ž• z–ëQèò|–nóY»”ŽØµyªN]Vg§xe’±/a¢Rº‰Âršì*΃çš:£T-¯kê\ÛvÜ6n7)mÎý:®¸ÃÌ‚~+^O!À;‚ƒ’ê¡4‰Û;|Õ«ŸuM°R¥õ ¤ckd‹»¶õ÷õm–_u~/úÜ4Ó–ûåAlÄÙnŠ†Tª×™>çXÂ'Xë›:}¿¥àíhCa37Í@€ F›àO¸k¼Ë@P­€NS¯“‡ŒÎ€Öð*ÙèS£¾x{D‘­Û/Éʺ »·ÙÈ7qPjU³Êáõ…ƒ“ý!*^¥z¼TÅ+PL§£ÕCÃß¿k„zù§ï+–ç31ŠÞów°swÚÆUÝï´ÛcÉnÔÜk<¢cÕH¼¡{…8áNÕÙyÚþŽíeýK•Š ùìG/ÁÇK˜XQ+j ñØÈwaü, VM³5¦;ÿ~8'f™UZMªp“C`ìè©Ñ=Q7zT Œ +Å=ô"²Í,÷º9ótì­-÷¥éƒcY‘F­#È#a{vÜVxŽIüîPEe­:‚8+¯À&Ò!|Ãõ&1«—ð|{BS7Iï5°~,TÞ‰ÌItýd*ì‹((²þöq?NÖ€xÁ×£ž®(Çòj.®¸e;TM5Ñ;±¥M-u?ÝUÛL¸Ú§6Õ'Q}´SÝTDv÷6¸y%fø s€cZèÀ‘ÕªƒrÞ—Ì€sª‹ªk¼Ž›ñăÁ°o¦&˜ºÆÖ„Í¡¿š8dMš1{Hˆ³xvi @vùeÞï“#bÎ…t½¾çRTŸÆíá%\&¦#ÒLlâØ3×Ý·¹œ^·«ÂÅ=‘ Áª"¿Õ#Ã:”†Öº^_õêg]{̃­6@¸ÄÜÕ_Œ%Ê>ò[Á‰X»YluÆ%ΑKÓM?q<%§wŸ8ÏoÍ1 ÷KÚãÊp›Sß(“y†òEô)XË`M¢O¬ôH:¦£¶Æ; ÞâüùâœY±¦¬ìa$PèSÈ, +«„9|FÁ6Bo°e¹ð>é­’Ž +ý"&õãŠÊÍ!;4õøÖ!PVü·}5€¤“w|¼ϸÞ`qöHì«ÊÓnmû´êIlvmë9R!ƒ,32e)ÆK¡ñv vå5º·ÝOFWáì/ìÓ& ¥­U5Fú ©]ü%äl¿ñg+Fp¢À¦´Ö[aöÄAãª_(!lRÝõzIÊÐ.ît +ø¦ÉÒöƒÉk·Äô7¥·¶%`¨:ˆ l4À/’NJýøkîþ^l„ÍÉ©m¶’IÚ¶hΠ¨pB\Ò˜`´· +y•%ÜZ’sKúi +¡e¬;lËñTßè­>Îq¬»X‘(Á‡WŒg½%s8C˜Ò(t aSIã{z«€{7îyÔ0YŽ‰¿S:×xæ’qn>sœR†\Áxý¨¿€AT %ú+Ç»¢9'¡r"Ž=É9¬ÃcgÛÝ´=Ø0š,»‡FSà[ø°XÂøÈZB[ø¸YŽæ¹ÇqAR32ÖŽ“.p@D¾tNt\óhuï[zG”ŽÓ7òž¯ÍÑF6x‚|lòEÀÐÌGϧL™ù%œCßÜ;c†‰Ì»ßŒlì' n:ð\ºÃÆAgA ŽßŠ³t\‚8Cž1ëàkëN>­}â¨]X}eâšì'Ôv:Êâx#œC@Š¡%^¡7Š©¯ÍÚV)J“õYTì±lZÛù±(Åtƒ/µ‹_C„×-iØW–6%õȇ‚_‚íïí7^˜þÀŸN Œ}  èEE‚QÔlÓi]Ðu‹s¸=Mâ¡ÇÃ! ؇D^†¬±*ûKzœuŸž¥¬õöfq@X,ÆVݲ¡µïïÂi(úð1d0Ù +il ¿ëÀõ/Ã0:‚ûÊb ppXý³9¹1Г& +ñ ™i]ÊAQ8þÍè™a5z Y½Dˆdp3œË–›ÌýÍ ¶Ò1Wž$§åE„ͬÒâD4T`sÕùpÇX­*ù%2¬còŸH!³à”PYlÇÃ=zÑLÝu»}Hâ;çÇNzÉâð4ÐÐl6u‹+`%µx€£Y‡#ª·_›C™‘ÈU.ƃc-ë ö’[vE$•»RÒÇçwnðn1`!Y¦¬Ÿ á½?dÊ|EÚt‡¬8y}á•ir„­q™VǬ} [dïÕ`©8£ÜÞ#Híea¤©Â{  4ÖrŽÔ«ð÷•0ÜÓqT¨5›å-„^U]Q³ XX¬ŽV:¶)+DÆr2ÃTéÛ‰?)a‹ÌKòªÓR*Ö…B±“ NZ¾ß9!éß? â_hÐúöƒC¼¬NA€¯Jºcó,0¨¹»S†£çÃÙLÍERŽÉ|\:ì¡‚^aÉ¡#ÞÒ)$÷w@™´›ÍÁA|BRt—¥Xͧ~l~Ür)ZqŠ‡–”Un|;ÖMaËÄJ§®!—¡ÝØ {ÃS8¬Ç IŒI·p+»E` +]}g:N\¸é$„6ùˆ$œÛP꣌³®£Ôx¤ºÝŽB˜ýŠi‹aÝPåµN´Af´J#”)Â’v0»ð(gÀ…ù¦qÎú·ÊCe­" +eß1.Yö‰®îÒ}…uVï§7):Ã:®èÊudeÒ\$:à%ØÜi'Ã95¥¡€ñéšPgwÕvE~ó&%¬à-mîLOé_½Ii1'§7±–ßmûŠ¢øp{;_b¬ãŠÊxÑŽ~Ãæv•ið³Ãý’›Q8ƒ"ºu‡bjaê§â0Ö`ŠòŽÜšÖ8ãÉ~=§ +<™ºÙcú‚`¾ŠÃÕÕyìñ\”®òñ^t&ù¡šÜVœkËT6¥x<6§ô9º)AYÙ* Ù.·l4 ßF7Ñþ½æöˆî\®‹Ó‰²¿Y -¹g%•»œ²Óö*rd¯¹##÷e5šY;žÙaæJsmk RlCPC­#éƒ)¸25`G¨‡}챆Ù}æJ{ÀqjJÒC Ýbw–ãq.ïèxT™Jªs)ó+@rÎ:qé +@Š=¹ß1X^~Û¥\}Å`RݪÏG´PtŒ·h¶”ŽÖ—ßy)Ü25#e÷ðœ[ÝÚ¢€®ó>ôNsªE„CŽò€ç¼ä›q/A÷cr&¶«ÛôÀè4OJÙÔ¾Ro·ýÁúáK ¬v8 +ƒ¦­$¼>ˆ£YoW¸ÏgÕ鹃›Ìz´Š;Ɇ+©é«ÇÆgùp%°Rr®Ä°fš>É•Ôä¹â.x•ûzglÃvp¸ó¢å—vE£¦ÈÖÎø®ip_bß¾]‡‘>i+±ÞœÇ¶áÒ:<‰Ëc{“XkÛ“˜DSÛž¤ÊcnOÂÝß\ ’¶+©:rÕ]‰íp7NOb +SÆŒž¤êX=÷öi³ž¤fM üŠô©‰‹ïvÇÙÒîn] 7â:÷#U9çð#ƨýp$¦Xéð$Ä9mGTdÝŽH©´MvÅa®×áG h)ƒ GbÚžŽì?v +œoŠY"ò¦#q‘Ê‘h¯ÀÑÔ~ga=Z…üÞGòmdïíõþul©mмË÷îz[çfTÒpY¯Cõ¹ÞÖðƉ¼Â鸊s{½¸B›ÌÄ[ûë%¸¶=€ŽÚ`%œüvÇìS*ßaSÚ;ìáKpd^Š4ƒ†…vØ‹ª¶ÏÃ|‹}†4Ô9](Eí°ùGî°Qï¹5EÂ1šwd©hW$¾ÜzòøÍãÏÊxÎHû•C$å0žØaoÛNî°wª¨vØÛ¶“;ìmÛ9¢ðæ¶Sóÿ0ž#ÂrÏwÕ:÷U;Õms8Äg„†Tý©M qm°§1þáìí!>}vpo‡øŒÌ6SÝÚ_ïã+ŠJãÜ`oñ-#u 6ØçØP­°;œ>gs°©6ØSªãŠ +ö¨Œ9T‡Cií°‡¤L +ö`N‡ë6ØCUã^±ÁÍþŒ +öŽ<6Ø‹T‘6Ø‹JÆÍÛªÏÈnFVÏ¡ÿ¬Äf,j™b3œGtåNŸ­”©qüèZh‡1pÖ«v&MSG²Ú>¹~‹›è +ŽÎ¨Ç²&rü VËÚ‘ƒervÌ­vòI£PÏg8ÖÂ×Ä–¥ž4;0Z`žJJúÅ:³NææX->®¨uë[_BTLžtªÍ"x¼g£¡ +ºÇ×WUí¼ ”þyСŸmÊÝ$ +O7 +»@}cß+M”š'÷æÐæññˆï›MºAŸ¬ÊxoMÀ_ÂÃ`›Éé@ì:¤C±Ñýf¬ +Ìåǧ?¡ [e¢Ñã XK¢L’8OèèYngÔuÒpE÷¼$éBAbosøØ©2m-i|pÎ@ñ‚ƒ/²³Oà +×AÑëñ^n`ôÚ°‚Ó…c™¤kv Ç Þ’îv\Ò>ý‰@….Ñ +`¢½yŵrqv°žà´+sÌT`Šìá@JÅ·Í|©i45–'C¡eMÐ +œb—?¿we¶jh¨ <¦N¨vœ’ÒÛñb³¬õ&å‚)Œ¯•ã×[P«þîZýV3g xxr¦Ÿ’rÚ`'ye½qk +TÖ]—ï3áúnC^»n`a©ðý$.O<ÄZÀE½ö8¤â3ò´á5™Œ@‡'/B1à;šv;hád‚Óf-˜±A€ùwN À¢Gƒ”jÓA9…Xœºu®rU«Í4®} ;Žô rÂOÐV‰Å`•õÍ5t´yF¬Â˜°Ï1> B£éhz¤ + sÓ6Áø”Cz yÔ°âBï|¢ŒP‹€)çT@%¤(Sj x+6¡cì8B²yu)KÿrùF[Ô ‚l“ $¦)>!5<ѹr^‡Mzèȼ¼‘ÔÉ;î@4Ä{;ÈeÍ©zjkÍ÷ +Hš¯àP¦¢[8„;QVöR¢ôˆ&•Õ ÀÊ 8ÎʘLF=>lDIÄŽKðÑã]ʬŠñ³rpï +Ìàl4æ®ÝGÈiØ<8˜m]éX­¯e~±Ö +d•0Ž0°f«<Ó˜d²O³ç8ûôL`‡4¦E·…Òœ4–¯Ì‹>BZ[…jT†Œ L.$Ç“Óàß97@kÉ©²N;?¿³l±`Ó-ú8¢T®i5¾¥‡d¶QË—\Ó‡§¿WGfØþª´m쮵ï4”—íE7á/w>‚Î\Ó*èÌ<ŒZªX^|éM”Ž[qE€ +ñ‚Ô]DdAµh%Ÿµ3P]Ñ2Ð̹èÔúÐ +7Jšû'i¬ÀEdžÛñÏ7Ò+ÚÎqaÿþa ©Ñ4p³5œH1ö•˜ò|¬¬ú«vչд¨ê«±£µW³É ©4ý +À”i,°ø6júÆhÊEvöŸ ¨ž##}ëw·ÊC»nk±JŠÔT˜iå¶íp¼êÅZ¼•»¯D€Ø5"btáoŽÏlC…k¡Z” FPdO +1º¨¤¿#›%£¨ß—¬¾f±0F .€°èg²>¿|¾‚îµL<–ÞýLýt…{"0hIA#<‡(Ö.räù ‚¬·ô€Þpüî+šúŽ†v~ªëÌ”è%Uw¸Ï+ê=§ÝÒ8§.a,né„vP¢.wŸÞ8RÆ8Y‹›zæDÕ×”fµ+”™j‚97Ô³LA.²\ýÆC–dU6 IrÓTÁèºOM l…#&¨VáƒÉt0îê ýälLj³œ$ƒxá e,L¹µ±ðÖœÈ7GöÔwEZ +7±7N^13Á‘öRϤ°xo¢Iý\‡uÙÎbLÍz¢Äë0â3"K7⓱Ҿ€3T‘ÉjÕÐŒ¼jÂ1ÂBãÄC`È"«êජ‚¤1¦º ¸xÇE¨9#÷àd¢Ö±ÉdB«é<Ú­l;6™Î261°…b +»¢ùûpk@ªµ*Õü+‰ônÿ¦ñæˆÒ «Àüþ Ó}ÊBi8~¤ôPH˜ÊÒCgåG¬8_O?R4a—);J’1$B>üˆí_3ÒáHŠkáH Ì Ñ GRjŒÞ¤r¾pG‚TAþÜ‘”6ŽÄp²"r$¥î¼Áän†èI‚žäà°{´ ´{øÙnÞ.Åït%Võ¿s¸ŠÒÔJw%¥iZ¢ßû§®N¸Û“Xÿ>È9ǃ*ˆçE +«ÿ’Òx š!R4 t´”Ų˧Š)±kgÌe½óWè¯àQÌÒ⌊g²ï +åÊIû±=9‘€Ë#SËDõé}Ñ*¨æG—.îáo4d¾" |ï†z0…­ÊA8"Xp<†ÌÄÖ(çÀ%m¥Åe¬Ö¬ôx™˜)—?Ë›Þ&f„}Æî6T%1)ØßßUíöKa2ÆSÚŽ“‰”v0"½ŠúN¹Ï”vÕz@OiV£¾¥´±EÒG¤´ +zÑŽ”6¡Û[>²Â[W­æðœ¶áSò™Ó®XÅñp¶"#¬œöA+§æ´í õÌi2ã~Ëiãrä´ut$D]‰H ëXÂâá§_áÏ„û1 R{KióXT¾ƒ{Å`ËKòtZä´+Ú)mkÉ<’€Òh‹2¸öbß)íš¼RÔ¶ŽîŒ”v¨E¤´ƒ)m>I“9/á´”œ|¨‡ëmC|j ó@ì4å« +±3ÞSÚ•Õ‹}I–“kÐq«£Î€-êdOiÂöám§"âÝ ?Í“9ß¾£D®e̸)u‚(ÂèûÈg›âä·|6U>›ê^ÔûUУ°Ü5Ž™ªøù&egÔ÷¦×Ïzq€‚þõTÆ¡6Ròyæ&dç +ò*±Ã‚v•8`A–û†ùxÞ®*¿‚ô»ãbNˆ37’¯c‚~$¨ioQ‡ízh@‚šN¼pHP:1ílÉ>A3“ƒÖñ>¦å8tÓûêupÑ7 ò\· AfTöwÜŠ Šo—‰¾ +#LÐq0A4*&!Øyê&ƒÅ˜ s8ÚÝÄëynê¤Ñ˜ ”'ÚÆ)wþÚ˜ ›ÑævhB鯊õ9”mè0ÇÙ4š4#b÷‘á  ‹`Z(ÈÒÅ«(Èšw¸¡æ·B5¯¬8*(‚?ytè  `!©ÔxŠs@~¬«ôVÍÁªGq:t€‚ Ž¡;œ-©S(ƒ3µá¶-@AMÇÂ8(ÈE%3Òж(œ¥¶AAniö·ÇŒÔAAMO×uúÖM§ÔÖî‘›‡c¢¡@зvcØtÓ~ +¶5‹'*P¢û†òD·†˜/M·À³‰#8Éà=U +'å¶É¥lo²³% Ê(‡f{2æ† »K¸$gŠv LœyŠ|}ÄI8qAƒÁ#uÖ Æ†>õE´…¢á1’6ÉÌ©¿Ñþíà0"ëÚ3£(äJ`†l!XœÃ´<äªk#€WÃûì»´©Ûþt€`ÅÄ +‡×Vn’ųa_jéär@SÆ{ÆáIõ +kÅt¬ÎÔ¾z­rS×p6,&dZBž!è­ë’¾à^ÍC3?ˆêzkòÏGS¼Þšk{¡R}P±¸Ó» +ÃÝsî×´ŠÏ€S4N£ÆevZí]êÔ®`¼6l(.ÑáK@!ð”$\ƒ©½6–Ë¢ŽÁvZ<ÒûAŸ*äœ!%› +v±Ý$N¦»bTë%•jÈ£¿\£CæÖ?åÕ7¾AŽ«úöŠ‰ëá«¿¨µQf²Ÿ¥Øtxê:„;ŽwÆëGÝ *fZjEIyW´àØqÈÎÜ;\7¼>Ñ]ƒ¨tâú±(mÛ”û”V‚žò`tÕ®4`è±+?j ™“ k•îÈ6q`³²ÖÀk¡Â=OÒ6„{m†öìÌ¿›XPüÎþ•Þ©ÆJ²‹„' pb6m¾eŽç±ÛFqÎõØ!³›Xˆz³'Œ¦ž;–àv‚mdS†l—0ÀÄ¿B7ÓO½ºW0 “¡Õ7!$Ԅ⣚çhŠ*Þý©½e—î ^dœ–ð:8<²„šP“©nóÏÔõ8ê(»9òþ¨j#Fí_Rµ‘hÆþúÿ({“$Ir%ml杻 °Ä0˜8×$"ÅZd-È +¯O×oPÀ3£ÿ~-µÈ‚†¹…ÎCˆyô¯øÆøp®ÍS•VsÑ\µYE8WÓøÂôà +wR(‡—Í5üÚŒ<ÕÚæXiQ†¶¥çy#Ü–Üahq êRÆU5´ùÞØGØœ‰)¸¨²„?#†z-ÝÏ»(*ˆÐi—¢‚ ¡Ã¶Óä\@US~tOoæ>á{oñ,âÂtÄÆ-²×ü‹÷`IêŒ !ó½Ì¯£¦ÇÅÃåÜŠŠ¦|BìüöÈsÁ8ã!oº•@~ ƒ‚<)Å\ZgìÕ7 Zƒ&$é€â3ðFØra¿ù c Éà ‘^‰"›¹vûû€àÌœ[^J‚> ,ð„\ŠßT´·…ª»@±×?h3è—‚€†W‡*ÚUÀA°r1Ã$ÌSS ‘DÙ#:é;X|ŠOªª´Î‰Gµ‚f ¤¸E#êP塇 ›.“‚Ðèrp1&¥¨Äø³TQÆþL ²É«ÓKU¯äRÛð´!†SPˆCÝr ¶¦|ˆ5KTq?°ü¬NŽþˆ7>Žî€%âÏ°[gAû›+eí(pÎ_0žNÜý_">4m—T“_q([B¯ + †„>yŠÌÑnE¤%éXºÂû‰Ky¤µS&Ñøêíòþ +©ÍL¶WúsŒk’› +¡m¦Î”ê]ke©þ“¡X—zd#ÕÀ÷<“ŸïÕÃuó<ÑÚL¥T€þÆ’ŒP†òb2)+ \â +Åja‰ÌÓKM²ˆ^…2DŒ—LѺiMÑô]õ.F<ô¢ð†=¾Œ:ì Íb™ðÆ´9à«$_uhR"oÐÖ'Œ•‰…Â:¬f&— +Ñà<Ž±Ï:,Ô‚˜˜¤|Q²ÂÆeWòœ©C:ùݹ¿ó†à…°ðyŽŸK¸¨ÔÀÛ¶bI臵|YÃ%ÄÛ}V¬cÊthž¯f‘Ó_Aš¬Á:u½è> pR2ª6fE["ÓV”lªÌ“;Ý?S˜Óñꛤ怨b}Nñ•Á"Ǭ¿K­Uo¾îÏÚB䆰Få±C¿ xÿüp ,@³ÖjÏÒ’qa“Cã—Râ­§ŠÇ1E…§Xê"u½·0• +Fö…{Ž'Ê_Rt×¥e¤¢»²Î KNŠ/ÂâJ!Ÿd;/ý‰¼;ð)UŠjÅA®Èáæ+ÜžB;tWô[Ïþ  2‘êµ»pEršØÜMòÈƦ’ón°˜ºwk³ýÀ²ñùµ.ó§]q®ÓnáKiyÅÎ`W·ÐFwº>»VÃÌ?ÝÖyê¶~J©è,^_²i%9ë×ëËw@\°ÑÆ`r÷~a±rçx%è—A<’Σ‚·¶³Þ2už¯ÃÜ[yJ0µ}lù‡²›Kþ Ü#š„†Æã2 yj­%úH­Ž»D¥ÏÄ4ÙÌ9+Ý¿„èûñ†fíO4­Û³h›µt I]údzAM¸d×é%Ñ‘ÝCŠX|Sð@‘¢Õ,™ôÃ.piý\\ÍŽ8œY…±VnäUòë2V·•¨/­©£ø»UÈá™UYø=ó´¢öŠ?|ø}ÿk6e÷œnõá÷…H×­jrØï»]é÷Íf©ÑwV¾¢ãVËóë'îƒ-:½läÖ}°çW²zº~ãnÞ}»~·Ù;]¿ŸíúŸÛõË[{x~-íÚ­8 +þ+Hq;¶4 È úgm­0Ë‚ô¥XÇ-’ªt&´fÁ 7ôï--µ»/E1ƒK•˜ Ûšä +Í ˜¦jññ¶°„hÂ\Õ힉`, sÉ€pìqô¯ÿÞZÍj…î$c£B«ý¯ÌÅøæ1Àã1y°*{uuÝüÊ\½wI$ê3P|u@tn +Á|—ú${øÑ®;§X½«³ø°ÃgÓ´²-ÞqI»Ä?¢”8àÇU„ÖyÓŒ—]7Ôƒ‚Fj1º…¯ÊÝ¿Ø [L©Lh»Ð\S±€×Œ–”㦳"öòá–D-EÝ&äf€aœÐEÕ§xB*XÜ'ž¦Kéx‰0ö)zùJ³*å/ý‚‹SW«‹Èy1εœS#òTW½žQD?INÚ¡‹”T;LšÅ!u"—¾‰«§„MÉqÆãCPš|ü½±¦TØoŠ0S/d ôÕØ 9 ¡7_A;E>“«¡i fxÍ—~#aQõ«±µ5ƦB5ìÂà Eˆ™‡›)D„ ñÿóÃí½òÛƒšãA”MŒÅÜnŒü%%›^‘æ#ŠÈé«zr‘íZ›D°dÉ5Eëúóác¤g^S$¯%¦w5àÊÅëÆdá!ÇÞMûŠÆë Êm™ƒ†šH4UF£½0ÌÄXr_ÈšÇÐGoÈ­½:êÀº‡s$¯òÄ1Ï¡²[¨‰Ë)ÂpgîõuJ0Ê™Ê'–ÄCHÿ/žDå \‹!^(JÆ\Ö7Píb÷’eÄ≦.…t=\+©?q” a1Ô™¦ -r©l/t…»9¯Ò6ÿˆ¥­¶™wƒ—w?qKq!…êþ_Õõ”‘,æ)4Ð!¢!Ê16ÙÆÎ\3¥u$¤ÄG.>  ʘ±à&j=–î5IÒä̽¤¥¥q^²Ò…^KŒ‚vsíÕ¤„0§Ï°ñTɼÔ9>ðYìK1wð…/%nÑ4GŠ&õû’•K¤ª©¤úÙÇM†úèqÍÖ…rÃZX,á‘ñnıi&&غ¦EâÔµ˜6Â)IþŒ•$®ÁKMB Œf³‰EsŸ‹9¨‰'âëÊ-4ßæ÷.T‘xÄóF“[W…ÉAî¼ó»»m7þÄxRŠÇz1$Ås8ž@Ço¼¬–]‡§9W§Ècœ¹x9ª†›{üÌÌD=v‹Œ ¦à7>äàœ†ZF…Š/‘kLÛ¾‰M`SFz©ª]Úût,¿CªäíÆc|8Qt¸D z%™Ù¦WjòR˜º ÂQªRWZäJÝÁiø#RÀ_Rv«Õœ;éìfZŸŠ¸&iYdV¯*Y^ôËö#]êVQH—M¦dØÎòE˜W'VÜÚcU’å +¶¾Ž›ö®EöD +¿ªªk1ëe: Ÿ˜ø@„ãÙß÷çXBÔYË€šäB¬Ïj=¬åMéiÎêÔ÷¹[-·â¡Ô#Õ€$xn!õE'ÀÜ2§´\»쀡Jñ%QQÌ[óê9Ð]òõþ¦ »aíGˆM×à1L®^TÞ® ßYÔ¡:ÜCÇpw\6äq‡e5†6·q¾8_%ÛÁKý,·ÅÄ +ïÇn§™%bmnvPuí +ÿP-·Ñ@´•ä\X<''áLÅh/IÌS"”WÑÓà±ná;Êòã§ü‰w†ÝÙ÷×ú;Ly3ë^ºvmÑ<œ ºþEÔ +Iªîë]Øꃅ£ù +µÑ +ˆ0R²5øW÷-¤¢Jö¢È˜ÑI¸¬ö‹=%cM¢t[vë·i¡‘Íé5Fƾñ5Çš§œjð}Rl¢ŽM·ÖëG袕Ÿ²ZÚ¹ÚØ¿ŸOp¬ÿ¥~9&²ú¸Üº!]ÍUcÔ4Ñß4‘5D%>Œæ~NiDÏo·jüÄyÇC;Ï*ÕíÊMrMª’/a­¾" FU%ZÉ=r1¹¢´oØödíÒ [É.£p+4e«k%bœÖ»ºßöŲʘʭÛÓ"—Êe”%€*±Nð¹Ü«ä„‘[Pö®vKG- ºcYŽQ< +ÊB/óZ¶hžéòØ…hÙ­T% +OYH* +‘`ó(EKÚw)MÀˆÔºÊƒö­R‹UiIƶ +q"€mŒ°o¡)+™ö•õœÙ‡ (–*’ÒÝ¥¹‰”íÐöÝ9aáþpöÕ•>Ùšé(a#X¤\}Ñ<¦ÜÃÀXy—¡/¾Êr‡èÌŸ¨“zè£_ Þ¼ëéÄ6{ö/T`d?”¢PýÀàÅñ%-Ùm/ËÈR›2׋Ëâí˜ RíJ ¬æȇI;ûëã>»Åa½WB]±kC…sσÿ"£Éœâ0d#l9Æù UwÅl¢7‚¼Ðe/rþì<~>oÈ é¿Ï‰õdY>\&P`AdQ½™ãði£EöF£–tfˆéÉÌ)ºoî¬ËŠ¾…lt¾$n=ü¹bjŸU¯xԳ¢Iy,íဨk§ +ØÊRLJ¼ÚeaGòæªJx— î´û¤€½²L£^_wÎu0×“Ï J¨êíÇ·5lµ}jTª~oÄ™’mS$>A!¡¯½Ýq*Ê*ÒÄõ/ÈS\Þï’yÁ5!‡ìg*b„ÿˆ{õ|J ±ß]¶ –ÑÜÖÝèSj×a6&­²˜A‰¥<‡[)’˜ì».w?½yÀ,iJ¹ŸÇX¶Š²m¦lÉN½s+Fö‚µ¶<ÿrHÍ b/8¨¤9jÙÅÊ£6¦HyÔÝhÒ +]LÔ6æâr”Ü¿f¢;2@LÔ +'Š†(|{Z% ZÞérAÜtߨ)·Ý7»)±‰*ÄmL¨êdŒJs6´'ý_».UE(Q|þ›ßHë˜~’#”’L~¦:’Rtò¸i·„…’¿ÊV“†pB¾,Ú2¿mèb|YíÀñÿR¼¸¯²§RwHáoàñá²C>–§ +)•^ò†07#•˜Oz×ÕO ³»¬mH¡Êdr¸Ú`"“uÅ«÷ ëÔß퟿¢àÌ%‘ÔŸPöœÄ-Öà9î±8>!Ò 2¹_gp~$Ñä<9wL³³"â^H·Å0WêrrÊ<^Ñ$)ïT·¹S˜w›Óü<†’÷ Ò•ë€@ÌòUÕÁëiEÚg$Y.g^•Ö3âI„2—¿ŸXÖ¨YoÒ;¸¿â=ö<îäàœæ»æß}@"9À¯oïyLÅnŠœGQ&‡çYX4v/%©X.VT,i¿¢ùÚäGxLžFO¿5§ùy$?ÓßÈpôFXÜ™bèaŸ2øު˹mg’zº¢;‚F‘ìâ°çÊŸˆÇewPÔ• +9.Êd ¥©d¡£Ü]Õ\¶Ñ¾Ð‡j0õ%Í+:·”PuöË /[gágc0}š;¥á„ì€_8ró­ß“bMW).›Qû³µ ;ú“6L/ð‘ù°jÏžäÈ AO¢¿ì)ýQ± ‡OvGó+Vª;>“®Žš±ïz‚î±.OßMªõÞÍÄåxŠ4¤-15m[Vx¶åZG°vŸIú!ôx*ñÕ‡¡!ñRI€ +qßÝì“Ç;äÁyh8‰•ÜÒ–Ö~ç?`E–|âaAž77X“p1Õ'õvð}$=Ñ+A‡˜ç*j1ÕfTʺ…à!rê—°Â?Žù‘C^—ãùK¥ë ±ÇÄ×LÆ‹3\%Ç\Ú£â}àÄ83½4~ÛµÙƒÎxˆ“‘Lȇ™;å»y`ÑíV;G˜6óþ?êA Ñ›8Ej߸Sm â´h¤Úª![ý‹´®û¼’ŠeþèOHjþø‘Üòç„".²…6RYêóß/êV9‚‰0G²pÆv¿‡94> ™Qk6¹‘N%ª4©Ea&VW%L|€`¨‚Ó*]è€Ö0†Ô£}¥f“Qd +*Ú¥ÚáUÆËKV·zñìõ>¸xÅâ…£ð¥Åâù‹n´wc\>(V2c¯ÞÐW”Èí¦°‚1è$ºyR( +¶ °&_’d«š]Dzàd@KG¯®ýH“Ñ +r³–IØU™åìüU™·€ÂWÀ>YC?¤÷§%vä8b« +éI}ܺûbii0³A|ÁU‹y4þÀ›0àdŠ™Á”óЧ—3vës•¿y '—"PÕj;¿»\\?öH6J¸àbO»êÕtΔqˆð¤deæÊ•¯‹i…Ì…x„ ð±ÀÈ9‰ °Ö©x|¢!·Œû;h×`ZÐ+¯³¾r 'Ë8ÐéQ i¡¦W]øRÙþú8±Ð`מIܘì§r©^Ubg’ä!ik|ÿˆLº) +º(gì@2A*›Ê ²Ê†0‘¨—uc ¹å]LŸØ¼¡ QàûÄ°>¾THÙzòÊ(ìíRuÚ|bä4À#h²kZ•õÞ#òR·ìRP/dï sãá ·'c»u€ýC+}q,õtŽªC¯J%ûÆn SJ<âÝ»ØÓýTowâŒì‚Ê—.å˜ÐB€õ•‰z}*‚s=ºêË“×Ã<Ap*“4Ùö—ü`{¯ú.¥¸D‹Sƒ}%‰ž;f†Óò@Ë"¾túCPU¼ury‹núA”Š^‚¯€Tf|\"SMÅDJáa‘#âK¡GànÆW¥‹8X«£ò¹ÍO¸C‡ßtÛѧè›Ð¢ç1Çš—Ïh/xEœ.ÀÛ<Px ¥½:ÑG;êî‘Wã‚Jr=")‹M9ri+S t‹"Ü¥ +„yÒÀ…W~F&m œü–’6a‡ƒ_”&1b?T5ü‚×DñÊ,ÒÉ„©]xž¤Küâq$íµòøØ{ý¢÷ •éɼtòv1ú8S1&U ùî“*Â*éÉ Î pˆã!Jì ­‹šgLƒaì(ÜÇ*;/{öX+…Š[¬ŒV€z‹øSû¾<ÎX+%9ô’@­ýÀC²82 +¯lÙBÆFXÿî<Äò( ãÀPT³Õ’¬ŽÚ,/½2ö@õ“!imÚ«Aµ—2LÇ<µ"Üy2 ­P]ø€@¥ˆSéÚ3ž+³bI“¨>£û0e{¸ª-X*|Jž>úÃu.U @üáZIÆ- (ný}‰ÃïDgä°¯ò“i?JWªÏN_ÒâQ‡ÐéKäüb?Æ'Öû ÀûÆì˜=¶0`ˆûŸnñ߈4óÇy}B†ú¶+`¼O9òú–s2ÂóqófcEunc:Š‰KbAv€øb2Ô[Y»hŽZ‡L7EyoPØ®Z£ó-]À0)—¶_ +ˆ—d¹@ "Ù½®ÛU9tº(2V‹~ÛVPn¹¯--Þ#6À½á +YÚÅ„ Í,O‚á =’Ý© T˜\,ÃÅÑl)ñ«åã Óþ¹lþ•˜#á ¨¯ „«/š”¥¿4ÛQ4-ÅD½Ÿx%›ÿÅ7ˆTEcT)#U½—›ÄŠrv1èèÿ5f»63)ï`7°å?_’ÌHi g°Ã—Z~¢(bÕ\ï’»xêLMo6„eOñ +²ëÛפ•ËÓ"ÎO±•.a|æ<“¡ï¥wUeD9V¸+ùŠ"¯ý×½³ÈÀØ™&|÷^ÍDð‘™*‹G®ßº" +Ò{_íÁR«¢Bc\æ1öðIš™€1énò)Ž†z’.ë£$NM?ªç #MØï:º `Q5” ‘C>NÁw:ËüY,£3£dXxEYѤ\Q)Wx>Ѥ¯ÞêñД¦s|¥I?¿ÿ’Õ˜túV~Kºìp=S‹È-'k)çÞrŽ»ºµòí¼–OCŠR>AƒÅ-×rÌ¥Y¦õC¬’é1?*•§Ü))ß.<"²ÿè”N6à äOÖð7:*Æ>}?EŒ•Ä¨ê8ea»?—DH†‚”ä +;Lù¦%E줖D{°“Z|/„äµäÅ7‰€ä~r“j‰-¹IU2s“ªŠKæ&Sª¿‹›ÔKeøÍMê•D‚Üd%17YÛ’0ÅlJ$n²æ&+ɹɢ'Áܤ*CrsF¿Ü$–¦*ÕàhÉÐNnz×'nUô%7©¶É%7‰Úüc$7©–úÄMjM¦çöÐ)*&?©U¹øIUÃ=ó“@qRazeǹd'1qñ4ÐáZ’뉡T–iËTý× …¡ÄœUÍøk}£86]‚øIŽ“Ÿ•ÑVõó“øÈõÁOª‚¨ÌOo~ ú~RU˜ÖüÄýBÌO"€;e™âÍš|)ùIœb?øI-i¦Cq£3”8´û`(èñÁOЂ¢øIŒõNö÷89Ê!K À}°”Äd)µ¦Ž–RÓZ –RÓæ—,%ÐS†Ñ…¿GI"“´¾J2C©*ÁivQ?ôDØÌ}AæW2Dœçû_ú +|b&J§Nf¢„냙¬¤Ú +Ÿ¨×Èâí—÷€uįÜD14/‘ +WŒB8¸ÄËHöu0’¸>3l”qðâ/ñý€îPó‘Mí»üAüÝ}ãƒüM˽ôç  ÿòÿ¤w2_DÉB6lUÓôU#9ˆÜ±ºÑcAítÄgØ?µ¿¢ni^{PŒ$c‡§KÀj¬PÕn=‚»ŸÏ\¥Î +r¼7›G•Ù·È°2<½HoAÌãÎãÎ]÷ë`ämiâ)4 T‹Åc^¢çò(f }l ~—ÏÄ,Àûµ™ÄMïz>q3ò(Æ/€\"½*[f_6VÖ]¹„ô…PÕG½tÃ>\…©-È#6$³F}ÒÒ†°E &©à3e5@î€RôR·hÅ“æ<¹Tb³(‚ôË  +ÖØtÕC³¶ôÈFaüUfDäÇU~‹×=­ýf—]KTŸ¿K5}$ótÙs`uÀ#Ë ¬¡híqX¶âWäD?Àر|ƒO0=ÑUårwÒÛÖæÓRTÈéÀ%™˜Ñ©£m¶¬@Äfß\½¤33èd21ß¼8S6U”lÊ™î`Y‘'ȯÈ3L-Ê:^zëïïÞéoª¦+vjæëz~3™þ±`fNðŽ>v:Ò· +P‰¦ ²á@Ÿs®E;œ5¼ÿ^‡ª:6lj#¨ÁzÕ‹KþO›LuO–KpÕO.³TLKT’ +hº%*Àf·*ϾüžåWú> õÃ%ë¬óë$Þ“m4ò‰‘”yê2ˤ’Ö¿:r+.Ñ×ÛqŒL‹Æé4}íÓ:ý¨œéß S¿y¥ÿ ¨Õ¤2ž'd’··Ê^0ö>7%mïskÊù1m‡Ç«õDb‘îÖS°æ÷¶ü>ŒUm]¨œê—àzEdªü¬wãxZ°&]ØT­ŒÔží²šÐžt²KéjÊ%·Ü”UŒ}­¿¾V— ÆÊ?–‚MJBPÝËÖ¿’Kâäf%j5™ ö–ÛØ‚$ª”ð> K›ã&·Ä‚¶y¼[Ä7¡/¤‚O|n"ð(ƺtꌢ× +êü:‘,Ÿãs«˜Š`7€1mC.Fz4²Cš¼íÕ! + ³äáÑé`›/Fþ íeÛf{”^šMi)D¶Íê f6U–0ÍÊ#ÚÛçŒiÏ¥®ŠÂÊñÆCÔÁ:Æ"N ‘iJ8.¶Ä¹ä‘³ÆoЯ¡±è™Lq$¿(ä…J@0´Þ]Õ¸9ÒF[gL$ùÆëã*;ľ õ­<ÐÉ°‹ßŽüg4`°ŽíÓRòÀ¬ôé'äÊL†ßF”’åðóã?@|?ê:²aÈ??L%âGKúí¡ÒËö’¨iK*<GÛʉhd?”“®®ȵ³ +….CîDt×"¡2~M‹×dõš,ÚÝè­šÔª@]!ï±tYBöEeWw)òhH_$OÀzI)¥s]Iw +ü-;^A¿ÖG ùõ¬dØeäAú³ º’# ¬ú¡îCgäaSæïÍ,Ñwª¸t@TÀ¯FX?f©/RR5£µœ‘|!—²JFt\j5›_Ã3-²Ó©ˆ~MFÄxÕšÑ SUØ}§áZ廞*âÖ‡%ƒM¯)Y:`µÊ/1è÷Œšé•ˆÂÈêºc‚à¸Q³‚)õl¥×ô~‹Ø¢áñ¹©œþæF]|GywÀ_þBmµèBssö²¥&éÕîYc½:’>î-Š•CL#Þý××;ÉHÖSÿNéÎÚkªÕj‰½»ú§$×·Sÿ¾²MRwì?à dž֮¢ Ü™—^ò8@æu8ù£@ &ý*‰$Œ':“BTBkÜôiÁ&Ò·®#Y+“`^e® wmÑ\åÈ~ù“)uÝOнÔ×ÙùÇW”aó¸ójqš{,˜I +Žü9^›ãñÙÝúöa!(ç9Ug'—2mïÈÅJs’Âñ +ï×þHUˆ_Q‡doxUÆÆy$I +õq@íØácŠª#7¢îøã<&É6}û]‚ÞÓ†gºáåï'–úŸ¾ßpÓþŠ÷Øóð±xš{¬PÂ}Ls«ó7+æGn›fr7Ú6îyæ½õRöÕîû&·ç8¦ý +ßìý“§±7œÓü<’Ÿéo¤EY2{˜<›E»%"ñ8øyWIªHU‘q`S°ŸÉG,ì@éê¡ñ7‚ÉÙÌO¨6(²°_ 6·pTÜ[‘E1 +üb¥Öö\çxZÉ$„<€i;ôƒ[63¨ÖâÃÜÕCI +õŒPñJŽ“{vaãÚmyÖV*lŽWÐû=”ñy"<¹çcuÿ~”áíªdñ©šÇäâ35¢=Ò7ò¹ µ<ÒÚ‡7!ò+¤‘`;1 H®P2…e<µS%Åú0z¯;ÐÎtßû—Úòæáí3­ÓÌ›é‘5ê+ï58¹:ÓØ©‰âô°qaC”þ@çÍÒæ©¢¨uÏo8jäæ#–Õ(H*Y9ð±ø'•÷ÄùSEãg*ÃËãâ0ç#B$i)x6Æã¸5—%«¡šù~à¡u)^éAµÇP"Ài)Mâ¤Sš|i:¨Çoxõ3®IÒ,Ž¤Ž­}$$5¥p$ “:¶–ãýIéÖ?CL(á,êjÙg1Îx‚Ðï-‘j‚³Û–ªÎÈU œès£ö%q?9Ìö7ñdh5¿áøõ•ÍoâÝüDù}ãêî¯dgt¾Á;ïâ¾7xcÌŠ}o8üʶ7«ëM¼Š]K‚î,U³åÍŠ†£o¬VK›5!ëz´´>õ»Aˆùåv7‘¤¯‰'Bè[SÇ‘îÐÿÙ³ßÍ•ÍzºBîs‰0’dˆØø¨Šï~7—y…ûÝ€ý‹BHŒ€|ušY ð§0BÀ y{îw“€ly¹ûnw£±ºÝÄÖâæ3):Ôë&ðè"¦K]ô +i:±¯k~íN7ÑÊd +9 EÃs«ÓRÚ+;Ý A›ƒZ:<îtƒt†’n4ÄÓ%ÓÊ+;Ý\¼\îts]ºìîtù8<9PÚ‹ýk5Zèœ5û•Úܬå&:Aht÷²ËÍ¢û@›Sêq[84‡®‡>Þ7¸‰Ãp«§0åÅQ­—»Ûìƒ;Žõû‡ƒÞ­m„ +»µÍÆŠT`·¶9Œ@ê”nÊÅ,‘æ”(cåí„JV?_ÙÛÍ?ÐEæÚhŸM=`¦¿Ü5¦ä4XÙ\½mbZú…{ÛÄÛo¦ët¡‚x5^ËÑLjFjmS&¯dX,rCÝÙ&hÌäú´ý] +{nÑI…Å¢­Í×KuµY4ˆª©M¼‹ÈËž61Õ-m‚LðÔâEã·~6û×ýlq?›ØÙÞ¾²ŸÍ•ì÷º¾ðžçÎ~6»('\28°¦¢kÔÎ&Ðrò9pæ÷ùån6`N{jÜ6IaP ØÌ—;ÙpćWTŽôŸÙï%^¶HãÖ¯yd`a#'aõ§‰‹)œ„éz¥h³€©Dýkâp"à pú‰ìcXÂ$Ö?ZÃøÊö5Èô|ºò²œ» dœ˜2¥(—Ç:3™ªˆå,½ fŠã(ÏÃþŽ6Ø£çh`³– +c8—†‹Ë‰ ê^³Ò8¥æ5‹ÑEî]»›Îrq+Ý¢j]ˆòDK[u®¢ðsÁ +%,ðùp¡, +±o.œÚÖhøÒãLøcX—œëêYs [Ö¬I +k^zæ—SžbòJ›cÚ(¯òÅDXv«Y;§æb9‹½jb燋b‘C÷ï¤pÎIR}dBÎÞ5‹¢çFfõ©¡ó¥65ç‚ѤW‡œ¬L2”œGK‹ ×L€Ý¡F‚á‹j4Ú +jbÿÜDIÛIáÐéb‘4¯fÓ6§YÎZd¶X +slMsü5YâÇe}¹/ +DN÷˜‰Píøš2Ž#Q8–©~1¡ÄIJ]ÌC¡“Ù£%‰…†îH³2”’ +i-âê5BMߣ•=;Ü­&öŸ.âîEø2œÕ$3£MàËÍÔ}ôhª!²Æ–PÌëXŒ%pÇZ¶« Í¢;È=hbÈDàÍJƒ%ÐRÇšÿ[ +Uÿ™ƒ„J?`X¨›Ï¼’¤²ùÌZGÊ"ª‚O0ÝÌ‚ÜÇøë„LeÁ +5c#õž ÚZÜiÎPß/užy}mñAåPC­gò µž‘ žg xg« Tp€l¬³•Y¿L÷¢<[²ÛŠ"jÅu³õ É?±q™Ÿ,$¥Ú+¥õž È"n”–”_ :m³ îbǒȾÓ¿Ô{†sȤÓVÄ•H:ÔZÉéåc¼ÛýÒ´ç–Ÿ«ò†à”"Å_pÎ#z,ok’㦔Ô…o6Û[<0®¬¥–G,ʼvr:ûά•ù|7å¬G½[S¾–pj:³–’3%ž­Ì»û¼Qê8³ªûr?™¸±H«É¡û$$ÀÉ‚!‰UUHZ_z^’‚{ÍÍR‚#MÓØhfÑ×®63!!"¢ËôcSz¶™¶Îç/*Ú¤·4Ô-f^ç•$•?ß&Ì0$Ø”ï‡ .e2t—yYëßa1Þx÷–‘ààÖ2)ôMo^ì—ðõ®[p`è ˆJã@%«MÊ“+jõ»DL›TÞ¤ +R àØ”Úɦ%?Ê$qßýd#¬~j'3DðÕKFCH0ÅB§ò ØÿdÛà{Úmk +†c¦¹ÆUl¯A•r;9= S{_ñSw‰º:=Ô’óÍž²ðtÕ³AÙãNaݹ\L5Ê?3’P†VíÛrÃÚ¿õ•BOI™s¨†ËËíibp|È~Ã* ’ã }3 +Gd65VȱV\ÒÈóúbÙ˜±™GÙ¶ Q›¢žÂ²ã ŒK/ü³üÓ–#Ð×Ö͉ §)‰V"þ¿_êŒ`L/Œ7•1‡õnʶæàhßDêE{gÅkÈÌÎ +:{J¶èàâóQ_GŠæRO ˜Õ7CsW Yu°›jz©XCîÓ²ÃzÕÇÊM“e‡Å_ÉfÝg©3扶×ÎS’uÇão4®B«IùêrZ‰óOqk†EUæqÇ’kÊÆÃ!É{ËlºpŽKÆdVZyỤ̀ĵmçAb›¸ÁÊĺ<ÕCÿþ þ~eÃ!ÄYÔÓ^b*¼ '9j‘œmÑÓÂIâÃbþXŒ;3\Š ñ7 ]ª«Ÿ°$r3[PåLâ+ÍÙ—º3›‰ГõO1£d´s ¥RøQù #"Ǫ¢?`rºŠMAàHµ¤”ÕQEì8TuC˜UÐÌ0ä‰ÉÔ².qAÁª0XAÀ`('±T¥bw™ ꦽ+¢ùí¯ƒ…ùóC) €Ê£a›èW0Ñ!ãzª¯sø¡ª­Aøº‚ Ã#xÙÖ>ÕÕW9m1þý®ò0)©Ó®¯Ø§È ¡*"¯¦ WÔ²ÃÓî°¤ñ)eиÏÞË#SÊÅàò㎴¬?:å–QĘNÕ½ ,… +†3HÚëËæ6Ü$ÐÔ©V +b°0¬•i3‚3N§äWê󸜗7í013IR§§EÒFV2[Y…·úEUnr²´_¹íÃ’S9¹ìÙh[Š.9„^rÃÅZÆ!4W=.¡˜}^.Pˆ*Ù¬‘*:¸úò¥ðß©YïñCÍq?ÿ|¼H¶„ÓeÜ”è+ŠqáuÌ +¹’û /Ý1vùÿ +éj’ÞF·«ÖÖ•žõ˜ó»"*6½P/©òW¶wJû·ù×b¶€ÍwêsÙq‰þÜü{jcm13Óꘫ lo*™“‡â"_þ^FÐr+pÌמÈR‹¡Ð49·"ʲØ/¯æ¾v¹v +áJA•B#¹Ii«“ÀŸ$Lí[(¶fl¨(æ€qý ðð–(„Í`…!…‘[Ê|EŽ‘Ma„<áÒ~ý:±«?GÄÌš˜ )šeèò’mš¤ƒe>'í“©í¨ + +Œà=‘]4vºñž±žÈ¢”»Ô+jÙ3a¹,¯)¼íè³BoSãëQzheœS@¸;l­¶HO'oñZ:J@ðàW Syæ1ìEdŒðcɽ~ƬÈ]¨ÛBCl«5]M2?&$[bGŽX9;^©WJ—¹Ã?ë Ïý’Á¦ù+Aö‹b—ÔI*½1ŽX¤¸2'Ȳsö“‰? ?‚+š×™Ct +iÈÃ:ÿžFMèûÁI/oŸÏœJSìžÜ¥Y†LÔ-#Æ!¿´ 4®ƒËÅû™"Hc·;½ïùQ‡F´˜ÿy_ÖÓ*Kžl5.² +{úß‘'HçXG&_µ‰Ö©ã• +ŽµJµìºTM'”Ð$w1Ód~G«Ýjæ¿V½Õ$˜¦PQ +BBk|–Õ­5:Oi+Õf`üS$Öé°tcŠmqt£™ã‰!ÉöFæ³ÍlÐfdQÌF3’é³ÑÌÖ”²ÑL°E!½Þ¢¯ÍÀlç60K~pæÔFN¿ù:Ç.÷_¬ûL…ª“µß]fs …hw³l¿èºÐFÛt Šl%V±ÃŒœ¦ŒÜ¡àÆè žÑ^a™ô +enÎCê.¦#“Ùƒêï£"-4ã8SkÚ50´-¼)N-:7f790+U!W¶"*ùTžR~PG™ J\~$1Å­pmêã=·¬9+{o÷âsÅTwÚ_§åëËdL’öYh»ÐG&%]öˆÁ럩ž1x!À£G•Â!ì·î h³y}e ™àÐ’@-dB|«[øº³ ²×(Ð)SÀ…4I5b¢.j!cã·[ÈØ8~\TØÓµ­-Q.[‘?‚úÊÇ)ÿxðG™ ¶Ø]^Ò¢“V?ÈòJÐzìÅÕ¯þÜo'àŸ¦³{Çló‘ZÇ$FŒ4±ªsÌÿÔ8†¾Ý×—ûÆùÔ6fû†Ù5Æ®cv Tª KwhªÌ§£0¤Õg5„‰‹ÒÛf*ít=>/ú ©]L(ÙÂÆb~a‹VðOêKÍb<üfÂá%ß|ýh¸Ê¢¤nÒËÑ)†G9ü3ZÄôv†ùc¼1D‘–?@êGËGh2O²Ow&Úgældw¾¨Š[ந„}^·‘Æ=·&ÉNØÌd2ª„ +ÇfÞYUÜ)!"ã+;ÅØ ÄN1rò¼ô )¬ÈÚL}˜b«ÇÓ-_$1‡±²AàÁÔ#fPµˆ‘š¢1ÖxØ Æ‹[hÈí ¡âê³í jîU¾Ü&YßÃ"•›÷©3Ìñ@™)±/Ì!°©+Œ¬&j +ósürS˜í’Wš¢$®ÝÆ^5„‘”Ïv0/ogWiZ̧íýޔ⃒œ`N›d¿ÌŒvŽ60¼risÍ\/·A1ælÇ‚ +Åóë胀1¿–Â]˶ +Šòil"–c*5ï>*KñàŸÏ•™; +O;RB®Y{¦„„d׎”-ûeJl§GJˆm«Î£ØÖW§ZOØAÍYgk_Q>GÎC) 9Í=v†ŒSBZ–¯¸”tè\G~Ç’DU˜É¶¹’+“%½VB2#d¿¡‰êìO ¤;'ÑSÚøHÉuì„Å…ì3²xÄ#ZÎä7·ECszYúÒœaÒè¹( +÷é_RºwS–×ùþÛJ=¿Û‘ç¼ +€ð¿ò烵z†DË2èïqÚ‡bÚãÙ,âåíbõÇÏïÇ~=Îü:wö¥Ùý¶õ?žÆ‘Lw¶3;'гgrN e}¡ÕLiqrNôèm'çˆdšÆß;9'ŸpðDUfgçÄW¸Ô•ÇXëJE½Ïñ•I·ÊÍYª•¬Ô(¿+3s¶n¯ÄœEg¿Òrò † ÌÉF””³v¢ T)9R¾‘Ùëösj{|LþH‘8Ž…ÉWÎÆÑyf2ÎZ‹q.ŽÝkJÅYΑM7¥[U1ÆÁ'qd˜aÎë°Ì( +džeá˜SéÄ·–Ã^N]±’¨ œí¹QdŒšÉ5Ž–r® +7ÇíH ‚ƒÁù7’Ö2ÿ47¿ KÁµœ}CVÀT×™ÜbyN•8 +±ÊÙ7ˆ‰;ù†ã•«¦àùÌ}s©EhÞ‹šIDƒÙ`ùÄ£„ÞxiÐ{'àˆ3íò6âeS Òë¿À®€#ufçßl…Ç€T‰˜kóÛøujZÙ˜åOHÊÚÙ=åð¹ÿ>™¿_ â¾o;Êÿûu"6ê¡:†åb¼¿^¸o@˜u^oñ +Q`Ï +wZ ç=b"‡x>ÂmŽ¿‡Ã7é|rŒáÖyØõ€7Ê>reðµ7~xû0œz<25B/~á‘÷²ãC=†^1¼à }Ø]€7{~XlË»ÞWé¹óm1ÄóAróïÈÖÁÛß‚ïÆÓ1lA +ŸÕòâF>]›;‘T’ð• >@¬*„5ŸÆÑWõó{)-3õ «Ž”úo×A8}X8èЊ_Ÿ÷}@‰óVð^2C¹—Þá'Š¯ï,`xèyÀqSãç¤0ÀÙŽ¼}xȧ˜b¤Š¹˜À„ŽKÑÐË£÷%ÿÞ¹èJ'‰(pÈÂØ zõÞÚ03’‚ãÆÜ5é=ªµƒÌhÇ*ú‡h.Ã0Ρäl‚üzÌQRœ¡Ôpˆµ\,J›âÚ¼D/y!^º€Á_fáñ}›$[ßW@ÈEA}ߣyP×߈G˜?èÉ߯…îÁóŸ•uö8ôÀ’2@xV‘@ATþþZ )_ \b…z%šr;×%ñ’ÑÂséçÅd xàÉ3‘{3—¸Û…Âäs‘Ôy#à¤ê¸Ædw0lZ< öUgÒ|@‚€ÅøÈî&3Ãx}B(ªÎ¥;!‘¼ÑlR´Æ2ÙÈ +§L$,¬™¿¿1GÞÁe^Ú‡‹” (d}ï÷Ήh!\°7²ÍÉBMØFÈs!÷ÛH»P`”uÛ\Å8çBjr¾÷nÍÅm±Y—¦ÓqÆS$c ÂÄvíQg¿Ñ +˜@2Í›t†*e u€,Æ +Š\ñ÷Ö9œQ1V +|º…Ñ“ÆæÅG‹Ë/½IDk ©.wìÖ’£nÐ@ŸQÌ †«ù7o\¶_ñ„U£ppë÷¯G%²9ôüœÀÜ@z”Èœ 8ŽQ¨s!ÚC¬¼S~È(=°ËãºÈbz×–~),9—‹¨§…ø¾±˜VÁ$ï(¢ý ⹊&áí_ GÀ&ðïzg¦˜OJúßhÇ›štÄâm'aŒFzô6Å°×àÃ7áxI/øBɉª ‹zì/bå=ìý>D˜EC¬)jLû.+îCBZ>sKPëÞÆ€{°VÁôP•žÃº – 0jømëvÙ…&rÊ X^¨ï˪Ȓª²l] ‚EÄ:ƒv¨øDralNT1˜ÚŽÉ‚Ú +ú¾ÌvI`ýÞªaÀë€Äûîñ ¸•$UéJÄ÷zÃü*~ ¼ˆ,ëf´ÖÛRÒ9£ÞOí| +bGìÏ›¡¾‰TDC~±÷äç¡À0ƒ>ybBˆ¨mþ¼d1™®Œb†¥Qôs±¨N©ÔïyÞ× +|ƒqo«ªžbm3:R®&ÅᅦVUo¾>äN¾×£>Žøc“òEbµü. +·Œ!RÈöð¦C8!= +ÜÈ¿_kJ +el}1›ã»`èe Ø¥Uäo*â7oÈ-¹ÐU47œü¯´6(AýiAÀÎ÷|d’aƒìO¹¸a#agö;rÆÎfßxÎn¢åxâF´ï"†¦„o:î!ä-nul9ƳèD‘<ÈÆÚ› ùç\ ü³ù°$þR•vȤFHžØ"~¦O¦h*ç¦,$w]²›ÑÒ…ÆÂBÞ4ôuüx¢H qèìȸMmé7å"DÇ—Šø9›êb¼dèi¯Þa +Ô3‚]¥cV}ñh’ðO`í~ª’­š4µwìõ(·ûàr!]¦0Õæö˜„¨@b7ŽDrÐ +iE2²0Ûµq§0Zó|"Ü©²°1k”†-Ûàt$Ds5W„jq«WO¤¡Þíãö!/Ÿ·/I{÷bñ:þÌ«ø‹¨ÿMu¡H#…âw¼rz*ÍÌ× ¹TûfÁ¡:Ë™Ó2tI~VJì¦OHy},Ð+]vwŠpJuç©4¦ÑšÏ´[PŠ´õnzõ bƒ.š=…“cÒ~t’³Ùª•¨q;ã¥þ<2!ÆFš®ž…5z‰þI'†¶Ê_PÛ¨Ùª”f­ ++‹¦5æ+ÍpK›þXµ¦´§érÚxÖÐħH¶†©ìuÜg›Ó°Á¢=]]oy¨•˜¿ûϨÀ¾œ0þoVXn“ƒ•;&šíyÖ†0÷“þ +“‡‡Ç™äã‘î³ Ì“âr«Ô¼x“¨‘¿0›È0ÜO,´Ž‘Eß©2é3Us!íÑF}÷R³QmeÝKýûçAÓaØgÆ,—0†ÌŽlÅ·RÈ;++­ê3 øJÂå#¬ÖJ;“93/ì /e&{¿”%>J98`Ûv/*ÆŽåû‰Ç®5f’<0%ÉØÿÒ‰D\‡¯³smïWvî—,þú!¶ð ¡^_§ÑŸÉËÛò‹©­žOMFç +o«?° Ž?™ýn]ælMõ’ÖOû÷žšmÿøH¢Vã¥]öä5ögÓúyYø'1ÖÚÔÍC@,ÇI“FšJøë©ÈàÂmÓArÖ"¹é¿®›ß0ô€8¯f!y”øúØ‹I˹|ø¨Äçáxˆˆy6=ÀHò"JnÖ%Ç̾œQ­Ð`è\ǼNÀïhñ÷ëúŠÿþÏÿýëÍš¾þ¿×ÿóUøßâŸõ§ãùþ÷Uƒr£hjvUºq-oÄã¼åüÿëëÿø_½ D h ;0þýòøõŸ¾ ʧ—u¼@€ÿö~þ¦ØýïWSÍrø‚÷!ÿ¯wÂó˜á»šÇ<àkþÛ +õkF?~¿F€ÿx9l4Ðõòß¾Â?È9´›íÃ>æðßîH~·Ò“ºßcÈÿpOÞ/{ÄûØCþ‡gTFU'¶òÎ(—–3Ê¥}Ìè?yEÎ%_ñ1—ÿä“EÝŽWò?=)¤Ý|,Gÿx.±¡!ÖïWòŸ¿ÎåòžN’ˆfîç•6äˆ/AÎBƒ:¨“ š^ðÿþßï?O9¶ŠHþ ôµ»Ácš²0b+Œáœ(ôÂÝ +™ª5x¼= +cü´–ão@ô?@±&ì4Á¢fÌ +E±¿¡û˳zäqjø‹±ÞY\üA™³Š@ÏPêp7` +FGÁ€ø‰Í”ùóÔüÉñ+O@DÄà£Ã€fɪ +/1ž{„œSr¬œ¦¿ñWçFÁ®#n­füëTÄÛó ø®ØãIôõðí‹¿ •—e¿qØ°Ú +´ä/ÂÛS|¢Tå/½¤|8>ƒÃycšŸÜêIÁâfÛ1L›>5¥8æFP¯óbhK{Œ½~yï +!cL½£'ÆÐû:Š ꓡ̸±ùÁûy^t v•Ó´ w˜¡€˜±Œ'l;lûk½ŒÈ/‹—Nq‚xX-Ìxi˱Ÿ˜ìC Àâýªú‰±fÊFдÒû1«‰è¦˜ô­lê?ïõ߯ŠÊ Ü1´]:.cF>4¸*ë`&)ð‘DÉõblZÅ°ú¹\ô;îOÐã¸ê(;¢Õã¡dÖ½U:m|1î‚Z,ÛS‹ÝǤ¿øPåBBÂwèØ +Šonzãi^|k…I5V¦c‰ªvI' +SÁ’󉪽àG"g‘³Š\œ8Ç•{©µ¬¤raØcÇ÷™!ŽoŸØéCsfZ5oJÃAWÔr4ä×!'„¤H×â×ö~ßHÉ HãiÞH@ßDJß¹µùÒ´Ê)R„o„ ¢0›þ +¾¨þ¶„ž…~،ؠ›Ì¢âÞÿ™ì]«\Úcì  +Q{Ö+/ò†5µƒÿàUEæ©’Ê G];F1¼EÑ +¤•‘YzÕmNÀ]t ÁÙ”ðì12d÷s¤ìÅÉ[#åWÚ•¦L]jÎòÆ2¾ +á´úÇïÁ{Ž/øÂìI„v~N²DÊñ¹áÿ±R(lÅÇ+´Wû(‰pNÛý9â*~: ¿A=£°bE+ÊïÌ-dqÑA÷C¸ÐXœá#ãñ,»ñr +ÂäáaÈN´[äNEŠÂ ì+ø”¢¢ÒJœþ¢Ð;ø'¤7A^ÉH„銩Þ„ÃìÀz)mâÏ‘çc +Wƒ·ìýÎ(5Áõ×G_‰Wù4û!AåØÌtÖ'¢âÞ0Å)÷JÌå>ω\Òfg©Ø¿NH”S[Ãa]Hº Ň.TR$mo\K™‚¸ÇeGC±…qÑ+g­&îñòÎò; ÝÁ‚º*ö€ fMVþâZ´ñ‚&²†ˆ”F˜‘ÐXü òq4¼(ÐA^A >Êjà¿Ñ%í¶pΓ,)ÍÁ½MéÂz·tõû‚íÑÃ(„IhÏEmXj楣!cƒÔÁM¹7>{ +Z±Ÿ­ï'ÌÅb {ù-ÐG¿˜zgdž‚‡oq§Ø@„ÌsJ(0 Ö‡˜'LfXqt^Ú{K;û +Ǥt!‘b^UÁ€‡Â T¹|ð(;ƽ ß/væÒŹ»‘@ Ë^UŸ·º>ÆDû +‰Ô±AÌjÒ#Ú‚xŦ•%Œ/7Á´i‰§9£)zèw¾"Úày!æˆçó=Póñ V¡¯ä!û@oxØ(òa›æ‘.ÞˆŸ¸Õ^ç- I®òFØ Æƒ÷0|œç8TÑïÌÕ)PFc¿r'æ4¦ýK‰7zƒ0­P| `Ú1«¶@N„›…O„­•È+2Š  ŒÈ²Œ~q +¡œµ +M"q ³y¨óü{«þ9IÅ•xéßÙVRÏQ¸ªpR‰à"Ry¥ˆ‡³KœS+ +"7_AMpåN><Ѳ˜¬‘°§ñ+X¼Z´P±ÁÓæ÷jJÌo&é¸ÁXcVµnòŽNϹ'µù禌¢ˆë‘¡PLæÍJÎx@–Ñ*®D!]br2*ý¬C þP¡¯ù +Bl·ã‡XþÒum:¢ÉñänZÝj45ÔYÆ•ÛÛȆh‰Y~ )‰þMÑße±ùc'é`ã<‘Gß±ZHÇboÈýÒ–ãëÅï |º±n!¾;ø‘’3EÐQc%}¬aº±Ö:ŽKû§k¿Wæ:à–`ÃV\ “~-„ß_XDèœÃ’˜å9î±ì‚DŠû~Eu˜y_…ž†ž%¯8WñÊñ÷±ÌýD—ðâ7x§òÞÊ=öšâÎçi|ÿxBCT‡-HµTþ¥àÝðË€!‘ ˆßlÈ?¯Ô"÷·Üz!•üäaXE$wšÆÀ5¯z˜Æ¨ÏD~p¡6î~ Ãk­Bãï­UO@"Æ hä…9äø†"1s² {’r߆¼‚Å/(8ߟØb'Qä·'¡íu¬ý„+%D;ññ +îÕù[<çáýëë÷ãøþñˆ¨†òø« v,Щñ¯=¾l‚€·|@–=£ÀÎS7׎ê;²:uaTÊ°ÜPÏglž†Ux —ïùE{$4‡G;Xß"9Ûâ‚ +:(QÐCé¼Å¸ÿ=ž‡LfÈÅDa†¨QmD §÷JÃveÛă]Sú›®I¡ˆŒ–z[ªŽ`¨ã¾ó$„¡Æá66Yæ “†qô†Cðñx¥%7¤$qÌR…®ÔNc*£&çqó@ÊMQÏ4 Jpª‹c¿"yS-Ü¿G.ЄP +–,äûª•â7w0L¢ØŽJ‰qõõ}‰=^D É€<Õu±øN¡6‘0‡y\’Ô"úS5ž%I7NU£LÚÒÈÃÃÀ,ŒáUmáTpoœÚ,ó Z©‚ ¸¢ý²² +0¶÷ò´Ð\†Å*8-ÄÆ¡ô¾ÅÔ8´’îÐ1NY jù8æ…XÌëSÿÀYsçÉ€«¯Ü² +P%¡²=‚Î)¡> 6õ™’¤P>_¥U0žD‡[‚fÓ1ôá_äÑQa‰¨R!?zëZ2j,ЃÃç;Ñ}LwòÞ£iùÒv¸¢÷#*ÀƒWpÜîz"eX|¡)ÐUãóÄÙv]ô‘Šj‡Ñ(gE-Pu¦pH|aÁ.þ‚(6DLøÿ4ck¶7û;!Õõ£i©†H½¹¶ 8’ö;äiScÞ•‹ñð)zñìû k½µ2ú1[6à/šˆØ1·¢s­Õ€Ö~ƒ ÙECÑu‘5m1ÉÑ“÷¥CBÂwp ;+®ÆX:oàsh!è›Lˆð«‰B7é1ú»ˆ +û ¿p¹GÔ$'Q9œèÝŒì!Y=Re±_ƒ<3QCQ£.3zMdBCb« 8}Øê=ŽáÛ?ië8êþ¼Á”ìõé±$Œk¼$s7¦4™ß))Šwp«©É‡3¸cÜ$öŠ&ØF1Eñ'Ìa5Z?"îM‹ÛÕ›IŒä^„TÄ¢ vÄÆ7zˆŠlbîlM+H +â V=¨3ËÙ:‹N²›mQ£c6{,½>>yY§QÓ½ó¡ð¨26“Œ`º¥#}xE䨣@8%6„eíëuÞ±%"ÅUrOá÷¾‡#Édž&Ý•ãHu·Ö‘¤XêîÐ5ˆU°" +3¿=ñG_d*¯aÙ¼×AZ6“˜¬ÀÊ+¤¢lhê=RåL¡x´@k#¾dwÁVŸx)„ÂÖ ä{­ß€Xn„tÕ¶À fŽg®¾©U´¨^±H£¸a, r¥i°±Z?(> ªN˜à¨¤+ëÓ-‘å‚Tö5×ñfUõçàóѲʽµè9ùs³5Ynb ‚0ƒÖLJPµMXÿ/~V×!»Ç¼$ÖƇ·øEŠŽc&zÝ…s× ÂŒïyÕÛû> îQ"ΔNEÏ +jÏ’…aÓ_=øa»Sú‚Žû9¤O•*\z嘇×M>ÑYù…íq‹³rœDIˆv8Å.éxå8Þ¨³!°À´®ýÔµ[§ËZ?Ñ5‚7Y¸ÄýÃÐŒA똧(šç€Öˆ”i,L¢«DÕÖÅÿ +ð­§îíC†uÓßp#èÑÈs‘:j ¯-…[ +M†ÛâÔ"¥íå¦ß2Ñß5Çßò0•'$× ùPhDí×oŠ@üF—.æ<覷/+\ŠÂ•¦hãÖEäMùCnððIÊŠÖmÝ/Éz}$—à^!c†â$pð”ñÍ.±¶=‰L”c(gÙ@dáï‰(€”ŸH–—SxèM‹q#…Fä""N¶Ð/›’/tö%=˜€Îãd ìÊ/ë1üZéÞãXGKBáCå >®G‹N›û¾¿¬òýÑÔ†\"¨cáY5“£\ª¸ VSæ$ CmJy’¦27'¥Àï26Su•®ÀçžWPG1^øJ‡T$[ +q¿D‘ê ÷Ö‹O0µÁÅG,±@o3½ ^ÇdÓl2vN —Õ¶™ìBœßÞ–ëB£gÞË‘«G•wTÆ ‡Vª”¥¯e É ©lL¯ísL‚dâîý.·9(Ƕ‰Vù¿Í-x.]Õ!ykmC¡˜1gI +ÚtÈìnÝè'tìcs,NÓtK;/â’tÆñwòÏó ›ˆ»vS¬~ÚàÛØà»\M„šµ™ôÁ"߾̭ˆT6­,Ò>1EI¾_û#¹‡ï¬"lkx(õ¤¯ýÄsôdh¯æzrR>õzÑïr¸1>1íGä{‹8]5ƶa˜§I׀⃅ÿŸ>@QðúøMcÄë¹óýšßؤÂPŠ +AÌ "Ødá¾|féœÛ±|2¬Wþ`Þ÷¡ ÷ö!å}+ïùx‚LM†ˆÞ¤òþ¤?ò1UÆ,h–UA +6xK'í-]l2Š÷¦ÎËf”ñŽ*}ñ¢ ¾Ù¼'juòÊ¡Æ:/ûøx…#ìn~>AuÏs° +VSô0£ÙÑùyåý…ôÛçäÙÏ):8 W‘Á¹NpŽW Sc¨,]ÎbïýX_¿Å÷Çó>ý[±§p\·­Ú' À\EÁýyÍäMÔÏ~‚tø•ø3ÒCþùsB1Ç–Î7ÅÓ7¹[^'ˆ(‘úÒ·žðÍd­Ë|uì[’ÝïÞŠ­X×ÅÍäÒ|©=~Vò»§1Q9D·Z}[‘ºmdb®s,bEY棟 WÄDNKæéÛëÓâGdku>).ܬ§'à›sí'~2”[Uâлr3ÚØDÈÅGBùø…¬Ê‘Bsè&ÜF¡r1ÌÍȹQ ÷Ä¿ —¡Ê¬ ‹‚̼Dk3KÅ·½·i~¹m¤X2¢!;S±ÏNä?”ì7D¾û6•{ËáTcÄY1zë +¸‹ü7Ó;­Á3{Œóy 3¾ÐŽk±¾g!‘2ô½­i¶S»Ÿ-4*øª@oËåèb§ííÒ0ãIkœ=·Êæ|À¶ío¶QZÛO¤Ï)ÅUó«å¼ªNøѨ0ÊШ߈Xú‰¸a<¡ûì’È7†¬L0ÜÇw䑆CðnÛ¢¬Åµ¿ä‚GTÉmO1h +3îN²ú) +òô$ñ ÛžM”% îJÑ•›LÊêM~~Ë7UÕ»%@϶»2W-’iõ³«ë=ˆÃF#•.ƯpÌe«¿’·ç‚NÞþû*ß Jú"¹ð{AŒňu–=j +“Ñ# +!Ù”: +«¨¢Š +rQedž»(³ZûǨưìÈe;¡>R²§QÓ`Îiî1íHaUíV¿áêù кÇ4‹ ¥Ò,1fI¶BûÁ² +§…¢øxC…Úߨ6ob{·9É㺠+"@Ï©~‰‚ZéÇg¥Îú€˜õ˜÷ UÖ ¦“¹ôýÀÒ½ê°Mäîù5ÃušªÄ$ó¾>Ç2kû|@ÉT¿­ˆ’Ír|á±Å('Á‚¯{’Žñ2’Žå:EÇò|ö³¿óÉYx«=ÉÏÃøù€þFÅ| +ÛŒÿ÷Ë ¬Êòñ–jMQ%G¡¤R_ž¦Jš!åÞ,”3EP°ª+d–'p³Ž¨þzËwQ™r÷ܲ)Ûj£úmèÿAª.•cW$Š qè|Éî¹|ƒœØ*™+/«ä¢¨škšßùÄUç1—ð¡ƒEé/s8k…X0U½Ìx'Ý!öQZÖ£êNi)Ï×ï'Ák‹û÷ë„ÖÚÆI•g”ͤûhî%ã»k¨É +[8Í»~è~oÈ#NŦ°PY˜`‹ˆ³uPÅ›¨H¦ÈV¬åˆ{¶SGzy®‡æþÜÉ UERÝQc;¥eÔFQR™qž¬ñïX\áÀ†À@/ÛHølŸ›äÖ@õl·dŒI×N^’y`¹/Î÷ªZ¾PiYšÌ³—]¤É –£´fÃ9ú¢ Ž±³E’1iùý¨h×Q\àiéu‚ƒAøB:Ý__¿£ÔÏh„aJ>£ºô/®O>Uª„¤Úõ I‚¼t(púÙOKóúzþùaBG®Aé(j¿s +øµ×ào 9Ù£Êõ‘kÿ¶k?nG®AÄÕ—Ï\ƒ½ßøño?R +4þÞQüLjòÏß³vÀñ% +ä”Zà)îa¬áû€Ü(·¶_p«Œ‡2 +Ê +ËÑ÷1‡[ñäžãÊžZÅ+ßÇB÷#Mõ+¸SçG¸—·Ô¡Üë˜ç×ï‡ñýã™ñÅydp¼3 +¢lÚúÈ48 Î4xƒ¢õxf”NÕL™O÷G¦A骣LƒÏ#Óãø3 +ÈLƒxc92 +bNNfÒÒ}¢<‚Å`{?Æ5M¿? ÊÅœ ëã8Ó õ>2 +â +̹3 +p%®iàñ÷Î48á;Ñ@Ù™xãuf‚tOš¹cŒö’ûø +êú~Ä’Çf”LA2Óà=®Îç¸ÖG¦AìteÄØÅ€€oN8ŽLƒ˜Hïg¦A@Ú<2 +è;Óãrf`ç“™#ÓÀ?âx|”/Þ™8Ç~fd]G¦A|+Ù)%„4…g2Ó Æõ92 +°ýÌ4#h™i€í;Ó ÆÑ{š¿ð•¸ê™iP:ƒ^reïC»>2 +2ŽLƒã˜™i ÀÏر3 +60 ¢@é¯à RŸŠ²ý™i€M½ÏLƒ€2;ÓñìLƒßÏ™izv¦hg`ÜÎLþÎ4ðÍLƒóÒ2Ó`?ÂL¾bgH©L@î#Óó,;Ó+¹ÎL@ff`éóÈ4¨¨©í¸yžŠ2ù+ÿ&Içh³¿ì#Ó`óì„@ý„ B™˜f=2 +ÎÅ3Ó ¥ð'\;%;ÓÀrÑDÄŽ¹k)G¦Á'„\Uú 3 +HÖŽLÂufà;ÏÎ4ˆ1<8Ê4ðXØÒš!;Ó¯†z-ãÌ4ÀWkf`ñ…IÈ4À4g¥¦\±_yf¢¬3 +°ã÷™i€3G¦Aœ¶R—=lÏG¢Ažô?^àL4 BíD¼¶1u•›!mSÑÀ¸áN`ÉxÔ¯Þ‰1î…ñÄ" âJ4Õh ÄEÙ"< +`ZÌD^¼v¢Æc'œ´X‰Z÷N4ØÄYRpçëL4¨…]š2‹¥äDçïÒµ;J4(]99J4§|&”îÄäX`QžÁh”gà¿Ï$öÌà±+×GžAqµò bëÈ3ˆ±3¤/ŽßLýuæIJ…„K¸c%3åÄøþÈ3(]„ª€±yŒò ’Ã8Ï ÿ®<ð¨Ì3àV{éþFq¶‰N©#{l³! +ߪ6Ö,Âe–:çˆíM¬„i—L3 ÒÜ·ã¹/lgC§`¬Û =gš zâAH"údšp¹iÀvf ©ªd†u^°O”Š¥å]«TI–¤‘ ½‡˜÷Jž»Q†t˜¿ -mfrÖ2ÍÀÏû„ònÇ÷Gôp¢Ì«Æ°3þ?5¼î8pò—ýÄ-­)xMýY@ÿôt&*¬" „B ìn´Xb + +siØ NqÚ“Š*c‚ž”¨¯ÛéMÌxÓXn6h +rí±Á4T yž +"°¾œJ;>†ž¯è¨—zÔcUèlä÷„‚¯ J ‚"¿’x–Ó(h¦€±ôÈ­C¼Ã}ÚmÓ A Ë·TÛšõy$'ä¹­%ë¯@™J} £+f#ïCJßÅØ~S‡58†íMBPMmÞ öGÐxŒ…jKZ²HN ßÁ茉7AyÍà@ŠÂŸA‹ÆŠW„ÜD +SYGÈô¼˜Ž‚@Θ:ÊÓ´Tg©¬;•»Q™}Bý¾0¯É'VG¦~á£eˆ½L“EA%ÇX!D0Ô¶w^d;в›õ®š÷Ä÷?$·Å‰W1*nW±¬‰“í/½¢që© ®Á#éä¯^yWAd0PžY#{½&ÓFªØï5òBÞO4ñì‹ÅªnÑÊó'É’õbcÓ-`wðÍÃЬjU¦É’ìø̱t½—|Œ'Î"m‰ñýÄxIrU91¦ž<õœÖXø;eÎò#Ô|¥ú;Åcop×J5iƒÔÓ_ïkBÙ-Z8™µÄ[%¸µ-<cÖ[Å’‘m +áÎy­¥RšFÈ&ƒ½l<ÿ—³äÚ(è‘PfžŒ–ùSRT•ÿ$¹Weÿȶ¼¥K…2ÆâÌ´î9(ËßðeuF–µ|³'±ÕM–]³°áþ:ÐŽ{Üeiº7Ž©PKL¯®vÜDµçÓøû`¤~‚íëøR’:V¥*Õ†–†%zßwSÅ‘PÄJz>.s¿„<—ƈꮪÉoTÓ«TÅ—7‘äÊÛ2N|Oæ'E[¥Âbq¢9)yCí¦¾Èxö3îýDÌ`ùÿ2cè’¨ØÜ-v2U§ŒX½ÙK4௃Y,Ä7§ÀÚT«k‹´E½‘¶±[ +ƒ•yΗ• ³KYô0˜›4ìxÿQŽ\b"J÷ +18~l#m>uæ‹#›zÂxÀ9m€×=R8bä¼5¹&ª/¯Uˆ[^E¸9I2Ea£þ§ôণ©'7õBÚ¿%ãëíÃèɉ›„œ9IöLÂ×ãñë·ýæ#¾Û¶*Tª$±»¾‡—?‚"‹q甆àmz£Œ2Sù)÷P¦NK«,Æ 4Ü"ÉL¹: ¢èSíáÒŸ=ænYª©®èÈc-™Fóè'Fœe*WºD_4«~©˜Ô7FÏþ~µãº+rH4—ñüCò¶èvBÒÝÙ‹vMײ£,õ B’e¸~‘êÒ§ ßÉl¤oõ´-R…˜7÷/kÝ¢5êßÚ\w‰{ßöL½¨é²^Û?6$6IFðÿZCìr-o—A7‰ÛÓÞDϹõöé:éݘnãRAþ°ô4\¶Ý'ºÝõ éöí*Ûg§p—œ^ã®ÊÇ”8üsуý›f<…•‡î¡¼Æ ‘×8_ ¯qWqÂíÐÍ9Èå›s”K¸«:ávç2÷´ˆï7pŸÎop'í4ΦÓø·£øþñxþ† 1Paw©UFBòÈc ©ä·‘µ£ãÌ”åÎ"®­Þ¬.äBdábhö†¢Lƒ ôE#!òý]‚",Œúß©RYšñÕíxÇ,¾=N¼S ªwªUâ¢_³Ð^Œ±Ï  &'÷Œ¤µINÜhåL2˜ ç¨~FæCÔ}ˆcUáCüMlhYú#Î .Za DDÏ.º½œ“«l2Jì U8 ¥ªl:jNÔ]^™Ÿ]˜_‚:Z5Ðû㧠›Ú+ÜùÐÏGÂØ€4’.d!T¦Ëêt# +²¢¯8 ÁZ°Ð·c¼1hCn…ãp‹‡ëz2™X·Z¿àŽBìLŒztØhTçeÉÎœ +–Á™€ mÍ£näìððo6Þéí8d Á+ß?â†ZÜDv“Ð*^* +¹ÍÊfò„ hÎÆyT] ìRed`0‡ÆÁ㎠+¿Ó·bb ökÓéôµ‰±¼„íx å,X4M)u1«^^ö]F@aeÛlÔHÖMØ!öxü•EÒ (*æ ± +g#_9×éeÑä‡4 –ûÊ£¸å°/Ìáø¥¥#aâx„ï¼UlëbzŒÇE ¾c6FN܃„–EõtŠ•µh¿®ºçL±æɆúc#wtÁÔ€oYºÖ1¯0Ÿ€Zª²{y¸}C¿ fLõ™ÞÀÜn\™ÄåÖU{Ѫà;‘,:vDÑM*­¯ª AÝÎG¬\L7ÛS#þPšý•ÎÀOHh½øFDm|gqÛI’î¼1’ùã;•ÊV·ãëS謊Á'„(†ÂÄ@ Ñm +. :g +A&ÑÙb1 O¸òf™5P Ÿµ•‡'´E¬“(Ò]š~aŒhÑ;‹-w/÷x,) !>ë~¸Èᘼòã“\þ€ Xª]Ú“ÁÈ´vå·"°è›T'©Ê+m2Á«ÒJßÃ$-^M>Ñõ +TÔD,¸DýFReöYäaÉ@TÔDà†¤&›&/¥¢þ©×rh’H³xŒM0ˆØÉëL!‘üi}ü†,…í-æW`:Œ'HÙgxZ,¤§ &e(×gÙ%ö¦Ï¯C¸‰ílóã ~vŽ“t#¡ Ö©47ĸZs硤È•zù‹ZÇË,þ fô¤]bPªÝ.¡iŠéMõŽB#ûú%Ëi—tÖ•´cé›)-æ$¡ù÷¥zã«YìÓ_¹ô“[ÇȺ=6½Ù!@u¥dÏ®UK(=­èÄw'¹1YË’>s%ÉÐ÷êQ-¡*Ï9°žCú/1Ž‰üÁš–ô[ªÇ­¾áüE,ŽÈýºËÍ@§Z2³µ%ݪ82mEΕj9%, +’28ÑÙ·X"lË1w#¥Z=ñçTún“d~R +OÜWkóíþ óts}rºw~çÁ1Š`LEø)Ø…Ž½¸¡ì*ïjŠ&ƒ,!)aY¯‡ ý[lªla˜Ç’>üØÒÍta/Í"÷Œ&ƒcI- 'ý&œC¥¥9ÚU•ìÛ¶BHbG}&’&˜ëQ“gŠ4M;œ¨PÚ5ÓÅN¦JìðfÍ¿ì@£:ÍŽ'ê#ÖC^Ë:m*’Z‡ +&JðÚ¦’Pºï(cë!í3ß'àV . D[5¿ð:qÍ“xèÚØ™"Ǩ±…¢†FXËt¤È+#"äwˆ´¿J×—¤ÊÒå‘›¼’pÛHeBPxèD!ìÓ£¢˜¼kõk›‹. oƒe×<ïîP"”ƒú͸ ¤(“Q>2¦Ü¶ÆµGÌz?ReÇ„å3"¦š¾ùØEh˜Vé¶pCYÊíÖ͵Ï  ^ï ÃÐ^*â­ñtýõ ÓÈñðßóÜaË<Æ’ŸéZUÑ ™kPYyC|ñÇ_ªOËÝrM¯[m +‚} ‰Ëƒâ2¢¨øQaßcÛ½ôG´ÿmØlˉ!îıHÃsM¸*ç#R¦x3ËÄY:š«G±Þ‚’ö)9Y4ˆ›É~g<Ƽ]Zš®ÿ£lg2Qˆ¶¸*±E·ò¡=<Ö«ê&1sWe/ +cÕ¢á£}\ælKñ>¡„³ô +? p‘»Ÿ ™ÑÇé•gÛ U¾ÃÛãk€Ôœ’¦ìš ´Ã ·PÂ]3%öá„*,‚\¯î°Œšª0R•+öæÙ KÄÞl${Sð ›lc®8Û|Éá¡c³Íh?1dáQýǪlWG¶jwØ»Ê_ +U ¦n ŠÜÍÓpĹ¹•p ’dStË0 .r³§µë + +òØlwKyÌò ˆ©Ÿ~˜ô'’ŒŠÅä¼l?÷”Ç#ÚáÍÝ JjMqø7ŠœN{)´{ä<)³ŸGüÄŽ]%B92„¬ä32Æ»¤¥cvNOº<´–ÍïÅŸ6YîÍ^fwên›õr[Ò@õ©ª&qvw¬ +zp€ãžÿk ‘ŽPþóáiØvBwÿj«š²”ç¢éW`uÇ(6¥ jëÁîBm#\Mþ-%/,ñιïnÑ©úýŒÇ2¾ÅÃ÷´÷ ºvZ?®Ä¿&Ã&È]ãÿ÷`Ø“àIè.å¢ÓýÈ=§¤8¶ƒò(E˜¯²ÀñŸCÉt¸t9ŸÌù`xÀ®=S³ï"£øR þ§Fsx˜èë:ýªÍ_à°OÈÏV½R³õ¾½?"Mt#“%¢›ÞN²uDy@‚àŠW$J¥øHrÕýP!Âè§e{Bš>Jr‹!K +'ãõÎÖùFb‰ØÓ³ìæ{I>]¦ ëb˜­Zo¬‹áòú~µ ½ÚeyImb]½°.&v¬KfJ’σuåºÜ÷ºrc]ì;ùºà6À…u1´_}c]ìCåºàŽØ…uQûó`]â a]xÍì`]4Øσuqœ¢À-†^+ëbwhÚ ë‚k:ëâ7ƒëòýXI/¬‹A¡úÁºΩÞXð a]D ¬KVô%fª#Büya]²¢+Žu±v»°.Ö‰ýºdf´»°.YY‰_XCÞ–ÖE”ÀºX{_X—ÌZñŸÖE×ëb7Ö…uñÕ¹†lÜÖå{©ÞX#ì ëòÝΕ‚ž6J_ëbíyc]Døè‚k·/ ‹.>ÐÅFÞo ‹MMäp½L9"  òU\@Í÷çEÁª½€.ZÈ›R ß„¿èâU]® Ðid>çùsp.&¯b,Í%ØéÙ‡–ì…syQpÊ%òo FnŸý80ƒã†¹ä¬‚¹¸5é0—co:Ì…” æb„}`.Çxv˜‹nóÌÅ:!Ø a.ÖÉäY~:µaT¦“Y>ôtÁ\¨îõ ç§Ñn˜‹ßvu (¾Òÿý²/˜ Øês±w#´#˜ TÞs±žß0$B90k."BX´ÌÅl&}0Þîº`.vù5¿`.FqtC“)¯õ^/yì0»åäµ4Õ-ÇCæbw±æ ær%)qû°=¯¦¯¾SºÊ` å’» +Dîcõ¬7ÊÅa\(·ZårÌG¹\OHê놴P.öÆùB¹øõ G¹˜%4.”‹µÓåBí~¡\`¡s·Ž i](—c ;ÊÅ(ãF¹¸¾q”K¨›@¹„FÊÅÚíF¹ØWÇ åb½@.‘Íæ´]ØJ/7ÈFÞrÑ?!Ë7©\p_ù¹!‹1Ó8 \G¾@.Æ{õr1î\7È%.å äb^ d€¸@.¶knŒËµÏˆqAb™ùÛÊé¸Øæ/Œ …ÿ…q‘>¬ǸxjǸ˜xK7ÆåH@Ǹd%lsŒ Žõ—„ …áˆáãâ¢Ü1.—(Æ%„½0.|ÅÇÁ¸\jI]P Œ‹ßËvŒ‹\·À°ëÊë…qÉžËjÇtÐÖÜ1¡n¢ãâ&Š0.n8ÆåX(Žq¹ž€?‡½ ã«èq±^µ ã7±ßjà…q Õpa\2½a¿a\ÖQtbE–ËÕæ·OÛYÊ’EÍˉe…¢ +W†÷¢U8êèa€'–—Ä»œX*vy±pG•ü/–]s½œXuÆŠK«0îy9±,€Ø.F$Râð¡…Ò꾬².,ä–©1ÖOPÜžä +ÔcÉíðAr¹±qe¸Ù2ýÅuÜ:wF§/¿Õ¹ƒ}9²lìÑF¬µ×C×\…«Âµt¹±* ׄË˶7VP»Üq»±Á>^,êÆ–˜,tâ^,\cÿ¸œX~å9œXÖ7íÛ¡Bvì‰;±‚N,û‰Ÿ·|Ê€*p'–õ¨ÈVY”yäÝAÅ‹ñ/–óo7—á–L¤)±Ã‡e+;xì¦ËXnPù+Ø>üs( ;2-–½Z8\XÊf>¬à&ù°”åçrbUæ>N,Ę?‡UG˜´2aëB”«Ž8“û£øÀíÃúÉÿ>Q0Ïl²‘=ëB?VãuÚ +“7¼‡ØRΨf–s²"IÌ^NðÍO]Èž÷ßÝαéáUèÁU4¢-‚*MÖ¦e‡Þmçl/çU\«Ú]ÐîFs%” +Ä%À¹å…ÈܽūÁî÷°dÏ«-sõ¢°[‘µZ) [‘Ô¨¾Î(û¦³@«W/”Dñjå±e§´­/},>ú/:‘Qým0çâÜQI…v°Ér‰I=Ø +죇E‘̸(IR…CÄ$uÔeSxBgn£$u- ß ;ûÄø£"ºZÝ«ÔyÆK쨭º¦ë^Nv ¯^g¹™h×<äÕr﬇z]…YtZoœ^–¸¬ì}j.aíÍ9%Ÿ{=K].PC#“,±î):×ìXXO´àQ'j¤ÓvÇ¢ê;ܱ”§‚m Ùb‹~ñ´ÚÌçlU’JÜY¸"V_) §ÊÓ<«T¥-I_W{ƒ]NžGbB[´E;{ ²2V4%´ü¥òÆõ#ìŸ?¡ðŸ83ÖØŒÄ ŒL£êHùp¬i¯¦ÜR™[ì +†uó{»øˆLh<²«‹N,HËárȇ}›üøþ +":)Ÿ«ô]óš×[¢1s=⌘…î™òs¥@øIÙá?â®2Ü÷(’Ÿš&Wkç~0!6ÓS~_v¦SÔwf9cW(’²óœ­dƒµìŽ“"a™~*D‚Y[¦qŽÝáQ©¥¡Ú5žZ")I ¶ˆòßÁèjå8ËÅ7%$Rñ[EYÖ¯³5ñ«3£·][°+WÉ=:€÷Œ³³ 44?/§û˜‰UÁ%úke˜Äæ¿á›ÖÈ÷e¥ˆrÑ “ïÚÈEÙzz›î¶âOüxœCï7ùô“€=jÜç§ý-g%‘pFiR4S)¬žèU,¹Ê³¯ÙŸÝ|ö;ï±–'#%á¤Wz—ËÛ”+Û¤|‰bCº'ŸuÉîß(&Z¾^¿å~QÁ®ùzQX +µÅ±®˜ÖÜL/´e[SM98›3>Ì#„ŒÀÖoƒïùùDÞ–Ö#Xí©Ÿ¸'TnN²¦l‡¸Î§­{,2»×¼yœÁ5f—™®$XŽK‚ÎŽJ)Û! #éÇ…aC§o!Ž’RªóõDSh‘¸GdáQàOÜÕâƒóm0ùïnËt1MÚ*ý{8‹‹ýß/ÜFœú=…SQ<ÚS;ÅZAÉ%§‹Â\>[Ó3À\L DŠî~ö„ÿ£QOµ–ëÑ^ +yÖåõžS¥1ƒõÀŽšnKô§î×(xÁDS‹ó0ôé­¢è¢ÚCzE”$x{ý +ºŽŸÎÑ‹ó9:‰-þ\ã.›c¤¤h*î7¸ˆOXP=¸&ü±Ÿ¿.Ž­}áN +$•KÌPùøº(¬¼üuª?å9¤ä¡ÇøÙ_”Ät2|‘}=ÿýÝ!ëc#UŽ…ÞÿÙG¾X¡CßO¦sú$TzîßWH²+%w`?Ç\5û`áĮ́g?¡ÁÁJ“#|ŒK|8-Ñ‘ªËçT¨?M‰+¨ç€¶7v73Ú~PTD§{Œ³Ñ麺`¦"òUÙDoã]¾}R¾^”ÁÄaÝCÏ p$7;™‰WH“…€U õŠsÎcc¤Oì0Ó¡$f ŽWÃrT·0 +ÔPÏ‹4¢GYA÷â/jœ +òlM‹ÿdiEeNÊ'ã2ˆà<–vE³¼ÞÝ¡KM)@ú*D1k \‘Ãé̃ ÄÓ”]\Èe[ñá?ñGà2èîÓ+ŒAô÷.Ôæq´ Ø9yËÅ­Ü~°H‰‘;0°‹š?¾Oß!"ÕÔ¦ÜCƉ»†ö§4_ÅiÅýɊ»ßí " +íöƒš¬AлVV`”î!f1oD´èO¹d²j‡(’@éx¼¹‚2ð;Rp5Ê„»Ì´á\/üú8oîXõ/Š]ú•1ßÃÃ/ÙÎB¬éPN‡Îñä'ÅÕý5²|b×ö_”Áó0¦ÏÀ¡À¥`Õ…ÎD¨aÔ€Ê7bù¦C-'Kö®<”O¬îåÖöõçXNþºýã~Bÿ@œÄ»Ð­Î.ž¶ü"…®“ë°ðŠÆÓ¢by=ÄÏk”纄Κä•ãLeJ*,ésUÚò^ +/Tèn`ƒ. +kIúk eñá8ñžbÒðÓ÷B÷m,Qqáéã÷|zð‚çLàùF Ì{ÑB¯{MLoË>Ú ²pc œ5nVû7²û•¢9 +uîŸ<×0B¦Å@%õb‘ÎF³öY¤çê…O·÷ò½ ¿/Ò¿¨†I½Ü`"þù8”ΣšUÇÜÔÊûŽ.-9\¾¢Tl¥…UÅs»…=X¶Ÿæ'JO¢i<0uˆ²˜jL½a¸gw,;”ûf¬l[¥ÐÓnnýŽ€/WTÏÄ+tåœy'Î{ƒ5]"^ýÝÆ•ø³vÉYº.Ÿ•/]—;_¨ÇV-l:WÀãÊ5ß•+•ë¯Áýù¸)Èņ²¨rfî(œ‹œò^µgðÙ~a·ÙQa•¥‡î.gæøÆH¥ÎÜqc„¿I‡x«ç»e",®{• oD$Hgø1NpŽOÌÐl¬=êœï–KeÄxÌpÿÀŠŽöáƒCOÛÚ5üŠ|ãvA]âåŠgŽ¨eÒÃMÎá¾Ë1åk,D1{³_9ÿ‹?täihÆ ÝÔd +7-mvgy®'< ì¥Ž»ý®5W´ +A‰`š®{v?øêw^û–Stª2þ¦ê¼œrgCwò\¤8øÅÏþ¦„…ïŸw +üõé”5\„ªT¢È¬Ú_Þ6g´Qú §¢ieeßSq¶f†"T%µúµÞ±­8'~~x™Õ§–(HkáÐ*…£Kjòy;“]·Xèõk`œÏëy# ¾ÎJ²Ñ·hªPñ!xÒÙdð•*Å¢{5{Ùvÿ|f‰qï\¦çÕ;ÏæçÇ£;T~ÎŽ¹¹_¹;Ÿ×ÌάäÈ×Ôþ¶¼ªð½V†–Iij'ø‡0pÆüæÀ ± +,FÀæ'–»ƒ„‡×¤2Üÿ,µÿñ’¥–"×cyW%b7]¾*Oºmì°øE8ܵÞÜå„‹™çüE€[È`fÕoÐØ–¹xAeíRÉ,¨q¬¦ßpŸÍ‡jQ{;’©3Å +Thïë磊þ´Þ~ ¼üÑÓ­žo£ÈÊéY4¥>%Áùch¯ç¼<Ô›¾-íç“nôŽ»òô=ñ€î?×¼œ·kÞ¤ü»AøïﮨB l~ç½Ú5ÝUùYØú"èzÇi½òÚ‡*/aü¤Ü#ˆÛþF0©a„†ò£ƒeœØÛ]û´AíèsdY¨tÒšteK¢¼Gö ›?¶±ª*µT<J©êåÉÚ$ùõg šÇ-…Ùs¿}Á‡ì_pîFÏ¢i=ÿ¼ ɳ™ÁÛÂÞ°ŒÐ†S÷3>Üuõž!}AŽ«ùé{ÎxüZå|ÎÛUÜÕ?³U‰*‡ÊÎÿ+KBõZ HÊqÞ8™PÓ¿h™ÐÊY +H^æ{áRXS³‡M©Iðù3fÃÌ¥¸ÞÎ¥ˆ¯s®£oj×!‡`'¶'~.ãGká¶\¶z&ÓÆ;ŽæsÖâ< ¥ð_kbâåš7ÿ4gõQ×~Lû¯+A”8ÔŒdÄ`Ì8 ì’$–iq*}ùŸ~™?ݶç$ÂG« +ѶŠ·ˆÑi‹ÎðÎàÇDâòKÍ®â +m™!¡T +Y9°¯ +PMuþóŽÆ@wÚ»°‚C +‘Î1¨º§ß-ŒÍ.|RX¢Ž)A=`_ŸÍBéCÕâ }ìåÓ+¤Ý>®}hû Uïüø1ó\Ÿ}çÏÇEHZ —]ºij¶9öo¢R³L CáÕñ¡4-€à¡ƒoäpP%‹ ´[èc±l@=y +& +â%ã)9,Í–8a•yþœiýj~€iÖW×㨅³„ ++,$´„ÞQó^iœ”e=âç«Q‰±šDj×—8j çg7+v&ª€ñr +4(ù^8Â.Û@¨1¯M`CÍÐüHóEäÞƾqd·s¯c]Æ9Îï%(i]YÏ´Ë™ÖÙ4‚) bÇǦù•˜…©¨â™uÜÂpB˜ ‚¬ü$<—±¡ßüMí­ïá¿¿»òï·’ÍQŽ¥¥Œ2îÊRAH!]E¦íÕ5%‚÷ÂE7^„¤Ѭµ€—(WË>EÅæ­0”5K>e£¬í…¨XXÊ(,°užès]¿£=?¾ÀBó§^™*×W“™……¥Î XXJßø8EŸNxïðô‘4Š»²Ôèy$ë£þŠ¤Ä-þŸKU–:sÊR?ãóײůZHT#°5«^» 9¡¢Ý¨#ÁËBʪªQßqª*¶¥TO©y@«6BõâÔu¢íõý8ÉM“®ª„ßl}jU/4£45L¹Nß“õ‰ÏZAõ[ +üj/ßaz»¨öMÉM0…¥kŸX*qZ4ˆïÅÂXê—(±„› +q¯hsÐbn¤ê•†õB““àŽ Æ(“óÊÂ~v ~0_=/pl«Ü¢@cÍ\R¯ÔIŠµ Ê$7¨bk»H{ëà %~³Î\ôÁé›øIõB¾ +µÁƒÀê—b“Åú—•kZO•ÙF¦`Õ{³!BâÕB1…^µ^Ë&§‚üÉêûz¤«¸Ë‚o«-²ø$Vm±Û.ÄóeQ•W“õœ¥B½¡=9–HíªÉr±äµl«ö¯—V¯®Y›ÅA+/ŠÁµ#RÙì–WF7ÿÍ™×>ǒĘ Õáôe[᫼’s‡Éd&¸å¿©<¿n‚¥Íc“% 3öÊdæ^Ljgç¼R&ƒ…5-Í ²¿ä/V,°ÒFð*Ä0.VÔf‰J£x¥LNÀ‚³Æ·¨µõ¹÷ìB‡û‘­ºÄÒÜ«†¦ÜÍ&µ±çèG?ámÞQصKelUó¦bí.„Gr;¿dÕIõd)LÌêàtn¾À«çìŸp9-óÎ÷å¤âÆ¡µƒÂ’³oÊD$#E)øçL"nï?H|$gýƒKÈ`íîrƒÉIK›¢o‰Æ/¦,‹ÀŠÛ7eªv¨¥Ƥ¹dÓ,S"¥Ø2›ûöáBš`¯ðkí‘N›«Ï +æ ÅXhÙð¤dJ‹äËT%Єx´µUásè RèfúΤ6_ƒ´\kMH¦*ùç§9á8o× +^Í*ä”v_?öð÷¶Æ-ñ”íjotµæªÉ(ðW×\ã;"÷åUá}‡lhÛ¢U\øP½bü¢HæDë­íeìQ]Û”{ÅÅ1D +_„:+îZÒÕšsTÜ•8¶ñtuË„XWò9g¯.)1Ù”à–CíÄ':„íEÐÂ¥ivpA +m+€^TZ,ƒ[2¯ˆk¡t´ks£ÒÌ4ip4Ÿ¿×÷–«ŭØÜ@_…jÛD›U©U ÙG¤Žç®×)$Nxp'Ì!é3¤r2³’˜à2d¿u;£U* —’©Xí×ß›¬?ˆX›‰®¼Ä¢ëY?ÉZÁÃÛi»Œ9”Ñõ‚NŒÕ’ÿ_÷før{¥6±^!3b^²Ryeô_ܬúÐÓ[Tf¹â¨ë©-<|EYíµ"-,–°q*˜¦zxÖ7ÂÌÜ “s»Tf É±ÁûÁ)ün•œÐæa$x3»Œ<ÊûÆñ«ÝÃ2”ÃìÒö²îƒƒ‚´$±è±ÊW㶷Ø2ñ,h¡+r®,c3ôB° +Qq£Ô«·cfÓxŽè¢å–Ü6ÞÙ_°<½¿!ëh#Ã<$ÛqÆÈY‚9¡î˜µ½62Þ¬hý¥Wp¶ÌɃ¯p.`\B’îí’f^‰[2 ÊÜÏÅfa‘3¸ÛÉ#©q‚}¿e™Õ¹LÇÇ ¶¸äüÐ +±›ï‡"0ÕÐ@ù¿å¦kÉç`JÞµ$iìD^.I’D«\Ò«Ôõ'(¥¯ç,°óZD&˜¹—yÇKü‰‚sžlú¼ŠsŠ´¤rÔ­¼ÄŒ.Qk71¸O¸¹…5}0`˜ƒ–)ß ƒŸMüy­ E·µiß`[>/‚3¸SªG¦lE,·*U(Dd ƒnvÈòÉ‘÷u´Ãv!KåQxƒ×ÿlS½§”ÇôÅòÈþ‹Ñù +ø-l=³,sò–Gh©æ’TNý¨’¤ZÒ€[›{ª¡²“µ¨Â;¤¡>¬ã}ßêÃ-Á£?¼”·?±d2%Ði—³× w^Q ž;u…í&ÁÂM5XC†É‹X"ì’NÖc1õìç÷|ÎvÆÖÐ\:ì0íêzô‹®# ÷ò–¸÷½NoãÅœ‚•Ä\X?òj›é'b’dæJ*Ù²ÕÓ«’ÂoÑ)°ÿûe{Û–¯0“…Ø–¯ªDnžyœŠ)7…ýáÌ~Y0¢égq±ÜnãM w}‹Ãÿ‡±v’ð°Õ‘08²pàwŒýl£P3ÌfUâS9±‰ +ÑØ5±®]5tŒå³³d3Cñ¸k$¯+ÝZÛœ°Ö¶Ô\Ö†1£6‘/ŠM5Ö8±.^ÂÆ^hþóõ„Ÿ_x–"± Ú ûÕ'šÝD;<÷Ð:ÿ-´ûŒ‰áf¢,7;¥È‚KˆÒYS[áˆò6›/`y9qù‹ƒŒ«V¨/W$+\ÇT$Ì´x‰âd××'±ÊG‘Ì8ùAM”¡}ŠÄâtµ¾žpe‘]†ìÇP$( µ®nY¦qIé?572sŽK“(“ghe¼TIq§ŽTIéÒ=®J.‚Þ)R%öÒ5.A[•  Ô¥IÊÐÆ‘ªqH*™²Yô÷‰4Z®Jž³G•LÜÕ;ª„9¨*q…yTÉD~q÷0~é~ѪkEKì*Ò§{†‡ì[˜>ìx>®¬Êt¡·&)#Ê|¢¯æš„íçÇtói°ÅQ$ÅÍ¡HÊ%òTT;:¤ ùkC‡ ŽÅ::ÄøRž®®ns໣BP(_ +b†R:óÄA»Í+ê*d…!–™á{á(™ +ýôjò¦·›ÆÔ!?w6w;Î÷ÿß°¬%Œ)9ƒ"¯%NQ`ðJéu¼ÚEú|qx­!Œƒk +mC¯ +7{ãï4~qÉg ‰Ôä`_z>êÑWvª]&9[3» •óŠKìàe;ïUUSÃL¢²àÚÚ¨ÈF +Ž£µË½P±AÔ~qf’–wË»”qts©†qŒdÉ=c%Esñz…ÏÖù/F?΄³Ÿï%ùüu™Œ ªÖ“†·-]Óš»)~(Sv.(–<Ë)HH Ð's*¯ÆœGßcª¦ñV¶ñVãÔêÛ7ÉU–e\, +¡k5–"F˜b¨‹I5–Òz[·&Ó.•àëBã-%d·«èIºÚ¥é$°…ý©ì>7ÖB ºvÖ+¤îèŒAZ›«ECÃÛÆÎ>øKMլʴ ÝÅ„Qp=ß¾1øD¯vƒ¿7€cÎ:691m½;“?Ût¤¥µÅ2Q°*\X¤E_J#ƒ„ êg—M +¬ ŸõrÆ<”†MI^Á}m\ªßâ +~꣖ښڦ߽҄á*õRÒskö‚‰‘Dà ¡C<Ò™&¸óhfm\éë]1*£pŽ;Mi0Ó  ªhi›bVÚ•¼3È+œ‰ÊëýK,éF"_€-&ï§ÛˆYËò.qG°>$ØiÛ,ù‚ÅbTy>/^›¼ƒcóP×µÀ/xþ_˜XLÛyi§°0â׋‚zŒßm +õÎr—Ö¶D¶F¨b %)Й}u© ´­Ã@³‰Ñ37Š/Ü2iÂvöáG¦¶ÊÔŽ¥c‹k¿ÑÞgƒ~ŸLH<¯kŽ‡÷#H…ЕínmÞѽXrKB7“3Â`¯Ìl[;¶øÚþ ¤Ã³‘™‘»6³³!-„.'Å<”ŸÖ æƒ ùnã2¨Í¤9ð­ +YØ`?”PÖÞÌço_ÃË%ç¥6{Žüv[¹Ç9tﮣ÷Æ[1ÖÖÐÈÆÚ’wöYþ—õt><ÌP*Nê?YTX°)ëS"ms’ùçB_V¥ëËØ€›…"L¬.rÛ§M^Ñ;üÞ%IpÕü©7J²,fÌ練¬f'R×d½Pëeáb.+‚ÁÏ¢†Ç²²Å3Xm½r¼&¹©K4à +37î®/Ýi6Ù$Yä_ëÿ~ÙÃßûzW}»Ce~ïë‹bþK´µ‰Ú¯ñ)ÖÞÞfþVvÝßæîÌ 6»AA%°«D~g1¥­:H¡„‹E\6\oN“` +q즡m®kSŽ„0ÞÕF·t¡z+E«Kç]˜Zi— Œvf +å.ÀúÎ,Vb¶€rA˜¾ú…³“µÚgôÒh bhÖìÂ@oË®ÈG`´ìª~†YóM¡PA®k¯î˜á1óVŸFÉ÷„zkX€iÓM4¹ßþ¾û¹W†ðÃqâ›@ãÒ¯lKÌ@Á…­›0ÁëзaG釭¦ìÐu€lÇ™˜Ú$eC¿ÎDxÓâ49øAyJ|ÀKc®X)àî>B]ïiÒJþ„‹‘e÷ú|’$ã,—ª^BÄp—ù2‰ÐVFÐ#,f‘Tè¸2¤×ut¶ö¦ Ò屬 +trÎYÛ=aPW›ó~(‰-ðN×BSÝ’š?Ãhrû[j‰3tiº˜¬Ð…Àè]¸h³£ãÃûRÍåZ¾‚·TªkZ2PY¦_@¦;—ª}È‘ÓyÕ" ̸eäQM¤ƒmä$üÉY~¢ÊùéÜVã,ÈùªÇ±¸†ßáágtMD³0åYw¨ŠâW­Æ}ô=~âÆȼeµî@.ÝôÛµ…›:Kq`\:°ÕjGŠ^«äsØ™t[Gek») r´ï +ïD©( }½Üô,ŽèV—Kjèî]—Ÿº¹ÕåªqÝ¢»…¬Óê§Hä‚c›Æî^ðšÝ™º‘ÑBäM&èôÁÏÀæ‡= ¨±¬“fÁ…ÿLMyR‚«/C榚¢yJÞˆò\¤¢òùÙo” +¼Àù¼(úù³O´,2”ŽŸ>n +´ÞÁùW³@áqâ%¼V… F\¹ Mo.µPã9"'±ö˜t>ä@n–ÍìÁ0£ ©tW^ »wÐý°Ã» :%Ú'gUfÓÒ“àtªI\UÙ±[ˆF÷sÈ‹òÜ*Ønc\N°7E·³U!V7XÝ'ÓöÁ• +?L¸²¡puâ +x2.)æDîÐtÊÞlð04#†žv6*orâ '¾ª +÷&¾+èSüîî Ð\åÇE{»B«»µO·¹-–»M÷ÅM±ø^!ØÓ²À¾’„åÒúòŽwÊâPªPg™m‡”Õ¸·´ªPh|ÄÝ›°Á¢Âð†Û~#Æaj‰ó™„¦KTX;ú½uéqK…m˜ÅdŽ…ð¸û%¿¾8Aöš¯k: =t| +´Ç‘9¾N¸û,wêfÎdÄÔvIÙ&ïÚöšï.tZZºj¢>e^_)äù­ÃíqÁaî‡ØH_!ñZ.–c¿¥Šƒ~ÊÁÊ"^&ZŠ~˜ÍÀËDN]míÆEÀ¨ø1a¿ª¾ €Öûãå…Ÿæë\5ܦ³Ê¦ÁUñÚŒ7Y;¦”kÖ¯õêÒ°Z/WŽ±^ªëë¥ê@XLd~®¯î˜RäqVEöR™Ð|ls˹0ñG˜÷ ¯ØŠÖÝqp`–˜Âö¼|ÕŸ#%NÀ—hßd¿St<üÝn4(>á,ÿ§<®œÈ\AΤ¢šl&HñŠçYŒÅƒ­vž×ÕÁ8Êã–jéá×äÀz-}*Œ +xâž%ù ‹rîë,«%Únò6EÑT ‰Ý¶=ÙZþ„QŸA4ä%pm?ìeŸï&ïwÕ'&]ì#Í« C7%ÐÍÛGoãp›^·†Ü <<R^4aHã_¥…—^çzK]+ˆ¡{µÏÅ8MFĈùmDÈÌ2i ^ÀÛ²t›Ñv¬bä”þlÄØ~ìyʆ&õÇ(èŸC™L…SZ@ÚbϧïÉ;ÊT…±(èG¹Ð%µ"äXX˜+âMM׿ŠÌÅØÕ,¼fCgžÛF#<@Š¤ð†™Nw?!re'D{8ë8Þ­»8çEXqƒÉá0H)€$« +Kèt¹ââºÐ7ó,lùN12­€”VïrŸnIåKL +ZPŸìUrÂö+f<¹ +Vm…PÑýŸÓâóyŽ[‡7 ûÍ´¶èµ…¤ç¢ÓPXp´ßŒ„’?9ëwnÓ•$yûdÑ_8j‹¼H‹>mkî×Éßò ²û ù¦@(1óe…=Á󯥌\åü}@É~þÁgÜ?a +º^ØádOÛím˜Ï+¦,ÿÈ„ÕøyõƒˆæÓÍÉ"ãg ÓÃ81RR4×+|²ÎGl6Ÿ«g¶ÙÍ÷zøU2G°ô¸$êÚÈZ£&nXá'–rŽ%Ò;:Þ%ÖÁ ¦þZ$Âgox® Œø {/vDžÙÉÓv±¼ì€wkÏ+´Ì¸OëµF®[½—Э÷eëC•&ÖÈ_q&Ë?âk¤^œÉf'ßËñûý 6^R§æ ýóq(:tÖô§ƒê!ݸ*mù@‹.r€7jŽ0.êå°Ê—_Ǫyœ¿; næxpK¿—‡\·­Ð ÓjvÙJ®䵋v8sI¡æ„ȵWÆm“UK!¯Zxªè£_pÀ’Å8bÉl õ`qm&zRÙ ÎÓ +Íï#Ë +xyþ¸ç²kÁ›Oé5¸?7eè³²v¸Zaì8‰ʲ¹&×ÐÃ¥mó4¨fg½;]±6Ò¤à¥]Ú0BN:®:©Ñ®9.ˆà¨uMŸßž,oX;ÃE˜À¡äs“oÞžˆZt¾rë_ç§0Dã×åAÁu„–iˆoxð-e]†¤bhmW-2 *`‹¾üÆV@\…ܯ=S‡Ü<Ôž'öñl™³[ünq÷+;` +…œÖ¸S8ÿqh ¦™J5úƒ¯~ç5»ëÛe4Ñ›õ‡7q±øáñº(òŠÕþné=mñøo¹~â³Wèñ¯®0ï­IVÕë`Ú[sŒFkÔ»Õƒ>™á³–àJÈKöM°›v¼G;W­S˜Eh‚Bd,)\­ u‰íCÂË¡ö7îù—è˜QÖ¡‚ç e2d—Xj¬Èã”TJZmÁcf€b˜|`5âpQ^£ý"ªsFPže3§MgjíÕžÃ1T¤,â›ð +ãDSi)@T˜Ž,ÀÃj +9ŒÁ$ƒ »NpLEIG>…mɯG°!û5[Ç_þbg=Á‚@uŒ`ÕÞ°ü»¹–?ƒ`rk-‘1G˜k×.1Ûô`àÀ,A@ǶÖ>ý²4Ÿ­àÐÜݘâMl%<ð4œ~MN?YšÍeaF“X'“‹ü?ñÑNq6PÙ(“HRÔì +•¹EÀO¢…ÊœÞ, œ$¶Ä9pU&n`¥»‹§¬xÛ‡qűWœ[Ý̳¶%÷­ìè­Š©Úc\œ4toc[l»{x¿,!&»5ö þ8ø…)+œýÚCi +(â¨àÓ¸–˜¡>eŒ“„Ù(²0ß,F‚íåy™áÑ}Q–ïæ8fflŸÁü¹ÎÈZl¦aæfØbm8p•‡Y„Â),³S<3^š˜¦¾!ë–~¡TÌàKËê®D˶àîx{Âñùù¢©3Øq;üæ“‹ùÌ+s1C\T̉ã®.Š“§ +F*æóˆÊŽZ»2Ó2g‚8/á ÌÀ* nx.fˆaä›÷E,´ïl»˜|¥bÁ31cûÃÄwìØÓÊÄŒ$ŒêF›Õ_ÇaŒ…Øêç!  O&f0íÆNàr$‘ÏÎ_+±p•hbÂcåav[A9‘³¤]Õ’À‡6õìÅœaÀFOfìêT^m—íNY(P䉘!9:qItÉØdÔÈÝœøÈÈL¼ÜuÐT?äA¹¡È4®=‘J>‰˜!Òʸ†¶aä}^ü¶#Oõšù^däaVûWƈ,ÌØHsŸ,Ì6þ¶"Óc3 3v‰9œ< 3„^÷ôµ”ƒ'Vea¦Ø#$iú̈{Ócf¬ãÄF;¯ÿ\½ehðK +Ã… ’0ß›uÉR:À"ó0Ýq–äC239vŸÌèff²`îð¹âOšFÞ'ówñŠ¾mg•éæ/\!Ÿ̘Kþœ‚sýyQ6¯vŸìʾ„7·ì~PCŽ ˜ÝŠŠÌgìÊ¿ Ë hƒ¤u%<rÚ$¢üË¢\ù—Ýz=ù—ßì;›3¤ + +´‹ç_¦ŒõÌØyQNÏ¥]ŽUéù—•éù—E9ù—ñŠ|0ßF30ã³™Ù'ØJŽÌ*ú¹õ‹ž¹òf (³s¬'`–ž×œ™tÝ„”`Y æí*Iä_éÿþÞ¿‘Eµî„I/ŸR0SÏ '£Y …¸†LÙ1Jc9˜³J*)3šÃ¡4”ö,,ã9˜Ñ&¨£HäMÅÊÁ ‹+1¯³å`F{2]2¥HHbÏÁl$øQ”ƒ9D³r0C4§H¨Ü)¼™L:‡eØ!g/‚Ö>(J¥§ÌÖF\9˜aßpSzæ¬ +Zž„9Ìea¾ ¥a>OÔ÷«õÇñ>|åvxàñeGÖ^?¥,fpu#{ÿ.~I­Ÿ<Ì´ÌùŽ®3ò *óe˜+3(k°_pËKË0 +sèea¾þÚdûAÄ* 3¾¿ú„$e÷ÎZBÀó¯¶ šC±º>‘…™–gŸü¼üL£4Ìࡶhu/ï&bûÆ6mÞY˜3Ê*õÏÂŒvázå䜧‰B$±éY˜Á«…èÀNîÖ PY˜³*Uyfì¼Îc§t¹È5Ä4ËY…Ë¢9\TXLY˜¥vÄsAI˜¡•X +Ry¥ý$bbäù<˜3={¸,â–/Ér´„°Â¥ 1¥Ì!¾™ƒù’ÞÊÁ|?À㨿áòxÌ}ç`F7 +³¹wù.ÖæOª¤»ù2n11 ¾Nf™$J–¥’0_‰’0‡E¢$Ì27NæË"Qæ°H”„™'»áb˜ ±,Ìè–@’õÊš}Iþ+ óQ‘†99>ÿof¬tkWf.4Á-$Zh¥a¾ÚÓ0Ç:) +óYG¦a¾WzÇKü žYq::y˜¹®žñ˜jGýRfô|0‰oûœ3³T<3f°ó:ôÑsày˜±Ë&?A;Gûò&8“;e‰wdÍÂáäi˜Ã)Ò0S–ïOÃ|´Ãv)+õ¡DÌñ€21S} Né ‚2ÇüÅÏî%%bæ šø&?AK?3óK(3ý,\vn,ö¤ŸúC‰˜þ`&æ£!Ü" Â4Ìñ÷%ûв'+óóžm>2is+ 3¤äâO܈v£€Y˜ašG#wI#çÑ'8üèžÏá öáY˜xØî :{uk}7»“Êw;Ó0_¼©4ÌGdIJJ¦”cÆ‹uþår‰i˜£[LÃü„`»Ó0Ÿí}Ò0ƒËW¿Ò0󰳯4Ìo +ûé½Ò0_§¥a¾)á+°o4Ì¡G< +3DÁ$胎³îGl¥a6JV¢æB¡fž7Oà !'­ 4ÌF"*”i˜­M|£b5çâ–qÝgf´+p´fØæ/òEñËhâ!{¸ÿçë yç•…”Æn& +ÈŸ"a›EæûjdJRfŸþP ›ºÂ祪!,eb~ óv›/a —QEþâ¡“ˆùV%K¿tU2å vU25ëçëJÄ|TÉŒ# #àC“ª¤Œx‰?៪¤ ‘¡J”‰ùô‹™˜C•(ó½]•‰9t‰21‡.Q&æK™÷êH™(ÍòQ&ÁGï)ebvmÂDÌ—2Q"æÐ%eh븪qNpe2e¹øÌÜ{)_’P&LÅ|” S1eâ:ó(¦b¾uÉ Ou S1]2CMú|Ïð‘I—L9h¨+”‰ùè’2⼌¿wñµt‰ÚÏ{²ùˆt ó0‡*)îfUR†«‘¦a~Ž)ºVs´H +ÒµH**Äõ•Qg %+¡DÊ“OJD‰˜o®t'Áy‚ØöP"ó¨Œây²Ý S•Œ{­yuëøóP¸èNÄüÖ"K‡ÖÿkZÖÖ”üA+³ów•ô +þö<ÌÁàÊÃì«ü­ƒ+óyB0Õ?ž‹ù㊵գ³lT.føV‰dÌW8 +ɘÙ+§S2f¸x‘å·‡ŸA[BɘãPªLË8A¢lU‚=/ŠçkæyKîF%cÆRŸô-šm3»cLVˆN%c¾Ÿ ŸÊE'Ó1ߢSÙ˜Ct*sˆNec¾˜”Ù˜/Ñ©lÌ!:•ùÕý'Qtþ`­; ï›ÝœÂ)+aÖuÁ-Î÷ḻϕ9ö¹²1_û¼Ö™bŸ×êîlº·tŒE¤cŽ]®ṯ‡c•Î*3HuD²et¢Í«}˜çPö‘ŽY.Ž“Ž™ Y‚{ÈÄ}D:fÐÙ˜ÁâÝ{Eh•mÞɘ)õw$c–ÿG¿p!?f$c–Ä~î½\cfµU3åëYùãçzÿÎõ(8å™÷a1òÖHf믦¤ ˜–5?@æ5{¨"óHnþ’Þ &c‰¢òƶ[sáM&‘LÓ’$J7{Ú¼¡ÊP…ù#Ç;rx»í gkà©Àp‚0\ ­¶òšœ˜ÆD¨F‹ÆªT¶®æ›iýä1‡Æy»jô¢X¯”²×^a‚eëÖI&a÷ #˜/NfNÀG07áÆ—"÷kì0é³Ç2Ŷµg½f«ÈU)¸Š{µÌØTøQ ºr¿½Stæ9Ü1™¸À¦¶lÊæð¢Ô-è™í,83™) +òÎXL¡¬¥1aQ×&ß9„ÈaGŠ‹È 4„)È=ÐBFYži \Ø¡µÏw™¶ˆ/x·…H„À)˜uZ Tã §XÅëD 2ïPDÆ1UÔÚš/;#ýy 83¸Ú‡ƒ…I Z3™ Ãp4¾§õm&ÏšB†*ž}gŠ­½#²‚‹ó ;chU†Òâ`nŠË¯$ÿ¼’ÌšUµ’mu-"ç÷Þ '1ÕŸ“¿ØÌ)Ê]”y˜Ð@[¢Îrbèy)Bwnžžc(Rì&0Ù¸&˜¢ÐcË̈;C»ÇÃ{ﻡ(øEì†OP`èØÛIäôFöÌbÞ®BÅJ!¨m(± |ª³×vºRUñô%¡&ŒÉtyL–é4úë¾4CÙ^¡±©xJÒ}j£(3ª¦à£ƒY)¸ŠY’ÿ݆½Ã%À•…ÏR,Ê \#¾@¸Û=ÙÓi”› +9Û.á vý$iã;:Ê)È2 R±ÌQ60´uU.EÄá¼2vïbîÄ$¾,vˆâÀE”Gzì>"³×¾š c@á@_9ÎsaÖð“6z®¯¦KùCY›8ÄÒ²'ÍéºÁ—[Etpƒë›„6Ä<ƒ}Øt°²—çæIrtüǽñv +¬GØYŽð1õZæ® ¡¿sàg[2M% !¥:óPX +[yˆ³J~ZÈ[ÂÐqK’ ðD“”vÒͦU¨Ë cÇÊ-U-3 VhqvíÁ,]ºéÅÚï™Y¸y>¾v­×@;á +¬‹Ý$%7O'F™ª‹ +4N.L &6¤_½Ð!ÇÈ>ñrXc^dºÜ2ò]ÝšªA Ç” é,·6bØ^ø¾¶( +ÃJ$Üê"hù/ +g'Ó—™»Ö%Ì… €@h²ï…/@Æ­äûÆs±\O ?wL¥MYü…-1f +Æ峟\2sÛ¸Ñ퀄Ƭ)Òñ_|GwK˸կT¯èû1ÔÁ ²º³ #ð&ºÆ^ú ßöõ€@ÐXŠ½MOzÀst)*—µkq·ùj0ŒS<ìí–}[4þ½ ƒ<ß„B)2Ã[t3ôù;°B˜yΰDÈhãÅ ÉòŽ…PÆ0 ,´Š4Ã*qd‚[eÓ|U'·I'º‚¼UiB䦰˵њäUrˆ¾6ëowSózS‚Z~E‘Kç›ð;dݧ¶Ý¤¬I@ÏØFèB„Ø9ï€6®!©©YEƒ±/ sT†’B +7N-EIò,Ìñ‘äY—Ñ≢³j&&<¡®¯¨Ð•QÐõ‚ÚkkO‰ú•_ò„4Y9V®pWœY›ö¨&T6JÖ](·Qp6¬Ç(³E›Ó&íä"ÉnÎÝ%2?ªO®a({5m—òð'ýÐÔxë"5HK”ÿ@5RðÊ!xIf?²Y‚ú…>q[ÁõÉ +1âúd tÀ‘ôÉ!¸>9ê“Eÿzè“%ŸÝÑ'ûXñÔ'›P¿ÐÊh}ôIQl–`Þú¤¸G.JQ&\W(ÅÍ>)”’BïI¡7C¡8DÇŠa5Z= +űG¡€n…b=—^£ Þ®ø\¡­{ý½IãPŸl•L»ôÉÖ7\ŸlúsCŸœ¶Ë‰C¡>ѵœÐ'ª@sé“-žw}¢;6¡O…}é“-Mèúdîçú¤¤cÍD)tÊD×'¶Š¥}R’û§¤O š‘{èUÈ}bkZ?žk£N£\êÄÚó¨“Ó”:9ªÇy¸: ® uRÒ9¡-%jG›”põ…6)º¥éÚ¼Û6 ùr¾øé)´‰Òh‡®`]§K™lÙ1çžE\™XHí‡2Yríå@q!ðÊd‰ÙC™¬Ú¡Lûáºd¹Ã–ªdÇdº*QBäP%Vλݪäø›­~©Û`mUBaüR%¶Mu|õJö’ïMKtÉf¨úº|r)EÓÎñ4(Í/ +œäoá×s‘ÎÏ¡ù•b.æ¯×¯@¹_TDüzQ쪿£Rl†Š¦K‘y »¨z!ŽÇønš—‹ÝAí¥É‹È牶ƒýºûwŽՙ‚€ž£¤³pIn“ø–j® ²óK +†GÂ^ÒÔ΄.u±wô“AÔ=f¿h‚hGEÏž1¬Ò¾Ÿ(aÃYi!¦Ý“aèX…X=² PT°ù´]À¦AB›¯›³¸ØÿýÂmÿ>ÌÃôrp;Xæ8¸ƒnÀ½.ƒ/ýrp]”ƒ_)JÍ¥2#¹ƒÛB®évp;æâRØS¡)bz/àà.¬v9¸‹®D¹ƒÛ"ø:ÈŽ~šáÞv½Û†¶Øëòn[hº¿¼Ûº\ÞmyÅ …Ÿòn#:ß®G|âèݶ¹N/ïvQ‰B÷nzlÝÞír\èáÝvpÑñnXuy· Ð9v(Uy·K÷ȼ۶ê2Óô ÷‡»bìaÖ˹ÍÔ?Ù]ÛE÷î³\ÛÀ’ÕØÆ|ÅVH7{-w]’)Jy{¶‹G1Î#s%ðJ’Õ‹+…·g›@¶÷l_M‡­ +ŒÜ¢\ÍîÙÆU ·g7t>±Ln—cP¹Ë± +èÈíØÆU3þb ƒâ»x¦&7i“g'»¬>òÀÇö_Œq¡ƒþÿiÆ!¸W0ot¾õ ƒ6vxPD<¶ò)Ó»¹õäh +Áƒâ‰æûùûtbÀ’ýð Ì£Ž:RGeÕ¾ptŠ¿:(7gG¹ëгHó~^AA)‚áäžoGáä}•j—%µöº´HÌUèG]O±rƒ`ˆÅ‚è¬.pîmœRí—´ pöw€ƒl kp<éŸdÇÚtJµË˜~>~rÖ òâ6§pÆ‚ à”jÇgÊvëì+à«27×<¥ÚaÖè'5\ëuG©ögqp@Ÿô0äVL,Ò™@ ø£qld­ŽöáCÁ…Gñ@tƒÀ9˜G±uŠµCô´S¬G¹û”U#ÆñA¹‰cÛ9“æ«X{œ(D±ò|Ü»9Ga{7Rrך*äUÿ2©gÀ•4qîh2 C4“î4£à᳧*Ð×úÝdø +Öí6yßõ´©4*±HÇžHŽØ>ÛA1Â÷Áj[©SÀ6ìĺ•ï,Ñ{¶YÑñóÃqDU€1—ÌV¦Áij¦šŸ.˜mOPxs_ØFàà¼zŒ †½ŽaÎr­‚æÖx‘¦ +¾a¬a @Œ™:ÄË™J7Ka†¸7l\*½ÀÛ† óõήFW®x¬ñzn&šðCN"¡TFÈ37°9KëFŠms_8hË ü÷xI<[:eü1ûMô*s¡…ï2Se³¾ú§lÆkty¢"Y‰ï£2X}u(!§ØÄt êc}(Cgš¥øELµ>ugíÊ ›µ§ +G|¶­ +Œ¼xÄ’%O~B€ Æ/ô¥ã2ßá«™íBµ­º^`22øå"à*†°`[¹#UxN{õól–…½ +Z\W$ð±f +“9®öŠ·Û‘`;7ñÚ“µ“W|2¨­Y%2Í ±ž±ÖŸ/>Á>µâBBÆ.rŠ!ØœPë›0áR·÷o¢3p5æÌD(8³2<¯$ùXÏr ý9Ø ðÛŽ XÛ;×o<”Czx$”Å_lŠƒ¥EÜ•ÍÂPyoüª}!Ã3WÄt†6Õÿ +Ô—O§5ÍËfr¨ +êÁ™¯ÍZ¼Å!' =< +ÈÚ‹°›º‘™Æ¬K{{挚1cÍ­’2«>X–Ø\@]zñ*`DÁ2Jºµ„°Âê§Ø²HwÃ9#è°ÑD˜l]ÌPîà3(›•GÄ +‰,[5RóÛ´©TО2žPÇD[•md+ïg¹›­G;ÃgòÁ·š´52É‚D*¾D˜ÕE3 1w¬mÕ.xÏàNvÍ\›¦1/!Žs+ wÓßØJÐ!;»˜½ƒÿצ³9o.a ‚ÙÌýøx°DÁ8[ê ÒP>¬¾õ^ößYAÅ„ºö Rñb‚¬ Ƀö¢?ML&« +6‹BŽ™°]n¢Ì“˜t¬;÷nHN#B8LôK°Ñ;.óçüÑ|\`âRdNˆß ORÉ2‰éDÌwº=oC\ɺéxšÆA2%[d)EKØD²±ïÿ'V¸Þž €ÉÅ4§ŸAðUámožQìö®ž§L ¶ 4×kĬ +»§9™§ä­4Ö™È\“=ÕÛIÂH=HÎfQ¸ ŽäøÉ\Ȭi“O“Ó`_û`ó%`ÛqPv –Týmnÿ=-À +?¾5‡Ò®¨ÿÙ³¬ àöžªéÉL}{2!´A{*~>–Cy +Ö•”⇣ Ñ3«d>/–iŽx˘~Ïú‚æM‚VÔQÙ?·#c¬•ÓÜ©Œ¹[­ÉYçäæß]˃þ4]V”òÙßçZff´Ø÷{Žš1 + Ï-Ô ýp#W&¼A¾º>Ãr††³“§mÐMLxæUÍ#Lé€9Í¿ÑáÂÀàœ=nßø8®„ÀI=3ëÝÔƒ 徉ÌÀÙÝô¿@?SFxéÞÄœ0ã –—6†Ê8vYU‰Üèpà…›íŽ²¶}j X5õ—™êbê¬Pù œ]öïút*aâo\z¯4TíGZ…ȬvÌ^_÷’e&G³«"¹žKG`­sy=Re)d¾à6ûbì+úsåêŠjDZ.Puì’Ž;ÈTVŽcÞÇ]üÜcÈ"ÈNÀÞÑEÈÚýs£…püSÅ3 vJÏ¥‚ØßÈ«¤IZxÛ<Ål#œ ¡\ß:a3ÚÁÁ¸}5­#~EoëøÞKBH‰X¯`/iõÓ@ÚUùP`ÎQW:“œ<<¤ +'xX"Ö™ 5½Á¡ šqa…Àge°†{º&wu¹ñÜ¿°O9YlUS;R¹Ä1\YÓ ƒpâçáPˆD<ƒâÆ~..m‰4eŠz ž[,ˆ¥/½ „é`[{·ùl[Ó–áôÈxÂr8ÄDÎD3˜Èɇ'ÁÝ.M¿'}ù‰q}ˆ•óFÒ¹h.éM Ín2¾“4(DÍx²^fZ‘;g»mÑF²šE û8¡ÆÖzªHèy+S!´ú"T?aØ¢* +:kheFØ`½lwûXxM2 6'ÈD>x“v8„º>”`F[ÑïËÚGÌVÏþ‘¥LLx"Ýèsp»Û8 œ)yZO ×­ŒöZcŸéó‚óî€Çú!Q+{û\Z“)ãwÄÅê +HÂ>¯+ª¦ƒ*PÈ\O* +dèͪ /:3ËO˜_r{I©hj“‹ðøÉï—òz7EznG.Æ£½ôqñóVèc ÿ\êØâEI>EGáñ·Õ‘O‰cÜm†êÒ7ù“®ŸX9.þDß`FŠÉ-P”ºé¯ã—Lø¢”}HUè=oÉ—ôyµç˜¬e¨ÓºGk©´äÓ+ÌÎ)Â×MȪ]ô-CŸÍä˜Qz‹tž7]¡¿”÷v7ÒcS€Í¨cÑtž~XiºBà^4ñk8ŸÈ¼´43üÈYâ‹-Æ §Î盓HëèÕ`P'z=„°¿÷ +öÄ3ÿ¿VQÐIûõŠfÂüš'š)§·G3Ó;¢™¾u<šé»Ñãg»z43ž8:g^ÁÌãÂö`¦¬ãfÂoÙN4SÎÝ+š ³tžh&.ëD3¹¯`¦™ŠTÚŽD¦øÓ–`sÂ"ÊL‘L÷(¹§³…Ç1·JÞrÌ.Ð5GGÞ+ˆyýÝb˜.ðÂ|$ñ}øO0¨ f‰ø¥o:/Cà3tùÐA‘Kz>NàÒ~ÙÇdÝnÏ÷¼œPÕ‹§DàÜ0d‰ëÕ°´×óÀÇx%„Šœ*\¹UNÑJëm÷xoæB0ŠX¥Û„ŒTÊÉ#–S ’òç,‚'#èGK±C$¶~D0òb‡ 0„G-ç§M‚»zðƒ¶0Œ{MšGõN]`›¼CCnZ8<4 •“Ÿ›<§3Å&ýøæ±I—#±5ãüÇФ$Ë<¡H;¿òñcm]{àc&ðúŸ‹ðmäxkؽ¶»¥¬ö‹Qı•o~Yœ±ZÛ1h~K¤±…\øf^¨b¾@°ëQƒiGE0—ÿ‹b^ÆSYÓªõÚ',oþbIʱ•£¤¬„Z€ƒfåcm+%86K:,¦"VóûùÉBšþ÷¹±í}ßBÇšðòù„/s!GÀ÷lÌ1šÙ|ßoÁo¿%дë„ßÆÚ!œÅKXLæožÅ´­³š `(ßcR“cEô-`kZo47Óo–¡,üÝ0íÖäÛM)cžM¨ÛÇçÐãæMšÌöuxà ÿazM­X7úÔ‚€. +,‡¹уŒéÅ1—«ù-AŒÁ:»l>â™øõ$!ÓƒP”?ø.ßTð°÷ÙBMbü{Ó¯c¢?ߢb2í¸¿ÌaOÔäC&]X%«Iø…-×âú,ŽõxÖϘé{ð“ð5Ÿ›=ô@BŠ4'öžE»ð¶oy¢½©×7p›¹®Ÿ`—Äõœ¼K1“ð$è'ß_¿ÉûH’±…ðæ=®ùŒl±¾¥F¿óYÊ×Rþ¶ú&Px¡EüÞš»â«¶ÄÔ¯‡`ÝD³S÷t´ôO|Taq<¶qh4)&ÒÕØç*_Fä$Þ¤l^h5ƒ¥U4—ö¹dæ6)brÍôÓ¶ÛÛ +ö† y¹yZ˜1B+ÖÎÅç.¸/8³äÚ΀…MÞ(°&l¯üú•ÝÓÚ’@C‘±˜¦Ô{fšÓ Œá}1Ýb3m¦Ï6”ý1!vUß„ØÌÎs=0d©›Á²~™5Ò1–e&Æ÷Aê±v–¡j` eÍ“mŠ¡.iÖ/¾`ÈÎå:íL™:_5 WÊ8,3”Äóf‘W6œµŽÀ²vÙ¹x€UI­Y8[vJ³ÏqŸÙÂòõÅ5P­Õ›Tgñ@JY¿®´Ÿ8×àQݦÃDZ°õÆbR³ê;þÃÌ +ϲ¨ZEÎILx›J¶©n[å]Mã¸Aæ‡q“‘(“j¢:G}ÀFs?ã’†5Á4‰¥þì ŵï•c[kòFÉ=}šn‡`¢†û m°ÐÍpª4&ì–}Ju2w Ó¢ó^wŽÕqMœL‹6ñ¹)Oˆ®”f§.)„qQM´ÌâYñÔÌ ç|Þ”!¤u+(¬ +—yJÉ‘[˾‰ë2ü<62ÓyeßÆyœç³pþë¡ê¶»!ÁsKŽoÞℤ­“ sÊ¿¼©‚¨;‚ÒçØ} 2WĆ-ÕjÎm´&‹ºj/*Å5vN®´`U•ó‹+îûÞÌË—±Á9úCs=Úغ²Y‚Ð`-r*#¤øZ¦QÎ?9áê?úÛ¨Qô9Ù49*xš jIY%q¬ÊrÚdòÍ;&{uª8²Ä‚ðQ¶´­ySÛÜxóz ¿:¾ÆӆѼþn|ûŒ¸vȽP¯^—vòê1š?WâXµN•[ +oÖÀ5NÏ]m;Øx–› - u­ü9ó—&ÿ¯rЦñ„—o³ÎÝ<©:iûÉ/`³ºie^Gi´Žúf³º%é \è©äïL—íÌívšÚxF‘Ç2R×Ú0÷\Çó,Ëö6„Ü<{Ÿý¥‘”´¦®dn÷“¶¶h»S¼15Ç`m°l^¨4¹Õè’ëM]^†Ä±ý ŒµÉ[YÒÃT¶A¤8\Õ…0Á.7<_‡R\w“¦{DË2ÁÒ¡éWv×e +øêRT‹ŒC3RmØd%þ]õo-þ0ÓUÉw,`àËó +–œ +¬Àí½+÷Áý|ÙstŒÀfXîï©ûN¢¸Ë>¸â~X~x»ÝÃkG +Ì +¥wíÔã¼%ÑÄzËËónuº8'QqÒÈPRÔï"ð‚ÀÍÏó~¹&Žûsøçâ<Œ+.¥mѶPXÇoêDÜ‹Xó*Œ +Å}À:ô{{zmÖVSܼ´Û±GÑ|nîÐI2—uì¦ßrbŠÅˆû€@¡†¸OpKÒzrq¦¾Dz¥ÉÉ\òL]7"êƒLÄöecÙh¼|¯uþüméu5….k› ÞLq—ÁäÕ“^|=Ï/ÏÂ9þ‰PØH»É·»¥1ÀQkò´”Yên; T¿G&”nJ»¢£ ï›žTTeˆWƒI‘c(™þôXä!Æm…—Óæô†”¸I“Ö.«ŒñµÇq¡¡×{ËË<ŸQÌ‹ùP·àÓï'ÜkbË´yŠÿ?ÇNàrS¥Ã 8B$‚;rŒ8ÝKŒÞ»+†ÜC>6@´O`NÈùÞÎß%ªŠãYè¢]éŠ Õýd53²NÉÖDü3¶q¶t!rS5C93·³Ÿ+óðmJç¥`ËÑõdÍÂÁ#/ÃifjÔ $%âXѱ…>îyýt^™3V÷eûÜý„Ìs¡ž0“<5m¥%ì!_3O¯†W{¤fn**§ûÉ—(çîIfb’L‚dÁ³åÚº²jV,œ1-èúúÁ6ž€°Ò‹çœTýàätÈž*V)uÚ=M¢ hsSWU´…ñŸ¢´¬NU‘ÇVv€ãÅ× éÈsN}Êlé. Âi·@úœ¥ðÙ²²p~†¬ÈÜÁÙ!˜½û¡ÌÙ‰— 霞p¬âÕ™‡Œƒont(RS&“M¸ä‹K‚LP°”Í@®båýÜBD#Éu4TØURŠ;›o)åÊ•q ykbá”ýæ½°¿®µ ’ B qñ¶ .‚ÊöåIYñƒð½lSAGÿÍo„‚²7ÿýÝæ¹ÜÇgó@ò´ŽÎ+YA+»'RòÛ³„¼;3ã +Ú¤„Yg·z=%QþgguVr9Sð•ÿmÞ›P=>÷DY“zŒwš²¿£„ ²…¹7Hx8”¡²0gÁdÖ./ÄgÂ]e?åŒ`¥+âüù£8"1 Ÿ…À3×x‚¯Ù<÷·}ÎÃæEh2N!¿´Å…YU# ±w¼Ôè$SRÉ¡ùòxB:ÕeÄK\ðme«ö²ñlv‰b†¦"¨|’¥ÈI¯ºˆ[ØK9èþ`fƒŠT|êªü>ÈˇãÇC?Ñö6ämój’"Àƒªj“ÆI‹}SÔ/E_üðÒØ[¹ :?¦c%+—/‰ ÑLE„K…ÆDî/ˆÐ¸¸aâ€æ*4–bSÝW<Å 5•T½ñ¤yÉ#‘6”ÇŒì…ùxÛÞ¾¹—_4‘‡šÆîÌá‡fp4£,'±&ª…kSæÓ +/Ñá)_Ò„ êdcSú•8ø:K“0kä9”eÃ$¢$ЙPq(à}ŸÒe?* )c!þZ¸a‘0NÃ@ç÷÷g`¿~dÇØþï¯A ³® ªÆO]GkqóvqsV¼nÒÚƒâ*‹Ñ8Å ¬êMr¯Ž¸ó¿o¡f¤â#R“¯ô|¥+Ÿß~fc×¢é…Oƒ@YË?@Ù”óú¨háŸÖétNI¦¼ó%2«éBóõï?×äœ×ûÔñë1¯ìšÏéý±c»'ç`ãð…¶z½Ç÷ŽPýyÜ„ÒbXsŒšg1âïÛÀüõ&Pýz?ç3¾¿C©¶q7=e,Pû\?/=ÇjŒí!šó}ÞŒŠÞQ­ ãûœå¸ +üyÌŽ¿Þ'_çÌ>êÝ©ÿu5þEõ9h{æ±þóq²J#ÂUY˜­¯×?RÞÀâS_%«s¬iâeÍ£Îà÷?(åS œY¿ìh¼®ØµQ&] +0Rkû%ù¬9 J¤•ÂGð=A–‚õ¢P~TÆ䎄©5Àã? 95=¯–ŸfE5lT +/`Ma°#+Wr` &É#–49)ô£šÂdÉŸP3^/4›5“V’•šYôôXøÕt ©ª…á‚@ª(½s¥BU¨ƒWy–›"~oç[kñðèÖß!™x´¿šÈ5üySÖ~NðɪÌw#±ÅâbQ=ß½%_1å5–Þ*b·ç¯–Qög~íëÀÛX­3Á5+s¢ÛJ±«^MU÷æňªLÌÉ÷Ä ˜ÂÛš0|Z0:òT[{“ok[®ö°N|ûjÌ®ZYô#(ú5ò…WÚtQ Û&–JF/T™:U"t +/'e-Þ7V}·(1 +ÍY‡ÊHªM†Wþ¤<#ü¼¿ñC„˜TarRxþðÆ–;âHt:4ÕþnðÄõ\Ïž3Ø!ø¦å÷nOðÏ.~Ôj,æêûóqÚˆ{D‹·تrÖ±½>]Û MM_àòÄæF0–á ³ W +¬ê$œüE±3óªÅ8Äí™ÀÝÉ8ðo DfŸ°Ë +@ˆ'<Ïkt+­s/ÃîÆ_™9 o#(¹µ@Ìßœ,40C@ëqš=†sYsØIÁº(Œ´‰¶ï¦ÃQ;²ò`6#q±@-Ðè߬¤æ'Çfž—ë»;·pûùLÍT¸ÒvÝÕSg·oìkæ?·‰6W±µ…èa©¨¤/¿·ÿC2WƒVÑ¥h£GÓk»=Zø« s‹®ÜàóÁµþþ¶Ý!hùt *\„!S?ø^8#,1‡9n×L\J}u<¿ ·4Ö*œ0óÞ¨)ä7׋70wÇÛ°|ZÓ^"D=0ë¸5Àå3GÞêñëlg±‹=â Vç\6–RåUߘz}·™^}‚[š–“éÇV‹« +qµx}'ç ÆŽ‰@Y¿Ú`fÖªÂqP­äµÐŸ¿­=±è&7Å!À~³CÕ*@hùMJÛ–vãmÚ–‘Ó\:mžãj„\ÿ4„AÃC¦6ÑjfÄT;DƒX·Íî$ÇÎÙ y±Ð6°q…,e:3š=P"4^¢"RXÕŒ<çìQw¦™aæä³N¨*ì:PV; ÷ø;çê{ÿTÁ 7_U(ì‰÷Á°ر¯Í€d›(ÅiߢΉv–UDÀì3›mA8>Þ0bƒn:ClSàZȆ¿ +¢kžÕïqmC„Š£‰V?“K-_ +^XɧSôE}!ìaµp-Z…f +Šæ£ÇÅä| #T‰¯èÐâ“9Ÿ +®yð +¶pƒ¹¦6ŸÊçˆ`ÊÀg`g‘·Ì‰û$Þ‚R1=Îvcrˆ½«œ<ÇÄÒ h¼Øù8*§?g4#S⦓ WR¾×òZë_—ŸvøÙöÊ‚°£Í$á_‡À̾hÌ!‘ +Œ*™„oË!™ØÏ´¼ÐØ/ÜÞ¬¨fBK øK$d®ébkšŒÝŒËZ®×>_5d&r)¶7»K1‚;i±ø–V üa¯ïn-8»uœÍ 6Ѳ´Ö»ÍnmlW¯Ld„ƱfìnØMà¸Nnhºv³išÑðâËÞE8 +/{—km‰Î… #¸ÒÆÂðv¬6Q‰}9)ŽäÔÉ¡ó(Y6kq†$%*×þŠž7§ +îcòï²Åˆ±ŽfqÁÎñ¦æûâ×iZ;N–÷‰0ÛD¦;v…Ñ@ÄÄeT°Äiü}S2ËŒ–vz‘à߸¦ ++& ÿEÃ?óy;Zw„«EØEjö mÉé±TD]Šc +ç(CvX +ZrHF¦Š`éí:xcqËýçJ ˆ2‘à\œuÔ¤^NA± °œrz´í–õ¸Ú¸È…_wÚSšé¼ýÈ$/,Š.‰¿hÕöèœtªÕîN²0›ü;®uµ÷¯˜gÞHXÇZª¾kÀ<ê÷Õëù¥©Ú¥¿÷Ï=³)ešjç&lǾü¿Æ•TöÊóÛ`°B¹÷v¹G›Â ¢<óiYõ}Drö +ÁÔ4|‹þ˜Œ›åÈ„á,u99wUÖ¥æRÆÚ°NçôŒqóü„ƒÄ0&j¹FÂwŠ9˜Ñ˜õ~D<ñÇA`‚úë× +¸ìóîF—$<ùËb{ñ€«ò<î`Yíu‰xþÞ%<Þ.WÀæË$ÿýV +Ò组¥æ<ø§^üómù?×ßG"Ó<ø¥ð¾„ºPöRã%Ô-7O"¶¥ +OÅ[[6 ÈVËkòÉ :¿ã"I  uq£nS~ú +lxù¯Z×AˆèÝÅ¿ƒ‘ÌJ·ü.Õ.XuâRÿRA^ƒïæ׬M„.å¡y€¤íŒ@>…’nßÕ‘˜ +asmã¬qš=dF8Ë“öÊø_e_’$Ik·Sä~›“îœN õ—Žf­ZT/¤®¯Ä@FV¶ëE5‘î@<…Š³dÈ+Á‡0ø8Ä)r&S'S:krl—£”ù]Ï¿G æšh¶$#ÓéÇJÁŒ½¨Y†£]b]ùr—¶lU«(;LÍ®#;Š¶ÓÔ%ŽøE‰Õ¬wY€ébt:n" ±!Àžý¶fXÌR¦æ­„ŸÜ@cE3ÎVSj×ôæ`yù!ëðψS +F¢{Ùš+€hTR`òˆvËƘ¾˜ÙK7éO@–ÅòM 7ãb-¨ƒï–¼þ{§áªOn(½»°8‡¿ ¸Dz8òrÙ¯G§Ò¯WrŠ=]èžXíaˆ7ä{g ÄÅÔÃàËå"ö´[ºî&ÇÓ‰¥½§^8e…‘Q"üÞþ’+•ï[܇ûƒË7ÃRAwGOùxÎëç!2f\»Q7›àZÏdžZr¶Ò”Àð€hrˆùáNc¥è~¬!JSÏóïâ€!Ìö5µæ¿é$@WÈz4Uó\wI‰o/ç8âWOÜ­XbÙìU5îuBPœ+gO´Wºª­ Q1‚¶I5m ²qð|{±gZ*¿fbË¡Xû¶_|¯*YRÞ®Öraö]Û‹÷÷ˈôÿ~~(Ã|Èš‘»Í²ÿ¬‘ª Éh6™‡šâpä—% %‚„ia:䶀k¾÷ßWz$¢$›.ïÈç±g"pQœ +ê¼ðbHòÓtz@Ö+Ýã•Ñ~ÝbªíËzù`âXAŸSoYþØίÓ^cȨ.îÜÎ˦a–5¼xgZ‹šwæ_‡ŽÆ<ÎÔÑeÚË|ÓNS…É +!,ÖÑex_zŸ +s&¼bU+¯1&G…ö™Á…„¡®¹™‚Æí;Ï|*,²üà"µ1;Å1 ‰¼sÍÈŒ + ¡€T¾¿÷`gåïpžÉto%/¥$›°L{u—heRíÊŽ+Ì)O™3¿Ù3%="¨`[”~<3£ˆTþhà ‰uŸwžA +sTÁbOò•>s?*ZÆqµ±)!®ÃqôJ œüg³ýüÖ]šŽc±ÁFÏãZ!æu€‡š‡½˜É%•¶>ö2v&d¾­êOëÌòøð¾Ð%Öö<Õ&8š9ßÚ¯Q¼0Ê_üA(¸Y`¸7¾j¯?;ò7¡ëV7ŒÜ}uxá•Ú¤¦oD{øy—$àV’Ó¢þv;n¢Päzø¢ +pÒô¹ÜEX¸xYâ¸VáV~ˆ:Ò7·EgS'>$khÝà»É¯Áöl™NÀ¢t¸¥'r2¬ô®É–—Ô¸ÙE@pçIßÐìIØHÊàå™O0c* +¾i©°çtX}!òÁìÑyÈÿÐÈT›{2²'6¶Ä ›Pü„Lç–ØÈ? J'–ñ5{n¬šNIÀÚ­,X»£ªf›A=Q£‰Ó'èp„ÎÈUQ‡;¦ºÄ˜ …¦<ƒR³©ð2" ^U=”þuøJ´Þõ¥ÞР¢ìrÃJªrLlÌñîócNE彚³e·èøY™îãgeIo«®úÍ?0×L± à @KqbÆã0pùƒr"R|ÑDîí¶¡j^ï.ÅÍ?¾¥dþÇÁ^ðV&Sk*^|Áäu0B£·­¢žë¯?…ÊŽœWHÈŽÖF°ÒtÀqX1½d<ò¶r­ +áÊpfxkÆ;«¹£µóﺟð¯­}¼ŸáÖùýe‡';·¼u¤¡6!äPFk#ˆàÉhm죬­xŽìœN)î<šg°öñ@§ÆâÏóTÕœVÀ‹&~;':ᎉ?cµç­hŃí_mgUØŸË0Î\ îí£¤, +çÉm¯áúïš ÿÚk±ß¿|ÉÀï/s;;—Mg§%¡Á¹»þìÈ|l Ì/<ÈVöÎ[oÚ»V•-^óJÃtšRüùôæôë=y² +9¯Þ}›úWão AÇè¢t½e‡9©¯‰2¦ÜÌðey4¦ÖÿV<Ë¢œ»Y\MÅ^‡`ôßY/~>“KÃÄ{Â׎¨ÔÂrÿŠC*”›ÝG2 '}Ë“öp~îÛ·]ÒàwµÇþ™PyÈÞ[r¾0¼{»V#x¯ˆÞ‘L;‰®ú'7¢,Ï©*ßæÈ×9 >’@#Í›Wîš¼bßáἯc@"ÚìrSïËv¾ó/ö@´ ª!\» öæ!ävõ«O‡¾+öI¢yO—ìvD§/qù:ráÌs׌¦yà=9 àÎÛ‡[Ñãhbn˜/ +È…Ÿ £o[ƒRõÉ×?Ž¥U|9Ä2ìµ»Z ȵ”93ÿãæi"ØëÜ1VÚY‹S9é `×453cÙ 9Í¿¨Ñ'ø­ÚO¨ˆê8þÎJ'hˆO`¿³Íœ´cÙe¢ïXömÄ›f~ðÚ[c2+âx6 +› ³Ñß;ü!ß»°O8!¡)ZÓÍÆKÝÝT01^AÁ¹0ZCÞš1Ú#6F‚#!ÞXXC— ¦lŒ„ø„JùGVkYE¿ð.“ Œ„¾¥W…‘Ð%LŒ5?#ÁFB¼OUZÆ«#¡E¨ùEøš/Díì¦lÂ`tA¾^79AIh󬂿@@˜Ž@Úx{­9Ýô%”„ýA¢yß{r¬ ’Ð&!/€‘Є7lü6³Æ/ … 6D‚Û»F~k°^6B‚FHˆÅ¼Ê·5å"Ó^>C$4Þndºc—wy3DB›B{ #!ÚP"ðÁ©ÛC$¡ubáר©*ˆ6 +ðx ˆÆmgˆ„6]™R mpõŒ‰Ð-hD„ƒ;’0îš ­'CˆmÎOa"<`¯"Ì0KÃj +!!öjso&'ßopL~Eî !bmrç„,ÖŽˆqrÈ•|[éÏŸ$C6>Âæ ¶ƒßGâ'Wm²×“ð±!ÕèjA †GhÂPÅ­–GðŸ»?ŽZ½“ØÑ—¼›Á`¶;¡°š¿d;š +^5¡ †wÔ1ýKÙ(×½'ðel„5é˜p5¡eŒã$<Âñw¼ïám¯ñ¢­\â#ÄëQŒœø!7!F¹R­)ûa×ÊoD8Úø"!Z@àÉ´ÍÜ›¸‹ŽÍpox„F”Ë\ø‘è#"4‡èMÂ#;v +b¼q3Lâ#Äô-ãbDåÏÖ´“KÍÆT!lÍ&ÿr²I>@dx½’=°õÛ™ÊÒ°5¯)¼îÔ“­æH­“Ä +OÂ#ÄÆðkŒ<‘°ÃÔAQ$`¢Ô¯I&4P +ñbž¯ +ÐcžÃ˜YÙl47 ‘kø¶Æ?.û†Hˆ]Öû‘Ðz%i lk +Ä7DB³?È Í™]ÄHˆéÆ®fA¨æÛ?c$w<ÝJ2ß?¸—¤6…‘Ð…H„]I`“s´l¦øˆçj¼(6HÂÁjIh +y$H VÐÊœ’è«òŽÕ£qÎÇͱ2ß³¨ÀÙ°½E˜ÌÛ FôwÏ k¦Ó? Âë Ðö<Ž%J‚ +¡$ìÁ%@*ÂI€ÜPN¥ÔÂ#¹“]kÐH|%N‚&!l*â"D@$QÂ$´–üO˜„x?r„“ösr¶=G˜„ãÏ}¿þ0H­Ï—®Üö(Þ.„h.¦Ó-Z#Î}$HBt\év8)ˆ…’`…Ëç;^Ç­M„XÍz¶¬~Ë‘æâþús#nŒpÌ‘o-ªØÈrõ·?²«ÄËâ@¹Çå·®z°wîóæ(Hå®è`B$Ds°Ø=˜WŽŒŸDB„¨!gÍQãÌýÞRS Á†ÎýzYŠ +%¡#](B¾Ìñ 0BHÒkžM™WÆIé¨ô#¬çT‘yâ$„¥±Üè˜Éø„I­`”„4%’°ÿÜe¨kÞ%Å7æA䥡²|>ÏM“lªzøÑtZT®"v.׉2pKU­¶™+ˆ„ aÌñ†HH% ˆ^†H€a9úN©³söôzŠˆj%„¤g7‡k˜”¨dŒR†HЉOs™ëQiÅâð +ŽÅÿç8#¼© +Åg#¡ +‚n°jËü\B$€Ý–˜öÍPN£íÚðiI ­'høÅqýϱW^zþæéüÄ@ˆ½Xž³éZ¦f=/«þ‹'vä=1ZSynb$„0*ü¹ÌyùË ’К’©’Иˆ–¢a r‚$A0Uæf˜ÐIØ‚V –´Iȟ €W|¿Œƒ$DsroJvîTÂEƒ/$ÏIH›@ ¶à’°m$Ø&J‚u~ÚÆ“°q¨ì¥@IÀIèÙB³íd&ٚ̑ ~ÙKò&¡OËì‘Ð*ôS {±W¸•Û¨<¡VS(¦[}*påÑgñb{6{e¢ ád¯ŒËü§W \ Ý^E§²“"UéBû‹^Ò×jîÊÚpâÐ)Ã@þ«˜yTxÿd®È#IÖbì›}2‹‘gžòoævÊ,™“=S©Ô´^ada{”°Sfñ^`;e"u¡ÍtʨÆzsqeÖ$ßNÔñîå| g¥rnÒ-Ég2YˆšŸöÊâZÛ+c‚ÏÔZýí”qÕô<—«®¸ÚèŽÌ1W5§Û@Q— ȼä“ÁJsß-ADz%\8;¨‹ñøÎ$¿‡ˆùdòƒó¯£ëöÉ ·«Úç‚é]é‚Q.Øá´QŠ‘}2‹q~Û'‹WGúd”—B—Ìk·7s$þÖ=OŸL4i‘ËeigÈ'c^¡Of-Ëð™ Qq¹lŸ ÒŠ|2JGz>` ,ûd”u¬ä±ÐŸ?­}H–j «§³|ñ°3Ù=(¨Lö›*¡,v»]½;äô ì©šÉì‹(VF´«©¤†{ž—i¡*ë¨éЦ HF’ÂUèßiŽ9®)Ø^†…#nÏS-Mff—02¢MÇF©¶wœ¦ÁÊ:å vy7…hqPÈ{&àÈÊ݃€êåNb~y~Éû¯ÝnGâ (ÖÏ›°NšOµÞøäxí@Kïºà”ãqÐâ7U›ü¢TW.‘Ž®;y¹LAQ‚Ë»Ÿ+ræJ籇¥ÃY™¼=ÉIôØFoé€Vù¼(O–úž<ÚYÞô’€Òᇒa¥ð²=b(-þHÜÚ´.&[\Å1ÆÚ׿¸ÖK`‹žÒ$ ÂÛLFÒ¥³¸l·À„=“úÒ”?ð²oÓ"v¾ï¡K+ ÆPEºÔ„¹°~1püfRÒþ@P ¥_ò¡gõ7Sêä¿€G8?FÚÀš½1xEÑZcŸv(êɳ²í²™WgÊ Ò¥¦%Ê$ˆƒœ®€?еúÍÌ!9lwîŒÌ>ºtñÝÝ¡È€†ø‘œ¾ã^Ù?Ÿ¶?ÅçÃkKø¤ÏáÃÌÚà4ô4›::E˜UÆò,ˆ5~™¹rÍíø8¸ÂË•|ó8Xá;+m€‡?3«T(A²Ÿ ƒù¸BxÐ9Ïé2yÎK„xå˜@3ó¶ÐÅäí4¾ƒÿ*Y¶”A%x‡}l¼]|FwQnt‡<äÝ!42{:Ë0غjì Ñä43xC +Òïö\©ÒAa2C¹ue!t‡`ÏÝ÷‡üä U “3ódzàÌ>‚whÎw¸ÓJ<¦Zô„w°Ñ«¤¤½ÙïД—"x‡Ð*È"¼Ã–„‚w¹ÙÛÇÁ$ˆ¡|癳äÿÁFIàìÜéæ—€SwŽ´8º€Š¬Âwþ¿ àй[f>o˱ññ¹ï¾à! +Má;È9e|˯Ş.à;Øj5¾CÈÁ;ñöð“0˜“.|9Xï6KÆ(¼È8Î ¼C›‰ûAx›f‚w fr‡q¨v4ÞAŽhÃ;ÈOcµ[ð>î•JÔy[Ø×zÃ;8†!qìoÙí‹G(;|'¼BR èK¿ù‰ ´0}5 ¿þèÈÆvØža;xñ‰í §Á¶9'p˜sh>> àÅ,‚;4^ÒÞtÆBÁÜ᛬ºÄÔ¹ãÑ÷Ãà +a¼ 46›kH+lÛ7ÌÓ‡°ÂüO”‰.‹_°Ä!¥„í æç‡^¦ll‡`„²>6¶CØ!—!ÂZë—+Ð…!ì’ð%” »l! ‡ÚHC¥aód'¤U‘ö t?qÓU³'`·…ÍOxŽ¨líý$\‡t~×AP©Fv×AîCt4ÌP•A¸MqÂuàí +Ÿ”ÈÌëbžÄ>ÁvcLˆ_`‚… +ñ?:]’ŠÆuÐñB¸>ª×A&‡FÊã¸gB±O—9~§ô×J‰p"¸ç|.D·ÜÒhÂuÁ¸6¨„ë° +.á:ȳa\©<ã:´–åü•5'‹i;4^nØÁÖ¹€4ü€£[ ìráMnœÀ§£Ô3×í +ëЖaêëÐV¦* Ö¡­LDrL®ëЋÞÖ¡_¬µþ 7ë°??2\í­í¸ëÉÛóoÚ™)ŒðÚÉán¼ÇóÃB›î¿-8¥àR·oL{:•N°=¡J7È¿3?Ïd¾þÄtÈï/X±sÙÌDµûLowÞQ~½Ü»k“Þ¡š7NÝ¢Ãñ€†^îsfürOÜ]ÎI=Ò"^ÙñÑš/·6!³^n3¯¥›ÁI)6˜¼M9KÓNK…’{°þ»f¿Þ¾~¿ÖÁß_V£N$Ps'™ˆyŽ¯ãç„·ÑJd%?$OÛ½³ä™G8ò™”r<€¥ðÏ5;ûõž<~]I)êÝ·©ÿq5vRJh†~I)Á‹Hl€PÔʤÞ.õ@-¸wNŠ6µcñÕÜ9)ùwFàç#sRâõ­œ9)ñý‘)'¸/Ø­a ]%ðåO‹ƒhx|”‘²ÚÊHiÊÓVFŠg^}ßJ )¯ý2R#¥œ‘¢sÊÎHAPÜžRU?aóµ;¿Óö2lü‰JHweBJëÂ!e> +¬4 {*¥)iSù(ûX®|øçz&¤ÈEâ|”í#Q>Š|$JG±Æ¹3®ÿÉdŸ„猎Wžâ”ŽÒòªäNóe›(’(›ž¬WRhú8ÅžW¥£@–îl—Ç×RB;h´ôÊd”à±?€âëú¶ô Ä´’QŽØ…0$ŸùÊd”.@½½JNc0YþÉ(ñºRœŒ"úòª^øî\Ì“&ý;ËüÈE;E‡Œ²#› ËÝÞ<íœÉ(ûü³ TÕQØWÔß;ð÷«>,ëTÛR¨“O´#åCC¯EljjÜ ”© ¸_, ÄI!Ú¨ÙÚ.È:·ù“ò>ŸË m&l Ÿ± ä DøUJ¾±]9h3ø«Éò¯iÇã¡‹oEÌA¼£ª}±±îÑV´Pt´³£WÄgbl] ƒW¾RñKÏB`A>ñ0”‰€§G*57ʨÂ'öõîgjÊúíå +Ÿ¦ôŽâj¿÷²Â0Æ?Öök½MÁÚ æäÌæµ=/ž ÇâIIW{Å‘äËF JH½x0Ñj{ô?S½eçk˜?~Råúػƛ\£G/ +Æ>)vwÍc!ú®ºÚ/-ƒÄŸí‡(­Î•\pR~ý0E1m¬Ãéžÿƒ·‚ߎ±Ð"©ý–© +Þ$Ê‹k¡„ýfhgã%Ú`ã~å‰;ÃZ‚‚õUžÚ˜Þ’¿P¸ò%çû Æ +âÍ¥^µÅ€ÜÎ`„øáÆu¤ãQÈ€l§$åb¸uGçÿ.zãÃÉgZS¿µAãô:°j(WÀÊŠ±òØÂnUd…)´_´+…€D:ÏÝÞßyÓÞœì.â=s+ö+¿¡Í³;çÛµ=Þïh‡•D@¯ $™±à @»s<íæß™WÕ;½Òßuê LeCZ`¿´ÉHÉÎuÿ†ì'Ç)à?:ƒR˱Èuhïsëvõ}éÕÙ»¿)Ù6.¥ áçM¦ +Ïdëû»-óú–‚XÖ˜Kñó®uè4cöñ+U½½¦’áí +Xq’ÜÞ>³íÍ¢›hc¶ +#?CR…ßó˜‹øÈÒŸnòä +® ”-žœü»Ç³Ìv$^^¸DQÕã*ÜA{w6n1`]t"çã>Ó„ÏYãK$õŽ’—žÁ`—(“uÎú—ÁÚÛÖ˜}¤’Uth¬-ƒi‡ˆb{禜~…æa†NŸzéb XŸ¸O%Ó@O}eYsw¥À6±s: 6CTÔõÖVÌ-)œNñÒÎ-<¥>QJ +êçÑO¸Ð «LëÅ “@Õ¦4cí,¨?Ñÿ é’ô,qº,©ÈE +hAز +eNazÖ ¢ Dõz›|ã`%<*T³mL¾ÅV€)VÙAÅ¿DDÒhÉULÒÞmeÛ”˜ÿñHQGàáÃnõ©ý¥f$ä}e7Je{`ðJÝíOÍDÝ~ä¢~`/eãv{=±h·‡§Ç€W®awùÜXfòr3bÍ(yòTE¾¤À`TsqS”a[£ùÜÜ倌 ùt›SÁÓ(œ­ÆoF•K¬–yuƒá€øhüûÕ¦€ +ìa_¾ÌÔ>Ï‘Ah²pTM½Ú Ô“€ÙºÎ![â®í»ô”úC"± G• +Ýÿ –tÁÝYR¡¯¥³†êaô}püdƒGòàb‘ÿ¢>2û%s-¦XÈ Ÿ+Ý$_Ç—еû€…-Ô«ã#BšØ§y´Ý+sdœJ&- x™ÉÚ³z$íxbØ`®íº:ç|ÛÔÔOó¯Iï@#_P_)b‰¥Ñ~5òÖõpåG'óª%oà0ùy +DçYç£A¾xòìàŸØo…Ô½yù¼a8ß~œª¹ù•‹ÈóÇÄ/UÆë+”­Q;×cô®n±ØÉ*»Uòûþ枇撟ž¥ÿ`^6ÛülÏò1‚íôIJ³¥>e‰vÕXx¤üÙ*˜í? Æ%ËŸ¼8.æaó¦Ä÷‹í: ³hY¶$qeç-ö ¼ê%Šœñ§žK‰æÏz{¢{…ìW.:²d¡2¹l±rù‘•èy…>®–µ–öCSYÉr¹Å7õ7§iOÙŽŽq`ï¥ô]”s)|'3–Î.»YÙ`òù°8^LZ÷é`(kÜlÆÛmf'kä‚Ÿ^›òëûû¥œÍÜíÿ|lŠ$l$aŽCÂ"iúMÂFŠî8%,r£Ÿ-?cðMÀ.æ¨ìšÜ%‚^ˆ”÷æ™\a¸Ò+ÁôêžîN¦­wú‘äþä/&õv$Íη]WÃô<Ôö’'Jj;ÀÇßüEѨ3‹¿zûW9Cöº×§™"½²dÀR¯Ä8î7½”uˆ%äôÊc4ZɤÞC±ÄôÜk+–µZ8¯2Íþ9K$æKè8'Ü's +¥çûüEHmÕy8‰]WR‹n ·¶Ù#GV9) Œ Èènéb"Ü„•? ƒÃÀ›‹M£¾µ°”t”:X„qãÂDY:Úºø?°;å?„«$?û²©ðÚû8‰˜^‰f`{E+ N¾¯ùÏ|ð7€ÆhÕ¥ö‹,ʾÏXø“q¤+ÅâXç•ÇZé„""ÒÅÅ”Ø`žìsäª^2å"ò=.ü×¾ò@ætÙ²ŒyZp}æ‘v¾dê1IG½Ò•R1VzÌ’Ç÷YG»dÂí½R}8³$o<ðBÉÿ(÷øFàbž8J’ɪæÓ¹o¾ `®OM½† +Ðaž·hAZ¹TzHÌÍ=·æÃìÕSõ1úx tg^q¢}K•*N.V¬m}kð¿¼òºß蚦ä•ÙéýÊ îÖ[­(iznÛ8û¦¤%7]TeÞô×aã¸ñvëÔ]EW¶—?;—7‚/̼u¤,?›þ1t̾.à$Òy „ìëeù£¬ÕB§t>'LÙ±XXË'§«Ø>å…Yƒü÷Ì~´7‡n +3[Ìá ¼qµó¤§|øÂ#Ú­ÙöճFá]x€#›î pU1º/<)ß÷&¢ôcÁï7rÆ߯ë#þû¯ÿåã‹E>þ×ë|þ#þ©¨­ýÄòóŸ×ý\¬ËÉ*\_lÕb ‘ðûã¿}ü§Þ÷?ÿ;z€Ó&J0w¿R Šò;)æCSÂ}ü*)/÷;æ<¶å}«„„)Ku à„‹r6plÅÎ'’WƒT+S~´' v½Úá[8žÀe<ßÀU‚8¾Ré–s7*] +ÙËÝŽq|šòiˆø†¿o„Ë~ÝøÑ3Žn‚Gï‘€à]2ž¤h2Þ^Áé:?ãÝ=áìçû’|þ¸L¿˜¬§I»¦Ò6ɤü>(¼¢Œƒ@hÇP6!G™€‰#,D3›^¶Ÿ2$ã ˜Íù߸€Têm²Í¤LFò‰î^Zïæ£ÛQ`>ûFðj>m¢ï¹=OùyP" _h¡„ ðP4‡aFûš†óŒðŠØ†>ŒµŠvS"zÈ#µÅË{>—vXPÈî|ØV6)E|ã’ÖˆG•¬we°\mÖÓ¯(Óà„\èYQœr[!÷ÿ¹8_¡T”îŽíÁÄÔ0c¢Ýô +ˆÇÐçA!Ê&™%RA!Ž!‘‚à¬é°lÐ~œÝ_B Ó'×ᇨ +0^Ià:„͸!6¾Z™ñ§E¬äHÁ‡k9nÁHÆŒ? ¤üÑ#òóB`ÉpªÆà™øÞ¨ÿ‚`Õ ‚ò¨ÊDx 0êåd3œíüAl ðlsa‡ûæ¢ôšã¢Ý]?¡tPX_ÌÄ}¬rc‹ ?3ÇßÈìÄ!æP¤ÄpãÐòûB ’Eã°a”zW®K\l)´UPŒy¸¸’ÎG}´¡'•±ê…[Ì€+ÔÂ/víÀ0Ãøƒ¡>püð³æE.§yE{vÁp>Ÿˆ{?¾í§—7†\РLäå.\ƒ [XØ¥m΢ãüÉÔÀŸBT¸u£Ù.¢æ‰Y¦;23.qׂ‘­ÊYCÈaNögR´dLºx‚ÙJ\¼¶}§´ÖÕæ‡îv³­®iü….Â0ë!N&§÷Âx^›üÅc!¶»FæAê•O}'„vÅÂTMÒCáJóQîW|·E2,LÏE´½…F»,;°§îœp¤‰"{ ÁS„K¸LfŒÐ%òC² \ȼÐËn Í9øQw +œ ¥#eQf5››¾¾ø"á!;Í>öDlýgRö:ÿúa†ÎßTðÈ,ÑÖ*„»I£úV&0×nX|¾3oô”šH¢+÷–Ô‘IûPµ:6n–¢ëáû¡Mi(Å8\ÂWð‡·þ.a\püe¯†@ËU-¿Z×Em&AY¦¢zš ¼ k‚þ pn +/ßPˆ‹8‰6{žÇ½:a2ë·´mµÄÔ\õ´k”ä{>"oˆt¤éòGÔ½}X>ƒÉ¬¸^6°ÊÞºE¯ÚÔ/Ê|¥jÿÍw@Ø,°h¤þªWW¾ÕhÎ;y€¼…p§³¦ž)¨²µ ÖüYÇáÒSœ»Þ5S·fà:6š3Uº`1“}7-e6å‰2|‡uwÎ>™y!ïW9Úu. +2õù w3µø{¹ÉW%ûWÈrúú•…ö¤+ŒåÑŽÉGP#æ›oèÔb±ƒ;F`±Q8i9Td|½m²Grj +¤1jªp‡¥°›•›ÐZg.=í=ê^³Äñ§¾i³«¨O|Ì5Dz8ű$_Œ«K6¶%Ö}(9Ç8„ËV, iÛÄX4¼wç!´%›ÐHòw­z%C›¯·¯0¦¤’dJ‘H&Xû)-¢"…XݶíÒæ_ÛÄ,5çS¦IavGš&¨po[DÌvÚ&åÞvì$£DH^Q«e1?zÑVî´Žoa³ZÀ£¢Ê7àdôwµªâMÅAþ¬zÁTÔC—lA¾.q¤TI½R1H•Dvé:UIdŸŽC•,ï 3ùÊCM²rgI“¬Ü|V%+·'UÉÒöµ*™šô­JÂ=õ¦Jl#P•Ì"V%3Å UÉL9$U² V%›BU2y%“ªD¡‡*YÛr§*Ñ•y*ŠÅ+Á­J”Ë›OÄŒS•TÖ§.©¬ˆ˜º¤ÒÒK]É»’ÚÒ%ÕÖaê¥[—D†ðs§.©JÙºLpê’z¥B£ ^VxÖ%믶ÞþþXÙ\‚ã¼Ú»*YÚœV% NäT%»i ±)R%Kتd‰™·*Ybw«’%›ee7@xª’%¸UIðû³U Ðlë©Jê%qhUKXëV%©€‡*©,ŽT%eÖ·*‰%½ß4I¥»<5IEšQj’Ý”&Ùj’ZR0ÞJR_cšDuR“D—ž­H¢Çu¼)’ÊܳT$`ܶIŠ–ñÕÇ¥T$tpo5bú§!$ÎùÖ#€E×#¬Ÿ´õÈD€ÈÖ# F:õÈLzd²#R#“sa-²r.­Eâe·‰[üçÔ"K>‚q°Ùl‡Q‘€Ô"ÃoZ$¶©Î«Ð"[´?Z¢Cô;¯ÿM“¶Éù BÕåÍ>&…ÞNRàÃÿæWo¿ÒþÙÍ+Ž);òûíW ìAEчqP‹CL +»³Å” +‹˜ØOPP*“¨Á[*Ë“{ç1Öîcí'ž•ìÿ!îÍìàâOÄuëçˆcE5Y#ÚQ•7ˆçÃüÞCÆÅ;µ±è7E·6ºué$Œ{jãÃج·äBn™¨±Î'jZo„Ò»º5].£†UÑ¥èl‹R(éÏ®¼>üÙ­Ú¶?;ŠG”²ýÙÀ´§?»*ñÏþìÚ·J‚0vo­¬’O ÷2˜qö‡?»Ü,¤?»NJá•h¥—ôÀpz¾¥øàë%ÍäÌ®#%“ùväúÃðµv•ÜÂ]¶€”3;fB>iz©œÙ1Ù×éÌ®,½˜Î쀧3»ny:³‰¹|:³£+ÏáÌ&bôvf*÷Í™ +ÌéÓ™«.M¿°ûÛj±¥A/_vŒîc{²k“1*Ov|tܹ‹ùŠUfnt°‰\0•:¯Gvõ­Å~„.é‡à‰Ù»uhŠíÈF*4*(°v[ïAY|Á:ÙÑnïŽì ñÐlÖ©ýðc,2§Î[˜%S¶;p‘A›¢oá}”ÛÖ,ÔÐ’îÛ±’~ì?øB•Wp ø×cÌ]ÅÆÓZ*) *ù®²¹2^–ò\tgé_2“ë=\‡i~oݤÝ™êÚÐ|âñn¦C´íРヿð;PdënŒ‹™TضóI «)Ëh“M>ØEãän‡·äÑ/|E 6’å53«çud%e°¬[|¤“ûàç¾[z©¯=Ž¶dFÕRŽéÍÕ¡e¢˜ÆxÞžˆ x •Ó˜Rm{Eô£‚v›˜!_Û½-"þâeìíUŸ¾›¸UníÑ\o¡Ø5*X[3Ò¢å;g±(‚í“ÛLá”UùãU^W%ðî +ð[c_Q!í‹@]0¨ëokê¦çÚ—Îz%ú3ø[)²ÿ<åÛ>¼o¤¦“K´gïI×òÀ‚°tiB˜U·7çlÊÄGžÔg8 ÝÔÊ^=éœÃÁâŽêÏ(õ ðW¢¼„'þd6¾ÊbhNˆýÀªšÄJƒØ 0+c«Ýü[íªU¡¯ +¶CŽÁEjó'‘;|>æ9_ðb߯·o¬£,Ûºû·Û½Ž”WpKùó(t¾;¯>÷×)!vç†bÐýW>îG¢ÊÀù +ÏÑþ†&ñADÐ1Éìáû2|þ¸4»xi +'ŠþØôZ“òû tD‹ÒîMy1t=”`$F¥Çù ••ëf¨Ë`YÐ AYhΊeï‚ðtÜfänÃ4ì'Ü +¤EDí¥n… …1žÐëRx1Æ“¼jpíh#ŸåFQ&¼!üMAÀb¬[#­c¿`ñÎÈ£ÿ0´P4‘V¶˜ˆ¦öKcçïGüN"féê4¶V3²ñv‹8þ¨·Âb¨¿wc ÞFQË€pDâ{t¥?&`QBרcÆ¢MÍVB”#H3„ž^|²ò“9ˆÛùyPnlFf(@Ïå!¯@#Fûâè3:ôÕG3†ì´U´&•hÆÔ^ÙvPw=ž¨´NñIF…Ã3‹¸¼hœâ›þ(pÓMB›»ý ÖÌçiŽÑ.dž%À6*ÜÙ,™‚ôpºªé¢~X´õQ:“ù¸_ÜÞWƒ“aQf?†FÀÆσá!¥c2Ê}®2Ôþ‘3B0;øPIyPýû Üp¢Í)Cm“ˆÁ°™ ô¾5É[XmÌnŒ6å1A°0U?ðÊ•Ò˜Nñè„W’ù9Οt0üFËHÁåðÅ;¶£°ï~¤ó®~ÖLÐ@pÇæÈ. ,»ãŽ#k€ÕµÉoÌ24r0KGø1áÕÍ,7替06þ§Ÿ˜Ìà®!yÈÉþ<(X1&±Œü¡·“r#÷ér3Q¤{Âê®9O—¿ƒiVÁ*,D{6$ð<’¡U­gÏÌ:‘Ž&Jmïüd6ÍÏÍÆ*&¸jÓ{«t€á+…© 8E„E*CÓæ«V›KgoR^N#@{-ºŸê´8ˆƒ2˜ +´Aø?ŸSÐOž…×1ë!Pc:•áÙ²èrÖ†™ U A¸¹&LEpûAbØçAñBÿúaÿ +À¥®io +³Ý?\š“›çÖ8KêÛQ0┇äfmP&;»Ó ™•‚¢:1"ÿauÅšG»"÷W e H /ä¶åV¬|ÔêŽös³MI²åñbÎ}˜«21’šèöѶ¨TÜWˆlL,ÐX¡½(l³íõO¼„í>ò01&cæÓìé‰çQ¶Xà .”ØVËR'm× h~ÜIÁ +Ù9WcýaCsÑÿz)Ó<.ÊÆþ³Â:¥àµB_kö߆QÃÈŠaÏ4Ò.6pi“Ðd$?Ïz»±ÁR"Xóžj‡SÁ-,=…oØRú"¨&*ã¿ô‚f¥ªë÷óÖ¶ Ù$^-K³óRŒˆF~7\ßBA%°„²"Ùpé–ÌL.RjE;—M.•Epž‡Ë$ØÒSÙòi›œ)ê‚ +üÉjäË0¹¢|…ãÔöÒšRVÝŠ;f-nè‡ÙßÚ”—'åV¸w0½tïfÊcþÀÅ\/–s‡"`_}ž*Äø…xÔÜŒ‹RÝh~\« +Ìž~AŒ´80Ï×!ÅW<-Å—L¤ýÄÝV¾Â˜x©}¸¥6Î3%tkÜÕ]B>*ÍŸr‚ÉLËY>Žui2lb®4Àm—,†˜¤a²PWVÇëàµzì±´c/¦Ëð´Yy#MQ̦ðÐqò†ð=å{]oÍ–Aýß•=I+¿?A~îó~T|f¬o‘:%_ë²!W{èè»Wûë|ú:;¸¹^wp©\¿Ž'˜9«ƒ㯫lo¥.ÕãNµdÉQ™#àWzÒ£’²–ÖÈuϤé§i´u¤i#a÷ʼù<ÚŸ'ÁC7E0"—íÚö—@džÅãHï/ÉuÆŽ·CK ‰Û­Gèo?€÷jdE¾…—£ÿõ$ŒÐâ+QÎ8bT۸׌—Þ¡’Æ¥¿+’!%Ûè¡‹¯4y¦Öø»"y(—"¨q—ŠÄ†¡ Ò4FÛç4Þ¬ç3}C6§ÏFÊ£È|ÙÏSAà,æK(ÀD.f©b™©wû_²ŒîüEý­®‘ÜZÓž¦·g¸–uN_Ê¡¤÷ˆÃ<Ùqh´û ®#Ĉ}çy¨_ë•ê~M©Š³Ï ü=·óßj:–Ï…væ¦ÐYEŠ]`áÛùý:Hù³r¥ÙóBF9_$Êù¢N«ßo”:+OM(!^.Î7jA~â s…Ç s9¹åJÝ¡é/¬p>aå°â@ZcôNð'c;000õðº3|É¢–b-…E ¤g£l±„¦ lŠž÷¢?ÙQ+NÜoÖÍIYY®Tƒ–¦ p5[š®t*l±Ö¡ÒÌVžäˆ’·Òê@ +ò£m+c¥7bŽþRH—]Ç•þõ« ë*ý 1ÂûL©å*é…ˆÕlÛÙyR`¶9VS~à»Ðg» ÊÊýe'4ã6å(] Nç¼Ø €R¨¦ýuòB3¬¸¼„çèìó‡»Ý’ +}ÇñÇ+ Áohͳº°Ênbû¾Ž‘ؽÇJŠ'ãxÅÛTGf÷aO4ûø¾Ÿ?.³µúïH±Ê{’?Fž9ˆÍ5xý&¥úÕ´ïL’2°Ê©TˤŒ—Ò,S¦yjUx§3€A‹*æÞI"Ç(’J?©Šµ¢''âIå“Ts¬[r2 áʃ +.­"nªq RÅÂWIA6zåLáÒó׎Ùú<(÷Ž£\ªÏŽ… ¿ÅÇeŸ‹‚ݬš(b<[)bÊL¡¤xD´½Vfšxϱ"‡½öÕî•Ý€½V†Œ±-¡‡â…l¯ÅªWªvØkelE.5 ÐÛk'Ñ^ûÆZŸ¸ò8lv3awã/‰;7´_Óˆ±É°„…QXfTÚß(ÝѶ“ó…Ó;òt_¹q¦¬ºÊ@×!‡ÃÍOPŽ7¹sЫ¡«mÓåÚ”°4p"éigŽíQ@äeÄë¸íȘÜåëy,'àË¿¯÷Ï<À€E +Y_š1ºo~ìK³Màs†Öv^I)r¯ïýI¹àjeP?nʯ:ô7¢\|9îbF?™‚ºM#±Wº¬˜fÇ_Ø‹Â%iŠ+¢2æt¬IJ]Â6 Oº¤"Ø.yõð/b¿ò¤ô¡«"ÃP#ÍRÉ!V<„Äæv# +ŠÊÞúmʇM2ÅëÕ}P Óø‰ò:l‰zë0ó%¶0?Æ+0™D5r•sÿ½@ðõynÍãv(ϦÞG‘]—NõØÔ]%§ªGÄøž“WfFQ×]?@3L¼vψ3Óc€ã̦ «C[KÅyˆº³ê úìim,e)”­ê2¼ÜC¼(ïF®nK»ìÑ8dŒ4àÝG›?(ËFy¤n‡Â 1ö°û´ÚïÞGŽÇ°p—°ê'eÜú W¨§ôÒX`®/Ü­/RfîE³ØF¬,³Qp5O^§{ŒíÏ’H +—ѯ@ä‰b½÷9çôÎÃÎD¸[g·pg¬ §‹·¼Øù×cÛ’ ¹‰éõÞ‹Ôå”CÐâëM¸8Tï?¼{IòLwöØÄâ#eQô¿„böÍØ"à”îÀhšßc£‡¹?±ëÎO(kƒox}ëü +Q³²K¶ª;¹Û^…å ú&>¿¡‰]V^¶÷i`/vƒwí»›ÀÃ|#!@æç1VCfNíz¿bf¼ƒ?Óù:ºáév7ßä„àòÖ¹H²9¼H_²µõã³wòq®’ ›ìù-HΙÇxÞ¤ìáû OÞp®ÒþŠçØý𲸛»=Ëó¾LU1Ø~Ee>GÝnÝg¼­Re¥©ì¦î÷HÒ(αÊ*ÎUò+fÆ7<ãm‘܉=Ýìäû‚ü¼H( +&Øݤ´Tú÷µ…³ÀÒìÇù4Ze¸ã.iè@`Ýö§À`Ú~Â_Ò蕈i<, +Ù/Ñ‹çNP4ì´Rvóù”Þ§ÔÑ8±5Ó‡Ë]÷•õ¼:m/Z$èi{шžæKoçù BÆXSפ޿S:úbâ¹'úÕ±BIy`†E +—G‰â¦«!…U^Ä +ÀAä*‰¤Æs^K(µÃI#,5$‚G£é 'ÚËxj‡'MxjéI¢Z3ŽÔ1ƒ˜j¯ã‘ªã£ÎmBUñãDUKSP¨iº~„Í ›åï8XY±†V£¤¾ó#F¯†Wƒ^*{“ŽYÕ?! +€÷–ïÂqße½Þ¶M¥!5‰\dBÊ>É™JF k¢¼> ³;‰›f,Sâ¶[²SgßûÒî¶_ÿnÛ`k>Pl´µãБ”<˜Üí½¥ñó¨“ÿIÉR~Ö”_?tåÿ/ܵfHíxWSþx€|‰ð0DêÔAF”ß›À.¢ðGIˆÊÆEˆºðøðIAHB´ÃÒ˜„( +=U«'ÚŒ{À|,ðÐ^Õ2n†²MYÈj‚‚+ƒã \â/vÃÛßè̸Ê^tòAör·é•…½B8Æñ +à>á¾:»I(g7/Ôl8FB±|Ž•5ªÔùŠ=[þHciàÝ=áìçû’|þ¸L¬Y­î‡¯†qÊdR~”"·5uÃìM +¢jÆŠ¼…-=jÖG6c)ØwñÖiTh…h3`d(4ªU—žm†TBù‰¥lÞø‚tŸÝr„é… ïÀ¾¸ÙÉ©[†v´‰,ô¹)BÃW#>Ú—âK1ÎÀ½¹è _k ¿t‹Ø9“U¶áOd½ŠÙˆ¡å#3_ZéSÀ”ný7’@ºQšQsȃðëáMIÛ>V[FÞ(`ÿØ“ûN +b¶ãˆíÊtðB‘<Þ1Ú&r3Ên·7k\:'%àrêmf‰ch`4¡lòdö>•£Ç•oL©öitŒ„ˆ§ VÁšL–žKªFrSoO@ö]tæV€ex.ç8òÐ{qº(hífp†Â-6%¬«h#ƒ}Dqq²Êý`²® Ç•%ìæàäÆ gÍeŒ}µïánqW”¸¬VÁõÉŸtl$,ÚŒ³3¿Å*6ò[›õXe›ö"üÌ,#÷ÙV¦ô…{ƒßo”ðϳ͉e d¸‡*÷‹c“ÛÛUeÞaâ±üÅÐB\úëÅ[ ’‹cK1ÀýÒv¡ÙªÒèÆä,VÎõ.ÝÑëǶ½E<‚B x??ÑæÊ(3]ù‹y†'â®2:Š–÷¹_ºìbhµ˜a+wU€ªÔà˜˜šîxFsá­ŸÀkÑQYñŽ¥ç|n +Wíåðä–¤“«ùR¬÷^cFy3{ ŸAÎ!b‹žspS!ÜŠp–] P‹1÷ìûaŽ™ohX ki–®"ÙÆy¾ ”úÌ]s3€#¾ô°d5’ú_Æö]v›¿¸ôÙ/ +y ^àxÅ¥u§9¼Ž>cWéçŠöbð±èhFÊW1HT!"ÝÃ/Œœ·Xº2·ƒ,µâ³è%ùùÿSò¨+üë‡íËšÜEÛõ¦z?(€Ž]º €¾C¬(77ÿn;^ø*:Y5C`…òöDàaQS)”¿H3uíËîPÈôÔvO¯om ™M)*º¿4.ÂX *ä È·(™ ^|Â=ÄuB´™¤%›äÆ>n±|c»pÁ '‚õ\‚95•¥l‚ÆQÈQ0´ô×d°<ƒœuÉn˜ç6s$'åÓʈì!ÝÒõ +·-$7…2{HŠ7ÙF’˜¿°¥…3L +qVø DaRà¹[7m½G‘踮  ¸Žù¦ 2!r)\lJ&´%-¶•ÀŸ‚½óÂ(_¡À³ãq~•TÆ9cõ”ÉáR@ŒÄú3NIщ>ó[ï(§AÒs"h^v[߶Gˆl¸í‘Á»±46†5ÿ<¶WoOÀíÑRÓò¦¶U ¦8E{ÑòœÂŸ OßB( Å @h\™ýòz3´(O‰AÁµuž7¥dÛ-9Tv›Œ*Q®¹/ŸQî؆ËíjÆ‹Ö)Qu—÷)Ñ…™·DE€éUŽ'Ú‡‹¦ðKïSb–¦Ö1‘õ°gwÛÇĤð˜¨É}LD´m¹õeœëÈc"ªNèü‡QŽÝþd¡çK›ƒlsTðM‹ï܆Û;uh/TÝ'Ä\Ããˆñ™§€¬c- +Vdæ ½*ý8"¢_HüÑ·5½Œ +5_øˆ˜”<"â7bvñÖyç‘•±Ëa¢c’,D×x´ <¢0ö|Î3"*_ßýx„FÞÅ`œç9‰ˆˆ–3‡DðÒ¨>$f3-““üe¿‰h_ë<$â#Ò´Y}»¦¾Ñ|êA×uŸQµºå1Ç•GD𚎇˜…ç}…xý c„è¹wi_"€ùž‡º)ÎeËÛðSÝ&ퟭo–M)¸„?_$Êñ¢8ÕпzP\ñšg2•I¸dLë]Žäf™v°ÚwߎÍy·‹l#yøx‚zZ’ÝšÚͼóe!å•ì˲ÚÓ'IÆŠê,å\³µÄs9à·èsߪÍ}ëÐ3ÜìcsÝ=µþD$ëƒK}b°oç"DLÏó‰­†Pi1b®«O;—6Aí›:ãŽöJöÉÐ#b;~lÖòjÿúÝë™ +ñÃÀXÄòGwcG›¤Ëq+'xËÉ‚GÀʃaÐî5Û9#£¼Úñwz%‡mó‚AÍ/ »*”D<²Ï¯ª^Z?9*‚³µ,«ÞŒöž:ˆáò0ÚÒ6wòÇ‘Ò±lkµäѦ˜Ñ5²‘Æ;'ç<2:Ñ-këºr Rœ¬¥|ÉM-ÍÊ©Úš·ÞçŸVÞ7£r/Cª£7Qˆš@¸±…;å6ªb|S™;f¼ê#y)˜'€y©(±Ý˜’L+£¨XïZ ©Bls¶F–’å#ï0eáb$_w)q3%×`K—íNtÀ=,üNèd´;%SËýFÕÂÕ ç5$Ùsï¸wwEÏcÜò7quj +DÒ[ÈT¦¥b$¦Ò,*|`Q ¨ÝoÖ, ¿Ï'*¡µö+´€ÒÔ +·¥º¸vns&¶ ñz¬pÄJi‡Ä®›‡–*Wm¸›,WºªŸÌ aX˜:è"ú±È¥¼­Ñ¸ÌIv^KÇ$¿QP¸Ó­±X-ù»õèT‘-êNƒúyœG¸÷¿[ߎÉÕ^>½c/?÷÷Ž½ÜæŽ÷Ž-!¡äxïÜXŒ÷έ:SÚz3+Þ;ŸPÌs´¯~Ä{ÇÖ½\<Ø/á”+Þ;¶*ˎ✣Ïb¶ ÷‚âq¸wÌ÷d,6ý%%Cî­|Ær‡Á…+ãƒàš+­8DV+Ü[^ÙŒ÷ŽÞ㸤俶}>ŽèøCK0ðçx ZmžáÞ‡–ùŠGû÷N-1R‹x+:Ü[vs†{w—ÌoNÞ#Ü;´Do›oìGøÎZo¡¾oìf +fLñÞáz}Ç{ÇW¦Ã̧.XæxïNÇŒ÷ŽžOWxvÏ.•µy#wÆ{çù7ã½uBÎxïUóû,㽃äŠÙÒõ>â¿7ïjIkMxƒŽxoðcIî!3~íÑuD|g7"¾¡Šçù)3ÇùN7Y†|Ë“–!ß–5{?Û—AßP“ýXÔ]ü}Ùf…#ê{ûœ½}å.Ïõ„Œúî]WKù£)ŠþxR~ýÐ!–2õÉN}l¹ƒÝÇ–òl0¯6 ¤P)Ó"Ÿzh7E»6ÙDŒ^réöâ7Ó_};,[n½ucäEÄŸ†öhtòëÏ1¤tlœá‰a=]-Ã!Ÿx»-Á3<Þæ¾CöBê+îtéÈ'Oˆãþò Sø†#<ñøŠb ³¾Œt7÷å¤öT=ï06éWº0?RœF‘ý_"ûY”‚“C)6ªs°ÒöŽOÌWx¾öG ˜ÝØK0Ýy.É[€¢.…Že²$«©L\«ÖWdk¼­’¥¥;ïSÛCSûX¥|‡ɥ¬q1Vöúv£’Ñ£aÆŒ±£Gém:¢G·»ÉÑ£ò69xÔ6Ë1{#ã:<šÔÔd°<6ÌrØ%}6‹Ùv +å}ê=z0¦<ŠP…«rlB@—üÆã£üŽ¨ý—¡£Á‰Í? RTƒmeÁ£Ç~aðèØ‘¹SaiÏf«ö> + >> +>> +endobj +5 0 obj +<< /Type /Page + /Parent 1 0 R + /MediaBox [ 0 0 368.503937 283.864563 ] + /Contents 3 0 R + /Group << + /Type /Group + /S /Transparency + /I true + /CS /DeviceRGB + >> + /Resources 2 0 R +>> +endobj +1 0 obj +<< /Type /Pages + /Kids [ 5 0 R ] + /Count 1 +>> +endobj +6 0 obj +<< /Creator (cairo 1.14.1 (http://cairographics.org)) + /Producer (cairo 1.14.1 (http://cairographics.org)) +>> +endobj +7 0 obj +<< /Type /Catalog + /Pages 1 0 R +>> +endobj +xref +0 8 +0000000000 65535 f +0000102423 00000 n +0000102123 00000 n +0000000015 00000 n +0000102098 00000 n +0000102195 00000 n +0000102488 00000 n +0000102615 00000 n +trailer +<< /Size 8 + /Root 7 0 R + /Info 6 0 R +>> +startxref +102667 +%%EOF Index: tags/1.2/doc/src/trm/images/instructionformat.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2/doc/src/trm/images/instructionformat.pdf =================================================================== --- tags/1.2/doc/src/trm/images/instructionformat.pdf (nonexistent) +++ tags/1.2/doc/src/trm/images/instructionformat.pdf (revision 10)
tags/1.2/doc/src/trm/images/instructionformat.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2/doc/src/trm/images/dbustiming.pdf =================================================================== --- tags/1.2/doc/src/trm/images/dbustiming.pdf (nonexistent) +++ tags/1.2/doc/src/trm/images/dbustiming.pdf (revision 10) @@ -0,0 +1,1192 @@ +%PDF-1.5 +%µí®û +3 0 obj +<< /Length 4 0 R + /Filter /FlateDecode +>> +stream +xœ¬½Ý®æ¸’x¯§Ø/ÐÙ¥'0`ÀÀؾ4|alÏé‚‘eŒ» +øõGë'‚Ü™û´kF¡;(}EƒÁX‹Áÿqœøï?ü›ü/çÇ?ýËqþ¸?þ×[úoßÿÿÛñŸþóÇùãüø¯GûøwÿããâÍÿ€ÊS\÷¼jûøüó˜íG¿ÆG¿~Ü­}üùqåÇ=jüÌ‚:Œq£ ^?ÊuýVpl¿éÏÞûïë7÷üñœå÷ýäxKÊ5~”íÿñãßÿû¹Ï·ìæ‡Ü?z½¢à}ÃÕ~”³~Œñã|o| FÿQÊÜ +æÛ†O?Öo\‡”ÿZôê¾U"JV-žö£¾­ºj± +¢ëG®Æ*ø‹õð£·z¸dÕãzÛ÷ì}«È*9\•ígQ“,ø‹5ñ3·š¬÷FMVÝ¢&Y²j’?‹šdÁ_¬É[Ø'5½´žà’÷½åù1Ÿ·&óùÑ^]Üj’%«&ù³¨Iüµš”rýxJÙÚ$JV›”sþ˜mWÖU’5Y?sMVÁ_¬‰Ÿ¹Õd½7j²ê5É’U“üYÔ$ þbMúù£Œ/5qÉV“úŽ×§í5É’U“üYÔ$ þbMüÌ­&ë½Q“U·¨I–¬šäÏ¢&Yð5ö½ÿ¾ë>v\²R~ÌóËØÉ’¥±ù³ÐØ,@M4Ÿüó?½¦XßÒƪ¸œçÍ‚Rïw0°O!^ÆÆÖ:Åó5NŸ(¸Úõq”Ö<ûÇ]ðóW„ úÑÏ”>!Ÿs]í?æõHº!µŠáM7÷WUÕÞÿ?Þ¯¿U¬½o|ÅùNL‡žý¶`©,xP£W®7äùþ¼àr¹Šý™ºŸýú<íxöŠ÷Úæ.ÎûµÏŸ«äá‹ñø!%h×ÍêLi‰jÓ9‹”×b5}é}Qã`³ônQÍòœ#ä·I¥p¯TK6ù+ö»¨ÉÇã‚2ÈÏåWáCnöD|ï¿]S<à§ð°`Ü°€¯ê•·å_yŽ r=5ˆîkèÐaŒÉ.ž¾þ¿âhwŠŸoË÷ãÜnè?Î[ÃýR¯ST˪©¢ Ÿ¼ý:Š¯”Ùîïg¾-ÊûËÕY0+õ†ÕEÇ^—ÕRUåû>Tð6 7k“š ÞþX¡oµÖ«~½°`RÛ¥»ÇÄTøcz´¼âá®»·Þ¾£J)ÉTeF|êÛòVi¶äÛ3çuQO6}ÊIÅøãøm|þí(¯Æ•¡OdÑVp½ +qt˜åWÙ4Pî +ýy Æ[Α6ñ»·Ûó› =e¤øÞþιe]¾ÞyÔÃn>ÙIk¾%5ÚãóUJ?väÕéK-rëfØ-š“wPþ›ÅU»Š +*&P~¡¬ËÁïœcŸWfÇS|½øÊéòÒîðƒß‚á/€“v\O6 >9Å·µË£ûYÐ+õñgöGüñ{Ÿ½ÝØèË„Ú¿ÝXe\ðsÈؾåµí·‚c·ó[Ák¶Î.ùy +åÂ)£tuÌIítÆ­å*Ñ-g}ø›Jçù­{÷}ºrÁ î¯þóÏœÇ^×Îùgüñ{¼­òªþê½oèíG{×?À.þ¿ßëµØ¶\öºkýÑî­®–ó-ñƒíµoQ£Á¬l‚??¶‚:/Š´å•å¡’¯4Øß“­.Ïþ6þ+ßM¿†½|+p²õªÍg­¶çy½Fõ–õçÓÝ®/ôÛ+MY·%¢îŸ{úÈ¿~yát/¶@ùöBeκ~\Ö½¬o}¿íX7Ä·ûçnš|z´œ_¾Ú•u£xl•ÿ¦/þ“'ËñŽ«yË%‰ú?!Þ¸›ØçÇ›nÅ’òj'äþ¾ÖÿýY¡4¦o§…u§GŽ÷B{=šŸ²ËãZ%4Ü0c˜kšùqê™Ïä^%Ý—'l܆ƼÂ4NÖøk)rÊ¢Äõwôuý|ÞtT8ýóëì˜À®á3Ï帼ÕÊrkh€ÊæÆÐNóz½áßL9½,Tæ•»æÃw¶…ëR*ÇÏ+ÞDcòçÓ$j>|ksä +S†âèé[@„ãËr<*Є9šZ¢ Ë¡—?Õ¾ÌÛ´¯-© jÉßùrh¾y¯ÔBåygš^² ꃮ,t®èŽâ8½–ÊsŸ¬Ý…·9¯óŠ÷C5·Ú~ÌÏôÌÞô(žÕêA¹]ù.HÝsÁCÁC=x¦®÷‹¾F< "üªw†ÚJàÉ<ºŸk—¯ž¼ìWÅÒó–Ý,ÌàM~•äÔŒU@W~Xç·B#.[xJy¸‡™f¼Ž-ÿ°¯à–Ý"ðmy{†ô´ðvö4†íM‘=~¹›— +§:ª¢öãÔÝøµ›?¿ëyzJRnªÇŸt æ\ê’òkͺ֯z>_ Þê¨ é%\²PÈBñRç •†&].ÂóÄ +?¥ÀÝ;RþääÌè€oxçÃ6õtN‚ŒC°6…®XãDˆ‚ îç+céRèd%ž\9~fúlðyó’åÐë*7Ø¡êÌ)SH#P¹£z*?n”é~!Z—×/åƒvŽMë7 ¡ë–vŸWÆpLa5Oº¡ì¬KÝÉ.(iˆþäëïžhú[êÞ¨GoÓ¬±ÈÊ¡Ž‡JÇó'ÚJn¬z¥ör‹µߢž·z^ôs_­·~½Î·kð :³¦º²‡Ü¶¢¿âçA]ØJl-ù:TVÑ%öÔ£Žá’ 3`“ž +µwF8RÞ;> +¨GüPŒJxÖ˜ÚªŸì°ÒûÝåK ŠTóÛúŠ• >=_iÉJtMÍáTëÓu.÷þóœ«Kéáo;!•°0Z=ˆ‚“ƒåg 50å—Sé/‰C-÷LVjrΦB,bæ(ÀbõkÕt!½˜Zb‚ÀK¦‚ è§î-BÚRƒ:uû|¬ƒ·§V`ÄÝ~uX­· õCð•;§zk…¦ôMËn[!YÉòx]×g@Ô—ßðdø­ìÐ¥µö+ÒùƒM¾ iätìëWúã§Lâ;‡Îª›&qøõÏÝÒÝß^ï­7ÿø}0¾ ²¦õ”†E[A{Íú+ögù +¯¨x8‘~¢ÀþÕðŠ—•ìÑ‚?ÆX¿¼|a +¯ïóŠT|¸,ïpÅâF¾®<ãöçä Æb†¶î¤kŒ•áãé’úÕ §é“ÝQ Ûïåj†q'F¼Ú¡)ÆÈŠ¢œË.N,)t˜^ñÒd? ¡¡éí©®&{µ5¾å¾ÃU8Øus%ªŽ(@;w{"ï}ÕSÑz·3nEÏå}ZWÜ +žÇ«§¯HMBehø«cnéêÖ.Šoil¢C¶_¾yºèdÀt ®žÐòï§Üm›*½¢c¿óJ»¹¤e +¯šîZY:(ìטfàEI<4¥©©â†‹~ÄÑW¿a­‘ë#-ß‹fDØÒJvËuÐjž35”‚n1úE3/‘Ô_©äkQßïV+žRöÏÕM§‚; Ñq°Ü]÷Ëâ¢Õ»Ô^†{…J +ì¡ÿgÜÎå8êÚ±ÑPì»$ŸK6ÎS·{vaÝXõd£nêêÔKsT¦ÊÜp,¾UíجTî’µ»ï"•ô²vPeÚ½Ûò¶l#hɾ,)âu‰ê&?Ž× ­XüC;Ä›nF³çŠù>c3MíG}U¥È³µþ*×ØUQ%üúˆ…c•j†»È±[6¿JU¯ô  Cçr¤DÇæT»eqÃ;`ºÝÉG£©ûe]mÕíŒP"=`þW ͨ˯Fûµãq´¿GÞZ—AÒ7kM~;§cHˆ*Gw6˜õ¶õç[AóµÎ­~™_±{¤­†ãúk%/Gi*E:T|m} 72ôÔduYÛ×!{Åq†®Â"½p1ÂßEøßG¸¯Lk+Ç…·_§þ˜¸_ñ¶ÛŸîjÈÞ ¯ñh/ÚÞ9™öpã;µê–åÅw¦•g«ôº¯ß’û\f¾5Ջ뇞­žá„Q›ùùº7¯|{Á‰pÆÛ§§DÝ«KÙøæ©ÛáŒWl2» +SF ¬×­ª1nF#ÿ°ƒm•a/^QNXù¦Åñ‘7\6•]­·vŒ´Ûiwå¡ÄFG5==•—YWèû{9µçöðnÅ«º[Ê[àhéõ·â…îÍ°Ïû)´ÂP¦›T¯åä·ÊYeetÙ]×èFŸ]3múÌ•ñ‡6»á²%è/X—&ÎŒ|f­•šïhõíQ'o¯Y®uó|Q`“ž{ÿA<éØü¿þÎ:ÏîÂóò†î}»ÚÂ#¬_?À‚Ðê£ËrBñMÙœû]›³Š“"æÔqغ?Ù +J`«ÚäXaèè†ÄE&KÓ·«_:Í$ðƳ:ÛYÜ‘ò'J8VÖ +uúþw6 +Í mý­,¢DZ4ëlFy…¿7ä’øsé”®Fˆx`N= +Ü5mÃ×5‚ÀMaJ4%Ã̈²­mgc[_Šß¼ùßtäoGoò…R“Þáv4ò]ÓBùW¼îÝÈ☛‘ïöÏmÄäo»‘Npm×á/.#ßá 1òà‡Íeä‰/#o|ù~9b%#ß…]¦‘›Èav °{/ˆaä!Ò¶žÛŸÖ,#GŸ=Œ<À¨k7òý¨j#ÿ~X/iÃÑ*Ï#0¨õý†§]iä£ÕÓÈ£Wêfä_™kSù^dÕ½ãÜyþxùW,}ùÞ䤑G×eäQÓkù^MÐ é…RùnÇÊF>Ål×U½&0»‘ d]dä_QAM×¥¡._üoCó­ÝÈÑßóÙÆ)OÑíûçGHm_‘Ž£Ôö•<ÝKkÇ¥Xˆ´ö€ü<+Z=Šb ©¶£¦bòzÕ<=mcÁy2:8šš‹Ì×`&\¦×KQÓ| ºa°‘×É<œ|íóèÖÔËÁòaúÖmowC´û²‰ê#J°:Bc´ ÝÁ‘-#U…«yÔ¾9˜ýº1ÃîM„~¢qÒÔ½µ¯õ‰é0so³2!3·µ»¬Ûýj=ͺ鋙çP%]VÀEFî»<Š `se—Š|ü¢-PºqòT U€Šªž2™˜ñ!öž3 +?*Í~yôM§ŸH2PðD£ÞArŒŠQÖ’²«Iº©Ž±\Å̈úöÐt¬‹·ÿÊ°19ß(yûø­C¢׈\Ž0—æŽEq«O¨#‚oï˹ö5’µ mF(ä#ð]úëLŒšÑ Å8Æ×È+ž›7C1ìî>!»û.ÞÇÂ;°¾ý¥[¿íéâ¯çâ§'='×›¶‰ +(\â¯ûy¿¾k9ÂP”ÔA—€ø(H D- >KˆÇo@ß2Ï7ˆ:W%iò2Ï7œ-xȨ±øˆÏëâù¼w<ˆç×c!ñ¨Œ«‘v4Vx)GŠ² 2\c$â,%‘øëiö–Ä£`ˆG‡ +"†FâC\H|Þ ä›¢‘o|ÛÓ1ˆ§,jàYŠ%pxHsß×3 +Ád×GA±l»- > +²:'›Ãà8•gøâQÒÄJœn\Äk¢ÍЪâ& ‰‡L28E±ÔÛˆL(ží(žâ,ŇøI͹¶Cñ|¼(ŒðµñvsLÌÓ} ª°tjÄ@¸»|¶®‚‹ ,CñIènº+H†âÑ8ªSæt[ÏaüL ÔÓ»Ϧo%xŽ± +ˆgGÕ@|vã×nþü®çˆýH$~)L4ú Å) C²ˆÅq8ˆ‰÷ˆ*Ê ÚX<õ†VäRH °Š9¡ø¼AP<Wï€â9o#¬˜M¨pµ$™Ì‹cnYpÑ”Š§r“>*Š³šlƒâik°ªOKÔ?ŒÄ[J >® +‡§Äu…pxZ=ašÂáÃ.‡‡HŒÊ}ÚEB5,¦(±ø(0OõgÐÑOÆ„â9HÌY1?w} +XëJõ-=¡x*¤ {,‰)^\À«¥lHŠ…5O‘Áw«bÉÄyƒ‰Kèʆâ9z„’ +‹ç$øܵsl’» ñøÚ󺡘¤Á?g,þz6ÀmšÖÐBp ijÕãâÙÄÃÓص+`xöFÔø:Ó¸‘{ðœ«;éÝo;È2¯ùá žD,qxv¡šS8¼úô >L’qøe´ŒÃçø3Ÿ*ajÝR1Se# +ónøðÇ~&¯F0<¿¦]ÃË ÀáÙlãðÔ08yÂá:g Ø=ös¨kvÿ¦à”«ò¥d´@¼\—@üú`ñh XW#ñôì%‰iM Éø(H >|Ãâ]p,$ž}Pzñ4C÷ ž/üHž/¸JÀðvÔãðË‘3 †áe/gÀðË Où9†ç«…²ÇÇ*èež>(ÓB᥋3Px¶¬H1BáÙòOÂîì\(ÃM²ˆ‚èË?~Š‰ÂKeêBáõØ(|¸ Fá!ä´çê9Ö(̼pø5Ôå½GàðšGZàð|™Þ≷rטf´aÛ¸ +ÁF f\ãðÙqÄácu”8<ºù!^Ó8#ÈGàðœZé ‡§–´;pxˆPUñ¡RŸ«Ÿ÷<ÖèAÈ°Ï9]*'ž*\ûê•KØc˜†ežÃk–@Þ9ϹDE¦>÷¬bÃk%tOË©nêîÔ“Óƒqxš#ýúœm3W‚áÙ³úOo°tãð›)où¸2ØîO_–T0ü±™ZãðyCq¨À?¿=^@:ß~i3Źl­qxV¾åÆÓTËFÃðvÀá—_`>üãðá„¥_`þÈ„Ãóç <´œÈ­âYg~lV™¬óa¥7$~îDâ±IM÷ +_½ÚŒßdŒ½¡õ0ö-|Å0ö@•Ç#‡Ï€éå%¬}[æÚ@G\XûV¼–µ'tÊ•Ôe¢7ÀVOa0÷€f=naîÛeæˆx»ÂÜDæ=rY¹‹Â2÷M£&Ì=ùv¥ÕØÄ&?s+‰$Òÿ¤½o—'ì=êç•=ahñ›Ž0èÍúœ¿Uûv¾^í9Éàûmm3øÑß_ˆý¿ X߈~ü¶‚FŒKóx´³®¿v‹¾ö|EmíM1€ÉÍ À4 +@OÛ +ð¿Ãä£kûfñ²Û‚ÃⓃq…Å?v¹Î°ø½ŠaßO~aòÑøï2ä°Ícàaó!*&¿i×QØüæ5³m>´¼µc3úÙWÜž‘ƒH6¿­Cc-§ÉW¿ióAŽ_M“Çl›q–´ù)Úæ{ .¶m~ÛìÊi®F:Øü¦ÍȶùÉÍXF¿9œa›Oµ¼Ó惲pîVm5¦ìÌ6÷ŠŒ6ûDiô›|´¼îx@üúm“Û3N²o¹ǪŽCôN«ßNm%O«1{¥Ù'ÔîØîã +× »¯1|mf¿•X|ÂêC©s1x¤¥ÕoÚÜ­:ØqÆkwÛŒ~cXCó3¬þfžƒ³Ykò5~5àdWGmÓ‡§šðû³ 3œûSœ|刟Çþçø®>óöß +.=l+ÑR¢ã/'Va½µ.Ìœ’9Mî|Í)´‰8½µöÌà¯ß¹˜¦f߶ާƒ‡I#,Á|â\ZŠãû\¹¤˜p©Bſ܆<—&€–º 6Î-ÿÝ KU"kß"ŠÉÜÖ¤uéÏÆ—‘†H±{#ÅŠ¹¿¨ÑÇGêõHCÓǦ7*øãwUzµëáÔ½â¯ý´™økD¸µŸTÈ‚»—{Â3Õ¤¤€M„_ûKwl·qå$Ù’Û£¯@Û﵎¼~yYT)zÝ¡à+Ðôª…\@ãÕé^|M1BpY à+H +Žn`$›Ã°_ö»—|Sà +ç¤<+öÚEþŽ«§@›ˆ½"çÂÙ¶Ø+’ Œ;c¯í!.±×è§-öÚåg$ïßBsý² ªÐ+).O¸ |¦D‡^‘â¡JƼž½¡×,pè÷ÏeXɱËØk2½âDL:ñ¡Wè@‹(Åé0˜æ÷^2.ö¤`8V‚øÜ+>ûf“ˆI¡W°Mì‰"ôš"»Ýý%½öjÔ‡áWHR?Ù!ëÂK— ÑWl_v¬_ó*6äÆP™<¡²}ùOg0`Z.šo~c™«û¾ôîwýMN替»胑…³Ý«"QP…lŸ¨•û.ÿÛ!”½gFƒç%¶ÁŽ”Œê×PEðc\¯Z­ÂõtÀÌcyêoAõ²ÿÑõÖUùdž4Œå@ò~µw¡:Œ>bl¢pé?zhµ Kðz£eØÒt„*…äh½ø­}Y5;øró†K8 Äw8¯\èu•­éE}-Ï+C¤àJœþöS·–~ÇÀ§AËÇ™S&W`4À+6Ä7S.Z•_ô…àÿÉýaK…²@{&ÆÉD%\!VjT<нp²W{ +”0’s¹—Oï²——!Ú{¢y ¯Ló¹l±<$/’ºx\.`2œ½„hžŸº)CÔÎEñÀãû4Ãã LÄ‹‹â×Mñ§Ó xàÍï'}Añ%8\£Ûê½D…Ãc8Èc†ÇèдÅðxe„Ãc z‹ÁðxÅ~?Éð°¸1<âS*†øÓÁð€Øœo€kT\OR<Æà +58O§­`ÇÝŒÏ/’G,¨<®:6’‡ ²F¤uë<ÂË|îý$ëÉñ‘/ïToõQttq£€vÐÛü=÷%7Ïc(¹ìây¸©ƒçaW¡Êq[®Dð<âºùôÄKò<èiÇÞ÷[®É;¬Ï®Ç¼’çÚLï­×LJ³Døç[³o¢GúºAô°?DÛx=rˆ„ Ûõ˜S¦²lèwÝíea»rz¬9¦Fú=Lk²¼ÞèYÏ#:N<¯‘ÏÝüú‘oÓ鸣‡ZÜN¯h·¢&Íc(¸4P©Åó`¤§¬±#5xÐP©œyÐç{f¾jüõÑcó<0¸JfXàPìÏ.öâN+Ýëz=hAœ„£z¦éæ…Ô˜¨úH¢ÇŠ –¹rÂZ3eŸ 6<”ªÂDeÉÛ2WË„ aGpaÙÙ zÄuãþy=ôø-á_?F=diƒçáM(Éóà$um<-$zØW žGºÁó°K<Ïø©Cé‹×ðÉ|ƒyÞšÐê½€$ a½…¼ƒcMqE²àÔRwÕ,Öc=„ˆùðþÙŸIÎȨ6Ò ¬¡±mŠý­‘ÿvtOkH>ÌxzØ?e€éÅ 1E5{Ìb—gØ+‘SºÚC¹õi‘¦;R¿¬«¾~ZS´¹Ÿ©{ÞÄhÎXÉ-_þZ»=h]^n4åaŠeV“z„óýÊW—óÍ׫Á¹x<­J…6QMÇG,ëðøëñ\ÐX›ê0 ­5*?¼¤ 4Ö‚MSÛ>ÍíºÛ~ÃS{Øô—¯j +°Å×Û-°…Ѽí}=z®{Ò7êsÚ{Æ* е–»¡]ÉY>cÓ/Wfx{µ7¨ +U›Ø´;y_'“M]O««£O'(ø¹0oÄãySˆË¦äó‹ã8(°ë×Ù´2ò>ûKy›È[ïUÒæ2öàÙ¦G¼ô²G-}n[TbyD¾m0ûeß.-j¿¼ìõ +Å,ÿ¼xäãK>€¯M¨^çÆré·€ +(‹qëVnç_½+•.ÙiúÑ›—‘N™øH­zò*hh¯ØµHCåÆ?÷ü ÇdÏ*©9iʳêryAãš~ýo¿( Zw¶èÏ»Þ:Þ#dñŠúcË×™9ª?vP»¥’)¡¨YsÜË6.Æ¥C¸y] &Æa'h1=EŠ{Úº]ÅéÀ°»A†ª +Ýïgóéò°·J´mDج9NoªÚ8Ax«-¾× ¥Ë4€ˆ&à©a„…ƒf)êé]Æ·5ýºŒÁ,k­–Ùן„–¹§cÚ2çõ<¹H‘³áiÍ ÝÝóIsÞ}˜ó· ¹àÑõˆO~~”ú‘«Þ®° ­ùÒó¯cth7ïÄ£FmÄÀJ¢gŠêè—£oZº:ˆ‚4AeXçd5¨~zš…= +Ìá”]z& ¢-LêhÄyR¡X¨”#âd™¦œj +ä +3#‡<6Ÿ×žÝ(øÍÆ2*yöå4cÕ8Ó .Öé&ä8 ¬§tÔ’I+¬±V³Ì>py.{Ÿ{þ£`¨ás1<>~éÕo;zÁ€ðm™-y+ Šb5';ÅÎOL ƒ;a@,÷Èy"è€ @ÝÒ®GÁ«¸?Ûnï(I °*G@µÄç*iκA<àY»½±4¡V + +´¸ À¸n(°’-H ?îÚ6{;ÿ~@}X*- BþUsß ¾âÙÛÞÚIÆô³`BhžûÙ€@dª¶›ãBìcµŠ5@`Õ2Ý`,ëZª“ß³À·€“œ‘À:5—åÛV^H +tf±@ˆtòi <òcxþy'X‘,,°"åSB}¯Ä Åc׸¡+¾e,°ŠIX ‡å±^Ÿ:ІÁ´Uo‰b˜ë±ÀªF`U KŒbˆµ8І۽ÑS5ó®g?~íçÏïº~aV…¦ÆDŽ¼æ†îÂët.FaLÓ"g:{^ „Î_™z"³Ð ´¼°À¸ÁX ”žGÎ ¬RÌBçààØ÷öjã‰>•wk5N¥’¿Åxê“` Úlam0 ¬Jß` ÅÆõy ÇL0°ê˜ŽÚ8Xµ‡"ú«Š×ö ´MZ`   ĘÉŒÇäÊ¿ÎaÁ4Bkž $^h ô²lã`à!±”mOhµ +4bI0PR`G^6ˆg?#¡@Œ nؘ`ôîªL†‘¾÷®×uú%³±P >úl +¬CÝH(ðP#+¡@4a1¶ÇPKu.;CÕ9Ìk*Œ²Ï#w~ÛÐ]øµ‹w00{}iíÞÀ@Ø«sKÀÎ)#Á@˜ë9 Dãõ=; +V} ¬‚ ÄH¹® + ŒL»Vm*1ˆž D‡``UÌ'À@[§Ó~%¸nàRΚa,p©™Á@ÙË«–ú 2XZ64°ÊÏ +4°jÉh ZâÜ2°Óå×Ú[¿éUœwÂnÙ…ºoØ÷KÁ¡öW(5n‘2X•«$ðÀüâ í\G"‚U±”«¨» tÁí( x|-¡ç>¨‰Â=%ñÀÊd)X•ö@Ð~›÷~§[x`\žënedç"Bnè± Áªmn±ùoÇFó‘Ÿûh°¬Bñ„~0UAA´îÛ¹­´ŠÆüÐÁóÚÅ»l ºóø‚ æx\˜`m.Ú +¸ß˜ }ˆÀyW[˜ Æ/f£À+S˜0o¡µ­# ÁÚIs1$H¤äÚ!Áª Y`‚5°"¸n à[0j¦`—)}&X{TƘ`a(@@ÎÊugX˜ ,æœ VíI L°*»äÂÝÔ ÚeL0]ŠÀ㺱&ˆÚs/àæR`a‚ra&äUÔÀáðè,.c‚éö&˜ í¿1Áôz´˜ M½1Áœ \×cr!1À1q¼«Ž +DejB~Xá´º0AôÄ ñT×t%;çŽ&¨ÕÒ‚ë o'DPO»ÎjÂœP¬:’4@ÁªXW€‚Ò)8;ÙQ=t +ž®ÔÞk·Ñ +P*\ŸÕ-*x(¸Æ‹AAôÿ\»½«à“M¼æ“   DUF€î)†•3(Xkô“AÁª˜N€‚µj8z÷·ìÕ±‚ˆ­&(U¯ .cÞÒ:rÛ¼!A™Ò#1Á´µ º 0Áø¹Ã¤ëñ΢ηk³ø¹lm€‚ < 䊻m  V‘‚í".H0ƒ€í$èy¿.§¯X+Â7ó +†ñ; +®˜É­½P»óZJTÅýÅDï`Zí VíNøû[¿ó7[,}lý¶¥­ßiésë·l}ný–©ß©»ÞùmS;¿mêsç·ŒýÇÚùm[;¿eëcãwÚúØøm[ÄÆoÌØø¶>6~ÛÖǾn›ŒMœò3³Dæ16~ÛØÇÆï4ö±ñÛÆ>7~Ûš¶˜Ö>6~Çuo&¶µßiísã·W¬±ñÛÖ>6~§µÌ4­}ìüÖç¬ß¶ö±ó;Í}ìü¶¹ß6ç±ó[â¾ó{Ý@ØÐöÞ;¿ÓÜÇÎo™ûØ×-s¿6~§¹ß +˜bÀ¿£ï¼ñ;ì½÷}ÛÞ¹ñÛö>6즽ß6ø±ñÛ_¿—±6~Ûàç’Áok¾ÐÐöÎoÛûìÛûØù½w~ÛàÇÆnüM”ÁwÁa‹Ÿ;¿mðÛ²+6Þúmƒ[¿mð›wò/5¶~ÛàÇÖoüØù&Ù;¿Ãd±óÛ=v~§Åßq=¢Þs‰M Ç{P†s?µSüòÏaòcçwšüØù6_¿?ÂèÇÆoÙüØ÷6ßû¾mò½ïÛ]Z´V~kßwÜà}߶ø±ï;-¾÷}ÛâK ÿÅTïû¾7‹ÌÖ³ÒÉÍ7€ó½Ü1©aáþ¡æ#Pk ƒ~3‚£ÈÏ$Ÿãں˻§Wwa1T×õiç¡èŒ©´A|[á7í†òL¾‰côˆg´¡x+U±év‚Ä +âØÌý¢^Û¿¢Œb‹ ƒLr +ì~í×a¨1}Hyz|H¡Sä«ö0#±«Þ+=m á·–°×Gîô^ý¤ý…1uî3¿çDq¢tM™iÏa%ž´ç÷mt_-9Ù´IcÓÚJ +äm—b¢„ü +â +4ß&~Ê&â,‰ÏU›× ç_ž«jäÓúê)} +~®¬J(u-†›©DŒ<4_ÀÃhÃiv–°¬” +R;Í]à…òt™PÙ4fA•Ë)ôpn‡<.qŒDzn‡z.bÚ¾!Í€xWDõø'ÐE n|h ³ë¤eÕƒà#ÇQ„Å|àBN– a¨NšÐܪ¹Ÿg=ÜÑ—lMYŽA4‘GCHTìOüÜ øƒG“q<îÉÙ÷J£P²6:…#«úõS¾ýº¿a²E¦þüȲº7"q st€Rð7ή6­ÊÍÿ,ËÚcR Ëë +×ërÄcͳáø_f†Gc—´ë=–!•­ÔuðÌêï.(Ds9l<{[V´s_x,K.Ÿa`)ÊRJV}„A1NéE>õ ŽØ‰;[줢éÙÞî-QkOPAÂÚ##¶È_Û§/q6$ñz‹~Ù°¸ßúŽŒ6šå¿·¬èǤ©5yä ¼²‘V`u‡¦”Pì<ÿ¤$…7;œFÀ¦\†²°í“®e]7 ¢¶¹z%wÿ Šr  áÐZs6L©#>€Y¡©z@CJ?ì)¯kôÝf„pOl%-lT×­³_7ѳP–ˆŒÇ9x‰ Ó¨^¥Tî½ö–Þ'gpbýÝvÙÚ&Ô‡,‡åQ +S49÷6Cnû˜¢ÁìñPà +ºÐÞ"ÃÃ.œ=»¢ï¤Ÿ0£CNÑЄ~务9úÅ!wéQ”]—¢sUƒ?›×ñ|õÆÉÞ峋FrâœÅ"9™³HÎG»€Í"±˜,ÉÙ8ÍH3‹äÔQ ‹E‚‚Ò’EòŠTjq4 )¾à‚«p¼/I,*ÁÙÈ•[,dø¶×uvl·3NÇÎM#9µÎ* +”¬ÑÛ|·N10ä- …ŠCÞoଯ{¨I‹F‚ö&åZ4’ÓùŸM#±¸7˜F‚×+i$èÍb¢‡”û#Ñ4‘ÇÄ\Ç.[;¢`üØÎ 8µY:h$˜‹Fò¶ÍCÌÒ4´Õ9“FrvîtY4’SQ ‘œ~Œh$è²4ôÓ;ä@eG~íèÏïú~ÑH¬!‹F’*çÃT‹F²ˆFò–6cBgÔw8•xiÑH Ôc&ätRê ‘X^4’¸ÁÁ<þéI#Au*ÑiÓHÎ;On§ª½ò)^ˆÄÉ-á‹F‚nÙ€ô»]I#Q›í4Ø›ö$ÖK€?i$$®äl>H€3ïÙÉ/‰­c°HNÈàîzÅq}Í#/‹´8$’ƒB‚% #ökCùy+z’Ó‡«GçO>fQH`ι($ÐQ¥à’3O¦u[u àXgƒCq.‰Åíà€¸ÁË–SC-h$§œE#9½Û4‘Sù6’G²÷½n˜ ’~žYSMžgØr]ä•yz½y$§rß- Ô°Ïä‘ åŸ;y$§œ»GbK<wã—Nþ®Û‰Ãj£œ˜ƒ6É9è˃Z_ž`ÀR];äìÊ nÉ)`!$0TÃzpœ&Æ"œÚŸh ´ ,þÈ©pnðGl–‚?’†+ù#ë†î Ÿ:aÉÒ1Hd)“@BèY’³Ûà É)+$øVQ%š5|˜Bç*ƳUÍAÓ+é"n×Åa·,jȯ¢YÅ_Jr™;r* JpGòcƒ;r6å‰S`0ΙÜØ—Å¡¸x#ö +×Fò,8‚7wê.Ij-‰#§r°,â}¹'7’ËUËCÒ• ∠‚8‚__-‰#é‹š7‚Ú#†Ä‘SÛ‚8âº-âÈIªGðF¨…-i#hØ6÷SÐòmm‡§Xê.¶¹GÜ“ü:g»1FðÀëIƈ݅`Œ`|^F;«Õæ|é—«·”Œîxü­U\¾ ŒœŠ!š2rŽð‰ƒ2r*ô”‘3¹2fSæ&(#¯ÌM´$`5Y5SF^y$ŠBÛÍ9y Æ"Œ°•ƒ.b× ê¤IF‎ëf!à·Ú¸¯©^g·/ºˆ]³Eº:o]ôØÆ/!ÝÛ ‹èSò¬[ùÃt‘ônƒ.bo5è"²éf‹„É¯Ë r2þ˜@uW/¾û˨Þ: >¦“›NÓ&6·Ô*)>I`ôÕe"‹xQ´Ø"èà1ó¤Ì³®“ 72ÛàIñFÿNMÁ‘:}¬ä'W ؇ú+Ù"ç´‰ +¶”ù)«W†´¯‡îòìG`d•µgãp´%v—Ͻ«×<*€“ßL¶ÈÙÝO&‹œŠÞYä È"i£jpjãnE`ã”å ÝË|·eu2ái[Ϥy +®HÜ`|=~^rÝ 8Å“#QäHãL®áãHÏK×ؘ"^)Vï·cxW$|€ ŠØªˆ§øT ð‚)nxPEð8s¶UÂ.jÓßÈ1‘Ý0;QĦzÑDN'Bÿ&r ˜ƒ™z°rjNÍGC% ôö*è®îò ãéÃw²yzx#TÐÄÁ^‘JŸ×Ûšk6À¯ÂñÍÑÛ•êœÈVhìÛvG«Ž¶ £×Ýn¬ !FÙ¥›A\‚„ZéÞ¢tEï±hø*j삃ö¡óñ—VÕ„Œ» ŒÞ¸û²Óþ”õòAo®9…ÑŒHä +],ŠøyçÛóé¡IñòÆ)Ž™œO{07S={ Èã ÑàÉí³÷ +ã ¹„Wá½ûñ̬&6ÀQ?ibTÒåÏ$BØ —‡j#p·¦5h‘½;<_5ÕDqܦ㪷êWzO­ +‡íI%¿N¨XQ w]w[ž½t®ßv™.Dø÷T¢veåØs½æ·%ÓàÖÓ^i—¥éhƒËÓ<UÁ‘FÒ0Ì\ c>w‘ÉË>W‰6½6mV†C5D^êöŸî²×æ&òD (!'—~Rë>õñšÂ`Þ0œ›<"V­xÝ;½ 2« Sæ×æl©;)d$¨Xd?ͯ׵ŒM‘D"‰Ýç\×Ã54¨y‘ó)tôTÁàௗçnÀ)ß^Rl˜ñ8ÇȦŽU`vS«,©ð9ä%‘à\ߧÖm¹hîÕêøzQ„ÛŽLãÑÔŽÞf*èBUÒû䛽óôñW„'{éÄ'†?Ö´í•uŸÖHÂR(¨âÒ ¯Ù¥@ÝŸÊÑzÈ]s(­?cˆEAÁÎTàú<+4®¬);ÕªC˜[©›3ÕaÞ&Ì0wÆ@'µé¬’u kØÝw¹nï´ûEwÓž(ú“ƒ³ÒÏc©’JBÏ,…Ž˜ÄÂ\ +Ñ°ª‘,:¤õ£Ç"Ä戀ˆ ÐVg]/¶…#Œ£vRZÔÐzuG_‡Î‰‘ñÜ%nd×°D‡2ÄDÒt +ÙÖ¹ÂJu °¶Ë£;‰–ÔCÏWæpõ¨âÛ]Ž(RÞÊš¯÷˜îuÈD9!¿é¹KaRÇС5&ˆ“•+VÄwÉ<%öèÚãxr|–†'áqçd#wç<Ô/×ÃW¥ùŸ+˜eo…+8yñT +ÏS„ˆ5(‚ŠÆÔDÍÉEÝ|DP‰/ +>쟊’QóÒ”;IQ‘=¸“xvÑÈ¥óÁ®'¾ÔÛW½°;£Ê[âDt3 +¶"Ð ƒŒ²®?®ØÃX^¶z 6‘=æ$NL¢PñºjiAÎÇAÜî=ü¹Œì§mŠP’ö˜€öùaGó Þñ|^UúÛW’ Îs[F¶HýìËÓÑ­[3IˆÑ¬!{„ÎŒQ@ûЊEªt“ŠºÜ©Ë^Ð8„úô˜§@âS›t¡m–+ä‚ÕˆD]¦ŽõD;x}ƒ2ššbyy¹bûõ\OL6JÔåtÿ†£ÁÃ-Nc€¬ +û/ê"wùßÆ%ùšçÔT¤óŒ­àç*Pð +<“gþ* y‰û+€—Á5Wwò%Ìô“ˆ4ƒ +Ïneê=ý[—/û¨½H:vs`´xGÎôwûˆÆÕì^§Hüã÷ï~›bxþ÷ÖNÌ„¡³? ÊgàìçõŠ¼9ÞÈLá@5uìÓŸ[³T¾>à÷×奙1Ã-}µÜÌo£ ù¼–È ü¼.·è”ëq]ýéÎSo7¯&ê¶D9ô[A=•®>~ÎÔ÷n‹WŒL)z½2gåN¾=ê~ +]þÌOóe}xþx5Œž½Ú¯^­ªš}möÏïz"Ù sÒ”%9aJC—tÕ% +GZÌL˜ ÛAL˜¤ ‰–0»Ç·Y –“”0…‘áÞò±( sÄI÷ˆšOe¦!a÷¸ùx6󑨒=ò–²ÅgD‡LF°l.Õï "Ìø.#ºsˆ‡f¦ÁœŠµZº1 Ù40ÑîSÝ-Â+ñ\Îd!Üì© !Ü蜠 HH‚¯ ë‡Pá’Š}p_ÓL>¸/† D=¸•°M°>Þ7ÊW!M¡!'ð<å¨%çÀ²«1ÍØ`»è&ÌéÔ‹âÌ)œ’/žÓþ¨ë¡’lpŸÒkÍùÈäÐ{îÓa3 + +ˆ·rñ ù±fHÎÄõxò5ƒdðJ&Јc0ÍɃ`> +%[ºutÐçVŸÒƒy‹g ¨‹‡VÒ ¦{ˆ\0¹=‚\€‘¤ø‚sD¶ô&¹w3 æ0>o^ú£1e½êïÎúÒ•Ÿßtn’ +ÔÿI)uñ¤/•|‚]Æ|q/G° î‹ +“ îKЩPÙRƒIp+ !"AHGòâ²hÐá~‹à>mÅM"¸Ï8q}7Á/_‰)Þn1߀Ҥ0}`ÎHb“­eîÀĤÚàLy¼¦Ìð͈«"À*#x´z0oÀFÌ´iJƒúÖn(¡ˆÑcYE°lÒÔ[i$¹õ¨JÊlÑÙ’1pûxu.ÌVóÍEŒoºÀ*e¶¤š\›¤ +H +ƒ)0…w™(0ý2O`:ÆošÞz¶` LƒYæ`Ø\W0æ­ú)1_ˆ™#ø‹´ˆú ÞÜ€éÓɵ†¿y&”xÍè)â@³DÔÆUr +áš^gš¤â +¾ÑI_ºð»NMJFKŸ‹ërmœ€©È)SŽºh¥16FìK›A˜¢Ã›¥çDg:À«Òl€É Áa2$ñcD@×ÕL,ïc*À>wt{ÊD€Ð ŧ–þhyk³f}a­¡I=âà t3àÏ's:l`\þ +íÀqm†û݈ ÿ» ÞÿU¦6>K>æ$·Ùð?*zøŸ_hì>ÍÈÿ4Š%ÜöAC#ÿ*Xп}¯Dþw¸?šZ ãû¯XôŸÁñ3æGƒ±$Èß‘ÿô–Œ÷‡3e¼öH#!’>žÐþ©Å¤±þ©í‰†úYŒSýhˆ9èŸÎ‚#œ={š€Å8zSå;'ÙÄGˆw7$goýñÛJ”N—,™˜±P~OÚùgâ¨òoQú ñãíO$…x¹ø1v…¸"šôJ˜ŸïÏ[~æè>ÜŠó +pêcû0q;¶?oo‚öañX#!ûó‰J؇÷rn?µëÊÒ}¶r¿G€ú·Î0¦_†Œé»Q +ê{ž¦oáóH?® +*¾u +¢ý;V(Æóå-Í¿uŠæa0ÿ¾l—§óh(_õ$_–Y0¾=Ç#a|»‡Fñm†…⧕6Š¿.ÚÞs?µAüû lX>ªIß9ïök“΀c!O‹ßGß¾÷Z"ÑûW&ü.ð}Zr“>&ºW_€îç:šþæUF÷R–Äí§¸¼1n§j?C4h?I<ŒÖ‡>ßFì—æ ¯Ÿ·²ºŸôõ—Ðn÷¢eLOÆê1öíCë/´ý‘P=ìé5©‡i=€z[gt€õé%0ú©½Ñ‡0z[ÖéiÔz`ô¶€ÎæöÐ}ØCôñSáóëÁBØñÚ2ÈÁöÐèü”¹:çR³,pÞ‹*cóöÂŒÌç„ld^òȼçàP˜‘ËÇU¡òsx”pU$éHL~ç]V‘€¯6täÓª&"?…þ]@þf4#áø[g1¿•·_`<ÌBñèÃ&åœ Åkl„5Öφá}­å\ P`^ñD6‚Îúpäø[[a ÀÃRm¿Ã,”@ßa´—8.EÀnZ_¶Øú­J–fD¢—Ü…¿ãò\s†p)ÁQÓ™„©Ï…×KªBÍ\¥©iñÓÁ—ƃ”!ÞŽq¤ÝÉ@| µú4æ&Éßh{Fu ¶[5lße«õPºš9¢;N-.j(hº0 [Mî +}cSû¡(NR1P)€ÚÂ÷V•ÿaÈ>¯{ÅftýÈÑõuù’Cvc딦Ái´ü”η+kti~“¥2Ê/›ò{ŒªOáÜÕgBv§²Ô`‚é!È= œ$%Œ”§ðÿ“Žxœ~ÌÛógTÂ@‚ðô©FÓaû…LŸ‚a…¥K1G ,³Èe¦ ÖŠðHŸ‰-©wBË䟭Ë\é¥ôrÝLl3.ÚõùÚ¸è‘3›tÌŠW"èó‰l–ä•[¾}v:Ñs_²„žß§C‚Ï1Ö…þýÔpëåex ­'B;qYÀ¹œãæ”;šF'Eà#_ò<šÓ•qR³ØU„ÌÃí1BzkÃ_âå°E"x0¶x*±©ár|é£üñ4¹„o +·CÉh®rGp(窱“s}òL%.6ËOµ“?$§yºŒ‘Ó%8ƒ<+Y%÷(ZÌ]ÑïXŒ‰N`™,I燑ƒ.V‡4HWC½î;¶1·Ò¯§¿~0néH`|]¦•ôƒ‹ÃñÌq˜r‡w1&©( Õˆœ ñ©…´q­7 ˆ¯Åˆ;{/äŠ8 ÑÜkEMÌœ°\4ÜnŸAËðp(.i·Åé¶Ú­}|Õ‘ï´æoÈÕÏÅk€ +K†+°$‚w–TèW8rú‹×½ߗWÉÍô…2üÔYoɚ̌*ø¨y£ +€û T¡=±FM”khà +í‰õ8=¿¦¸:†Íø…ä–ñ戚òœVh#†q!ã†,ª`Q '1¨ÐßÉ•Êø¶ÎšRtØñ‡¿|"½—"[»êcA +Mû)u) )(¦²£ÆêÖcÚÅ™·%ãЮ‡c%|‚2ïça¨ÀS=Sð‹TˆŠÄÂÐè¾Q…&@  +~Q¢ +¤ +ôá5ñ-½PlO<Èì˜[¡!£ + %(œ‡ÕI›4'‰*4A¸FŒÓU)Q…U@¦ŠWFÚŒ5’]Æ)»+TJPUˆ/;›< +9NIòc`&š;"¶žôµ¥,`…vG0‹Ýõ¥3?¿éÞ× +t**„gÉïôÜÙ[̤hùÞAE?tñ%%ÂåC#èˆÔ +ƒ7kõÑkÌ¥N•1ìaOåÁàdÏqˆUC’ŽV~“3~Ô•úi—»ÕåîΚÑv>/ðZWJ[¬(ÞÉ¢söYãE¾°#üÂ;ï^'g ~™y±w ˆ2!õ’®ƒd‡_ž]Áuìß[‹!£‚&¸Éô!‹ì³íix°.ÃCÓçMôŠÓ÷²êÂÃP36¤<wÛ®½è˜átA–æ+ aå4DSÒzq¤ö0Ç@'­ŠQy¥k¹5>xðn;gÑ­ôÅÆh|Ž1ÜH-oéöÊ:ä)f@W’¤)žÔh1ë©PYM¢<¸£æÊ¢f+äl–Vv¾ª¬^Yhi/f§›–1â›é %hOÞR,¤ÆI šeÐWè2…1/QÀ3ȧB2:ŽÅ_ÀËýª A˜÷¦)Ãß! +sÌŸâーÁ(?àh‘àûÆ/B/Îi +ÞPJ¼©íÛLr*VòÚRìaž©ÃèE´ŒŒkD{‡u-| ØÈá¸ÆT®¤³×SÆZRUD™LZ苲!}Ú|„”Œž:B×ùÌ™äÙûvÿZv—$€Ø$„Jhúšñ¾‚þa)é’“þÑŠ4ýÃàrbD.š¶º™âÑµØ êØããs+€_hŽ1¸ÌÁw÷+pîSËž¥·”¤€ ÝvÂTkŒ`€Àlˆ.âÁQ£²×™ö(( ÑO_zñ»~M +H×s’ƒ.ïEÁBýžA"×i +½7 +HËEš@dÓ?`X¦Q~Ô–Æ»ý£i7Ù4&€Þ’þÑö™þ¡ÑböG;;½õã…ðÞ¤Tq?lÏÌý —q÷µ£!ê«ÄÄâ~xùiîvèù'âh5s?š2áˆêqDë%÷ÃmŸÜŽ_e²¿î5ñ6LqÀÁ´£ì׈ܳp•ÌðpdF’Â8²,ºœ]öÇo* èF–,AO@8a›þÁF•ýƒ3»É|5ŽDûƒÇÓgE…ºXvf0l5Íþ`˜Ê˜2ѹ®,~fô¤ + ,7œ&ì>urš +Ö®÷[\­ ú%ÈVüŽ.¸sIH9ì^"›Ç®ìŸft…y“ýá5ûÓ´Ø9ƒ‹üqäU-èñ˧ûÛ"’ýa_Áô®hºØÊ,ºü‘N£ÙQ±?l•EÿH—Qì#üBÓ?l‚EÿH múǺhcß2ƒCg¸#22LÀü$ߣk/HH—×+K†÷bò‡ºæ0ûÃëˆd0ö݃ýiMd¦>^9ºÏš'zJ¥º…׳¹¨(IüàyÀ=ô:5ƒö…«>KãÄ~wèc¶ú)ê +OÜ ÚGã–ö vÀ¶Î²IWsJÊJ®dÚ磴·aŠ¦žÆðD°>ZP°DûHËbâ ëÙ‚øÑ”ÖB¼ee[Ú¯"2ÏÓÓÖ™ø‘–ÐĸêÔßüið>ô`kB{M$5?l Müà*ö#hN«´­¢Žà}Øû2ï#gbó><›ö¡Ù¶¦ …uëÃEúÀs48<}º¿ý@Fò<¼úÿÅrn´´¥Iûhƒ£úÚGŒÒd}¤Ä»-éuKR@¾f öÁäAWi6¡ômƒã‰è‚ei•£ +­EhÃørXCkÑ÷¼/lðiVŒÃiêM+±ó²qt|ÜFÚªÍhàûQ#Ú`)£ +!ËJÌïmh23+Ú€ïŽ`CSò]‡ÛŽº‚ +M™|ãj®¹lÐI ++Øàƒlh:`ÅÁ†¦±—ц3ÜàîÝ +€”g¨©Îq ɱ;eIFšÔLÑyè]=qŒ5# +Q‘˜:Pm¹÷E{ó1Ø"Þà7åäzŠk=ôÛU²§öNüü½Wÿ K§®#K˜8¾iZŮ٦†SŠcpÐÕ€'óK(œ%`T„®Ê%\šü„{A=© ø¥<&øZx®r‰a¾ÓiôÚ¼*»µg[µãºªƒH“~˜N@žˆ{kΧ +‚Ø­#[LÙ]1ý%ußy ×?“Sî0@Þ/fpû^­€oýMÕ–.I89(,ÞâªÆ¯ÞŒ'FYËnr1Œ·û¸îiUá#”cYÕ.xÓs’d™°”# ЛaÛvGDŒ[aðÞæ ÿ÷Z¶ ÷f +µŸvó¹S^“ªN+Ð`b((_÷š +nºWÞCÞ2FÝôé[‡“éslW}CoY•éÅ·Kk×´ªíÝ:Ëÿð¸²OaõÏzÜ©•!gŠ!“}‡uâ—ÝšëF¬‹ï*ª€[ÃÃ!åª*5Õ,±›ŸºjÀüú>z‘§,€òÀa œÞsŽ‘ˆÎ–ƒ`§Ÿ1ûÂ'¡ëX|ÐÄÍ«ð^²L>™¥ûÚ0ñ`|¹ŠY^’ÖQóùrós‡Øψ°ÂÆuA*áÍrdP|0Ýyw~¿"y:„¦¶|4Êî@“n™¥ˆkÊê@œ45·~*Âó >J5t%Én¤eF¥š Þv®eÃÏs¨eïl¯5E·¥_Ôã}á‰(1§žÎ Òv_B–×è#FnÈX}¦|¬ºß¢7!Þõ€_d¸7o•~YÀoïâ~ÓŸ¡ðdœ‘@ «t%²îÉ]@!S£ÏuÍñN€lMËíÁÚ=C38öZÔƒ>®—´]`]©ï¬ZD:é?$Ð(7anS‡}³6ŒõùD%ÿóú¢ bÎÕè.=eYj„p…H "oJÇßÑâ<ÑwV•‡j¢gÙ‡ºú,uõÌ¿)G’PþîÊÐÄF¾žEBéZÛ˜„‡ù)AB}½M3°écØÃ$‡ ˜gTÊ$”u•¦ºŠ*!J¯:|*I( <µ ¡Øw5 µ`ôÁ<bÕDz8‹‚L”ù$ÓÔ««¦št5–¤¥¾e.ažÃLÐë" +t’þ¡‰(M‡j™ˆbpK4n&J^ÅþŽ­Á™ÅÍK|*x(0&WEƒe˜³6æêÁCiÌCISeŠ'Võ·lw)_Õac.,Ie +ìéÙ‚‡Òžhî+\E†ëÌC¡'4”¦ãÌ’†Bk>ƒ†â¥‡i(ö׎ ¡`ÜŸ-h(²ÑØ6#&¡Ø䎌³`Å!éØz\—áfµà 0´”~E’‚Ò/¢5f `!‚¯7*HçÇ”®ï3…îÎÅ3?‚r8ÚiŠ¡1 "Lj +E#»åâ,kéøWú1(E»m’ƒRN¥£O‰°~JÏt1åzœðÃÇ£8í·NGщ>ëpÉÉA)''ßä HÞ8(×C74Fyœ£òïz›xAôÿ!—)ÎDA†§‘‰ëHÉq"Š6«Ç(¢Þ¥œòÍ2)—ÒD¥"grP€;Öà™-((¥1l}$¥8c¦((ŹzEA±””¸*êGaŽÌ¤ @<鸞V¿{PPŠ2hŠëQ5 êGáÞ–‚¢‚/çŸ<\­ãO$Çé'b&›͸æ$”rŠPx%ÖŽ0³_-¶yÖ¤ò’„Øø +JÑŽ¤#^#¨99(EãÛHwžxb)9(’“ƒ‚'—àÍ÷vÚIña^b™”B:$öü–‰¤\ÊÊ"ŠO{ðé ]ÉBá  +Z«'“P +ã!ÉAA¥Ð-¥ßël“G=MA‰^úÒ‡Ÿßôj²PÜóÉBIMAûEBÙD39j3¥4e%…4í<“"ÈHjÝ[ϽïáÓC€Åe…!¡¿}Cê!6.J©&’<:n„™C,vK2PÈ +Á@A£ëyÌr͘<\KÆù%9¡q|‰¤uz‰¯Š‚r騺8»S`ÝrØ„ÅÑ%Ü+—(ÛFU°ýH +ŠeSPÐ>¢¾ªðhJ +J©ò·@­…ööÎ$|éåÔ"·ŒÌ¥«˜jŠÂ¥ABAEšs– º e¸î`¡à7ý  +žµ½Î´HÁB‰®úÒ‘ßum²P¨Ð×b¡À¸”k±PŠ¶çš…[zÇÑ$h©¹MRT5¥Ð6ÚVL8 oædDÃL”Â=ó‘ˆÒåt<•DøcJ¢Ag’亳ïÙ>‘ÄŠáIR‰DF±m3UjÁE)"—™‡¤È•1…ƳΆ6¥(¤e.JA¥’yH܆ÉEq$×ä7Y¤ß•‡£X|aQ|6N!‰/ŒCH”ßÒd üq帔A`A"9É(ö¿’Œ²ËÉ>AÞ™›¤hTrQ²ËþømX%¥œ.Yò“TÏÛ&£Ø<oƒJ;IÑÎ-±Q ÜÛa#Eœ?³Q`;#I¹ìlNER´$2¥$‹dºâƒ@@FÁLÐFQJá$v˜Ž‚é5¡îÉËSG’€oRÀlæ…ÏM¾ó|‘¢jLF)Ja›d7©É(ž­EF±°R‘ÄU-ì!)Ó §`PŸd; +&£`Þ¯JiA%i¶ÍæE¤÷h6 +ëdg‘Qâd«ÌEbÑd[b‘QÒP×tE|ÑÑ9Jæ"ñ“lTAÄÐ,jë’´tYòõ<™‹$ú†l¯(’‚ɳÜÁFA§ŠüÃISÓIæ")Ú?ê\$E!3R¬-II)%HXÃÞM)™‹jìÄŠ6áGëk¯³X)KõÅJÁLõd.Œ¨ÒS:9‘|nrïAJáÔt)¥œ±zŠcC«ˆSCÄ ó™!a`ÌIýé3 y:ó!il[<ˆ [|`ˆLž9)iã´¯1ã´ÿ´Äçû¸¤â¤Ø"ÆQ!¿>“‘`î˜s±R¼¬2)Åþ˜I)9)Ç1! ¯8&Dópœ³râ«>"ä‰qâ©ôÔæ&¦ VWÛì¤9\›Ýx)iW×!ÚÌõwy)‚Y!ˆ%éOI=afJ„ ÌLqÂÌ”œ›ÌLÉ„™)ƒ03eÅ ÌLq ‚ÌE LLÉDäžWÂÌ«K0SR{ÌL±Ç%©v?^§rz8ñ°£æ§H>‚ ²n‰`¿ù¹C4•€RPµ=‚ ¿¸\Á@)J¶¿$Íž!#»NÐS0yBÌOÁôP";Ç54#Ü¢Á¨ÏôKIO‘|?E«‡à§0º¶ÌÇñ +Sß›rŠ2ßbr<’¡‚u•×÷´ÕjæyfŠ‘ÂÕçÒÃüË»è—fü¹oÝó(â¹Aâ§Ø…J~JYdÆNñbÄO{°:œßü”"*”ø)XÀ¹M~JQbñS ë:$ÄQ.y !ÃãYô‰‡u‡BèÕå!#ËRÄO27’2ÔÄÂ]¦ƒÔ”c»ì Ü¬AMáDlÎÑðÄløòX ­UL±‰ÑØM³4¬ä +¨aÓE.àÄv-Csë$é+ÎœaNmÁž2¿VØ”»Ðe¦‘=e¢ÄMYŽÓÁÛR‡/ºñ²$7%C-f,d0&d¶Î°6„üÇoú‘ô”¿»@Ê —¿0K ÂrÆI}Ê€à‚O@ˆ±V\,3iÅçcäã×áHyŒ¤Y0ÆH2‰÷5+—ñtKâ:ô¶]ez¦¤ŽJë±¢/\گǷŹ\£”ä×,TõK:ÙëÉŠÄk•ÿ>ª¤áîëãø9]™Ìâ[ó§n‰|°Û nîjCÖioa±mô¿çþûÿæã|\üóðÏ; :\`ýù{ï +ž¤„#‚ŸYP'M4"ðʨøkÁ±~S¯ó÷‚õ›>ùýEÖxÜø=ÄX‹GüÇü…A>[çÌß\Þºàý[YóÆ`z¹÷Uæ` ¯äT&Cý&j‘±<´ö­Q²êñ4Æ V=VAÔcý(*²JþjM†Àõ­&.Y5¹¸é[U²äˆÊl?˺dÉ_­‹ŸºÕ%ßœuY¯‰ºDÉV—Uá¨K–üÕº< +Ò½uyT‰ ;gì yËβ×%J¶ºäϲ.YòëRŠ2®v‰’Õ.åT²ÓU—,YuY?‹º¬’¿Z?u«K¾9ë²^u‰’­.«ÂQ—,ù«uA +˜Ù+ú(JVÓ·ºDÉV—üYÖ%Kþj]üÔ­.ùæ¬ËzMÔ%J¶º¬ +G]²äS—벦"DÁœFSÙÔ¢ žðÿ×ùŸÿóÿþçÿþñù/ÿøÿôùüïÿø_Îú—#~1nùó#Ÿ©‚Ÿ:W ÞÔàÒì§M¬Ä ÷ï§ßzl%üöÜ¿ÿ~M@~7’˜ý¯·ôß¾ÿÿ·ã?ýç×+ûø¯GûøwÿÚã}uï¦ÿo¾z|÷Õ¿UÒ«â£\²}7` +žv˜÷±å~~äs²äß/ÿµ2ó›ÊÜÝ +ïqÁªÊÉzÕd*­Çê,øã·§~Wû›jôI€cUëXÓ{ƒ0ÃoÙª‘üöÔïªñ|S +@rèü. Hô÷'\çþˆÔP¾PÐéS_q…a®Mƒ{Ê·/¾¾¼8“oJµJ] +É߬’%!Xr©z|óèo«S¾«Nê€_žŠe9µ&~° +¢*©züþÔo+R¿«Hj_œªe9õ&~° +¢"©|üþÔecþùŸòÕÀ¿0Š+aŸW­Wϯʗ~æX»¬Íù·Q2°cEL™ˆ”8†U¤tˆÊ=Í^ëºaèA Öáß™7>zœŽÃƒ±Œbʺ(…'aaŠºaÑÌwé9|2›Ÿe¨ˆ#òᲈ$ÅÁß5¬?øýµBFR²:”ÖMòÁåÌ[·LW]«ÿURWÖÜß:9ž5Å"½28©”eŠ®üÀûG4í~µëˆÁWR“ö¼›pø'놸Ÿ?nÊ$±@àZÅ;…¬¬ì(a¥N{Óü`äÇ«J™ü@ÈjAFð‘Ù¡tQòHET‰éüxø,Ƨ÷(äv‰Tgø¡’ÏU)7xc{[K]‡ÞeeNßKº5šÈÊs£¥j¿¡ŨÓM­F5:§²U³KÏâÍÇœ§^)%+ïVk14ÏžŒ>%+Í·ò2!ß^¬ }F¯jÀ¨rØ Âásª{¤êÍÇ:° š• Sí+[ïû‹¨ ¥[ºm0¸AíÖóÇ >”*ƒ¡¥êCMY#Š¡/Z%GãÐQñ`ìèqrùûÏåèzÞõCgfVÇ•È@P#‚÷™Ôq|úââz¶;¢¯Ía¨Õ=Ç»òk‡ž)»æ=9ú:éyIC‡|ú z~|Ä ŒP/dÒjÑ.Õ +6ÝÑÔÍ_R¼T2@¹ËÂ1©Ÿeý‚KüuKÏúñ(Vè +D‰ó>Ñ|XŽ¡¤I'{ÑKÆÙ­¬~ËÈŒŸrKI‚­ÚÞDS3lÓn¸½„nóFµÒmó +ÉÝ¿N5;h‡Q¬"fþI‡¦Õ,ø¹ +¦ò¸D,ì×}˜PƯ€­|WÒÜ{ñ˜_墣òüê9³ÿöé‘~¦/ˆ’?¾ùª÷K‘²ß¡ûþ¤§"ÝÌgeÉúxSc¢äØŠV¥âÑQòÇ7¯Cc—H?,S½Ð¼O5Uéê¡R(¸ã 7¼Ï»xz¡R¨Û¾¶mœÛ~“g«¨-¤dõÎNþ§FÙ²Ÿªóªº|éz1®ŽäÞ#ÞËãF¾”œ: cëÛ÷ Oßf‚m.mè€\‘mšf·ŒH£Íá6t2Y}÷çïVÅ^x–áôÇrIØ™-’ß.tS1KÁìY™IBÀÔ¹Fž§Ó³î+DwÒ}ï×y KÊ +Po÷w`™Ûeõa¾]T½Ì³+SÒãš”„§}táf BtË´È)ÎÓîá’èeS sÊOÚáê#"žÛ.?OŒV¿WªC¼J^ÝLÞÐÉ/»µoˆs»ÎÀºK~ýZ.Pšúúác±0ÛÚ?Ò}·Ã MgëÝöššßÕcæj>¦ñ4è€Ýû¼sò£Øâ}!z€úÄ_ç©,Ü€eOE‡·Í;†¿OxšüÚ‡ŒkþT[M=Å®¬…K(뼟ùõ~S®ë“Öµó$¨´õòü¥¸q\h•ÿì±Y…Úë ¸£ÂgkÜ^e€—èv 7¥]oWóíMgQcË0MÄÅ ð$¶-QƒèØJ†9><ê¹×Ó.^B!Dº‚Ûý%g +ÖãÉ •8EBßòdN^å:uMæT®©ÂŒÑ˜*À)lkª0wq›*@P,5§ +RW×Tƒð®±M¤º>9U@¼ï5U,ÙÖ9 +ý¡OÍY"NìJ«oΫ +µj_³D+áo¬û‡ÎcŽëÖ*ÎÛÙ†Õ¤ÆÑÝœ%ZS 9K4|s–0eسO¾«ž$ÉòÛÞ´D€ÿ<˜@"ºŠ³Ê±•0¬ÖOözÕ«tžŸÜ´)fÞÖÐ'¸‡<øá:üút#>z²˜„?ùrÞ‘‹Ð¦M [RÅÒùAbÜŸê]ŒãB·‚õ“çœçB–OáÌxiQ3tè‚˹ú7ñ΋ê{ D¨ï}FéêLU·Ó™§NS;uXØR{&ÓyøöjÛL垤Ϥ5qPv˜Óüþ. •çI¬«„ÇFÁ¥Ü]ìµAéÑyÏ·½ˆGç>©NUG.1¦M‘ÚaK™çÓtýÖŸAŽƒFÁ|4ìeºïðHÔÌ{§|~ÓMï œ¤ô-ù?u\Ê%x+å \ÎjHêÃ%<ϵ+¦’Gi‚\PÅYòkظ¶‡Ö+ÂódŠŸ …àÈÏ핱ã/e¾úaŠßrέõÀ+FUÀÌjWÔÊë¸ +zwº¼ŸÏdÅŠ3®· ²µ·Ï\ŠfÁ¿·³"0Eg°9« ¢ E‡hÉÚüý·B¢]ÇÓ(›¸oÅxÈ©À&€xiw–´`»”½?.C…7±aÊýr?lU%lá‚P9¡´|º¥O¯"z^Å„ÙRUè0Ÿ'V0]¹t&¯“Y•b˜Y3S•pT!—['»)9;cMéÁK,טM‰Þ"“ü]«»,:`8\ü¼ñœˆ|~FÔS +<%¾ï%ëT"J…@â%lîñË®Ë_Ÿ)Ò‚ióSþaú*±ÅûBtõ|0—¯‡j<2^!æÃœdƘ‚Ô<FcA¬ñõÌàa}oQÔã~ž)›—}þ¶Ž×¤–úÍÑ#s)™Þ|†½µáá6HáüÕwOÓÖu•,iÌgHàÑÙ‡ªŽâlÚÊ©xŽ¶3ÅÑÇVR/bÏ1]X<ö!*ãÜyÜZÅ7ëÌ ¨µ+û°ö(Æ¢äÔ·îg‚ÕÂ\ Db±´D,›»ö˜O#ú«Ž¯!ðÝ ømgR„Ÿ«ø‹³OSØÂÃ)½ +óõ8¾7ë¶î£&FJpŸ¶‚FŒvûMUÆ(øƒ‘ '†+dûq© dâN¦%ÓËÞ–§[§Ä{¹¸øRÒtÊRN—¿¾çoGxùhÅgÄò§=1ŸãúŸFÿKÁ±ÿ¦êô¸ß +r2÷n“ù¯UykGâÞ»è‰ôüî"Lý÷ÞEÊ|·d¨gùÒE]äì­ *§éúŽûÒEfõ+Òº‹úµõvIÞ{ÿ0§ð8¾–xäj_^²ÑÆÿÿÑõ‚ϵø’âúüe–c<`‘?ý€ÿ¯”Í0tãd &Ýöï^ý…ÕÔvVS>7ifñØä™%¡:he‹ú¼ˆf¿=çÿW2)ÈùéISÎOO.ó¿þé_X£ù”¨r¾(>}±ãC—|}úoÏù?÷éÙªþ¬­Žÿú‡Žoûx1ú¢“¥ïB¼èzK¿Ìé;VÇoTÑßþ-•n~Ûòù›ü¬¬Ðêõx×êõ¬P…?k"H†¿?üÛ +ÝßµÐ"ÆF‹dº}’Cw$ÍÐÏøÂ_ýí¹ßVåù®mò'¹]£ÿB±Î÷ÄOVšå ãñ·ç~W•r~×*æ&þëÿYM/ÀêÈ…H&¹Kþ:«ÛpÇØá’ïK¹¾ûhsw7jü;qŒ +˜’Í6o±Õ"4!Kþøý±ß6ùNò'ù9÷/›ò=K÷£ 4!*ûÇïýŽqúÿ¶v-»’ã8vï¯ÈõÕ°Þòv~%D-²ÖóûçAIqãÖt¡1» Öm‰"Eêˆ,w·{8 “ƒ hfÊ1æô¥•)gaNÁcCNA qIÐ)Èbˆ©0ŠàÄHÐéK¿2¹ŠA§rÂt +3ù“ :áÇÅMBRrªGÏ|!ô”ÏmϽ“pÑõúyúñE¯Dªé¼¡ÏøJgCÚ--Îþn¥<€§›µ_)šÞÀÓÏÇ¡Ÿ/XÀÓr+‰ïžâD ¤eí¬ågòTÈbàÐtšõž‚ƒðäÁ(\&÷í +îý:<¹n é_œiÀ/ä)›mÏFž‚¡©Úã¹aþ7”ç<ýxzk%¢Ÿ%°DT4÷ ,§Z]{»š',&f,gš·‚¹fÒ +haƒ4Ñæù?–+‹ìÊ”|\ß9ÒÆ…ú×N3Ískšº{ÑåfZž…'ÍmÍÀA,òõN3Ȫ.…³¦|ã‰ÀATÏx¢r?Þ½Ó"I™œŒ×›MDj< MtÐ ,†ÐDq·ÀD«ñ‘à)_­˜ˆ¯þ¤ +'â§Õ'àDüpI ûi´zÀ‰Øs‚©b™&ÑðŽA_h!u{çß/¹6ݸ(9.×BóøFÛh"JÌ]7ðô¢í3’´Jd’÷Ð›Ö · ‹Ñ5Õ –Ôµn‰‡[kq?°D¢Q6t‚ß7G0HÞé$1kûÛjÿ:/¸³·¿eØû†ñã´ˆ³¡çØüfW<é‘“F0Ø9Þ{oö/òÆ™6”ÈW H…ýè0z ùiL$÷¥œÿO¡“‡—²aYBy¶ƒ‘SÀ‰¢£<ˆŒùƒïq^Ãsœ×Óøÿ ê1œ$¢þND9N-àD ‰™“ÇH™OeÁ‰@óm'âÊÊp"ÒÂö Nõ¯àD$Ÿp¢ƒŒDÆ‚­Û 'Z­œˆŒÜN Éøêµp"~Ûœ'â—K„'Ù„öU4 [˜R¡\dòzÈÿ·SöúŽ¶é¶Ý ™H>]j3ñZá»ÍDRê»e&p(y™PGo­ŸÍõñ?¿o“Bïíëh +‘”úÅv e®j—•xÑsÑX?äQ¶•ÀzBˆU[‰T´•HD„‘H:1¸ŒóÖ¦‘xрⴉëöÃJ¤fƒf"5±§Ê´§Ý/ÁŠ l&âvÛ‰h~Ù‰¤=O›‰‹¯—ú2 ›ÌÃP$- CoLÝ]eh–‡×ê2I9QC³cÚ¡øÓÂÆß’kÑiáB}}b¾Ìãÿæ;Ì,˜ò2\Í–ºN(P}¢†"Ý äê¾L:,ÚOƒ‘\ßé4¤ +}Òš5ï‰Âœó$o^±©H¶ ó’ß=ì¾]@Û |{ËP¤@úö&ˆÛË,\¾Þsž†"ùø“ +H?L–ÂŒe*@—¹MEÒlSàçmS‘];þƉ°‰Nêi)4c—¥@ÇLKá~Úš?å€3ËR ›Ëº€dïï×÷mH’²:‡¡H%àÉa( Çw^†")Wo +Ek1ø"2Iõ2 G;ŒDF(ŒD"=ŒÄ&c.W6 #·ËHDëËH$Ê #w{Ú2©®ã/6IYuÃHà«û²è+ET8Ël$0“DZ¨y—üo'ƒœ:ƒF9ʛŒâÈ„œV¤šr +FÏa.ÒÄë[OÏã$ÁOÒ2š¦ióÆæä2ææì;4ª&µ¼TKMÈãJ@Ÿ“<‚¡bY‹¼×åx§q8™xNÉQ]‡#ÏÎ 9ÔÊüýxOË6Ð3â L3ä`óí¦Ñ×åê’’‹¡º‘×o@ +ÎoùŽs]ÂÎÏ*À}9ä¡9$çƪi˜íÝQP³ +Ò©Ú3?O††v*_}¡úEë[@´;¼7dSð_ù­Þ߅´*t‰Hd3Ù1>Ç"1’Ò¦áo~HÛ_«oÒ\oS”Úej£/9yƒVK‰Ù‚ôH!ät\ÀúYArê¸\™Q¿õ2üÄ“oj«„—YÑG²ZëŠhÚOú7*4k¥!s“µ>º"tádèt¦T“WF‹ÎS}Çm²LæIõ9BcˆÁítߪ© + éé ª¿§ãCÊÝÌcÞ|mUÙt ŒÕQ`8cJ䘟 +=! +Èlõ3|²(uÈɾê}†8Òÿí„€¥xx\Nw¹à„9£|,ãy<Ú«ÔMíu““'3k‡_æå&‡9³w1öz…¥eò±ÜÀ2Ze覜B©2Ñ^G§ª9œgÞïË;™×Épåãì’ôŸOy}xfæotײYÛn¢/:^; +n¾“¼úòWºŠšo_´^a?n½Òû à¤6×Pd½ÖPd%‰Xï uø"G,·c(òˆ•V Å£SqÇ£ Wk(X!°î¡È^CÇPd•VßCR….Ûã%r»Þ̤} Å—§¼‘ë’;f»¡ªæ¦t§„"Õâ¸Âв/È©tÏ?ÿ}BV5ŸnÆvó »°À¹¹ÁtûÄû¢§q?ÿî YG4_ªVœë»Uª{6­Õ£ÉÁ#§›,*´€,ÈÚѯ¬/ãñ?¯§ã¹X•×}ëÇç»ü‘úÕâx«Ll6yÁâ(þ‘´áWuòÖUÓ|q´¿kï¿ÿ ¯Ë±þ?ûýí#ÿúè×J÷m¤ÿƒ€rEd1$ Øox[–¬<‡vÛ¡0ùO%Ë­/ÁŠÖC°¢½¬MÿCÁÊj-ÁÊÏ- ¡k5)ÁÚäÿ¿`×þcdî˼䊡­—¢þc  ‚b¾¤‹Kê‹•x˜î¢P}¶õÏdêË÷ýõÑ¥ÿ@"ÞÆøïZX}–’*潌ÃɽqˆY„IåÑ•‹ä@ §Ò$–ç@ÑàªjFð UGU5õÄôI U€ –úÂ9 œ[B4x’d!æ”\kyÔ8 +˜Š¼ô!,hV—NWšT²´ÊǂãA`)Fõ%¬êž\øŒ±õî[hÑF ~Öèʦ™XyD +vþÅ"ÉluÌÒ,¢»ÏŠ¨®;ÖŽM©¹yx‘;Q쯇uØ°¬¦ÕAꀸÂPœÑaÉÔirÜ¡ã*²(Ú«=`‘ë¾ë…ÅøèjÊc³,tM:Š›Pœ—£ÞÕ¤êÚ¥$0 +?»kŒ§nHCí˜á~`és8¦y5É!e ÃÎØq8{ô4ƒpس¸ßi•zß'ÑBS£ë,+\3`¿ÄÒë"àØPñ[a4âz#bòNŸG’8ǯ +Ò_}Ñâü#:‹6y°ðº‹/³wbD5ÕËÁaØd@˜zL +pñüÐHG³/ÌJÍÎÝNÎZÎMûLöâd¦:@ ,l’Qýî"ƒË³±Îâ©,YÉŠ¯„ÒEÐ}EÓþáœL "ÿ ]r‘ʤRh’ï&Ž"R-vB±g IÌ;fŸ¿)éiMÄB<8ñê¤ô™ÉÅŽ4ï›^ +1—ä +=¾ÞÎäKë4mr]Æ‘]§U<ä¤Éîr­Ä‘-ÍÙb“–v)ÖŠJ@ú‡žÊBÉ!Ÿ`¨7X—ÔÕ{3FâFŠÃ§©î‡?™”iq™‹+ãµ{ˆ™Ä_™e9BO& +e +º1@;ÖIé%«ÙŠ4,FÖ‘‚/6…çP?ì̯oÒy¦ÚzÍ,VgÙLƹxZÆ¢€BV.¬z¹cð@ÿo1("'‡~§oúýãÚ, .xô;Îã‚…à Z©à\Z;ÊbDœ¯»0îœçÑT¨í¸©éø@|ºÓ<äú-G’-N9~ÓCÈ‘ÒÊjû—ããYœßGsUF‡Fò‰vjÏ]gó•–K¡:Kñ$pò›"Ä5'– ¬,_¦é­œÂ™øs²œ-—[4#-¬6ÃøDç̼’œàîkÏwÄÇ© +£vû-ÅøfócL¾âà +ÌÌØjA…:A~"¢’ õN9¬s~,sYpþ `mÓ!¼þÅ`Eh[óÎÓjÊ)àóTyhƒgÓ-ª•Ÿ¬h´ÚrÁÈgQ¶Š¯A£¢ ßxÍÔ«Ì'CiHE;çiÄárËó$ƒ éa¥@$ý­`ôpjõ.ÃÏÜîÕx0ê •"[p,eŠt澂©X$ûÚ“¹ÎÐ —ϹðHðº×OYiÉ»®ªDÊ+ØĈ42¶{M–vßµôÐÑ„cm‚ô/·ß*®(^%÷Å}ç ·§ž—LEèìíÎä ªx +F[‚ó]‚CØLS4¦LÙ”]%sôH!Ë\kŸ¸¥±É°ô½nG; lB‹ñ×JîÒCJ[KÝÁÎqz–üx #Qõíõk»^X¯\¯sJ7JØjÖ…ÝYÓ’å@m¬˜£§´°m×’eýŠ7ZÂú•¬rãÈ.þh^¦úˆ©!¹.z"5†±r ”Àø«~„Î|´Ái{ ô!õÍ@c)èë¡/œkY}'SpÃQïóa¿˜Å0yI?d©{æGóç‘ÝZž–9×ÁjÔãºíï8U%3÷M/©±RøŽã>Z_œ?¿ù2e8Èv"B­Èݲ_[Ö™Úw«*œëK+EËÖä|·ö¶…nLŒt½±Š¿#–#àTù9eƇiÆž>Š÷\îéâÝ°kEoN"=$æñ<$G1¯ÎÇx(õ3¯»‹jv›èS>¤kô4“ <ËA´ÃÒï07Jæ+Ÿ‚FP¾ßû­«Yo°W$/¯PѺªÛºÏ°q(}(ƒ¥=¯)±o5_µèîY¦+GÚ»ãq“â;N˜ÌuÓ;ã͆B±µò7œè¢øŠcö}|Ù¯+Ïi›.õÉaCì÷±¢Gèô°J5†œ)nAsïË[Ð +Dä6ÏNtDnA+\àÐ-É,…n_¢nm¢Ð-h­ºqX…nÁ¹C;Ò‚ÌPCÄ´Š3Fè„#t ºØêʲ/F„pON×3B]‘ê;GqñR<Áa\0¸kdž]ÃÅ}¸>Œ½|\1Bd¹J]Ã&¸–|ÜÀ™ŽE* zú…rÁiÅÛé*¦s)ø% S¬“¶i"R+/œJ´ëÅn×¾L”›ÎŸí.q”Ÿv\Ñ–FA›ãÇ®§–óì¿–ww7¢â#–{ÒŠånŽS@²;GSý¯°m±07¿e_ïô$ÝÏY1UaâÚ‘\Jol IóØqÜÝÇeO%qCDg& sÒÕ35ƒö˜rZjdLð@9øˆärˆ›Bš-¡ä­´¹›wíR –·íÑG׸丣GD!Ÿ9½cç¯ì©V[³¤¥Y†»>º:ðò1V$(Ñ­ž¬Ÿõ#«yÕ@Mk:¶åÞéŠÆƒçÈå„låZzñ§Õ€A —3ZÏ`t|ÖåŒ(ŽK-Qôáô_•.KSLž+èÙD‡$kà -UÓþåXâ#í5Ÿ´Ã¶ø2E5Ó’ü~ººê wÞÔìÒÖ=ã+º/:¥‡#H«Ór`‡qÁ‘ð+Œ z…¤ ºÉ©hq‹D5[©Æ+Œûžhéðit^†è¹—ý~途;ϳügéák­°-8B¾qä +ØsºVØFljÝòɉ°-ƒq!'B»’Åáø¢ÎPÔŒjÁØœüq“ã ±¾À©{u¾á„Ÿ†Ûz;=·?¿é" ÚËZ…*PÊw ws"™~"Ë£¯¥î@®NÊþØq\­õÄI:Ø[¸õ¡æ¼§÷å;î&™%î®^±%£‚«"JÆe–ئ$óÅe×UnŽvp˜w û‰< ›YÃ\½T^ƒˆÍ;Ù@+ ÚzPö™Yš¦U!Êo?vžØ5«êªÛZ*Ò*Éì8î¦W÷dE£ãÑÒOÇSw’Åì“#LWÃœ–; ÆÚuÿfÖÑs$$!ÐŽä2÷‰®ÏʾV  ŠÔ$a➺g‘†ðØ’æIõ6vw‹IÄqu¢Ûsáù'´#ŽKÁ4í@n$XØ\âÿcÓØ’¥ ­<(Iá3>‘2Š›âû’˜FÓgðË +í*”Ëîy?.ÃÂe7«óDuvä¢Î;K‰·t"’K©¨íGDr9C–íÎ"EÂä‚ŽÀmšÊ¯¥v>&¦¢:ÉZV°€Ü="a© +ŽØ.µÇtVHŽÇ¥ +‰YÐVwáŽã~ªÇ_:lé-)¹¶<QϽ¿Í ÍS*þš*g¿Xá©MG$÷óq¿ˆÿ¯e7&ÐjÏg\îäÈ ·nÎu°Âç䙯¿áØéÜ7½3®·/‰ÅÂwwÒúŠí…~~P¡ÙËÛˆ‚,BDA¯$„0ïA‡ÛÑ9CKwÅK®û¢È:º~^ØFFMöY¬Us[»_<¸›Û +!}ödHQì°˜vìÐÐðzQÏÝË°ˆ‚ÓcˇvyÜ.z©úÍ€¥Ívm8ä(€dK›2ŸEÜŒv˹ÖÂHyvãßbqTóxU7ÊýKŸ½ÝŽ©F°±}z +7Ç7]?¶ -Eœ©äºACP/¹îxé²\b­ñÁ™µ^o—ÄìEд4¤8Yyæ%—íÞ¢)04ÉUbŠ«‹\¶UÉÏñ½44ç êcÒN ™ !;â !Æ'B‚Jíñ%òÖ4©Éš5ú(Ä7½yƒ3,,2ìõ #5­³×‡ÈP;SèýDÆû?°5¯‡<¬SN±aÀÊ¡æÚ=Øz*,6õf(î~Žm(êc¾ÜQoZ—T£í¦–/(Åg·KIÕ¦x©mè0ï(oš.õŽ<•º!˜tÒjwg +)Ôr +Tcéºf©KkPyô7Ò>ÁâT#б€Ä Q>D¡¦¶î¨.ÑÀá-/aŽ‡ª”¡\-JùÔ¦D#œdÂf'9ÉóX•xâ䧺Ó«sÛ¾â¥z‚ö>š’ŠŒ2ÝÃÁ^wÔêÈ{\’=;ïGr³üWF!z388ªiõÞ.+y€Ñ’u…ŒjÝU œ`L/|“äκϲŒœ-Õ²ÂL»XËÚÐí`Œi ôíI—¬è,{<[t–u«ywiÝ0‰b‹LßeÞXoï’×$\nØêÀ¹:œ*—à“« ^UÃåÎzlŠ•`ݘúp|õ€è5> + >> + /Pattern << /p5 5 0 R /p6 6 0 R /p7 7 0 R /p8 8 0 R /p9 9 0 R /p10 10 0 R /p11 11 0 R /p12 12 0 R /p13 13 0 R /p14 14 0 R /p15 15 0 R /p16 16 0 R /p17 17 0 R /p18 18 0 R /p19 19 0 R /p20 20 0 R /p21 21 0 R /p22 22 0 R >> +>> +endobj +23 0 obj +<< /Type /Page + /Parent 1 0 R + /MediaBox [ 0 0 400.501068 293.187134 ] + /Contents 3 0 R + /Group << + /Type /Group + /S /Transparency + /I true + /CS /DeviceRGB + >> + /Resources 2 0 R +>> +endobj +5 0 obj +<< /Length 25 0 R + /PatternType 1 + /BBox [ 0 0 403 1781 ] + /XStep 403 + /YStep 1781 + /TilingType 1 + /PaintType 1 + /Matrix [ 0.008 0 -0 0.008 187.706543 184.616422 ] + /Resources << /XObject << /x24 24 0 R >> >> +>> +stream + /x24 Do + + +endstream +endobj +25 0 obj + 11 +endobj +6 0 obj +<< /Length 27 0 R + /PatternType 1 + /BBox [ 0 0 403 1781 ] + /XStep 403 + /YStep 1781 + /TilingType 1 + /PaintType 1 + /Matrix [ 0.008 0 -0 0.008 216.053 156.269974 ] + /Resources << /XObject << /x26 26 0 R >> >> +>> +stream + /x26 Do + + +endstream +endobj +27 0 obj + 11 +endobj +7 0 obj +<< /Length 29 0 R + /PatternType 1 + /BBox [ 0 0 403 1781 ] + /XStep 403 + /YStep 1781 + /TilingType 1 + /PaintType 1 + /Matrix [ 0.008 0 -0 0.008 216.053 99.577062 ] + /Resources << /XObject << /x28 28 0 R >> >> +>> +stream + /x28 Do + + +endstream +endobj +29 0 obj + 11 +endobj +8 0 obj +<< /Length 31 0 R + /PatternType 1 + /BBox [ 0 0 403 1781 ] + /XStep 403 + /YStep 1781 + /TilingType 1 + /PaintType 1 + /Matrix [ 0.008 0 -0 0.008 216.053 71.230598 ] + /Resources << /XObject << /x30 30 0 R >> >> +>> +stream + /x30 Do + + +endstream +endobj +31 0 obj + 11 +endobj +9 0 obj +<< /Length 33 0 R + /PatternType 1 + /BBox [ 0 0 403 1781 ] + /XStep 403 + /YStep 1781 + /TilingType 1 + /PaintType 1 + /Matrix [ 0.008 0 -0 0.008 216.053 42.884174 ] + /Resources << /XObject << /x32 32 0 R >> >> +>> +stream + /x32 Do + + +endstream +endobj +33 0 obj + 11 +endobj +10 0 obj +<< /Length 35 0 R + /PatternType 1 + /BBox [ 0 0 403 1781 ] + /XStep 403 + /YStep 1781 + /TilingType 1 + /PaintType 1 + /Matrix [ 0.008 0 -0 0.008 286.919136 184.61643 ] + /Resources << /XObject << /x34 34 0 R >> >> +>> +stream + /x34 Do + + +endstream +endobj +35 0 obj + 11 +endobj +11 0 obj +<< /Length 37 0 R + /PatternType 1 + /BBox [ 0 0 403 1781 ] + /XStep 403 + /YStep 1781 + /TilingType 1 + /PaintType 1 + /Matrix [ 0.008 0 -0 0.008 286.919136 156.269974 ] + /Resources << /XObject << /x36 36 0 R >> >> +>> +stream + /x36 Do + + +endstream +endobj +37 0 obj + 11 +endobj +12 0 obj +<< /Length 39 0 R + /PatternType 1 + /BBox [ 0 0 403 1781 ] + /XStep 403 + /YStep 1781 + /TilingType 1 + /PaintType 1 + /Matrix [ 0.008 0 -0 0.008 286.919136 99.577062 ] + /Resources << /XObject << /x38 38 0 R >> >> +>> +stream + /x38 Do + + +endstream +endobj +39 0 obj + 11 +endobj +13 0 obj +<< /Length 41 0 R + /PatternType 1 + /BBox [ 0 0 403 1781 ] + /XStep 403 + /YStep 1781 + /TilingType 1 + /PaintType 1 + /Matrix [ 0.008 0 -0 0.008 286.919128 71.230574 ] + /Resources << /XObject << /x40 40 0 R >> >> +>> +stream + /x40 Do + + +endstream +endobj +41 0 obj + 11 +endobj +14 0 obj +<< /Length 43 0 R + /PatternType 1 + /BBox [ 0 0 403 1781 ] + /XStep 403 + /YStep 1781 + /TilingType 1 + /PaintType 1 + /Matrix [ 0.008 0 -0 0.008 357.78528 184.616422 ] + /Resources << /XObject << /x42 42 0 R >> >> +>> +stream + /x42 Do + + +endstream +endobj +43 0 obj + 11 +endobj +15 0 obj +<< /Length 45 0 R + /PatternType 1 + /BBox [ 0 0 403 1781 ] + /XStep 403 + /YStep 1781 + /TilingType 1 + /PaintType 1 + /Matrix [ 0.008 0 -0 0.008 456.997872 184.61643 ] + /Resources << /XObject << /x44 44 0 R >> >> +>> +stream + /x44 Do + + +endstream +endobj +45 0 obj + 11 +endobj +16 0 obj +<< /Length 47 0 R + /PatternType 1 + /BBox [ 0 0 403 1781 ] + /XStep 403 + /YStep 1781 + /TilingType 1 + /PaintType 1 + /Matrix [ 0.008 0 -0 0.008 386.131736 156.269974 ] + /Resources << /XObject << /x46 46 0 R >> >> +>> +stream + /x46 Do + + +endstream +endobj +47 0 obj + 11 +endobj +17 0 obj +<< /Length 49 0 R + /PatternType 1 + /BBox [ 0 0 403 1781 ] + /XStep 403 + /YStep 1781 + /TilingType 1 + /PaintType 1 + /Matrix [ 0.008 0 -0 0.008 456.997873 156.269976 ] + /Resources << /XObject << /x48 48 0 R >> >> +>> +stream + /x48 Do + + +endstream +endobj +49 0 obj + 11 +endobj +18 0 obj +<< /Length 51 0 R + /PatternType 1 + /BBox [ 0 0 403 1781 ] + /XStep 403 + /YStep 1781 + /TilingType 1 + /PaintType 1 + /Matrix [ 0.008 0 -0 0.008 386.131736 99.577062 ] + /Resources << /XObject << /x50 50 0 R >> >> +>> +stream + /x50 Do + + +endstream +endobj +51 0 obj + 11 +endobj +19 0 obj +<< /Length 53 0 R + /PatternType 1 + /BBox [ 0 0 403 1781 ] + /XStep 403 + /YStep 1781 + /TilingType 1 + /PaintType 1 + /Matrix [ 0.008 0 -0 0.008 456.997872 99.577062 ] + /Resources << /XObject << /x52 52 0 R >> >> +>> +stream + /x52 Do + + +endstream +endobj +53 0 obj + 11 +endobj +20 0 obj +<< /Length 55 0 R + /PatternType 1 + /BBox [ 0 0 403 1781 ] + /XStep 403 + /YStep 1781 + /TilingType 1 + /PaintType 1 + /Matrix [ 0.008 0 -0 0.008 386.131744 71.230654 ] + /Resources << /XObject << /x54 54 0 R >> >> +>> +stream + /x54 Do + + +endstream +endobj +55 0 obj + 11 +endobj +21 0 obj +<< /Length 57 0 R + /PatternType 1 + /BBox [ 0 0 403 1781 ] + /XStep 403 + /YStep 1781 + /TilingType 1 + /PaintType 1 + /Matrix [ 0.008 0 -0 0.008 401.722288 42.88415 ] + /Resources << /XObject << /x56 56 0 R >> >> +>> +stream + /x56 Do + + +endstream +endobj +57 0 obj + 11 +endobj +22 0 obj +<< /Length 59 0 R + /PatternType 1 + /BBox [ 0 0 403 1781 ] + /XStep 403 + /YStep 1781 + /TilingType 1 + /PaintType 1 + /Matrix [ 0.008 0 -0 0.008 456.997872 42.884118 ] + /Resources << /XObject << /x58 58 0 R >> >> +>> +stream + /x58 Do + + +endstream +endobj +59 0 obj + 11 +endobj +24 0 obj +<< /Length 61 0 R + /Filter /FlateDecode + /Type /XObject + /Subtype /Form + /BBox [ 0 0 403 1781 ] + /Resources 60 0 R +>> +stream +xœŠ1 +€0û{Å~À󢓼@,¢¥Xˆ‚ Z ¿o”eØÙD‚/C‹rì7YÁ“Ç.÷ i†°`#Eó‹Æyƒõ¢JÙšÊA*\¨g¯šµkØÚ€#"Ezk, +endstream +endobj +61 0 obj + 100 +endobj +60 0 obj +<< + /ExtGState << + /a0 << /CA 1 /ca 1 >> + >> +>> +endobj +26 0 obj +<< /Length 63 0 R + /Filter /FlateDecode + /Type /XObject + /Subtype /Form + /BBox [ 0 0 403 1781 ] + /Resources 62 0 R +>> +stream +xœŠ1 +€0û{Å~À󢓼@,¢¥Xˆ‚ Z ¿o”eØÙD‚/C‹rì7YÁ“Ç.÷ i†°`#Eó‹Æyƒõ¢JÙšÊA*\¨g¯šµkØÚ€#"Ezk, +endstream +endobj +63 0 obj + 100 +endobj +62 0 obj +<< + /ExtGState << + /a0 << /CA 1 /ca 1 >> + >> +>> +endobj +28 0 obj +<< /Length 65 0 R + /Filter /FlateDecode + /Type /XObject + /Subtype /Form + /BBox [ 0 0 403 1781 ] + /Resources 64 0 R +>> +stream +xœŠ1 +€0û{Å~À󢓼@,¢¥Xˆ‚ Z ¿o”eØÙD‚/C‹rì7YÁ“Ç.÷ i†°`#Eó‹Æyƒõ¢JÙšÊA*\¨g¯šµkØÚ€#"Ezk, +endstream +endobj +65 0 obj + 100 +endobj +64 0 obj +<< + /ExtGState << + /a0 << /CA 1 /ca 1 >> + >> +>> +endobj +30 0 obj +<< /Length 67 0 R + /Filter /FlateDecode + /Type /XObject + /Subtype /Form + /BBox [ 0 0 403 1781 ] + /Resources 66 0 R +>> +stream +xœŠ1 +€0û{Å~À󢓼@,¢¥Xˆ‚ Z ¿o”eØÙD‚/C‹rì7YÁ“Ç.÷ i†°`#Eó‹Æyƒõ¢JÙšÊA*\¨g¯šµkØÚ€#"Ezk, +endstream +endobj +67 0 obj + 100 +endobj +66 0 obj +<< + /ExtGState << + /a0 << /CA 1 /ca 1 >> + >> +>> +endobj +32 0 obj +<< /Length 69 0 R + /Filter /FlateDecode + /Type /XObject + /Subtype /Form + /BBox [ 0 0 403 1781 ] + /Resources 68 0 R +>> +stream +xœŠ1 +€0û{Å~À󢓼@,¢¥Xˆ‚ Z ¿o”eØÙD‚/C‹rì7YÁ“Ç.÷ i†°`#Eó‹Æyƒõ¢JÙšÊA*\¨g¯šµkØÚ€#"Ezk, +endstream +endobj +69 0 obj + 100 +endobj +68 0 obj +<< + /ExtGState << + /a0 << /CA 1 /ca 1 >> + >> +>> +endobj +34 0 obj +<< /Length 71 0 R + /Filter /FlateDecode + /Type /XObject + /Subtype /Form + /BBox [ 0 0 403 1781 ] + /Resources 70 0 R +>> +stream +xœŠ1 +€0û{Å~À󢓼@,¢¥Xˆ‚ Z ¿o”eØÙD‚/C‹rì7YÁ“Ç.÷ i†°`#Eó‹Æyƒõ¢JÙšÊA*\¨g¯šµkØÚ€#"Ezk, +endstream +endobj +71 0 obj + 100 +endobj +70 0 obj +<< + /ExtGState << + /a0 << /CA 1 /ca 1 >> + >> +>> +endobj +36 0 obj +<< /Length 73 0 R + /Filter /FlateDecode + /Type /XObject + /Subtype /Form + /BBox [ 0 0 403 1781 ] + /Resources 72 0 R +>> +stream +xœŠ1 +€0û{Å~À󢓼@,¢¥Xˆ‚ Z ¿o”eØÙD‚/C‹rì7YÁ“Ç.÷ i†°`#Eó‹Æyƒõ¢JÙšÊA*\¨g¯šµkØÚ€#"Ezk, +endstream +endobj +73 0 obj + 100 +endobj +72 0 obj +<< + /ExtGState << + /a0 << /CA 1 /ca 1 >> + >> +>> +endobj +38 0 obj +<< /Length 75 0 R + /Filter /FlateDecode + /Type /XObject + /Subtype /Form + /BBox [ 0 0 403 1781 ] + /Resources 74 0 R +>> +stream +xœŠ1 +€0û{Å~À󢓼@,¢¥Xˆ‚ Z ¿o”eØÙD‚/C‹rì7YÁ“Ç.÷ i†°`#Eó‹Æyƒõ¢JÙšÊA*\¨g¯šµkØÚ€#"Ezk, +endstream +endobj +75 0 obj + 100 +endobj +74 0 obj +<< + /ExtGState << + /a0 << /CA 1 /ca 1 >> + >> +>> +endobj +40 0 obj +<< /Length 77 0 R + /Filter /FlateDecode + /Type /XObject + /Subtype /Form + /BBox [ 0 0 403 1781 ] + /Resources 76 0 R +>> +stream +xœŠ1 +€0û{Å~À󢓼@,¢¥Xˆ‚ Z ¿o”eØÙD‚/C‹rì7YÁ“Ç.÷ i†°`#Eó‹Æyƒõ¢JÙšÊA*\¨g¯šµkØÚ€#"Ezk, +endstream +endobj +77 0 obj + 100 +endobj +76 0 obj +<< + /ExtGState << + /a0 << /CA 1 /ca 1 >> + >> +>> +endobj +42 0 obj +<< /Length 79 0 R + /Filter /FlateDecode + /Type /XObject + /Subtype /Form + /BBox [ 0 0 403 1781 ] + /Resources 78 0 R +>> +stream +xœŠ1 +€0û{Å~À󢓼@,¢¥Xˆ‚ Z ¿o”eØÙD‚/C‹rì7YÁ“Ç.÷ i†°`#Eó‹Æyƒõ¢JÙšÊA*\¨g¯šµkØÚ€#"Ezk, +endstream +endobj +79 0 obj + 100 +endobj +78 0 obj +<< + /ExtGState << + /a0 << /CA 1 /ca 1 >> + >> +>> +endobj +44 0 obj +<< /Length 81 0 R + /Filter /FlateDecode + /Type /XObject + /Subtype /Form + /BBox [ 0 0 403 1781 ] + /Resources 80 0 R +>> +stream +xœŠ1 +€0û{Å~À󢓼@,¢¥Xˆ‚ Z ¿o”eØÙD‚/C‹rì7YÁ“Ç.÷ i†°`#Eó‹Æyƒõ¢JÙšÊA*\¨g¯šµkØÚ€#"Ezk, +endstream +endobj +81 0 obj + 100 +endobj +80 0 obj +<< + /ExtGState << + /a0 << /CA 1 /ca 1 >> + >> +>> +endobj +46 0 obj +<< /Length 83 0 R + /Filter /FlateDecode + /Type /XObject + /Subtype /Form + /BBox [ 0 0 403 1781 ] + /Resources 82 0 R +>> +stream +xœŠ1 +€0û{Å~À󢓼@,¢¥Xˆ‚ Z ¿o”eØÙD‚/C‹rì7YÁ“Ç.÷ i†°`#Eó‹Æyƒõ¢JÙšÊA*\¨g¯šµkØÚ€#"Ezk, +endstream +endobj +83 0 obj + 100 +endobj +82 0 obj +<< + /ExtGState << + /a0 << /CA 1 /ca 1 >> + >> +>> +endobj +48 0 obj +<< /Length 85 0 R + /Filter /FlateDecode + /Type /XObject + /Subtype /Form + /BBox [ 0 0 403 1781 ] + /Resources 84 0 R +>> +stream +xœŠ1 +€0û{Å~À󢓼@,¢¥Xˆ‚ Z ¿o”eØÙD‚/C‹rì7YÁ“Ç.÷ i†°`#Eó‹Æyƒõ¢JÙšÊA*\¨g¯šµkØÚ€#"Ezk, +endstream +endobj +85 0 obj + 100 +endobj +84 0 obj +<< + /ExtGState << + /a0 << /CA 1 /ca 1 >> + >> +>> +endobj +50 0 obj +<< /Length 87 0 R + /Filter /FlateDecode + /Type /XObject + /Subtype /Form + /BBox [ 0 0 403 1781 ] + /Resources 86 0 R +>> +stream +xœŠ1 +€0û{Å~À󢓼@,¢¥Xˆ‚ Z ¿o”eØÙD‚/C‹rì7YÁ“Ç.÷ i†°`#Eó‹Æyƒõ¢JÙšÊA*\¨g¯šµkØÚ€#"Ezk, +endstream +endobj +87 0 obj + 100 +endobj +86 0 obj +<< + /ExtGState << + /a0 << /CA 1 /ca 1 >> + >> +>> +endobj +52 0 obj +<< /Length 89 0 R + /Filter /FlateDecode + /Type /XObject + /Subtype /Form + /BBox [ 0 0 403 1781 ] + /Resources 88 0 R +>> +stream +xœŠ1 +€0û{Å~À󢓼@,¢¥Xˆ‚ Z ¿o”eØÙD‚/C‹rì7YÁ“Ç.÷ i†°`#Eó‹Æyƒõ¢JÙšÊA*\¨g¯šµkØÚ€#"Ezk, +endstream +endobj +89 0 obj + 100 +endobj +88 0 obj +<< + /ExtGState << + /a0 << /CA 1 /ca 1 >> + >> +>> +endobj +54 0 obj +<< /Length 91 0 R + /Filter /FlateDecode + /Type /XObject + /Subtype /Form + /BBox [ 0 0 403 1781 ] + /Resources 90 0 R +>> +stream +xœŠ1 +€0û{Å~À󢓼@,¢¥Xˆ‚ Z ¿o”eØÙD‚/C‹rì7YÁ“Ç.÷ i†°`#Eó‹Æyƒõ¢JÙšÊA*\¨g¯šµkØÚ€#"Ezk, +endstream +endobj +91 0 obj + 100 +endobj +90 0 obj +<< + /ExtGState << + /a0 << /CA 1 /ca 1 >> + >> +>> +endobj +56 0 obj +<< /Length 93 0 R + /Filter /FlateDecode + /Type /XObject + /Subtype /Form + /BBox [ 0 0 403 1781 ] + /Resources 92 0 R +>> +stream +xœŠ1 +€0û{Å~À󢓼@,¢¥Xˆ‚ Z ¿o”eØÙD‚/C‹rì7YÁ“Ç.÷ i†°`#Eó‹Æyƒõ¢JÙšÊA*\¨g¯šµkØÚ€#"Ezk, +endstream +endobj +93 0 obj + 100 +endobj +92 0 obj +<< + /ExtGState << + /a0 << /CA 1 /ca 1 >> + >> +>> +endobj +58 0 obj +<< /Length 95 0 R + /Filter /FlateDecode + /Type /XObject + /Subtype /Form + /BBox [ 0 0 403 1781 ] + /Resources 94 0 R +>> +stream +xœŠ1 +€0û{Å~À󢓼@,¢¥Xˆ‚ Z ¿o”eØÙD‚/C‹rì7YÁ“Ç.÷ i†°`#Eó‹Æyƒõ¢JÙšÊA*\¨g¯šµkØÚ€#"Ezk, +endstream +endobj +95 0 obj + 100 +endobj +94 0 obj +<< + /ExtGState << + /a0 << /CA 1 /ca 1 >> + >> +>> +endobj +1 0 obj +<< /Type /Pages + /Kids [ 23 0 R ] + /Count 1 +>> +endobj +96 0 obj +<< /Creator (cairo 1.14.1 (http://cairographics.org)) + /Producer (cairo 1.14.1 (http://cairographics.org)) +>> +endobj +97 0 obj +<< /Type /Catalog + /Pages 1 0 R +>> +endobj +xref +0 98 +0000000000 65535 f +0000047762 00000 n +0000035514 00000 n +0000000015 00000 n +0000035490 00000 n +0000036039 00000 n +0000036333 00000 n +0000036624 00000 n +0000036914 00000 n +0000037204 00000 n +0000037494 00000 n +0000037788 00000 n +0000038083 00000 n +0000038377 00000 n +0000038671 00000 n +0000038965 00000 n +0000039259 00000 n +0000039554 00000 n +0000039849 00000 n +0000040143 00000 n +0000040437 00000 n +0000040731 00000 n +0000041024 00000 n +0000035810 00000 n +0000041318 00000 n +0000036311 00000 n +0000041676 00000 n +0000036602 00000 n +0000042034 00000 n +0000036892 00000 n +0000042392 00000 n +0000037182 00000 n +0000042750 00000 n +0000037472 00000 n +0000043108 00000 n +0000037766 00000 n +0000043466 00000 n +0000038061 00000 n +0000043824 00000 n +0000038355 00000 n +0000044182 00000 n +0000038649 00000 n +0000044540 00000 n +0000038943 00000 n +0000044898 00000 n +0000039237 00000 n +0000045256 00000 n +0000039532 00000 n +0000045614 00000 n +0000039827 00000 n +0000045972 00000 n +0000040121 00000 n +0000046330 00000 n +0000040415 00000 n +0000046688 00000 n +0000040709 00000 n +0000047046 00000 n +0000041002 00000 n +0000047404 00000 n +0000041296 00000 n +0000041603 00000 n +0000041580 00000 n +0000041961 00000 n +0000041938 00000 n +0000042319 00000 n +0000042296 00000 n +0000042677 00000 n +0000042654 00000 n +0000043035 00000 n +0000043012 00000 n +0000043393 00000 n +0000043370 00000 n +0000043751 00000 n +0000043728 00000 n +0000044109 00000 n +0000044086 00000 n +0000044467 00000 n +0000044444 00000 n +0000044825 00000 n +0000044802 00000 n +0000045183 00000 n +0000045160 00000 n +0000045541 00000 n +0000045518 00000 n +0000045899 00000 n +0000045876 00000 n +0000046257 00000 n +0000046234 00000 n +0000046615 00000 n +0000046592 00000 n +0000046973 00000 n +0000046950 00000 n +0000047331 00000 n +0000047308 00000 n +0000047689 00000 n +0000047666 00000 n +0000047828 00000 n +0000047956 00000 n +trailer +<< /Size 98 + /Root 97 0 R + /Info 96 0 R +>> +startxref +48009 +%%EOF Index: tags/1.2/doc/src/trm/images/lxp32-logo.pdf =================================================================== --- tags/1.2/doc/src/trm/images/lxp32-logo.pdf (nonexistent) +++ tags/1.2/doc/src/trm/images/lxp32-logo.pdf (revision 10) @@ -0,0 +1,68 @@ +%PDF-1.5 +%µí®û +3 0 obj +<< /Length 4 0 R + /Filter /FlateDecode +>> +stream +xœmNIÃ0¼óŠù@S ö7ú„÷à’þ_ªq–Ji…€0Ì,ÄðX3î##¿IŒÄ ¢¸yY'ÌÄX2à.‘h†:êZÏò‚hj¨4äY¶g_Ô–{ÒÉœ›°F½÷þÙ9Lûú—ô äµ,A +endstream +endobj +4 0 obj + 116 +endobj +2 0 obj +<< + /ExtGState << + /a0 << /CA 1 /ca 1 >> + >> +>> +endobj +5 0 obj +<< /Type /Page + /Parent 1 0 R + /MediaBox [ 0 0 432 432 ] + /Contents 3 0 R + /Group << + /Type /Group + /S /Transparency + /I true + /CS /DeviceRGB + >> + /Resources 2 0 R +>> +endobj +1 0 obj +<< /Type /Pages + /Kids [ 5 0 R ] + /Count 1 +>> +endobj +6 0 obj +<< /Creator (cairo 1.14.1 (http://cairographics.org)) + /Producer (cairo 1.14.1 (http://cairographics.org)) +>> +endobj +7 0 obj +<< /Type /Catalog + /Pages 1 0 R +>> +endobj +xref +0 8 +0000000000 65535 f +0000000516 00000 n +0000000230 00000 n +0000000015 00000 n +0000000208 00000 n +0000000302 00000 n +0000000581 00000 n +0000000708 00000 n +trailer +<< /Size 8 + /Root 7 0 R + /Info 6 0 R +>> +startxref +760 +%%EOF Index: tags/1.2/doc/src/trm/lxp32-trm.tex =================================================================== --- tags/1.2/doc/src/trm/lxp32-trm.tex (nonexistent) +++ tags/1.2/doc/src/trm/lxp32-trm.tex (revision 10) @@ -0,0 +1,1860 @@ +% !TEX TS-program = lualatex +\documentclass[a4paper,12pt,twoside,extrafontsizes]{memoir} + +\input{preamble.tex} + +\begin{document} + +\input{frontmatter.tex} + +\mainmatter + +\chapter{Introduction} + +\section{Main features} + +\lxp{} (\emph{Lightweight eXecution Pipeline}) is a small 32-bit CPU IP core optimized for FPGA implementation. Its key features include: + +\begin{itemize} + \item portability (described in behavioral VHDL-93, not tied to any particular vendor); + \item 3-stage hazard-free pipeline; + \item 256 registers implemented as a RAM block; + \item a simple instruction set with only 30 distinct opcodes; + \item separate instruction and data buses, optional instruction cache; + \item WISHBONE compatibility; + \item 8 interrupts with hardwired priorities; + \item optional divider. +\end{itemize} + +As a lightweight CPU core, \lxp{} lacks some features of more advanced processors, such as nested interrupt handling, debugging support, floating-point and memory management units. \lxp{} is based on an original ISA (Instruction Set Architecture) which does not currently have a C compiler. It can be programmed in the assembly language covered by Appendix \ref{app:assemblylanguage}. + +Two major hardware versions of the CPU are provided: \lxp{}U which does not include an instruction cache and uses the Low Latency Interface (Section \ref{sec:lli}) to fetch instructions, and \lxp{}C which fetches instructions over a cached WISHBONE bus protocol. These versions are otherwise identical and have the same instruction set architecture. + +\section{Implementation estimates} + +Typical results of \lxp{} core FPGA implementation are presented in Table \ref{tab:implementation}. Note that these data are only useful as rough estimates, since actual results depend greatly on tool versions and configuration, design constraints, device utilization ratio and other factors. + +Data on two configurations are provided: + +\begin{itemize} + \item \emph{Compact}: \lxp{}U (without instruction cache), no divider, 2-cycle multiplier. + \item \emph{Full}: \lxp{}C (with instruction cache), divider, 2-cycle multiplier. +\end{itemize} + +The slowest speed grade was used for clock frequency estimation. + +\begin{table}[htbp] + \caption{Typical results of \lxp{} core FPGA implementation} + \label{tab:implementation} + \begin{tabularx}{\textwidth}{Q{0.5\textwidth}LL} + \toprule + Resource & Compact & Full \\ + \midrule + \multicolumn{3}{c}{Microsemi\textregistered{} IGLOO\textregistered{}2 M2GL005-FG484} \\ + \midrule + Logic elements (LUT+DFF) & 1457 & 2086 \\ + \hspace*{1em}LUTs & 1421 & 1999 \\ + \hspace*{1em}Flip-flops & 706 & 1110 \\ + Mathblocks (MACC) & 3 & 3 \\ + RAM blocks (RAM1K18) & 2 & 3 \\ + Clock frequency & 107.7 MHz & 109.2 MHz \\ + \midrule + \multicolumn{3}{c}{Xilinx\textregistered{} Artix\textregistered{}-7 xc7a15tfgg484-1} \\ + \midrule + Slices & 235 & 365 \\ + \hspace*{1em}LUTs & 666 & 1011 \\ + \hspace*{1em}Flip-flops & 528 & 883 \\ + DSP blocks (DSP48E1) & 4 & 4 \\ + RAM blocks (RAMB18E1) & 2 & 3 \\ + Clock frequency & 111.9 MHz & 120.2 MHz \\ + \bottomrule + \end{tabularx} +\end{table} + +\section{Structure of this manual} + +General description of the \lxp{} operation from a software developer's point of view can be found in Chapter \ref{ch:isa}, \styledtitleref{ch:isa}. Future versions of the \lxp{} CPU are intended to be at least backwards compatible with this architecture. + +Topics related to hardware, such as synthesis, implementation and interfacing other IP cores, are covered in Chapter \ref{ch:integration}, \styledtitleref{ch:integration}. A brief description of the \lxp{} pipelined architecture is provided in Chapter \ref{ch:pipeline}, \styledtitleref{ch:pipeline}. The \lxp{} IP core package includes a verification environment (self-checking testbench) which can be used to simulate the design as described in Chapter \ref{ch:simulation}, \styledtitleref{ch:simulation}. + +Documentation for tools shipped with the \lxp{} IP core package (assembler/linker, disassembler and interconnect generator) is provided in Chapter \ref{ch:developmenttools}, \styledtitleref{ch:developmenttools}. + +Appendices include a detailed description of the \lxp{} instruction set, instruction cycle counts and \lxp{} assembly language definition. WISHBONE datasheet required by the WISHBONE specification is also provided. + +\chapter{Instruction set architecture} +\label{ch:isa} + +\section{Data format} + +Most \lxp{} instructions work with 32-bit data words. A few instructions that address individual bytes use little-endian order, that is, the least significant byte is stored at the lowest address. Signed values are encoded in a 2's complement format. + +\section{Instruction format} +\label{sec:instructionformat} + +All \lxp{} instructions are encoded as 32-bit words, with the exception of \instr{lc} (\instrname{Load Constant}), which occupies two adjacent 32-bit words. Instructions in memory must be aligned to word boundaries. + +Most arithmetic and logical instructions take two source operands and write the result to an independent destination register. General instruction format is presented on Figure \ref{fig:instructionformat}. + +\begin{figure}[htbp] + \centering + \includegraphics[scale=1.2]{images/instructionformat.pdf} + \caption{\lxp{} instruction format} + \label{fig:instructionformat} +\end{figure} + +This format includes the following fields: + +\begin{enumerate} + \item OPCODE -- a 6-bit instruction code (see Appendix \ref{app:instructionset}). + \item T1 -- type of the RD1 field. + \item T2 -- type of the RD2 field. + \item DST -- register number (usually the destination register). + \item RD1 -- register/direct operand 1. + \item RD2 -- register/direct operand 2. +\end{enumerate} + +Some of these fields may not have meaning for a particular instruction; such unused fields are replaced with zeros. + +DST field specifies one of the 256 \lxp{} registers. RD1 and RD2 fields can denote either source register operands or direct (immediate) operands: if the corresponding T field is 1, RD value is a register number, otherwise it is interpreted as a direct signed byte in a 2's complement format (valid values range from -128 to 127). + +For example, consider the following instruction that adds \code{10} to \code{r0} and writes the result to \code{r1}: + +\begin{codepar} + \instr{add} r1, r0, 10 +\end{codepar} + +In this example, OPCODE is \code{010000}, T1 is \code{1}, T2 is \code{0}, DST is \code{00000001}, RD1 is \code{00000000} and RD2 is \code{00001010}. Hence, the instruction is encoded as \code{0x4201000A}. + +For convenience, some instructions have alias mnemonics. For example, \lxp{} does not have a distinct \instr{mov} opcode: instead, \code{\instr{mov} dst, src} is an alias for \code{\instr{add} dst, src, 0}. + +A complete list of \lxp{} instructions is provided in Appendix \ref{app:instructionset}. + +\section{Registers} + +\lxp{} has 256 registers denoted as \code{r0} -- \code{r255}. The first 240 of them (from \code{r0} to \code{r239}) are general-purpose registers (GPR), the last 16 (from \code{r240} to \code{r255}) are special-purpose registers (SPR). For convenience, some special-purpose registers have alias names: for example, \code{r255} can be also referred to as \code{sp} (stack pointer). Special purpose registers are listed in Table \ref{tab:spr}. Some of these registers are reserved: the software should not access them. + +\begin{table}[htbp] + \caption{\lxp{} special-purpose registers} + \label{tab:spr} + \begin{tabularx}{\textwidth}{llL} + \toprule + Alias name & Generic name & Description \\ + \midrule + \code{iv0} & \code{r240} & Interrupt vector 0 (Section \ref{sec:interrupthandling}) \\ + \code{iv1} & \code{r241} & Interrupt vector 1 (Section \ref{sec:interrupthandling}) \\ + \code{iv2} & \code{r242} & Interrupt vector 2 (Section \ref{sec:interrupthandling}) \\ + \code{iv3} & \code{r243} & Interrupt vector 3 (Section \ref{sec:interrupthandling}) \\ + \code{iv4} & \code{r244} & Interrupt vector 4 (Section \ref{sec:interrupthandling}) \\ + \code{iv5} & \code{r245} & Interrupt vector 5 (Section \ref{sec:interrupthandling}) \\ + \code{iv6} & \code{r246} & Interrupt vector 6 (Section \ref{sec:interrupthandling}) \\ + \code{iv7} & \code{r247} & Interrupt vector 7 (Section \ref{sec:interrupthandling}) \\ + \multicolumn{1}{l}{---} & \code{r248}\,--\,\code{r251} & \emph{Reserved} \\ + \code{cr} & \code{r252} & Control register (Section \ref{sec:interrupthandling}) \\ + \code{irp} & \code{r253} & Interrupt return pointer (Section \ref{sec:interrupthandling}) \\ + \code{rp} & \code{r254} & Return pointer (Section \ref{sec:callingprocedures})\\ + \code{sp} & \code{r255} & Stack pointer (Section \ref{sec:stack}) \\ + \bottomrule + \end{tabularx} +\end{table} + +All registers are zero-initialized during the CPU reset. + +\section{Addressing} +\label{sec:addressing} + +All addressing in \lxp{} is indirect. In order to access a memory location, its address must be stored in a register; any available register can be used for this purpose. + +\lxp{} uses a 32-bit address space. Each address refers to an individual byte. Some instructions, namely \instr{lsb} (\instrname{Load Signed Byte}), \instr{lub} (\instrname{Load Unsigned Byte}) and \instr{sb} (\instrname{Store Byte}) provide byte-granular access, in which case all 32 bits in the address are significant. Otherwise the least two address bits are ignored as \lxp{} doesn't support unaligned access to 32-bit data words (during simulation, a warning is emitted if such a transaction is attempted). + +A special rule applies to pointers that refer to instructions: since instructions are always word-aligned, the least significant bit is interpreted as the \code{IRF} (\emph{Interrupt Return Flag}). See Section \ref{sec:interrupthandling} for details. + +\section{Stack} +\label{sec:stack} + +The current pointer to the top of the stack is stored in the \code{sp} register. To the hardware this register is not different from general purpose registers, that is, in no situation does the CPU access the stack implicitly (procedure calls and interrupts use register-based conventions). + +Software can access the stack as follows: + +\begin{codepar} + \emph{// push r0 on the stack} + \instr{sub} sp, sp, 4 + \instr{sw} sp, r0 + \emph{// pop r0 from the stack} + \instr{lw} r0, sp + \instr{add} sp, sp, 4 +\end{codepar} + +Before using the stack, the \code{sp} register must be set up to point to a valid memory location. The simplest software can operate stackless, or even without data memory altogether if registers are enough to store the program state. + +\section{Calling procedures} +\label{sec:callingprocedures} + +\lxp{} provides a \instr{call} instruction which saves the address of the next instruction in the \code{rp} register and transfers execution to the address stored in the register operand. Return from a procedure is performed by the \code{\instr{jmp} rp} instruction which also has a \instr{ret} alias. + +If a procedure must in turn call a nested procedure itself, the return address in the \code{rp} register will be overwritten by the \instr{call} instruction. Hence, unless it is a tail call (see below), the procedure must save the \code{rp} value somewhere; the most general solution is to use the stack: + +\begin{codepar} + \instr{sub} sp, sp, 4 + \instr{sw} sp, rp + ... + \instr{lc} r0, Nested_proc + \instr{call} r0 + ... + \instr{lw} rp, sp + \instr{add} sp, sp, 4 + \instr{ret} +\end{codepar} + +Procedures that don't use the \instr{call} instruction (sometimes called \emph{leaf procedures}) don't need to save the \code{rp} value. + +Since \instr{ret} is just an alias for \code{\instr{jmp} rp}, one can also use \instrname{Compare and Jump} instructions (\instr{cjmp\emph{xxx}}) to perform a conditional procedure return. For example, consider the following procedure which calculates the absolute value of \code{r1}: + +\begin{codepar} +Abs_proc: + \instr{cjmpsge} rp, r1, 0 \emph{// return immediately if r1>=0} + \instr{neg} r1, r1 \emph{// otherwise, negate r1} + \instr{ret} \emph{// jmp rp} +\end{codepar} + +A \emph{tail call} is a special type of procedure call where the calling procedure calls a nested procedure as the last action before return. In such cases the \instr{call} instruction can be replaced with \instr{jmp}, so that when the nested procedure executes \instr{ret}, it returns directly to the caller's parent procedure. + +Although the \lxp{} architecture doesn't mandate any particular calling convention, some general recommendations are presented below: + +\begin{enumerate} + \item Pass arguments and return values through the \code{r1}--\code{r31} registers (a procedure can have multiple return values). + \item If necessary, the \code{r0} register can be used to load the procedure address. + \item Designate \code{r0}--\code{r31} registers as \emph{caller-saved}, that is, they are not guaranteed to be preserved during procedure calls and must be saved by the caller if needed. The procedure can use them for any purpose, regardless of whether they are used to pass arguments and/or return values. +\end{enumerate} + +\section{Interrupt handling} +\label{sec:interrupthandling} + +\subsection{Control register} + +\lxp{} supports 8 interrupts with hardwired priority levels (interrupts with lower vector numbers have higher priority). Interrupts vectors (pointers to interrupt handlers) are stored in the \code{iv0}--\code{iv7} registers. Interrupt handling is controlled by the \code{cr} register (Table \ref{tab:cr}). + +\begin{table}[htbp] + \caption{Control register} + \label{tab:cr} + \begin{tabularx}{\textwidth}{lL} + \toprule + Bit & Description \\ + \midrule + 0 & Enable interrupt 0 \\ + 1 & Enable interrupt 1 \\ + & \ldots \\ + 7 & Enable interrupt 7 \\ + 8 & Temporarily block interrupt 0 \\ + 9 & Temporarily block interrupt 1 \\ + & \ldots \\ + 15 & Temporarily block interrupt 7 \\ + 31--16 & \emph{Reserved} \\ + \bottomrule + \end{tabularx} +\end{table} + +Disabled interrupts are ignored altogether: if the CPU receives an interrupt request signal while the corresponding interrupt is disabled, the interrupt handler will not be called even if the interrupt is enabled later. Conversely, temporarily blocked interrupts are still registered, but their handlers are not called until they are unblocked. + +Like other registers, \code{cr} is zero-initialized during the CPU reset, meaning that no interrupts are initially enabled. + +\subsection{Invoking interrupt handlers} + +Interrupt handlers are invoked by the CPU similarly to procedures (Section \ref{sec:callingprocedures}), the difference being that in this case return address is stored in the \code{irp} register (as opposed to \code{rp}), and the least significant bit of the register (\code{IRF} -- \emph{Interrupt Return Flag}) is set. + +An interrupt handler returns using the \code{\instr{jmp} irp} instruction which also has an \instr{iret} alias. Until the interrupt handler returns, the CPU will defer further interrupt processing (although incoming interrupt requests will still be registered). This also means that the \code{irp} register value will not be unexpectedly overwritten. When executing the \code{\instr{jmp} irp} instruction, the CPU will recognize the \code{IRF} flag and resume interrupt processing as usual. It is also possible to perform a conditional return from the interrupt handler, similarly to the technique described in Section \ref{sec:callingprocedures} for conditional procedure returns. + +\subsection{Non-returnable interrupts} + +If an interrupt vector has the least significant bit (\code{IRF}) set, the CPU will resume interrupt processing immediately. One should not try to invoke \instr{iret} from such a handler since the \code{irp} register could have been overwritten by another interrupt. This technique can be useful when the CPU's only task is to process external events: + +\begin{codeparbreakable} +\emph{// Set the IRF to mark the interrupt as non-returnable} + \instr{lc} iv0, main\_loop@1 + \instr{mov} cr, 1 \emph{// enable the interrupt} + \instr{hlt} \emph{// wait for an interrupt request} +main\_loop: +\emph{// Process the event...} + \instr{hlt} \emph{// wait for the next interrupt request} +\end{codeparbreakable} + +Note that \instr{iret} is never called in this example. + +\chapter{Integration} +\label{ch:integration} + +\section{Overview} + +The \lxp{} IP core is delivered in a form of a synthesizable RTL description expressed in \mbox{VHDL-93}. It does not use any technology specific primitives and should work out of the box with major FPGA synthesis software. \lxp{} can be integrated in both VHDL and Verilog\textregistered{} based SoC designs. + +Major \lxp{} hardware versions have separate top-level design units: + +\begin{itemize} + \item \shellcmd{lxp32u\_top} -- \lxp{}U (without instruction cache), + \item \shellcmd{lxp32c\_top} -- \lxp{}C (with instruction cache). +\end{itemize} + +A high level block diagram of the CPU is presented on Figure \ref{fig:blockdiagram}. Schematic symbols for \lxp{}U and \lxp{}C are shown on Figure \ref{fig:symbols}. + +\begin{figure}[htbp] + \centering + \includegraphics[scale=0.85]{images/blockdiagram.pdf} + \caption{\lxp{} CPU block diagram} + \label{fig:blockdiagram} +\end{figure} + +\begin{figure}[htbp] + \centering + \includegraphics[scale=0.85]{images/symbols.pdf} + \caption{Schematic symbols for \lxp{}U and \lxp{}C} + \label{fig:symbols} +\end{figure} + +\lxp{}U uses the Low Latency Interface (LLI) described in Section \ref{sec:lli} to fetch instructions. This interface is designed to interact with low latency on-chip peripherals such as RAM blocks. It works best with slaves that can return the instruction on the next cycle after its address has been set, although the slave can still introduce wait states if needed. Low Latency Interface can be also connected to a custom (external) instruction cache. + +To achieve the least possible latency, some LLI outputs are not registered. For this reason the LLI is not suitable for interaction with off-chip peripherals. + +\lxp{}C is designed to work with high latency memory controllers and uses a simple instruction cache based on a ring buffer. The instructions are fetched over the WISHBONE instruction bus. To maximize throughput, the CPU makes use of the WISHBONE registered feedback signals [CTI\_O()] and [BTE\_O()]. All outputs on this bus are registered. This version is also recommended for use in situations where LLI combinatorial delays are unacceptable. + +Both \lxp{}U and \lxp{}C use the WISHBONE protocol for the data bus. + +\section{Ports} + +\begin{ctabular}{lccl} + \toprule + Port & Direction & Bus width & Description \\ + \midrule + \tabcutin{4}{Global signals} \\ + \midrule + \signal{clk\_i} & in & 1 & System clock \\ + \signal{rst\_i} & in & 1 & Synchronous reset, active high \\ + \midrule + \tabcutin{4}{Instruction bus -- Low Latency Interface (\lxp{}U only)} \\ + \midrule + \signal{lli\_re\_o} & out & 1 & Read enable output, active high \\ + \signal{lli\_adr\_o} & out & 30 & Address output \\ + \signal{lli\_dat\_i} & in & 32 & Data input \\ + \signal{lli\_busy\_i} & in & 1 & Busy flag input, active high \\ + \midrule + \tabcutin{4}{Instruction bus -- WISHBONE (\lxp{}C only)} \\ + \midrule + \signal{ibus\_cyc\_o} & out & 1 & Cycle output \\ + \signal{ibus\_stb\_o} & out & 1 & Strobe output \\ + \signal{ibus\_cti\_o} & out & 3 & Cycle type identifier \\ + \signal{ibus\_bte\_o} & out & 2 & Burst type extension \\ + \signal{ibus\_ack\_i} & in & 1 & Acknowledge input \\ + \signal{ibus\_adr\_o} & out & 30 & Address output \\ + \signal{ibus\_dat\_i} & in & 32 & Data input \\ + \midrule + \tabcutin{4}{Data bus} \\ + \midrule + \signal{dbus\_cyc\_o} & out & 1 & Cycle output \\ + \signal{dbus\_stb\_o} & out & 1 & Strobe output \\ + \signal{dbus\_we\_o} & out & 1 & Write enable output \\ + \signal{dbus\_sel\_o} & out & 4 & Select output \\ + \signal{dbus\_ack\_i} & in & 1 & Acknowledge input \\ + \signal{dbus\_adr\_o} & out & 30 & Address output \\ + \signal{dbus\_dat\_o} & out & 32 & Data output \\ + \signal{dbus\_dat\_i} & in & 32 & Data input \\ + \midrule + \tabcutin{4}{Other ports} \\ + \midrule + \signal{irq\_i} & in & 8 & Interrupt requests \\ + \bottomrule +\end{ctabular} + +\section{Generics} +\label{sec:generics} + +The following generics can be used to configure the \lxp{} IP core parameters. + +\subsection{DBUS\_RMW} + +By default, \lxp{} uses the \signal{dbus\_sel\_o} (byte enable) port to perform byte-granular write transactions initiated by the \instr{sb} (\instrname{Store Byte}) instruction. If this option is set to \code{true}, \signal{dbus\_sel\_o} is always tied to \code{"1111"}, and byte-granular write access is performed using the RMW (read-modify-write) cycle. The latter method is slower, but can work with slaves that do not have the [SEL\_I()] port. + +This feature is designed with the assumption that read and write transactions do not cause side effects, thus it can be unsuitable for some slaves. + +\subsection{DIVIDER\_EN} + +\lxp{} includes a divider unit which has quite a low performance but occupies a considerable amount of resources. It can be disabled by setting this option to \code{false}. + +\subsection{IBUS\_BURST\_SIZE} + +Instruction bus burst size. Default value is 16. Only for \lxp{}C. + +\subsection{IBUS\_PREFETCH\_SIZE} + +Number of words that the instruction cache will read ahead from the current instruction pointer. Default value is 32. Only for \lxp{}C. + +\subsection{MUL\_ARCH} + +\lxp{} provides three multiplier options: + +\begin{itemize} + \item \code{"dsp"} is the fastest architecture designed for technologies that provide fast parallel $16 \times 16$ multipliers, which includes most modern FPGA families. One multiplication takes 2 clock cycles. + \item \code{"opt"} architecture uses a semi-parallel multiplication algorithm based on carry-save accumulation of partial products. It is designed for technologies that do not provide fast $16 \times 16$ multipliers. One multiplication takes 6 clock cycles. + \item \code{"seq"} is a fully sequential design. One multiplication takes 34 clock cycles. +\end{itemize} + +The default multiplier architecture is \code{"dsp"}. This option is recommended for most modern FPGA devices regardless of optimization goal since it is not only the fastest, but also occupies the least amount of general-purpose logic resources. However, it will create a timing bottleneck on technologies that lack fast multipliers. + +For older FPGA families that don't provide dedicated multipliers the \code{"opt"} architecture can be used if decent throughput is still needed. It is designed to avoid creating a timing bottleneck on such technologies. Alternatively, \code{"seq"} architecture can be used when throughput is not a concern. + +\subsection{START\_ADDR} + +Address of the first instruction to be executed after CPU reset. Default value is \code{0}. The two least significant bits are ignored as instructions are always word-aligned. + +\section{Clock and reset} +\label{sec:clockreset} + +All flip-flops in the CPU are triggered by a rising edge of the \signal{clk\_i} signal. No specific requirements are imposed on the \signal{clk\_i} signal apart from usual constraints on setup and hold times. + +\lxp{} is reset synchronously when the \signal{rst\_i} signal is asserted. If the system reset signal comes from an asynchronous source, a synchronization circuit must be used; an example of such a circuit is shown on Figure \ref{fig:resetsync}. + +\begin{figure}[htbp] + \centering + \includegraphics[scale=1]{images/resetsync.pdf} + \caption{Reset synchronization circuit} + \label{fig:resetsync} +\end{figure} + +In SRAM-based FPGAs flip-flops and RAM blocks have deterministic state after a bitstream is loaded. On such technologies \lxp{} can operate without reset. In this case the \signal{rst\_i} port can be tied to a logical \code{0} in the RTL design to allow the synthesizer to remove redundant logic. + +\signal{clk\_i} and \signal{rst\_i} signals also serve the role of [CLK\_I] and [RST\_I] WISHBONE signals, respectively, for both instruction and data buses. + +\section{Low Latency Interface} +\label{sec:lli} + +Low Latency Interface (LLI) is a simple pipelined synchronous protocol with a typical latency of 1 cycle used by \lxp{}U to fetch instructions. It was designed to allow simple connection of the CPU to on-chip program RAM or cache. The timing diagram of the LLI is shown on Figure \ref{fig:llitiming}. + +\begin{figure}[htbp] + \centering + \includegraphics[scale=1]{images/llitiming.pdf} + \caption{Low Latency Interface timing diagram (\lxp{}U)} + \label{fig:llitiming} +\end{figure} + +To request a word, the master produces its address on \signal{lli\_adr\_o} and asserts \signal{lli\_re\_o}. The request is considered valid when \signal{lli\_re\_o} is high and \signal{lli\_busy\_i} is low on the same clock cycle. On the next cycle after a valid request, the slave must either produce data on \signal{lli\_dat\_i} or assert \signal{lli\_busy\_i} to indicate that data are not ready. \signal{lli\_busy\_i} must be held high until the valid data are present on the \signal{lli\_dat\_i} port. + +The data provided by the slave are only required to be valid on the next cycle after a valid request (if \signal{lli\_busy\_i} is not asserted) or on the cycle when \signal{lli\_busy\_i} is deasserted after being held high. Otherwise \signal{lli\_dat\_i} is undefined. + +The values of \signal{lli\_re\_o} and \signal{lli\_adr\_o} are not guaranteed to be preserved by the master while the slave is busy. + +The simplest slaves such as on-chip RAM blocks which are never busy can be trivially connected to the LLI by connecting address, data and read enable ports and tying the \signal{lli\_busy\_i} signal to a logical \code{0} (you can even ignore \signal{lli\_re\_o} in this case, although doing so can theoretically increase power consumption). + +Since the \signal{lli\_re\_o} output signal is not registered, this interface is not suitable for interaction with off-chip peripherals. Also, care should be taken to avoid introducing too much additional combinatorial delay on its outputs. + +The instruction bus, whether LLI or WISHBONE, doesn't support access to individual bytes and uses a 30-bit address port to address 32-bit words (instructions are always word-aligned). The lower two bits of the 32-bit address are ignored for the purpose of addressing. Consider the following example: + +\begin{codeparbreakable} + \instr{lc} r0, 0x10000000 + \instr{jmp} r0 +\emph{// 0x04000000 will appear on lli_adr_o or ibus_adr_o} +\end{codeparbreakable} + +\section{WISHBONE instruction bus} + +The \lxp{}C CPU fetches instructions over the WISHBONE bus. Its parameters are defined in the WISHBONE datasheet (Appendix \ref{app:wishbonedatasheet}). For a detailed description of the bus protocol refer to the WISHBONE specification, revision B3. + +With classic WISHBONE handshake decent throughput can be only achieved when the slave is able to terminate cycles asynchronously. It is usually possible only for the simplest slaves which should probably be using the Low Latency Interface instead. To maximize throughput for complex, high latency slaves, \lxp{}C instruction bus uses optional WISHBONE address tags [CTI\_O()] (Cycle Type Identifier) and [BTE\_O()] (Burst Type Extension). These signals are hints allowing the slave to predict the address that will be set by the master in the next cycle and prepare data in advance. The slave can ignore these hints, processing requests as classic WISHBONE cycles, although performance would almost certainly suffer in this case. + +A typical \lxp{}C instruction bus burst timing diagram is shown on Figure \ref{fig:ibustiming}. + +\begin{figure}[htbp] + \centering + \includegraphics[scale=0.786]{images/ibustiming.pdf} + \caption{Typical WISHBONE instruction bus burst (\lxp{}C)} + \label{fig:ibustiming} +\end{figure} + +\section{WISHBONE data bus} + +\lxp{} uses the WISHBONE bus to interact with data memory and other peripherals. This bus is distinct from the instruction bus; its parameters are defined in the WISHBONE datasheet (Appendix \ref{app:wishbonedatasheet}). + +The data bus uses a 30-bit \signal{dbus\_adr\_o} port to address 32-bit words; the \signal{dbus\_sel\_o} port is used to select individual bytes to be written or read. The upper 30 bits of the address appear on the \signal{dbus\_adr\_o} port, while the lower two bits are decoded to create a 4-bit \signal{dbus\_sel\_o} signal. Consider: + +\begin{codeparbreakable} + \instr{lc} r0, 0x20000002 + \instr{sb} r0, 0x55 +\emph{// write 0x55 to the address in r0} +\emph{// 0x08000000 will appear on dbus_adr_o} +\emph{// 0x4 will appear on dbus_sel_o} +\end{codeparbreakable} + +The byte-granular access feature is optional. If it is not needed, the \signal{dbus\_sel\_o} port can be left unconnected. It is also possible to set the \code{DBUS\_RMW} generic to \code{true} to enable byte-granular access emulation using the read-modify-write (RMW) cycle, which works even if the interconnect or slave doesn't provide the [SEL\_I()] port (Section \ref{sec:generics}). + +For a detailed description of the bus protocol refer to the WISHBONE specification, revision B3. + +Typical timing diagrams for write and read cycles are shown on Figure \ref{fig:dbustiming}. In these examples the peripheral terminates the cycle asynchronously; however, it can also introduce wait states by delaying the \signal{dbus\_ack\_i} signal. + +\begin{figure}[htbp] + \centering + \includegraphics[scale=0.928]{images/dbustiming.pdf} + \caption{Typical WISHBONE data bus WRITE and READ cycles} + \label{fig:dbustiming} +\end{figure} + +\section{Interrupts} + +\lxp{} registers an interrupt condition when the corresponding request signal goes from \code{0} to \code{1}. Transitions from \code{1} to \code{0} are ignored. All interrupt request signals must be synchronous with the system clock (\signal{clk\_i}); if coming from an asynchronous source, they must be synchronized using a sequence of at least two flip-flops clocked by \signal{clk\_i}. These flip-flops are not included in the \lxp{} core in order not to increase interrupt processing delay for interrupt sources that are inherently synchronous. Failure to properly synchronize interrupt request signals will cause timing violations that will manifest itself as intermittent, hard to debug faults. + +\section{Synthesis and optimization} +\label{sec:synthesis} + +\subsection{Technology specific primitives} + +\lxp{} RTL design is described in behavioral VHDL. However, it can also benefit from certain special resources provided by most FPGA devices, namely, RAM blocks and dedicated multipliers. For improved portability, hardware description that can potentially be mapped to such resources is localized in separate design units: + +\begin{itemize} + \item \shellcmd{lxp32\_ram256x32} -- a dual-port synchronous $256 \times 32$ bit RAM with one write port and one read port; + \item \shellcmd{lxp32\_mul16x16} -- an unsigned $16 \times 16$ multiplier with an output register. +\end{itemize} + +These design units contain behavioral description of respective hardware that is recognizable by FPGA synthesis tools. Usually no adjustments are needed as the synthesizer will automatically infer an appropriate primitive from its behavioral description. If automatic inference produces unsatisfactory results, these design units can be replaced with library element wrappers. The same is true for ASIC logic synthesis software which is unlikely to infer complex primitives. + +\lxp{} implements its own bypass logic dealing with situations when RAM read and write addresses collide. It does not depend on the read/write conflict resolution behavior of the underlying primitive. + +\subsection{General optimization guidelines} + +This subsection contains general advice on achieving satisfactory synthesis results regardless of the optimization goal. Some of these suggestions are also mentioned in other parts of this manual. + +\begin{enumerate} + \item If the technology doesn't provide dedicated multiplier resources, consider using \code{"opt"} or \code{"seq"} multiplier architecture (Section \ref{sec:generics}). + + \item Ensure that the instruction bus has adequate throughput. For \lxp{}C, check that the slave supports the WISHBONE registered feedback signals [CTI\_I()] and [BTE\_I()]. + + \item Multiplexing instruction and data buses, or connecting them to the same interconnect that allows only one master at a time to be active (i.e. \emph{shared bus} interconnect topology) is not recommended. If you absolutely must do so, assign a higher priority level to the data bus, otherwise instruction prefetches will massively slow down data transactions. + + \item For small programs, consider mapping code and data memory to the beginning or end of the address space (i.e. \code{0x00000000}--\code{0x000FFFFF} or \code{0xFFF00000}--\code{0xFFFFFFFF}) to be able to load pointers with the \instr{lcs} instruction which saves both memory and CPU cycles as compared to \instr{lc}. +\end{enumerate} + +\subsection{Optimizing for timing} + +\begin{enumerate} + \item Set up reasonable timing constraints. Do not overconstrain the design by more than 10--15~\%. + + \item Analyze the worst path. The natural \lxp{} timing bottleneck usually goes from the scratchpad (register file) output through the ALU (in the Execute stage) to the scratchpad input. If timing analysis lists other critical paths, the problem can lie elsewhere. If the \signal{rst\_i} signal becomes a bottleneck, promote it to a global network or, with SRAM-based FPGAs, consider operating without reset (see Section \ref{sec:clockreset}). Critical paths affecting the WISHBONE state machines could indicate problems with interconnect performance. + + \item Configure the synthesis tool to reduce the fanout limit. Note that setting this limit to a too small value can lead to an opposite effect. + + \item Synthesis tools can support additional options to improve timing, such as the \emph{Retiming} algorithm which rearranges registers and combinatorial logic across the pipeline in attempt to balance delays. The efficiency of such algorithms is not very predictable. In general, sloppy designs are the most likely to benefit from it, while for a carefully designed circuit timing can sometimes get worse. +\end{enumerate} + +\subsection{Optimizing for area} + +\begin{enumerate} + \item Consider disabling the divider if not using it (see Section \ref{sec:generics}). + + \item Relaxing timing constraints can sometimes allow the synthesizer to produce a more area-efficient circuit. + + \item Increase the fanout limit in the synthesizer settings to reduce buffer replication. +\end{enumerate} + +\chapter{Hardware architecture} +\label{ch:pipeline} + +The \lxp{} CPU is based on a 3-stage hazard-free pipelined architecture and uses a large RAM-based register file (scratchpad) with two read ports and one write port. The pipeline includes the following stages: + +\begin{itemize} + \item\emph{Fetch} -- fetches instructions from the program memory. + \item\emph{Decode} -- decodes instructions and reads register operand values from the scratchpad. + \item\emph{Execute} -- executes instructions and writes the results (if any) to the scratchpad. +\end{itemize} + +\lxp{} instructions are encoded in such a way that operand register numbers can be known without decoding the instruction (Section \ref{sec:instructionformat}). When the \emph{Fetch} stage produces an instruction, scratchpad input addresses are set immediately, before the instruction itself is decoded. If the instruction does not use one or both of the register operands, the corresponding data read from the scratchpad are discarded. Collision bypass logic in the scratchpad detects situations where the \emph{Decode} stage tries to read a register which is currently being written by the \emph{Execute} stage and forwards its value, bypassing the RAM block and avoiding Read After Write (RAW) pipeline hazards. Other types of data hazards are also impossible with this architecture. + +As an example, consider the following simple code chunk: + +\begin{codepar} + \instr{mov} r0, 10 \emph{// alias for add r0, 10, 0} + \instr{mov} r1, 20 \emph{// alias for add r1, 20, 0} + \instr{add} r2, r0, r1 +\end{codepar} + +Table \ref{tab:examplepipeline} illustrates how this chunk is processed by the \lxp{} pipeline. Note that on the fourth cycle the \emph{Decode} stage requests the \code{r1} register value while the \emph{Execute} stage writes to the same register. Collision bypass logic in the scratchpad ensures that the \emph{Decode} stage reads the correct (new) value of \code{r1} without stalling the pipeline. + +\begin{table}[htbp] + \caption{Example of the \lxp{} pipeline operation} + \small + \label{tab:examplepipeline} + \begin{tabularx}{\textwidth}{lllL} + \toprule + Cycle & Fetch & Decode & Execute \\ + \midrule + 1 & \code{\instr{add} r0, 10, 0} & & \\ + \midrule + 2 & \code{\instr{add} r1, 20, 0} & \code{\instr{add} r0, 10, 0} & \\ + & & Request \code{r10} (discarded) & \\ + & & Request \code{r0} (discarded) & \\ + & & Pass 10 and 0 as operands & \\ + \midrule + 3 & \code{\instr{add} r2, r0, r1} & \code{\instr{add} r1, 20, 0} & Perform the addition \\ + & & Request \code{r20} (discarded) & Write 10 to \code{r0} \\ + & & Request \code{r0} (discarded) & \\ + & & Pass 20 and 0 as operands & \\ + \midrule + 4 & & \code{\instr{add} r2, r0, r1} & Perform the addition \\ + & & Request \code{r0} & Write 20 to \code{r1} \\ + & & Request \code{r1} (bypass) & \\ + & & Pass 10 and 20 as operands & \\ + \midrule + 5 & & & Perform the addition \\ + & & & Write 30 to \code{r2} \\ + \bottomrule + \end{tabularx} +\end{table} + +When an instruction takes more than one cycle to execute, the \emph{Execute} stage simply stalls the pipeline. + +Branch hazards are impossible in \lxp{} as well since the pipeline is flushed whenever an execution transfer occurs. + +\chapter{Simulation} +\label{ch:simulation} + +\lxp{} package includes an automated verification environment (self-checking testbench) which verifies the \lxp{} CPU functional correctness. The environment consists of two major parts: a test platform which is a SoC-like design providing peripherals for the CPU to interact with, and the testbench itself which loads test firmware and monitors the platform's output signals. Like the CPU itself, the test environment is written in VHDL-93. + +A separate testbench for the instruction cache (\shellcmd{lxp32\_icache}) is also provided. It can be invoked similarly to the main CPU testbench. + +\section{Requirements} + +The following software is required to simulate the \lxp{} design: + +\begin{itemize} + \item An HDL simulator supporting VHDL-93. \lxp{} package includes scripts (makefiles) for the following simulators: + + \begin{itemize} + \item GHDL -- a free and open-source VHDL simulator which supports multiple operating systems\footnote{\url{http://ghdl.free.fr/}}; + \item Mentor Graphics\textregistered{} ModelSim\textregistered{} simulator (\shellcmd{vsim}); + \item Xilinx\textregistered{} Vivado\textregistered{} Simulator (\shellcmd{xsim}). + \end{itemize} + + With GHDL, a waveform viewer such as GTKWave is also recommended (Figure \ref{fig:gtkwave})\footnote{\url{http://gtkwave.sourceforge.net/}}. + + Some FPGA vendors provide limited versions of the ModelSim\textregistered{} simulator for free as parts of their design suites. These versions should suffice for \lxp{} simulation. + + Other simulators can be used with some preparations (Section \ref{sec:simmanual}). + + \item GNU \shellcmd{make} and \shellcmd{coreutils} are needed to simulate the design using the provided makefiles. Under Microsoft\textregistered{} Windows\textregistered{}, MSYS or Cygwin can be used. + \item \lxp{} assembler/linker program (\shellcmd{lxp32asm}) must be present (Section \ref{sec:lxp32asm}). A prebuilt executable for Microsoft\textregistered{} Windows\textregistered{} is already included in the \lxp{} package, for other operating systems \shellcmd{lxp32asm} must be built from source (Section \ref{sec:buildfromsource}). +\end{itemize} + +\begin{figure}[htbp] + \centering + \includegraphics[scale=0.65]{images/gtkwave.png} + \caption{GTKWave displaying the \lxp{} waveform dump produced by GHDL} + \label{fig:gtkwave} +\end{figure} + +\section{Running simulation using makefiles} + +To simulate the design, go to the \shellcmd{verify/lxp32/run/<\emph{simulator}>} directory and run \shellcmd{make}. The following make targets are supported: + +\begin{itemize} + \item \shellcmd{batch} -- simulate the design in batch mode. Results will be written to the standard output. This is the default target. + \item \shellcmd{gui} -- simulate the design in GUI mode. Note: since GHDL doesn't have a GUI, the simulation itself will be run in batch mode; upon a completion, GTKWave will be run automatically to display the dumped waveforms. + \item \shellcmd{compile} -- compile only, don't run simulation. + \item \shellcmd{clean} -- delete all the produced artifacts. +\end{itemize} + +\section{Running simulation manually} +\label{sec:simmanual} + +\lxp{} testbench can be also run manually. The following steps must be performed: + +\begin{enumerate} + \item Compile the test firmware in the \shellcmd{verify/lxp32/src/firmware} directory: + + \begin{codepar} + lxp32asm -f textio \emph{filename}.asm -o \emph{filename}.ram + \end{codepar} + + Produced \shellcmd{*.ram} files must be placed to the simulator's working directory. + \item Compile the \lxp{} RTL description (\shellcmd{rtl} directory). + \item Compile the common package (\shellcmd{verify/common\_pkg}). + \item Compile the test platform (\shellcmd{verify/lxp32/src/platform} directory). + \item Compile the testbench itself (\shellcmd{verify/lxp32/src/tb} directory). + \item Simulate the \shellcmd{tb} design unit defined in the \shellcmd{tb.vhd} file. +\end{enumerate} + +\section{Testbench parameters} + +Simulation parameters can be configured by overriding generics defined by the \shellcmd{tb} design unit: + +\begin{itemize} + \item \code{CPU\_DBUS\_RMW} -- \code{DBUS\_RMW} CPU generic value (see Section \ref{sec:generics}). + \item \code{CPU\_MUL\_ARCH} -- \code{MUL\_ARCH} CPU generic value (see Section \ref{sec:generics}). + \item \code{MODEL\_LXP32C} -- simulate the \lxp{}C version. By default, this option is set to \code{true}. If set to \code{false}, \lxp{}U is simulated instead. + \item \code{TEST\_CASE} -- if set to a non-empty string, specifies the file name of a test case to run. If set to an empty string (default), all tests are executed. + \item \code{THROTTLE\_DBUS} -- perform pseudo-random data bus throttling. By default, this option is set to \code{true}. + \item \code{THROTTLE\_IBUS} -- perform pseudo-random instruction bus throttling. By default, this option is set to \code{true}. + \item \code{VERBOSE} -- print more messages. +\end{itemize} + +\chapter{Development tools} +\label{ch:developmenttools} + +\section{\shellcmd{lxp32asm} -- Assembler and linker} +\label{sec:lxp32asm} + +\shellcmd{lxp32asm} is a combined assembler and linker for the \lxp{} platform. It takes one or more input files and produces executable code for the CPU. Input files can be either source files in the \lxp{} assembly language (Appendix \ref{app:assemblylanguage}) or \emph{linkable objects}. Linkable object is a relocatable format for storing compiled \lxp{} code together with symbol information. + +\shellcmd{lxp32asm} operates in two stages: + +\begin{enumerate} + \item Compile. + + Source files are compiled to linkable objects. + + \item Link. + + Linkable objects are combined into a single executable module. References to symbols defined in external modules are resolved at this stage. +\end{enumerate} + +In the simplest case there is only one input source file which doesn't contain external symbol references. If there are multiple input files, one of them must define the \code{entry} (or \code{Entry}) symbol at the beginning of the code. + +\subsection{Command line syntax} +\label{subsec:assemblercmdline} + +\begin{codepar} + lxp32asm [ \emph{options} | \emph{input files} ] +\end{codepar} + +\subsubsection{General options} + +\begin{itemize} + \item \shellcmd{-c} -- compile only (skip the Link stage). + + \item \shellcmd{-h}, \shellcmd{--help} -- display a short help message and exit. + + \item \shellcmd{-o \emph{file}} -- output file name. + + \item \shellcmd{--} -- do not interpret the subsequent command line arguments as options. Can be used if there are input file names starting with a dash. +\end{itemize} + +\subsubsection{Compiler options} + +\begin{itemize} + \item \shellcmd{-i \emph{dir}} -- add \emph{dir} to the list of directories used to search for included files. Multiple directories can be specified with multiple \shellcmd{-i} arguments. +\end{itemize} + +\subsubsection{Linker options (ignored in compile-only mode)} + +\begin{itemize} + \item \shellcmd{-a \emph{align}} -- object alignment. Must be a power of 2 and can't be less than 4. Default value is 4. + + \item \shellcmd{-b \emph{addr}} -- base address, that is, the address in memory where the executable image will be located. Must be a multiple of object alignment. Default value is 0. + + \item \shellcmd{-f \emph{fmt}} -- executable image format. See below for the list of supported formats. + + \item \shellcmd{-m \emph{file}} -- generate a map file. A map file is a human-readable list of all object and symbol addresses in the executable image. + + \item \shellcmd{-s \emph{size}} -- size of the executable image. Must be a multiple of 4. If total code size is less than the specified value, the executable image is padded with zeros. By default, the image is not padded. +\end{itemize} + +\subsection{Output formats} + +Output formats that can be specified with the \shellcmd{-f} command line option are listed below. + +\begin{itemize} + \item \shellcmd{bin} -- raw binary image (little-endian). This is the default format. + \item \shellcmd{textio} -- text format representing binary data as a sequence of zeros and ones. This format can be directly read from VHDL (using the \code{std.textio} package) or Verilog\textregistered{} (using the \code{\$readmemb} function). + \item \shellcmd{dec} -- text format representing each word as a decimal number. + \item \shellcmd{hex} -- text format representing each word as a hexadecimal number. +\end{itemize} + +\section{\shellcmd{lxp32dump} -- Disassembler} + +\shellcmd{lxp32dump} takes an executable image and produces a source file in \lxp{} assembly language. The produced file is a valid program that can be compiled by \shellcmd{lxp32asm}. + +\subsection{Command line syntax} + +\begin{codepar} + lxp32dump [ \emph{options} | \emph{input file} ] +\end{codepar} + +Supported options are: + +\begin{itemize} + \item \shellcmd{-b \emph{addr}} -- executable image base address, only used for comments. + + \item \shellcmd{-f \emph{fmt}} -- input file format. All \shellcmd{lxp32asm} output formats are supported. If this option is not supplied, autodetection is performed. + + \item \shellcmd{-h}, \shellcmd{--help} -- display a short help message and exit. + + \item \shellcmd{-na} -- do not use instruction aliases (such as \instr{mov}, \instr{ret}, \instr{not}) and register aliases (such as \code{sp}, \code{rp}). + + \item \shellcmd{-o \emph{file}} -- output file name. By default, the standard output stream is used. + + \item \shellcmd{--} -- do not interpret subsequent command line arguments as options. +\end{itemize} + +\section{\shellcmd{wigen} -- Interconnect generator} + +\shellcmd{wigen} is a small tool that generates VHDL description of a simple WISHBONE interconnect based on shared bus topology. It supports any number of masters and slaves. The interconnect can then be used to create a SoC based on \lxp{}. + +For interconnects with multiple masters a priority-based arbitration circuit is inserted with lower-numbered masters taking precedence. However, when a bus cycle is in progress ([CYC\_O] is asserted by the active master), the arbiter will not interrupt it even if a master with a higher priority level requests bus ownership. + +\subsection{Command line syntax} + +\begin{codepar} + wigen [ \emph{option(s)} ] \emph{nm} \emph{ns} \emph{ma} \emph{sa} \emph{ps} [ \emph{pg} ] +\end{codepar} + +\begin{itemize} + \item\shellcmd{\emph{nm}} -- number of masters, + \item\shellcmd{\emph{ns}} -- number of slaves, + \item\shellcmd{\emph{ma}} -- master address width, + \item\shellcmd{\emph{sa}} -- slave address width, + \item\shellcmd{\emph{ps}} -- port size (8, 16, 32 or 64), + \item\shellcmd{\emph{pg}} -- port granularity (8, 16, 32 or 64, default: the same as port size). +\end{itemize} + +Supported options are: + +\begin{itemize} + \item \shellcmd{-e \emph{entity}} -- name of the design entity (default is \code{"intercon"}). + + \item \shellcmd{-h}, \shellcmd{--help} -- display a short help message and exit. + + \item \shellcmd{-o \emph{file}} -- output file name (default is \shellcmd{\emph{entity}.vhd}). + + \item \shellcmd{-p} -- generate pipelined arbiter (reduced combinatorial delays, increased latency). + + \item \shellcmd{-r} -- generate WISHBONE registered feedback signals ([CTI\_IO()] and [BTE\_IO()]). + + \item \shellcmd{-u} -- generate unsafe slave decoder (reduced combinatorial delays and resource usage, may not work properly if the address is invalid). +\end{itemize} + +\section{Building from source} +\label{sec:buildfromsource} + +Prebuilt tool executables for 32-bit Microsoft\textregistered{} Windows\textregistered{} are included in the \lxp{} IP core package. For other platforms the tools must be built from source. Since they are developed in \cplusplus{} using only the standard library, it should be possible to build them for any platform that provides a modern \cplusplus{} compiler. + +\subsection{Requirements} + +The following software is required to build \lxp{} tools from source: + +\begin{enumerate} + \item A modern \cplusplus{} compiler, such as Microsoft\textregistered{} Visual Studio\textregistered{} 2013 or newer, GCC 4.8 or newer, Clang 3.4 or newer. + \item CMake 3.3 or newer. +\end{enumerate} + +\subsection{Build procedure} + +This software uses CMake as a build system generator. Building it involves two steps: first, the \shellcmd{cmake} program is invoked to generate a native build environment (a set of Makefiles or an IDE project); second, the generated environment is used to build the software. More details can be found in the CMake documentation. + +\subsubsection{Examples} + +In the following examples, it is assumed that the commands are run from the \shellcmd{tools} subdirectory of the \lxp{} IP core package tree. + +For Microsoft\textregistered{} Visual Studio\textregistered{}: + +\begin{codepar} + mkdir build + cd build + cmake -G "NMake Makefiles" ../src + nmake + nmake install +\end{codepar} + +For MSYS: + +\begin{codepar} + mkdir build + cd build + cmake -G "MSYS Makefiles" ../src + make + make install +\end{codepar} + +For MinGW without MSYS: + +\begin{codepar} + mkdir build + cd build + cmake -G "MinGW Makefiles" ../src + mingw32-make + mingw32-make install +\end{codepar} + +For other platforms: + +\begin{codepar} + mkdir build + cd build + cmake ../src + make + make install +\end{codepar} + +\appendix + +\chapter{Instruction set reference} +\label{app:instructionset} + +See Section \ref{sec:instructionformat} for a general description of \lxp{} instruction encoding. + +\section{List of instructions by group} + +\begin{ctabular}{lll} + \toprule + Instruction & Description & Opcode \\ + \midrule + \tabcutin{3}{Data transfer} \\ + \midrule + \hyperref[subsec:instr:mov]{\instr{mov}} & Move & alias for \code{\instr{add} dst, src, 0} \\ + \hyperref[subsec:instr:lc]{\instr{lc}} & Load Constant & \code{000001} \\ + \hyperref[subsec:instr:lcs]{\instr{lcs}} & Load Constant Short & \code{101xxx} \\ + \hyperref[subsec:instr:lw]{\instr{lw}} & Load Word & \code{001000} \\ + \hyperref[subsec:instr:lub]{\instr{lub}} & Load Unsigned Byte & \code{001010} \\ + \hyperref[subsec:instr:lsb]{\instr{lsb}} & Load Signed Byte & \code{001011} \\ + \hyperref[subsec:instr:sw]{\instr{sw}} & Store Word & \code{001100} \\ + \hyperref[subsec:instr:sb]{\instr{sb}} & Store Byte & \code{001110} \\ + \midrule + \tabcutin{3}{Arithmetic operations} \\ + \midrule + \hyperref[subsec:instr:add]{\instr{add}} & Add & \code{010000} \\ + \hyperref[subsec:instr:sub]{\instr{sub}} & Subtract & \code{010001} \\ + \hyperref[subsec:instr:neg]{\instr{neg}} & Negate & alias for \code{\instr{sub} dst, 0, src} \\ + \hyperref[subsec:instr:mul]{\instr{mul}} & Multiply & \code{010010} \\ + \hyperref[subsec:instr:divu]{\instr{divu}} & Divide Unsigned & \code{010100} \\ + \hyperref[subsec:instr:divs]{\instr{divs}} & Divide Signed & \code{010101} \\ + \hyperref[subsec:instr:modu]{\instr{modu}} & Modulo Unsigned & \code{010110} \\ + \hyperref[subsec:instr:mods]{\instr{mods}} & Modulo Signed & \code{010111} \\ + \midrule + \tabcutin{3}{Bitwise operations} \\ + \midrule + \hyperref[subsec:instr:not]{\instr{not}} & Bitwise Not & alias for \code{\instr{xor} dst, src, -1} \\ + \hyperref[subsec:instr:and]{\instr{and}} & Bitwise And & \code{011000} \\ + \hyperref[subsec:instr:or]{\instr{or}} & Bitwise Or & \code{011001} \\ + \hyperref[subsec:instr:xor]{\instr{xor}} & Bitwise Exclusive Or & \code{011010}\\ + \hyperref[subsec:instr:sl]{\instr{sl}} & Shift Left & \code{011100} \\ + \hyperref[subsec:instr:sru]{\instr{sru}} & Shift Right Unsigned & \code{011110} \\ + \hyperref[subsec:instr:srs]{\instr{srs}} & Shift Right Signed & \code{011111} \\ + \midrule + \tabcutin{3}{Execution transfer} \\ + \midrule + \hyperref[subsec:instr:jmp]{\instr{jmp}} & Jump & \code{100000} \\ + \hyperref[subsec:instr:cjmpxxx]{\instr{cjmp\emph{xxx}}} & Compare and Jump & \code{11\emph{xxxx}} (\code{\emph{xxxx}} = condition) \\ + \hyperref[subsec:instr:call]{\instr{call}} & Call Procedure & \code{100001} \\ + \hyperref[subsec:instr:ret]{\instr{ret}} & Return from Procedure & alias for \code{\instr{jmp} rp} \\ + \hyperref[subsec:instr:iret]{\instr{iret}} & Interrupt Return & alias for \code{\instr{jmp} irp}\\ + \midrule + \tabcutin{3}{Miscellaneous instructions} \\ + \midrule + \hyperref[subsec:instr:nop]{\instr{nop}} & No Operation & \code{000000} \\ + \hyperref[subsec:instr:hlt]{\instr{hlt}} & Halt & \code{000010} \\ +\end{ctabular} + +\section{Alphabetical list of instructions} + +\settocdepth{subsection} + +{ +\setlength{\parindent}{0pt} +\nonzeroparskip + +\subsection{\instr{add} -- Add} +\label{subsec:instr:add} + +\subsubsection{Syntax} + +\code{\instr{add} DST, RD1, RD2} + +\subsubsection{Encoding} + +\code{010000 T1 T2 DST RD1 RD2} + +Example: \code{\instr{add} r2, r1, 10} $\rightarrow$ \code{0x4202010A} + +\subsubsection{Operation} + +\code{DST := RD1 + RD2} + +\subsection{\instr{and} -- Bitwise And} +\label{subsec:instr:and} + +\subsubsection{Syntax} + +\code{\instr{and} DST, RD1, RD2} + +\subsubsection{Encoding} + +\code{011000 T1 T2 DST RD1 RD2} + +Example: \code{\instr{and} r2, r1, 0x3F} $\rightarrow$ \code{0x6202013F} + +\subsubsection{Operation} + +\code{DST := RD1 $\land$ RD2} + +\subsection{\instr{call} -- Call Procedure} +\label{subsec:instr:call} + +Save a pointer to the next instruction in the \code{rp} register and transfer execution to the address pointed by the operand. + +\subsubsection{Syntax} + +\code{\instr{call} RD1} + +\subsubsection{Encoding} + +\code{100001 1 0 11111110 RD1 00000000} + +RD1 must be a register. + +Example: \code{\instr{call} r1} $\rightarrow$ \code{0x86FE0100} + +\subsubsection{Operation} + +\code{rp := \emph{return\_address}} + +\code{goto RD1} + +Pointer in RD1 is interpreted as described in Section \ref{sec:addressing}. + +\subsection{\instr{cjmp\emph{xxx}} -- Compare and Jump} +\label{subsec:instr:cjmpxxx} + +Compare two operands and transfer execution to the specified address if a condition is satisfied. + +\subsubsection{Syntax} + +\code{\instr{cjmpe} DST, RD1, RD2} (Equal) + +\code{\instr{cjmpne} DST, RD1, RD2} (Not Equal) + +\code{\instr{cjmpsg} DST, RD1, RD2} (Signed Greater) + +\code{\instr{cjmpsge} DST, RD1, RD2} (Signed Greater or Equal) + +\code{\instr{cjmpsl} DST, RD1, RD2} (Signed Less) + +\code{\instr{cjmpsle} DST, RD1, RD2} (Signed Less or Equal) + +\code{\instr{cjmpug} DST, RD1, RD2} (Unsigned Greater) + +\code{\instr{cjmpuge} DST, RD1, RD2} (Unsigned Greater or Equal) + +\code{\instr{cjmpul} DST, RD1, RD2} (Unsigned Less) + +\code{\instr{cjmpule} DST, RD1, RD2} (Unsigned Less or Equal) + +\subsubsection{Encoding} + +\code{OPCODE T1 T2 DST RD1 RD2} + +Opcodes: + +\begin{tabularx}{\textwidth}{lL} +\instr{cjmpe} & \code{111000} \\ +\instr{cjmpne} & \code{110100} \\ +\instr{cjmpsg} & \code{110001} \\ +\instr{cjmpsge} & \code{111001} \\ +\instr{cjmpug} & \code{110010} \\ +\instr{cjmpuge} & \code{111010} \\ +\end{tabularx} + +\instr{cjmpsl}, \instr{cjmpsle}, \instr{cjmpul}, \instr{cjmpule} instructions are aliases for \instr{cjmpsg}, \instr{cjmpsge}, \instr{cjmpug}, \instr{cjmpuge}, respectively, with RD1 and RD2 operands swapped. + +Example: \code{\instr{cjmpuge} r2, r1, 5} $\rightarrow$ \code{0xEA020105} + +\subsubsection{Operation} + +\code{if \emph{condition} then goto DST} + +Pointer in DST is interpreted as described in Section \ref{sec:addressing}. Unlike most instructions, \instr{cjmp\emph{xxx}} does not write to DST. + +\subsection{\instr{divs} -- Divide Signed} +\label{subsec:instr:divs} + +\subsubsection{Syntax} + +\code{\instr{divs} DST, RD1, RD2} + +\subsubsection{Encoding} + +\code{010101 T1 T2 DST RD1 RD2} + +Example: \code{\instr{divs} r2, r1, -3} $\rightarrow$ \code{0x560201FD} + +\subsubsection{Operation} + +\code{DST := (\emph{signed}) RD1 / (\emph{signed}) RD2} + +The result is rounded towards zero and is undefined if RD2 is zero. If the CPU was configured without a divider, this instruction returns \code{0}. + +\subsection{\instr{divu} -- Divide Unsigned} +\label{subsec:instr:divu} + +\subsubsection{Syntax} + +\code{\instr{divu} DST, RD1, RD2} + +\subsubsection{Encoding} + +\code{010100 T1 T2 DST RD1 RD2} + +Example: \code{\instr{divu} r2, r1, 73} $\rightarrow$ \code{0x52020107} + +\subsubsection{Operation} + +\code{DST := RD1 / RD2} + +The result is rounded towards zero and is undefined if RD2 is zero. If the CPU was configured without a divider, this instruction returns \code{0}. + +\subsection{\instr{hlt} -- Halt} +\label{subsec:instr:hlt} + +Wait for an interrupt. + +\subsubsection{Syntax} + +\code{\instr{hlt}} + +\subsubsection{Encoding} + +\code{000010 0 0 00000000 00000000 00000000} + +\subsubsection{Operation} + +Pause execution until an interrupt is received. + +\subsection{\instr{jmp} -- Jump} +\label{subsec:instr:jmp} + +Transfer execution to the address pointed by the operand. + +\subsubsection{Syntax} + +\code{\instr{jmp} RD1} + +\subsubsection{Encoding} + +\code{100000 1 0 00000000 RD1 00000000} + +RD1 must be a register. + +Example: \code{\instr{jmp} r1} $\rightarrow$ \code{0x82000100} + +\subsubsection{Operation} + +\code{goto RD1} + +Pointer in RD1 is interpreted as described in Section \ref{sec:addressing}. + +\subsection{\instr{iret} -- Interrupt Return} +\label{subsec:instr:iret} + +Return from an interrupt handler. + +\subsubsection{Syntax} + +\instr{iret} + +Alias for \code{\instr{jmp} irp}. + +\subsection{\instr{lc} -- Load Constant} +\label{subsec:instr:lc} + +Load a 32-bit word to the specified register. Note that values from the [-1048576; 1048575] range can be loaded more efficiently using the \instr{lcs} instruction. + +\subsubsection{Syntax} + +\code{\instr{lc} DST, WORD32} + +\subsubsection{Encoding} + +\code{000001 0 0 DST 00000000 00000000 WORD32} + +Unlike other instructions, \instr{lc} occupies two 32-bit words. + +Example: \code{\instr{lc} r1, 0x12345678} $\rightarrow$ \code{0x04010000 0x12345678} + +\subsubsection{Operation} + +\code{DST := WORD32} + +\subsection{\instr{lcs} -- Load Constant Short} +\label{subsec:instr:lcs} + +Load a signed value from the [-1048576; 1048575] range (a sign extended 21-bit value) to the specified register. Unlike the \instr{lc} instruction, this instruction is encoded as a single word. + +\subsubsection{Syntax} + +\code{\instr{lcs} DST, VAL} + +\subsubsection{Encoding} + +\code{101 VAL[20:16] DST VAL[15:0]} + +Example: \code{\instr{lcs} r1, -1000000} $\rightarrow$ \code{0xB001BDC0} + +\subsubsection{Operation} + +\code{DST := (\emph{signed}) VAL} + +\subsection{\instr{lsb} -- Load Signed Byte} +\label{subsec:instr:lsb} + +Load a byte from the specified address to the register, performing sign extension. + +\subsubsection{Syntax} + +\code{\instr{lsb} DST, RD1} + +\subsubsection{Encoding} + +\code{001011 1 0 DST RD1 00000000} + +RD1 must be a register. + +Example: \code{\instr{lsb} r2, r1} $\rightarrow$ \code{0x2E020100} + +\subsubsection{Operation} + +\code{DST := (\emph{signed}) (*(BYTE*)RD1)} + +Pointer in RD1 is interpreted as described in Section \ref{sec:addressing}. + +\subsection{\instr{lub} -- Load Unsigned Byte} +\label{subsec:instr:lub} + +Load a byte from the specified address to the register. Higher 24 bits are zeroed. + +\subsubsection{Syntax} + +\code{\instr{lub} DST, RD1} + +\subsubsection{Encoding} + +\code{001010 1 0 DST RD1 00000000} + +RD1 must be a register. + +Example: \code{\instr{lub} r2, r1} $\rightarrow$ \code{0x2A020100} + +\subsubsection{Operation} + +\code{DST := *(BYTE*)RD1} + +Pointer in RD1 is interpreted as described in Section \ref{sec:addressing}. + +\subsection{\instr{lw} -- Load Word} +\label{subsec:instr:lw} + +Load a word from the specified address to the register. + +\subsubsection{Syntax} + +\code{\instr{lw} DST, RD1} + +\subsubsection{Encoding} + +\code{001000 1 0 DST RD1 00000000} + +RD1 must be a register. + +Example: \code{\instr{lw} r2, r1} $\rightarrow$ \code{0x22020100} + +\subsubsection{Operation} + +\code{DST := *RD1} + +Pointer in RD1 is interpreted as described in Section \ref{sec:addressing}. + +\subsection{\instr{mods} -- Modulo Signed} +\label{subsec:instr:mods} + +\subsubsection{Syntax} + +\code{\instr{mods} DST, RD1, RD2} + +\subsubsection{Encoding} + +\code{010111 T1 T2 DST RD1 RD2} + +Example: \code{\instr{mods} r2, r1, 10} $\rightarrow$ \code{0x5E02010A} + +\subsubsection{Operation} + +\code{DST := (\emph{signed}) RD1 mod (\emph{signed}) RD2} + +Modulo operation satisfies the following condition: if $Q=A/B$ and $R=A \mod B$, then $A=B \cdot Q+R$. + +The result is undefined if RD2 is zero. If the CPU was configured without a divider, this instruction returns \code{0}. + +\subsection{\instr{modu} -- Modulo Unsigned} +\label{subsec:instr:modu} + +\subsubsection{Syntax} + +\code{\instr{modu} DST, RD1, RD2} + +\subsubsection{Encoding} + +\code{010110 T1 T2 DST RD1 RD2} + +Example: \code{\instr{modu} r2, r1, 10} $\rightarrow$ \code{0x5A02010A} + +\subsubsection{Operation} + +\code{DST := RD1 mod RD2} + +Modulo operation satisfies the following condition: if $Q=A/B$ and $R=A \mod B$, then $A=B \cdot Q+R$. + +The result is undefined if RD2 is zero. If the CPU was configured without a divider, this instruction returns \code{0}. + +\subsection{\instr{mov} -- Move} +\label{subsec:instr:mov} + +\subsubsection{Syntax} + +\code{\instr{mov} DST, RD1} + +Alias for \code{\instr{add} DST, RD1, 0} + +\subsection{\instr{mul} -- Multiply} +\label{subsec:instr:mul} + +Multiply two 32-bit values. The result is also 32-bit. + +\subsubsection{Syntax} + +\code{\instr{mul} DST, RD1, RD2} + +\subsubsection{Encoding} + +\code{010010 T1 T2 DST RD1 RD2} + +Example: \code{\instr{mul} r2, r1, 3} $\rightarrow$ \code{0x4A020103} + +\subsubsection{Operation} + +\code{DST := RD1 * RD2} + +Since the product width is the same as the operand width, the result of a multiplication does not depend on operand signedness. + +\subsection{\instr{neg} -- Negate} +\label{subsec:instr:neg} + +\subsubsection{Syntax} + +\code{\instr{neg} DST, RD2} + +Alias for \code{\instr{sub} DST, 0, RD2} + +\subsection{\instr{nop} -- No Operation} +\label{subsec:instr:nop} + +\subsubsection{Syntax} + +\instr{nop} + +\subsubsection{Encoding} + +\code{000000 0 0 00000000 00000000 00000000} + +\subsubsection{Operation} + +This instruction does not alter the machine state. + +\subsection{\instr{not} -- Bitwise Not} +\label{subsec:instr:not} + +\subsubsection{Syntax} + +\code{\instr{not} DST, RD1} + +Alias for \code{\instr{xor} DST, RD1, -1}. + +\subsection{\instr{or} -- Bitwise Or} +\label{subsec:instr:or} + +\subsubsection{Syntax} + +\code{\instr{or} DST, RD1, RD2} + +\subsubsection{Encoding} + +\code{011001 T1 T2 DST RD1 RD2} + +Example: \code{\instr{or} r2, r1, 0x3F} $\rightarrow$ \code{0x6602013F} + +\subsubsection{Operation} + +\code{DST := RD1 $\lor$ RD2} + +\subsection{\instr{ret} -- Return from Procedure} +\label{subsec:instr:ret} + +Return from a procedure. + +\subsubsection{Syntax} + +\instr{ret} + +Alias for \code{\instr{jmp} rp}. + +\subsection{\instr{sb} -- Store Byte} +\label{subsec:instr:sb} + +Store the lowest byte from the register to the specified address. + +\subsubsection{Syntax} + +\code{\instr{sb} RD1, RD2} + +\subsubsection{Encoding} + +\code{001110 1 T2 00000000 RD1 RD2} + +RD1 must be a register. + +Example: \code{\instr{sb} r2, r1} $\rightarrow$ \code{0x3B000201} + +\subsubsection{Operation} + +\code{*(BYTE*)RD1 := RD2 $\land$ 0x000000FF} + +Pointer in RD1 is interpreted as described in Section \ref{sec:addressing}. + +\subsection{\instr{sl} -- Shift Left} +\label{subsec:instr:sl} + +\subsubsection{Syntax} + +\code{\instr{sl} DST, RD1, RD2} + +\subsubsection{Encoding} + +\code{011100 T1 T2 DST RD1 RD2} + +Example: \code{\instr{sl} r2, r1, 5} $\rightarrow$ \code{0x72020105} + +\subsubsection{Operation} + +\code{DST := RD1 << RD2} + +The result is undefined if RD2 is outside the [0; 31] range. + +\subsection{\instr{srs} -- Shift Right Signed} +\label{subsec:instr:srs} + +\subsubsection{Syntax} + +\code{\instr{srs} DST, RD1, RD2} + +\subsubsection{Encoding} + +\code{011111 T1 T2 DST RD1 RD2} + +Example: \code{\instr{srs} r2, r1, 5} $\rightarrow$ \code{0x7E020105} + +\subsubsection{Operation} + +\code{DST := ((\emph{signed}) RD1) >> RD2} + +The result is undefined if RD2 is outside the [0; 31] range. + +\subsection{\instr{sru} -- Shift Right Unsigned} +\label{subsec:instr:sru} + +\subsubsection{Syntax} + +\code{\instr{sru} DST, RD1, RD2} + +\subsubsection{Encoding} + +\code{011110 T1 T2 DST RD1 RD2} + +Example: \code{\instr{sru} r2, r1, 5} $\rightarrow$ \code{0x7A020105} + +\subsubsection{Operation} + +\code{DST := RD1 >> RD2} + +The result is undefined if RD2 is outside the [0; 31] range. + +\subsection{\instr{sub} -- Subtract} +\label{subsec:instr:sub} + +\subsubsection{Syntax} + +\code{\instr{sub} DST, RD1, RD2} + +\subsubsection{Encoding} + +\code{010001 T1 T2 DST RD1 RD2} + +Example: \code{\instr{sub} r2, r1, 5} $\rightarrow$ \code{0x46020105} + +\subsubsection{Operation} + +\code{DST := RD1 - RD2} + +\subsection{\instr{sw} -- Store Word} +\label{subsec:instr:sw} + +Store the value of the register to the specified address. + +\subsubsection{Syntax} + +\code{\instr{sw} RD1, RD2} + +\subsubsection{Encoding} + +\code{001100 1 T2 00000000 RD1 RD2} + +RD1 must be a register. + +Example: \code{\instr{sw} r2, r1} $\rightarrow$ \code{0x33000201} + +\subsubsection{Operation} + +\code{*RD1 := RD2} + +Pointer in RD1 is interpreted as described in Section \ref{sec:addressing}. + +\subsection{\instr{xor} -- Bitwise Exclusive Or} +\label{subsec:instr:xor} + +\subsubsection{Syntax} + +\code{\instr{xor} DST, RD1, RD2} + +\subsubsection{Encoding} + +\code{011010 T1 T2 DST RD1 RD2} + +Example: \code{\instr{xor} r2, r1, 0x3F} $\rightarrow$ \code{0x6A02013F} + +\subsubsection{Operation} + +\code{DST := RD1 $\oplus$ RD2} + +} + +\settocdepth{section} + +\chapter{Instruction cycle counts} + +Cycle counts for \lxp{} instructions are listed in Table \ref{tab:cycles}, based on an assumption that no pipeline stalls are caused by the instruction bus latency or cache misses. These data are provided for reference purposes; the software should not depend on them as they can change in future hardware revisions. + +\begin{table}[htbp] + \centering + \caption{Instruction cycle counts} + \label{tab:cycles} + \begin{tabularx}{0.8\textwidth}{LLLL} + \toprule + Instruction & Cycles & Instruction & Cycles \\ + \midrule + \instr{add} & 1 & \instr{modu} & 37 \\ + \instr{and} & 1 & \instr{mov} & 1 \\ + \instr{call} & 4 & \instr{mul} & 2, 6 or 34\footnotemark[3] \\ + \instr{cjmp\emph{xxx}} & 5 or 2\footnotemark[1] & \instr{neg} & 1 \\ + \instr{divs} & 36 & \instr{nop} & 1 \\ + \instr{divu} & 36 & \instr{not} & 1 \\ + \instr{hlt} & N/A & \instr{or} & 1 \\ + \instr{jmp} & 4 & \instr{ret} & 4 \\ + \instr{iret} & 4 & \instr{sb} & $\ge$ 2\footnotemark[2] \\ + \instr{lc} & 2 & \instr{sl} & 2 \\ + \instr{lcs} & 1 & \instr{srs} & 2 \\ + \instr{lsb} & $\ge$ 3\footnotemark[2] & \instr{sru} & 2 \\ + \instr{lub} & $\ge$ 3\footnotemark[2] & \instr{sub} & 1 \\ + \instr{lw} & $\ge$ 3\footnotemark[2] & \instr{sw} & $\ge$ 2\footnotemark[2] \\ + \instr{mods} & 37 & \instr{xor} & 1 \\ + \bottomrule + \end{tabularx} +\end{table} + +\footnotetext[1]{Depends on whether the jump is taken or not.} +\footnotetext[2]{Depends on the data bus latency.} +\footnotetext[3]{Depends on the multiplier architecture. See Section \ref{sec:generics}.} + +\chapter{LXP32 assembly language} +\label{app:assemblylanguage} + +This appendix defines the assembly language used by \lxp{} development tools. + +\section{Comments} + +\lxp{} assembly language supports C style comments that can span across multiple lines and single-line \cplusplus{} style comments: + +\begin{codepar}\itshape + /* + * This is a comment. + */ + + // This is also a comment +\end{codepar} + +From a parser's point of view comments are equivalent to whitespace. + +\section{Literals} + +\lxp{} assembly language uses numeric and string literals similar to those provided by the C programming language. + +Numeric literals can take form of decimal, hexadecimal or octal numbers. Literals prefixed with \code{0x} are interpreted as hexadecimal, literals prefixed with \code{0} are interpreted as octal, other literals are interpreted as decimal. A numeric literal can also start with an unary plus or minus sign which is also considered a part of the literal. + +String literals must be enclosed in double quotes. The most common escape sequences used in C are supported (Table \ref{tab:stringescape}). Note that strings are not null-terminated in the LXP32 assembly language; when required, terminating null character must be inserted explicitly. + +\begin{table}[htbp] + \caption{Escape sequences used in string literals} + \label{tab:stringescape} + \begin{tabularx}{\textwidth}{lL} + \toprule + Sequence & Interpretation \\ + \midrule + \code{\textbackslash\textbackslash} & Backslash character \\ + \code{\textbackslash "} & Double quotation mark \\ + \code{\textbackslash '} & Single quotation mark (can be also used directly) \\ + \code{\textbackslash t} & Tabulation character \\ + \code{\textbackslash n} & Line feed \\ + \code{\textbackslash r} & Carriage return \\ + \code{\textbackslash x\emph{XX}} & Character with a hexadecimal code of \emph{XX} (1--2 digits) \\ + \code{\textbackslash \emph{XXX}} & Character with an octal code of \emph{XXX} (1--3 digits) \\ + \bottomrule + \end{tabularx} +\end{table} + +\section{Symbols} +\label{sec:symbols} + +Symbols (labels) are used to refer to data or code locations. \lxp{} assembly language does not have distinct code and data labels: symbols are used in both these contexts. + +Symbol names must be valid identifiers. A valid identifier must start with an alphabetic character or an underscore, and may contain alphanumeric characters and underscores. + +A symbol definition must be the first token in a source code line followed by a colon. A symbol definition can occupy a separate line (in which case it refers to the following statement). Alternatively, a statement can follow the symbol definition on the same line. + +Symbols can be used as operands to the \instr{lc} and \instr{lcs} instruction statements. A symbol reference can end with a \code{@\emph{n}} sequence, where \code{\emph{n}} is a numeric literal; in this case it is interpreted as an offset (in bytes) relative to the symbol definition. For the \instr{lcs} instruction, the resulting address must still fit into the sign extended 21-bit value range (\code{0x00000000}--\code{0x000FFFFF} or \code{0xFFF00000}--\code{0xFFFFFFFF}), otherwise the linker will report an error. + +By default all symbols are local, that is, they can be only referenced from the module where they were defined. To make a symbol accessible from other modules, use the \instr{\#export} directive. To reference a symbol defined in another module use the \instr{\#import} directive. + +A symbol named \code{entry} or \code{Entry} has a special meaning: it is used to inform the linker about the program entry point if there are multiple input files. It does not have to be exported. If defined, this symbol must precede the first instruction or data definition statement in the module. Only one module in the program can define the entry symbol. + +\begin{codeparbreakable} + \instr{lc} r10, jump\_label + \instr{lc} r11, data\_word +\emph{// ...} + \instr{sw} r11, r0 \emph{// store the value of r0 to the} + \emph{// location pointed by data\_word} + \instr{jmp} r10 \emph{// transfer execution to jump\_label} +\emph{// ...} +jump\_label: + \instr{mov} r1, r0 +\emph{// ...} +data\_word: + \instr{.word} 0x12345678 +\end{codeparbreakable} + +\section{Statements} + +Each statement occupies a single source code line. There are three kinds of statements: + +\begin{itemize} + \item \emph{Directives} provide directions for the assembler that do not directly cause code generation. + \item \emph{Data definition statements} insert arbitrary data to the generated code. + \item \emph{Instruction statements} insert \lxp{} CPU instructions to the generated code. +\end{itemize} + +\subsection{Directives} + +The first token of a directive statement always starts with the \code{\#} character. + +\begin{codepar} +\instr{\#define} \emph{identifier} [ \emph{token} ... ] +\end{codepar} + +Defines a macro that will be substituted with zero or more tokens. The \code{\emph{identifier}} must satisfy the requirements listed in Section \ref{sec:symbols}. Tokens can be anything, including keywords, identifiers, literals and separators (i.e. comma and colon characters). + +\begin{codepar} +\instr{\#error} [ \emph{msg} ] +\end{codepar} + +Raises a compiler error. If \emph{msg} is supplied, uses it as an error message. + +\begin{codepar} +\instr{\#export} \emph{identifier} +\end{codepar} + +Declares \code{\emph{identifier}} as an exported symbol. Exported symbols can be referenced by other modules. + +\begin{codepar} +\instr{\#ifdef} | \instr{\#ifndef} \emph{identifier} +\code{...} +\instr{\#else} +\code{...} +\instr{\#endif} +\end{codepar} + +Define C preprocessor-style conditional sections which are processed or not based on whether a certain macro has been defined. \instr{\#else} is optional. Can be nested. + +\begin{codepar} +\instr{\#import} \emph{identifier} +\end{codepar} + +Declares \code{\emph{identifier}} as an imported symbol. Used to refer to symbols exported by other modules. + +\begin{codepar} +\instr{\#include} \emph{filename} +\end{codepar} + +Processes \code{\emph{filename}} contents as it were literally inserted at the point of the \instr{\#include} directive. \code{\emph{filename}} must be a string literal. + +\begin{codepar} +\instr{\#message} \emph{msg} +\end{codepar} + +Prints \code{\emph{msg}} to the standard output stream. \code{\emph{msg}} must be a string literal. + +\subsection{Data definition statements} + +The first token of a data definition statement always starts with the \code{.} (period) character. + +\begin{codepar} +\instr{.align} [ \emph{alignment} ] +\end{codepar} + +Ensures that code generated by the next data definition or instruction statement is aligned to a multiple of \code{\emph{alignment}} bytes, inserting padding zeros if needed. \code{\emph{alignment}} must be a power of 2 and can't be less than 4. Default \code{\emph{alignment}} is 4. Instructions and words are always at least word-aligned; the \instr{.align} statement can be used to align them to a larger boundary, or to align byte data (see below). + +The \instr{.align} statement is not guaranteed to work if the requested alignment is greater than the section alignment specified for the linker (see Subsection \ref{subsec:assemblercmdline}). + +\begin{codepar} +\instr{.byte} \emph{token} [, \emph{token} ... ] +\end{codepar} + +Inserts one or more bytes to the output code. Each \code{\emph{token}} can be either a numeric literal with a valid range of [-128; 255] or a string literal. By default, bytes are not aligned. + +To define a null-terminated string, the terminating null character must be inserted explicitly. + +\begin{codepar} +\instr{.reserve} \emph{n} +\end{codepar} + +Inserts \code{\emph{n}} zero bytes to the output code. + +\begin{codepar} +\instr{.word} \emph{token} [, \emph{token} ... ] +\end{codepar} + +Inserts one or more 32-bit words to the output code. Tokens must be numeric literals. + +\subsection{Instruction statements} + +Instruction statements have the following general syntax: + +\begin{codepar} + \instr{\emph{instruction}} [ \emph{operand} [, \emph{operand} ... ] ] +\end{codepar} + +Depending on the instruction, operands can be registers, numeric literals or symbols. Supported instructions are listed in Appendix \ref{app:instructionset}. + +\chapter{WISHBONE datasheet} +\label{app:wishbonedatasheet} + +\section[Instruction bus (LXP32C only)]{Instruction bus (\lxp{}C only)} + +\begin{ctabular}{ll} + \toprule + \tabcutin{2}{\makebox[0.9\textwidth][c]{General information}} \\ + \midrule + WISHBONE revision & B3 \\ + Type of interface & MASTER \\ + Supported cycles & BLOCK READ \\ + \midrule + \tabcutin{2}{Signal names} \\ + \midrule + \signal{clk\_i} & CLK\_I \\ + \signal{rst\_i} & RST\_I \\ + \signal{ibus\_cyc\_o} & CYC\_O \\ + \signal{ibus\_stb\_o} & STB\_O \\ + \signal{ibus\_cti\_o} & CTI\_O() \\ + \signal{ibus\_bte\_o} & BTE\_O() \\ + \signal{ibus\_ack\_i} & ACK\_I \\ + \signal{ibus\_adr\_o} & ADR\_O() \\ + \signal{ibus\_dat\_i} & DAT\_I() \\ + \midrule + \tabcutin{2}{Supported tag signals} \\ + \midrule + \signal{ibus\_cti\_o} & Cycle Type Identifier (address tag) \\ + & \hspace{\parindent} ``010'' (Incrementing burst cycle) \\ + & \hspace{\parindent} ``111'' (End-of-Burst) \\ + \signal{ibus\_bte\_o} & Burst Type Extension (address tag) \\ + & \hspace{\parindent} ``00'' (Linear burst) \\ + \midrule + \tabcutin{2}{Dimensions} \\ + \midrule + Port size & 32 \\ + Port granularity & 32 \\ + Maximum operand size & 32 \\ + Data transfer ordering & BIG/LITTLE ENDIAN \\ + Data transfer sequence & UNDEFINED \\ + \bottomrule +\end{ctabular} + +\section{Data bus} + +\begin{ctabular}{ll} + \toprule + \tabcutin{2}{\makebox[0.9\textwidth][c]{General information}} \\ + \midrule + WISHBONE revision & B3 \\ + Type of interface & MASTER \\ + Supported cycles & SINGLE READ/WRITE \\ + & RMW \\ + \midrule + \tabcutin{2}{Signal names} \\ + \midrule + \signal{clk\_i} & CLK\_I \\ + \signal{rst\_i} & RST\_I \\ + \signal{dbus\_cyc\_o} & CYC\_O \\ + \signal{dbus\_stb\_o} & STB\_O \\ + \signal{dbus\_we\_o} & WE\_O \\ + \signal{dbus\_sel\_o} & SEL\_O() \\ + \signal{dbus\_ack\_i} & ACK\_I \\ + \signal{dbus\_adr\_o} & ADR\_O() \\ + \signal{dbus\_dat\_o} & DAT\_O() \\ + \signal{dbus\_dat\_i} & DAT\_I() \\ + \midrule + \tabcutin{2}{Dimensions} \\ + \midrule + Port size & 32 \\ + Port granularity & 8 \\ + Maximum operand size & 32 \\ + Data transfer ordering & LITTLE ENDIAN \\ + Data transfer sequence & UNDEFINED \\ + \bottomrule +\end{ctabular} + +\chapter{List of changes} + +\section*{Version 1.2 (2021-10-21)} + +This release introduces a few non-breaking changes to the software and testbench. The CPU RTL description hasn't been changed from the previous release. + +\begin{itemize} + \item \shellcmd{lxp32asm} now supports C-style conditional processing directives: \instr{\#ifdef}, \instr{\#ifndef}, \instr{\#else} and \instr{\#endif}. + \item \instr{\#define} directive can now declare a macro with zero subsitute tokens. + \item A new \instr{\#error} directive. + \item Minor changes to the testbench. +\end{itemize} + +\section*{Version 1.1 (2019-01-11)} + +This release introduces a minor but technically breaking hardware change: the START\_ADDR generic, which used to be 30-bit, has been for convenience extended to a full 32-bit word; the two least significant bits are ignored. + +The other breaking change affects the assembly language syntax. Previously all symbols used to be public, and multiple modules could not define symbols with the same name. As of now only symbols explicitly exported using the \instr{\#export} directive are public. \instr{\#extern} directive has been replaced by \instr{\#import}. + +Other notable changes include: + +\begin{itemize} + \item A new instruction, \instr{lcs} (\instrname{Load Constant Short}), has been added, which loads a 21-bit sign extended constant to a register. Unlike \instr{lc}, it is encoded as a single word and takes one cycle to execute. + \item Optimizations in the divider unit. Division instructions (\instr{divs} and \instr{divu}) now take one fewer cycle to execute (modulo instructions are unaffected). + \item LXP32 assembly language now supports a new instruction alias, \instr{neg} (\instrname{Negate}), which is equivalent to \code{\instr{sub} dst, 0, src}. +\end{itemize} + +\section*{Version 1.0 (2016-02-20)} + +Initial public release. + +\end{document} Index: tags/1.2/doc/src/trm/preamble.tex =================================================================== --- tags/1.2/doc/src/trm/preamble.tex (nonexistent) +++ tags/1.2/doc/src/trm/preamble.tex (revision 10) @@ -0,0 +1,89 @@ +\usepackage{microtype} +\usepackage{graphicx} +\usepackage{alltt} +\usepackage{amsmath} +\usepackage[charter]{mathdesign} + +\usepackage{fontspec} +\setmainfont[Ligatures=TeX]{XCharter} +\setmonofont[Scale=MatchLowercase]{DejaVu Sans Mono} + +\usepackage[english]{babel} + +\usepackage[perpage]{footmisc} + +\newcommand{\styledtitleref}[1]{\emph{\titleref{#1}}} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Various Memoir class settings +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\sloppybottom +\setsecnumdepth{section} +\settocdepth{section} + +\setpnumwidth{2.55em} +\setrmarg{3.55em} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Code +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newcommand{\shellcmd}[1]{\texttt{#1}} +\newcommand{\code}[1]{\mbox{\texttt{#1}}} +\newcommand{\instr}[1]{\texttt{\textbf{#1}}} +\newcommand{\instrname}[1]{\emph{#1}} +\newcommand{\signal}[1]{\texttt{#1}} + +\newenvironment{codepar}{% + \vspace{0.5\baselineskip}% + \begin{minipage}{0.9\textwidth}\begin{alltt} +}{% + \end{alltt}\end{minipage}% + \vspace{0.5\baselineskip} +} + +\newenvironment{codeparbreakable}{% + \vspace{0.5\baselineskip}% + \begin{alltt} + }{% + \end{alltt}% + \vspace{0.5\baselineskip} +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Tables +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newcolumntype{L}{>{\raggedright\arraybackslash}X} +\newcolumntype{R}{>{\raggedleft\arraybackslash}X} +\newcolumntype{C}{>{\centering\arraybackslash}X} + +\newcolumntype{Q}[1]{>{\raggedright\arraybackslash}m{#1}} +\newcolumntype{E}[1]{>{\raggedleft\arraybackslash}m{#1}} +\newcolumntype{W}[1]{>{\centering\arraybackslash}m{#1}} + +\newcommand{\tabcutin}[2]{\multicolumn{#1}{c}{\emph{#2}}} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Various stuff +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newcommand{\cplusplus}{C\texttt{\raisebox{0.05em}{++}}} +\newcommand{\lxp}{\textls[60]{LXP}32} +\newcommand{\tocitem}[2]{\phantomsection\addcontentsline{toc}{#1}{#2}} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Hyperlinks +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\usepackage[bookmarks=true, + bookmarksnumbered=true, + bookmarksdepth=2, + hypertexnames=false] + {hyperref} + +\hypersetup{ + pdftitle={LXP32 Technical Reference Manual}, + pdfauthor={Alex I. Kuznetsov} +} Index: tags/1.2/doc/lxp32-logo.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2/doc/lxp32-logo.png =================================================================== --- tags/1.2/doc/lxp32-logo.png (nonexistent) +++ tags/1.2/doc/lxp32-logo.png (revision 10)
tags/1.2/doc/lxp32-logo.png Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2/misc/highlight/akelpad/asm.coder =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2/misc/highlight/akelpad/asm.coder =================================================================== --- tags/1.2/misc/highlight/akelpad/asm.coder (nonexistent) +++ tags/1.2/misc/highlight/akelpad/asm.coder (revision 10)
tags/1.2/misc/highlight/akelpad/asm.coder Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2/misc/highlight/notepad++/LXP32Assembly.xml =================================================================== --- tags/1.2/misc/highlight/notepad++/LXP32Assembly.xml (nonexistent) +++ tags/1.2/misc/highlight/notepad++/LXP32Assembly.xml (revision 10) @@ -0,0 +1,64 @@ + + + + + + + + 00// 01 02 03/* 04*/ + + 0x + A B C D E F a b c d e f + + + + + @ , + + + + + + + + + + + add and call cjmpe cjmpne cjmpsg cjmpsge cjmpsl cjmpsle cjmpug cjmpuge cjmpul cjmpule divs divu hlt jmp iret lc lcs lsb lub lw mods modu mov mul neg nop not or ret sb sl srs sru sub sw xor + cr irp iv0 iv1 iv2 iv3 iv4 iv5 iv6 iv7 r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15 r16 r17 r18 r19 r20 r21 r22 r23 r24 r25 r26 r27 r28 r29 r30 r31 r32 r33 r34 r35 r36 r37 r38 r39 r40 r41 r42 r43 r44 r45 r46 r47 r48 r49 r50 r51 r52 r53 r54 r55 r56 r57 r58 r59 r60 r61 r62 r63 r64 r65 r66 r67 r68 r69 r70 r71 r72 r73 r74 r75 r76 r77 r78 r79 r80 r81 r82 r83 r84 r85 r86 r87 r88 r89 r90 r91 r92 r93 r94 r95 r96 r97 r98 r99 r100 r101 r102 r103 r104 r105 r106 r107 r108 r109 r110 r111 r112 r113 r114 r115 r116 r117 r118 r119 r120 r121 r122 r123 r124 r125 r126 r127 r128 r129 r130 r131 r132 r133 r134 r135 r136 r137 r138 r139 r140 r141 r142 r143 r144 r145 r146 r147 r148 r149 r150 r151 r152 r153 r154 r155 r156 r157 r158 r159 r160 r161 r162 r163 r164 r165 r166 r167 r168 r169 r170 r171 r172 r173 r174 r175 r176 r177 r178 r179 r180 r181 r182 r183 r184 r185 r186 r187 r188 r189 r190 r191 r192 r193 r194 r195 r196 r197 r198 r199 r200 r201 r202 r203 r204 r205 r206 r207 r208 r209 r210 r211 r212 r213 r214 r215 r216 r217 r218 r219 r220 r221 r222 r223 r224 r225 r226 r227 r228 r229 r230 r231 r232 r233 r234 r235 r236 r237 r238 r239 r240 r241 r242 r243 r244 r245 r246 r247 r248 r249 r250 r251 r252 r253 r254 r255 rp sp + #define #else #endif #error #export #ifdef #ifndef #import #include #message + .align .byte .reserve .word + + + + + 00" 01\ 02" 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2/misc/highlight/readme.txt =================================================================== --- tags/1.2/misc/highlight/readme.txt (nonexistent) +++ tags/1.2/misc/highlight/readme.txt (revision 10) @@ -0,0 +1,5 @@ +This directory contains LXP32 assembly language syntax highlighting +rules for the following text editors: + + * AkelPad (http://akelpad.sourceforge.net/) + * Notepad++ (https://notepad-plus-plus.org/) Index: tags/1.2/rtl/lxp32_alu.vhd =================================================================== --- tags/1.2/rtl/lxp32_alu.vhd (nonexistent) +++ tags/1.2/rtl/lxp32_alu.vhd (revision 10) @@ -0,0 +1,250 @@ +--------------------------------------------------------------------- +-- Arithmetic logic unit +-- +-- Part of the LXP32 CPU +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- Performs arithmetic and logic operations. +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity lxp32_alu is + generic( + DIVIDER_EN: boolean; + MUL_ARCH: string + ); + port( + clk_i: in std_logic; + rst_i: in std_logic; + + valid_i: in std_logic; + + cmd_signed_i: in std_logic; + cmd_addsub_i: in std_logic; + cmd_mul_i: in std_logic; + cmd_div_i: in std_logic; + cmd_div_mod_i: in std_logic; + cmd_cmp_i: in std_logic; + cmd_negate_op2_i: in std_logic; + cmd_and_i: in std_logic; + cmd_xor_i: in std_logic; + cmd_shift_i: in std_logic; + cmd_shift_right_i: in std_logic; + + op1_i: in std_logic_vector(31 downto 0); + op2_i: in std_logic_vector(31 downto 0); + + result_o: out std_logic_vector(31 downto 0); + + cmp_eq_o: out std_logic; + cmp_ug_o: out std_logic; + cmp_sg_o: out std_logic; + + we_o: out std_logic; + busy_o: out std_logic + ); +end entity; + +architecture rtl of lxp32_alu is + +signal addend1: unsigned(31 downto 0); +signal addend2: unsigned(31 downto 0); +signal adder_result: unsigned(32 downto 0); +signal adder_we: std_logic; + +signal cmp_eq: std_logic; +signal cmp_carry: std_logic; +signal cmp_s1: std_logic; +signal cmp_s2: std_logic; + +signal logic_result: std_logic_vector(31 downto 0); +signal logic_we: std_logic; + +signal mul_result: std_logic_vector(31 downto 0); +signal mul_ce: std_logic; +signal mul_we: std_logic; + +signal div_result: std_logic_vector(31 downto 0); +signal div_ce: std_logic; +signal div_we: std_logic; + +signal shift_result: std_logic_vector(31 downto 0); +signal shift_ce: std_logic; +signal shift_we: std_logic; + +signal result_mux: std_logic_vector(31 downto 0); +signal result_we: std_logic; + +signal busy: std_logic:='0'; + +begin + +assert MUL_ARCH="dsp" or MUL_ARCH="seq" or MUL_ARCH="opt" + report "Invalid MUL_ARCH generic value: dsp, opt or seq expected" + severity failure; + +-- Add/subtract + +addend1<=unsigned(op1_i); + +addend2_gen: for i in addend2'range generate + addend2(i)<=op2_i(i) xor cmd_negate_op2_i; +end generate; + +adder_result<=("0"&addend1)+("0"&addend2)+(to_unsigned(0,adder_result'length-1)&cmd_negate_op2_i); +adder_we<=cmd_addsub_i and valid_i; + +-- Comparator (needs cmd_negate_op2_i to work correctly) + +process (clk_i) is +begin + if rising_edge(clk_i) then + if valid_i='1' and cmd_cmp_i='1' then + if op1_i=op2_i then + cmp_eq<='1'; + else + cmp_eq<='0'; + end if; + + cmp_carry<=adder_result(adder_result'high); + cmp_s1<=op1_i(op1_i'high); + cmp_s2<=op2_i(op2_i'high); + end if; + end if; +end process; + +cmp_eq_o<=cmp_eq; +cmp_ug_o<=cmp_carry and not cmp_eq; +cmp_sg_o<=((cmp_s1 and cmp_s2 and cmp_carry) or + (not cmp_s1 and not cmp_s2 and cmp_carry) or + (not cmp_s1 and cmp_s2)) and not cmp_eq; + +-- Bitwise operations (and, or, xor) +-- Note: (a or b) = (a and b) or (a xor b) + +logic_result_gen: for i in logic_result'range generate + logic_result(i)<=((op1_i(i) and op2_i(i)) and cmd_and_i) or + ((op1_i(i) xor op2_i(i)) and cmd_xor_i); +end generate; + +logic_we<=(cmd_and_i or cmd_xor_i) and valid_i; + +-- Multiplier + +mul_ce<=cmd_mul_i and valid_i; + +gen_mul_dsp: if MUL_ARCH="dsp" generate + mul_inst: entity work.lxp32_mul_dsp(rtl) + port map( + clk_i=>clk_i, + rst_i=>rst_i, + ce_i=>mul_ce, + op1_i=>op1_i, + op2_i=>op2_i, + ce_o=>mul_we, + result_o=>mul_result + ); +end generate; + +gen_mul_opt: if MUL_ARCH="opt" generate + mul_inst: entity work.lxp32_mul_opt(rtl) + port map( + clk_i=>clk_i, + rst_i=>rst_i, + ce_i=>mul_ce, + op1_i=>op1_i, + op2_i=>op2_i, + ce_o=>mul_we, + result_o=>mul_result + ); +end generate; + +gen_mul_seq: if MUL_ARCH="seq" generate + mul_inst: entity work.lxp32_mul_seq(rtl) + port map( + clk_i=>clk_i, + rst_i=>rst_i, + ce_i=>mul_ce, + op1_i=>op1_i, + op2_i=>op2_i, + ce_o=>mul_we, + result_o=>mul_result + ); +end generate; + +-- Divider + +div_ce<=cmd_div_i and valid_i; + +gen_divider: if DIVIDER_EN generate + divider_inst: entity work.lxp32_divider(rtl) + port map( + clk_i=>clk_i, + rst_i=>rst_i, + ce_i=>div_ce, + op1_i=>op1_i, + op2_i=>op2_i, + signed_i=>cmd_signed_i, + rem_i=>cmd_div_mod_i, + ce_o=>div_we, + result_o=>div_result + ); +end generate; + +gen_no_divider: if not DIVIDER_EN generate + div_we<=div_ce; + div_result<=(others=>'0'); +end generate; + +-- Shifter + +shift_ce<=cmd_shift_i and valid_i; + +shifter_inst: entity work.lxp32_shifter(rtl) + port map( + clk_i=>clk_i, + rst_i=>rst_i, + ce_i=>shift_ce, + d_i=>op1_i, + s_i=>op2_i(4 downto 0), + right_i=>cmd_shift_right_i, + sig_i=>cmd_signed_i, + ce_o=>shift_we, + d_o=>shift_result + ); + +-- Result multiplexer + +result_mux_gen: for i in result_mux'range generate + result_mux(i)<=(adder_result(i) and adder_we) or + (logic_result(i) and logic_we) or + (mul_result(i) and mul_we) or + (div_result(i) and div_we) or + (shift_result(i) and shift_we); +end generate; + +result_o<=result_mux; + +result_we<=adder_we or logic_we or mul_we or div_we or shift_we; +we_o<=result_we; + +-- Pipeline control + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' or result_we='1' then + busy<='0'; + elsif shift_ce='1' or mul_ce='1' or div_ce='1' then + busy<='1'; + end if; + end if; +end process; + +busy_o<=busy; + +end architecture; Index: tags/1.2/rtl/lxp32_compl.vhd =================================================================== --- tags/1.2/rtl/lxp32_compl.vhd (nonexistent) +++ tags/1.2/rtl/lxp32_compl.vhd (revision 10) @@ -0,0 +1,50 @@ +--------------------------------------------------------------------- +-- Complementor +-- +-- Part of the LXP32 CPU +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- Computes a 2's complement of its input. Used as an auxiliary +-- unit in the divider. +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity lxp32_compl is + port( + clk_i: in std_logic; + compl_i: in std_logic; + d_i: in std_logic_vector(31 downto 0); + d_o: out std_logic_vector(31 downto 0) + ); +end entity; + +architecture rtl of lxp32_compl is + +signal d_prepared: unsigned(d_i'range); +signal sum_low: unsigned(16 downto 0); +signal d_high: unsigned(15 downto 0); +signal sum_high: unsigned(15 downto 0); + +begin + +d_prepared_gen: for i in d_prepared'range generate + d_prepared(i)<=d_i(i) xor compl_i; +end generate; + +process (clk_i) is +begin + if rising_edge(clk_i) then + sum_low<=("0"&d_prepared(15 downto 0))+(to_unsigned(0,16)&compl_i); + d_high<=d_prepared(31 downto 16); + end if; +end process; + +sum_high<=d_high+(to_unsigned(0,15)&sum_low(sum_low'high)); + +d_o<=std_logic_vector(sum_high&sum_low(15 downto 0)); + +end architecture; Index: tags/1.2/rtl/lxp32_cpu.vhd =================================================================== --- tags/1.2/rtl/lxp32_cpu.vhd (nonexistent) +++ tags/1.2/rtl/lxp32_cpu.vhd (revision 10) @@ -0,0 +1,256 @@ +--------------------------------------------------------------------- +-- LXP32 CPU Core +-- +-- Part of the LXP32 CPU +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity lxp32_cpu is + generic( + DBUS_RMW: boolean; + DIVIDER_EN: boolean; + MUL_ARCH: string; + START_ADDR: std_logic_vector(31 downto 0) + ); + port( + clk_i: in std_logic; + rst_i: in std_logic; + + lli_re_o: out std_logic; + lli_adr_o: out std_logic_vector(29 downto 0); + lli_dat_i: in std_logic_vector(31 downto 0); + lli_busy_i: in std_logic; + + dbus_cyc_o: out std_logic; + dbus_stb_o: out std_logic; + dbus_we_o: out std_logic; + dbus_sel_o: out std_logic_vector(3 downto 0); + dbus_ack_i: in std_logic; + dbus_adr_o: out std_logic_vector(31 downto 2); + dbus_dat_o: out std_logic_vector(31 downto 0); + dbus_dat_i: in std_logic_vector(31 downto 0); + + irq_i: in std_logic_vector(7 downto 0) + ); +end entity; + +architecture rtl of lxp32_cpu is + +signal fetch_word: std_logic_vector(31 downto 0); +signal fetch_next_ip: std_logic_vector(29 downto 0); +signal fetch_current_ip: std_logic_vector(29 downto 0); +signal fetch_valid: std_logic; +signal fetch_jump_ready: std_logic; + +signal decode_ready: std_logic; +signal decode_valid: std_logic; + +signal decode_cmd_loadop3: std_logic; +signal decode_cmd_signed: std_logic; +signal decode_cmd_dbus: std_logic; +signal decode_cmd_dbus_store: std_logic; +signal decode_cmd_dbus_byte: std_logic; +signal decode_cmd_addsub: std_logic; +signal decode_cmd_mul: std_logic; +signal decode_cmd_div: std_logic; +signal decode_cmd_div_mod: std_logic; +signal decode_cmd_cmp: std_logic; +signal decode_cmd_jump: std_logic; +signal decode_cmd_negate_op2: std_logic; +signal decode_cmd_and: std_logic; +signal decode_cmd_xor: std_logic; +signal decode_cmd_shift: std_logic; +signal decode_cmd_shift_right: std_logic; + +signal decode_jump_type: std_logic_vector(3 downto 0); + +signal decode_op1: std_logic_vector(31 downto 0); +signal decode_op2: std_logic_vector(31 downto 0); +signal decode_op3: std_logic_vector(31 downto 0); +signal decode_dst: std_logic_vector(7 downto 0); + +signal execute_ready: std_logic; +signal execute_jump_valid: std_logic; +signal execute_jump_dst: std_logic_vector(29 downto 0); + +signal sp_raddr1: std_logic_vector(7 downto 0); +signal sp_rdata1: std_logic_vector(31 downto 0); +signal sp_raddr2: std_logic_vector(7 downto 0); +signal sp_rdata2: std_logic_vector(31 downto 0); +signal sp_waddr: std_logic_vector(7 downto 0); +signal sp_we: std_logic; +signal sp_wdata: std_logic_vector(31 downto 0); + +signal interrupt_valid: std_logic; +signal interrupt_vector: std_logic_vector(2 downto 0); +signal interrupt_ready: std_logic; +signal interrupt_return: std_logic; + +begin + +fetch_inst: entity work.lxp32_fetch(rtl) + generic map( + START_ADDR=>START_ADDR + ) + port map( + clk_i=>clk_i, + rst_i=>rst_i, + + lli_re_o=>lli_re_o, + lli_adr_o=>lli_adr_o, + lli_dat_i=>lli_dat_i, + lli_busy_i=>lli_busy_i, + + word_o=>fetch_word, + next_ip_o=>fetch_next_ip, + current_ip_o=>fetch_current_ip, + valid_o=>fetch_valid, + ready_i=>decode_ready, + + jump_valid_i=>execute_jump_valid, + jump_dst_i=>execute_jump_dst, + jump_ready_o=>fetch_jump_ready + ); + +decode_inst: entity work.lxp32_decode(rtl) + port map( + clk_i=>clk_i, + rst_i=>rst_i, + + word_i=>fetch_word, + next_ip_i=>fetch_next_ip, + current_ip_i=>fetch_current_ip, + valid_i=>fetch_valid, + jump_valid_i=>execute_jump_valid, + ready_o=>decode_ready, + + interrupt_valid_i=>interrupt_valid, + interrupt_vector_i=>interrupt_vector, + interrupt_ready_o=>interrupt_ready, + + sp_raddr1_o=>sp_raddr1, + sp_rdata1_i=>sp_rdata1, + sp_raddr2_o=>sp_raddr2, + sp_rdata2_i=>sp_rdata2, + + ready_i=>execute_ready, + valid_o=>decode_valid, + + cmd_loadop3_o=>decode_cmd_loadop3, + cmd_signed_o=>decode_cmd_signed, + cmd_dbus_o=>decode_cmd_dbus, + cmd_dbus_store_o=>decode_cmd_dbus_store, + cmd_dbus_byte_o=>decode_cmd_dbus_byte, + cmd_addsub_o=>decode_cmd_addsub, + cmd_mul_o=>decode_cmd_mul, + cmd_div_o=>decode_cmd_div, + cmd_div_mod_o=>decode_cmd_div_mod, + cmd_cmp_o=>decode_cmd_cmp, + cmd_jump_o=>decode_cmd_jump, + cmd_negate_op2_o=>decode_cmd_negate_op2, + cmd_and_o=>decode_cmd_and, + cmd_xor_o=>decode_cmd_xor, + cmd_shift_o=>decode_cmd_shift, + cmd_shift_right_o=>decode_cmd_shift_right, + + jump_type_o=>decode_jump_type, + + op1_o=>decode_op1, + op2_o=>decode_op2, + op3_o=>decode_op3, + dst_o=>decode_dst + ); + +execute_inst: entity work.lxp32_execute(rtl) + generic map( + DBUS_RMW=>DBUS_RMW, + DIVIDER_EN=>DIVIDER_EN, + MUL_ARCH=>MUL_ARCH + ) + port map( + clk_i=>clk_i, + rst_i=>rst_i, + + cmd_loadop3_i=>decode_cmd_loadop3, + cmd_signed_i=>decode_cmd_signed, + cmd_dbus_i=>decode_cmd_dbus, + cmd_dbus_store_i=>decode_cmd_dbus_store, + cmd_dbus_byte_i=>decode_cmd_dbus_byte, + cmd_addsub_i=>decode_cmd_addsub, + cmd_mul_i=>decode_cmd_mul, + cmd_div_i=>decode_cmd_div, + cmd_div_mod_i=>decode_cmd_div_mod, + cmd_cmp_i=>decode_cmd_cmp, + cmd_jump_i=>decode_cmd_jump, + cmd_negate_op2_i=>decode_cmd_negate_op2, + cmd_and_i=>decode_cmd_and, + cmd_xor_i=>decode_cmd_xor, + cmd_shift_i=>decode_cmd_shift, + cmd_shift_right_i=>decode_cmd_shift_right, + + jump_type_i=>decode_jump_type, + + op1_i=>decode_op1, + op2_i=>decode_op2, + op3_i=>decode_op3, + dst_i=>decode_dst, + + sp_waddr_o=>sp_waddr, + sp_we_o=>sp_we, + sp_wdata_o=>sp_wdata, + + valid_i=>decode_valid, + ready_o=>execute_ready, + + dbus_cyc_o=>dbus_cyc_o, + dbus_stb_o=>dbus_stb_o, + dbus_we_o=>dbus_we_o, + dbus_sel_o=>dbus_sel_o, + dbus_ack_i=>dbus_ack_i, + dbus_adr_o=>dbus_adr_o, + dbus_dat_o=>dbus_dat_o, + dbus_dat_i=>dbus_dat_i, + + jump_valid_o=>execute_jump_valid, + jump_dst_o=>execute_jump_dst, + jump_ready_i=>fetch_jump_ready, + + interrupt_return_o=>interrupt_return + ); + +scratchpad_inst: entity work.lxp32_scratchpad(rtl) + port map( + clk_i=>clk_i, + + raddr1_i=>sp_raddr1, + rdata1_o=>sp_rdata1, + raddr2_i=>sp_raddr2, + rdata2_o=>sp_rdata2, + + waddr_i=>sp_waddr, + we_i=>sp_we, + wdata_i=>sp_wdata + ); + +interrupt_mux_inst: entity work.lxp32_interrupt_mux(rtl) + port map( + clk_i=>clk_i, + rst_i=>rst_i, + + irq_i=>irq_i, + + interrupt_valid_o=>interrupt_valid, + interrupt_vector_o=>interrupt_vector, + interrupt_ready_i=>interrupt_ready, + interrupt_return_i=>interrupt_return, + + sp_waddr_i=>sp_waddr, + sp_we_i=>sp_we, + sp_wdata_i=>sp_wdata + ); + +end architecture; Index: tags/1.2/rtl/lxp32_dbus.vhd =================================================================== --- tags/1.2/rtl/lxp32_dbus.vhd (nonexistent) +++ tags/1.2/rtl/lxp32_dbus.vhd (revision 10) @@ -0,0 +1,171 @@ +--------------------------------------------------------------------- +-- DBUS master +-- +-- Part of the LXP32 CPU +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- Manages data bus (DBUS) access. +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity lxp32_dbus is + generic( + RMW: boolean + ); + port( + clk_i: in std_logic; + rst_i: in std_logic; + + valid_i: in std_logic; + + cmd_dbus_i: in std_logic; + cmd_dbus_store_i: in std_logic; + cmd_dbus_byte_i: in std_logic; + cmd_signed_i: in std_logic; + addr_i: in std_logic_vector(31 downto 0); + wdata_i: in std_logic_vector(31 downto 0); + + rdata_o: out std_logic_vector(31 downto 0); + we_o: out std_logic; + busy_o: out std_logic; + + dbus_cyc_o: out std_logic; + dbus_stb_o: out std_logic; + dbus_we_o: out std_logic; + dbus_sel_o: out std_logic_vector(3 downto 0); + dbus_ack_i: in std_logic; + dbus_adr_o: out std_logic_vector(31 downto 2); + dbus_dat_o: out std_logic_vector(31 downto 0); + dbus_dat_i: in std_logic_vector(31 downto 0) + ); +end entity; + +architecture rtl of lxp32_dbus is + +signal strobe: std_logic:='0'; +signal we_out: std_logic:='0'; +signal we: std_logic; +signal byte_mode: std_logic; +signal sel: std_logic_vector(3 downto 0); +signal sig: std_logic; +signal rmw_mode: std_logic; + +signal dbus_rdata: std_logic_vector(31 downto 0); +signal selected_byte: std_logic_vector(7 downto 0); + +begin + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' then + we_out<='0'; + strobe<='0'; + sig<='-'; + byte_mode<='-'; + sel<=(others=>'-'); + we<='-'; + rmw_mode<='-'; + dbus_adr_o<=(others=>'-'); + dbus_dat_o<=(others=>'-'); + else + we_out<='0'; + if strobe='0' then + if valid_i='1' and cmd_dbus_i='1' then + strobe<='1'; + sig<=cmd_signed_i; + + dbus_adr_o<=addr_i(31 downto 2); + + if cmd_dbus_byte_i='0' then + byte_mode<='0'; + dbus_dat_o<=wdata_i; + sel<="1111"; + + -- synthesis translate_off + assert addr_i(1 downto 0)="00" + report "Misaligned word-granular access on data bus" + severity warning; + -- synthesis translate_on + else + byte_mode<='1'; + dbus_dat_o<=wdata_i(7 downto 0)&wdata_i(7 downto 0)& + wdata_i(7 downto 0)&wdata_i(7 downto 0); + + case addr_i(1 downto 0) is + when "00" => sel<="0001"; + when "01" => sel<="0010"; + when "10" => sel<="0100"; + when "11" => sel<="1000"; + when others => + end case; + end if; + + if not RMW then + we<=cmd_dbus_store_i; + rmw_mode<='0'; + else + we<=cmd_dbus_store_i and not cmd_dbus_byte_i; + rmw_mode<=cmd_dbus_store_i and cmd_dbus_byte_i; + end if; + end if; + else + if dbus_ack_i='1' then + if rmw_mode='1' and we='0' and RMW then + we<='1'; + for i in sel'range loop + if sel(i)='0' then + dbus_dat_o(i*8+7 downto i*8)<= + dbus_dat_i(i*8+7 downto i*8); + end if; + end loop; + else + strobe<='0'; + if we='0' then + we_out<='1'; + end if; + end if; + end if; + end if; + end if; + end if; +end process; + +dbus_cyc_o<=strobe; +dbus_stb_o<=strobe; +dbus_we_o<=we; + +sel_no_rmw_gen: if not RMW generate + dbus_sel_o<=sel; +end generate; + +sel_rmw_gen: if RMW generate + dbus_sel_o<=(others=>'1'); +end generate; + +process (clk_i) is +begin + if rising_edge(clk_i) then + dbus_rdata<=dbus_dat_i; + end if; +end process; + +selected_byte_gen: for i in selected_byte'range generate + selected_byte(i)<=(dbus_rdata(i) and sel(0)) or + (dbus_rdata(i+8) and sel(1)) or + (dbus_rdata(i+16) and sel(2)) or + (dbus_rdata(i+24) and sel(3)); +end generate; + +rdata_o<=dbus_rdata when byte_mode='0' else + X"000000"&selected_byte when selected_byte(selected_byte'high)='0' or sig='0' else + X"FFFFFF"&selected_byte; + +we_o<=we_out; +busy_o<=strobe or we_out; + +end architecture; Index: tags/1.2/rtl/lxp32_decode.vhd =================================================================== --- tags/1.2/rtl/lxp32_decode.vhd (nonexistent) +++ tags/1.2/rtl/lxp32_decode.vhd (revision 10) @@ -0,0 +1,327 @@ +--------------------------------------------------------------------- +-- Instruction decoder +-- +-- Part of the LXP32 CPU +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- The second stage of the LXP32 pipeline. +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity lxp32_decode is + port( + clk_i: in std_logic; + rst_i: in std_logic; + + word_i: in std_logic_vector(31 downto 0); + next_ip_i: in std_logic_vector(29 downto 0); + current_ip_i: in std_logic_vector(29 downto 0); + valid_i: in std_logic; + jump_valid_i: in std_logic; + ready_o: out std_logic; + + interrupt_valid_i: in std_logic; + interrupt_vector_i: in std_logic_vector(2 downto 0); + interrupt_ready_o: out std_logic; + + sp_raddr1_o: out std_logic_vector(7 downto 0); + sp_rdata1_i: in std_logic_vector(31 downto 0); + sp_raddr2_o: out std_logic_vector(7 downto 0); + sp_rdata2_i: in std_logic_vector(31 downto 0); + + ready_i: in std_logic; + valid_o: out std_logic; + + cmd_loadop3_o: out std_logic; + cmd_signed_o: out std_logic; + cmd_dbus_o: out std_logic; + cmd_dbus_store_o: out std_logic; + cmd_dbus_byte_o: out std_logic; + cmd_addsub_o: out std_logic; + cmd_mul_o: out std_logic; + cmd_div_o: out std_logic; + cmd_div_mod_o: out std_logic; + cmd_cmp_o: out std_logic; + cmd_jump_o: out std_logic; + cmd_negate_op2_o: out std_logic; + cmd_and_o: out std_logic; + cmd_xor_o: out std_logic; + cmd_shift_o: out std_logic; + cmd_shift_right_o: out std_logic; + + jump_type_o: out std_logic_vector(3 downto 0); + + op1_o: out std_logic_vector(31 downto 0); + op2_o: out std_logic_vector(31 downto 0); + op3_o: out std_logic_vector(31 downto 0); + dst_o: out std_logic_vector(7 downto 0) + ); +end entity; + +architecture rtl of lxp32_decode is + +-- Decoder FSM state + +type DecoderState is (Regular,ContinueLc,ContinueCjmp,ContinueInterrupt,Halt); +signal state: DecoderState:=Regular; + +-- Input instruction portions + +signal opcode: std_logic_vector(5 downto 0); +signal t1: std_logic; +signal t2: std_logic; +signal destination: std_logic_vector(7 downto 0); +signal rd1: std_logic_vector(7 downto 0); +signal rd2: std_logic_vector(7 downto 0); + +-- Signals related to pipeline control + +signal downstream_busy: std_logic; +signal self_busy: std_logic:='0'; +signal busy: std_logic; +signal valid_out: std_logic:='0'; + +signal dst_out: std_logic_vector(7 downto 0); + +-- Signals related to RD operand decoding + +signal rd1_reg: std_logic_vector(7 downto 0); +signal rd2_reg: std_logic_vector(7 downto 0); + +signal rd1_select: std_logic; +signal rd1_direct: std_logic_vector(31 downto 0); +signal rd2_select: std_logic; +signal rd2_direct: std_logic_vector(31 downto 0); + +-- Signals related to interrupt handling + +signal interrupt_ready: std_logic:='0'; + +begin + +-- Dissect input word + +opcode<=word_i(31 downto 26); +t1<=word_i(25); +t2<=word_i(24); +destination<=word_i(23 downto 16); +rd1<=word_i(15 downto 8); +rd2<=word_i(7 downto 0); + +-- Pipeline control + +downstream_busy<=valid_out and not ready_i; +busy<=downstream_busy or self_busy; + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' then + valid_out<='0'; + self_busy<='0'; + state<=Regular; + interrupt_ready<='0'; + cmd_loadop3_o<='-'; + cmd_signed_o<='-'; + cmd_dbus_o<='-'; + cmd_dbus_store_o<='-'; + cmd_dbus_byte_o<='-'; + cmd_addsub_o<='-'; + cmd_negate_op2_o<='-'; + cmd_mul_o<='-'; + cmd_div_o<='-'; + cmd_div_mod_o<='-'; + cmd_cmp_o<='-'; + cmd_jump_o<='-'; + cmd_and_o<='-'; + cmd_xor_o<='-'; + cmd_shift_o<='-'; + cmd_shift_right_o<='-'; + rd1_select<='-'; + rd1_direct<=(others=>'-'); + rd2_select<='-'; + rd2_direct<=(others=>'-'); + op3_o<=(others=>'-'); + jump_type_o<=(others=>'-'); + dst_out<=(others=>'-'); + else + interrupt_ready<='0'; + if jump_valid_i='1' then + valid_out<='0'; + self_busy<='0'; + state<=Regular; + elsif downstream_busy='0' then + op3_o<=(others=>'-'); + rd1_direct<=std_logic_vector(resize(signed(rd1),rd1_direct'length)); + rd2_direct<=std_logic_vector(resize(signed(rd2),rd2_direct'length)); + + cmd_signed_o<=opcode(0); + cmd_div_mod_o<=opcode(1); + cmd_shift_right_o<=opcode(1); + cmd_dbus_byte_o<=opcode(1); + cmd_dbus_store_o<=opcode(2); + + case state is + when Regular => + cmd_loadop3_o<='0'; + cmd_dbus_o<='0'; + cmd_addsub_o<='0'; + cmd_negate_op2_o<='0'; + cmd_mul_o<='0'; + cmd_div_o<='0'; + cmd_cmp_o<='0'; + cmd_jump_o<='0'; + cmd_and_o<='0'; + cmd_xor_o<='0'; + cmd_shift_o<='0'; + + jump_type_o<=opcode(3 downto 0); + + if interrupt_valid_i='1' and valid_i='1' then + cmd_jump_o<='1'; + cmd_loadop3_o<='1'; + op3_o<=current_ip_i&"01"; -- LSB indicates interrupt return + dst_out<=X"FD"; -- interrupt return pointer + rd1_select<='1'; + rd2_select<='0'; + valid_out<='1'; + interrupt_ready<='1'; + self_busy<='1'; + state<=ContinueInterrupt; + else + if opcode(5 downto 3)="101" or opcode="000001" then -- lc or lcs + cmd_loadop3_o<='1'; +-- Setting op3_o here only affects the lcs instruction + op3_o<=std_logic_vector(resize(signed(opcode(2 downto 0)& + t1&t2&rd1&rd2),op3_o'length)); + end if; + + if opcode(5 downto 3)="001" then + cmd_dbus_o<='1'; + end if; + + if opcode(5 downto 1)="01000" then + cmd_addsub_o<='1'; + end if; + + cmd_negate_op2_o<=opcode(0); + + if opcode="010010" then + cmd_mul_o<='1'; + end if; + + if opcode(5 downto 2)="0101" then + cmd_div_o<='1'; + end if; + + if opcode(5 downto 3)="100" then -- jump or call + cmd_jump_o<='1'; + cmd_loadop3_o<=opcode(0); +-- Setting op3_o here only affects the call instruction + op3_o<=next_ip_i&"00"; + end if; + + -- Note: (a or b) = (a and b) or (a xor b) + + if opcode(5 downto 1)="01100" then + cmd_and_o<='1'; + end if; + + if opcode="011010" or opcode="011001" then + cmd_xor_o<='1'; + end if; + + if opcode(5 downto 2)="0111" then + cmd_shift_o<='1'; + end if; + + if opcode(5 downto 4)="11" then + cmd_cmp_o<='1'; + cmd_negate_op2_o<='1'; + end if; + + rd1_select<=t1; + rd2_select<=t2; + + dst_out<=destination; + + if valid_i='1' then + if opcode="000001" then + valid_out<='0'; + self_busy<='0'; + state<=ContinueLc; + elsif opcode="000010" then + valid_out<='0'; + self_busy<='1'; + state<=Halt; + elsif opcode(5 downto 4)="11" then + valid_out<='1'; + self_busy<='1'; + state<=ContinueCjmp; + else + valid_out<='1'; + end if; + else + valid_out<='0'; + end if; + end if; + when ContinueLc => + if valid_i='1' then + valid_out<='1'; + op3_o<=word_i; + self_busy<='0'; + state<=Regular; + end if; + when ContinueCjmp => + valid_out<='1'; + cmd_jump_o<='1'; + rd1_select<='1'; + self_busy<='0'; + state<=Regular; + when ContinueInterrupt => + valid_out<='0'; + when Halt => + if interrupt_valid_i='1' then + self_busy<='0'; + state<=Regular; + end if; + end case; + end if; + end if; + end if; +end process; + +valid_o<=valid_out; +dst_o<=dst_out; + +ready_o<=not busy; + +interrupt_ready_o<=interrupt_ready; + +-- Decode RD (register/direct) operands + +process (clk_i) is +begin + if rising_edge(clk_i) then + if busy='0' then + rd1_reg<=rd1; + rd2_reg<=rd2; + end if; + end if; +end process; + +sp_raddr1_o<="11110"&interrupt_vector_i when (state=Regular and interrupt_valid_i='1' and downstream_busy='0') or state=ContinueInterrupt else + dst_out when (state=ContinueCjmp and downstream_busy='0') else + rd1_reg when busy='1' else + rd1; + +sp_raddr2_o<=rd2_reg when busy='1' else rd2; + +op1_o<=sp_rdata1_i when rd1_select='1' else rd1_direct; +op2_o<=sp_rdata2_i when rd2_select='1' else rd2_direct; + +end architecture; Index: tags/1.2/rtl/lxp32_divider.vhd =================================================================== --- tags/1.2/rtl/lxp32_divider.vhd (nonexistent) +++ tags/1.2/rtl/lxp32_divider.vhd (revision 10) @@ -0,0 +1,172 @@ +--------------------------------------------------------------------- +-- Divider +-- +-- Part of the LXP32 CPU +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- Based on the NRD (Non Restoring Division) algorithm. Takes +-- 36 cycles to calculate quotient (37 for remainder). +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity lxp32_divider is + port( + clk_i: in std_logic; + rst_i: in std_logic; + ce_i: in std_logic; + op1_i: in std_logic_vector(31 downto 0); + op2_i: in std_logic_vector(31 downto 0); + signed_i: in std_logic; + rem_i: in std_logic; + ce_o: out std_logic; + result_o: out std_logic_vector(31 downto 0) + ); +end entity; + +architecture rtl of lxp32_divider is + +-- Complementor signals + +signal compl_inv: std_logic; +signal compl_mux: std_logic_vector(31 downto 0); +signal compl_out: std_logic_vector(31 downto 0); + +signal inv_res: std_logic; + +-- Divider FSM signals + +signal fsm_ce: std_logic:='0'; + +signal dividend: unsigned(31 downto 0); +signal divisor: unsigned(32 downto 0); +signal want_remainder: std_logic; + +signal partial_remainder: unsigned(32 downto 0); +signal addend: unsigned(32 downto 0); +signal sum: unsigned(32 downto 0); +signal sum_positive: std_logic; +signal sum_subtract: std_logic; + +signal cnt: integer range 0 to 34:=0; + +signal ceo: std_logic:='0'; + +-- Output restoration signals + +signal remainder_corrector: unsigned(31 downto 0); +signal remainder_corrector_1: std_logic; +signal remainder_pos: unsigned(31 downto 0); +signal result_pos: unsigned(31 downto 0); + +begin + +compl_inv<=op1_i(31) and signed_i when ce_i='1' else inv_res; +compl_mux<=op1_i when ce_i='1' else std_logic_vector(result_pos); + +compl_op1_inst: entity work.lxp32_compl(rtl) + port map( + clk_i=>clk_i, + compl_i=>compl_inv, + d_i=>compl_mux, + d_o=>compl_out + ); + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' then + fsm_ce<='0'; + want_remainder<='-'; + inv_res<='-'; + else + fsm_ce<=ce_i; + if ce_i='1' then + want_remainder<=rem_i; + if rem_i='1' then + inv_res<=op1_i(31) and signed_i; + else + inv_res<=(op1_i(31) xor op2_i(31)) and signed_i; + end if; + end if; + end if; + end if; +end process; + +-- Main adder/subtractor + +addend_gen: for i in addend'range generate + addend(i)<=divisor(i) xor sum_subtract; +end generate; + +sum<=partial_remainder+addend+(to_unsigned(0,32)&sum_subtract); +sum_positive<=not sum(32); + +-- Divider state machine + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' then + cnt<=0; + ceo<='0'; + divisor<=(others=>'-'); + dividend<=(others=>'-'); + partial_remainder<=(others=>'-'); + sum_subtract<='-'; + else + if cnt=1 then + ceo<='1'; + else + ceo<='0'; + end if; + + if ce_i='1' then + divisor(31 downto 0)<=unsigned(op2_i); + divisor(32)<=op2_i(31) and signed_i; + end if; + + if fsm_ce='1' then + dividend<=unsigned(compl_out(30 downto 0)&"0"); + partial_remainder<=to_unsigned(0,32)&compl_out(31); + sum_subtract<=not divisor(32); + if want_remainder='1' then + cnt<=34; + else + cnt<=33; + end if; + else + partial_remainder<=sum(31 downto 0)÷nd(31); + sum_subtract<=sum_positive xor divisor(32); + dividend<=dividend(30 downto 0)&sum_positive; + if cnt>0 then + cnt<=cnt-1; + end if; + end if; + end if; + end if; +end process; + +-- Output restoration circuit + +process (clk_i) is +begin + if rising_edge(clk_i) then + for i in remainder_corrector'range loop + remainder_corrector(i)<=(divisor(i) xor divisor(32)) and not sum_positive; + end loop; + remainder_corrector_1<=divisor(32) and not sum_positive; + remainder_pos<=partial_remainder(32 downto 1)+remainder_corrector+ + (to_unsigned(0,31)&remainder_corrector_1); + end if; +end process; + +result_pos<=remainder_pos when want_remainder='1' else dividend; + +result_o<=compl_out; +ce_o<=ceo; + +end architecture; Index: tags/1.2/rtl/lxp32_execute.vhd =================================================================== --- tags/1.2/rtl/lxp32_execute.vhd (nonexistent) +++ tags/1.2/rtl/lxp32_execute.vhd (revision 10) @@ -0,0 +1,260 @@ +--------------------------------------------------------------------- +-- Execution unit +-- +-- Part of the LXP32 CPU +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- The third stage of the LXP32 pipeline. +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity lxp32_execute is + generic( + DBUS_RMW: boolean; + DIVIDER_EN: boolean; + MUL_ARCH: string + ); + port( + clk_i: in std_logic; + rst_i: in std_logic; + + cmd_loadop3_i: in std_logic; + cmd_signed_i: in std_logic; + cmd_dbus_i: in std_logic; + cmd_dbus_store_i: in std_logic; + cmd_dbus_byte_i: in std_logic; + cmd_addsub_i: in std_logic; + cmd_mul_i: in std_logic; + cmd_div_i: in std_logic; + cmd_div_mod_i: in std_logic; + cmd_cmp_i: in std_logic; + cmd_jump_i: in std_logic; + cmd_negate_op2_i: in std_logic; + cmd_and_i: in std_logic; + cmd_xor_i: in std_logic; + cmd_shift_i: in std_logic; + cmd_shift_right_i: in std_logic; + + jump_type_i: in std_logic_vector(3 downto 0); + + op1_i: in std_logic_vector(31 downto 0); + op2_i: in std_logic_vector(31 downto 0); + op3_i: in std_logic_vector(31 downto 0); + dst_i: in std_logic_vector(7 downto 0); + + sp_waddr_o: out std_logic_vector(7 downto 0); + sp_we_o: out std_logic; + sp_wdata_o: out std_logic_vector(31 downto 0); + + valid_i: in std_logic; + ready_o: out std_logic; + + dbus_cyc_o: out std_logic; + dbus_stb_o: out std_logic; + dbus_we_o: out std_logic; + dbus_sel_o: out std_logic_vector(3 downto 0); + dbus_ack_i: in std_logic; + dbus_adr_o: out std_logic_vector(31 downto 2); + dbus_dat_o: out std_logic_vector(31 downto 0); + dbus_dat_i: in std_logic_vector(31 downto 0); + + jump_valid_o: out std_logic; + jump_dst_o: out std_logic_vector(29 downto 0); + jump_ready_i: in std_logic; + + interrupt_return_o: out std_logic + ); +end entity; + +architecture rtl of lxp32_execute is + +-- Pipeline control signals + +signal busy: std_logic; +signal can_execute: std_logic; + +-- ALU signals + +signal alu_result: std_logic_vector(31 downto 0); +signal alu_we: std_logic; +signal alu_busy: std_logic; + +signal alu_cmp_eq: std_logic; +signal alu_cmp_ug: std_logic; +signal alu_cmp_sg: std_logic; + +-- OP3 loader signals + +signal loadop3_we: std_logic; + +-- Jump machine signals + +signal jump_condition: std_logic; +signal jump_valid: std_logic:='0'; +signal jump_dst: std_logic_vector(jump_dst_o'range); + +-- DBUS signals + +signal dbus_result: std_logic_vector(31 downto 0); +signal dbus_busy: std_logic; +signal dbus_we: std_logic; + +-- Result mux signals + +signal result_mux: std_logic_vector(31 downto 0); +signal result_valid: std_logic; +signal result_regaddr: std_logic_vector(7 downto 0); + +signal dst_reg: std_logic_vector(7 downto 0); + +-- Signals related to interrupt handling + +signal interrupt_return: std_logic:='0'; + +begin + +-- Pipeline control + +busy<=alu_busy or dbus_busy; +ready_o<=not busy; +can_execute<=valid_i and not busy; + +-- ALU + +alu_inst: entity work.lxp32_alu(rtl) + generic map( + DIVIDER_EN=>DIVIDER_EN, + MUL_ARCH=>MUL_ARCH + ) + port map( + clk_i=>clk_i, + rst_i=>rst_i, + + valid_i=>can_execute, + + cmd_signed_i=>cmd_signed_i, + cmd_addsub_i=>cmd_addsub_i, + cmd_mul_i=>cmd_mul_i, + cmd_div_i=>cmd_div_i, + cmd_div_mod_i=>cmd_div_mod_i, + cmd_cmp_i=>cmd_cmp_i, + cmd_negate_op2_i=>cmd_negate_op2_i, + cmd_and_i=>cmd_and_i, + cmd_xor_i=>cmd_xor_i, + cmd_shift_i=>cmd_shift_i, + cmd_shift_right_i=>cmd_shift_right_i, + + op1_i=>op1_i, + op2_i=>op2_i, + + result_o=>alu_result, + + cmp_eq_o=>alu_cmp_eq, + cmp_ug_o=>alu_cmp_ug, + cmp_sg_o=>alu_cmp_sg, + + we_o=>alu_we, + busy_o=>alu_busy + ); + +-- OP3 loader + +loadop3_we<=can_execute and cmd_loadop3_i; + +-- Jump logic + +jump_condition<=(not cmd_cmp_i) or (jump_type_i(3) and alu_cmp_eq) or + (jump_type_i(2) and not alu_cmp_eq) or (jump_type_i(1) and alu_cmp_ug) or + (jump_type_i(0) and alu_cmp_sg); + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' then + jump_valid<='0'; + interrupt_return<='0'; + jump_dst<=(others=>'-'); + else + if jump_valid='0' then + jump_dst<=op1_i(31 downto 2); + if can_execute='1' and cmd_jump_i='1' and jump_condition='1' then + jump_valid<='1'; + interrupt_return<=op1_i(0); + end if; + elsif jump_ready_i='1' then + jump_valid<='0'; + interrupt_return<='0'; + end if; + end if; + end if; +end process; + +jump_valid_o<=jump_valid or (can_execute and cmd_jump_i and jump_condition); +jump_dst_o<=jump_dst when jump_valid='1' else op1_i(31 downto 2); + +interrupt_return_o<=interrupt_return; + +-- DBUS access + +dbus_inst: entity work.lxp32_dbus(rtl) + generic map( + RMW=>DBUS_RMW + ) + port map( + clk_i=>clk_i, + rst_i=>rst_i, + + valid_i=>can_execute, + + cmd_dbus_i=>cmd_dbus_i, + cmd_dbus_store_i=>cmd_dbus_store_i, + cmd_dbus_byte_i=>cmd_dbus_byte_i, + cmd_signed_i=>cmd_signed_i, + addr_i=>op1_i, + wdata_i=>op2_i, + + rdata_o=>dbus_result, + busy_o=>dbus_busy, + we_o=>dbus_we, + + dbus_cyc_o=>dbus_cyc_o, + dbus_stb_o=>dbus_stb_o, + dbus_we_o=>dbus_we_o, + dbus_sel_o=>dbus_sel_o, + dbus_ack_i=>dbus_ack_i, + dbus_adr_o=>dbus_adr_o, + dbus_dat_o=>dbus_dat_o, + dbus_dat_i=>dbus_dat_i + ); + +-- Result multiplexer + +result_mux_gen: for i in result_mux'range generate + result_mux(i)<=(alu_result(i) and alu_we) or + (op3_i(i) and loadop3_we) or + (dbus_result(i) and dbus_we); +end generate; + +result_valid<=alu_we or loadop3_we or dbus_we; + +-- Write destination register + +process (clk_i) is +begin + if rising_edge(clk_i) then + if can_execute='1' then + dst_reg<=dst_i; + end if; + end if; +end process; + +result_regaddr<=dst_i when can_execute='1' else dst_reg; + +sp_we_o<=result_valid; +sp_waddr_o<=result_regaddr; +sp_wdata_o<=result_mux; + +end architecture; Index: tags/1.2/rtl/lxp32_fetch.vhd =================================================================== --- tags/1.2/rtl/lxp32_fetch.vhd (nonexistent) +++ tags/1.2/rtl/lxp32_fetch.vhd (revision 10) @@ -0,0 +1,226 @@ +--------------------------------------------------------------------- +-- Instruction fetch +-- +-- Part of the LXP32 CPU +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- The first stage of the LXP32 pipeline. +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity lxp32_fetch is + generic( + START_ADDR: std_logic_vector(31 downto 0) + ); + port( + clk_i: in std_logic; + rst_i: in std_logic; + + lli_re_o: out std_logic; + lli_adr_o: out std_logic_vector(29 downto 0); + lli_dat_i: in std_logic_vector(31 downto 0); + lli_busy_i: in std_logic; + + word_o: out std_logic_vector(31 downto 0); + current_ip_o: out std_logic_vector(29 downto 0); + next_ip_o: out std_logic_vector(29 downto 0); + valid_o: out std_logic; + ready_i: in std_logic; + + jump_valid_i: in std_logic; + jump_dst_i: in std_logic_vector(29 downto 0); + jump_ready_o: out std_logic + ); +end entity; + +architecture rtl of lxp32_fetch is + +signal init: std_logic:='1'; +signal init_cnt: unsigned(7 downto 0):=(others=>'0'); + +signal fetch_addr: std_logic_vector(29 downto 0):=START_ADDR(31 downto 2); + +signal next_word: std_logic; +signal suppress_re: std_logic:='0'; +signal re: std_logic; +signal requested: std_logic:='0'; + +signal fifo_rst: std_logic; +signal fifo_we: std_logic; +signal fifo_din: std_logic_vector(31 downto 0); +signal fifo_re: std_logic; +signal fifo_dout: std_logic_vector(31 downto 0); +signal fifo_empty: std_logic; +signal fifo_full: std_logic; + +signal jr: std_logic:='0'; + +signal next_ip: std_logic_vector(fetch_addr'range); +signal current_ip: std_logic_vector(fetch_addr'range); + +begin + +-- INIT state machine (to initialize all registers) + +-- All CPU registers are expected to be zero-initialized after reset. +-- Since these registers are implemented as a RAM block, we perform +-- the initialization sequentially by generating "mov rN, 0" instructions +-- for each N from 0 to 255. +-- +-- With SRAM-based FPGAs, flip-flops and RAM blocks have deterministic +-- state after configuration. On these technologies the CPU can operate +-- without reset and the initialization procedure described above is not +-- needed. However, the initialization is still performed as usual when +-- external reset signal is asserted. + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' then + init<='0'; + init_cnt<=(others=>'0'); + else + if init='0' and ready_i='1' then + init_cnt<=init_cnt+1; + if init_cnt=X"FF" then + init<='1'; + end if; + end if; + end if; + end if; +end process; + +-- FETCH state machine + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' then + fetch_addr<=START_ADDR(31 downto 2); + requested<='0'; + jr<='0'; + suppress_re<='0'; + next_ip<=(others=>'-'); + else + jr<='0'; +-- Suppress LLI request if jump signal is active but will not be processed +-- in this cycle. Helps to reduce jump latency with high-latency LLI slaves. +-- Note: gating "re" with "jump_valid_i and not jr" asynchronously would +-- reduce jump latency even more, but we really want to avoid too large +-- clock-to-out on LLI outputs. + suppress_re<=jump_valid_i and not jr and not next_word; + if lli_busy_i='0' then + requested<=re and not (jump_valid_i and not jr); + end if; + if next_word='1' then +-- It's not immediately obvious why, but current_ip and next_ip will contain +-- the addresses of the current instruction and the next instruction to be +-- fetched, respectively, by the time the instruction is passed to the decode +-- stage. Basically, this is because when either the decoder or the IBUS +-- stalls, the fetch_addr counter will also stop incrementing. + next_ip<=fetch_addr; + current_ip<=next_ip; + if jump_valid_i='1' and jr='0' then + fetch_addr<=jump_dst_i; + jr<='1'; + else + fetch_addr<=std_logic_vector(unsigned(fetch_addr)+1); + end if; + end if; + end if; + end if; +end process; + +next_word<=(fifo_empty or ready_i) and not lli_busy_i and init; +re<=(fifo_empty or ready_i) and init and not suppress_re; +lli_re_o<=re; +lli_adr_o<=fetch_addr; + +jump_ready_o<=jr; + +-- Small instruction buffer + +fifo_rst<=rst_i or (jump_valid_i and not jr); +fifo_we<=requested and not lli_busy_i; +fifo_din<=lli_dat_i; +fifo_re<=ready_i and not fifo_empty; + +ubuf_inst: entity work.lxp32_ubuf(rtl) + generic map( + DATA_WIDTH=>32 + ) + port map( + clk_i=>clk_i, + rst_i=>fifo_rst, + + we_i=>fifo_we, + d_i=>fifo_din, + re_i=>fifo_re, + d_o=>fifo_dout, + + empty_o=>fifo_empty, + full_o=>fifo_full + ); + +next_ip_o<=next_ip; +current_ip_o<=current_ip; +word_o<=fifo_dout when init='1' else X"40"&std_logic_vector(init_cnt)&X"0000"; +valid_o<=not fifo_empty or not init; + +-- Note: the following code contains a few simulation-only assertions +-- to check that current_ip and next_ip signals, used in procedure calls +-- and interrupts, are correct. +-- This code should be ignored by a synthesizer since it doesn't drive +-- any signals, but we also surround it by metacomments, just in case. + +-- synthesis translate_off + +process (clk_i) is + type Pair is record + addr: std_logic_vector(fetch_addr'range); + data: std_logic_vector(31 downto 0); + end record; + type Pairs is array (7 downto 0) of Pair; + variable buf: Pairs; + variable count: integer range buf'range:=0; + variable current_pair: Pair; +begin + if rising_edge(clk_i) then + if fifo_rst='1' then -- jump + count:=0; + elsif fifo_we='1' then -- LLI returned data + current_pair.data:=fifo_din; + buf(count):=current_pair; + count:=count+1; + end if; + if re='1' and lli_busy_i='0' then -- data requested + current_pair.addr:=fetch_addr; + end if; + if fifo_empty='0' and fifo_rst='0' then -- fetch output is valid + assert count>0 + report "Fetch: buffer should be empty" + severity failure; + assert buf(0).data=fifo_dout + report "Fetch: incorrect data" + severity failure; + assert buf(0).addr=current_ip + report "Fetch: incorrect current_ip" + severity failure; + assert std_logic_vector(unsigned(buf(0).addr)+1)=next_ip + report "Fetch: incorrect next_ip" + severity failure; + if ready_i='1' then + buf(buf'high-1 downto 0):=buf(buf'high downto 1); -- we don't care about the highest item + count:=count-1; + end if; + end if; + end if; +end process; + +-- synthesis translate_on + +end architecture; Index: tags/1.2/rtl/lxp32_icache.vhd =================================================================== --- tags/1.2/rtl/lxp32_icache.vhd (nonexistent) +++ tags/1.2/rtl/lxp32_icache.vhd (revision 10) @@ -0,0 +1,289 @@ +--------------------------------------------------------------------- +-- Instruction cache +-- +-- Part of the LXP32 CPU +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- A simple single-page buffer providing both caching and +-- prefetching capabilities. Useful for high-latency memory, +-- such as external SDRAM. +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity lxp32_icache is + generic( + BURST_SIZE: integer; + PREFETCH_SIZE: integer + ); + port( + clk_i: in std_logic; + rst_i: in std_logic; + + lli_re_i: in std_logic; + lli_adr_i: in std_logic_vector(29 downto 0); + lli_dat_o: out std_logic_vector(31 downto 0); + lli_busy_o: out std_logic; + + wbm_cyc_o: out std_logic; + wbm_stb_o: out std_logic; + wbm_cti_o: out std_logic_vector(2 downto 0); + wbm_bte_o: out std_logic_vector(1 downto 0); + wbm_ack_i: in std_logic; + wbm_adr_o: out std_logic_vector(29 downto 0); + wbm_dat_i: in std_logic_vector(31 downto 0) + ); +end entity; + +architecture rtl of lxp32_icache is + +signal lli_adr_reg: std_logic_vector(lli_adr_i'range); +signal lli_adr_mux: std_logic_vector(lli_adr_i'range); + +signal ram_waddr: std_logic_vector(7 downto 0); +signal ram_raddr: std_logic_vector(7 downto 0); +signal ram_re: std_logic; +signal ram_we: std_logic; + +signal read_base: unsigned(21 downto 0); +signal read_offset: unsigned(7 downto 0); + +signal init: std_logic:='0'; +signal burst1: std_logic; +signal terminate_burst: std_logic; +signal near_miss: std_logic:='0'; +signal prefetch_distance: unsigned(7 downto 0); +signal wrap_cnt: integer range 0 to 3:=0; +signal burst_cnt: integer range 0 to BURST_SIZE:=0; +signal wb_stb: std_logic:='0'; +signal wb_cti: std_logic_vector(2 downto 0); + +-- Note: the following five signals are zero-initialized for +-- simulation only, to suppress warnings from numeric_std. +-- This initialization is not required for synthesis. + +signal current_base: unsigned(21 downto 0):=(others=>'0'); +signal current_offset: unsigned(7 downto 0):=(others=>'0'); +signal prev_base: unsigned(21 downto 0):=(others=>'0'); +signal next_base: unsigned(21 downto 0):=(others=>'0'); +signal start_offset: unsigned(7 downto 0):=(others=>'0'); + +signal hitc: std_logic; +signal hitp: std_logic; +signal miss: std_logic:='0'; + +begin + +assert PREFETCH_SIZE>=4 + report "PREFETCH_SIZE cannot be less than 4" + severity failure; +assert BURST_SIZE>=4 + report "BURST_SIZE cannot be less than 4" + severity failure; +assert PREFETCH_SIZE+BURST_SIZE<=128 + report "PREFETCH_SIZE and BURST_SIZE combined cannot be greater than 128" + severity failure; + + +process (clk_i) is +begin + if rising_edge(clk_i) then + if miss='0' then + lli_adr_reg<=lli_adr_i; + end if; + end if; +end process; + +lli_adr_mux<=lli_adr_i when miss='0' else lli_adr_reg; + +read_base<=unsigned(lli_adr_mux(29 downto 8)); +read_offset<=unsigned(lli_adr_mux(7 downto 0)); + +-- Cache RAM + +ram_waddr<=std_logic_vector(current_offset); +ram_raddr<=std_logic_vector(read_offset); +ram_we<=wb_stb and wbm_ack_i; +ram_re<=lli_re_i or miss; + +ram_inst: entity work.lxp32_ram256x32(rtl) + port map( + clk_i=>clk_i, + + we_i=>ram_we, + waddr_i=>ram_waddr, + wdata_i=>wbm_dat_i, + + re_i=>ram_re, + raddr_i=>ram_raddr, + rdata_o=>lli_dat_o + ); + +-- Determine hit/miss + +-- This cache uses a single ring buffer. Address in buffer corresponds +-- to the lower 8 bits of the full address. The part of the buffer that +-- is higher than current_offset represents a previous block ("p"), the +-- other part represents a current block ("c"). + +hitc<='1' when read_base=current_base and read_offset=start_offset) or + wrap_cnt=2 or wrap_cnt=3) else '0'; + +hitp<='1' when read_base=prev_base and read_offset>current_offset and + ((wrap_cnt=2 and read_offset>=start_offset) or + wrap_cnt=3) else '0'; + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' then + miss<='0'; + else + if hitc='0' and hitp='0' and ram_re='1' then + miss<='1'; + else + miss<='0'; + end if; + end if; + end if; +end process; + +lli_busy_o<=miss; + +-- Set INIT flag when the first lli_re_i signal is detected + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' then + init<='0'; + elsif lli_re_i='1' then + init<='1'; + end if; + end if; +end process; + +-- Fill cache + +prefetch_distance<=current_offset-read_offset; + +-- Note: "near_miss" signal prevents cache invalidation when difference +-- between the requested address and the currently fetched address +-- is too small (and, therefore, the requested data will be fetched soon +-- without invalidation). + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' then + near_miss<='0'; + elsif wrap_cnt>0 and read_offset-current_offset<=to_unsigned(BURST_SIZE/2,8) and + ((read_base=current_base and read_offset>=current_offset) or + (read_base=next_base and read_offset2 or burst1='0') and near_miss='0' else '0'; + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' then + burst_cnt<=0; + wb_stb<='0'; + wrap_cnt<=0; + wb_cti<=(others=>'-'); + burst1<='-'; + current_offset<=(others=>'-'); + start_offset<=(others=>'-'); + current_base<=(others=>'-'); + next_base<=(others=>'-'); + prev_base<=(others=>'-'); + + -- To suppress numeric_std warnings + -- synthesis translate_off + current_offset<=(others=>'0'); + start_offset<=(others=>'0'); + current_base<=(others=>'0'); + next_base<=(others=>'0'); + prev_base<=(others=>'0'); + -- synthesis translate_on + else + if burst_cnt=0 and init='1' then + if miss='1' and near_miss='0' then + wb_stb<='1'; + wb_cti<="010"; + current_offset<=read_offset; + start_offset<=read_offset; + current_base<=read_base; + next_base<=read_base+1; + burst_cnt<=1; + burst1<='1'; + wrap_cnt<=1; + elsif prefetch_distance'0'); + +type state_type is (Ready,Requested,WaitForExit); +signal state: state_type:=Ready; + +signal pending_interrupts: std_logic_vector(irq_i'range):=(others=>'0'); + +signal interrupt_valid: std_logic:='0'; + +signal interrupts_enabled: std_logic_vector(7 downto 0):=(others=>'0'); +signal interrupts_blocked: std_logic_vector(7 downto 0):=(others=>'0'); + +begin + +-- Note: "disabled" interrupts (i.e. for which interrupts_enabled_i(i)='0') +-- are ignored completely, meaning that the interrupt handler won't be +-- called even if the interrupt is enabled later. Conversely, "blocked" +-- interrupts are registered, but their handlers are not called until they +-- are unblocked. + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' then + irq_reg<=(others=>'0'); + pending_interrupts<=(others=>'0'); + state<=Ready; + interrupt_valid<='0'; + interrupt_vector_o<=(others=>'-'); + else + irq_reg<=irq_i; + + pending_interrupts<=(pending_interrupts or + (irq_i and not irq_reg)) and + interrupts_enabled; + + case state is + when Ready => + for i in pending_interrupts'reverse_range loop -- lower interrupts have priority + if pending_interrupts(i)='1' and interrupts_blocked(i)='0' then + pending_interrupts(i)<='0'; + interrupt_valid<='1'; + interrupt_vector_o<=std_logic_vector(to_unsigned(i,3)); + state<=Requested; + exit; + end if; + end loop; + when Requested => + if interrupt_ready_i='1' then + interrupt_valid<='0'; + state<=WaitForExit; + end if; + when WaitForExit => + if interrupt_return_i='1' then + state<=Ready; + end if; + end case; + end if; + end if; +end process; + +interrupt_valid_o<=interrupt_valid; + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' then + interrupts_enabled<=(others=>'0'); + interrupts_blocked<=(others=>'0'); + elsif sp_we_i='1' and sp_waddr_i=X"FC" then + interrupts_enabled<=sp_wdata_i(7 downto 0); + interrupts_blocked<=sp_wdata_i(15 downto 8); + end if; + end if; +end process; + +end architecture; Index: tags/1.2/rtl/lxp32_mul16x16.vhd =================================================================== --- tags/1.2/rtl/lxp32_mul16x16.vhd (nonexistent) +++ tags/1.2/rtl/lxp32_mul16x16.vhd (revision 10) @@ -0,0 +1,36 @@ +--------------------------------------------------------------------- +-- A basic parallel 16x16 multiplier with an output register +-- +-- Part of the LXP32 CPU +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- A straightforward behavioral description. Can be replaced +-- with a library component wrapper if needed. +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity lxp32_mul16x16 is + port( + clk_i: in std_logic; + a_i: in std_logic_vector(15 downto 0); + b_i: in std_logic_vector(15 downto 0); + p_o: out std_logic_vector(31 downto 0) + ); +end entity; + +architecture rtl of lxp32_mul16x16 is + +begin + +process (clk_i) is +begin + if rising_edge(clk_i) then + p_o<=std_logic_vector(unsigned(a_i)*unsigned(b_i)); + end if; +end process; + +end architecture; Index: tags/1.2/rtl/lxp32_mul_dsp.vhd =================================================================== --- tags/1.2/rtl/lxp32_mul_dsp.vhd (nonexistent) +++ tags/1.2/rtl/lxp32_mul_dsp.vhd (revision 10) @@ -0,0 +1,82 @@ +--------------------------------------------------------------------- +-- DSP multiplier +-- +-- Part of the LXP32 CPU +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- This multiplier is designed for technologies that provide fast +-- 16x16 multipliers, including most modern FPGA families. One +-- multiplication takes 2 cycles. +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity lxp32_mul_dsp is + port( + clk_i: in std_logic; + rst_i: in std_logic; + ce_i: in std_logic; + op1_i: in std_logic_vector(31 downto 0); + op2_i: in std_logic_vector(31 downto 0); + ce_o: out std_logic; + result_o: out std_logic_vector(31 downto 0) + ); +end entity; + +architecture rtl of lxp32_mul_dsp is + +signal pp00: std_logic_vector(31 downto 0); +signal pp01: std_logic_vector(31 downto 0); +signal pp10: std_logic_vector(31 downto 0); + +signal product: unsigned(31 downto 0); + +signal ceo: std_logic:='0'; + +begin + +mul00_inst: entity work.lxp32_mul16x16 + port map( + clk_i=>clk_i, + a_i=>op1_i(15 downto 0), + b_i=>op2_i(15 downto 0), + p_o=>pp00 + ); + +mul01_inst: entity work.lxp32_mul16x16 + port map( + clk_i=>clk_i, + a_i=>op1_i(15 downto 0), + b_i=>op2_i(31 downto 16), + p_o=>pp01 + ); + +mul10_inst: entity work.lxp32_mul16x16 + port map( + clk_i=>clk_i, + a_i=>op1_i(31 downto 16), + b_i=>op2_i(15 downto 0), + p_o=>pp10 + ); + +product(31 downto 16)<=unsigned(pp00(31 downto 16))+unsigned(pp01(15 downto 0))+unsigned(pp10(15 downto 0)); +product(15 downto 0)<=unsigned(pp00(15 downto 0)); +result_o<=std_logic_vector(product); + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' then + ceo<='0'; + else + ceo<=ce_i; + end if; + end if; +end process; + +ce_o<=ceo; + +end architecture; Index: tags/1.2/rtl/lxp32_mul_opt.vhd =================================================================== --- tags/1.2/rtl/lxp32_mul_opt.vhd (nonexistent) +++ tags/1.2/rtl/lxp32_mul_opt.vhd (revision 10) @@ -0,0 +1,168 @@ +--------------------------------------------------------------------- +-- Optimized multiplier +-- +-- Part of the LXP32 CPU +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- This multiplier is designed for technologies that don't provide +-- fast 16x16 multipliers. One multiplication takes 6 cycles. +-- +-- The multiplication algorithm is based on carry-save accumulation +-- of partial products. +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity lxp32_mul_opt is + port( + clk_i: in std_logic; + rst_i: in std_logic; + ce_i: in std_logic; + op1_i: in std_logic_vector(31 downto 0); + op2_i: in std_logic_vector(31 downto 0); + ce_o: out std_logic; + result_o: out std_logic_vector(31 downto 0) + ); +end entity; + +architecture rtl of lxp32_mul_opt is + +function csa_sum(a: unsigned; b: unsigned; c: unsigned; n: integer) return unsigned is + variable r: unsigned(n-1 downto 0); +begin + for i in r'range loop + r(i):=a(i) xor b(i) xor c(i); + end loop; + return r; +end function; + +function csa_carry(a: unsigned; b: unsigned; c: unsigned; n: integer) return unsigned is + variable r: unsigned(n-1 downto 0); +begin + for i in r'range loop + r(i):=(a(i) and b(i)) or (a(i) and c(i)) or (b(i) and c(i)); + end loop; + return r&"0"; +end function; + +signal reg1: unsigned(op1_i'range); +signal reg2: unsigned(op2_i'range); + +type pp_type is array (7 downto 0) of unsigned(31 downto 0); +signal pp: pp_type; + +type pp_sum_type is array (7 downto 0) of unsigned(31 downto 0); +signal pp_sum: pp_sum_type; + +type pp_carry_type is array (7 downto 0) of unsigned(32 downto 0); +signal pp_carry: pp_carry_type; + +signal acc_sum: unsigned(31 downto 0); +signal acc_carry: unsigned(31 downto 0); + +signal cnt: integer range 0 to 4:=0; + +signal result: std_logic_vector(result_o'range); +signal ceo: std_logic:='0'; + +begin + +-- Calculate 8 partial products in parallel + +pp_gen: for i in pp'range generate + pp(i)<=shift_left(reg1,i) when reg2(i)='1' else (others=>'0'); +end generate; + +-- Add partial products to the accumulator using carry-save adder tree + +pp_sum(0)<=csa_sum(pp(0),pp(1),pp(2),32); +pp_carry(0)<=csa_carry(pp(0),pp(1),pp(2),32); + +pp_sum(1)<=csa_sum(pp(3),pp(4),pp(5),32); +pp_carry(1)<=csa_carry(pp(3),pp(4),pp(5),32); + +pp_sum(2)<=csa_sum(pp(6),pp(7),acc_sum,32); +pp_carry(2)<=csa_carry(pp(6),pp(7),acc_sum,32); + +pp_sum(3)<=csa_sum(pp_sum(0),pp_carry(0),pp_sum(1),32); +pp_carry(3)<=csa_carry(pp_sum(0),pp_carry(0),pp_sum(1),32); + +pp_sum(4)<=csa_sum(pp_carry(1),pp_sum(2),pp_carry(2),32); +pp_carry(4)<=csa_carry(pp_carry(1),pp_sum(2),pp_carry(2),32); + +pp_sum(5)<=csa_sum(pp_sum(3),pp_carry(3),pp_sum(4),32); +pp_carry(5)<=csa_carry(pp_sum(3),pp_carry(3),pp_sum(4),32); + +pp_sum(6)<=csa_sum(pp_sum(5),pp_carry(5),pp_carry(4),32); +pp_carry(6)<=csa_carry(pp_sum(5),pp_carry(5),pp_carry(4),32); + +pp_sum(7)<=csa_sum(pp_sum(6),pp_carry(6),acc_carry,32); +pp_carry(7)<=csa_carry(pp_sum(6),pp_carry(6),acc_carry,32); + +-- Multiplier state machine + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' then + ceo<='0'; + cnt<=0; + reg1<=(others=>'-'); + reg2<=(others=>'-'); + acc_sum<=(others=>'-'); + acc_carry<=(others=>'-'); + else + if cnt=1 then + ceo<='1'; + else + ceo<='0'; + end if; + + if ce_i='1' then + cnt<=4; + reg1<=unsigned(op1_i); + reg2<=unsigned(op2_i); + acc_sum<=(others=>'0'); + acc_carry<=(others=>'0'); + else + acc_sum<=pp_sum(7); + acc_carry<=pp_carry(7)(acc_carry'range); + reg1<=reg1(reg1'high-8 downto 0)&X"00"; + reg2<=X"00"®2(reg2'high downto 8); + if cnt>0 then + cnt<=cnt-1; + end if; + end if; + end if; + end if; +end process; + +result<=std_logic_vector(acc_sum+acc_carry); + +result_o<=result; +ce_o<=ceo; + +-- A simulation-time multiplication check + +-- synthesis translate_off + +process (clk_i) is + variable p: unsigned(op1_i'length+op2_i'length-1 downto 0); +begin + if rising_edge(clk_i) then + if ce_i='1' then + p:=unsigned(op1_i)*unsigned(op2_i); + elsif ceo='1' then + assert result=std_logic_vector(p(result'range)) + report "Incorrect multiplication result" + severity failure; + end if; + end if; +end process; + +-- synthesis translate_on + +end architecture; Index: tags/1.2/rtl/lxp32_mul_seq.vhd =================================================================== --- tags/1.2/rtl/lxp32_mul_seq.vhd (nonexistent) +++ tags/1.2/rtl/lxp32_mul_seq.vhd (revision 10) @@ -0,0 +1,77 @@ +--------------------------------------------------------------------- +-- Sequential multiplier +-- +-- Part of the LXP32 CPU +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- The smallest possible multiplier. Implemented using +-- an accumulator. One multiplication takes 34 cycles. +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity lxp32_mul_seq is + port( + clk_i: in std_logic; + rst_i: in std_logic; + ce_i: in std_logic; + op1_i: in std_logic_vector(31 downto 0); + op2_i: in std_logic_vector(31 downto 0); + ce_o: out std_logic; + result_o: out std_logic_vector(31 downto 0) + ); +end entity; + +architecture rtl of lxp32_mul_seq is + +signal reg1: unsigned(op1_i'range); +signal reg2: unsigned(op2_i'range); +signal pp: unsigned(31 downto 0); +signal acc_sum: unsigned(31 downto 0); +signal cnt: integer range 0 to 32:=0; +signal ceo: std_logic:='0'; + +begin + +pp<=reg1 when reg2(0)='1' else (others=>'0'); + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' then + ceo<='0'; + cnt<=0; + reg1<=(others=>'-'); + reg2<=(others=>'-'); + acc_sum<=(others=>'-'); + else + if cnt=1 then + ceo<='1'; + else + ceo<='0'; + end if; + + if ce_i='1' then + cnt<=32; + reg1<=unsigned(op1_i); + reg2<=unsigned(op2_i); + acc_sum<=(others=>'0'); + else + acc_sum<=acc_sum+pp; + reg1<=reg1(reg1'high-1 downto 0)&"0"; + reg2<="0"®2(reg2'high downto 1); + if cnt>0 then + cnt<=cnt-1; + end if; + end if; + end if; + end if; +end process; + +result_o<=std_logic_vector(acc_sum); +ce_o<=ceo; + +end architecture; Index: tags/1.2/rtl/lxp32_ram256x32.vhd =================================================================== --- tags/1.2/rtl/lxp32_ram256x32.vhd (nonexistent) +++ tags/1.2/rtl/lxp32_ram256x32.vhd (revision 10) @@ -0,0 +1,70 @@ +--------------------------------------------------------------------- +-- Generic dual-port memory +-- +-- Part of the LXP32 CPU +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- Portable description of a dual-port memory block with one write +-- port. Major FPGA synthesis tools can infer on-chip block RAM +-- from this description. Can be replaced with a library component +-- wrapper if needed. +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity lxp32_ram256x32 is + port( + clk_i: in std_logic; + + we_i: in std_logic; + waddr_i: in std_logic_vector(7 downto 0); + wdata_i: in std_logic_vector(31 downto 0); + + re_i: in std_logic; + raddr_i: in std_logic_vector(7 downto 0); + rdata_o: out std_logic_vector(31 downto 0) + ); +end entity; + +architecture rtl of lxp32_ram256x32 is + +type ram_type is array(255 downto 0) of std_logic_vector(31 downto 0); +signal ram: ram_type:=(others=>(others=>'0')); -- zero-initialize for SRAM-based FPGAs + +attribute syn_ramstyle: string; +attribute syn_ramstyle of ram: signal is "no_rw_check"; +attribute ram_style: string; -- for Xilinx +attribute ram_style of ram: signal is "block"; + +begin + +-- Write port + +process (clk_i) is +begin + if rising_edge(clk_i) then + if we_i='1' then + ram(to_integer(unsigned(waddr_i)))<=wdata_i; + end if; + end if; +end process; + +-- Read port + +process (clk_i) is +begin + if rising_edge(clk_i) then + if re_i='1' then + if is_x(raddr_i) then -- to avoid numeric_std warnings during simulation + rdata_o<=(others=>'X'); + else + rdata_o<=ram(to_integer(unsigned(raddr_i))); + end if; + end if; + end if; +end process; + +end architecture; Index: tags/1.2/rtl/lxp32_scratchpad.vhd =================================================================== --- tags/1.2/rtl/lxp32_scratchpad.vhd (nonexistent) +++ tags/1.2/rtl/lxp32_scratchpad.vhd (revision 10) @@ -0,0 +1,93 @@ +--------------------------------------------------------------------- +-- Scratchpad +-- +-- Part of the LXP32 CPU +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- LXP32 register file implemented as a RAM block. Since we need +-- to read two registers simultaneously, the memory is duplicated. +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity lxp32_scratchpad is + port( + clk_i: in std_logic; + + raddr1_i: in std_logic_vector(7 downto 0); + rdata1_o: out std_logic_vector(31 downto 0); + raddr2_i: in std_logic_vector(7 downto 0); + rdata2_o: out std_logic_vector(31 downto 0); + + waddr_i: in std_logic_vector(7 downto 0); + we_i: in std_logic; + wdata_i: in std_logic_vector(31 downto 0) + ); +end entity; + +architecture rtl of lxp32_scratchpad is + +signal wdata_reg: std_logic_vector(wdata_i'range); +signal ram1_rdata: std_logic_vector(31 downto 0); +signal ram2_rdata: std_logic_vector(31 downto 0); + +signal ram1_collision: std_logic; +signal ram2_collision: std_logic; + +begin + +-- RAM 1 + +ram_inst1: entity work.lxp32_ram256x32(rtl) + port map( + clk_i=>clk_i, + + we_i=>we_i, + waddr_i=>waddr_i, + wdata_i=>wdata_i, + + re_i=>'1', + raddr_i=>raddr1_i, + rdata_o=>ram1_rdata + ); + +-- RAM 2 + +ram_inst2: entity work.lxp32_ram256x32(rtl) + port map( + clk_i=>clk_i, + + we_i=>we_i, + waddr_i=>waddr_i, + wdata_i=>wdata_i, + + re_i=>'1', + raddr_i=>raddr2_i, + rdata_o=>ram2_rdata + ); + +-- Read/write collision detection + +process (clk_i) is +begin + if rising_edge(clk_i) then + wdata_reg<=wdata_i; + if waddr_i=raddr1_i and we_i='1' then + ram1_collision<='1'; + else + ram1_collision<='0'; + end if; + if waddr_i=raddr2_i and we_i='1' then + ram2_collision<='1'; + else + ram2_collision<='0'; + end if; + end if; +end process; + +rdata1_o<=ram1_rdata when ram1_collision='0' else wdata_reg; +rdata2_o<=ram2_rdata when ram2_collision='0' else wdata_reg; + +end architecture; Index: tags/1.2/rtl/lxp32_shifter.vhd =================================================================== --- tags/1.2/rtl/lxp32_shifter.vhd (nonexistent) +++ tags/1.2/rtl/lxp32_shifter.vhd (revision 10) @@ -0,0 +1,99 @@ +--------------------------------------------------------------------- +-- Barrel shifter +-- +-- Part of the LXP32 CPU +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- Performs logical (unsigned) and arithmetic (signed) shifts +-- in both directions. Pipeline latency: 1 cycle. +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity lxp32_shifter is + port( + clk_i: in std_logic; + rst_i: in std_logic; + ce_i: in std_logic; + d_i: in std_logic_vector(31 downto 0); + s_i: in std_logic_vector(4 downto 0); + right_i: in std_logic; + sig_i: in std_logic; + ce_o: out std_logic; + d_o: out std_logic_vector(31 downto 0) + ); +end entity; + +architecture rtl of lxp32_shifter is + +signal data: std_logic_vector(d_i'range); +signal data_shifted: std_logic_vector(d_i'range); + +signal fill: std_logic; -- 0 for unsigned shifts, sign bit for signed ones +signal fill_v: std_logic_vector(3 downto 0); + +type cascades_type is array (4 downto 0) of std_logic_vector(d_i'range); +signal cascades: cascades_type; + +signal stage2_data: std_logic_vector(d_i'range); +signal stage2_s: std_logic_vector(s_i'range); +signal stage2_fill: std_logic; +signal stage2_fill_v: std_logic_vector(15 downto 0); +signal stage2_right: std_logic; + +signal ceo: std_logic:='0'; + +begin + +-- Internally, data are shifted in left direction. For right shifts +-- we reverse the argument's bit order + +data_gen: for i in data'range generate + data(i)<=d_i(i) when right_i='0' else d_i(d_i'high-i); +end generate; + +-- A set of cascaded shifters shifting by powers of two + +fill<=sig_i and data(0); +fill_v<=(others=>fill); + +cascades(0)<=data(30 downto 0)&fill_v(0) when s_i(0)='1' else data; +cascades(1)<=cascades(0)(29 downto 0)&fill_v(1 downto 0) when s_i(1)='1' else cascades(0); +cascades(2)<=cascades(1)(27 downto 0)&fill_v(3 downto 0) when s_i(2)='1' else cascades(1); + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' then + ceo<='0'; + stage2_data<=(others=>'-'); + stage2_s<=(others=>'-'); + stage2_fill<='-'; + stage2_right<='-'; + else + ceo<=ce_i; + stage2_data<=cascades(2); + stage2_s<=s_i; + stage2_fill<=fill; + stage2_right<=right_i; + end if; + end if; +end process; + +stage2_fill_v<=(others=>stage2_fill); + +cascades(3)<=stage2_data(23 downto 0)&stage2_fill_v(7 downto 0) when stage2_s(3)='1' else stage2_data; +cascades(4)<=cascades(3)(15 downto 0)&stage2_fill_v(15 downto 0) when stage2_s(4)='1' else cascades(3); + +-- Reverse bit order back, if needed + +data_shifted_gen: for i in data_shifted'range generate + data_shifted(i)<=cascades(4)(i) when stage2_right='0' else cascades(4)(cascades(4)'high-i); +end generate; + +d_o<=data_shifted; +ce_o<=ceo; + +end architecture; Index: tags/1.2/rtl/lxp32_ubuf.vhd =================================================================== --- tags/1.2/rtl/lxp32_ubuf.vhd (nonexistent) +++ tags/1.2/rtl/lxp32_ubuf.vhd (revision 10) @@ -0,0 +1,84 @@ +--------------------------------------------------------------------- +-- Microbuffer +-- +-- Part of the LXP32 CPU +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- A small buffer with a FIFO-like interface, implemented +-- using registers. +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity lxp32_ubuf is + generic( + DATA_WIDTH: integer + ); + port( + clk_i: in std_logic; + rst_i: in std_logic; + + we_i: in std_logic; + d_i: in std_logic_vector(DATA_WIDTH-1 downto 0); + re_i: in std_logic; + d_o: out std_logic_vector(DATA_WIDTH-1 downto 0); + + empty_o: out std_logic; + full_o: out std_logic + ); +end entity; + +architecture rtl of lxp32_ubuf is + +signal we: std_logic; +signal re: std_logic; + +signal empty: std_logic:='1'; +signal full: std_logic:='0'; + +type regs_type is array (1 downto 0) of std_logic_vector(DATA_WIDTH-1 downto 0); +signal regs: regs_type; +signal regs_mux: regs_type; + +begin + +we<=we_i and not full; +re<=re_i and not empty; + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' then + empty<='1'; + full<='0'; + regs<=(others=>(others=>'-')); + else + if re='0' then + regs(0)<=regs_mux(0); + else + regs(0)<=regs_mux(1); + end if; + + regs(1)<=regs_mux(1); + + if we='1' and re='0' then + empty<='0'; + full<=not empty; + elsif we='0' and re='1' then + empty<=not full; + full<='0'; + end if; + end if; + end if; +end process; + +regs_mux(0)<=regs(0) when we='0' or empty='0' else d_i; +regs_mux(1)<=regs(1) when we='0' or empty='1' else d_i; + +d_o<=regs(0); +empty_o<=empty; +full_o<=full; + +end architecture; Index: tags/1.2/rtl/lxp32c_top.vhd =================================================================== --- tags/1.2/rtl/lxp32c_top.vhd (nonexistent) +++ tags/1.2/rtl/lxp32c_top.vhd (revision 10) @@ -0,0 +1,122 @@ +--------------------------------------------------------------------- +-- LXP32C CPU top-level module (C-series, with instruction cache) +-- +-- Part of the LXP32 CPU +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- This version uses Wishbone B3 interface for the instruction bus +-- (IBUS). It is designed for high-latency program memory, such as +-- external SDRAM chips. +-- +-- Parameters: +-- DBUS_RMW: Use RMW cycle instead of SEL_O() signal +-- for byte-granular access to data bus +-- DIVIDER_EN: enable divider +-- IBUS_BURST_SIZE: size of the burst +-- IBUS_PREFETCH_SIZE: initiate read burst if number of words +-- left in the buffer is less than specified +-- MUL_ARCH: multiplier architecture ("dsp", "opt" +-- or "seq") +-- START_ADDR: address in program memory where execution +-- starts +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity lxp32c_top is + generic( + DBUS_RMW: boolean:=false; + DIVIDER_EN: boolean:=true; + IBUS_BURST_SIZE: integer:=16; + IBUS_PREFETCH_SIZE: integer:=32; + MUL_ARCH: string:="dsp"; + START_ADDR: std_logic_vector(31 downto 0):=(others=>'0') + ); + port( + clk_i: in std_logic; + rst_i: in std_logic; + + ibus_cyc_o: out std_logic; + ibus_stb_o: out std_logic; + ibus_cti_o: out std_logic_vector(2 downto 0); + ibus_bte_o: out std_logic_vector(1 downto 0); + ibus_ack_i: in std_logic; + ibus_adr_o: out std_logic_vector(29 downto 0); + ibus_dat_i: in std_logic_vector(31 downto 0); + + dbus_cyc_o: out std_logic; + dbus_stb_o: out std_logic; + dbus_we_o: out std_logic; + dbus_sel_o: out std_logic_vector(3 downto 0); + dbus_ack_i: in std_logic; + dbus_adr_o: out std_logic_vector(31 downto 2); + dbus_dat_o: out std_logic_vector(31 downto 0); + dbus_dat_i: in std_logic_vector(31 downto 0); + + irq_i: in std_logic_vector(7 downto 0) + ); +end entity; + +architecture rtl of lxp32c_top is + +signal lli_re: std_logic; +signal lli_adr: std_logic_vector(29 downto 0); +signal lli_dat: std_logic_vector(31 downto 0); +signal lli_busy: std_logic; + +begin + +cpu_inst: entity work.lxp32_cpu(rtl) + generic map( + DBUS_RMW=>DBUS_RMW, + DIVIDER_EN=>DIVIDER_EN, + MUL_ARCH=>MUL_ARCH, + START_ADDR=>START_ADDR + ) + port map( + clk_i=>clk_i, + rst_i=>rst_i, + + lli_re_o=>lli_re, + lli_adr_o=>lli_adr, + lli_dat_i=>lli_dat, + lli_busy_i=>lli_busy, + + dbus_cyc_o=>dbus_cyc_o, + dbus_stb_o=>dbus_stb_o, + dbus_we_o=>dbus_we_o, + dbus_sel_o=>dbus_sel_o, + dbus_ack_i=>dbus_ack_i, + dbus_adr_o=>dbus_adr_o, + dbus_dat_o=>dbus_dat_o, + dbus_dat_i=>dbus_dat_i, + + irq_i=>irq_i + ); + +icache_inst: entity work.lxp32_icache(rtl) + generic map( + BURST_SIZE=>IBUS_BURST_SIZE, + PREFETCH_SIZE=>IBUS_PREFETCH_SIZE + ) + port map( + clk_i=>clk_i, + rst_i=>rst_i, + + lli_re_i=>lli_re, + lli_adr_i=>lli_adr, + lli_dat_o=>lli_dat, + lli_busy_o=>lli_busy, + + wbm_cyc_o=>ibus_cyc_o, + wbm_stb_o=>ibus_stb_o, + wbm_cti_o=>ibus_cti_o, + wbm_bte_o=>ibus_bte_o, + wbm_ack_i=>ibus_ack_i, + wbm_adr_o=>ibus_adr_o, + wbm_dat_i=>ibus_dat_i + ); + +end architecture; Index: tags/1.2/rtl/lxp32u_top.vhd =================================================================== --- tags/1.2/rtl/lxp32u_top.vhd (nonexistent) +++ tags/1.2/rtl/lxp32u_top.vhd (revision 10) @@ -0,0 +1,86 @@ +--------------------------------------------------------------------- +-- LXP32U CPU top-level module (U-series, without instruction cache) +-- +-- Part of the LXP32 CPU +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- This version uses a Low Latency Interface for the instruction bus +-- (IBUS). It is designed for low-latency slaves such as on-chip +-- RAM blocks. +-- +-- Parameters: +-- DBUS_RMW: Use RMW cycle instead of SEL_O() signal +-- for byte-granular access to data bus +-- DIVIDER_EN: enable divider +-- MUL_ARCH: multiplier architecture ("dsp", "opt" +-- or "seq") +-- START_ADDR: address in program memory where execution +-- starts +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity lxp32u_top is + generic( + DBUS_RMW: boolean:=false; + DIVIDER_EN: boolean:=true; + MUL_ARCH: string:="dsp"; + START_ADDR: std_logic_vector(31 downto 0):=(others=>'0') + ); + port( + clk_i: in std_logic; + rst_i: in std_logic; + + lli_re_o: out std_logic; + lli_adr_o: out std_logic_vector(29 downto 0); + lli_dat_i: in std_logic_vector(31 downto 0); + lli_busy_i: in std_logic; + + dbus_cyc_o: out std_logic; + dbus_stb_o: out std_logic; + dbus_we_o: out std_logic; + dbus_sel_o: out std_logic_vector(3 downto 0); + dbus_ack_i: in std_logic; + dbus_adr_o: out std_logic_vector(31 downto 2); + dbus_dat_o: out std_logic_vector(31 downto 0); + dbus_dat_i: in std_logic_vector(31 downto 0); + + irq_i: in std_logic_vector(7 downto 0) + ); +end entity; + +architecture rtl of lxp32u_top is + +begin + +cpu_inst: entity work.lxp32_cpu(rtl) + generic map( + DBUS_RMW=>DBUS_RMW, + DIVIDER_EN=>DIVIDER_EN, + MUL_ARCH=>MUL_ARCH, + START_ADDR=>START_ADDR + ) + port map( + clk_i=>clk_i, + rst_i=>rst_i, + + lli_re_o=>lli_re_o, + lli_adr_o=>lli_adr_o, + lli_dat_i=>lli_dat_i, + lli_busy_i=>lli_busy_i, + + dbus_cyc_o=>dbus_cyc_o, + dbus_stb_o=>dbus_stb_o, + dbus_we_o=>dbus_we_o, + dbus_sel_o=>dbus_sel_o, + dbus_ack_i=>dbus_ack_i, + dbus_adr_o=>dbus_adr_o, + dbus_dat_o=>dbus_dat_o, + dbus_dat_i=>dbus_dat_i, + + irq_i=>irq_i + ); + +end architecture; Index: tags/1.2/tools/.gitignore =================================================================== --- tags/1.2/tools/.gitignore (nonexistent) +++ tags/1.2/tools/.gitignore (revision 10) @@ -0,0 +1,2 @@ +/bin +/build Index: tags/1.2/tools/bin/lxp32asm.exe =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2/tools/bin/lxp32asm.exe =================================================================== --- tags/1.2/tools/bin/lxp32asm.exe (nonexistent) +++ tags/1.2/tools/bin/lxp32asm.exe (revision 10)
tags/1.2/tools/bin/lxp32asm.exe Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2/tools/bin/lxp32dump.exe =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2/tools/bin/lxp32dump.exe =================================================================== --- tags/1.2/tools/bin/lxp32dump.exe (nonexistent) +++ tags/1.2/tools/bin/lxp32dump.exe (revision 10)
tags/1.2/tools/bin/lxp32dump.exe Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2/tools/bin/wigen.exe =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2/tools/bin/wigen.exe =================================================================== --- tags/1.2/tools/bin/wigen.exe (nonexistent) +++ tags/1.2/tools/bin/wigen.exe (revision 10)
tags/1.2/tools/bin/wigen.exe Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2/tools/src/CMakeLists.txt =================================================================== --- tags/1.2/tools/src/CMakeLists.txt (nonexistent) +++ tags/1.2/tools/src/CMakeLists.txt (revision 10) @@ -0,0 +1,50 @@ +cmake_minimum_required(VERSION 3.3.0) +project(lxp32tools) + +# Examine environment + +if(CMAKE_C_COMPILER_ID STREQUAL GNU OR CMAKE_C_COMPILER_ID STREQUAL Clang) + set(GNU_SYNTAX TRUE) +endif() + +# Set default install prefix if not manually set by the user + +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${PROJECT_SOURCE_DIR}/../bin" CACHE PATH "Install prefix" FORCE) +endif() + +message("Install prefix: ${CMAKE_INSTALL_PREFIX}") + +# Enable C++11 + +set(CMAKE_CXX_STANDARD 11) + +# Set up warning level for GCC/Clang + +if(GNU_SYNTAX) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pedantic -Wall -Wextra") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic -Wall -Wextra") +endif() + +# On Windows, link runtime statically + +if(WIN32) + if(GNU_SYNTAX) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static") + elseif(MSVC) + foreach(flag_var + CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE + CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO + CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE + CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO + ) + string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") + endforeach(flag_var) + endif() +endif() + +# Build targets + +add_subdirectory(lxp32asm) +add_subdirectory(lxp32dump) +add_subdirectory(wigen) Index: tags/1.2/tools/src/lxp32asm/CMakeLists.txt =================================================================== --- tags/1.2/tools/src/lxp32asm/CMakeLists.txt (nonexistent) +++ tags/1.2/tools/src/lxp32asm/CMakeLists.txt (revision 10) @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 3.3.0) + +add_executable(lxp32asm assembler.cpp linkableobject.cpp linker.cpp main.cpp outputwriter.cpp utils.cpp) + +if(MSVC) +# Make the program expand wildcard command-line arguments + set_target_properties(lxp32asm PROPERTIES LINK_FLAGS "setargv.obj") +endif() + +# Install + +install(TARGETS lxp32asm DESTINATION .) Index: tags/1.2/tools/src/lxp32asm/assembler.cpp =================================================================== --- tags/1.2/tools/src/lxp32asm/assembler.cpp (nonexistent) +++ tags/1.2/tools/src/lxp32asm/assembler.cpp (revision 10) @@ -0,0 +1,971 @@ +/* + * Copyright (c) 2016 by Alex I. Kuznetsov. + * + * Part of the LXP32 CPU IP core. + * + * This module implements members of the Assembler class. + */ + +#include "assembler.h" +#include "utils.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void Assembler::processFile(const std::string &filename) { + auto nativePath=Utils::normalizeSeparators(filename); + auto pos=nativePath.find_last_of('/'); + if(pos!=std::string::npos) nativePath=filename.substr(pos+1); + _obj.setName(nativePath); + + _line=0; + _state=Initial; + _currentFileName=filename; + processFileRecursive(filename); + + if(!_currentLabels.empty()) + throw std::runtime_error("Symbol definition must be followed by an instruction or data definition statement"); + + if(!_sectionEnabled.empty()) + throw std::runtime_error("#endif expected"); + +// Examine symbol table + for(auto const &sym: _obj.symbols()) { + if(sym.second.type==LinkableObject::Unknown&&!sym.second.refs.empty()) { + std::ostringstream msg; + msg<<"Undefined symbol \""+sym.first+"\""; + msg<<" (referenced from "<=str.size()) throw std::runtime_error("Unexpected end of line"); + ch=str[i]; + if(ch=='/') i=str.size(); // skip the rest of the line + else if(ch=='*') _state=BlockComment; + else throw std::runtime_error(std::string("Unexpected character: \"")+ch+"\""); + } + else throw std::runtime_error(std::string("Unexpected character: \"")+ch+"\""); + break; + case Word: + if(std::isalnum(ch)||ch=='_'||ch=='@'||ch=='+'||ch=='-') word+=ch; + else { + i--; + _state=Initial; + tokenList.push_back(std::move(word)); + } + break; + case StringLiteral: + if(ch=='\\') { + if(++i>=str.size()) throw std::runtime_error("Unexpected end of line"); + ch=str[i]; + if(ch=='\\') word.push_back('\\'); + else if(ch=='\"') word.push_back('\"'); + else if(ch=='\'') word.push_back('\''); + else if(ch=='t') word.push_back('\t'); + else if(ch=='n') word.push_back('\n'); + else if(ch=='r') word.push_back('\r'); + else if(ch=='x') { // hexadecimal sequence can be 1-2 digit long + std::string seq; + if(i+1(std::stoul(seq,nullptr,16))); + } + catch(std::exception &) { + throw std::runtime_error("Ill-formed escape sequence"); + } + i+=seq.size(); + } + else if(Utils::isoctdigit(ch)) { // octal sequence can be 1-3 digit long + std::string seq(1,ch); + if(i+1255) throw std::runtime_error("Octal value is out of range"); + word.push_back(static_cast(value)); + + i+=seq.size()-1; + } + else throw std::runtime_error(std::string("Unknown escape sequence: \"\\")+ch+"\""); + } + else if(ch=='\"') { + word.push_back('\"'); + tokenList.push_back(std::move(word)); + _state=Initial; + } + else word.push_back(ch); + break; + case BlockComment: + if(ch=='*') { + if(++i>=str.size()) break; + ch=str[i]; + if(ch=='/') _state=Initial; + else i--; + } + break; + } + } + + if(_state==StringLiteral) throw std::runtime_error("Unexpected end of line"); + if(_state==Word) tokenList.push_back(std::move(word)); // store last word + if(_state!=BlockComment) _state=Initial; // reset state if not in block comment + + return tokenList; +} + +void Assembler::expand(TokenList &list) { + TokenList newlist; +// Perform macro substitution + for(auto &token: list) { + auto it=_macros.find(token); + bool substitute=false; + if(it!=_macros.end()) { + substitute=true; +// Don't substitute macros for a second token in certain directives + if(newlist.size()==1) { + if(newlist[0]=="#define") substitute=false; + else if(newlist[0]=="#ifdef") substitute=false; + else if(newlist[0]=="#ifndef") substitute=false; + } + else if(newlist.size()==3&&newlist[1]==":") { + if(newlist[2]=="#define") substitute=false; + else if(newlist[2]=="#ifdef") substitute=false; + else if(newlist[2]=="#ifndef") substitute=false; + } + } + + if(substitute) { + for(auto const &replace: it->second) newlist.push_back(replace); + } + else newlist.push_back(std::move(token)); + } + list=std::move(newlist); +} + +void Assembler::elaborate(TokenList &list) { + if(list.empty()) return; + +// Process label (if present) + if(list.size()>=2&&list[1]==":") { + if(!validateIdentifier(list[0])) + throw std::runtime_error("Ill-formed identifier: \""+list[0]+"\""); + if(isSectionEnabled()) _currentLabels.push_back(std::move(list[0])); + list.erase(list.begin(),list.begin()+2); + } + + if(list.empty()) return; + +// If the section is disabled, we look only for #ifdef, #ifndef, #else or #endif + if(!isSectionEnabled()&&list[0]!="#ifdef"&&list[0]!="#ifndef"&& + list[0]!="#else"&&list[0]!="#endif") return; + +// Process statement itself + if(list[0][0]=='#') elaborateDirective(list); + else { + LinkableObject::Word rva; + if(list[0][0]=='.') rva=elaborateDataDefinition(list); + else rva=elaborateInstruction(list); + + for(auto const &label: _currentLabels) { + _obj.addSymbol(label,rva); + } + _currentLabels.clear(); + } +} + +void Assembler::elaborateDirective(TokenList &list) { + assert(!list.empty()); + + if(list[0]=="#define") { + if(list.size()<2) + throw std::runtime_error("Wrong number of tokens in the directive"); + if(_macros.find(list[1])!=_macros.end()) + throw std::runtime_error("Macro \""+list[1]+"\" has been already defined"); + if(!validateIdentifier(list[1])) + throw std::runtime_error("Ill-formed identifier: \""+list[1]+"\""); + _macros.emplace(list[1],TokenList(list.begin()+2,list.end())); + } + else if(list[0]=="#export") { + if(list.size()!=2) throw std::runtime_error("Wrong number of tokens in the directive"); + if(!validateIdentifier(list[1])) throw std::runtime_error("Ill-formed identifier: \""+list[1]+"\""); + _exportedSymbols.push_back(list[1]); + } + else if(list[0]=="#import") { + if(list.size()!=2) throw std::runtime_error("Wrong number of tokens in the directive"); + if(!validateIdentifier(list[1])) throw std::runtime_error("Ill-formed identifier: \""+list[1]+"\""); + _obj.addImportedSymbol(list[1]); + } + else if(list[0]=="#include") { + if(list.size()!=2) throw std::runtime_error("Wrong number of tokens in the directive"); + auto filename=Utils::dequoteString(list[1]); + if(Utils::isAbsolutePath(filename)) return processFileRecursive(filename); + else { + auto path=Utils::relativePath(currentFileName(),filename); + if(Utils::fileExists(path)) return processFileRecursive(path); + else { + for(auto const &dir: _includeSearchDirs) { + path=Utils::nativeSeparators(dir+filename); + if(Utils::fileExists(path)) return processFileRecursive(path); + } + } + } + throw std::runtime_error("Cannot locate include file \""+filename+"\""); + } + else if(list[0]=="#message") { + if(list.size()!=2) throw std::runtime_error("Wrong number of tokens in the directive"); + auto msg=Utils::dequoteString(list[1]); + std::cout<2) throw std::runtime_error("Unexpected token: \""+list[2]+"\""); + std::size_t align=4; + if(list.size()>1) align=static_cast(numericLiteral(list[1])); + if(!Utils::isPowerOf2(align)) throw std::runtime_error("Alignment must be a power of 2"); + if(align<4) throw std::runtime_error("Alignment must be at least 4"); + rva=_obj.addPadding(align); + } + else if(list[0]==".reserve") { + if(list.size()<2) throw std::runtime_error("Unexpected end of statement"); + else if(list.size()>2) throw std::runtime_error("Unexpected token: \""+list[2]+"\""); + auto n=static_cast(numericLiteral(list[1])); + rva=_obj.addZeros(n); + } + else if(list[0]==".word") { + if(list.size()<2) throw std::runtime_error("Unexpected end of statement"); + for(std::size_t i=1;i(numericLiteral(list[i])); + auto r=_obj.addWord(w); + if(i==1) rva=r; + } + else { + if(list[i]!=",") throw std::runtime_error("Comma expected"); + if(i+1==list.size()) throw std::runtime_error("Unexpected end of statement"); + } + } + } + else if(list[0]==".byte") { + if(list.size()<2) throw std::runtime_error("Unexpected end of statement"); + for(std::size_t i=1;i + (bytes.c_str()),bytes.size()); + if(i==1) rva=r; + } + else { + auto n=numericLiteral(list[i]); + + if(n>255||n<-128) throw std::runtime_error("\""+list[i]+"\": out of range"); + + auto b=static_cast(n); + auto r=_obj.addByte(b); + if(i==1) rva=r; + } + } + else { + if(list[i]!=",") throw std::runtime_error("Comma expected"); + if(i+1==list.size()) throw std::runtime_error("Unexpected end of statement"); + } + } + } + else throw std::runtime_error("Unrecognized statement: \""+list[0]+"\""); + + return rva; +} + +LinkableObject::Word Assembler::elaborateInstruction(TokenList &list) { + assert(!list.empty()); + auto rva=_obj.addPadding(); + if(list[0]=="add") encodeAdd(list); + else if(list[0]=="and") encodeAnd(list); + else if(list[0]=="call") encodeCall(list); + else if(list[0].substr(0,4)=="cjmp") encodeCjmpxx(list); + else if(list[0]=="divs") encodeDivs(list); + else if(list[0]=="divu") encodeDivu(list); + else if(list[0]=="hlt") encodeHlt(list); + else if(list[0]=="jmp") encodeJmp(list); + else if(list[0]=="iret") encodeIret(list); + else if(list[0]=="lc") encodeLc(list); + else if(list[0]=="lcs") encodeLcs(list); + else if(list[0]=="lsb") encodeLsb(list); + else if(list[0]=="lub") encodeLub(list); + else if(list[0]=="lw") encodeLw(list); + else if(list[0]=="mods") encodeMods(list); + else if(list[0]=="modu") encodeModu(list); + else if(list[0]=="mov") encodeMov(list); + else if(list[0]=="mul") encodeMul(list); + else if(list[0]=="neg") encodeNeg(list); + else if(list[0]=="nop") encodeNop(list); + else if(list[0]=="not") encodeNot(list); + else if(list[0]=="or") encodeOr(list); + else if(list[0]=="ret") encodeRet(list); + else if(list[0]=="sb") encodeSb(list); + else if(list[0]=="sl") encodeSl(list); + else if(list[0]=="srs") encodeSrs(list); + else if(list[0]=="sru") encodeSru(list); + else if(list[0]=="sub") encodeSub(list); + else if(list[0]=="sw") encodeSw(list); + else if(list[0]=="xor") encodeXor(list); + else throw std::runtime_error("Unrecognized instruction: \""+list[0]+"\""); + return rva; +} + +bool Assembler::isSectionEnabled() const { + if(_sectionEnabled.empty()) return true; + bool enabled=true; + for(auto b: _sectionEnabled) enabled=enabled&&b; + return enabled; +} + +bool Assembler::validateIdentifier(const std::string &str) { +/* + * Valid identifier must satisfy the following requirements: + * 1. Must not be empty + * 2. The first character must be either alphabetic or an underscore + * 3. Subsequent characters must be either alphanumeric or underscores + */ + if(str.empty()) return false; + for(std::size_t i=0;i::type SignedWord; + + if(i>static_cast(std::numeric_limits::max())|| + i(std::numeric_limits::min())) + throw std::runtime_error("\""+str+"\": out of range"); + + return i; +} + +std::vector Assembler::getOperands(const TokenList &list) { + std::vector arglist; + for(std::size_t i=1;i=0&®<=255) { + a.type=Operand::Register; + a.reg=static_cast(reg); + arglist.push_back(std::move(a)); + continue; + } + } + +// Try alternative register names + if(list[i]=="sp") { // stack pointer + a.type=Operand::Register; + a.reg=255; + arglist.push_back(std::move(a)); + } + else if(list[i]=="rp") { // return pointer + a.type=Operand::Register; + a.reg=254; + arglist.push_back(std::move(a)); + } + else if(list[i]=="irp") { // interrupt return pointer + a.type=Operand::Register; + a.reg=253; + arglist.push_back(std::move(a)); + } + else if(list[i]=="cr") { // control register + a.type=Operand::Register; + a.reg=252; + arglist.push_back(std::move(a)); + } + else if(list[i].size()==3&&list[i].substr(0,2)=="iv"&& + list[i][2]>='0'&&list[i][2]<='7') // interrupt vector + { + a.type=Operand::Register; + a.reg=240+(list[i][2]-'0'); + arglist.push_back(std::move(a)); + } + else if(validateIdentifier(list[i])) { +// Is argument an identifier? + a.type=Operand::Identifier; + arglist.push_back(std::move(a)); + } + else { + auto atpos=list[i].find_first_of('@'); + if(atpos!=std::string::npos) { +// Identifier with an offset? + a.type=Operand::Identifier; + a.str=list[i].substr(0,atpos); + if(!validateIdentifier(a.str)) throw std::runtime_error("Ill-formed identifier"); + a.i=numericLiteral(list[i].substr(atpos+1)); + arglist.push_back(std::move(a)); + } + else { +// Numeric literal? + a.type=Operand::NumericLiteral; + a.i=numericLiteral(list[i]); + arglist.push_back(std::move(a)); + } + } + } + else { + if(list[i]!=",") throw std::runtime_error("Comma expected"); + if(i+1==list.size()) throw std::runtime_error("Unexpected end of line"); + } + } + return arglist; +} + +/* + * Member functions to encode LXP32 instructions + */ + +void Assembler::encodeDstOperand(LinkableObject::Word &word,const Operand &arg) { + if(arg.type!=Operand::Register) + throw std::runtime_error("\""+arg.str+"\": must be a register"); + word|=arg.reg<<16; +} + +void Assembler::encodeRd1Operand(LinkableObject::Word &word,const Operand &arg) { + if(arg.type==Operand::Register) { + word|=0x02000000; + word|=arg.reg<<8; + } + else if(arg.type==Operand::NumericLiteral) { + if((arg.i<-128||arg.i>127)&&(arg.i<0xFFFFFF80||arg.i>0xFFFFFFFF)) + throw std::runtime_error("\""+arg.str+"\": out of range"); + auto b=static_cast(arg.i); + word|=b<<8; + } + else throw std::runtime_error("\""+arg.str+"\": bad argument"); +} + +void Assembler::encodeRd2Operand(LinkableObject::Word &word,const Operand &arg) { + if(arg.type==Operand::Register) { + word|=0x01000000; + word|=arg.reg; + } + else if(arg.type==Operand::NumericLiteral) { + if((arg.i<-128||arg.i>127)&&(arg.i<0xFFFFFF80||arg.i>0xFFFFFFFF)) + throw std::runtime_error("\""+arg.str+"\": out of range"); + auto b=static_cast(arg.i); + word|=b; + } + else throw std::runtime_error("\""+arg.str+"\": bad argument"); +} + +void Assembler::encodeAdd(const TokenList &list) { + auto args=getOperands(list); + if(args.size()!=3) throw std::runtime_error("add instruction requires 3 operands"); + LinkableObject::Word w=0x40000000; + encodeDstOperand(w,args[0]); + encodeRd1Operand(w,args[1]); + encodeRd2Operand(w,args[2]); + _obj.addWord(w); +} + +void Assembler::encodeAnd(const TokenList &list) { + auto args=getOperands(list); + if(args.size()!=3) throw std::runtime_error("and instruction requires 3 operands"); + LinkableObject::Word w=0x60000000; + encodeDstOperand(w,args[0]); + encodeRd1Operand(w,args[1]); + encodeRd2Operand(w,args[2]); + _obj.addWord(w); +} + +void Assembler::encodeCall(const TokenList &list) { + auto args=getOperands(list); + if(args.size()!=1) throw std::runtime_error("call instruction requires 1 operand"); + if(args[0].type!=Operand::Register) throw std::runtime_error("\""+args[0].str+"\": must be a register"); + LinkableObject::Word w=0x86FE0000; + encodeRd1Operand(w,args[0]); + _obj.addWord(w); +} + +void Assembler::encodeCjmpxx(const TokenList &list) { + auto args=getOperands(list); + if(args.size()!=3) throw std::runtime_error("cjmpxx instruction requires 3 operands"); + + LinkableObject::Word w; + bool reverse=false; +/* + * Note: cjmpul, cjmpule, cjmpsl and cjmpsle don't have distinct opcodes; + * instead, they are aliases for respective "g" or "ge" instructions + * with reversed operand order. + */ + if(list[0]=="cjmpe") w=0xE0000000; + else if(list[0]=="cjmpne") w=0xD0000000; + else if(list[0]=="cjmpug"||list[0]=="cjmpul") w=0xC8000000; + else if(list[0]=="cjmpuge"||list[0]=="cjmpule") w=0xE8000000; + else if(list[0]=="cjmpsg"||list[0]=="cjmpsl") w=0xC4000000; + else if(list[0]=="cjmpsge"||list[0]=="cjmpsle") w=0xE4000000; + else throw std::runtime_error("Unrecognized instruction: \""+list[0]+"\""); + + if(list[0]=="cjmpul"||list[0]=="cjmpule"|| + list[0]=="cjmpsl"||list[0]=="cjmpsle") reverse=true; + + encodeDstOperand(w,args[0]); + + if(!reverse) { + encodeRd1Operand(w,args[1]); + encodeRd2Operand(w,args[2]); + } + else { + encodeRd1Operand(w,args[2]); + encodeRd2Operand(w,args[1]); + } + _obj.addWord(w); +} + +void Assembler::encodeDivs(const TokenList &list) { + auto args=getOperands(list); + if(args.size()!=3) throw std::runtime_error("divs instruction requires 3 operands"); + LinkableObject::Word w=0x54000000; + encodeDstOperand(w,args[0]); + encodeRd1Operand(w,args[1]); + encodeRd2Operand(w,args[2]); + _obj.addWord(w); +} + +void Assembler::encodeDivu(const TokenList &list) { + auto args=getOperands(list); + if(args.size()!=3) throw std::runtime_error("divu instruction requires 3 operands"); + LinkableObject::Word w=0x50000000; + encodeDstOperand(w,args[0]); + encodeRd1Operand(w,args[1]); + encodeRd2Operand(w,args[2]); + _obj.addWord(w); +} + +void Assembler::encodeHlt(const TokenList &list) { + auto args=getOperands(list); + if(!args.empty()) throw std::runtime_error("hlt instruction doesn't take operands"); + _obj.addWord(0x08000000); +} + +void Assembler::encodeJmp(const TokenList &list) { + auto args=getOperands(list); + if(args.size()!=1) throw std::runtime_error("jmp instruction requires 1 operand"); + if(args[0].type!=Operand::Register) throw std::runtime_error("\""+args[0].str+"\": must be a register"); + LinkableObject::Word w=0x82000000; + encodeRd1Operand(w,args[0]); + _obj.addWord(w); +} + +void Assembler::encodeIret(const TokenList &list) { +// Note: "iret" is not a real instruction, but an alias for "jmp irp" + auto args=getOperands(list); + if(!args.empty()) throw std::runtime_error("iret instruction doesn't take operands"); + _obj.addWord(0x8200FD00); +} + +void Assembler::encodeLc(const TokenList &list) { + auto args=getOperands(list); + if(args.size()!=2) throw std::runtime_error("lc instruction requires 2 operands"); + + LinkableObject::Word w=0x04000000; + encodeDstOperand(w,args[0]); + _obj.addWord(w); + + if(args[1].type==Operand::Identifier) { + LinkableObject::Reference ref; + ref.source=currentFileName(); + ref.line=line(); + ref.rva=_obj.addWord(0); + ref.offset=args[1].i; + ref.type=LinkableObject::Regular; + _obj.addReference(args[1].str,ref); + } + else if(args[1].type==Operand::NumericLiteral) { + _obj.addWord(static_cast(args[1].i)); + } + else throw std::runtime_error("\""+args[1].str+"\": bad argument"); +} + +void Assembler::encodeLcs(const TokenList &list) { + auto args=getOperands(list); + if(args.size()!=2) throw std::runtime_error("lcs instruction requires 2 operands"); + + LinkableObject::Word w=0xA0000000; + encodeDstOperand(w,args[0]); + + if(args[1].type==Operand::NumericLiteral) { + if((args[1].i<-1048576||args[1].i>1048575)&&(args[1].i<0xFFF00000||args[1].i>0xFFFFFFFF)) + throw std::runtime_error("\""+args[1].str+"\": out of range"); + auto c=static_cast(args[1].i)&0x1FFFFF; + w|=(c&0xFFFF); + w|=((c<<8)&0x1F000000); + _obj.addWord(w); + } + else if(args[1].type==Operand::Identifier) { + LinkableObject::Reference ref; + ref.source=currentFileName(); + ref.line=line(); + ref.rva=_obj.addWord(w); + ref.offset=args[1].i; + ref.type=LinkableObject::Short; + _obj.addReference(args[1].str,ref); + } + else throw std::runtime_error("\""+args[1].str+"\": bad argument"); +} + +void Assembler::encodeLsb(const TokenList &list) { + auto args=getOperands(list); + if(args.size()!=2) throw std::runtime_error("lsb instruction requires 2 operands"); + if(args[1].type!=Operand::Register) throw std::runtime_error("\""+args[1].str+"\": must be a register"); + LinkableObject::Word w=0x2E000000; + encodeDstOperand(w,args[0]); + encodeRd1Operand(w,args[1]); + _obj.addWord(w); +} + +void Assembler::encodeLub(const TokenList &list) { + auto args=getOperands(list); + if(args.size()!=2) throw std::runtime_error("lub instruction requires 2 operands"); + if(args[1].type!=Operand::Register) throw std::runtime_error("\""+args[1].str+"\": must be a register"); + LinkableObject::Word w=0x2A000000; + encodeDstOperand(w,args[0]); + encodeRd1Operand(w,args[1]); + _obj.addWord(w); +} + +void Assembler::encodeLw(const TokenList &list) { + auto args=getOperands(list); + if(args.size()!=2) throw std::runtime_error("lw instruction requires 2 operands"); + if(args[1].type!=Operand::Register) throw std::runtime_error("\""+args[1].str+"\": must be a register"); + LinkableObject::Word w=0x22000000; + encodeDstOperand(w,args[0]); + encodeRd1Operand(w,args[1]); + _obj.addWord(w); +} + +void Assembler::encodeMods(const TokenList &list) { + auto args=getOperands(list); + if(args.size()!=3) throw std::runtime_error("mods instruction requires 3 operands"); + LinkableObject::Word w=0x5C000000; + encodeDstOperand(w,args[0]); + encodeRd1Operand(w,args[1]); + encodeRd2Operand(w,args[2]); + _obj.addWord(w); +} + +void Assembler::encodeModu(const TokenList &list) { + auto args=getOperands(list); + if(args.size()!=3) throw std::runtime_error("modu instruction requires 3 operands"); + LinkableObject::Word w=0x58000000; + encodeDstOperand(w,args[0]); + encodeRd1Operand(w,args[1]); + encodeRd2Operand(w,args[2]); + _obj.addWord(w); +} + +void Assembler::encodeMov(const TokenList &list) { +// Note: "mov" is not a real instruction, but an alias for "add dst, src, 0" + auto args=getOperands(list); + if(args.size()!=2) throw std::runtime_error("mov instruction requires 2 operands"); + LinkableObject::Word w=0x40000000; + encodeDstOperand(w,args[0]); + encodeRd1Operand(w,args[1]); + _obj.addWord(w); +} + +void Assembler::encodeMul(const TokenList &list) { + auto args=getOperands(list); + if(args.size()!=3) throw std::runtime_error("mul instruction requires 3 operands"); + LinkableObject::Word w=0x48000000; + encodeDstOperand(w,args[0]); + encodeRd1Operand(w,args[1]); + encodeRd2Operand(w,args[2]); + _obj.addWord(w); +} + +void Assembler::encodeNeg(const TokenList &list) { +// Note: "neg" is not a real instruction, but an alias for "sub dst, 0, src" + auto args=getOperands(list); + if(args.size()!=2) throw std::runtime_error("neg instruction requires 2 operands"); + LinkableObject::Word w=0x44000000; + encodeDstOperand(w,args[0]); + encodeRd2Operand(w,args[1]); + _obj.addWord(w); +} + +void Assembler::encodeNop(const TokenList &list) { + auto args=getOperands(list); + if(!args.empty()) throw std::runtime_error("nop instruction doesn't take operands"); + _obj.addWord(0); +} + +void Assembler::encodeNot(const TokenList &list) { +// Note: "not" is not a real instruction, but an alias for "xor dst, src, -1" + auto args=getOperands(list); + if(args.size()!=2) throw std::runtime_error("not instruction requires 2 operands"); + LinkableObject::Word w=0x680000FF; + encodeDstOperand(w,args[0]); + encodeRd1Operand(w,args[1]); + _obj.addWord(w); +} + +void Assembler::encodeOr(const TokenList &list) { + auto args=getOperands(list); + if(args.size()!=3) throw std::runtime_error("or instruction requires 3 operands"); + LinkableObject::Word w=0x64000000; + encodeDstOperand(w,args[0]); + encodeRd1Operand(w,args[1]); + encodeRd2Operand(w,args[2]); + _obj.addWord(w); +} + +void Assembler::encodeRet(const TokenList &list) { +// Note: "ret" is not a real instruction, but an alias for "jmp rp" + auto args=getOperands(list); + if(!args.empty()) throw std::runtime_error("ret instruction doesn't take operands"); + _obj.addWord(0x8200FE00); +} + +void Assembler::encodeSb(const TokenList &list) { + auto args=getOperands(list); + if(args.size()!=2) throw std::runtime_error("sb instruction requires 2 operands"); + if(args[0].type!=Operand::Register) throw std::runtime_error("\""+args[0].str+"\": must be a register"); + if(args[1].type==Operand::NumericLiteral) { +// If numeric literal value is between 128 and 255 (inclusive), convert +// it to a signed byte to avoid exception in encodeRd2Operand() + if(args[1].i>=128&&args[1].i<=255) args[1].i-=256; + } + LinkableObject::Word w=0x3A000000; + encodeRd1Operand(w,args[0]); + encodeRd2Operand(w,args[1]); + _obj.addWord(w); +} + +void Assembler::encodeSl(const TokenList &list) { + auto args=getOperands(list); + if(args.size()!=3) throw std::runtime_error("sl instruction requires 3 operands"); + if(args[2].type==Operand::NumericLiteral&& + (args[2].i<0||args[2].i>=static_cast(8*sizeof(LinkableObject::Word)))) + { + std::cerr<=static_cast(8*sizeof(LinkableObject::Word)))) + { + std::cerr<=static_cast(8*sizeof(LinkableObject::Word)))) + { + std::cerr< +#include +#include +#include + +class Assembler { + typedef std::vector TokenList; + typedef std::int_least64_t Integer; + enum LexerState { + Initial, + Word, + StringLiteral, + BlockComment + }; + struct Operand { + enum Type {Null,Register,Identifier,NumericLiteral}; + Type type=Null; + std::string str; + Integer i=0; + std::uint8_t reg=0; + }; + + LinkableObject _obj; + std::map _macros; + LexerState _state; + int _line; + std::vector _currentLabels; + std::string _currentFileName; + std::vector _includeSearchDirs; + std::vector _exportedSymbols; + std::vector _sectionEnabled; +public: + void processFile(const std::string &filename); + + void addIncludeSearchDir(const std::string &dir); + + int line() const; + std::string currentFileName() const; + + LinkableObject &object(); + const LinkableObject &object() const; +private: + void processFileRecursive(const std::string &filename); + TokenList tokenize(const std::string &str); + void expand(TokenList &list); + void elaborate(TokenList &list); + + void elaborateDirective(TokenList &list); + LinkableObject::Word elaborateDataDefinition(TokenList &list); + LinkableObject::Word elaborateInstruction(TokenList &list); + + bool isSectionEnabled() const; + static bool validateIdentifier(const std::string &str); + static Integer numericLiteral(const std::string &str); + static std::vector getOperands(const TokenList &list); + +// LXP32 instructions + void encodeDstOperand(LinkableObject::Word &word,const Operand &arg); + void encodeRd1Operand(LinkableObject::Word &word,const Operand &arg); + void encodeRd2Operand(LinkableObject::Word &word,const Operand &arg); + + void encodeAdd(const TokenList &list); + void encodeAnd(const TokenList &list); + void encodeCall(const TokenList &list); + void encodeCjmpxx(const TokenList &list); + void encodeDivs(const TokenList &list); + void encodeDivu(const TokenList &list); + void encodeHlt(const TokenList &list); + void encodeJmp(const TokenList &list); + void encodeIret(const TokenList &list); + void encodeLc(const TokenList &list); + void encodeLcs(const TokenList &list); + void encodeLsb(const TokenList &list); + void encodeLub(const TokenList &list); + void encodeLw(const TokenList &list); + void encodeMods(const TokenList &list); + void encodeModu(const TokenList &list); + void encodeMov(const TokenList &list); + void encodeMul(const TokenList &list); + void encodeNeg(const TokenList &list); + void encodeNop(const TokenList &list); + void encodeNot(const TokenList &list); + void encodeOr(const TokenList &list); + void encodeRet(const TokenList &list); + void encodeSb(const TokenList &list); + void encodeSl(const TokenList &list); + void encodeSrs(const TokenList &list); + void encodeSru(const TokenList &list); + void encodeSub(const TokenList &list); + void encodeSw(const TokenList &list); + void encodeXor(const TokenList &list); +}; + +#endif Index: tags/1.2/tools/src/lxp32asm/linkableobject.cpp =================================================================== --- tags/1.2/tools/src/lxp32asm/linkableobject.cpp (nonexistent) +++ tags/1.2/tools/src/lxp32asm/linkableobject.cpp (revision 10) @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2016 by Alex I. Kuznetsov. + * + * Part of the LXP32 CPU IP core. + * + * This module implements members of the LinkableObject class. + */ + +#include "linkableobject.h" +#include "utils.h" + +#include +#include +#include +#include +#include +#include + +std::string LinkableObject::name() const { + return _name; +} + +void LinkableObject::setName(const std::string &str) { + _name=str; +} + +LinkableObject::Word LinkableObject::virtualAddress() const { + return _virtualAddress; +} + +void LinkableObject::setVirtualAddress(Word addr) { + _virtualAddress=addr; +} + +LinkableObject::Byte *LinkableObject::code() { + return _code.data(); +} + +const LinkableObject::Byte *LinkableObject::code() const { + return _code.data(); +} + +std::size_t LinkableObject::codeSize() const { + return _code.size(); +} + +LinkableObject::Word LinkableObject::addWord(Word w) { + auto rva=addPadding(sizeof(Word)); +// Note: this code doesn't depend on host machine's endianness + _code.push_back(static_cast(w)); + _code.push_back(static_cast(w>>8)); + _code.push_back(static_cast(w>>16)); + _code.push_back(static_cast(w>>24)); + return rva; +} + +LinkableObject::Word LinkableObject::addByte(Byte b) { + auto rva=static_cast(_code.size()); + _code.push_back(b); + return rva; +} + +LinkableObject::Word LinkableObject::addBytes(const Byte *p,std::size_t n) { + auto rva=static_cast(_code.size()); + _code.insert(_code.end(),p,p+n); + return rva; +} + +LinkableObject::Word LinkableObject::addZeros(std::size_t n) { + auto rva=static_cast(_code.size()); + _code.resize(_code.size()+n); + return rva; +} + +LinkableObject::Word LinkableObject::addPadding(std::size_t size) { + auto padding=(size-_code.size()%size)%size; + if(padding>0) _code.resize(_code.size()+padding); + return static_cast(_code.size()); +} + +LinkableObject::Word LinkableObject::getWord(Word rva) const { + Word w=0; + if(rva(_code[rva++]); + if(rva(_code[rva++])<<8; + if(rva(_code[rva++])<<16; + if(rva(_code[rva++])<<24; + return w; +} + +void LinkableObject::replaceWord(Word rva,Word value) { + assert(rva+sizeof(Word)<=codeSize()); +// Note: this code doesn't depend on host machine's endianness + _code[rva++]=static_cast(value); + _code[rva++]=static_cast(value>>8); + _code[rva++]=static_cast(value>>16); + _code[rva++]=static_cast(value>>24); +} + +void LinkableObject::addSymbol(const std::string &name,Word rva) { + auto &data=symbol(name); + if(data.type!=Unknown) throw std::runtime_error("Symbol \""+name+"\" is already defined"); + data.type=Local; + data.rva=rva; +} + +void LinkableObject::addImportedSymbol(const std::string &name) { + auto &data=symbol(name); + if(data.type!=Unknown) throw std::runtime_error("Symbol \""+name+"\" is already defined"); + data.type=Imported; +} + +void LinkableObject::exportSymbol(const std::string &name) { + auto it=_symbols.find(name); + if(it==_symbols.end()||it->second.type==Unknown) throw std::runtime_error("Undefined symbol \""+name+"\""); + if(it->second.type==Imported) throw std::runtime_error("Symbol \""+name+"\" can't be both imported and exported at the same time"); + if(it->second.type==Exported) throw std::runtime_error("Symbol \""+name+"\" has been already exported"); + it->second.type=Exported; +} + +void LinkableObject::addReference(const std::string &symbolName,const Reference &ref) { + auto &data=symbol(symbolName); + data.refs.push_back(ref); +} + +LinkableObject::SymbolData &LinkableObject::symbol(const std::string &name) { + return _symbols[name]; +} + +const LinkableObject::SymbolData &LinkableObject::symbol(const std::string &name) const { + auto const it=_symbols.find(name); + if(it==_symbols.end()) throw std::runtime_error("Undefined symbol \""+name+"\""); + return it->second; +} + +const LinkableObject::SymbolTable &LinkableObject::symbols() const { + return _symbols; +} + +void LinkableObject::serialize(const std::string &filename) const { + std::ofstream out(filename,std::ios_base::out); + if(!out) throw std::runtime_error("Cannot open \""+filename+"\" for writing"); + + out<<"LinkableObject"<(std::strtoul(tokens[0].c_str(),NULL,0)); + addWord(w); + } + throw std::runtime_error("Unexpected end of file"); +} + +void LinkableObject::deserializeSymbol(std::istream &in) { + std::string line; + std::string name; + SymbolData data; + while(std::getline(in,line)) { + auto tokens=tokenize(line); + if(tokens.empty()) continue; + if(tokens[0]=="End") { + if(tokens.size()<2) throw std::runtime_error("Unexpected end of line"); + if(tokens[1]=="Symbol") { + if(name.empty()) throw std::runtime_error("Symbol name is not defined"); + if(data.type==Unknown) throw std::runtime_error("Bad symbol type"); + _symbols.emplace(std::move(name),std::move(data)); + return; + } + throw std::runtime_error("Unexpected token: \""+tokens[1]+"\""); + } + else if(tokens[0]=="Name") { + if(tokens.size()<2) throw std::runtime_error("Unexpected end of line"); + name=Utils::urlDecode(tokens[1]); + } + else if(tokens[0]=="Type") { + if(tokens.size()<2) throw std::runtime_error("Unexpected end of line"); + if(tokens[1]=="Local") data.type=Local; + else if(tokens[1]=="Exported") data.type=Exported; + else if(tokens[1]=="Imported") data.type=Imported; + else throw std::runtime_error("Bad symbol type"); + } + else if(tokens[0]=="RVA") { + if(tokens.size()<2) throw std::runtime_error("Unexpected end of line"); + data.rva=std::strtoul(tokens[1].c_str(),NULL,0); + } + else if(tokens[0]=="Ref") { + Reference ref; + if(tokens.size()<4) throw std::runtime_error("Unexpected end of line"); + ref.source=Utils::urlDecode(tokens[1]); + ref.line=std::strtoul(tokens[2].c_str(),NULL,0); + ref.rva=std::strtoul(tokens[3].c_str(),NULL,0); + ref.offset=std::strtoll(tokens[4].c_str(),NULL,0); + if(tokens[5]=="Regular") ref.type=Regular; + else if(tokens[5]=="Short") ref.type=Short; + else throw std::runtime_error("Invalid reference type: \""+tokens[5]+"\""); + data.refs.push_back(std::move(ref)); + } + } + throw std::runtime_error("Unexpected end of file"); +} + +std::vector LinkableObject::tokenize(const std::string &str) { + std::vector tokens; + for(std::size_t pos=0;;) { + auto start=str.find_first_not_of(" \t\r\n",pos); + if(start==std::string::npos) return tokens; + auto end=str.find_first_of(" \t\r\n",start); + if(end==std::string::npos) { + tokens.push_back(str.substr(start)); + return tokens; + } + else tokens.push_back(str.substr(start,end-start)); + pos=end; + } +} Index: tags/1.2/tools/src/lxp32asm/linkableobject.h =================================================================== --- tags/1.2/tools/src/lxp32asm/linkableobject.h (nonexistent) +++ tags/1.2/tools/src/lxp32asm/linkableobject.h (revision 10) @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2016 by Alex I. Kuznetsov. + * + * Part of the LXP32 CPU IP core. + * + * This module defines the LinkableObject class which represents + * compiled LXP32 binary code. + */ + +#ifndef LINKABLEOBJECT_H_INCLUDED +#define LINKABLEOBJECT_H_INCLUDED + +#include +#include +#include +#include +#include + +class LinkableObject { +public: + typedef unsigned char Byte; + typedef std::uint32_t Word; + typedef std::int_least64_t Integer; + + enum SymbolType {Unknown,Local,Exported,Imported}; + enum RefType {Regular,Short}; + + struct Reference { + std::string source; + int line; + Word rva; + Integer offset; + RefType type; + }; + struct SymbolData { + SymbolType type=Unknown; + Word rva; + std::vector refs; + }; + + typedef std::map SymbolTable; + +private: + std::string _name; + std::vector _code; + SymbolTable _symbols; + Word _virtualAddress=0; + +public: + std::string name() const; + void setName(const std::string &str); + + Word virtualAddress() const; + void setVirtualAddress(Word addr); + + Byte *code(); + const Byte *code() const; + std::size_t codeSize() const; + + Word addWord(Word w); + Word addByte(Byte b); + Word addBytes(const Byte *p,std::size_t n); + Word addZeros(std::size_t n); + + Word addPadding(std::size_t size=sizeof(LinkableObject::Word)); + + Word getWord(Word rva) const; + void replaceWord(Word rva,Word value); + + void addSymbol(const std::string &name,Word rva); + void addImportedSymbol(const std::string &name); + void exportSymbol(const std::string &name); + void addReference(const std::string &symbolName,const Reference &ref); + + SymbolData &symbol(const std::string &name); + const SymbolData &symbol(const std::string &name) const; + const SymbolTable &symbols() const; + + void serialize(const std::string &filename) const; + void deserialize(const std::string &filename); + +private: + void deserializeCode(std::istream &in); + void deserializeSymbol(std::istream &in); + static std::vector tokenize(const std::string &str); +}; + +#endif Index: tags/1.2/tools/src/lxp32asm/linker.cpp =================================================================== --- tags/1.2/tools/src/lxp32asm/linker.cpp (nonexistent) +++ tags/1.2/tools/src/lxp32asm/linker.cpp (revision 10) @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2016 by Alex I. Kuznetsov. + * + * Part of the LXP32 CPU IP core. + * + * This module implements members of the Linker class. + */ + +#include "linker.h" + +#include "linkableobject.h" +#include "utils.h" + +#include +#include +#include +#include +#include +#include +#include + +void Linker::addObject(LinkableObject &obj) { + _objects.push_back(&obj); +} + +void Linker::link(OutputWriter &writer) { + if(_objects.empty()) throw std::runtime_error("Object set is empty"); + +// Merge symbol tables + buildSymbolTable(); + +// Determine entry point + if(_objects.size()==1) _entryObject=_objects[0]; + else if(_entryObject==nullptr) + throw std::runtime_error("Entry point not defined: cannot find \"entry\" or \"Entry\" symbol"); + +// Assign virtual addresses + placeObjects(); + +// Perform relocations + for(auto &obj: _objects) relocateObject(obj); + +// Write binary data + writeObjects(writer); + _bytesWritten=writer.size(); +} + +void Linker::setBase(LinkableObject::Word base) { + _base=base; +} + +void Linker::setAlignment(std::size_t align) { + _align=align; +} + +void Linker::setImageSize(std::size_t size) { + _imageSize=size; +} + +void Linker::generateMap(std::ostream &s) { +// Calculate the maximum length of a symbol name + std::size_t len=0; + for(auto const &obj: _objects) { + for(auto const &sym: obj->symbols()) { + if(sym.second.type!=LinkableObject::Imported) + len=std::max(len,sym.first.size()); + } + } + len=std::max(len+3,std::size_t(8)); // width of the first column + + s<<"Image base address: "<name()<<"\" at address "<virtualAddress())< > sorted; + for(auto const &sym: obj->symbols()) sorted.emplace(sym.second.rva,sym); + for(auto const &sym: sorted) { + if(sym.second.second.type==LinkableObject::Imported) continue; + s<virtualAddress()+sym.second.second.rva); + if(sym.second.second.type==LinkableObject::Local) s<<" Local"; + else s<<" Exported"; + s<symbols(); + for(auto const &item: table) { + if((item.first=="entry"||item.first=="Entry")&&item.second.type!=LinkableObject::Imported) { + if(_entryObject) { + std::ostringstream msg; + msg<name()<<": Duplicate definition of the entry symbol "; + msg<<"(previously defined in "<<_entryObject->name()<<")"; + throw std::runtime_error(msg.str()); + } + if(item.second.rva!=0) { + std::ostringstream msg; + msg<name()<<": "; + msg<<"Entry point must refer to the start of the object"; + throw std::runtime_error(msg.str()); + } + _entryObject=obj; + } + if(item.second.type==LinkableObject::Local) continue; +// Insert item to the global symbol table if it doesn't exist yet + auto it=_globalSymbolTable.emplace(item.first,GlobalSymbolData()).first; + +// Check that the symbol has not been already defined in another object + if(item.second.type==LinkableObject::Exported) { + if(it->second.obj) { + std::ostringstream msg; + msg<name()<<": Duplicate definition of \""<second.obj->name()<<")"; + throw std::runtime_error(msg.str()); + } + it->second.obj=obj; + it->second.rva=item.second.rva; + } + + if(!item.second.refs.empty()) it->second.refs.insert(obj); + } + } + +// Check that local symbols don't shadow the public ones + for(auto const &obj: _objects) { + auto const &table=obj->symbols(); + for(auto const &item: table) { + if(item.second.type!=LinkableObject::Local) continue; + auto it=_globalSymbolTable.find(item.first); + if(it==_globalSymbolTable.end()) continue; + if(!it->second.obj) continue; + if(item.first==it->first) { + std::ostringstream msg; + msg<name()<<": Local symbol \""<second.obj->name()<<")"; + throw std::runtime_error(msg.str()); + } + } + } + +// Check that no undefined symbols remain + for(auto const &item: _globalSymbolTable) { + if(item.second.obj==nullptr&&!item.second.refs.empty()) { + std::ostringstream msg; + msg<<"Undefined symbol: \""<name()<<")"; + throw std::runtime_error(msg.str()); + } + } +} + +void Linker::placeObjects() { + auto currentBase=_base; + +// Make entry object the first + if(_objects.size()>1) { + for(auto it=_objects.begin();it!=_objects.end();++it) { + if(*it==_entryObject) { + _objects.erase(it); + break; + } + } + _objects.insert(_objects.begin(),_entryObject); + } + +// Remove unreferenced objects + if(_objects.size()>1) { + std::set used; + markAsUsed(_objects[0],used); + for(auto it=_objects.begin();it!=_objects.end();) { + if(used.find(*it)==used.end()) { + std::cerr<<"Linker warning: skipping an unreferenced object \""; + std::cerr<<(*it)->name()<<"\""<second.obj==*it) sym=_globalSymbolTable.erase(sym); + else ++sym; + } + it=_objects.erase(it); + } + else ++it; + } + } + +// Set base addresses + for(auto it=_objects.begin();it!=_objects.end();++it) { + (*it)->setVirtualAddress(currentBase); + if(it+1!=_objects.end()) (*it)->addPadding(_align); + else (*it)->addPadding(); + currentBase+=static_cast((*it)->codeSize()); + } +} + +void Linker::relocateObject(LinkableObject *obj) { + for(auto const &sym: obj->symbols()) { + LinkableObject::Word addr; + if(sym.second.refs.empty()) continue; + + if(sym.second.type==LinkableObject::Local) addr=obj->virtualAddress()+sym.second.rva; + else { + auto it=_globalSymbolTable.find(sym.first); + assert(it!=_globalSymbolTable.end()); + assert(it->second.obj); + addr=it->second.obj->virtualAddress()+it->second.rva; + } + + for(auto const &ref: sym.second.refs) { + if(ref.type==LinkableObject::Regular) obj->replaceWord(ref.rva,addr+ref.offset); + else { + auto target=static_cast(addr+ref.offset); + if(target>0xFFFFF&&target<0xFFF00000) { + std::ostringstream msg; + msg<<"Address 0x"<getWord(ref.rva); + w|=(target&0xFFFF); + w|=((target<<8)&0x1F000000); + obj->replaceWord(ref.rva,w); + } + } + } +} + +void Linker::writeObjects(OutputWriter &writer) { + std::size_t currentSize=0; +// Write entry object + writer.write(reinterpret_cast(_entryObject->code()),_entryObject->codeSize()); + currentSize+=_entryObject->codeSize(); +// Write other objects + for(auto const &obj: _objects) { + if(obj==_entryObject) continue; + writer.write(reinterpret_cast(obj->code()),obj->codeSize()); + currentSize+=obj->codeSize(); + } + +// Pad file if requested + if(_imageSize>0) { + if(currentSize>_imageSize) + throw std::runtime_error("Image size exceeds the specified value"); + else if(currentSize<_imageSize) writer.pad(_imageSize-currentSize); + } +} + +void Linker::markAsUsed(const LinkableObject *obj,std::set &used) { + if(used.find(obj)!=used.end()) return; // already processed + used.insert(obj); + for(auto const &sym: _globalSymbolTable) { + for(auto const &ref: sym.second.refs) { + if(ref==obj) markAsUsed(sym.second.obj,used); + } + } +} Index: tags/1.2/tools/src/lxp32asm/linker.h =================================================================== --- tags/1.2/tools/src/lxp32asm/linker.h (nonexistent) +++ tags/1.2/tools/src/lxp32asm/linker.h (revision 10) @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2016 by Alex I. Kuznetsov. + * + * Part of the LXP32 CPU IP core. + * + * This module defines the Linker class which performs + * linking of LXP32 binary objects. + */ + +#ifndef LINKER_H_INCLUDED +#define LINKER_H_INCLUDED + +#include "linkableobject.h" +#include "outputwriter.h" + +#include +#include +#include +#include +#include + +class Linker { + struct GlobalSymbolData { + LinkableObject *obj=nullptr; + LinkableObject::Word rva=0; + std::set refs; + }; + + std::vector _objects; + LinkableObject *_entryObject=nullptr; + std::map _globalSymbolTable; + +// Various output options + LinkableObject::Word _base=0; + std::size_t _align=4; + std::size_t _imageSize=0; + std::size_t _bytesWritten=0; +public: + void addObject(LinkableObject &obj); + void link(OutputWriter &writer); + void setBase(LinkableObject::Word base); + void setAlignment(std::size_t align); + void setImageSize(std::size_t size); + void generateMap(std::ostream &s); +private: + void buildSymbolTable(); + void placeObjects(); + void relocateObject(LinkableObject *obj); + void writeObjects(OutputWriter &writer); + void markAsUsed(const LinkableObject *obj,std::set &used); +}; + +#endif Index: tags/1.2/tools/src/lxp32asm/main.cpp =================================================================== --- tags/1.2/tools/src/lxp32asm/main.cpp (nonexistent) +++ tags/1.2/tools/src/lxp32asm/main.cpp (revision 10) @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2016 by Alex I. Kuznetsov. + * + * Part of the LXP32 CPU IP core. + * + * Main translation unit for the LXP32 assembler/linker. + */ + +#include "assembler.h" +#include "linker.h" +#include "utils.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct Options { + enum OutputFormat {Bin,Textio,Dec,Hex}; + + bool compileOnly=false; + std::string outputFileName; + std::string mapFileName; + std::vector includeSearchDirs; + LinkableObject::Word base=0; + std::size_t align=4; + std::size_t imageSize=0; + OutputFormat fmt=Bin; +}; + +static void displayUsage(std::ostream &os,const char *program) { + os< Object alignment (default: 4)"< Base address (default: 0)"< Output file format (see below)"< Add directory to the list of directories used to search"< Generate map file"< Output file name"< Output image size"<(-1)) + return false; // the stream is not seekable + + std::vector buf(idSize); + in.read(buf.data(),idSize); + if(static_cast(in.gcount())!=idSize) return false; + if(std::memcmp(buf.data(),id,idSize)) return false; + return true; +} + +int main(int argc,char *argv[]) try { + std::vector inputFiles; + Options options; + bool alignmentSpecified=false; + bool baseSpecified=false; + bool formatSpecified=false; + bool noMoreOptions=false; + + std::cout<<"LXP32 Platform Assembler and Linker"<0) + std::cerr<<"Warning: Image size is ignored in compile-only mode"<1&&!options.outputFileName.empty()) + throw std::runtime_error("Output file name cannot be specified " + "for multiple files in compile-only mode"); + + std::vector assemblers; + std::vector rawObjects; + + for(auto const &filename: inputFiles) { + if(options.compileOnly||!isLinkableObject(filename)) { + Assembler as; + for(auto const &dir: options.includeSearchDirs) as.addIncludeSearchDir(dir); + try { + as.processFile(filename); + } + catch(std::exception &ex) { + std::cerr<<"Assembler error in "<0) std::cerr<<":"< writer; + + switch(options.fmt) { + case Options::Bin: + writer=std::unique_ptr(new BinaryOutputWriter(outputFileName)); + break; + case Options::Textio: + writer=std::unique_ptr(new TextOutputWriter(outputFileName,TextOutputWriter::Bin)); + break; + case Options::Dec: + writer=std::unique_ptr(new TextOutputWriter(outputFileName,TextOutputWriter::Dec)); + break; + case Options::Hex: + writer=std::unique_ptr(new TextOutputWriter(outputFileName,TextOutputWriter::Hex)); + break; + default: + assert(false); + } + + try { + linker.link(*writer); + } + catch(std::exception &ex) { + writer->abort(); + std::cerr<<"Linker error: "<size()/4<<" words written"< +#include +#include +#include +#include +#include +#include + +/* + * OutputWriter members + */ + +void OutputWriter::write(const char *data,std::size_t n) { + writeData(data,n); + _size+=n; +} + +void OutputWriter::pad(std::size_t size) { + static char zeros[256]; // static objects are zero-initialized + while(size>0) { + auto n=std::min(size,256); + write(zeros,n); + size-=n; + } +} + +std::size_t OutputWriter::size() const { + return _size; +} + +/* + * BinaryOutputWriter members + */ + +BinaryOutputWriter::BinaryOutputWriter(const std::string &filename): + _filename(filename), + _os(filename,std::ios_base::out|std::ios_base::binary) +{ + if(!_os) throw std::runtime_error("Cannot open \""+filename+"\" for writing"); +} + +void BinaryOutputWriter::writeData(const char *data,std::size_t n) { + _os.write(data,n); +} + +void BinaryOutputWriter::abort() { + _os.close(); + std::remove(_filename.c_str()); +} + +/* + * TextOutputWriter members + */ + +TextOutputWriter::TextOutputWriter(const std::string &filename,Format f): + _filename(filename), + _os(filename,std::ios_base::out), + _fmt(f) +{ + if(!_os) throw std::runtime_error("Cannot open \""+filename+"\" for writing"); +} + +TextOutputWriter::~TextOutputWriter() { + if(!_buf.empty()) { + assert(_buf.size()<4); + pad(4-_buf.size()); + } +} + +void TextOutputWriter::writeData(const char *data,std::size_t n) { + while(n>0) { + assert(_buf.size()<4); + auto count=std::min(4-_buf.size(),n); + _buf.append(data,count); + data+=count; + n-=count; + + if(_buf.size()<4) continue; + + assert(_buf.size()==4); + + std::uint32_t word=(static_cast(_buf[3])<<24)| + (static_cast(_buf[2])<<16)| + (static_cast(_buf[1])<<8)| + static_cast(_buf[0]); + + if(_fmt==Bin) _os< +#include + +/* + * An abstract base class for all writers + */ + +class OutputWriter { + std::size_t _size=0; +public: + virtual ~OutputWriter() {} + virtual void write(const char *data,std::size_t n); + virtual void abort() {} + void pad(std::size_t size); + std::size_t size() const; +protected: + virtual void writeData(const char *data,std::size_t n)=0; +}; + +/* + * Write a regular binary file + */ + +class BinaryOutputWriter : public OutputWriter { + std::string _filename; + std::ofstream _os; +public: + BinaryOutputWriter(const std::string &filename); + virtual void abort() override; +protected: + virtual void writeData(const char *data,std::size_t n) override; +}; + +/* + * Write a text file (one word per line) + */ + +class TextOutputWriter : public OutputWriter { +public: + enum Format {Bin,Dec,Hex}; +private: + std::string _filename; + std::ofstream _os; + std::string _buf; + Format _fmt; +public: + TextOutputWriter(const std::string &filename,Format f); + ~TextOutputWriter(); + virtual void abort() override; +protected: + virtual void writeData(const char *data,std::size_t n) override; +}; + +#endif Index: tags/1.2/tools/src/lxp32asm/utils.cpp =================================================================== --- tags/1.2/tools/src/lxp32asm/utils.cpp (nonexistent) +++ tags/1.2/tools/src/lxp32asm/utils.cpp (revision 10) @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2016 by Alex I. Kuznetsov. + * + * Part of the LXP32 CPU IP core. + * + * This module implements members of the Utils namespace. + */ + +#include "utils.h" + +#include +#include +#include +#include +#include + +std::string Utils::urlEncode(const std::string &str) { + std::string res; + for(std::size_t i=0;i='A'&&ch<='Z') res.push_back(ch); + else if(ch>='a'&&ch<='z') res.push_back(ch); + else if(ch>='0'&&ch<='9') res.push_back(ch); + else if(ch=='-'||ch=='_'||ch=='.'||ch=='~') res.push_back(ch); + else res+="%"+hex(ch); + } + return res; +} + +std::string Utils::urlDecode(const std::string &str) { + std::string res; + for(std::size_t i=0;i(std::stoul(hexcode,nullptr,16)); + res.push_back(static_cast(u)); + } + catch(std::exception &) { + throw std::runtime_error("Ill-formed URL-encoded string"); + } + } + } + return res; +} + +std::string Utils::normalizeSeparators(const std::string &path) { + std::string str(path); +#ifdef _WIN32 + std::replace(str.begin(),str.end(),'\\','/'); +#endif + return str; +} + +std::string Utils::nativeSeparators(const std::string &path) { + std::string str(path); +#ifdef _WIN32 + std::replace(str.begin(),str.end(),'/','\\'); +#endif + return str; +} + +bool Utils::isAbsolutePath(const std::string &path) { + auto native=nativeSeparators(path); + if(native.empty()) return false; + if(native[0]=='/') return true; +#ifdef _WIN32 + if(native.size()>1&&native[1]==':') return true; +#endif + return false; +} + +bool Utils::fileExists(const std::string &path) { + std::ifstream in(nativeSeparators(path),std::ios_base::in); + if(!in) return false; + return true; +} + +std::string Utils::relativePath(const std::string &from,const std::string &to) { +// Normalize directory separators + auto nfrom=normalizeSeparators(from); + auto nto=normalizeSeparators(to); + + if(nto.empty()) return std::string(); + +// If "nto" is an absolute path, just return it + if(isAbsolutePath(nto)) return nativeSeparators(nto); + +// Process relative path + auto pos=nfrom.find_last_of('/'); + if(pos==std::string::npos) return nativeSeparators(nto); + else return nativeSeparators(nfrom.substr(0,pos+1)+nto); +} + +std::string Utils::dequoteString(const std::string &str) { + if(str.size()<2) throw std::runtime_error("String literal expected"); + if(str.front()!='\"'||str.back()!='\"') throw std::runtime_error("String literal expected"); + return str.substr(1,str.size()-2); +} + +bool Utils::ishexdigit(char ch) { + static const char *digits="0123456789ABCDEFabcdef"; + return (std::strchr(digits,ch)!=NULL); +} + +bool Utils::isoctdigit(char ch) { + static const char *digits="01234567"; + return (std::strchr(digits,ch)!=NULL); +} Index: tags/1.2/tools/src/lxp32asm/utils.h =================================================================== --- tags/1.2/tools/src/lxp32asm/utils.h (nonexistent) +++ tags/1.2/tools/src/lxp32asm/utils.h (revision 10) @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2016 by Alex I. Kuznetsov. + * + * Part of the LXP32 CPU IP core. + * + * This module declares the members of the Utils namespace. + */ + +#ifndef UTILS_H_INCLUDED +#define UTILS_H_INCLUDED + +#include +#include + +namespace Utils { + template std::string hex(const T &w) { + static_assert(std::is_integral::value,"Argument must be of integral type"); + const char *hexstr="0123456789ABCDEF"; + std::string res; + + res.reserve(sizeof(T)*2); + + for(int i=sizeof(T)*8-4;i>=0;i-=4) { + res.push_back(hexstr[(w>>i)&0x0F]); + } + return res; + } + + template std::string bin(const T &w) { + static_assert(std::is_integral::value,"Argument must be of integral type"); + std::string res; + + res.reserve(sizeof(T)*8); + + for(int i=sizeof(T)*8-1;i>=0;i--) { + if(((w>>i)&1)!=0) res.push_back('1'); + else res.push_back('0'); + } + return res; + } + + std::string urlEncode(const std::string &str); + std::string urlDecode(const std::string &str); + + std::string normalizeSeparators(const std::string &path); + std::string nativeSeparators(const std::string &path); + bool isAbsolutePath(const std::string &path); + bool fileExists(const std::string &path); + std::string relativePath(const std::string &from,const std::string &to); + + std::string dequoteString(const std::string &str); + + bool ishexdigit(char ch); + bool isoctdigit(char ch); + + template bool isPowerOf2(const T &x) { + static_assert(std::is_integral::value,"Argument must be of integral type"); + return (x!=0)&&((x&(x-1))==0); + } +} + +#endif Index: tags/1.2/tools/src/lxp32dump/CMakeLists.txt =================================================================== --- tags/1.2/tools/src/lxp32dump/CMakeLists.txt (nonexistent) +++ tags/1.2/tools/src/lxp32dump/CMakeLists.txt (revision 10) @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.3.0) + +add_executable(lxp32dump disassembler.cpp main.cpp) + +# Install + +install(TARGETS lxp32dump DESTINATION .) Index: tags/1.2/tools/src/lxp32dump/disassembler.cpp =================================================================== --- tags/1.2/tools/src/lxp32dump/disassembler.cpp (nonexistent) +++ tags/1.2/tools/src/lxp32dump/disassembler.cpp (revision 10) @@ -0,0 +1,456 @@ +/* + * Copyright (c) 2016 by Alex I. Kuznetsov. + * + * Part of the LXP32 CPU IP core. + * + * This module implements members of the Disassembler class. + */ + +#include "disassembler.h" + +#include + +/* + * Disassembler::Operand class members + */ + +Disassembler::Operand::Operand(Type t,int value): + _type(t),_value(value) {} + +Disassembler::Operand::Type Disassembler::Operand::type() const { + return _type; +} + +int Disassembler::Operand::value() const { + return _value; +} + +/* + * Disassembler class members + */ + +Disassembler::Disassembler(std::istream &is,std::ostream &os): + _is(is),_os(os),_fmt(Bin),_preferAliases(true),_lineNumber(0),_pos(0) {} + +void Disassembler::setFormat(Format fmt) { + _fmt=fmt; +} + +void Disassembler::setBase(Word base) { + _pos=base; +} + +void Disassembler::setPreferAliases(bool b) { + _preferAliases=b; +} + +void Disassembler::dump() { + Word word; + + for(;;) { + auto offset=_pos; + if(!getWord(word)) break; + auto opcode=word>>26; + + std::string instruction; + + bool lcValid=false; + Word lcOperand; + + switch(opcode) { + case 0x10: + instruction=decodeAdd(word); + break; + case 0x18: + instruction=decodeAnd(word); + break; + case 0x21: + instruction=decodeCall(word); + break; + case 0x15: + instruction=decodeDivs(word); + break; + case 0x14: + instruction=decodeDivu(word); + break; + case 0x02: + instruction=decodeHlt(word); + break; + case 0x20: + instruction=decodeJmp(word); + break; + case 0x01: + instruction=decodeLc(word,lcValid,lcOperand); + break; + case 0x0B: + instruction=decodeLsb(word); + break; + case 0x0A: + instruction=decodeLub(word); + break; + case 0x08: + instruction=decodeLw(word); + break; + case 0x17: + instruction=decodeMods(word); + break; + case 0x16: + instruction=decodeModu(word); + break; + case 0x12: + instruction=decodeMul(word); + break; + case 0x00: + instruction=decodeNop(word); + break; + case 0x19: + instruction=decodeOr(word); + break; + case 0x0E: + instruction=decodeSb(word); + break; + case 0x1C: + instruction=decodeSl(word); + break; + case 0x1F: + instruction=decodeSrs(word); + break; + case 0x1E: + instruction=decodeSru(word); + break; + case 0x11: + instruction=decodeSub(word); + break; + case 0x0C: + instruction=decodeSw(word); + break; + case 0x1A: + instruction=decodeXor(word); + break; + default: + if((opcode>>4)==0x03) instruction=decodeCjmpxx(word); + else if((opcode>>3)==0x05) instruction=decodeLcs(word); + else instruction=decodeWord(word); + } + + auto size=instruction.size(); + std::size_t padding=0; + if(size<32) padding=32-size; + + _os<<'\t'<(_is.gcount()); + if(n==0) return false; + if(n(buf[3])<<24)|(static_cast(buf[2])<<16)| + (static_cast(buf[1])<<8)|static_cast(buf[0]); + } + else { + try { + std::string line; + if(!std::getline(_is,line)) return false; + _lineNumber++; + + if(_fmt==Textio) w=std::stoul(line,nullptr,2); + else if(_fmt==Dec) w=std::stoul(line,nullptr,10); + else if(_fmt==Hex) w=std::stoul(line,nullptr,16); + else return false; + } + catch(std::exception &) { + throw std::runtime_error("Bad literal at line "+std::to_string(_lineNumber)); + } + } + _pos+=sizeof(Word); + return true; +} + +std::string Disassembler::str(const Operand &op) { + if(op.type()==Operand::Register) { + if(!_preferAliases) return "r"+std::to_string(op.value()); + else if(op.value()>=240&&op.value()<=247) return "iv"+std::to_string(op.value()-240); + else if(op.value()==252) return "cr"; + else if(op.value()==253) return "irp"; + else if(op.value()==254) return "rp"; + else if(op.value()==255) return "sp"; + else return "r"+std::to_string(op.value()); + } + else return std::to_string(op.value()); +} + +Disassembler::Operand Disassembler::decodeRd1Operand(Word w) { + int value=(w>>8)&0xFF; + if(w&0x02000000) return Operand(Operand::Register,value); + else { + if(value>127) value-=256; + return Operand(Operand::Direct,value); + } +} + +Disassembler::Operand Disassembler::decodeRd2Operand(Word w) { + int value=w&0xFF; + if(w&0x01000000) return Operand(Operand::Register,value); + else { + if(value>127) value-=256; + return Operand(Operand::Direct,value); + } +} + +Disassembler::Operand Disassembler::decodeDstOperand(Word w) { + int value=(w>>16)&0xFF; + return Operand(Operand::Register,value); +} + +std::string Disassembler::decodeSimpleInstruction(const std::string &op,Word w) { + auto dst=decodeDstOperand(w); + auto rd1=decodeRd1Operand(w); + auto rd2=decodeRd2Operand(w); + return op+' '+str(dst)+", "+str(rd1)+", "+str(rd2); +} + +std::string Disassembler::decodeAdd(Word w) { + auto dst=decodeDstOperand(w); + auto rd1=decodeRd1Operand(w); + auto rd2=decodeRd2Operand(w); + + if(rd2.type()==Operand::Direct&&rd2.value()==0&&_preferAliases) + return "mov "+str(dst)+", "+str(rd1); + else + return "add "+str(dst)+", "+str(rd1)+", "+str(rd2); +} + +std::string Disassembler::decodeAnd(Word w) { + return decodeSimpleInstruction("and",w); +} + +std::string Disassembler::decodeCall(Word w) { + auto dst=decodeDstOperand(w); + auto rd1=decodeRd1Operand(w); + auto rd2=decodeRd2Operand(w); + + if(dst.value()!=0xFE) return decodeWord(w); + if(rd1.type()!=Operand::Register) return decodeWord(w); + if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w); + + return "call "+str(rd1); +} + +std::string Disassembler::decodeCjmpxx(Word w) { + auto jumpType=(w>>26)&0x0F; + std::string op; + + switch(jumpType) { + case 0x8: + op="cjmpe"; + break; + case 0x4: + op="cjmpne"; + break; + case 0x2: + op="cjmpug"; + break; + case 0xA: + op="cjmpuge"; + break; + case 0x1: + op="cjmpsg"; + break; + case 0x9: + op="cjmpsge"; + break; + default: + return decodeWord(w); + } + + return decodeSimpleInstruction(op,w); +} + +std::string Disassembler::decodeDivs(Word w) { + auto rd2=decodeRd2Operand(w); + if(rd2.type()==Operand::Direct&&rd2.value()==0) return decodeWord(w); + return decodeSimpleInstruction("divs",w); +} + +std::string Disassembler::decodeDivu(Word w) { + auto rd2=decodeRd2Operand(w); + if(rd2.type()==Operand::Direct&&rd2.value()==0) return decodeWord(w); + return decodeSimpleInstruction("divu",w); +} + +std::string Disassembler::decodeHlt(Word w) { + if(w!=0x08000000) return decodeWord(w); + return "hlt"; +} + +std::string Disassembler::decodeJmp(Word w) { + auto dst=decodeDstOperand(w); + auto rd1=decodeRd1Operand(w); + auto rd2=decodeRd2Operand(w); + + if(dst.value()!=0) return decodeWord(w); + if(rd1.type()!=Operand::Register) return decodeWord(w); + if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w); + + if(rd1.value()==253&&_preferAliases) return "iret"; + if(rd1.value()==254&&_preferAliases) return "ret"; + return "jmp "+str(rd1); +} + +std::string Disassembler::decodeLc(Word w,bool &valid,Word &operand) { + auto dst=decodeDstOperand(w); + auto rd1=decodeRd1Operand(w); + auto rd2=decodeRd2Operand(w); + + valid=false; + + if(rd1.type()!=Operand::Direct||rd1.value()!=0) return decodeWord(w); + if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w); + + bool b=getWord(operand); + if(!b) return decodeWord(w); + + valid=true; + return "lc "+str(dst)+", 0x"+hex(operand); +} + +std::string Disassembler::decodeLcs(Word w) { + auto dst=decodeDstOperand(w); + auto operand=w&0xFFFF; + operand|=(w>>8)&0x001F0000; + if(operand&0x00100000) operand|=0xFFE00000; + return "lcs "+str(dst)+", 0x"+hex(operand); +} + +std::string Disassembler::decodeLsb(Word w) { + auto dst=decodeDstOperand(w); + auto rd1=decodeRd1Operand(w); + auto rd2=decodeRd2Operand(w); + + if(rd1.type()!=Operand::Register) return decodeWord(w); + if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w); + + return "lsb "+str(dst)+", "+str(rd1); +} + +std::string Disassembler::decodeLub(Word w) { + auto dst=decodeDstOperand(w); + auto rd1=decodeRd1Operand(w); + auto rd2=decodeRd2Operand(w); + + if(rd1.type()!=Operand::Register) return decodeWord(w); + if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w); + + return "lub "+str(dst)+", "+str(rd1); +} + +std::string Disassembler::decodeLw(Word w) { + auto dst=decodeDstOperand(w); + auto rd1=decodeRd1Operand(w); + auto rd2=decodeRd2Operand(w); + + if(rd1.type()!=Operand::Register) return decodeWord(w); + if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w); + + return "lw "+str(dst)+", "+str(rd1); +} + +std::string Disassembler::decodeMods(Word w) { + auto rd2=decodeRd2Operand(w); + if(rd2.type()==Operand::Direct&&rd2.value()==0) return decodeWord(w); + return decodeSimpleInstruction("mods",w); +} + +std::string Disassembler::decodeModu(Word w) { + auto rd2=decodeRd2Operand(w); + if(rd2.type()==Operand::Direct&&rd2.value()==0) return decodeWord(w); + return decodeSimpleInstruction("modu",w); +} + +std::string Disassembler::decodeMul(Word w) { + return decodeSimpleInstruction("mul",w); +} + +std::string Disassembler::decodeNop(Word w) { + if(w!=0) return decodeWord(w); + return "nop"; +} + +std::string Disassembler::decodeOr(Word w) { + return decodeSimpleInstruction("or",w); +} + +std::string Disassembler::decodeSb(Word w) { + auto dst=decodeDstOperand(w); + auto rd1=decodeRd1Operand(w); + auto rd2=decodeRd2Operand(w); + + if(dst.value()!=0) return decodeWord(w); + if(rd1.type()!=Operand::Register) return decodeWord(w); + + return "sb "+str(rd1)+", "+str(rd2); +} + +std::string Disassembler::decodeSl(Word w) { + auto rd2=decodeRd2Operand(w); + if(rd2.type()==Operand::Direct&&(rd2.value()<0||rd2.value()>31)) return decodeWord(w); + return decodeSimpleInstruction("sl",w); +} + +std::string Disassembler::decodeSrs(Word w) { + auto rd2=decodeRd2Operand(w); + if(rd2.type()==Operand::Direct&&(rd2.value()<0||rd2.value()>31)) return decodeWord(w); + return decodeSimpleInstruction("srs",w); +} + +std::string Disassembler::decodeSru(Word w) { + auto rd2=decodeRd2Operand(w); + if(rd2.type()==Operand::Direct&&(rd2.value()<0||rd2.value()>31)) return decodeWord(w); + return decodeSimpleInstruction("sru",w); +} + +std::string Disassembler::decodeSub(Word w) { + auto dst=decodeDstOperand(w); + auto rd1=decodeRd1Operand(w); + auto rd2=decodeRd2Operand(w); + + if(rd1.type()==Operand::Direct&&rd1.value()==0&&_preferAliases) + return "neg "+str(dst)+", "+str(rd2); + else + return "sub "+str(dst)+", "+str(rd1)+", "+str(rd2); +} + +std::string Disassembler::decodeSw(Word w) { + auto dst=decodeDstOperand(w); + auto rd1=decodeRd1Operand(w); + auto rd2=decodeRd2Operand(w); + + if(dst.value()!=0) return decodeWord(w); + if(rd1.type()!=Operand::Register) return decodeWord(w); + + return "sw "+str(rd1)+", "+str(rd2); +} + +std::string Disassembler::decodeXor(Word w) { + auto dst=decodeDstOperand(w); + auto rd1=decodeRd1Operand(w); + auto rd2=decodeRd2Operand(w); + + if(rd2.type()==Operand::Direct&&rd2.value()==-1&&_preferAliases) + return "not "+str(dst)+", "+str(rd1); + else + return "xor "+str(dst)+", "+str(rd1)+", "+str(rd2); +} + +std::string Disassembler::decodeWord(Word w) { + return ".word 0x"+hex(w); +} Index: tags/1.2/tools/src/lxp32dump/disassembler.h =================================================================== --- tags/1.2/tools/src/lxp32dump/disassembler.h (nonexistent) +++ tags/1.2/tools/src/lxp32dump/disassembler.h (revision 10) @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2016 by Alex I. Kuznetsov. + * + * Part of the LXP32 CPU IP core. + * + * This module defines the Disassembler class which disassembles + * LXP32 executable code. + */ + +#ifndef DISASSEMBLER_H_INCLUDED +#define DISASSEMBLER_H_INCLUDED + +#include +#include +#include + +class Disassembler { +public: + enum Format {Bin,Textio,Dec,Hex}; + typedef std::uint32_t Word; +private: + class Operand { + public: + enum Type {Register,Direct}; + private: + Type _type; + int _value; + public: + Operand(Type t,int value); + Type type() const; + int value() const; + }; + + std::istream &_is; + std::ostream &_os; + Format _fmt; + bool _preferAliases; + int _lineNumber; + Word _pos; +public: + Disassembler(std::istream &is,std::ostream &os); + void setFormat(Format fmt); + void setBase(Word base); + void setPreferAliases(bool b); + void dump(); + + template static std::string hex(const T &w) { + static_assert(std::is_integral::value,"Argument must be of integral type"); + const char *hexstr="0123456789ABCDEF"; + std::string res; + + res.reserve(sizeof(T)*2); + + for(int i=sizeof(T)*8-4;i>=0;i-=4) { + res.push_back(hexstr[(w>>i)&0x0F]); + } + return res; + } +private: + bool getWord(Word &w); + std::string str(const Operand &op); + static Operand decodeRd1Operand(Word w); + static Operand decodeRd2Operand(Word w); + static Operand decodeDstOperand(Word w); + + std::string decodeSimpleInstruction(const std::string &op,Word w); + std::string decodeAdd(Word w); + std::string decodeAnd(Word w); + std::string decodeCall(Word w); + std::string decodeCjmpxx(Word w); + std::string decodeDivs(Word w); + std::string decodeDivu(Word w); + std::string decodeHlt(Word w); + std::string decodeJmp(Word w); + std::string decodeLc(Word w,bool &valid,Word &operand); + std::string decodeLcs(Word w); + std::string decodeLsb(Word w); + std::string decodeLub(Word w); + std::string decodeLw(Word w); + std::string decodeMods(Word w); + std::string decodeModu(Word w); + std::string decodeMul(Word w); + std::string decodeNop(Word w); + std::string decodeOr(Word w); + std::string decodeSb(Word w); + std::string decodeSl(Word w); + std::string decodeSrs(Word w); + std::string decodeSru(Word w); + std::string decodeSub(Word w); + std::string decodeSw(Word w); + std::string decodeXor(Word w); + std::string decodeWord(Word w); +}; + +#endif Index: tags/1.2/tools/src/lxp32dump/main.cpp =================================================================== --- tags/1.2/tools/src/lxp32dump/main.cpp (nonexistent) +++ tags/1.2/tools/src/lxp32dump/main.cpp (revision 10) @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2016 by Alex I. Kuznetsov. + * + * Part of the LXP32 CPU IP core. + * + * Main translation unit for the LXP32 disassembler. + */ + +#ifdef _MSC_VER + #define _CRT_SECURE_NO_WARNINGS +#endif + +#include "disassembler.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +static void displayUsage(std::ostream &os,const char *program) { + os< Base address (for comments only)"< Input format (bin, textio, dec, hex), default: autodetect"< Output file name, default: standard output"<(in.gcount()); + in.clear(); + in.seekg(0); + + Disassembler::Format fmt=Disassembler::Textio; + + for(std::size_t i=0;i +#include +#include +#include +#include +#include + +Generator::Generator(): + _masters(1), + _slaves(1), + _addrWidth(32), + _portSize(32), + _portGranularity(32), + _entityName("intercon"), + _pipelinedArbiter(false), + _registeredFeedback(false), + _unsafeDecoder(false) {} + +void Generator::setMasters(int i) { + if(i<1) throw std::runtime_error("Invalid number of masters"); + _masters=i; +} + +void Generator::setSlaves(int i) { + if(i<1) throw std::runtime_error("Invalid number of slaves"); + _slaves=i; +} + +void Generator::setAddrWidth(int i) { + if(i<1) throw std::runtime_error("Invalid address width"); + _addrWidth=i; +} + +void Generator::setSlaveAddrWidth(int i) { + if(i<1) throw std::runtime_error("Invalid slave address width"); + _slaveAddrWidth=i; +} + +void Generator::setPortSize(int i) { + if(i!=8&&i!=16&&i!=32&&i!=64) + throw std::runtime_error("Invalid port size: 8, 16, 32 or 64 expected"); + _portSize=i; +} + +void Generator::setPortGranularity(int i) { + if(i!=8&&i!=16&&i!=32&&i!=64) + throw std::runtime_error("Invalid port granularity: 8, 16, 32 or 64 expected"); + _portGranularity=i; +} + +void Generator::setEntityName(const std::string &str) try { + if(str.empty()) throw std::exception(); +// First character must be a letter + if(!std::isalpha(str[0])) throw std::exception(); +// Subsequent characters can be letters, digits or underscores + for(std::size_t i=1;iaddrWidth()) throw std::runtime_error("Invalid slave address width"); + if(slaves()>(1<<(addrWidth()-slaveAddrWidth()))) throw std::runtime_error("Invalid slave address width"); + if(slaveAddrWidth()<=_addrRange.low()) throw std::runtime_error("Invalid slave address width"); + + _slaveAddrRange.assign(slaveAddrWidth()-1,_addrRange.low()); + + if(slaves()>1) { + _slaveDecoderRange.assign(_addrRange.high(),slaveAddrWidth()); + if(unsafeDecoder()) { + int requiredSize=0; + while((1<1) { + os<<"signal request: std_logic_vector("<< + _mastersRange.toString()<<");"<\'0\');"<1) { + os<<"signal select_slave: std_logic_vector("<< + _slavesRange.toString()<<");"<1) writeArbiter(os); + writeMasterMux(os); + writeMasterDemux(os); + writeSlaveMux(os); + writeSlaveDemux(os); + + os<<"end architecture;"<0) os<<'&'; + } + os<<';'<\'0\');"<\'0\');"<\'0\');"<SLAVE MUX"<1) { + os<<"cyc_mux<="; + for(int i=0;i0) os<<'\t'; + os<<"(s"<SLAVE DEMUX"<1) { + os<<"select_slave<="; + for(int i=0;i0) os<<'\t'; + os<'-');"<MASTER MUX"<1) { + os<<"ack_mux<="; + for(int i=0;i0) os<<'\t'; + os<<"(m"<MASTER DEMUX"<1) { + for(int i=0;i=0;i--) { + if(value>=static_cast(sizeof(int)*8)) oss.put('0'); + else if((value>>i)&1) oss.put('1'); + else oss.put('0'); + } + oss.put('\"'); + return oss.str(); +} + +std::string Generator::decodedLiteral(int value,int n) { + std::ostringstream oss; + oss.put('\"'); + for(int i=n-1;i>=0;i--) { + if(value==i) oss.put('1'); + else oss.put('0'); + } + oss.put('\"'); + return oss.str(); +} Index: tags/1.2/tools/src/wigen/generator.h =================================================================== --- tags/1.2/tools/src/wigen/generator.h (nonexistent) +++ tags/1.2/tools/src/wigen/generator.h (revision 10) @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2016 by Alex I. Kuznetsov. + * + * Part of the LXP32 CPU IP core. + * + * This module defines the Generator class which generates + * WISHBONE interconnect VHDL description based on provided + * parameters. + */ + +#ifndef GENERATOR_H_INCLUDED +#define GENERATOR_H_INCLUDED + +#include "range.h" + +#include +#include + +class Generator { + int _masters; + int _slaves; + int _addrWidth; + int _slaveAddrWidth; + int _portSize; + int _portGranularity; + + std::string _entityName; + bool _pipelinedArbiter; + bool _registeredFeedback; + bool _unsafeDecoder; + + Range _mastersRange; + Range _slavesRange; + Range _addrRange; + Range _slaveAddrRange; + Range _slaveDecoderRange; + Range _dataRange; + Range _selRange; + + bool _fallbackSlave; + +public: + Generator(); + + void setMasters(int i); + void setSlaves(int i); + void setAddrWidth(int i); + void setSlaveAddrWidth(int i); + void setPortSize(int i); + void setPortGranularity(int i); + void setEntityName(const std::string &str); + void setPipelinedArbiter(bool b); + void setRegisteredFeedback(bool b); + void setUnsafeDecoder(bool b); + + int masters() const; + int slaves() const; + int addrWidth() const; + int slaveAddrWidth() const; + int portSize() const; + int portGranularity() const; + std::string entityName() const; + bool pipelinedArbiter() const; + bool registeredFeedback() const; + bool unsafeDecoder() const; + + void generate(const std::string &filename); + +private: + void prepare(); + void writeBanner(std::ostream &os); + void writePreamble(std::ostream &os); + void writeEntity(std::ostream &os); + void writeArchitecture(std::ostream &os); + + void writeArbiter(std::ostream &os); + void writeMasterMux(std::ostream &os); + void writeMasterDemux(std::ostream &os); + void writeSlaveMux(std::ostream &os); + void writeSlaveDemux(std::ostream &os); + + static std::string binaryLiteral(int value,int n); + static std::string decodedLiteral(int value,int n); +}; + +#endif Index: tags/1.2/tools/src/wigen/main.cpp =================================================================== --- tags/1.2/tools/src/wigen/main.cpp (nonexistent) +++ tags/1.2/tools/src/wigen/main.cpp (revision 10) @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2016 by Alex I. Kuznetsov. + * + * Part of the LXP32 CPU IP core. + * + * Main translation unit for the WISHBONE interconnect generator. + */ + +#include "generator.h" + +#include +#include +#include +#include +#include + +static void displayUsage(std::ostream &os,const char *program) { + os< [ ]"< Number of masters"< Number of slaves"< Master address width"< Slave address width"< Port size"< Port granularity, default: port size"< Entity name, default: \"intercon\""< Output file name, default: \".vhd\""<5) throw std::runtime_error("Too many arguments"); + + int value; + + try { + value=std::stoi(argv[i],nullptr,0); + } + catch(std::exception &) { + throw std::runtime_error("Invalid value"); + } + + switch(mainArg) { + case 0: + gen.setMasters(value); + break; + case 1: + gen.setSlaves(value); + break; + case 2: + gen.setAddrWidth(value); + break; + case 3: + gen.setSlaveAddrWidth(value); + break; + case 4: + gen.setPortSize(value); + break; + case 5: + gen.setPortGranularity(value); + break; + } + mainArg++; + } + } + + if(mainArg<5) throw std::runtime_error("Too few arguments"); + if(mainArg==5) gen.setPortGranularity(gen.portSize()); + + if(outputFileName.empty()) outputFileName=gen.entityName()+".vhd"; + + gen.generate(outputFileName); +} +catch(std::exception &ex) { + std::cerr<<"Error: "< + +Range::Range(): _valid(false) {} + +Range::Range(int h,int l): _high(h),_low(l),_valid(true) { + if(l>h) throw std::runtime_error("Invalid range"); +} + +void Range::assign(int h,int l) { + if(l>h) throw std::runtime_error("Invalid range"); + _high=h; + _low=l; + _valid=true; +} + +void Range::clear() { + _valid=false; +} + +bool Range::valid() const { + return _valid; +} + +int Range::high() const { + if(!_valid) throw std::runtime_error("Invalid range"); + return _high; +} + +int Range::low() const { + if(!_valid) throw std::runtime_error("Invalid range"); + return _low; +} + +int Range::length() const { + if(!_valid) throw std::runtime_error("Invalid range"); + return _high-_low+1; +} + +std::string Range::toString() const { + if(!_valid) throw std::runtime_error("Invalid range"); + return std::to_string(_high)+" downto "+std::to_string(_low); +} Index: tags/1.2/tools/src/wigen/range.h =================================================================== --- tags/1.2/tools/src/wigen/range.h (nonexistent) +++ tags/1.2/tools/src/wigen/range.h (revision 10) @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2016 by Alex I. Kuznetsov. + * + * Part of the LXP32 CPU IP core. + * + * This module defines the Range class which represents + * VHDL array ranges. + */ + +#ifndef RANGE_H_INCLUDED +#define RANGE_H_INCLUDED + +#include + +class Range { + int _high; + int _low; + bool _valid; +public: + Range(); + Range(int h,int l); + + void assign(int h,int l); + void clear(); + + bool valid() const; + int high() const; + int low() const; + int length() const; + std::string toString() const; +}; + +#endif Index: tags/1.2/verify/common_pkg/common_pkg.vhd =================================================================== --- tags/1.2/verify/common_pkg/common_pkg.vhd (nonexistent) +++ tags/1.2/verify/common_pkg/common_pkg.vhd (revision 10) @@ -0,0 +1,26 @@ +--------------------------------------------------------------------- +-- Common package for LXP32 testbenches +-- +-- Part of the LXP32 verification environment +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +package common_pkg is + type rng_state_type is record + seed1: positive; + seed2: positive; + end record; + + -- Generate a pseudo-random value of integer type from [a;b] range + -- Output is stored in x + procedure rand(variable st: inout rng_state_type; a,b: integer; variable x: out integer); + + -- Convert std_logic_vector to a hexadecimal string (similar to + -- the "to_hstring" function from VHDL-2008 + function hex_string(x: std_logic_vector) return string; +end package; Index: tags/1.2/verify/common_pkg/common_pkg_body.vhd =================================================================== --- tags/1.2/verify/common_pkg/common_pkg_body.vhd (nonexistent) +++ tags/1.2/verify/common_pkg/common_pkg_body.vhd (revision 10) @@ -0,0 +1,72 @@ +--------------------------------------------------------------------- +-- Common package for LXP32 testbenches +-- +-- Part of the LXP32 verification environment +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use ieee.math_real.all; + +package body common_pkg is + procedure rand(variable st: inout rng_state_type; a,b: integer; variable x: out integer) is + variable r: real; + begin + assert a<=b report "Invalid range" severity failure; + uniform(st.seed1,st.seed2,r); + r:=r*real(b-a+1); + x:=a+integer(floor(r)); + end procedure; + + function hex_string(x: std_logic_vector) return string is + variable xx: std_logic_vector(x'length-1 downto 0); + variable i: integer:=0; + variable ii: integer; + variable c: integer; + variable high_index: integer; + variable s: string(x'length downto 1); + begin + xx:=x; + loop + ii:=i*4; + exit when ii>xx'high; + if ii+3<=xx'high then + high_index:=ii+3; + else + high_index:=xx'high; + end if; + + if is_x(xx(high_index downto ii)) then + c:=-1; + else + c:=to_integer(unsigned(xx(high_index downto ii))); + end if; + + case c is + when 0 => s(i+1):='0'; + when 1 => s(i+1):='1'; + when 2 => s(i+1):='2'; + when 3 => s(i+1):='3'; + when 4 => s(i+1):='4'; + when 5 => s(i+1):='5'; + when 6 => s(i+1):='6'; + when 7 => s(i+1):='7'; + when 8 => s(i+1):='8'; + when 9 => s(i+1):='9'; + when 10 => s(i+1):='A'; + when 11 => s(i+1):='B'; + when 12 => s(i+1):='C'; + when 13 => s(i+1):='D'; + when 14 => s(i+1):='E'; + when 15 => s(i+1):='F'; + when others => s(i+1):='X'; + end case; + + i:=i+1; + end loop; + return s(i downto 1); + end function; +end package body; Index: tags/1.2/verify/icache/run/ghdl/.gitignore =================================================================== --- tags/1.2/verify/icache/run/ghdl/.gitignore (nonexistent) +++ tags/1.2/verify/icache/run/ghdl/.gitignore (revision 10) @@ -0,0 +1,5 @@ +*.vcd +*.cf +*.o +tb +compile.stamp Index: tags/1.2/verify/icache/run/ghdl/Makefile =================================================================== --- tags/1.2/verify/icache/run/ghdl/Makefile (nonexistent) +++ tags/1.2/verify/icache/run/ghdl/Makefile (revision 10) @@ -0,0 +1,47 @@ +include ../../src/make/sources.make + +GHDL_FLAGS=--std=93 + +WAVE_VCD=wave.vcd +WAVE_OUT=wave.fst + +######################## +# Phony targets +######################## + +all: batch + +.PHONY: all compile batch gui clean + +.PRECIOUS: $(WAVE_OUT) + +compile: compile.stamp + +batch: compile.stamp + ghdl -r $(GHDL_FLAGS) $(TB_MOD) + +gui: $(WAVE_OUT) + gtkwave $(WAVE_OUT) + +clean: + rm -f *.cf + rm -f $(WAVE_VCD) + rm -f $(WAVE_OUT) + rm -f *.o + rm -f $(TB_MOD) + rm -f compile.stamp + +######################## +# Normal targets +######################## + +$(WAVE_OUT): $(WAVE_VCD) + vcd2fst $^ $@ + +$(WAVE_VCD): compile.stamp + ghdl -r $(GHDL_FLAGS) $(TB_MOD) --vcd=$(WAVE_VCD) + +compile.stamp: $(LXP32_RTL) $(COMMON_SRC) $(TB_SRC) + ghdl -a $(GHDL_FLAGS) $(LXP32_RTL) $(COMMON_SRC) $(TB_SRC) + ghdl -e $(GHDL_FLAGS) $(TB_MOD) + echo > compile.stamp Index: tags/1.2/verify/icache/run/vsim/.gitignore =================================================================== --- tags/1.2/verify/icache/run/vsim/.gitignore (nonexistent) +++ tags/1.2/verify/icache/run/vsim/.gitignore (revision 10) @@ -0,0 +1,6 @@ +/work +*.stamp +*.wlf +*.ini +*.o +transcript Index: tags/1.2/verify/icache/run/vsim/Makefile =================================================================== --- tags/1.2/verify/icache/run/vsim/Makefile (nonexistent) +++ tags/1.2/verify/icache/run/vsim/Makefile (revision 10) @@ -0,0 +1,39 @@ +include ../../src/make/sources.make + +VCOMFLAGS=-93 +VSIMFLAGS=-t 1ps + +######################## +# Phony targets +######################## + +all: batch + +.PHONY: all compile batch gui clean + +compile: compile.stamp + +batch: compile.stamp + vsim $(VSIMFLAGS) -do "run -all; quit -f" -c work.$(TB_MOD) + +gui: compile.stamp + vsim $(VSIMFLAGS) work.$(TB_MOD) + +clean: + rm -rf work + rm -f modelsim.ini + rm -f transcript + rm -f vsim.wlf + rm -f compile.stamp + +######################## +# Normal targets +######################## + +compile.stamp: $(LXP32_RTL) $(COMMON_SRC) $(TB_SRC) | work + vcom $(VCOMFLAGS) $(LXP32_RTL) $(COMMON_SRC) $(TB_SRC) + echo > compile.stamp + +work: + vlib work + vmap work work Index: tags/1.2/verify/icache/run/xsim/.gitignore =================================================================== --- tags/1.2/verify/icache/run/xsim/.gitignore (nonexistent) +++ tags/1.2/verify/icache/run/xsim/.gitignore (revision 10) @@ -0,0 +1,10 @@ +/.Xil +/xsim.dir +webtalk* +xelab* +xsim* +xvhdl* +hs_err* +vivado* +*.stamp +*.wdb Index: tags/1.2/verify/icache/run/xsim/Makefile =================================================================== --- tags/1.2/verify/icache/run/xsim/Makefile (nonexistent) +++ tags/1.2/verify/icache/run/xsim/Makefile (revision 10) @@ -0,0 +1,44 @@ +include ../../src/make/sources.make + +ifeq ($(findstring Windows,$(OS)),) + BAT= +else + BAT=.bat +endif + +######################## +# Phony targets +######################## + +all: batch + +.PHONY: all compile batch gui clean + +compile: compile.stamp + +batch: compile.stamp + xsim$(BAT) -R tb_sim + +gui: compile.stamp + xsim$(BAT) -g -onfinish stop -onerror stop tb_sim + +clean: + rm -rf .Xil + rm -rf xsim.dir + rm -f webtalk* + rm -f xelab* + rm -f xsim* + rm -f xvhdl* + rm -f hs_err* + rm -f vivado* + rm -f *.wdb + rm -f compile.stamp + +######################## +# Normal targets +######################## + +compile.stamp: $(LXP32_RTL) $(COMMON_SRC) $(TB_SRC) + xvhdl$(BAT) $(LXP32_RTL) $(COMMON_SRC) $(TB_SRC) + xelab$(BAT) work.tb -s tb_sim -debug typical + echo > compile.stamp Index: tags/1.2/verify/icache/src/make/sources.make =================================================================== --- tags/1.2/verify/icache/src/make/sources.make (nonexistent) +++ tags/1.2/verify/icache/src/make/sources.make (revision 10) @@ -0,0 +1,20 @@ +# CPU RTL + +LXP32_DIR=../../../../rtl +LXP32_RTL=$(LXP32_DIR)/lxp32_ram256x32.vhd\ + $(LXP32_DIR)/lxp32_icache.vhd + +# Common package + +COMMON_PKG_DIR=../../../common_pkg +COMMON_SRC=$(COMMON_PKG_DIR)/common_pkg.vhd $(COMMON_PKG_DIR)/common_pkg_body.vhd + +# Testbench sources + +TB_DIR=../../src/tb +TB_SRC=$(TB_DIR)/tb_pkg.vhd\ + $(TB_DIR)/cpu_model.vhd\ + $(TB_DIR)/ram_model.vhd\ + $(TB_DIR)/tb.vhd + +TB_MOD=tb Index: tags/1.2/verify/icache/src/tb/cpu_model.vhd =================================================================== --- tags/1.2/verify/icache/src/tb/cpu_model.vhd (nonexistent) +++ tags/1.2/verify/icache/src/tb/cpu_model.vhd (revision 10) @@ -0,0 +1,179 @@ +--------------------------------------------------------------------- +-- CPU model +-- +-- Part of the LXP32 instruction cache testbench +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- Requests data from cache +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use ieee.math_real.all; + +use work.common_pkg.all; +use work.tb_pkg.all; + +entity cpu_model is + generic( + BLOCKS: integer; + VERBOSE: boolean + ); + port( + clk_i: in std_logic; + + lli_re_o: out std_logic; + lli_adr_o: out std_logic_vector(29 downto 0); + lli_dat_i: in std_logic_vector(31 downto 0); + lli_busy_i: in std_logic; + + finish_o: out std_logic + ); +end entity; + +architecture sim of cpu_model is + +constant bursts: integer:=10000; + +signal re: std_logic:='0'; +signal lli_adr: std_logic_vector(29 downto 0); + +signal request: std_logic:='0'; +signal request_addr: std_logic_vector(29 downto 0); + +signal finish: std_logic:='0'; + +signal current_latency: integer:=1; +signal max_latency: integer:=-1; +signal total_latency: integer:=0; +signal spurious_misses: integer:=0; + +begin + +process is + variable b: integer:=1; + variable start: integer; + variable size: integer; + variable addr: integer:=0; + variable delay: integer; + variable rng_state: rng_state_type; + variable r: integer; + variable total_requests: integer:=0; +begin + while b<=BLOCKS loop + rand(rng_state,1,10,r); + if r=1 then -- insert large block occasionally + rand(rng_state,1,400,size); + else -- small block + rand(rng_state,1,32,size); + end if; + + rand(rng_state,0,1,r); + if r=0 then -- long jump + rand(rng_state,0,1024,start); + addr:=start; + if VERBOSE then + report "Fetching block #"&integer'image(b)&" at address "&integer'image(addr)& + " of size "&integer'image(size); + end if; + else -- short jump + rand(rng_state,-10,10,r); + start:=addr+r; + if start<0 then + start:=0; + end if; + addr:=start; + if VERBOSE then + report "Fetching block #"&integer'image(b)&" at address "&integer'image(addr)& + " of size "&integer'image(size)&" (short jump)"; + end if; + end if; + + while addr0 then + for i in 1 to delay loop + wait until rising_edge(clk_i); + end loop; + end if; + end loop; + + if (b mod 10000)=0 then + report integer'image(b)&" BLOCKS PROCESSED"; + end if; + + b:=b+1; + end loop; + + report "Number of requests: "&integer'image(total_requests); + report "Maximum latency: "&integer'image(max_latency); + report "Average latency: "&real'image(real(total_latency)/real(total_requests)); + report "Number of spurious misses: "&integer'image(spurious_misses); + + finish<='1'; + wait; +end process; + +lli_re_o<=re; +lli_adr_o<=lli_adr; + +process (clk_i) is +begin + if rising_edge(clk_i) then + if lli_busy_i='0' then + if request='1' then + assert lli_dat_i=(("00"&request_addr) xor xor_constant) + report "Data mismatch: expected 0x"& + hex_string(("00"&request_addr) xor xor_constant)& + ", got 0x"&hex_string(lli_dat_i) + severity failure; + end if; + + request<=re; + request_addr<=lli_adr; + end if; + end if; +end process; + +finish_o<=finish; + +-- Measure latency + +process (clk_i) is +begin + if rising_edge(clk_i) then + if lli_busy_i='0' then + if request='1' then + total_latency<=total_latency+current_latency; + if current_latency>max_latency then + max_latency<=current_latency; + end if; + end if; + current_latency<=1; + else + if lli_dat_i=(("00"&request_addr) xor xor_constant) and current_latency=1 then + spurious_misses<=spurious_misses+1; + end if; + current_latency<=current_latency+1; + end if; + end if; +end process; + +process (clk_i) is +begin + if rising_edge(clk_i) then + assert lli_busy_i='0' or request='1' + report "LLI busy signal asserted without a request" + severity failure; + end if; +end process; + +end architecture; Index: tags/1.2/verify/icache/src/tb/ram_model.vhd =================================================================== --- tags/1.2/verify/icache/src/tb/ram_model.vhd (nonexistent) +++ tags/1.2/verify/icache/src/tb/ram_model.vhd (revision 10) @@ -0,0 +1,79 @@ +--------------------------------------------------------------------- +-- RAM model +-- +-- Part of the LXP32 instruction cache testbench +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- Simulates RAM controller which provides WISHBONE registered +-- feedback interface. +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.common_pkg.all; +use work.tb_pkg.all; + +entity ram_model is + port( + clk_i: in std_logic; + + wbm_cyc_i: in std_logic; + wbm_stb_i: in std_logic; + wbm_cti_i: in std_logic_vector(2 downto 0); + wbm_bte_i: in std_logic_vector(1 downto 0); + wbm_ack_o: out std_logic; + wbm_adr_i: in std_logic_vector(29 downto 0); + wbm_dat_o: out std_logic_vector(31 downto 0) + ); +end entity; + +architecture sim of ram_model is + +signal ack: std_logic:='0'; +signal cycle: std_logic:='0'; + +begin + +wbm_ack_o<=ack; + +process (clk_i) is +begin + if rising_edge(clk_i) then + if wbm_cyc_i='1' and wbm_stb_i='1' and wbm_cti_i="010" and wbm_bte_i="00" then + cycle<='1'; + elsif wbm_cyc_i='0' or (wbm_cyc_i='1' and wbm_stb_i='1' and (wbm_cti_i/="010" or wbm_bte_i/="00")) then + cycle<='0'; + end if; + end if; +end process; + +process is + variable rng_state: rng_state_type; + variable delay: integer; +begin + wait until rising_edge(clk_i) and wbm_cyc_i='1' and wbm_stb_i='1'; + ack<='0'; + +-- Random delay before the first beat + if cycle='0' then + rand(rng_state,0,3,delay); + if delay>0 then + for i in 1 to delay loop + wait until rising_edge(clk_i) and wbm_cyc_i='1' and wbm_stb_i='1'; + end loop; + end if; + end if; + + if ack='0' then + wbm_dat_o<=("00"&wbm_adr_i) xor xor_constant; + ack<='1'; + elsif wbm_cti_i="010" and wbm_bte_i="00" then + wbm_dat_o<=("00"&std_logic_vector(unsigned(wbm_adr_i)+1)) xor xor_constant; + ack<='1'; + end if; +end process; + +end architecture; Index: tags/1.2/verify/icache/src/tb/tb.vhd =================================================================== --- tags/1.2/verify/icache/src/tb/tb.vhd (nonexistent) +++ tags/1.2/verify/icache/src/tb/tb.vhd (revision 10) @@ -0,0 +1,104 @@ +--------------------------------------------------------------------- +-- LXP32 instruction cache verification environment (self-checking +-- testbench) +-- +-- Part of the LXP32 instruction cache testbench +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- Parameters: +-- CACHE_BURST_SIZE: burst size for cache unit +-- CACHE_PREFETCH_SIZE: prefetch distance for cache unit +-- CPU_BLOCKS: number of data blocks to fetch +-- VERBOSE: print more messages +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity tb is + generic( + CACHE_BURST_SIZE: integer:=16; + CACHE_PREFETCH_SIZE: integer:=32; + CPU_BLOCKS: integer:=100000; + VERBOSE: boolean:=false + ); +end entity; + +architecture testbench of tb is + +signal clk: std_logic:='0'; +signal rst: std_logic:='0'; + +signal lli_re: std_logic; +signal lli_adr: std_logic_vector(29 downto 0); +signal lli_dat: std_logic_vector(31 downto 0); +signal lli_busy: std_logic; + +signal wbm_cyc: std_logic; +signal wbm_stb: std_logic; +signal wbm_cti: std_logic_vector(2 downto 0); +signal wbm_bte: std_logic_vector(1 downto 0); +signal wbm_ack: std_logic; +signal wbm_adr: std_logic_vector(29 downto 0); +signal wbm_dat: std_logic_vector(31 downto 0); + +signal finish: std_logic:='0'; + +begin + +clk<=not clk and not finish after 5 ns; + +dut: entity work.lxp32_icache(rtl) + generic map( + BURST_SIZE=>CACHE_BURST_SIZE, + PREFETCH_SIZE=>CACHE_PREFETCH_SIZE + ) + port map( + clk_i=>clk, + rst_i=>rst, + + lli_re_i=>lli_re, + lli_adr_i=>lli_adr, + lli_dat_o=>lli_dat, + lli_busy_o=>lli_busy, + + wbm_cyc_o=>wbm_cyc, + wbm_stb_o=>wbm_stb, + wbm_cti_o=>wbm_cti, + wbm_bte_o=>wbm_bte, + wbm_ack_i=>wbm_ack, + wbm_adr_o=>wbm_adr, + wbm_dat_i=>wbm_dat + ); + +ram_model_inst: entity work.ram_model(sim) + port map( + clk_i=>clk, + + wbm_cyc_i=>wbm_cyc, + wbm_stb_i=>wbm_stb, + wbm_cti_i=>wbm_cti, + wbm_bte_i=>wbm_bte, + wbm_ack_o=>wbm_ack, + wbm_adr_i=>wbm_adr, + wbm_dat_o=>wbm_dat + ); + +cpu_model_inst: entity work.cpu_model(sim) + generic map( + BLOCKS=>CPU_BLOCKS, + VERBOSE=>VERBOSE + ) + port map( + clk_i=>clk, + + lli_re_o=>lli_re, + lli_adr_o=>lli_adr, + lli_dat_i=>lli_dat, + lli_busy_i=>lli_busy, + + finish_o=>finish + ); + +end architecture; Index: tags/1.2/verify/icache/src/tb/tb_pkg.vhd =================================================================== --- tags/1.2/verify/icache/src/tb/tb_pkg.vhd (nonexistent) +++ tags/1.2/verify/icache/src/tb/tb_pkg.vhd (revision 10) @@ -0,0 +1,17 @@ +--------------------------------------------------------------------- +-- LXP32 instruction cache testbench package +-- +-- Part of the LXP32 instruction cache testbench +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- Auxiliary package declaration for the LXP32 instruction cache +-- testbench. +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +package tb_pkg is + constant xor_constant: std_logic_vector(31 downto 0):=X"12345678"; +end package; Index: tags/1.2/verify/lxp32/run/ghdl/.gitignore =================================================================== --- tags/1.2/verify/lxp32/run/ghdl/.gitignore (nonexistent) +++ tags/1.2/verify/lxp32/run/ghdl/.gitignore (revision 10) @@ -0,0 +1,6 @@ +*.ram +*.vcd +*.cf +*.o +tb +compile.stamp Index: tags/1.2/verify/lxp32/run/ghdl/Makefile =================================================================== --- tags/1.2/verify/lxp32/run/ghdl/Makefile (nonexistent) +++ tags/1.2/verify/lxp32/run/ghdl/Makefile (revision 10) @@ -0,0 +1,51 @@ +include ../../src/make/sources.make + +GHDL_FLAGS=--std=93 + +WAVE_VCD=wave.vcd +WAVE_OUT=wave.fst + +######################## +# Phony targets +######################## + +all: batch + +.PHONY: all compile batch gui clean + +.PRECIOUS: $(WAVE_OUT) $(WAVE_VCD) + +compile: compile.stamp $(FIRMWARE) + +batch: compile.stamp $(FIRMWARE) + ghdl -r $(GHDL_FLAGS) $(TB_MOD) + +gui: $(WAVE_OUT) + gtkwave $(WAVE_OUT) + +clean: + rm -f *.cf + rm -f $(WAVE_VCD) + rm -f $(WAVE_OUT) + rm -f $(FIRMWARE) + rm -f *.o + rm -f $(TB_MOD) + rm -f compile.stamp + +######################## +# Normal targets +######################## + +$(WAVE_OUT): $(WAVE_VCD) + vcd2fst $^ $@ + +$(WAVE_VCD): compile.stamp $(FIRMWARE) + -ghdl -r $(GHDL_FLAGS) $(TB_MOD) --vcd=$(WAVE_VCD) + +compile.stamp: $(LXP32_RTL) $(COMMON_SRC) $(PLATFORM_RTL) $(TB_SRC) + ghdl -a $(GHDL_FLAGS) $(LXP32_RTL) $(COMMON_SRC) $(PLATFORM_RTL) $(TB_SRC) + ghdl -e $(GHDL_FLAGS) $(TB_MOD) + echo > compile.stamp + +%.ram: $(FW_SRC_DIR)/%.asm + $(ASM) -f textio $^ -o $@ Index: tags/1.2/verify/lxp32/run/vsim/.gitignore =================================================================== --- tags/1.2/verify/lxp32/run/vsim/.gitignore (nonexistent) +++ tags/1.2/verify/lxp32/run/vsim/.gitignore (revision 10) @@ -0,0 +1,7 @@ +/work +*.ram +*.stamp +*.wlf +*.ini +*.o +transcript Index: tags/1.2/verify/lxp32/run/vsim/Makefile =================================================================== --- tags/1.2/verify/lxp32/run/vsim/Makefile (nonexistent) +++ tags/1.2/verify/lxp32/run/vsim/Makefile (revision 10) @@ -0,0 +1,43 @@ +include ../../src/make/sources.make + +VCOMFLAGS=-93 +VSIMFLAGS=-t 1ps + +######################## +# Phony targets +######################## + +all: batch + +.PHONY: all compile batch gui clean + +compile: compile.stamp + +batch: compile.stamp + vsim $(VSIMFLAGS) -do "run -all; quit -f" -c work.$(TB_MOD) + +gui: compile.stamp + vsim $(VSIMFLAGS) work.$(TB_MOD) + +clean: + rm -rf work + rm -f modelsim.ini + rm -f transcript + rm -f vsim.wlf + rm -f $(FIRMWARE) + rm -f compile.stamp + +######################## +# Normal targets +######################## + +compile.stamp: $(LXP32_RTL) $(COMMON_SRC) $(PLATFORM_RTL) $(TB_SRC) $(FIRMWARE) | work + vcom $(VCOMFLAGS) $(LXP32_RTL) $(COMMON_SRC) $(PLATFORM_RTL) $(TB_SRC) + echo > compile.stamp + +work: + vlib work + vmap work work + +%.ram: $(FW_SRC_DIR)/%.asm + $(ASM) -f textio $^ -o $@ Index: tags/1.2/verify/lxp32/run/xsim/.gitignore =================================================================== --- tags/1.2/verify/lxp32/run/xsim/.gitignore (nonexistent) +++ tags/1.2/verify/lxp32/run/xsim/.gitignore (revision 10) @@ -0,0 +1,11 @@ +/.Xil +/xsim.dir +webtalk* +xelab* +xsim* +xvhdl* +hs_err* +vivado* +*.ram +*.stamp +*.wdb Index: tags/1.2/verify/lxp32/run/xsim/Makefile =================================================================== --- tags/1.2/verify/lxp32/run/xsim/Makefile (nonexistent) +++ tags/1.2/verify/lxp32/run/xsim/Makefile (revision 10) @@ -0,0 +1,48 @@ +include ../../src/make/sources.make + +ifeq ($(findstring Windows,$(OS)),) + BAT= +else + BAT=.bat +endif + +######################## +# Phony targets +######################## + +all: batch + +.PHONY: all compile batch gui clean + +compile: compile.stamp + +batch: compile.stamp + xsim$(BAT) -R tb_sim + +gui: compile.stamp + xsim$(BAT) -g -onfinish stop -onerror stop tb_sim + +clean: + rm -rf .Xil + rm -rf xsim.dir + rm -f webtalk* + rm -f xelab* + rm -f xsim* + rm -f xvhdl* + rm -f hs_err* + rm -f vivado* + rm -f *.wdb + rm -f $(FIRMWARE) + rm -f compile.stamp + +######################## +# Normal targets +######################## + +compile.stamp: $(LXP32_RTL) $(COMMON_SRC) $(PLATFORM_RTL) $(TB_SRC) $(FIRMWARE) + xvhdl$(BAT) $(LXP32_RTL) $(COMMON_SRC) $(PLATFORM_RTL) $(TB_SRC) + xelab$(BAT) work.tb -s tb_sim -debug typical + echo > compile.stamp + +%.ram: $(FW_SRC_DIR)/%.asm + $(ASM) -f textio $^ -o $@ Index: tags/1.2/verify/lxp32/src/firmware/test001.asm =================================================================== --- tags/1.2/verify/lxp32/src/firmware/test001.asm (nonexistent) +++ tags/1.2/verify/lxp32/src/firmware/test001.asm (revision 10) @@ -0,0 +1,482 @@ +/* + * This test verifies that basic instructions + * (data transfers, addition/subtraction, jumps) work. + */ + + lc r100, 0x10000000 // test result output pointer + lc r101, halt + lc r102, bad_jump + lc r103, reg_is_nonzero + +// Check that all registers are zero-initialized after reset +// Ignore r100-r103 which are already used + cjmpne r103, r0, 0 + cjmpne r103, r1, 0 + cjmpne r103, r2, 0 + cjmpne r103, r3, 0 + cjmpne r103, r4, 0 + cjmpne r103, r5, 0 + cjmpne r103, r6, 0 + cjmpne r103, r7, 0 + cjmpne r103, r8, 0 + cjmpne r103, r9, 0 + cjmpne r103, r10, 0 + cjmpne r103, r11, 0 + cjmpne r103, r12, 0 + cjmpne r103, r13, 0 + cjmpne r103, r14, 0 + cjmpne r103, r15, 0 + cjmpne r103, r16, 0 + cjmpne r103, r17, 0 + cjmpne r103, r18, 0 + cjmpne r103, r19, 0 + cjmpne r103, r20, 0 + cjmpne r103, r21, 0 + cjmpne r103, r22, 0 + cjmpne r103, r23, 0 + cjmpne r103, r24, 0 + cjmpne r103, r25, 0 + cjmpne r103, r26, 0 + cjmpne r103, r27, 0 + cjmpne r103, r28, 0 + cjmpne r103, r29, 0 + cjmpne r103, r30, 0 + cjmpne r103, r31, 0 + cjmpne r103, r32, 0 + cjmpne r103, r33, 0 + cjmpne r103, r34, 0 + cjmpne r103, r35, 0 + cjmpne r103, r36, 0 + cjmpne r103, r37, 0 + cjmpne r103, r38, 0 + cjmpne r103, r39, 0 + cjmpne r103, r40, 0 + cjmpne r103, r41, 0 + cjmpne r103, r42, 0 + cjmpne r103, r43, 0 + cjmpne r103, r44, 0 + cjmpne r103, r45, 0 + cjmpne r103, r46, 0 + cjmpne r103, r47, 0 + cjmpne r103, r48, 0 + cjmpne r103, r49, 0 + cjmpne r103, r50, 0 + cjmpne r103, r51, 0 + cjmpne r103, r52, 0 + cjmpne r103, r53, 0 + cjmpne r103, r54, 0 + cjmpne r103, r55, 0 + cjmpne r103, r56, 0 + cjmpne r103, r57, 0 + cjmpne r103, r58, 0 + cjmpne r103, r59, 0 + cjmpne r103, r60, 0 + cjmpne r103, r61, 0 + cjmpne r103, r62, 0 + cjmpne r103, r63, 0 + cjmpne r103, r64, 0 + cjmpne r103, r65, 0 + cjmpne r103, r66, 0 + cjmpne r103, r67, 0 + cjmpne r103, r68, 0 + cjmpne r103, r69, 0 + cjmpne r103, r70, 0 + cjmpne r103, r71, 0 + cjmpne r103, r72, 0 + cjmpne r103, r73, 0 + cjmpne r103, r74, 0 + cjmpne r103, r75, 0 + cjmpne r103, r76, 0 + cjmpne r103, r77, 0 + cjmpne r103, r78, 0 + cjmpne r103, r79, 0 + cjmpne r103, r80, 0 + cjmpne r103, r81, 0 + cjmpne r103, r82, 0 + cjmpne r103, r83, 0 + cjmpne r103, r84, 0 + cjmpne r103, r85, 0 + cjmpne r103, r86, 0 + cjmpne r103, r87, 0 + cjmpne r103, r88, 0 + cjmpne r103, r89, 0 + cjmpne r103, r90, 0 + cjmpne r103, r91, 0 + cjmpne r103, r92, 0 + cjmpne r103, r93, 0 + cjmpne r103, r94, 0 + cjmpne r103, r95, 0 + cjmpne r103, r96, 0 + cjmpne r103, r97, 0 + cjmpne r103, r98, 0 + cjmpne r103, r99, 0 + cjmpne r103, r104, 0 + cjmpne r103, r105, 0 + cjmpne r103, r106, 0 + cjmpne r103, r107, 0 + cjmpne r103, r108, 0 + cjmpne r103, r109, 0 + cjmpne r103, r110, 0 + cjmpne r103, r111, 0 + cjmpne r103, r112, 0 + cjmpne r103, r113, 0 + cjmpne r103, r114, 0 + cjmpne r103, r115, 0 + cjmpne r103, r116, 0 + cjmpne r103, r117, 0 + cjmpne r103, r118, 0 + cjmpne r103, r119, 0 + cjmpne r103, r120, 0 + cjmpne r103, r121, 0 + cjmpne r103, r122, 0 + cjmpne r103, r123, 0 + cjmpne r103, r124, 0 + cjmpne r103, r125, 0 + cjmpne r103, r126, 0 + cjmpne r103, r127, 0 + cjmpne r103, r128, 0 + cjmpne r103, r129, 0 + cjmpne r103, r130, 0 + cjmpne r103, r131, 0 + cjmpne r103, r132, 0 + cjmpne r103, r133, 0 + cjmpne r103, r134, 0 + cjmpne r103, r135, 0 + cjmpne r103, r136, 0 + cjmpne r103, r137, 0 + cjmpne r103, r138, 0 + cjmpne r103, r139, 0 + cjmpne r103, r140, 0 + cjmpne r103, r141, 0 + cjmpne r103, r142, 0 + cjmpne r103, r143, 0 + cjmpne r103, r144, 0 + cjmpne r103, r145, 0 + cjmpne r103, r146, 0 + cjmpne r103, r147, 0 + cjmpne r103, r148, 0 + cjmpne r103, r149, 0 + cjmpne r103, r150, 0 + cjmpne r103, r151, 0 + cjmpne r103, r152, 0 + cjmpne r103, r153, 0 + cjmpne r103, r154, 0 + cjmpne r103, r155, 0 + cjmpne r103, r156, 0 + cjmpne r103, r157, 0 + cjmpne r103, r158, 0 + cjmpne r103, r159, 0 + cjmpne r103, r160, 0 + cjmpne r103, r161, 0 + cjmpne r103, r162, 0 + cjmpne r103, r163, 0 + cjmpne r103, r164, 0 + cjmpne r103, r165, 0 + cjmpne r103, r166, 0 + cjmpne r103, r167, 0 + cjmpne r103, r168, 0 + cjmpne r103, r169, 0 + cjmpne r103, r170, 0 + cjmpne r103, r171, 0 + cjmpne r103, r172, 0 + cjmpne r103, r173, 0 + cjmpne r103, r174, 0 + cjmpne r103, r175, 0 + cjmpne r103, r176, 0 + cjmpne r103, r177, 0 + cjmpne r103, r178, 0 + cjmpne r103, r179, 0 + cjmpne r103, r180, 0 + cjmpne r103, r181, 0 + cjmpne r103, r182, 0 + cjmpne r103, r183, 0 + cjmpne r103, r184, 0 + cjmpne r103, r185, 0 + cjmpne r103, r186, 0 + cjmpne r103, r187, 0 + cjmpne r103, r188, 0 + cjmpne r103, r189, 0 + cjmpne r103, r190, 0 + cjmpne r103, r191, 0 + cjmpne r103, r192, 0 + cjmpne r103, r193, 0 + cjmpne r103, r194, 0 + cjmpne r103, r195, 0 + cjmpne r103, r196, 0 + cjmpne r103, r197, 0 + cjmpne r103, r198, 0 + cjmpne r103, r199, 0 + cjmpne r103, r200, 0 + cjmpne r103, r201, 0 + cjmpne r103, r202, 0 + cjmpne r103, r203, 0 + cjmpne r103, r204, 0 + cjmpne r103, r205, 0 + cjmpne r103, r206, 0 + cjmpne r103, r207, 0 + cjmpne r103, r208, 0 + cjmpne r103, r209, 0 + cjmpne r103, r210, 0 + cjmpne r103, r211, 0 + cjmpne r103, r212, 0 + cjmpne r103, r213, 0 + cjmpne r103, r214, 0 + cjmpne r103, r215, 0 + cjmpne r103, r216, 0 + cjmpne r103, r217, 0 + cjmpne r103, r218, 0 + cjmpne r103, r219, 0 + cjmpne r103, r220, 0 + cjmpne r103, r221, 0 + cjmpne r103, r222, 0 + cjmpne r103, r223, 0 + cjmpne r103, r224, 0 + cjmpne r103, r225, 0 + cjmpne r103, r226, 0 + cjmpne r103, r227, 0 + cjmpne r103, r228, 0 + cjmpne r103, r229, 0 + cjmpne r103, r230, 0 + cjmpne r103, r231, 0 + cjmpne r103, r232, 0 + cjmpne r103, r233, 0 + cjmpne r103, r234, 0 + cjmpne r103, r235, 0 + cjmpne r103, r236, 0 + cjmpne r103, r237, 0 + cjmpne r103, r238, 0 + cjmpne r103, r239, 0 + cjmpne r103, r240, 0 + cjmpne r103, r241, 0 + cjmpne r103, r242, 0 + cjmpne r103, r243, 0 + cjmpne r103, r244, 0 + cjmpne r103, r245, 0 + cjmpne r103, r246, 0 + cjmpne r103, r247, 0 + cjmpne r103, r248, 0 + cjmpne r103, r249, 0 + cjmpne r103, r250, 0 + cjmpne r103, r251, 0 + cjmpne r103, r252, 0 + cjmpne r103, r253, 0 + cjmpne r103, r254, 0 + cjmpne r103, r255, 0 + lc r0, jump0 + jmp r0 + +reg_is_nonzero: + sw r100, 2 // failure: register is not initialized + jmp r101 + +// Test different jump conditions +jump0: + lc r0, jump1 + jmp r0 + sw r100, 3 // failure: this instruction should not be reachable + jmp r101 + +jump1: + lc r0, jump2 + mov r1, 100 + cjmpne r0, r1, 101 + sw r100, 4 // failure: required jump is not taken + jmp r101 + +jump2: + lc r0, jump3 + cjmpe r0, r1, 100 + sw r100, 5 // failure: required jump is not taken + jmp r101 + +jump3: + lc r0, jump4 + cjmpuge r0, r1, 99 + sw r100, 6 // failure: required jump is not taken + jmp r101 + +jump4: + lc r0, jump5 + cjmpuge r0, r1, 100 + sw r100, 7 // failure: required jump is not taken + jmp r101 + +jump5: + lc r0, jump6 + cjmpug r0, r1, 99 + sw r100, 8 // failure: required jump is not taken + jmp r101 + +jump6: + lc r0, jump7 + cjmpsge r0, r1, -128 + sw r100, 9 // failure: required jump is not taken + jmp r101 + +jump7: + lc r0, jump8 + cjmpsge r0, r1, 100 + sw r100, 10 // failure: required jump is not taken + jmp r101 + +jump8: + lc r0, jump9 + cjmpsg r0, r1, 99 + sw r100, 11 // failure: required jump is not taken + jmp r101 + +jump9: + lc r0, 2227053353 + lc r1, 2933288161 + cjmpug r102, r0, r1 + + lc r0, 3957963761 + lc r1, 4048130130 + cjmpug r102, r0, r1 + + lc r0, 1021028019 + lc r1, 2570980487 + cjmpug r102, r0, r1 + + lc r0, 470638116 + lc r1, 3729241862 + cjmpug r102, r0, r1 + + lc r0, 2794175299 + lc r1, 3360494259 + cjmpug r102, r0, r1 + + lc r0, 522532873 + lc r1, 2103051039 + cjmpug r102, r0, r1 + + lc r0, 994440598 + lc r1, 4241216605 + cjmpug r102, r0, r1 + + lc r0, 176753939 + lc r1, 850320156 + cjmpug r102, r0, r1 + + lc r0, 3998259744 + lc r1, 4248205376 + cjmpug r102, r0, r1 + + lc r0, 3695803806 + lc r1, 4130490642 + cjmpug r102, r0, r1 + + lc r0, -798605244 + lc r1, -233549907 + cjmpsg r102, r0, r1 + + lc r0, -1221540757 + lc r1, 580991794 + cjmpsg r102, r0, r1 + + lc r0, -1651432714 + lc r1, -635466783 + cjmpsg r102, r0, r1 + + lc r0, 43633328 + lc r1, 1235055289 + cjmpsg r102, r0, r1 + + lc r0, -2132159079 + lc r1, -981565396 + cjmpsg r102, r0, r1 + + lc r0, -859182414 + lc r1, -697843885 + cjmpsg r102, r0, r1 + + lc r0, 1720638509 + lc r1, 2127959231 + cjmpsg r102, r0, r1 + + lc r0, -1888878751 + lc r1, 1230499715 + cjmpsg r102, r0, r1 + + lc r0, 517066081 + lc r1, 1914084509 + cjmpsg r102, r0, r1 + + lc r0, -266475918 + lc r1, 2001358724 + cjmpsg r102, r0, r1 + + mov r1, 100 + cjmpe r102, r1, 101 + cjmpne r102, r1, 100 + cjmpuge r102, r1, 101 + cjmpug r102, r1, 100 + cjmpug r102, r1, 101 + cjmpsge r102, r1, 101 + cjmpsg r102, r1, 101 + cjmpsg r102, r1, 100 + cjmpsg r102, -128, r1 + lc r0, jump10 + jmp r0 + +bad_jump: + sw r100, 12 // failure: jump should not be taken + jmp r101 + +jump10: + +// Copy itself to another portion of memory + mov r0, 0 // source pointer + lc r1, 0x00008000 // destination pointer + lc r2, halt@2 // size of block to copy, in bytes + lc r32, copy_loop + +copy_loop: + lw r3, r0 + sw r1, r3 + add r0, r0, 4 + add r1, r1, 4 + cjmpul r32, r0, r2 + +// Calculate sum of program body in a post-condition loop + mov r0, 0 // pointer + mov r16, 0 // sum + lc r32, sum_loop + +sum_loop: + lw r1, r0 + add r16, r16, r1 + add r0, r0, 4 + cjmpul r32, r0, r2 + +// Calculate sum of copied program body with negative sign, in a pre-condition loop + lc r0, 0x00008000 // pointer + add r2, r0, r2 // end pointer + mov r17, 0 // sum + lc r32, sum2_loop + lc r33, sum2_end + +sum2_loop: + cjmpuge r33, r0, r2 + lw r1, r0 + sub r17, r17, r1 + add r0, r0, 4 + jmp r32 + sw r100, 13 // failure: this instruction should not be reachable + jmp r101 + +sum2_end: + +// Check that sums are equal (but with opposite signs) + add r0, r16, r17 // r0 should be zero now + lc r32, success + cjmpe r32, r0, 0 + sw r100, 14 // failure: results do not match + jmp r101 + +success: + sw r100, 1 + +halt: + hlt + jmp r101 Index: tags/1.2/verify/lxp32/src/firmware/test002.asm =================================================================== --- tags/1.2/verify/lxp32/src/firmware/test002.asm (nonexistent) +++ tags/1.2/verify/lxp32/src/firmware/test002.asm (revision 10) @@ -0,0 +1,93 @@ +/* + * This test calculates a few Fibonacci sequence members + * end compares them to pre-calculated values. + */ + + lc r100, 0x10000000 // test result output pointer + lc r101, halt + +// Calculate Fibonacci sequence members + mov r16, 0 // current member + mov r17, 1 // next member + lc r18, 0 // counter + lc r19, 0x00008000 // destination pointer + lc r32, calc_loop + +calc_loop: + sw r19, r16 + add r19, r19, 4 + add r18, r18, 1 + add r0, r16, r17 + mov r16, r17 + mov r17, r0 + cjmpul r32, r18, 40 + +// Compare + lc r16, 0x00008000 + lc r17, expected + mov r18, 0 // counter + lc r32, comp_loop + lc r33, comp_differ + +comp_loop: + lw r0, r16 + lw r1, r17 + cjmpne r33, r0, r1 + add r16, r16, 4 + add r17, r17, 4 + add r18, r18, 1 + cjmpul r32, r18, 40 + +// Everything seems to be OK + sw r100, 1 + +halt: + hlt + jmp r101 + +comp_differ: + sw r100, 2 + jmp r101 + +// Expected (pre-calculated) values +expected: + .word 0 + .word 1 + .word 1 + .word 2 + .word 3 + .word 5 + .word 8 + .word 13 + .word 21 + .word 34 + .word 55 + .word 89 + .word 144 + .word 233 + .word 377 + .word 610 + .word 987 + .word 1597 + .word 2584 + .word 4181 + .word 6765 + .word 10946 + .word 17711 + .word 28657 + .word 46368 + .word 75025 + .word 121393 + .word 196418 + .word 317811 + .word 514229 + .word 832040 + .word 1346269 + .word 2178309 + .word 3524578 + .word 5702887 + .word 9227465 + .word 14930352 + .word 24157817 + .word 39088169 + .word 63245986 Index: tags/1.2/verify/lxp32/src/firmware/test003.asm =================================================================== --- tags/1.2/verify/lxp32/src/firmware/test003.asm (nonexistent) +++ tags/1.2/verify/lxp32/src/firmware/test003.asm (revision 10) @@ -0,0 +1,43 @@ +/* + * This test verifies that basic logical operations + * (and, xor, or, not) work. + */ + + lc r100, 0x10000000 // test result output pointer + lc r101, halt + lc r102, failure + + lc r0, 0xD54B65C0 + lc r1, 0xCE8870A8 + lc r16, 0x10000004 // destination pointer + + and r2, r0, r1 + sw r16, r2 + lc r3, 0xC4086080 + cjmpne r102, r2, r3 + + or r2, r0, r1 + sw r16, r2 + lc r3, 0xDFCB75E8 + cjmpne r102, r2, r3 + + xor r2, r0, r1 + sw r16, r2 + lc r3, 0x1BC31568 + cjmpne r102, r2, r3 + +// Note: "not dst, src" is just an alias for "xor dst, src, -1" + not r2, r0 + sw r16, r2 + lc r3, 0x2AB49A3F + cjmpne r102, r2, r3 + + sw r100, 1 + jmp r101 + +failure: + sw r100, 2 + +halt: + hlt + jmp r101 Index: tags/1.2/verify/lxp32/src/firmware/test004.asm =================================================================== --- tags/1.2/verify/lxp32/src/firmware/test004.asm (nonexistent) +++ tags/1.2/verify/lxp32/src/firmware/test004.asm (revision 10) @@ -0,0 +1,548 @@ +/* + * This test verifies that nop instruction does not change + * register values. + */ + + lc r0, failure + nop + mov r1, 1 + nop + mov r2, 2 + mov r3, 3 + nop + mov r4, 4 + mov r5, 5 + mov r6, 6 + nop + nop + mov r7, 7 + mov r8, 8 + mov r9, 9 + nop + mov r10, 10 + mov r11, 11 + mov r12, 12 + mov r13, 13 + mov r14, 14 + mov r15, 15 + mov r16, 16 + mov r17, 17 + mov r18, 18 + mov r19, 19 + mov r20, 20 + mov r21, 21 + mov r22, 22 + mov r23, 23 + mov r24, 24 + mov r25, 25 + mov r26, 26 + mov r27, 27 + mov r28, 28 + mov r29, 29 + mov r30, 30 + mov r31, 31 + mov r32, 32 + mov r33, 33 + mov r34, 34 + mov r35, 35 + mov r36, 36 + mov r37, 37 + mov r38, 38 + mov r39, 39 + mov r40, 40 + mov r41, 41 + mov r42, 42 + mov r43, 43 + mov r44, 44 + mov r45, 45 + mov r46, 46 + mov r47, 47 + mov r48, 48 + mov r49, 49 + mov r50, 50 + mov r51, 51 + mov r52, 52 + mov r53, 53 + mov r54, 54 + mov r55, 55 + mov r56, 56 + mov r57, 57 + mov r58, 58 + mov r59, 59 + mov r60, 60 + mov r61, 61 + mov r62, 62 + mov r63, 63 + mov r64, 64 + mov r65, 65 + mov r66, 66 + mov r67, 67 + mov r68, 68 + mov r69, 69 + mov r70, 70 + mov r71, 71 + mov r72, 72 + mov r73, 73 + mov r74, 74 + mov r75, 75 + mov r76, 76 + mov r77, 77 + mov r78, 78 + mov r79, 79 + mov r80, 80 + mov r81, 81 + mov r82, 82 + mov r83, 83 + mov r84, 84 + mov r85, 85 + mov r86, 86 + mov r87, 87 + mov r88, 88 + mov r89, 89 + mov r90, 90 + mov r91, 91 + mov r92, 92 + mov r93, 93 + mov r94, 94 + mov r95, 95 + mov r96, 96 + mov r97, 97 + mov r98, 98 + mov r99, 99 + mov r100, 0 + mov r101, 1 + mov r102, 2 + mov r103, 3 + mov r104, 4 + mov r105, 5 + mov r106, 6 + mov r107, 7 + mov r108, 8 + mov r109, 9 + mov r110, 10 + mov r111, 11 + mov r112, 12 + mov r113, 13 + mov r114, 14 + mov r115, 15 + mov r116, 16 + mov r117, 17 + mov r118, 18 + mov r119, 19 + mov r120, 20 + mov r121, 21 + mov r122, 22 + mov r123, 23 + mov r124, 24 + mov r125, 25 + mov r126, 26 + mov r127, 27 + mov r128, 28 + mov r129, 29 + mov r130, 30 + mov r131, 31 + mov r132, 32 + mov r133, 33 + mov r134, 34 + mov r135, 35 + mov r136, 36 + mov r137, 37 + mov r138, 38 + mov r139, 39 + mov r140, 40 + mov r141, 41 + mov r142, 42 + mov r143, 43 + mov r144, 44 + mov r145, 45 + mov r146, 46 + mov r147, 47 + mov r148, 48 + mov r149, 49 + mov r150, 50 + mov r151, 51 + mov r152, 52 + mov r153, 53 + mov r154, 54 + mov r155, 55 + mov r156, 56 + mov r157, 57 + mov r158, 58 + mov r159, 59 + mov r160, 60 + mov r161, 61 + mov r162, 62 + mov r163, 63 + mov r164, 64 + mov r165, 65 + mov r166, 66 + mov r167, 67 + mov r168, 68 + mov r169, 69 + mov r170, 70 + mov r171, 71 + mov r172, 72 + mov r173, 73 + mov r174, 74 + mov r175, 75 + mov r176, 76 + mov r177, 77 + mov r178, 78 + mov r179, 79 + mov r180, 80 + mov r181, 81 + mov r182, 82 + mov r183, 83 + mov r184, 84 + mov r185, 85 + mov r186, 86 + mov r187, 87 + mov r188, 88 + mov r189, 89 + mov r190, 90 + mov r191, 91 + mov r192, 92 + mov r193, 93 + mov r194, 94 + mov r195, 95 + mov r196, 96 + mov r197, 97 + mov r198, 98 + mov r199, 99 + mov r200, 0 + mov r201, 1 + mov r202, 2 + mov r203, 3 + mov r204, 4 + mov r205, 5 + mov r206, 6 + mov r207, 7 + mov r208, 8 + mov r209, 9 + mov r210, 10 + mov r211, 11 + mov r212, 12 + mov r213, 13 + mov r214, 14 + mov r215, 15 + mov r216, 16 + mov r217, 17 + mov r218, 18 + mov r219, 19 + mov r220, 20 + mov r221, 21 + mov r222, 22 + mov r223, 23 + mov r224, 24 + mov r225, 25 + mov r226, 26 + mov r227, 27 + mov r228, 28 + mov r229, 29 + mov r230, 30 + mov r231, 31 + mov r232, 32 + mov r233, 33 + mov r234, 34 + mov r235, 35 + mov r236, 36 + mov r237, 37 + mov r238, 38 + mov r239, 39 + mov r240, 40 + mov r241, 41 + mov r242, 42 + mov r243, 43 + mov r244, 44 + mov r245, 45 + mov r246, 46 + mov r247, 47 + mov r248, 48 + mov r249, 49 + mov r250, 50 + mov r251, 51 + mov r252, 52 + mov r253, 53 + mov r254, 54 + mov r255, 55 + + nop + nop + nop + + cjmpne r0, r1, 1 + nop + cjmpne r0, r2, 2 + nop + nop + cjmpne r0, r3, 3 + cjmpne r0, r4, 4 + cjmpne r0, r5, 5 + nop + cjmpne r0, r6, 6 + cjmpne r0, r7, 7 + cjmpne r0, r8, 8 + cjmpne r0, r9, 9 + cjmpne r0, r10, 10 + cjmpne r0, r11, 11 + nop + nop + nop + cjmpne r0, r12, 12 + cjmpne r0, r13, 13 + cjmpne r0, r14, 14 + cjmpne r0, r15, 15 + cjmpne r0, r16, 16 + cjmpne r0, r17, 17 + cjmpne r0, r18, 18 + cjmpne r0, r19, 19 + cjmpne r0, r20, 20 + cjmpne r0, r21, 21 + cjmpne r0, r22, 22 + cjmpne r0, r23, 23 + cjmpne r0, r24, 24 + cjmpne r0, r25, 25 + cjmpne r0, r26, 26 + cjmpne r0, r27, 27 + cjmpne r0, r28, 28 + cjmpne r0, r29, 29 + cjmpne r0, r30, 30 + cjmpne r0, r31, 31 + cjmpne r0, r32, 32 + cjmpne r0, r33, 33 + cjmpne r0, r34, 34 + cjmpne r0, r35, 35 + cjmpne r0, r36, 36 + cjmpne r0, r37, 37 + cjmpne r0, r38, 38 + cjmpne r0, r39, 39 + cjmpne r0, r40, 40 + cjmpne r0, r41, 41 + cjmpne r0, r42, 42 + cjmpne r0, r43, 43 + cjmpne r0, r44, 44 + cjmpne r0, r45, 45 + cjmpne r0, r46, 46 + cjmpne r0, r47, 47 + cjmpne r0, r48, 48 + cjmpne r0, r49, 49 + cjmpne r0, r50, 50 + cjmpne r0, r51, 51 + cjmpne r0, r52, 52 + cjmpne r0, r53, 53 + cjmpne r0, r54, 54 + cjmpne r0, r55, 55 + cjmpne r0, r56, 56 + cjmpne r0, r57, 57 + cjmpne r0, r58, 58 + cjmpne r0, r59, 59 + cjmpne r0, r60, 60 + cjmpne r0, r61, 61 + cjmpne r0, r62, 62 + cjmpne r0, r63, 63 + cjmpne r0, r64, 64 + cjmpne r0, r65, 65 + cjmpne r0, r66, 66 + cjmpne r0, r67, 67 + cjmpne r0, r68, 68 + cjmpne r0, r69, 69 + cjmpne r0, r70, 70 + cjmpne r0, r71, 71 + cjmpne r0, r72, 72 + cjmpne r0, r73, 73 + cjmpne r0, r74, 74 + cjmpne r0, r75, 75 + cjmpne r0, r76, 76 + cjmpne r0, r77, 77 + cjmpne r0, r78, 78 + cjmpne r0, r79, 79 + cjmpne r0, r80, 80 + cjmpne r0, r81, 81 + cjmpne r0, r82, 82 + cjmpne r0, r83, 83 + cjmpne r0, r84, 84 + cjmpne r0, r85, 85 + cjmpne r0, r86, 86 + cjmpne r0, r87, 87 + cjmpne r0, r88, 88 + cjmpne r0, r89, 89 + cjmpne r0, r90, 90 + cjmpne r0, r91, 91 + cjmpne r0, r92, 92 + cjmpne r0, r93, 93 + cjmpne r0, r94, 94 + cjmpne r0, r95, 95 + cjmpne r0, r96, 96 + cjmpne r0, r97, 97 + cjmpne r0, r98, 98 + cjmpne r0, r99, 99 + cjmpne r0, r100, 0 + cjmpne r0, r101, 1 + cjmpne r0, r102, 2 + cjmpne r0, r103, 3 + cjmpne r0, r104, 4 + cjmpne r0, r105, 5 + cjmpne r0, r106, 6 + cjmpne r0, r107, 7 + cjmpne r0, r108, 8 + cjmpne r0, r109, 9 + cjmpne r0, r110, 10 + cjmpne r0, r111, 11 + cjmpne r0, r112, 12 + cjmpne r0, r113, 13 + cjmpne r0, r114, 14 + cjmpne r0, r115, 15 + cjmpne r0, r116, 16 + cjmpne r0, r117, 17 + cjmpne r0, r118, 18 + cjmpne r0, r119, 19 + cjmpne r0, r120, 20 + cjmpne r0, r121, 21 + cjmpne r0, r122, 22 + cjmpne r0, r123, 23 + cjmpne r0, r124, 24 + cjmpne r0, r125, 25 + cjmpne r0, r126, 26 + cjmpne r0, r127, 27 + cjmpne r0, r128, 28 + cjmpne r0, r129, 29 + cjmpne r0, r130, 30 + cjmpne r0, r131, 31 + cjmpne r0, r132, 32 + cjmpne r0, r133, 33 + cjmpne r0, r134, 34 + cjmpne r0, r135, 35 + cjmpne r0, r136, 36 + cjmpne r0, r137, 37 + cjmpne r0, r138, 38 + cjmpne r0, r139, 39 + cjmpne r0, r140, 40 + cjmpne r0, r141, 41 + cjmpne r0, r142, 42 + cjmpne r0, r143, 43 + cjmpne r0, r144, 44 + cjmpne r0, r145, 45 + cjmpne r0, r146, 46 + cjmpne r0, r147, 47 + cjmpne r0, r148, 48 + cjmpne r0, r149, 49 + cjmpne r0, r150, 50 + cjmpne r0, r151, 51 + cjmpne r0, r152, 52 + cjmpne r0, r153, 53 + cjmpne r0, r154, 54 + cjmpne r0, r155, 55 + cjmpne r0, r156, 56 + cjmpne r0, r157, 57 + cjmpne r0, r158, 58 + cjmpne r0, r159, 59 + cjmpne r0, r160, 60 + cjmpne r0, r161, 61 + cjmpne r0, r162, 62 + cjmpne r0, r163, 63 + cjmpne r0, r164, 64 + cjmpne r0, r165, 65 + cjmpne r0, r166, 66 + cjmpne r0, r167, 67 + cjmpne r0, r168, 68 + cjmpne r0, r169, 69 + cjmpne r0, r170, 70 + cjmpne r0, r171, 71 + cjmpne r0, r172, 72 + cjmpne r0, r173, 73 + cjmpne r0, r174, 74 + cjmpne r0, r175, 75 + cjmpne r0, r176, 76 + cjmpne r0, r177, 77 + cjmpne r0, r178, 78 + cjmpne r0, r179, 79 + cjmpne r0, r180, 80 + cjmpne r0, r181, 81 + cjmpne r0, r182, 82 + cjmpne r0, r183, 83 + cjmpne r0, r184, 84 + cjmpne r0, r185, 85 + cjmpne r0, r186, 86 + cjmpne r0, r187, 87 + cjmpne r0, r188, 88 + cjmpne r0, r189, 89 + cjmpne r0, r190, 90 + cjmpne r0, r191, 91 + cjmpne r0, r192, 92 + cjmpne r0, r193, 93 + cjmpne r0, r194, 94 + cjmpne r0, r195, 95 + cjmpne r0, r196, 96 + cjmpne r0, r197, 97 + cjmpne r0, r198, 98 + cjmpne r0, r199, 99 + cjmpne r0, r200, 0 + cjmpne r0, r201, 1 + cjmpne r0, r202, 2 + cjmpne r0, r203, 3 + cjmpne r0, r204, 4 + cjmpne r0, r205, 5 + cjmpne r0, r206, 6 + cjmpne r0, r207, 7 + cjmpne r0, r208, 8 + cjmpne r0, r209, 9 + cjmpne r0, r210, 10 + cjmpne r0, r211, 11 + cjmpne r0, r212, 12 + cjmpne r0, r213, 13 + cjmpne r0, r214, 14 + cjmpne r0, r215, 15 + cjmpne r0, r216, 16 + cjmpne r0, r217, 17 + cjmpne r0, r218, 18 + cjmpne r0, r219, 19 + cjmpne r0, r220, 20 + cjmpne r0, r221, 21 + cjmpne r0, r222, 22 + cjmpne r0, r223, 23 + cjmpne r0, r224, 24 + cjmpne r0, r225, 25 + cjmpne r0, r226, 26 + cjmpne r0, r227, 27 + cjmpne r0, r228, 28 + cjmpne r0, r229, 29 + cjmpne r0, r230, 30 + cjmpne r0, r231, 31 + cjmpne r0, r232, 32 + cjmpne r0, r233, 33 + cjmpne r0, r234, 34 + cjmpne r0, r235, 35 + cjmpne r0, r236, 36 + cjmpne r0, r237, 37 + cjmpne r0, r238, 38 + cjmpne r0, r239, 39 + cjmpne r0, r240, 40 + cjmpne r0, r241, 41 + cjmpne r0, r242, 42 + cjmpne r0, r243, 43 + cjmpne r0, r244, 44 + cjmpne r0, r245, 45 + cjmpne r0, r246, 46 + cjmpne r0, r247, 47 + cjmpne r0, r248, 48 + cjmpne r0, r249, 49 + cjmpne r0, r250, 50 + cjmpne r0, r251, 51 + cjmpne r0, r252, 52 + cjmpne r0, r253, 53 + cjmpne r0, r254, 54 + cjmpne r0, r255, 55 + + lc r100, 0x10000000 + lc r101, halt + sw r100, 1 + jmp r101 + +failure: + lc r100, 0x10000000 + lc r101, halt + sw r100, 2 + +halt: + hlt + jmp r101 Index: tags/1.2/verify/lxp32/src/firmware/test005.asm =================================================================== --- tags/1.2/verify/lxp32/src/firmware/test005.asm (nonexistent) +++ tags/1.2/verify/lxp32/src/firmware/test005.asm (revision 10) @@ -0,0 +1,81 @@ +/* + * This test verifies bytewise DBUS access + */ + + lc r100, 0x10000000 // test result output pointer + lc r101, halt + lc r102, failure + + lc r16, 0x10000004 // output pointer + lc r17, data // input pointer + +// Check for bytewise read + lc r18, 0xbc + lc r19, 0x9a + lc r20, 0x78 + lc r21, 0x56 + lc r22, 0xffffffbc + lc r23, 0xffffff9a + lc r24, 0x78 + lc r25, 0x56 + + lub r0, r17 + sw r16, r0 + cjmpne r102, r0, r18 + add r17, r17, 1 + lub r0, r17 + sw r16, r0 + cjmpne r102, r0, r19 + add r17, r17, 1 + lub r0, r17 + sw r16, r0 + cjmpne r102, r0, r20 + add r17, r17, 1 + lub r0, r17 + sw r16, r0 + cjmpne r102, r0, r21 + sub r17, r17, 3 + lsb r0, r17 + sw r16, r0 + cjmpne r102, r0, r22 + add r17, r17, 1 + lsb r0, r17 + sw r16, r0 + cjmpne r102, r0, r23 + add r17, r17, 1 + lsb r0, r17 + sw r16, r0 + cjmpne r102, r0, r24 + add r17, r17, 1 + lsb r0, r17 + sw r16, r0 + cjmpne r102, r0, r25 + +// Check for bytewise write + lc r17, 0x00008004 + sb r17, 0x12 + add r17, r17, 1 + sb r17, 0x34 + add r17, r17, 1 + sb r17, 0x56 + add r17, r17, 1 + sb r17, 0x78 + +// Read the whole word and compare + sub r17, r17, 3 + lw r0, r17 + lc r18, 0x78563412 + cjmpne r102, r0, r18 + + sw r100, 1 + jmp r101 + +failure: + sw r100, 2 + +halt: + hlt + jmp r101 + +data: + .word 0x56789ABC Index: tags/1.2/verify/lxp32/src/firmware/test006.asm =================================================================== --- tags/1.2/verify/lxp32/src/firmware/test006.asm (nonexistent) +++ tags/1.2/verify/lxp32/src/firmware/test006.asm (revision 10) @@ -0,0 +1,33 @@ +/* + * This test checks for a bug with jump destination register + * being wrongly overwritten when jump instruction follows "lw" + */ + + lc r100, 0x10000000 // test result output pointer + lc r101, halt + lc r102, failure + + lc r16, 0x10000004 + lc r17, 0x12345678 + lc r18, 0x12345678 + + sw r16, 123 + lw r0, r16 + cjmpne r17, 0, 0 // r17 used to be wrongly overwritten by the value of r16 here + + sw r16, r17 + + nop + nop + + cjmpne r102, r17, r18 + + sw r100, 1 + jmp r101 + +failure: + sw r100, 2 + +halt: + hlt + jmp r101 Index: tags/1.2/verify/lxp32/src/firmware/test007.asm =================================================================== --- tags/1.2/verify/lxp32/src/firmware/test007.asm (nonexistent) +++ tags/1.2/verify/lxp32/src/firmware/test007.asm (revision 10) @@ -0,0 +1,134 @@ +/* + * This test verifies bitwise shift operations. + */ + + lc r100, 0x10000000 // test result output pointer + lc r101, halt + lc r102, failure + + lc r16, 0x10000004 // output pointer + +// Test left shifts (by comparison with self-addition) + + lc r0, 0x12345678 + mov r3, r0 // for comparison + lc r32, sl_loop + mov r1, 0 // counter + +sl_loop: + sl r2, r0, r1 + sw r16, r2 + cjmpne r102, r2, r3 + add r1, r1, 1 + add r3, r3, r3 + cjmpul r32, r1, 32 + +// Test unsigned right shifts (by comparison with pre-calculated values) + + lc r32, sru_loop + lc r17, sru_expected_data + mov r1, 0 // counter + +sru_loop: + sru r2, r0, r1 + sw r16, r2 + lw r3, r17 + cjmpne r102, r2, r3 + add r1, r1, 1 + add r17, r17, 4 + cjmpul r32, r1, 32 + +// Test signed right shifts (by comparison with pre-calculated values) + + lc r0, 0x87654321 + lc r32, srs_loop + lc r17, srs_expected_data + mov r1, 0 // counter + +srs_loop: + srs r2, r0, r1 + sw r16, r2 + lw r3, r17 + cjmpne r102, r2, r3 + add r1, r1, 1 + add r17, r17, 4 + cjmpul r32, r1, 32 + +// Report success + sw r100, 1 + jmp r101 + +failure: + sw r100, 2 + +halt: + hlt + jmp r101 + +sru_expected_data: + .word 0x12345678 + .word 0x091A2B3C + .word 0x048D159E + .word 0x02468ACF + .word 0x01234567 + .word 0x0091A2B3 + .word 0x0048D159 + .word 0x002468AC + .word 0x00123456 + .word 0x00091A2B + .word 0x00048D15 + .word 0x0002468A + .word 0x00012345 + .word 0x000091A2 + .word 0x000048D1 + .word 0x00002468 + .word 0x00001234 + .word 0x0000091A + .word 0x0000048D + .word 0x00000246 + .word 0x00000123 + .word 0x00000091 + .word 0x00000048 + .word 0x00000024 + .word 0x00000012 + .word 0x00000009 + .word 0x00000004 + .word 0x00000002 + .word 0x00000001 + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 + +srs_expected_data: + .word 0x87654321 + .word 0xC3B2A190 + .word 0xE1D950C8 + .word 0xF0ECA864 + .word 0xF8765432 + .word 0xFC3B2A19 + .word 0xFE1D950C + .word 0xFF0ECA86 + .word 0xFF876543 + .word 0xFFC3B2A1 + .word 0xFFE1D950 + .word 0xFFF0ECA8 + .word 0xFFF87654 + .word 0xFFFC3B2A + .word 0xFFFE1D95 + .word 0xFFFF0ECA + .word 0xFFFF8765 + .word 0xFFFFC3B2 + .word 0xFFFFE1D9 + .word 0xFFFFF0EC + .word 0xFFFFF876 + .word 0xFFFFFC3B + .word 0xFFFFFE1D + .word 0xFFFFFF0E + .word 0xFFFFFF87 + .word 0xFFFFFFC3 + .word 0xFFFFFFE1 + .word 0xFFFFFFF0 + .word 0xFFFFFFF8 + .word 0xFFFFFFFC + .word 0xFFFFFFFE + .word 0xFFFFFFFF Index: tags/1.2/verify/lxp32/src/firmware/test008.asm =================================================================== --- tags/1.2/verify/lxp32/src/firmware/test008.asm (nonexistent) +++ tags/1.2/verify/lxp32/src/firmware/test008.asm (revision 10) @@ -0,0 +1,59 @@ +/* + * This test calculates a CRC-32 checksum of a small byte array + * CRC32("123456789")=0xCBF43926 + */ + + lc r100, 0x10000000 // test result output pointer + lc r101, halt + lc r102, failure + + lc r16, 0x10000004 // output pointer + lc r17, 0xFFFFFFFF // initial CRC value + lc r18, 0xEDB88320 // polynom + lc r19, data // input pointer + + lc r32, byte_loop + lc r33, bit_loop + lc r34, dont_xor + + mov r20, 0 // byte counter + +byte_loop: + lub r0, r19 + mov r21, 0 // bit counter + +bit_loop: + and r1, r0, 1 + and r2, r17, 1 + sru r17, r17, 1 + xor r3, r1, r2 + cjmpe r34, r3, 0 + xor r17, r17, r18 + +dont_xor: + sru r0, r0, 1 + add r21, r21, 1 + cjmpul r33, r21, 8 + + add r19, r19, 1 + add r20, r20, 1 + cjmpul r32, r20, 9 + + not r17, r17 + sw r16, r17 + + lc r0, 0xCBF43926 + cjmpne r102, r0, r17 + + sw r100, 1 + jmp r101 + +failure: + sw r100, 2 + +halt: + hlt + jmp r101 + +data: + .byte "123456789" Index: tags/1.2/verify/lxp32/src/firmware/test009.asm =================================================================== --- tags/1.2/verify/lxp32/src/firmware/test009.asm (nonexistent) +++ tags/1.2/verify/lxp32/src/firmware/test009.asm (revision 10) @@ -0,0 +1,116 @@ +/* + * This test verifies call and ret instructions + */ + + lc r100, 0x10000000 // test result output pointer + lc r101, halt + lc r102, failure + lc sp, 0x00010000 // stack pointer + + lc r0, 0x00008000 + sw r0, 0 + +// Test simple procedure call + + lc r1, testproc + + call r1 // testproc + + lw r0, r0 + lc r1, 0x11223344 + + cjmpne r102, r0, r1 // failure + +// Test jump directly to CALL instruction + lc r1, jump_to_call + lc r2, testproc2 + + jmp r1 + nop + nop + nop + +jump_to_call: + call r2 + + lw r0, r0 + lc r1, 0x55667788 + + cjmpne r102, r0, r1 // failure + +// Test recursive calls: calculate 10th Fibonnaci number +// using recursive algorithm + mov r0, 10 // argument + mov r16, 0 // how many times test_recursive has been called + lc r1, test_recursive + call r1 // test_recursive + + lc r1, 0x00008000 + sw r1, r0 + + add r1, r1, 4 + sw r1, r16 + + lc r1, 55 + cjmpne r102, r0, r1 + + lc r1, 177 + cjmpne r102, r16, r1 + + sw r100, 1 + jmp r101 // halt + +failure: + sw r100, 2 + +halt: + hlt + jmp r101 // halt + +testproc: + lc r0, 0x00008000 + lc r1, 0x11223344 + sw r0, r1 + ret + +testproc2: + lc r0, 0x00008000 + lc r1, 0x55667788 + sw r0, r1 + ret + +test_recursive: + add r16, r16, 1 // increment call counter + +// If r0 is 0 or 1, just return + cjmpe rp, r0, 0 + cjmpe rp, r0, 1 + +// Save return address in stack + sub sp, sp, 4 + sw sp, rp +// Save argument in stack + sub sp, sp, 4 + sw sp, r0 +// Call itself for with (r0-1) and (r0-2) arguments + sub r0, r0, 1 + lc r1, test_recursive + call r1 +// Restore value from stack, save temporary result + lw r1, sp + sw sp, r0 + + sub r0, r1, 2 + lc r1, test_recursive + call r1 + +// Restore result from stack + lw r1, sp + add sp, sp, 4 + + add r0, r0, r1 + +// Restore return address + lw rp, sp + add sp, sp, 4 + ret Index: tags/1.2/verify/lxp32/src/firmware/test010.asm =================================================================== --- tags/1.2/verify/lxp32/src/firmware/test010.asm (nonexistent) +++ tags/1.2/verify/lxp32/src/firmware/test010.asm (revision 10) @@ -0,0 +1,54 @@ +/* + * This test verifies interrupt handling using a simple timer model + */ + + lc r100, 0x10000000 // test result output pointer + lc r101, halt + lc r102, failure + lc r103, 0x20000000 // timer: number of pulses (0xFFFFFFFF - infinite) + lc r104, 0x20000004 // timer: delay between pulses (in cycles) + + lc iv0, timer_handler0 + lc iv1, timer_handler1 + mov cr, 3 // enable interrupts 0 and 1 + + lc r32, 2000 // cycle counter + lc r33, cnt_loop + mov r34, 0 // interrupt 0 call counter + mov r35, 0 // interrupt 1 call counter + + sw r104, 100 + sw r103, 10 + +cnt_loop: + sub r32, r32, 1 + cjmpug r33, r32, 0 // cnt_loop + + cjmpne r102, r34, 10 // failure + cjmpne r102, r35, 4 // failure + + sw r100, 1 + jmp r101 // halt + +failure: + sw r100, 2 + +halt: + hlt + jmp r101 // halt + +timer_handler0: + add r34, r34, 1 + lc r0, 0x10000004 + sw r0, r34 + cjmpne irp, r34, 5 // exit interrupt handler if r34!=5 + mov cr, 1 // disable interrupt 1 + iret + +timer_handler1: + add r35, r35, 1 +// Interrupt 1 has lower priority than interrupt 0 and will be called later + cjmpne r102, r34, r35 + lc r0, 0x10000008 + sw r0, r35 + iret Index: tags/1.2/verify/lxp32/src/firmware/test011.asm =================================================================== --- tags/1.2/verify/lxp32/src/firmware/test011.asm (nonexistent) +++ tags/1.2/verify/lxp32/src/firmware/test011.asm (revision 10) @@ -0,0 +1,172 @@ +/* + * Coroutine switching test + * + * There are two coroutines in this test. The main coroutine calculates + * CRC32 of the 1024-byte data block. The secondary coroutine simulates + * a linear-feedback shift register (LFSR) with a polynom 1+x^6+x^7. + * It is invoked by the timer interrupt. + */ + + lc r100, 0x10000000 // test result output pointer + lc r101, halt + lc r102, failure + lc r103, 0x20000000 // timer: number of pulses (0xFFFFFFFF - infinite) + lc r104, 0x20000004 // timer: delay between pulses (in cycles) + +// Set up secondary routine (invoked by timer) + mov r200, 127 // initial value + lc r201, 250 // counter (number of LFSR iterations) + mov r204, 0 // result + lc r210, 0x10000008 // secondary routine output pointer + + lc iv0, timer_handler + mov cr, 1 // enable interrupt 0 + + sw r104, 100 + lc r0, 0xFFFFFFFF + sw r103, r0 // activate timer, unlimited pulses + +// Main routine + lc r16, 0x10000004 // output pointer + lc r17, 0xFFFFFFFF // initial CRC value + lc r18, 0xEDB88320 // polynom + lc r19, data // input pointer + lc r20, 256 // data block size in words + + lc r32, word_loop + lc r33, bit_loop + lc r34, dont_xor + + mov r64, 0 // word counter + +word_loop: + lw r0, r19 + mov r65, 0 // bit counter + +bit_loop: + and r1, r0, 1 + and r2, r17, 1 + sru r17, r17, 1 + xor r3, r1, r2 + cjmpe r34, r3, 0 // dont_xor + xor r17, r17, r18 + +dont_xor: + sru r0, r0, 1 + add r65, r65, 1 + cjmpul r33, r65, 32 // bit_loop + + sw r16, r17 + add r19, r19, 4 + add r64, r64, 1 + cjmpul r32, r64, r20 // word_loop + + not r17, r17 + sw r16, r17 + +// Check main routine result + lc r0, 0x501860E6 + cjmpne r102, r0, r17 + +// Wait until secondary routine finishes its job + lc r0, wait_secondary + +wait_secondary: + cjmpe r0, r204, 0 + +// Check secondary routine result + cjmpne r102, r204, 0x57 + + sw r103, 0 // deactivate timer + + sw r100, 1 + jmp r101 + +failure: + sw r100, 2 + +halt: + hlt + jmp r101 + +timer_handler: + sru r202, r200, 5 + sru r203, r200, 6 + xor r202, r202, r203 + and r202, r202, 1 + sl r200, r200, 1 + or r200, r200, r202 + and r200, r200, 0x7f + sub r201, r201, 1 + cjmpug irp, r201, 0 // exit interrupt handler if r201>0 + mov r204, r200 + sw r210, r204 + mov cr, 0 // disable further interrupts + iret + + .align +data: + .byte 0x00, 0x90, 0x31, 0xCF, 0x95, 0x7A, 0x59, 0xE5, 0xD2, 0xBF, 0x2C, 0xDB, 0xB5, 0x83, 0x4D, 0x03 + .byte 0x17, 0x5D, 0x25, 0x2A, 0xFD, 0x72, 0x1E, 0x01, 0x02, 0x60, 0x88, 0x92, 0x9A, 0x9B, 0x2A, 0xA9 + .byte 0x73, 0x5A, 0x0E, 0x9B, 0xC8, 0xCD, 0x85, 0x4D, 0xE0, 0xBA, 0xF4, 0xEC, 0x8A, 0x24, 0x76, 0x3C + .byte 0xDC, 0x35, 0xC7, 0xD7, 0xFF, 0xFF, 0x9C, 0x64, 0x44, 0x4C, 0xD7, 0x06, 0x60, 0x17, 0xAD, 0x0E + .byte 0x02, 0xEB, 0x46, 0x45, 0x96, 0xB0, 0xD6, 0xB9, 0x7C, 0x34, 0xBE, 0x77, 0x75, 0xF2, 0xBE, 0x1B + .byte 0x99, 0x62, 0xBC, 0x9B, 0x92, 0x5C, 0x26, 0x39, 0x6C, 0xCD, 0x84, 0xFD, 0xC0, 0x58, 0x2B, 0xA8 + .byte 0x7D, 0x10, 0xB3, 0x81, 0x25, 0xF3, 0x24, 0xE7, 0xB1, 0x4D, 0x6D, 0x12, 0xF7, 0xAE, 0x27, 0xE0 + .byte 0xD2, 0x95, 0x30, 0x2D, 0xD1, 0x79, 0x27, 0x81, 0xBB, 0x67, 0x47, 0x91, 0xAE, 0xC1, 0xB8, 0x79 + .byte 0x1F, 0x5E, 0xD5, 0x08, 0x84, 0xA9, 0x6D, 0x1A, 0xF3, 0xEB, 0x8C, 0x58, 0x78, 0x5F, 0xD8, 0x51 + .byte 0x74, 0x45, 0xFB, 0x4C, 0xBD, 0x91, 0x32, 0xC2, 0xD6, 0x65, 0x80, 0xE3, 0x07, 0xFE, 0x92, 0x0C + .byte 0x88, 0x31, 0xD7, 0xA0, 0xA8, 0x32, 0xD7, 0x1F, 0x1C, 0xBE, 0x50, 0xF0, 0x49, 0x56, 0x23, 0xBB + .byte 0xD5, 0xB5, 0x99, 0xBF, 0x40, 0x24, 0x00, 0x0F, 0xCE, 0xDA, 0x35, 0x1D, 0x8D, 0x03, 0x1D, 0x74 + .byte 0xC0, 0xAF, 0x8B, 0x12, 0x6F, 0x33, 0xB2, 0x4A, 0x6F, 0x3B, 0x93, 0x88, 0xA0, 0x29, 0x81, 0xF6 + .byte 0xB2, 0xEC, 0x30, 0x56, 0x2D, 0xFE, 0x75, 0xFF, 0x18, 0xA0, 0x18, 0x70, 0xEE, 0x0C, 0xE5, 0x4A + .byte 0x3A, 0xC4, 0x69, 0x33, 0xA0, 0x9A, 0x73, 0x77, 0x99, 0xA2, 0xDA, 0xD4, 0x9F, 0xB8, 0x90, 0x60 + .byte 0x2F, 0xBC, 0x8E, 0xE7, 0x3E, 0x30, 0x9A, 0xB2, 0x95, 0x59, 0x7E, 0x14, 0xBD, 0x9C, 0x9E, 0xB0 + .byte 0xCD, 0x26, 0x93, 0xDE, 0xE9, 0x9D, 0xBA, 0x0B, 0xAA, 0xF9, 0x50, 0x91, 0x4E, 0x2C, 0x1B, 0xDE + .byte 0xD9, 0xBE, 0x27, 0x53, 0x14, 0x13, 0xA4, 0xD1, 0x8B, 0x72, 0x68, 0x4C, 0x77, 0x80, 0x27, 0x52 + .byte 0xBC, 0x50, 0xD3, 0xF5, 0xDF, 0xB9, 0x4C, 0xF1, 0x20, 0x10, 0xC8, 0x86, 0x9C, 0xF4, 0x12, 0xE0 + .byte 0xA7, 0x52, 0x1A, 0x81, 0x3A, 0x4A, 0xEB, 0x8D, 0xA9, 0x1D, 0x7E, 0x61, 0x7F, 0xCB, 0x82, 0x61 + .byte 0xB0, 0x88, 0x9B, 0x65, 0x01, 0xB5, 0x19, 0x9F, 0xDC, 0x7D, 0xBF, 0x7F, 0x61, 0xC9, 0x8D, 0x5B + .byte 0xF4, 0xA1, 0x2D, 0x5F, 0x21, 0xBE, 0xF3, 0x9C, 0x07, 0x54, 0x0E, 0xA3, 0x21, 0xD8, 0xDD, 0x98 + .byte 0xB8, 0xDA, 0x03, 0x20, 0xB5, 0x9D, 0x37, 0x10, 0x2B, 0x9F, 0x57, 0x51, 0x5E, 0xA9, 0xCD, 0xCE + .byte 0x86, 0x9C, 0xCC, 0xE6, 0x25, 0xA1, 0x67, 0x40, 0x22, 0xDA, 0x10, 0x6D, 0x92, 0x4D, 0x8C, 0x39 + .byte 0x4F, 0x1C, 0xCE, 0x22, 0x48, 0xC9, 0xE5, 0xCA, 0xBE, 0x9D, 0x5C, 0xDB, 0x3A, 0xDD, 0x3A, 0x3F + .byte 0x8A, 0xFC, 0x0D, 0x14, 0x86, 0x6D, 0x18, 0x42, 0xE4, 0x3B, 0x25, 0x20, 0xEE, 0x14, 0x0C, 0x0F + .byte 0x56, 0xEA, 0x66, 0x6E, 0xF2, 0xD6, 0x88, 0xD7, 0xB1, 0x65, 0x42, 0x01, 0x86, 0xF4, 0x66, 0x3D + .byte 0x95, 0x41, 0xAF, 0xF1, 0x6F, 0xE3, 0x01, 0xF0, 0x99, 0xC9, 0x93, 0x24, 0x38, 0x62, 0x01, 0x6A + .byte 0x15, 0xA8, 0xDA, 0x10, 0xCF, 0xA9, 0xB1, 0xCD, 0x87, 0xAF, 0x24, 0xB0, 0xBA, 0xC7, 0x07, 0xDE + .byte 0xA4, 0xB4, 0x15, 0x8D, 0xF2, 0x0F, 0x46, 0x25, 0xFB, 0x9E, 0x4A, 0xEC, 0x5E, 0xB1, 0x37, 0x27 + .byte 0x3D, 0x85, 0xE6, 0x1B, 0xE7, 0x71, 0x14, 0xC8, 0x2B, 0xF9, 0xC6, 0xDE, 0x35, 0x74, 0x00, 0xC0 + .byte 0x1D, 0x67, 0x4F, 0xFE, 0x09, 0x40, 0x30, 0x3F, 0x27, 0x9E, 0xE2, 0xF0, 0x32, 0xC7, 0xA5, 0xA8 + .byte 0xE8, 0x74, 0xEB, 0xAA, 0x26, 0xA2, 0x91, 0x6C, 0xF1, 0x8A, 0x94, 0x89, 0x41, 0x65, 0x59, 0x09 + .byte 0xCB, 0x32, 0x11, 0x63, 0x97, 0x12, 0x32, 0x27, 0xA4, 0x74, 0x9A, 0xB2, 0x70, 0xAF, 0x65, 0xD5 + .byte 0x97, 0x33, 0xF3, 0xE0, 0x64, 0xFC, 0x2F, 0xE5, 0x93, 0x71, 0xA0, 0xB5, 0x0C, 0x49, 0x42, 0x68 + .byte 0xE5, 0xB5, 0xBA, 0xE5, 0x64, 0x65, 0xE7, 0x4F, 0x63, 0x92, 0x5A, 0xBB, 0xBE, 0xBC, 0xBD, 0x23 + .byte 0x33, 0x45, 0xAE, 0xE9, 0x5E, 0x84, 0x1C, 0xE8, 0x33, 0x84, 0xA7, 0x70, 0xB0, 0x17, 0x14, 0x13 + .byte 0x07, 0x5A, 0x4E, 0xB2, 0x24, 0x65, 0x11, 0xAC, 0xB9, 0x32, 0xB1, 0x9D, 0xA7, 0x8B, 0x19, 0x8B + .byte 0x0C, 0xF9, 0x76, 0xF8, 0xBA, 0x87, 0xAE, 0xB1, 0x5F, 0x63, 0x0C, 0xCF, 0x2B, 0x0F, 0x4F, 0xC8 + .byte 0x36, 0x52, 0x7C, 0x02, 0x70, 0x82, 0x9B, 0xC2, 0x66, 0x59, 0xD7, 0xF1, 0x9F, 0xFF, 0x0D, 0x90 + .byte 0xDD, 0x63, 0x4E, 0x48, 0x06, 0x9C, 0x64, 0x04, 0x07, 0x74, 0xDB, 0xEF, 0x66, 0xBA, 0x9C, 0xCE + .byte 0xE0, 0x95, 0x98, 0x14, 0xCB, 0x76, 0x97, 0x96, 0x91, 0xD0, 0xAC, 0x57, 0x02, 0x44, 0x57, 0x3B + .byte 0xC5, 0x5F, 0xDE, 0x1D, 0xB9, 0xA1, 0xE4, 0x2E, 0x89, 0xE6, 0xC7, 0xF7, 0x32, 0xE6, 0xCC, 0xF4 + .byte 0xD9, 0xE3, 0xA0, 0x2F, 0x9D, 0x43, 0x40, 0xBB, 0xC9, 0x2B, 0xB6, 0x7B, 0x14, 0xCE, 0xDA, 0x1F + .byte 0x4E, 0x92, 0x79, 0xC3, 0x31, 0xBA, 0xFE, 0x03, 0xA5, 0xB1, 0x2C, 0x12, 0x46, 0xAD, 0xD6, 0x8E + .byte 0x5F, 0xC7, 0x3B, 0xA3, 0x3B, 0x34, 0xF8, 0x48, 0x05, 0xC4, 0x26, 0x0C, 0x02, 0x59, 0xA4, 0x57 + .byte 0x6A, 0x6A, 0x17, 0x8B, 0xB3, 0x56, 0xA8, 0xE0, 0x89, 0x91, 0x0D, 0x77, 0x42, 0x6D, 0xDD, 0x7C + .byte 0x16, 0x90, 0xB5, 0xC7, 0xDD, 0xD9, 0x4B, 0xDD, 0xA5, 0xBF, 0xD4, 0xC3, 0xDF, 0xE8, 0xE9, 0x85 + .byte 0x70, 0x1B, 0x5A, 0xD2, 0x6D, 0x2B, 0x00, 0xA8, 0xC6, 0x10, 0x16, 0x62, 0xAF, 0xCE, 0x27, 0x24 + .byte 0x0C, 0x58, 0x04, 0xFA, 0xA5, 0x0D, 0xEA, 0xA3, 0x6E, 0x05, 0x3E, 0x64, 0xA7, 0xC8, 0x05, 0xD3 + .byte 0x23, 0xA2, 0x8C, 0xFB, 0x76, 0x36, 0x4C, 0xC8, 0x57, 0x7B, 0x9B, 0x1A, 0xFC, 0xC1, 0x26, 0x74 + .byte 0xB6, 0xFF, 0xC6, 0xA4, 0x9F, 0xF2, 0xB0, 0x4A, 0x91, 0x4A, 0x8C, 0xB6, 0x3F, 0x8B, 0x7E, 0xF3 + .byte 0xAB, 0xC3, 0x9F, 0x72, 0xCC, 0xBE, 0xFD, 0x34, 0xA1, 0xE8, 0x97, 0xEB, 0x81, 0x7D, 0x73, 0xE3 + .byte 0xF0, 0x2E, 0x40, 0x33, 0xBB, 0xF0, 0xA0, 0x0A, 0xA4, 0x08, 0x8E, 0x8B, 0x72, 0x0F, 0xFE, 0x20 + .byte 0x99, 0x0C, 0x2C, 0xA9, 0x55, 0x50, 0xA7, 0x69, 0x6D, 0x38, 0xAD, 0x2A, 0x7F, 0x81, 0xCD, 0x6F + .byte 0x01, 0x56, 0x60, 0x20, 0xD3, 0xBB, 0xE4, 0xA4, 0xA6, 0x83, 0xBB, 0xBC, 0xF5, 0x77, 0x5C, 0x1C + .byte 0xE7, 0xD2, 0x74, 0x1B, 0xDE, 0xC2, 0x0A, 0x6A, 0xEF, 0x11, 0x2A, 0x36, 0x1D, 0x97, 0x1E, 0x9E + .byte 0x94, 0xB0, 0xBB, 0xEA, 0xAB, 0x4C, 0xCF, 0x60, 0xFF, 0xC5, 0x34, 0x2B, 0x63, 0x2E, 0x94, 0x32 + .byte 0xF5, 0x30, 0x61, 0x4D, 0x1E, 0x32, 0x0B, 0xC5, 0xC2, 0xE1, 0x00, 0x72, 0x6D, 0xCD, 0x76, 0x7E + .byte 0xBF, 0x3D, 0x8F, 0x17, 0xEC, 0xE4, 0xDB, 0x0F, 0x7D, 0xA1, 0xBF, 0xC1, 0x41, 0xE8, 0xCA, 0x33 + .byte 0x8D, 0x0D, 0x85, 0xCA, 0xB4, 0x06, 0xBB, 0x8D, 0xEA, 0xE0, 0xCC, 0x4E, 0x65, 0x7B, 0x0D, 0xA6 + .byte 0x00, 0xC4, 0xC1, 0x38, 0x27, 0x0E, 0xAB, 0x08, 0x58, 0xB2, 0xCC, 0x6F, 0xFB, 0xA2, 0x4B, 0x7A + .byte 0xDF, 0x14, 0x19, 0x24, 0x24, 0xEB, 0x4F, 0x5F, 0xD0, 0x0B, 0xD0, 0x3D, 0xE5, 0x41, 0x44, 0x35 + .byte 0x3A, 0xD8, 0xDF, 0xE3, 0xD8, 0x9B, 0x0A, 0x2C, 0x2F, 0x5B, 0x73, 0x2F, 0xE4, 0x9F, 0x8B, 0xE9 Index: tags/1.2/verify/lxp32/src/firmware/test012.asm =================================================================== --- tags/1.2/verify/lxp32/src/firmware/test012.asm (nonexistent) +++ tags/1.2/verify/lxp32/src/firmware/test012.asm (revision 10) @@ -0,0 +1,373 @@ +/* + * Test multiplication + */ + + lc r100, 0x10000000 // test result output pointer + lc r101, halt + lc r102, failure + lc r103, 0x10000004 + +// Check multiplication table + + lc r32, op1 + lc r33, op2 + lc r34, product + + lc r35, loop + mov r10, 100 + +loop: + lw r0, r32 + lw r1, r33 + mul r3, r0, r1 + lw r2, r34 + cjmpne r102, r2, r3 // failure + add r32, r32, 4 + add r33, r33, 4 + add r34, r34, 4 + sub r10, r10, 1 + cjmpug r35, r10, 0 // loop + +// Simulate a linear congruent random number generator +// as described in ISO/IEC 9899:1999 ("C99" standard) + + mov r64, 1 // initial value + lc r65, 1103515245 // multiplier + lc r66, 12345 // addition constant + lc r67, 32767 // mask + + mov r10, 100 + lc r32, rand + lc r35, rnd_loop + +rnd_loop: + call r32 // rand + sw r103, r0 + sub r10, r10, 1 + cjmpug r35, r10, 0 // rnd_loop + + lc r1, 26521 + cjmpne r102, r0, r1 // failure + + sw r100, 1 + jmp r101 // halt + +failure: + sw r100, 2 + +halt: + hlt + jmp r101 // halt + +rand: + mul r64, r64, r65 + add r64, r64, r66 + sru r0, r64, 16 + and r0, r0, r67 + ret + +op1: + .word 5 + .word 1021028019 + .word 3360494259 + .word 4241216605 + .word 3998259744 + .word 4061417389 + .word 2643534582 + .word 3313401900 + .word 2127959231 + .word 517066081 + .word 971560706 + .word 2765397972 + .word 1972360008 + .word 5267214 + .word 3667030040 + .word 3641602966 + .word 297473786 + .word 3637724660 + .word 3268423030 + .word 2775202737 + .word 2509905173 + .word 3885678420 + .word 820072030 + .word 1177172069 + .word 1047341530 + .word 1826819693 + .word 1694831631 + .word 4270696691 + .word 1299413127 + .word 2817552511 + .word 2675818186 + .word 231984537 + .word 65817694 + .word 3640600522 + .word 545754317 + .word 2973624217 + .word 2669208735 + .word 1079210895 + .word 660979290 + .word 738800690 + .word 1631093128 + .word 489263629 + .word 4116157872 + .word 3178886821 + .word 2324324955 + .word 2982397572 + .word 3365621776 + .word 2764926001 + .word 1498466135 + .word 1012944436 + .word -246837166 + .word 470638116 + .word 2103051039 + .word 176753939 + .word -164476654 + .word -1221540757 + .word 43633328 + .word -859182414 + .word 1230499715 + .word -266475918 + .word 1949507090 + .word -856415694 + .word 737657061 + .word 118818171 + .word 359218821 + .word 1246427092 + .word -615317895 + .word 1029267653 + .word 628714057 + .word -2029278762 + .word -1700206210 + .word -785893232 + .word -492445025 + .word -1032292742 + .word -1506164940 + .word 63097629 + .word -1909659707 + .word 1003528447 + .word 1095156443 + .word 325606314 + .word 1750055165 + .word 861103782 + .word -1441910348 + .word 1113139065 + .word -1337158265 + .word -381613907 + .word 567364862 + .word -808095798 + .word -1503281503 + .word -1646541226 + .word -405777159 + .word -98798373 + .word -1948683123 + .word -1889476128 + .word 994740197 + .word 57636334 + .word -1628834166 + .word -15689588 + .word 1568614403 + .word 722317890 + +op2: + .word 3 + .word 2570980487 + .word 2794175299 + .word 994440598 + .word 4248205376 + .word 3496362052 + .word 3659500513 + .word 2162808217 + .word 1720638509 + .word 1914084509 + .word 3385545516 + .word 3476389465 + .word 706599398 + .word 3196936660 + .word 2983089252 + .word 1751592726 + .word 2284105389 + .word 4111191592 + .word 3563638217 + .word 2361468945 + .word 3236010945 + .word 1439769561 + .word 1910111900 + .word 2038606217 + .word 311877730 + .word 538878248 + .word 3378587675 + .word 1911288510 + .word 3196239568 + .word 2503116372 + .word 457280137 + .word 3023717616 + .word 98988876 + .word 4098692253 + .word 2797102115 + .word 2159140448 + .word 637551125 + .word 2125433411 + .word 2902980138 + .word 395247949 + .word 1645373547 + .word 1922640262 + .word 1835827423 + .word 3088444407 + .word 4150011791 + .word 273297575 + .word 673792897 + .word 2743197342 + .word 656195007 + .word 2550324965 + .word -337003535 + .word -565725434 + .word 522532873 + .word 850320156 + .word -599163490 + .word 580991794 + .word 1235055289 + .word -697843885 + .word -1888878751 + .word 2001358724 + .word -705426274 + .word 764466127 + .word 1149731192 + .word 528626491 + .word 74073848 + .word 1986549712 + .word 1021657893 + .word 1502226327 + .word 339763464 + .word -248542057 + .word -1245542745 + .word 1721855193 + .word 1203018508 + .word -551112349 + .word -245462721 + .word -2079899329 + .word -603441594 + .word 2123105909 + .word 821726251 + .word -167975413 + .word 343634678 + .word 279038731 + .word -1328164947 + .word -121529220 + .word 760122714 + .word -710590105 + .word -1288727804 + .word -829054509 + .word 1774242228 + .word 198747848 + .word 2017990513 + .word -1246218417 + .word 135357763 + .word -193250194 + .word 1080138546 + .word -278225361 + .word 1216454983 + .word -808631398 + .word 1236885385 + .word -1142156106 + +product: + .word 15 + .word 3187625061 + .word 4060456409 + .word 3720114046 + .word 2133166080 + .word 2956880372 + .word 39144502 + .word 4048238156 + .word 3781675411 + .word 2552762493 + .word 2186320472 + .word 2004478132 + .word 1215814320 + .word 1967719832 + .word 961259872 + .word 3218110692 + .word 808743666 + .word 1758021152 + .word 3653971878 + .word 1641193153 + .word 1749066709 + .word 2447944244 + .word 1085998408 + .word 3424443149 + .word 1143260532 + .word 542297608 + .word 3545920917 + .word 820648538 + .word 131342256 + .word 3650446252 + .word 3798859290 + .word 1641505648 + .word 3270043112 + .word 2203660002 + .word 2262848519 + .word 3335948128 + .word 301711115 + .word 853759085 + .word 1108457156 + .word 3991332106 + .word 3268240344 + .word 4293625806 + .word 2556650576 + .word 2577362995 + .word 2650590677 + .word 1310146588 + .word 247957520 + .word 2454471742 + .word 1425274089 + .word 39783556 + .word -2091990222 + .word -1969753896 + .word 1297343511 + .word -32067820 + .word -824646884 + .word -1038744090 + .word -615130832 + .word 1160766902 + .word -878690909 + .word -1535377208 + .word -1071814884 + .word -139010962 + .word 18403416 + .word 2137375833 + .word 2082402008 + .word 1027762240 + .word 1775596157 + .word 1957173043 + .word 1934687048 + .word -1391708870 + .word 1441023282 + .word 897888784 + .word -2134317964 + .word 1520184110 + .word -123674164 + .word -464692957 + .word -481104418 + .word -946631029 + .word 55606985 + .word -2060538802 + .word 1653304606 + .word 1163987746 + .word -2138299740 + .word 1903549084 + .word 1936321654 + .word -455120229 + .word 1931283960 + .word 617295230 + .word -470388172 + .word -522275024 + .word -1465917207 + .word 541793429 + .word -1975377433 + .word 1462865472 + .word 1922773434 + .word 1925941938 + .word 1115302470 + .word 604268600 + .word -32471397 + .word 948036332 Index: tags/1.2/verify/lxp32/src/firmware/test013.asm =================================================================== --- tags/1.2/verify/lxp32/src/firmware/test013.asm (nonexistent) +++ tags/1.2/verify/lxp32/src/firmware/test013.asm (revision 10) @@ -0,0 +1,935 @@ +/* + * Test division (divu, divs, modu, mods) + */ + + lc r100, 0x10000000 // test result output pointer + lc r101, halt + lc r102, failure + lc r103, 0x10000004 + +// Test unsigned division + + lc r32, op1 + lc r33, op2 + lc r34, quotient + lc r35, remainder + lc r36, cnt_loop + lc r10, 100 // counter + +cnt_loop: + lw r0, r32 + lw r1, r33 + divu r2, r0, r1 + modu r3, r0, r1 + lw r4, r34 + lw r5, r35 + cjmpne r102, r2, r4 // failure + cjmpne r102, r3, r5 // failure + mul r6, r2, r1 + add r6, r6, r3 + cjmpne r102, r6, r0 // failure + add r32, r32, 4 + add r33, r33, 4 + add r34, r34, 4 + add r35, r35, 4 + sub r10, r10, 1 + cjmpug r36, r10, 0 // cnt_loop + + sw r103, 1 + +// Test signed division + + lc r32, op1_signed + lc r33, op2_signed + lc r34, quotient_signed + lc r35, remainder_signed + lc r36, cnt_loop2 + lc r10, 100 // counter + +cnt_loop2: + lw r0, r32 + lw r1, r33 + divs r2, r0, r1 + mods r3, r0, r1 + lw r4, r34 + lw r5, r35 + cjmpne r102, r2, r4 // failure + cjmpne r102, r3, r5 // failure + mul r6, r2, r1 + add r6, r6, r3 + cjmpne r102, r6, r0 // failure + add r32, r32, 4 + add r33, r33, 4 + add r34, r34, 4 + add r35, r35, 4 + sub r10, r10, 1 + cjmpug r36, r10, 0 // cnt_loop2 + + sw r103, 2 + +// Random division/multiplication test + + mov r64, 1 // initial PRBS value + lc r65, 1103515245 // PRBS multiplier + lc r66, 12345 // PRBS addition constant + lc r67, 32767 // PRBS mask + lc r68, 16384 + + lc r10, 1000 + lc r32, rnd_loop + lc r33, rand + lc r34, rnd_cont + +rnd_loop: + call r33 // rand + sub r1, r0, r68 // dividend in r1 + call r33 // rand + sub r2, r0, r68 // divisor in r2 + cjmpne r34, r2, 0 // rnd_cont + mov r2, 1 + +rnd_cont: + divs r3, r1, r2 + mods r4, r1, r2 + mul r5, r3, r2 + add r5, r5, r4 + cjmpne r102, r5, r1 // failure + sub r10, r10, 1 + cjmpug r32, r10, 0 // rnd_loop + + sw r103, 3 + + sw r100, 1 + jmp r101 // halt + +failure: + sw r100, 2 + +halt: + hlt + jmp r101 // halt + +// Linear congruent pseudo-random number generator (as in ISO/IEC 9899:1999) + +rand: + mul r64, r64, r65 + add r64, r64, r66 + sru r0, r64, 16 + and r0, r0, r67 + ret + +op1: + .word 2227053353 + .word 4059122064 + .word 210189531 + .word 1203176988 + .word 2794175299 + .word 1562322232 + .word 219364165 + .word 1352278066 + .word 4130490642 + .word 1156715599 + .word 993179440 + .word 529260957 + .word 1235055289 + .word 2994792917 + .word 348116583 + .word 1475314534 + .word 517066081 + .word 2230328806 + .word 1395407336 + .word 4094467700 + .word 3476389465 + .word 1210945747 + .word 3236243997 + .word 1348406852 + .word 118818171 + .word 1692045936 + .word 1190663529 + .word 1731139289 + .word 1986549712 + .word 2038965422 + .word 1173634277 + .word 1499514357 + .word 3268423030 + .word 136673642 + .word 672245098 + .word 797742983 + .word 3236010945 + .word 1421197958 + .word 948983249 + .word 3780009574 + .word 3802522271 + .word 2303076920 + .word 2976105080 + .word 2531287614 + .word 4049504575 + .word 488644257 + .word 336561159 + .word 753386953 + .word 4270696691 + .word 1966854304 + .word 3201322355 + .word 4203490113 + .word 2503116372 + .word 3405118694 + .word 3103595329 + .word 3553466644 + .word 861103782 + .word 1275325516 + .word 3484264974 + .word 1293196760 + .word 4173438076 + .word 2275850340 + .word 3885575502 + .word 1091087744 + .word 2669208735 + .word 69325132 + .word 2319663187 + .word 2510410703 + .word 2902980138 + .word 845791433 + .word 3327530895 + .word 948013067 + .word 3889190137 + .word 2250058130 + .word 927988252 + .word 1820385269 + .word 135357763 + .word 3770160619 + .word 1650193531 + .word 1250420215 + .word 2982397572 + .word 788754293 + .word 1132578971 + .word 2174830494 + .word 2743197342 + .word 1473236291 + .word 671295260 + .word 1615737929 + .word 722317890 + .word 1373795119 + .word 3187744723 + .word 353993505 + .word 3691968907 + .word 2452722797 + .word 1784599952 + .word 912987979 + .word 2183033578 + .word 2941180254 + .word 3706025245 + .word 2141225307 + +op2: + .word 225 + .word 3018582459 + .word 6462 + .word 222 + .word 799 + .word 19412 + .word 3676048009 + .word 16622 + .word 32158 + .word 64 + .word 8865 + .word 2580197594 + .word 3313401900 + .word 1405929962 + .word 214 + .word 24905 + .word 1914084509 + .word 41372239 + .word 203 + .word 213 + .word 50 + .word 3866464211 + .word 247 + .word 2371998720 + .word 528626491 + .word 2243022420 + .word 106 + .word 21608 + .word 250 + .word 635130622 + .word 22739 + .word 61 + .word 3563638217 + .word 97 + .word 2849410241 + .word 241 + .word 2594761086 + .word 191 + .word 40 + .word 48 + .word 6924 + .word 2054783657 + .word 702209830 + .word 968832018 + .word 1826819693 + .word 17099 + .word 25861 + .word 142 + .word 190 + .word 3078 + .word 130 + .word 32560 + .word 170 + .word 2308931006 + .word 26703 + .word 13 + .word 19211 + .word 115 + .word 667594965 + .word 1495759348 + .word 205 + .word 19605 + .word 61 + .word 2772527081 + .word 16917 + .word 147 + .word 175 + .word 206 + .word 16033 + .word 2356 + .word 7643 + .word 97 + .word 2017990513 + .word 41 + .word 13752 + .word 109 + .word 165 + .word 225 + .word 2698 + .word 12859 + .word 12455 + .word 158 + .word 4136249385 + .word 3446419784 + .word 140 + .word 20679 + .word 23935 + .word 48162108 + .word 5302 + .word 126 + .word 80 + .word 741054488 + .word 188 + .word 116 + .word 64 + .word 177 + .word 141 + .word 16378 + .word 3662043152 + .word 19292 + +quotient: + .word 9898014 + .word 1 + .word 32527 + .word 5419716 + .word 3497090 + .word 80482 + .word 0 + .word 81354 + .word 128443 + .word 18073681 + .word 112033 + .word 0 + .word 0 + .word 2 + .word 1626713 + .word 59237 + .word 0 + .word 53 + .word 6873927 + .word 19222853 + .word 69527789 + .word 0 + .word 13102202 + .word 0 + .word 0 + .word 0 + .word 11232674 + .word 80115 + .word 7946198 + .word 3 + .word 51613 + .word 24582202 + .word 0 + .word 1409006 + .word 0 + .word 3310136 + .word 1 + .word 7440827 + .word 23724581 + .word 78750199 + .word 549179 + .word 1 + .word 4 + .word 2 + .word 2 + .word 28577 + .word 13014 + .word 5305541 + .word 22477351 + .word 639003 + .word 24625556 + .word 129099 + .word 14724213 + .word 1 + .word 116226 + .word 273343588 + .word 44823 + .word 11089787 + .word 5 + .word 0 + .word 20358234 + .word 116085 + .word 63697959 + .word 0 + .word 157782 + .word 471599 + .word 13255218 + .word 12186459 + .word 181062 + .word 358994 + .word 435369 + .word 9773330 + .word 1 + .word 54879466 + .word 67480 + .word 16700782 + .word 820350 + .word 16756269 + .word 611635 + .word 97240 + .word 239453 + .word 4992115 + .word 0 + .word 0 + .word 19594266 + .word 71243 + .word 28046 + .word 33 + .word 136234 + .word 10903135 + .word 39846809 + .word 0 + .word 19638132 + .word 21144162 + .word 27884374 + .word 5158124 + .word 15482507 + .word 179581 + .word 1 + .word 110990 + +remainder: + .word 203 + .word 1040539605 + .word 57 + .word 36 + .word 389 + .word 5648 + .word 219364165 + .word 11878 + .word 20648 + .word 15 + .word 6895 + .word 529260957 + .word 1235055289 + .word 182932993 + .word 1 + .word 17049 + .word 517066081 + .word 37600139 + .word 155 + .word 11 + .word 15 + .word 1210945747 + .word 103 + .word 1348406852 + .word 118818171 + .word 1692045936 + .word 85 + .word 14369 + .word 212 + .word 133573556 + .word 6270 + .word 35 + .word 3268423030 + .word 60 + .word 672245098 + .word 207 + .word 641249859 + .word 1 + .word 9 + .word 22 + .word 6875 + .word 248293263 + .word 167265760 + .word 593623578 + .word 395865189 + .word 6134 + .word 6105 + .word 131 + .word 1 + .word 3070 + .word 75 + .word 26673 + .word 162 + .word 1096187688 + .word 12451 + .word 0 + .word 9129 + .word 11 + .word 146290149 + .word 1293196760 + .word 106 + .word 3915 + .word 3 + .word 1091087744 + .word 10641 + .word 79 + .word 37 + .word 149 + .word 13092 + .word 1569 + .word 5628 + .word 57 + .word 1871199624 + .word 24 + .word 3292 + .word 31 + .word 13 + .word 94 + .word 2301 + .word 11055 + .word 10457 + .word 123 + .word 1132578971 + .word 2174830494 + .word 102 + .word 2294 + .word 14250 + .word 26388365 + .word 5222 + .word 109 + .word 3 + .word 353993505 + .word 91 + .word 5 + .word 16 + .word 31 + .word 91 + .word 2636 + .word 43982093 + .word 6227 + +op1_signed: + .word 1173464398 + .word 644568570 + .word 1413618866 + .word 940280095 + .word 1307051796 + .word 69701148 + .word 791353789 + .word -1751134801 + .word -540034563 + .word -664201053 + .word 859052625 + .word 506263265 + .word 1672805452 + .word -940950084 + .word 639564287 + .word -320080770 + .word -194326606 + .word -1401122692 + .word 1361841711 + .word -1572666822 + .word 223085807 + .word -2143536785 + .word -771364638 + .word -392756254 + .word -2075946315 + .word -133598861 + .word 869612982 + .word 727395029 + .word -1173738546 + .word 1865699269 + .word 1001660457 + .word -1435705417 + .word 313397375 + .word 91734875 + .word 55211040 + .word -1298145437 + .word -1587928274 + .word 120185203 + .word 1253220522 + .word 664380448 + .word 659766337 + .word -1867423126 + .word 211715071 + .word 1172375319 + .word 1010876232 + .word 1866163921 + .word 1337698510 + .word -1489886717 + .word -844206754 + .word 1252556476 + .word 1062583479 + .word -2028701144 + .word -925730358 + .word 63629404 + .word 2084388372 + .word 1185701000 + .word 344972780 + .word 1506745295 + .word -1310164994 + .word 785548626 + .word -960828075 + .word -788757195 + .word 1742449807 + .word 1952581789 + .word -1868879050 + .word -727870971 + .word 457544035 + .word -2083100074 + .word 2092326142 + .word 456912800 + .word -1930624925 + .word 1981026677 + .word -641082819 + .word 1259278117 + .word 1481501124 + .word -444342667 + .word 1947675341 + .word -608834426 + .word -906130612 + .word -480045052 + .word 182898482 + .word 1025708506 + .word -363535658 + .word 1180470009 + .word -62562240 + .word 987486196 + .word -531865065 + .word 676720261 + .word 1125242878 + .word -1621168845 + .word 1990517921 + .word -1383494740 + .word -1522980151 + .word 434249114 + .word -129245145 + .word 97983477 + .word 658513595 + .word 1548110625 + .word 1140579073 + .word -1285950881 + +op2_signed: + .word 1389891600 + .word 176 + .word -129 + .word -10300 + .word -24713 + .word 36 + .word 539501672 + .word -412262764 + .word -999517400 + .word 27 + .word -185 + .word 632355259 + .word 1914747195 + .word -202 + .word 152 + .word -151 + .word -49343821 + .word 161975794 + .word -172 + .word -3509 + .word 8811 + .word -135 + .word -224114196 + .word 5373 + .word -30158 + .word 735955126 + .word 7320 + .word -1137550910 + .word 413980723 + .word -28499 + .word -1858419248 + .word -31374 + .word 153 + .word -245 + .word -231 + .word 1065580722 + .word 114 + .word 25851 + .word 1113949699 + .word 1883394154 + .word 211 + .word 22075 + .word -143 + .word -1052684430 + .word -197 + .word -28563 + .word -12517 + .word 141 + .word -197 + .word -79 + .word 79 + .word -103 + .word 563090517 + .word -13711 + .word -2 + .word -250 + .word -130626268 + .word -1824933506 + .word 501 + .word 135 + .word -965460037 + .word 90 + .word -24983 + .word -5626 + .word -175 + .word -42 + .word -72 + .word 9948 + .word -29411 + .word 223 + .word 16237 + .word -192 + .word -297352066 + .word 2140975764 + .word -511619965 + .word -7170 + .word -380546211 + .word 1065203866 + .word -81584403 + .word -23445 + .word 213 + .word 31410 + .word -270351532 + .word -8040 + .word -13293 + .word 16010 + .word -223 + .word -60 + .word 9338 + .word -46 + .word 26045 + .word 21525 + .word 1705744137 + .word 1754448529 + .word -1602585578 + .word 1341015177 + .word 1 + .word -72 + .word -156 + .word 1932634409 + +quotient_signed: + .word 0 + .word 3662321 + .word -10958285 + .word -91289 + .word -52889 + .word 1936143 + .word 1 + .word 4 + .word 0 + .word -24600039 + .word -4643527 + .word 0 + .word 0 + .word 4658168 + .word 4207659 + .word 2119740 + .word 3 + .word -8 + .word -7917684 + .word 448180 + .word 25319 + .word 15878050 + .word 3 + .word -73098 + .word 68835 + .word 0 + .word 118799 + .word 0 + .word -2 + .word -65465 + .word 0 + .word 45760 + .word 2048348 + .word -374428 + .word -239008 + .word -1 + .word -13929195 + .word 4649 + .word 1 + .word 0 + .word 3126854 + .word -84594 + .word -1480524 + .word -1 + .word -5131351 + .word -65335 + .word -106870 + .word -10566572 + .word 4285313 + .word -15855145 + .word 13450423 + .word 19696127 + .word -1 + .word -4640 + .word -1042194186 + .word -4742804 + .word -2 + .word 0 + .word -2615099 + .word 5818878 + .word 0 + .word -8763968 + .word -69745 + .word -347063 + .word 10679308 + .word 17330261 + .word -6354778 + .word -209398 + .word -71140 + .word 2048936 + .word -118902 + .word -10317847 + .word 2 + .word 0 + .word -2 + .word 61972 + .word -5 + .word 0 + .word 11 + .word 20475 + .word 858678 + .word 32655 + .word 1 + .word -146824 + .word 4706 + .word 61679 + .word 2385045 + .word -11278671 + .word 120501 + .word 35242800 + .word 76426 + .word -64273 + .word 0 + .word 0 + .word 0 + .word 0 + .word 658513595 + .word -21501536 + .word -7311404 + .word 0 + +remainder_signed: + .word 1173464398 + .word 74 + .word 101 + .word 3395 + .word 5939 + .word 0 + .word 251852117 + .word -102083745 + .word -540034563 + .word 0 + .word 130 + .word 506263265 + .word 1672805452 + .word -148 + .word 119 + .word -30 + .word -46295143 + .word -105316340 + .word 63 + .word -3202 + .word 98 + .word -35 + .word -99022050 + .word -700 + .word -20385 + .word -133598861 + .word 4302 + .word 727395029 + .word -345777100 + .word 12234 + .word 1001660457 + .word -31177 + .word 131 + .word 15 + .word 192 + .word -232564715 + .word -44 + .word 3904 + .word 139270823 + .word 664380448 + .word 143 + .word -10576 + .word 139 + .word 119690889 + .word 85 + .word 316 + .word 6720 + .word -65 + .word -93 + .word 21 + .word 62 + .word -63 + .word -362639841 + .word 10364 + .word 0 + .word 0 + .word 83720244 + .word 1506745295 + .word -395 + .word 96 + .word -960828075 + .word -75 + .word 10472 + .word 5351 + .word -150 + .word -9 + .word 19 + .word -8770 + .word 27602 + .word 72 + .word -13151 + .word 53 + .word -46378687 + .word 1259278117 + .word 458261194 + .word -3427 + .word 44944286 + .word -608834426 + .word -8702179 + .word -8677 + .word 68 + .word 14956 + .word -93184126 + .word 5049 + .word -5382 + .word 5406 + .word -30 + .word 1 + .word 4540 + .word -45 + .word 2751 + .word -18415 + .word -1522980151 + .word 434249114 + .word -129245145 + .word 97983477 + .word 0 + .word 33 + .word 49 + .word -1285950881 Index: tags/1.2/verify/lxp32/src/firmware/test014.asm =================================================================== --- tags/1.2/verify/lxp32/src/firmware/test014.asm (nonexistent) +++ tags/1.2/verify/lxp32/src/firmware/test014.asm (revision 10) @@ -0,0 +1,27 @@ +/* + * Test "hlt" instruction + */ + + lc r100, 0x10000000 // test result output pointer + lc r101, halt + lc r103, 0x20000000 // timer: number of pulses (0xFFFFFFFF - infinite) + lc r104, 0x20000004 // timer: delay between pulses (in cycles) + + lc iv0, timer_handler + mov r10, 2 + mov cr, 1 // enable interrupt 0 + lc r0, 1000 + sw r104, r0 + sw r103, 1 + + hlt + + sw r100, r10 // r10 will be 2 if interrupt hasn't been called, which is a failure code + +halt: + hlt + jmp r101 // halt + +timer_handler: + mov r10, 1 + iret Index: tags/1.2/verify/lxp32/src/firmware/test015.asm =================================================================== --- tags/1.2/verify/lxp32/src/firmware/test015.asm (nonexistent) +++ tags/1.2/verify/lxp32/src/firmware/test015.asm (revision 10) @@ -0,0 +1,59 @@ +/* + * Test unconventional interrupt handlers + */ + + lc r100, 0x10000000 // test result output pointer + lc r101, halt + lc r102, 0x30000000 // coprocessor input register + lc r103, 0x30000004 // coprocessor output register + lc r104, failure + +// Initialize interrupt handlers + lc iv2, coprocessor_handler + mov cr, 4 // enable interrupts from the coprocessor + lc r110, interrupt_exit@1 // '1' in the LSB is an interrupt exit flag + +// Initialize random generator + mov r64, 1 // initial PRBS value + lc r65, 1103515245 // PRBS multiplier + lc r66, 12345 // PRBS addition constant + lc r67, 32767 // PRBS mask + +// Main loop + lc r32, loop + lc r33, rand + lc r34, 2000 + +loop: + call r33 + cjmpe r32, r0, 0 // if(r==0) continue; + sw r102, r0 + hlt + +interrupt_exit: + lw r1, r103 + mul r0, r0, 3 + cjmpne r104, r0, r1 // failure + + sub r34, r34, 1 + cjmpug r32, r34, 0 // loop + + sw r100, 1 + jmp r101 // halt + +failure: + sw r100, 2 + +halt: + hlt + jmp r101 // halt + +rand: + mul r64, r64, r65 + add r64, r64, r66 + sru r0, r64, 16 + and r0, r0, r67 + ret + +coprocessor_handler: + jmp r110 // exit to a given point, ignore irp Index: tags/1.2/verify/lxp32/src/firmware/test016.asm =================================================================== --- tags/1.2/verify/lxp32/src/firmware/test016.asm (nonexistent) +++ tags/1.2/verify/lxp32/src/firmware/test016.asm (revision 10) @@ -0,0 +1,47 @@ +/* + * Test for temporarily blocked interrupts + */ + + lc r100, 0x10000000 // test result output pointer + lc r101, halt + lc r102, failure + lc r103, 0x20000000 // timer: number of pulses (0xFFFFFFFF - infinite) + lc r104, 0x20000004 // timer: delay between pulses (in cycles) + + lc iv0, timer_handler + lc cr, 0x101 // enable interrupt 0 in temporarily blocked state + + lc r32, 0 // interrupt handler call counter + lc r33, 1000 // loop counter + lc r34, loop1 + lc r35, loop2 + + sw r104, 100 + sw r103, 1 + +loop1: + sub r33, r33, 1 + cjmpug r34, r33, 0 // loop1 + + lc r33, 1000 + mov cr, 1 // unblock interrupt 0 + +loop2: + sub r33, r33, 1 + cjmpug r35, r33, 0 // loop2 + +// r32 should be 1 by this point + cjmpne r102, r32, 1 // failure + sw r100, 1 + jmp r101 // halt + +failure: + sw r100, 2 + +halt: + hlt + jmp r101 // halt + +timer_handler: + add r32, r32, 1 + iret Index: tags/1.2/verify/lxp32/src/firmware/test017.asm =================================================================== --- tags/1.2/verify/lxp32/src/firmware/test017.asm (nonexistent) +++ tags/1.2/verify/lxp32/src/firmware/test017.asm (revision 10) @@ -0,0 +1,25 @@ +/* + * Test the new "lcs" instruction + */ + + lc r100, 0x10000000 // test result output pointer + lcs r101, halt + lcs r102, failure + + lc r0, 1000000 + lc r1, -1000011 + lcs r10, 1000000 + lcs r11, -1000011 + + cjmpne r102, r0, r10 // failure + cjmpne r102, r1, r11 // failure + + sw r100, 1 + jmp r101 // halt + +failure: + sw r100, 2 + +halt: + hlt + jmp r101 // halt Index: tags/1.2/verify/lxp32/src/firmware/test018.asm =================================================================== --- tags/1.2/verify/lxp32/src/firmware/test018.asm (nonexistent) +++ tags/1.2/verify/lxp32/src/firmware/test018.asm (revision 10) @@ -0,0 +1,1122 @@ +/* + * Additional interrupt test. The objective is to check that interrupt + * arrival at any time will not disrupt program flow. + * + * The main part of the program calculates CRC32 of a 16 kbyte block + * of data. The other part generates interrupts at random times using + * the C99 pseudorandom generator and the timer peripheral. + */ + + lc r100, 0x10000000 // test result output pointer + lcs r101, halt + lcs r102, failure + lc r103, 0x20000000 // timer: number of pulses (0xFFFFFFFF - infinite) + lc r104, 0x20000004 // timer: delay between pulses (in cycles) + +// Set up the interrupt handler + lcs r200, 0 // initialize counter + lc r201, 0x10000008 // output pointer + lc r202, 1103515245 // PRNG: multiplicative constant + lcs r203, 12345 // PRNG: additive constant + lcs r204, 32767 // PRNG: modulo + lcs r205, 1 // PRNG: current seed value + + lcs iv0, timer_handler + mov cr, 1 // enable interrupt 0 + + sw r104, 100 + sw r103, 1 // activate timer, one pulse + +// Main routine + lc r16, 0x10000004 // output pointer + lcs r17, 0xFFFFFFFF // initial CRC value + lc r18, 0xEDB88320 // polynom + lcs r19, data // input pointer + lcs r20, 4096 // data block size in words + + lcs r32, word_loop + lcs r33, bit_loop + lcs r34, dont_xor + + mov r64, 0 // word counter + +word_loop: + lw r0, r19 + mov r65, 0 // bit counter + +bit_loop: + and r1, r0, 1 + and r2, r17, 1 + sru r17, r17, 1 + xor r3, r1, r2 + cjmpe r34, r3, 0 // dont_xor + xor r17, r17, r18 + +dont_xor: + sru r0, r0, 1 + add r65, r65, 1 + cjmpul r33, r65, 32 // bit_loop + + sw r16, r64 + add r19, r19, 4 + add r64, r64, 1 + cjmpul r32, r64, r20 // word_loop + + not r17, r17 + sw r16, r17 + +// Check main routine result + lc r0, 0xF958DFE2 + cjmpne r102, r0, r17 + + mov cr, 0 // disable interrupts + sw r103, 0 // deactivate timer + + sw r100, 1 + jmp r101 + +failure: + sw r100, 2 + +halt: + hlt + jmp r101 + +timer_handler: +// PRNG generator from C99 (ISO/IEC 9899:1999) + mul r205, r205, r202 + add r205, r205, r203 + sru r220, r205, 16 + and r220, r220, r204 // r220 now contains the C99 pseudorandom number + and r221, r220, 0x1F + add r221, r221, 32 // r221 is now a pseudorandom number from the [32, 63] range + sw r104, r221 // set up the timer delay + sw r103, 1 // single shot + iret + + .align +data: + .byte 0xD7, 0x64, 0xC8, 0xCC, 0xE9, 0x32, 0x55, 0xC4, 0x47, 0x8D, 0x7A, 0xA0, 0x5D, 0x83, 0xF3, 0xEA + .byte 0xA2, 0xB7, 0x24, 0x9B, 0x04, 0x3E, 0x23, 0xCD, 0x28, 0x66, 0x21, 0x1B, 0xFF, 0x37, 0x83, 0xD6 + .byte 0x9C, 0x4B, 0xA3, 0x86, 0x7E, 0xF9, 0x4A, 0xC5, 0x86, 0xC5, 0x66, 0xE4, 0x48, 0x5A, 0xCE, 0xEB + .byte 0x11, 0xF3, 0x86, 0x16, 0x31, 0xA9, 0xE3, 0x59, 0x10, 0x05, 0x75, 0x10, 0x3C, 0xF8, 0xE6, 0xD9 + .byte 0x44, 0x8A, 0x60, 0xC2, 0x83, 0xAA, 0x88, 0x0A, 0x70, 0xEE, 0xEE, 0xB8, 0x48, 0xBD, 0xA3, 0x5A + .byte 0xB0, 0x2A, 0x70, 0xE1, 0xD4, 0x54, 0x3A, 0xE4, 0x59, 0xAF, 0xF4, 0x96, 0xA8, 0xDB, 0x70, 0xEC + .byte 0x65, 0xD0, 0xAF, 0xE9, 0x7B, 0x37, 0xF3, 0xEB, 0x25, 0xE1, 0xA4, 0x6E, 0x9E, 0x47, 0xC9, 0x4E + .byte 0x72, 0x39, 0x30, 0x46, 0x8E, 0x6A, 0x2B, 0xE8, 0x1A, 0x20, 0x7E, 0xC2, 0xFC, 0xEF, 0xAF, 0x62 + .byte 0xBF, 0x5E, 0x4B, 0x3B, 0x95, 0x3E, 0x27, 0xBB, 0x20, 0xCB, 0x2A, 0xBE, 0x13, 0xF3, 0x0D, 0x85 + .byte 0x2D, 0x3D, 0xCC, 0xBB, 0xA8, 0xF7, 0xA3, 0xC2, 0x17, 0x22, 0x85, 0x14, 0x11, 0x34, 0x76, 0xD1 + .byte 0x92, 0xC1, 0x0D, 0x28, 0xFF, 0x34, 0xE3, 0x20, 0xFF, 0x0D, 0xDE, 0x12, 0x01, 0xEC, 0x98, 0x2E + .byte 0x29, 0x64, 0xE9, 0xD1, 0x5B, 0x8D, 0x94, 0x73, 0xAF, 0x19, 0x87, 0xC1, 0x4D, 0xFE, 0x93, 0xE0 + .byte 0xBF, 0xA1, 0x09, 0xBF, 0xD5, 0xEC, 0xDF, 0xD4, 0xFA, 0xBE, 0xE7, 0xFB, 0xAA, 0x7F, 0x29, 0xD4 + .byte 0xE3, 0x13, 0xA6, 0x3F, 0xA1, 0x3A, 0xB3, 0x51, 0x54, 0x3B, 0x12, 0xA2, 0x39, 0xA6, 0x82, 0xF8 + .byte 0x47, 0x8B, 0xB8, 0x1C, 0x78, 0x97, 0xF1, 0x73, 0x56, 0xD9, 0x6F, 0x00, 0x58, 0x99, 0xD5, 0x3B + .byte 0xAC, 0x7B, 0x7B, 0x4E, 0xB6, 0x2E, 0x9F, 0x0A, 0x69, 0xB2, 0xAC, 0xA3, 0x58, 0x2F, 0x9B, 0xA0 + .byte 0xBB, 0x54, 0xBD, 0x33, 0xEB, 0xAF, 0xA7, 0x41, 0x88, 0x16, 0x42, 0xE0, 0xAF, 0x17, 0x1C, 0x5C + .byte 0x93, 0x97, 0xAA, 0x49, 0xC6, 0x49, 0x54, 0x30, 0xFB, 0x00, 0xD3, 0x54, 0x30, 0x6F, 0xF5, 0xEB + .byte 0xC3, 0xB2, 0x1F, 0xAF, 0x62, 0xC6, 0xF1, 0xEA, 0xDC, 0x34, 0xCB, 0x8C, 0x4C, 0xE7, 0xE8, 0xDF + .byte 0x7F, 0x93, 0x29, 0x46, 0xDD, 0x7E, 0x76, 0xD9, 0x7E, 0x4A, 0x2E, 0xAF, 0xBA, 0x23, 0x9A, 0x7E + .byte 0xD6, 0xB9, 0x2D, 0x38, 0x7F, 0x1F, 0x23, 0x5C, 0x53, 0xEE, 0xE8, 0x9F, 0xD6, 0xD1, 0x7E, 0x55 + .byte 0x64, 0xA8, 0x9B, 0x42, 0x26, 0x12, 0x1B, 0xA5, 0x5D, 0x49, 0x54, 0x17, 0x6D, 0xEF, 0x95, 0x43 + .byte 0xA8, 0xC3, 0x7C, 0x28, 0xE2, 0xA0, 0x84, 0x35, 0x8E, 0x6D, 0xD4, 0x64, 0x3E, 0x53, 0xBA, 0xA3 + .byte 0xFC, 0x56, 0xE5, 0x22, 0x69, 0x01, 0xC8, 0xC6, 0x4B, 0x1D, 0xDD, 0xB8, 0x0C, 0x72, 0xFC, 0xB5 + .byte 0x35, 0x79, 0xDD, 0x18, 0x19, 0x62, 0x4D, 0xA8, 0xCF, 0x21, 0x0D, 0x0D, 0x75, 0xC7, 0xB1, 0x71 + .byte 0x1E, 0x96, 0x94, 0x87, 0x98, 0x5C, 0x4D, 0xE3, 0x7A, 0x2B, 0x9C, 0x86, 0x9E, 0x98, 0x3B, 0xD4 + .byte 0x11, 0x19, 0xEC, 0x2B, 0x7B, 0x39, 0xD3, 0x4A, 0x5B, 0xE0, 0x58, 0xD0, 0xA8, 0x09, 0x41, 0xC7 + .byte 0xA0, 0xD6, 0x4E, 0x38, 0x32, 0x9C, 0x1C, 0xAC, 0xC8, 0xB8, 0x33, 0x66, 0x50, 0x6F, 0x3B, 0x62 + .byte 0x88, 0x27, 0x8E, 0x03, 0x61, 0x61, 0x4E, 0xBC, 0x42, 0xA6, 0x8D, 0xEB, 0xAF, 0xCF, 0xB2, 0x4F + .byte 0xA5, 0x01, 0x88, 0xD8, 0x9E, 0xA4, 0x84, 0x66, 0x5C, 0xB8, 0xCD, 0xAD, 0x27, 0x08, 0x10, 0xAF + .byte 0x30, 0x9E, 0xB3, 0x91, 0x00, 0x01, 0x4E, 0x42, 0xA7, 0xDB, 0x2E, 0x57, 0xAA, 0xE1, 0xA7, 0x50 + .byte 0xE2, 0x2F, 0x28, 0x80, 0xD4, 0xAC, 0xE7, 0x30, 0x64, 0xB4, 0xDE, 0x8C, 0xBD, 0xEE, 0x3B, 0xED + .byte 0x8D, 0xEE, 0x7E, 0x8D, 0xF0, 0xCC, 0xD0, 0x98, 0xA8, 0xFE, 0xEF, 0x53, 0xDF, 0x96, 0xA3, 0xC2 + .byte 0xC6, 0xCB, 0x43, 0x9A, 0x78, 0x2A, 0xCB, 0xDD, 0xDF, 0xAA, 0x69, 0x9C, 0x98, 0xA5, 0x89, 0x25 + .byte 0x94, 0x08, 0xB3, 0x84, 0xD5, 0x83, 0x1C, 0x7D, 0x82, 0x0C, 0xD0, 0x62, 0xA3, 0x73, 0x24, 0x69 + .byte 0x3F, 0x68, 0x04, 0xB7, 0x92, 0xD0, 0x95, 0x72, 0x7A, 0xFE, 0x0F, 0x13, 0xA4, 0x98, 0x38, 0x38 + .byte 0xA1, 0xEC, 0xBC, 0x76, 0x70, 0xD9, 0xF3, 0xF2, 0xE6, 0xC4, 0x55, 0x89, 0x38, 0x7A, 0xF3, 0x77 + .byte 0xE2, 0xF7, 0x2F, 0x75, 0xC7, 0xC4, 0xE7, 0x41, 0xC2, 0xF6, 0x54, 0x67, 0x8F, 0x8D, 0x9F, 0x30 + .byte 0x7A, 0x5C, 0xA7, 0xEA, 0x35, 0x9B, 0xDD, 0x1C, 0x5F, 0x32, 0xA5, 0x97, 0xAD, 0x98, 0x0F, 0x8F + .byte 0x90, 0x3E, 0x04, 0x58, 0x02, 0xEC, 0x99, 0xC5, 0xE3, 0xEE, 0x2C, 0x72, 0x7C, 0xCB, 0xA3, 0xF7 + .byte 0x27, 0x4A, 0xE1, 0x5D, 0xE6, 0xBF, 0x79, 0x45, 0xF2, 0x1F, 0xDD, 0x9F, 0xB7, 0xEC, 0x2F, 0x48 + .byte 0x2A, 0x33, 0xA0, 0x2D, 0x20, 0x3A, 0xF2, 0x03, 0x29, 0x1E, 0x76, 0xA6, 0xEA, 0x19, 0x9D, 0x12 + .byte 0x64, 0x7F, 0x6F, 0x4B, 0x3E, 0xE9, 0x90, 0x30, 0x08, 0x6E, 0xD0, 0xC0, 0x5B, 0xFF, 0x09, 0x86 + .byte 0x33, 0xA9, 0xB3, 0x53, 0xE3, 0xA5, 0x57, 0x0C, 0xC4, 0xCD, 0xB2, 0xAE, 0xE7, 0x50, 0xC0, 0x4C + .byte 0xCF, 0x30, 0x97, 0x0D, 0x19, 0x28, 0x3E, 0x22, 0x96, 0x0E, 0xE3, 0xF2, 0x0E, 0xEC, 0x78, 0x41 + .byte 0x96, 0x2B, 0x95, 0x79, 0xD0, 0xED, 0x86, 0x95, 0xBA, 0x39, 0x43, 0xA2, 0x89, 0x04, 0xEE, 0x58 + .byte 0x34, 0x85, 0x66, 0x4E, 0xAE, 0xA5, 0x71, 0x44, 0xB4, 0x55, 0x36, 0xC2, 0x42, 0xAE, 0x04, 0xD8 + .byte 0xDA, 0x99, 0x52, 0xAA, 0x86, 0xD9, 0x40, 0x41, 0x12, 0x83, 0xE3, 0x9C, 0x87, 0xD2, 0xF5, 0xBC + .byte 0x58, 0x5C, 0x0B, 0x06, 0x01, 0x7C, 0x4A, 0xB5, 0xD1, 0x81, 0x77, 0x14, 0x30, 0x7B, 0xEC, 0x0B + .byte 0x15, 0x3E, 0xB6, 0x9C, 0x17, 0xF6, 0xDE, 0x2A, 0x79, 0xC1, 0xC7, 0x01, 0x94, 0xBC, 0xBE, 0xEC + .byte 0x18, 0xC9, 0xF2, 0x19, 0x46, 0x3D, 0xCF, 0x18, 0xBF, 0x46, 0x2C, 0xF0, 0xC2, 0x18, 0xFB, 0xD8 + .byte 0x57, 0xB1, 0x74, 0x6F, 0xA7, 0x52, 0x99, 0x21, 0x14, 0x60, 0x23, 0xA8, 0x1D, 0xE1, 0x95, 0x35 + .byte 0xAB, 0x87, 0x4F, 0xF1, 0xC4, 0x1F, 0x09, 0x83, 0x66, 0x36, 0x73, 0x29, 0x4E, 0x6F, 0x01, 0xA6 + .byte 0x20, 0x76, 0x15, 0xC7, 0xC9, 0xAF, 0xE9, 0xDE, 0x10, 0x0C, 0x86, 0x2D, 0xED, 0x1C, 0x63, 0x98 + .byte 0xA3, 0xB3, 0x8A, 0x68, 0xD2, 0x93, 0xEB, 0x38, 0xCA, 0x5F, 0x61, 0x18, 0xCE, 0x63, 0xBF, 0xEF + .byte 0xD9, 0xD4, 0xB6, 0xA2, 0x84, 0x9F, 0x80, 0x94, 0xAB, 0x07, 0xC1, 0x99, 0x23, 0x24, 0x32, 0xC7 + .byte 0xD8, 0xBC, 0x2F, 0xAA, 0x50, 0x1B, 0xE3, 0x1A, 0x7A, 0x45, 0x33, 0x49, 0xA8, 0xF2, 0x38, 0x81 + .byte 0xC7, 0xEF, 0x24, 0x4B, 0x8F, 0xA4, 0xDF, 0x3B, 0xAC, 0xA1, 0xD5, 0xD0, 0xC5, 0x07, 0x97, 0x9E + .byte 0xC3, 0xC6, 0x48, 0x13, 0xE1, 0x2C, 0x2D, 0x5C, 0x71, 0x60, 0xA5, 0x19, 0x53, 0xDE, 0x9B, 0x1A + .byte 0xCE, 0xBF, 0x66, 0x5D, 0x64, 0x45, 0x99, 0x11, 0xE6, 0x6E, 0xE1, 0xAC, 0x75, 0x78, 0x4A, 0x39 + .byte 0x3E, 0x93, 0x4D, 0x20, 0xBF, 0x7A, 0x7C, 0x31, 0xDB, 0x22, 0x4B, 0x2F, 0x00, 0xE6, 0x49, 0xCF + .byte 0xA6, 0xB0, 0x2C, 0x0B, 0xF5, 0xC6, 0x1C, 0xDC, 0x35, 0xFE, 0x89, 0xAA, 0x77, 0xD4, 0xE4, 0xB6 + .byte 0x67, 0x31, 0xD6, 0x27, 0xAC, 0x52, 0x58, 0x88, 0x75, 0xA3, 0xB7, 0x75, 0x8A, 0x01, 0x44, 0x31 + .byte 0xB1, 0x71, 0x3C, 0xA7, 0x38, 0x59, 0x83, 0x6D, 0x57, 0x0C, 0x18, 0xCF, 0xE1, 0xFC, 0x85, 0x48 + .byte 0x2E, 0x5B, 0x70, 0xDA, 0xAE, 0xC9, 0x62, 0x23, 0x6D, 0x1A, 0x99, 0xF7, 0x1B, 0xDE, 0x28, 0xCD + .byte 0x50, 0x65, 0x74, 0x88, 0xBE, 0xF8, 0xF5, 0x16, 0x05, 0x0D, 0xE5, 0xE6, 0x0A, 0x6B, 0x2F, 0x38 + .byte 0xC7, 0x9F, 0x12, 0x76, 0x68, 0x75, 0x9A, 0xD5, 0x90, 0x33, 0xCD, 0xAC, 0x12, 0xF6, 0x79, 0x62 + .byte 0x5B, 0xEE, 0xEA, 0x1A, 0xE6, 0xE0, 0x31, 0xEB, 0xED, 0x16, 0xD2, 0xF7, 0x82, 0x01, 0x30, 0x49 + .byte 0xA0, 0x43, 0xBF, 0x09, 0xB8, 0x59, 0xDF, 0x48, 0x8D, 0xAC, 0xF5, 0x9F, 0xA3, 0x6E, 0x02, 0xFE + .byte 0x5D, 0xEC, 0x19, 0x43, 0xCD, 0x4A, 0x2F, 0xBA, 0x61, 0x01, 0xB2, 0xE3, 0x02, 0xE2, 0x2D, 0xA3 + .byte 0x25, 0xEC, 0xAC, 0xDE, 0x46, 0x8C, 0x27, 0xD4, 0x39, 0x1C, 0x73, 0xDC, 0x8B, 0x76, 0xDB, 0xE8 + .byte 0x62, 0xF4, 0x2C, 0x30, 0x3F, 0x5C, 0xEA, 0xA0, 0x5D, 0x9D, 0x84, 0x60, 0x80, 0xB1, 0x04, 0xA6 + .byte 0x9E, 0xB1, 0x85, 0xE5, 0x3D, 0xAC, 0xB9, 0x76, 0xC9, 0x2D, 0x53, 0x55, 0xA3, 0x2E, 0x3E, 0x06 + .byte 0x23, 0x6A, 0x36, 0x62, 0xC7, 0x21, 0x03, 0x25, 0xBE, 0x87, 0x86, 0x3F, 0x39, 0x8A, 0xE5, 0xD8 + .byte 0x3C, 0x6A, 0xBD, 0x7A, 0x17, 0x76, 0xF0, 0xE1, 0xA3, 0x44, 0x36, 0x47, 0x72, 0x75, 0x4D, 0x96 + .byte 0xE0, 0x83, 0xF8, 0xA7, 0xA4, 0xFC, 0xCC, 0x63, 0x83, 0x52, 0xA2, 0xBD, 0xDD, 0x88, 0x95, 0x19 + .byte 0xF3, 0x52, 0x93, 0x0B, 0xC9, 0x84, 0xEC, 0x6D, 0xC8, 0x23, 0xB4, 0x3B, 0x98, 0x02, 0xD1, 0x79 + .byte 0x85, 0xCA, 0x20, 0x2A, 0xC6, 0xEC, 0x8E, 0x4A, 0x3F, 0x31, 0x08, 0x1C, 0xBA, 0x9D, 0x36, 0xAD + .byte 0xF0, 0xC9, 0xB8, 0xBA, 0x4E, 0xA5, 0x27, 0x17, 0xC8, 0xDC, 0x52, 0x61, 0xDE, 0x24, 0xDA, 0x63 + .byte 0xEE, 0xFB, 0x8E, 0xB5, 0xE8, 0x1D, 0x00, 0x27, 0x4E, 0x08, 0x44, 0x08, 0xA5, 0x7A, 0xB6, 0x96 + .byte 0x44, 0x6F, 0x50, 0x92, 0x14, 0x77, 0xA9, 0xDD, 0x53, 0xFC, 0x3F, 0x31, 0x20, 0x19, 0x95, 0x0F + .byte 0x15, 0x24, 0xC4, 0xFD, 0x41, 0xC4, 0x24, 0x90, 0xCC, 0x69, 0x99, 0x72, 0xE3, 0x4F, 0x09, 0x28 + .byte 0xBF, 0x59, 0xBB, 0xD3, 0xD1, 0x64, 0xB1, 0x25, 0x61, 0xF0, 0x57, 0x81, 0x0A, 0xEC, 0x91, 0x1F + .byte 0x11, 0x56, 0x1C, 0x52, 0x1B, 0x41, 0xE3, 0xE8, 0xAB, 0x7C, 0x5A, 0x8F, 0xCC, 0x64, 0xB7, 0x8C + .byte 0xBD, 0x72, 0x5F, 0x8E, 0xD7, 0x11, 0xB4, 0x38, 0x01, 0x0B, 0xBA, 0x0B, 0xF8, 0x4B, 0x2B, 0x09 + .byte 0xA2, 0x48, 0x5C, 0xBD, 0x89, 0x3F, 0xA5, 0x34, 0xBC, 0x00, 0xC3, 0x89, 0x64, 0x7B, 0x15, 0x22 + .byte 0xED, 0x75, 0xB1, 0xC4, 0x86, 0x65, 0xFD, 0x88, 0x70, 0xB7, 0x94, 0x68, 0x03, 0xBF, 0x71, 0xA5 + .byte 0x07, 0xCE, 0x63, 0x91, 0x0E, 0x08, 0xC6, 0xCA, 0x09, 0x8A, 0x54, 0x6D, 0x05, 0x69, 0x90, 0xF2 + .byte 0xDF, 0x41, 0xB7, 0x66, 0xA6, 0xB4, 0xEE, 0x16, 0x6C, 0x83, 0x7F, 0x70, 0x43, 0xF1, 0x16, 0x4A + .byte 0xBF, 0x79, 0xDC, 0xCD, 0x82, 0xA2, 0x98, 0x8B, 0x2C, 0xED, 0xF9, 0x32, 0x57, 0x89, 0x24, 0x36 + .byte 0xCA, 0xDC, 0x9C, 0x71, 0x91, 0x8B, 0x88, 0xFE, 0x0F, 0x07, 0x6E, 0x52, 0xF9, 0x84, 0x9C, 0xB8 + .byte 0xFE, 0x79, 0x86, 0x80, 0x1B, 0x1F, 0x0B, 0x48, 0x0C, 0x05, 0x7A, 0x63, 0x8E, 0x9F, 0x9A, 0x59 + .byte 0x7C, 0x37, 0xCB, 0x0D, 0xC3, 0x53, 0x0C, 0xD2, 0x5B, 0x7A, 0x24, 0x54, 0xFF, 0xC1, 0x0D, 0xFE + .byte 0x3A, 0x94, 0x7E, 0x56, 0xB3, 0x8A, 0x9F, 0xC0, 0x8F, 0x1A, 0x24, 0x1E, 0xB9, 0xBF, 0x78, 0x36 + .byte 0xF6, 0x43, 0x44, 0xB9, 0x97, 0x50, 0x8C, 0xF2, 0xCB, 0xB0, 0x46, 0xCB, 0x72, 0x53, 0xC9, 0xAD + .byte 0xE8, 0x47, 0x04, 0x9B, 0xD1, 0xA3, 0x5C, 0x61, 0xBD, 0x81, 0x80, 0x77, 0x40, 0xF8, 0xAD, 0x37 + .byte 0x3C, 0xF1, 0xF0, 0xD3, 0x42, 0x7D, 0xC5, 0x0D, 0x2D, 0x0C, 0xD8, 0xA0, 0x60, 0xA1, 0x4D, 0x48 + .byte 0xE8, 0x51, 0xE4, 0xBA, 0xF4, 0x41, 0x1B, 0xB2, 0xC2, 0x9B, 0x2A, 0x03, 0x94, 0xD8, 0x3A, 0xD0 + .byte 0xC9, 0x2A, 0xA4, 0x0B, 0xA7, 0x69, 0x19, 0xD5, 0x76, 0xF1, 0x75, 0xD6, 0x92, 0xC3, 0x1F, 0x7B + .byte 0x14, 0x03, 0x36, 0x09, 0x44, 0x52, 0xBC, 0x07, 0xEE, 0xE6, 0x0A, 0x82, 0xBE, 0x44, 0x53, 0x88 + .byte 0x6F, 0xF7, 0x94, 0x17, 0x61, 0xAD, 0xED, 0xD8, 0x9F, 0x63, 0xAF, 0x32, 0x26, 0xCE, 0xAE, 0x3B + .byte 0xD2, 0xE4, 0x44, 0x17, 0x36, 0x00, 0x1E, 0x25, 0xE7, 0x28, 0xA8, 0xA5, 0x6D, 0xFB, 0x2E, 0xDC + .byte 0xF3, 0xC2, 0xF4, 0x55, 0x70, 0xE1, 0x2D, 0x0F, 0x44, 0xDC, 0x41, 0x6A, 0xAB, 0xEF, 0xA5, 0x7D + .byte 0xD4, 0xEA, 0x94, 0x0B, 0xEB, 0xB3, 0x30, 0xD2, 0xDC, 0xD9, 0x78, 0x49, 0xD5, 0xA6, 0x26, 0xC8 + .byte 0x68, 0x1A, 0x1E, 0xD9, 0xFC, 0x4B, 0xE8, 0x40, 0x28, 0x2A, 0xAB, 0xD3, 0x19, 0x51, 0x51, 0xEE + .byte 0x3C, 0xE5, 0xF9, 0x27, 0x98, 0x2A, 0xFA, 0x74, 0x03, 0x72, 0xBE, 0xD8, 0x18, 0xE4, 0xA1, 0x81 + .byte 0xFF, 0xBF, 0x5B, 0xFB, 0x0B, 0x43, 0x3C, 0x34, 0x6D, 0xE7, 0x07, 0x87, 0x39, 0x58, 0x75, 0x75 + .byte 0x3E, 0x6F, 0x9C, 0xD7, 0x9A, 0x96, 0x4B, 0x9D, 0x08, 0x09, 0x76, 0x21, 0xEE, 0x17, 0xA3, 0xED + .byte 0xD7, 0xFE, 0xE8, 0xE2, 0x42, 0x24, 0x16, 0xB0, 0x0C, 0x1E, 0x37, 0x45, 0x77, 0xAD, 0xBA, 0xB6 + .byte 0x1D, 0x56, 0x8D, 0xB7, 0xED, 0xD8, 0x55, 0xF6, 0xE2, 0xCB, 0x18, 0xD0, 0xE3, 0xBC, 0xBE, 0xBA + .byte 0xBB, 0xA7, 0x9D, 0xFD, 0xCB, 0xB4, 0xAD, 0xD8, 0xD2, 0xE5, 0x1D, 0x4A, 0x92, 0xD8, 0x00, 0xAF + .byte 0x2F, 0x8D, 0x67, 0x1C, 0x66, 0xBC, 0x13, 0x48, 0x87, 0x2B, 0x19, 0x6A, 0xE7, 0xD7, 0x24, 0xA3 + .byte 0x7E, 0xC2, 0xA0, 0x4A, 0x76, 0x4E, 0x23, 0x49, 0x33, 0x41, 0x93, 0xC5, 0x19, 0x94, 0x75, 0x49 + .byte 0x22, 0xDD, 0x66, 0x88, 0x99, 0x79, 0xD1, 0x21, 0xA5, 0xEB, 0x8B, 0x8D, 0xC3, 0xB0, 0x30, 0x42 + .byte 0x72, 0xD0, 0x8C, 0xE9, 0x1E, 0xB0, 0x32, 0x52, 0xF1, 0xC5, 0x18, 0x0B, 0x5A, 0x8D, 0x54, 0x7C + .byte 0x6A, 0xBA, 0x04, 0x04, 0x34, 0xD6, 0x25, 0xD9, 0xC1, 0xB1, 0x66, 0x84, 0x62, 0x97, 0xC6, 0xD5 + .byte 0x67, 0x53, 0xBE, 0x86, 0x03, 0xF0, 0xD8, 0xF5, 0xB6, 0xF0, 0x00, 0x10, 0x7E, 0x55, 0x8C, 0xE9 + .byte 0x10, 0x91, 0xEE, 0x44, 0x67, 0x13, 0x1E, 0x29, 0xC5, 0x84, 0xAE, 0x27, 0x1B, 0x74, 0xFD, 0x83 + .byte 0xC8, 0xBB, 0x0A, 0xCC, 0xAC, 0xE3, 0xC1, 0x62, 0xD4, 0xC2, 0x72, 0x53, 0x18, 0xFF, 0x3D, 0x28 + .byte 0x90, 0x2B, 0x6D, 0xF8, 0x3F, 0x8B, 0x21, 0x04, 0x0F, 0xCF, 0x2C, 0x2B, 0x44, 0x29, 0xAF, 0x0D + .byte 0xE5, 0xB9, 0xD9, 0x91, 0x9D, 0x9B, 0xF3, 0x71, 0x5E, 0x66, 0xC5, 0x76, 0x65, 0x02, 0x9F, 0xF6 + .byte 0x2D, 0x0C, 0xEF, 0x6D, 0x97, 0x11, 0x72, 0xA7, 0xE1, 0x9E, 0xD2, 0x25, 0xC8, 0x81, 0x33, 0xAD + .byte 0x3B, 0x0C, 0x3E, 0xD9, 0xA8, 0x32, 0x4B, 0x06, 0x98, 0x10, 0x7D, 0xFE, 0x12, 0x1C, 0xF5, 0x40 + .byte 0x28, 0xE4, 0xAE, 0xBF, 0xF6, 0x20, 0x66, 0xD7, 0xBE, 0x39, 0xFD, 0x87, 0xBB, 0x30, 0x34, 0xF7 + .byte 0x3C, 0x73, 0xD0, 0xE5, 0xA5, 0x1B, 0xEB, 0x3D, 0x2C, 0x68, 0x3C, 0x3F, 0x85, 0x31, 0x80, 0xAD + .byte 0x16, 0x2E, 0x6D, 0x0C, 0x4E, 0xD3, 0xE3, 0x0D, 0x0D, 0xE0, 0x94, 0xC8, 0x10, 0xC9, 0xBF, 0x4D + .byte 0x3C, 0x90, 0x32, 0xE2, 0xAC, 0x1E, 0x1F, 0xD8, 0x87, 0x5B, 0x18, 0x0C, 0x8D, 0x98, 0xB9, 0xA3 + .byte 0xC6, 0x27, 0xAF, 0x15, 0xFA, 0x92, 0x22, 0x08, 0x73, 0xB7, 0xD0, 0x84, 0x81, 0x90, 0xD1, 0xBE + .byte 0x21, 0x04, 0xA0, 0xCD, 0x23, 0xC0, 0xA6, 0xAA, 0x1B, 0xBE, 0xB7, 0xA9, 0x56, 0x71, 0x4C, 0x1D + .byte 0x98, 0xFB, 0x32, 0x93, 0x8E, 0x55, 0x9B, 0x01, 0x0C, 0x6C, 0x85, 0x8E, 0xFD, 0x57, 0x4C, 0x1E + .byte 0x5C, 0xEC, 0xEC, 0x7F, 0xAC, 0x92, 0x2A, 0xC8, 0x51, 0xE2, 0x71, 0xA7, 0x53, 0xBE, 0xC5, 0xEB + .byte 0xBA, 0xF7, 0x7E, 0x48, 0x4C, 0x1A, 0x49, 0x59, 0x86, 0xCF, 0xE7, 0x83, 0x27, 0x33, 0xA2, 0x83 + .byte 0x20, 0x8E, 0x03, 0xCC, 0x21, 0x2D, 0x95, 0x72, 0x0F, 0x07, 0x1A, 0x63, 0xC5, 0xDF, 0x4E, 0x7F + .byte 0xD7, 0xCD, 0xC7, 0x24, 0xE7, 0x11, 0x7D, 0x6E, 0xE1, 0x65, 0xF2, 0x08, 0x99, 0x94, 0x8B, 0xB9 + .byte 0x23, 0x8E, 0x86, 0x44, 0xBC, 0x1C, 0xB6, 0xCC, 0x23, 0xD1, 0x2F, 0xE9, 0xB0, 0x7E, 0x68, 0x87 + .byte 0x4C, 0x30, 0xAB, 0x33, 0x42, 0x29, 0xA2, 0x23, 0x8E, 0x94, 0x2C, 0x28, 0x29, 0xB8, 0xE1, 0x4C + .byte 0x47, 0x68, 0x91, 0x03, 0x84, 0x47, 0xD0, 0xA8, 0x18, 0x00, 0x91, 0xC9, 0x7F, 0xF9, 0x51, 0xCB + .byte 0x2A, 0xFC, 0xFE, 0x6C, 0x26, 0xA1, 0x90, 0xB4, 0x35, 0xBC, 0xDC, 0x5E, 0x74, 0xBE, 0xAB, 0xBC + .byte 0x26, 0x3C, 0xC0, 0xAB, 0x84, 0x90, 0x53, 0x9D, 0x91, 0xE4, 0x66, 0x10, 0xDE, 0xB8, 0xDB, 0x08 + .byte 0xB4, 0xDA, 0x75, 0xDA, 0x7B, 0x05, 0x8F, 0xB1, 0xC2, 0x6C, 0x10, 0x37, 0x2B, 0xBB, 0xF3, 0x52 + .byte 0xF8, 0xB3, 0xFD, 0x7C, 0x43, 0x51, 0x19, 0xD5, 0x35, 0x80, 0xE5, 0x14, 0x38, 0xC0, 0x1C, 0xED + .byte 0x9B, 0x91, 0xC8, 0x16, 0x97, 0x58, 0xC7, 0x59, 0xC5, 0xD7, 0x90, 0xF0, 0x93, 0x83, 0x42, 0x8B + .byte 0x36, 0x40, 0x08, 0x7A, 0x91, 0x22, 0x4F, 0xC7, 0xA3, 0x34, 0xDC, 0xDB, 0xF5, 0xF8, 0xC9, 0x90 + .byte 0x8A, 0x92, 0xA7, 0x21, 0xEA, 0x6E, 0x7B, 0xB0, 0x46, 0x0B, 0xA0, 0xDA, 0x8E, 0xE3, 0x65, 0xC5 + .byte 0x24, 0x6E, 0x3F, 0xB5, 0x90, 0x8F, 0x7D, 0x33, 0xC3, 0x59, 0x0F, 0xB9, 0x52, 0xD8, 0x49, 0xDD + .byte 0x6B, 0xF0, 0xFF, 0x56, 0x5F, 0x7A, 0x06, 0xA6, 0x85, 0xA7, 0x80, 0x14, 0x8A, 0xE6, 0xDA, 0xAE + .byte 0x54, 0x19, 0x64, 0xE4, 0xA9, 0xE2, 0x18, 0x6C, 0x3C, 0x27, 0x26, 0x8F, 0x00, 0x70, 0x6C, 0x6B + .byte 0x61, 0x6B, 0xC1, 0xC0, 0xE5, 0xC7, 0x67, 0x6B, 0x6F, 0xE8, 0x80, 0xF9, 0xCE, 0x5A, 0xA8, 0x23 + .byte 0x73, 0x0D, 0x08, 0x1C, 0xF0, 0x20, 0x89, 0x2C, 0x47, 0xB0, 0xBC, 0x47, 0x20, 0x28, 0xB3, 0x81 + .byte 0x94, 0x74, 0x41, 0x79, 0x3C, 0xA9, 0xE5, 0xAB, 0x91, 0x65, 0xA5, 0x60, 0xBF, 0x4E, 0x84, 0x33 + .byte 0x5B, 0x8C, 0x50, 0x4C, 0xAC, 0xDA, 0x79, 0xF4, 0x8A, 0x35, 0x3C, 0xAA, 0x5D, 0xEF, 0x2B, 0xF2 + .byte 0x64, 0x6D, 0x6C, 0xA0, 0x17, 0x51, 0x4C, 0xA8, 0xB6, 0xF1, 0x09, 0x76, 0x3F, 0x8D, 0xA9, 0x9B + .byte 0x1A, 0xFA, 0xE7, 0xC7, 0xD4, 0x60, 0xBB, 0x5E, 0x96, 0xF8, 0x09, 0xF4, 0xE7, 0x34, 0xE6, 0x4C + .byte 0xA2, 0x52, 0xED, 0xB9, 0xA3, 0x39, 0x62, 0x5A, 0x2A, 0x6B, 0xD0, 0x6A, 0xF8, 0x7A, 0x05, 0x12 + .byte 0x74, 0xED, 0xD9, 0x48, 0x4E, 0x95, 0xA7, 0xE4, 0x8D, 0xB0, 0xD8, 0x75, 0xE5, 0xBE, 0xC2, 0x87 + .byte 0x10, 0xAF, 0x41, 0xB4, 0xE8, 0xA3, 0x0E, 0x13, 0x0E, 0xDF, 0x7D, 0x07, 0x59, 0x83, 0x1A, 0xCD + .byte 0x70, 0xF4, 0x16, 0xBE, 0x89, 0xBE, 0xA3, 0x17, 0x6E, 0x7B, 0x8D, 0x54, 0x39, 0x4F, 0xDB, 0x4A + .byte 0xFE, 0x1C, 0xFE, 0xE7, 0xC0, 0x0D, 0xFA, 0xCE, 0xEC, 0x77, 0xD5, 0x46, 0xFA, 0xF0, 0x14, 0x6B + .byte 0xE4, 0x2A, 0x29, 0x6E, 0xE9, 0xCC, 0x85, 0x57, 0x48, 0x13, 0xAC, 0x82, 0x63, 0x88, 0xCC, 0x62 + .byte 0xA5, 0xCB, 0x49, 0x65, 0xD9, 0x43, 0x33, 0xC5, 0xBB, 0x09, 0x0B, 0xB6, 0xF9, 0x1F, 0x21, 0xDD + .byte 0x4A, 0x4B, 0x4B, 0x33, 0x18, 0xD1, 0x8B, 0x60, 0xE4, 0x37, 0xE3, 0x48, 0xBF, 0xAF, 0xAA, 0x65 + .byte 0x7B, 0xF3, 0xCA, 0x54, 0x37, 0xFE, 0x1A, 0xF2, 0x07, 0x25, 0xA9, 0x01, 0x45, 0xCA, 0xDF, 0x8F + .byte 0x16, 0x2B, 0xC3, 0x2E, 0xFD, 0x4E, 0x8F, 0xE2, 0x86, 0x72, 0x2A, 0x46, 0x22, 0xD4, 0xAB, 0x9D + .byte 0xC7, 0x75, 0xF2, 0xFE, 0x73, 0x0C, 0xF1, 0x7B, 0x32, 0x9A, 0x7D, 0x77, 0x65, 0x5C, 0x07, 0x7B + .byte 0x88, 0xCA, 0xAA, 0x85, 0x19, 0x39, 0x67, 0x9F, 0xAB, 0x91, 0xE6, 0xCD, 0x65, 0x91, 0x6B, 0x2C + .byte 0x06, 0x5D, 0x2B, 0x7A, 0x6A, 0x1D, 0xF6, 0x9C, 0xB7, 0x73, 0x14, 0x1D, 0xD0, 0x1B, 0x98, 0x58 + .byte 0xE6, 0x42, 0xDD, 0xFF, 0x7C, 0x44, 0x9F, 0x27, 0xD5, 0x85, 0xF5, 0x3A, 0x16, 0x61, 0x67, 0x1D + .byte 0xBF, 0x93, 0x98, 0x2A, 0xB0, 0x8E, 0xC6, 0x68, 0x02, 0xDA, 0x85, 0xD2, 0xF5, 0x1E, 0x2A, 0xDB + .byte 0x61, 0x07, 0xDB, 0xDD, 0x4B, 0x7A, 0x05, 0x21, 0xFF, 0xFB, 0x5C, 0x16, 0x5D, 0xC4, 0x34, 0x1D + .byte 0x57, 0xCC, 0x47, 0x08, 0x5B, 0x0D, 0x71, 0x5D, 0xE8, 0xF7, 0x2F, 0xDE, 0x16, 0x5A, 0xBA, 0x77 + .byte 0x61, 0x95, 0x55, 0xAD, 0x10, 0x5A, 0xCF, 0x10, 0x56, 0x2B, 0x26, 0xB3, 0xF0, 0x5A, 0xD1, 0x48 + .byte 0x27, 0x18, 0x50, 0x82, 0x25, 0xC2, 0xDF, 0x0E, 0xB9, 0x0F, 0xEC, 0xD0, 0x69, 0xA6, 0x47, 0xCB + .byte 0x3C, 0x9D, 0x79, 0x4C, 0xF8, 0x48, 0x5C, 0x4E, 0x74, 0x83, 0x02, 0x64, 0xDD, 0xD3, 0xAC, 0x05 + .byte 0xEB, 0xFD, 0x87, 0x11, 0xC0, 0x66, 0x20, 0x7A, 0x76, 0x0C, 0x4A, 0xDF, 0xB3, 0x92, 0xAB, 0xEF + .byte 0x2F, 0x24, 0x3B, 0x27, 0x6D, 0x98, 0x76, 0xE1, 0x1B, 0x78, 0x46, 0xF9, 0x4C, 0xF3, 0xFE, 0x38 + .byte 0xF1, 0x85, 0x4A, 0xB1, 0xEC, 0x6A, 0x2C, 0x62, 0x77, 0x76, 0x42, 0x2A, 0x09, 0xED, 0x19, 0x38 + .byte 0x11, 0x54, 0x60, 0x7E, 0xED, 0xD6, 0x60, 0x08, 0x4F, 0xA7, 0x02, 0x9C, 0x9B, 0x00, 0xD4, 0x8C + .byte 0x86, 0x1F, 0x3E, 0x73, 0x8A, 0x6A, 0xD5, 0x01, 0xE1, 0x18, 0x2B, 0xEA, 0x05, 0x44, 0x23, 0x16 + .byte 0x99, 0x83, 0x95, 0x86, 0x59, 0xF6, 0x8F, 0xA9, 0x9D, 0x92, 0x45, 0x38, 0x93, 0x1A, 0xC5, 0x19 + .byte 0x39, 0x03, 0x8D, 0xC3, 0x6E, 0x63, 0xC5, 0x50, 0x7B, 0xF0, 0x3B, 0x80, 0x35, 0x5E, 0x97, 0xCE + .byte 0xE2, 0x2C, 0x55, 0x3C, 0x23, 0xE5, 0xE5, 0xC0, 0x77, 0x2B, 0xF9, 0x0B, 0x45, 0xBE, 0x25, 0x7F + .byte 0xC2, 0xB2, 0x42, 0x31, 0x15, 0x07, 0x81, 0x90, 0xF8, 0xBC, 0x10, 0x2D, 0x1B, 0xA7, 0xFC, 0xFD + .byte 0xD4, 0x52, 0x3A, 0xF7, 0x38, 0x1F, 0xB8, 0xB0, 0x4A, 0xB1, 0xBB, 0x90, 0x70, 0xE0, 0x0F, 0x33 + .byte 0x92, 0x51, 0x64, 0xA8, 0x59, 0xE6, 0x38, 0x52, 0xA3, 0x49, 0x7F, 0xBE, 0xF1, 0x7C, 0xBC, 0xC6 + .byte 0xCF, 0xF6, 0xBD, 0x07, 0x16, 0x76, 0xB7, 0x60, 0x28, 0x73, 0xF1, 0x98, 0x53, 0x00, 0xCC, 0xE6 + .byte 0x52, 0x30, 0x8E, 0xAC, 0x16, 0xC7, 0xFE, 0xBA, 0x10, 0x7E, 0x78, 0x01, 0xFA, 0x35, 0xC7, 0xCA + .byte 0x2B, 0x85, 0xD1, 0x41, 0xFB, 0x89, 0xA2, 0x24, 0xFC, 0x93, 0xBC, 0x50, 0x94, 0x89, 0x36, 0xE6 + .byte 0xB9, 0xC5, 0x92, 0xD0, 0x8C, 0x90, 0x8A, 0x9D, 0x0F, 0x03, 0x9F, 0x0A, 0x38, 0x67, 0xD4, 0x64 + .byte 0xED, 0xA6, 0xA6, 0xE8, 0x2F, 0x49, 0x0D, 0x2C, 0xDD, 0xCA, 0x7C, 0x71, 0x53, 0xB3, 0x57, 0x0C + .byte 0x79, 0xE9, 0xDD, 0x05, 0x7A, 0x68, 0xA3, 0x89, 0x6B, 0x42, 0x93, 0xA4, 0xA9, 0x67, 0x09, 0x96 + .byte 0x0D, 0xAF, 0x7F, 0x3D, 0xF8, 0x8C, 0x6A, 0xD5, 0x57, 0xE6, 0x47, 0xAA, 0x9A, 0x9E, 0xB6, 0x14 + .byte 0x88, 0x94, 0x1A, 0x03, 0xFD, 0xBD, 0x8D, 0x69, 0xFF, 0x20, 0x0D, 0xA9, 0x88, 0x16, 0x40, 0x96 + .byte 0xC6, 0xC0, 0xD4, 0xBE, 0x4D, 0x3E, 0x94, 0xA4, 0x25, 0xDB, 0x4E, 0xC0, 0x7A, 0x05, 0xD4, 0x03 + .byte 0x9A, 0xEE, 0x06, 0x97, 0xAB, 0x93, 0x00, 0xAB, 0xB4, 0x0D, 0x55, 0x3D, 0x24, 0x96, 0xD4, 0xEB + .byte 0x56, 0xA8, 0xA9, 0xA4, 0xE7, 0x3E, 0x48, 0x0D, 0x1A, 0x97, 0xCD, 0x94, 0x9C, 0xA1, 0x97, 0x36 + .byte 0x90, 0x9D, 0xCE, 0x3C, 0x31, 0xCE, 0xE7, 0xE6, 0xDC, 0x3D, 0x23, 0x00, 0xD3, 0xF8, 0xEB, 0x29 + .byte 0xA0, 0x95, 0xCD, 0x88, 0xD4, 0x16, 0x95, 0xEE, 0xAD, 0x62, 0x82, 0x4A, 0x04, 0x1A, 0x81, 0x94 + .byte 0xB8, 0x4F, 0xD1, 0xE9, 0x1D, 0xB8, 0xCF, 0xF9, 0xF6, 0xF3, 0xFA, 0xC9, 0xEB, 0xE6, 0xF3, 0x8C + .byte 0x7C, 0xC1, 0x14, 0x50, 0xD7, 0xAA, 0x3F, 0x85, 0x0D, 0xC1, 0xCF, 0x12, 0xDB, 0x51, 0xA7, 0x93 + .byte 0xA0, 0x78, 0x7D, 0xBD, 0x31, 0x4D, 0xB7, 0x27, 0x40, 0xB2, 0xF0, 0x2C, 0x99, 0xE4, 0xB8, 0x15 + .byte 0xA5, 0xCD, 0x66, 0x7D, 0x78, 0xA5, 0x02, 0x85, 0x67, 0xD2, 0x97, 0x43, 0x23, 0x3E, 0xD7, 0xC4 + .byte 0xB7, 0x55, 0x82, 0xE8, 0xA2, 0x39, 0x0F, 0xE3, 0xEC, 0xFF, 0x0F, 0x85, 0xE3, 0xC8, 0x9B, 0x89 + .byte 0x96, 0x02, 0x06, 0x0E, 0xA8, 0x09, 0x93, 0x10, 0xDC, 0x2B, 0x53, 0xFF, 0x6A, 0x2B, 0xC4, 0x21 + .byte 0x80, 0x46, 0x09, 0x22, 0x80, 0x19, 0x06, 0x6C, 0x18, 0x15, 0xF2, 0xFC, 0xDD, 0x8E, 0x86, 0x74 + .byte 0x91, 0x8C, 0x82, 0x3A, 0x95, 0x16, 0x4A, 0x72, 0x42, 0x9E, 0x71, 0xAC, 0xC9, 0x35, 0xCE, 0x49 + .byte 0x7C, 0xD8, 0x6C, 0xFC, 0xF1, 0x72, 0x69, 0x0A, 0x87, 0x5C, 0x06, 0x65, 0xEA, 0x8C, 0xD9, 0x7C + .byte 0x19, 0x5C, 0xB6, 0xAF, 0x72, 0x00, 0x21, 0xB4, 0x9E, 0x93, 0x61, 0x67, 0xC9, 0x2F, 0xB1, 0x45 + .byte 0x08, 0x1D, 0x42, 0xF9, 0x8F, 0xAB, 0x03, 0x17, 0x07, 0x0A, 0x7D, 0xF2, 0x97, 0x57, 0x6E, 0xB0 + .byte 0xB3, 0x24, 0x60, 0x26, 0x24, 0x81, 0xDB, 0xC2, 0x15, 0x3C, 0x2A, 0xDE, 0x6C, 0xDB, 0x24, 0x74 + .byte 0xF9, 0x66, 0x6D, 0x89, 0x11, 0x71, 0xA1, 0x19, 0x7B, 0x1F, 0x0B, 0x12, 0x76, 0x79, 0xC3, 0x2A + .byte 0x9D, 0x23, 0x51, 0xC2, 0xA5, 0x2C, 0x85, 0xBA, 0x68, 0xAF, 0x98, 0xD5, 0x8B, 0xBC, 0x49, 0x85 + .byte 0x23, 0xB7, 0x0F, 0x34, 0x29, 0xB0, 0x4D, 0xA4, 0xCF, 0x59, 0xB7, 0x46, 0xD2, 0x7B, 0x71, 0x70 + .byte 0x9E, 0xC2, 0x32, 0x43, 0xEE, 0xB7, 0xFE, 0x57, 0x67, 0x96, 0x2D, 0xF3, 0x53, 0x76, 0x78, 0x76 + .byte 0x2E, 0x87, 0xAB, 0x57, 0x38, 0xF9, 0xFC, 0x08, 0x52, 0xB3, 0x4E, 0x24, 0x2E, 0xC0, 0x95, 0xCD + .byte 0x82, 0xC7, 0x11, 0x71, 0x7E, 0x0F, 0xC9, 0xE6, 0xA6, 0xF6, 0xD9, 0xFA, 0x6D, 0x52, 0x71, 0x9C + .byte 0xDA, 0x1D, 0xF3, 0x13, 0x16, 0xF0, 0x1B, 0x68, 0xA3, 0x6A, 0x8D, 0xD2, 0x2A, 0x22, 0xA0, 0xAD + .byte 0xEA, 0xB2, 0x1E, 0x69, 0xC2, 0xE8, 0x4F, 0x69, 0xDF, 0x29, 0x63, 0x4C, 0x7C, 0xD5, 0xE8, 0x56 + .byte 0xF2, 0xDC, 0x69, 0x08, 0xCC, 0x85, 0x71, 0x70, 0xEF, 0xFF, 0x43, 0x19, 0x22, 0xE4, 0xC6, 0x0C + .byte 0x96, 0xE5, 0x75, 0x59, 0xCE, 0xC5, 0xC2, 0xAD, 0xEE, 0x26, 0xF9, 0x6A, 0xFB, 0xE2, 0xC1, 0xED + .byte 0xBF, 0x2B, 0xF6, 0x8C, 0xB0, 0x67, 0xFD, 0x9F, 0x67, 0x40, 0xB9, 0x89, 0x25, 0x7F, 0x95, 0xBB + .byte 0x65, 0x0B, 0x14, 0x33, 0xD0, 0xD7, 0xE0, 0xBE, 0xFD, 0xDA, 0x29, 0xF8, 0xBD, 0xEA, 0xE6, 0x7D + .byte 0x15, 0xDC, 0x09, 0xC6, 0x44, 0x06, 0x66, 0xAB, 0x47, 0x1F, 0x34, 0x6C, 0x9F, 0xCA, 0x28, 0x04 + .byte 0xD5, 0x3D, 0x38, 0xA5, 0x14, 0x19, 0x64, 0x11, 0xF4, 0x8D, 0x0A, 0xB2, 0x78, 0xF0, 0x2F, 0x8E + .byte 0xCC, 0x38, 0x54, 0x10, 0x3F, 0xBA, 0xBC, 0x86, 0xD9, 0xF1, 0xF3, 0x79, 0xBB, 0x1B, 0x7D, 0x91 + .byte 0x59, 0xB6, 0x36, 0x6D, 0xCF, 0x9B, 0x7F, 0xC4, 0x28, 0x89, 0x76, 0xA0, 0x79, 0xA5, 0x2E, 0x46 + .byte 0xDE, 0x83, 0x57, 0x1D, 0x3D, 0x13, 0xA4, 0x17, 0x04, 0x98, 0x90, 0xC0, 0xB3, 0x0E, 0x51, 0x0D + .byte 0xC4, 0x88, 0x7A, 0x94, 0x23, 0xFA, 0x58, 0x4C, 0x84, 0xCE, 0xEC, 0xFD, 0x74, 0x1B, 0x44, 0x52 + .byte 0x9E, 0x9B, 0x70, 0xDC, 0xAF, 0x14, 0xF3, 0xB4, 0xAD, 0x84, 0x75, 0x61, 0x92, 0xC6, 0x6E, 0x56 + .byte 0x4F, 0xE9, 0xEB, 0x73, 0xE3, 0x43, 0xBF, 0x67, 0x12, 0xAC, 0x65, 0x86, 0xC8, 0xAA, 0xD8, 0x66 + .byte 0x45, 0x48, 0x43, 0xF5, 0x5D, 0x36, 0xA9, 0x0A, 0xBA, 0x1E, 0x6B, 0x4D, 0xE5, 0xDA, 0xA4, 0x35 + .byte 0xC3, 0x8F, 0xA8, 0xA7, 0xD3, 0x68, 0x0E, 0xE5, 0x15, 0x74, 0x6B, 0xDD, 0x1E, 0x44, 0x44, 0x64 + .byte 0x8D, 0x87, 0x59, 0xEB, 0xBE, 0x03, 0xF6, 0x79, 0x22, 0x62, 0xC6, 0x07, 0x3C, 0x6A, 0x3D, 0xFF + .byte 0xFA, 0xE5, 0xA6, 0xCD, 0x4E, 0xB5, 0xB2, 0x63, 0x29, 0x1E, 0x41, 0x48, 0x63, 0x86, 0xAC, 0xF0 + .byte 0x0E, 0x05, 0xDC, 0xCD, 0x09, 0xD2, 0x46, 0x2B, 0x34, 0x0D, 0x32, 0x70, 0x78, 0x6F, 0x70, 0x72 + .byte 0x55, 0x17, 0x3F, 0xA4, 0xCC, 0xF2, 0x08, 0xF6, 0x11, 0x4A, 0x3E, 0x74, 0xD0, 0xEA, 0x65, 0xDF + .byte 0xF0, 0x41, 0xAC, 0xF9, 0x13, 0xF2, 0x24, 0x48, 0xFF, 0x57, 0xB9, 0x77, 0xC7, 0x29, 0xEA, 0x1D + .byte 0x40, 0x29, 0xC1, 0x0D, 0x1B, 0xCA, 0x03, 0x2D, 0x14, 0x41, 0xA1, 0xE5, 0x2C, 0x06, 0xC4, 0x1C + .byte 0x48, 0x70, 0x16, 0x5C, 0x62, 0x3B, 0xA4, 0x62, 0x93, 0x5E, 0xDA, 0x5A, 0x87, 0xC4, 0x78, 0xC8 + .byte 0xEE, 0x3A, 0xD6, 0x0A, 0x04, 0xD9, 0x37, 0x18, 0x1B, 0xD8, 0xFD, 0x48, 0xDF, 0xC1, 0x65, 0x27 + .byte 0x32, 0x7B, 0x83, 0x94, 0xB7, 0x28, 0xF7, 0x4A, 0x86, 0xD2, 0xA5, 0x0E, 0x96, 0x1D, 0xD7, 0x85 + .byte 0x57, 0xAD, 0x8F, 0x5C, 0x87, 0xC6, 0x75, 0xA3, 0x9F, 0x73, 0xEC, 0x7F, 0x35, 0x51, 0xA6, 0x67 + .byte 0xCD, 0x2A, 0xFC, 0x84, 0x53, 0xF3, 0xCE, 0xDA, 0xC5, 0x73, 0xE8, 0x5C, 0x91, 0xC0, 0xE1, 0xE8 + .byte 0x6E, 0x70, 0x45, 0xF6, 0x37, 0xBA, 0x9A, 0xD7, 0x2D, 0x86, 0x56, 0x62, 0xD7, 0xFD, 0xCA, 0xA4 + .byte 0x28, 0xC6, 0x29, 0x7B, 0xB9, 0xF7, 0x55, 0x7E, 0x6B, 0x3E, 0xDB, 0xFC, 0xFE, 0xBC, 0xE5, 0x6D + .byte 0x2D, 0x2A, 0x63, 0x64, 0xE5, 0xFD, 0x3B, 0x12, 0x84, 0x92, 0x75, 0x5B, 0x8F, 0x3F, 0x00, 0xB7 + .byte 0x05, 0x2A, 0x32, 0xBF, 0x22, 0x88, 0x3E, 0x8D, 0xC6, 0x19, 0x8A, 0xC5, 0xD5, 0x70, 0x32, 0x03 + .byte 0x9A, 0x96, 0x67, 0x80, 0x94, 0xA3, 0x93, 0x18, 0x35, 0x08, 0x74, 0xC4, 0x48, 0x74, 0x7C, 0x4E + .byte 0x9F, 0xAF, 0x0D, 0xC1, 0x37, 0x4B, 0x4F, 0xFE, 0x65, 0xD9, 0xC4, 0x3B, 0x49, 0xF7, 0x3E, 0xE4 + .byte 0x8D, 0xA5, 0x64, 0x22, 0x49, 0xF7, 0x3A, 0x7E, 0x00, 0xAE, 0x43, 0x49, 0x23, 0xC0, 0x97, 0xC2 + .byte 0x6F, 0xA4, 0x83, 0xA7, 0xF0, 0xD2, 0xA6, 0x55, 0xAC, 0x6A, 0x90, 0xF6, 0x61, 0xCF, 0xDA, 0xEF + .byte 0x74, 0x3F, 0x11, 0xBD, 0x37, 0x4C, 0x3C, 0x38, 0xFA, 0x80, 0x81, 0x1E, 0x40, 0x18, 0xE0, 0xAF + .byte 0xBD, 0x64, 0x57, 0xAE, 0x37, 0xFD, 0x04, 0xE4, 0x67, 0x95, 0xDA, 0xC9, 0x64, 0xB5, 0xB9, 0xD8 + .byte 0xF5, 0xCB, 0x96, 0x2C, 0x17, 0xD3, 0x64, 0x12, 0x54, 0xE6, 0x30, 0x94, 0xFE, 0x11, 0x44, 0xBC + .byte 0x76, 0x9B, 0x6A, 0xAE, 0x99, 0x6E, 0x92, 0x00, 0x03, 0x6D, 0xCA, 0x67, 0x22, 0x84, 0x40, 0x17 + .byte 0x4F, 0xD7, 0x44, 0x67, 0xAB, 0xA8, 0x79, 0xFF, 0x8E, 0xAA, 0x94, 0x8D, 0xBC, 0xD8, 0x49, 0x32 + .byte 0x74, 0xB4, 0xE0, 0x0D, 0x22, 0x73, 0x0E, 0x26, 0xE0, 0xD9, 0x8E, 0x02, 0x5D, 0xCE, 0x1A, 0xAC + .byte 0xA6, 0x5E, 0x14, 0x51, 0x07, 0x8D, 0x51, 0x96, 0x38, 0xE5, 0x23, 0xF4, 0xBE, 0x6D, 0x26, 0x32 + .byte 0x21, 0x07, 0x40, 0x44, 0x7A, 0x4E, 0x6A, 0x5A, 0x28, 0xF8, 0x5D, 0x85, 0xC7, 0x77, 0x32, 0x6E + .byte 0xD5, 0x46, 0xC0, 0xDC, 0xD4, 0x11, 0x72, 0x0C, 0xF6, 0x96, 0x00, 0xB4, 0x03, 0x27, 0xE7, 0x25 + .byte 0x2F, 0x28, 0x69, 0xA9, 0x76, 0xD3, 0x04, 0x9F, 0xCC, 0x61, 0x24, 0x94, 0xD9, 0x56, 0x02, 0xAE + .byte 0x9C, 0xC2, 0x8B, 0x70, 0xD4, 0xFE, 0x7D, 0xCB, 0x94, 0x7D, 0x7F, 0x98, 0xA5, 0x67, 0xBD, 0xD4 + .byte 0x8F, 0x26, 0x7E, 0x06, 0xFA, 0x83, 0xA5, 0xC7, 0xE5, 0xCA, 0x5B, 0xBE, 0x20, 0x5E, 0x6D, 0xBD + .byte 0x21, 0xF8, 0x2E, 0xF5, 0xF6, 0xAB, 0xC0, 0x8B, 0x29, 0x40, 0x23, 0xCF, 0xA8, 0xE0, 0xA3, 0x37 + .byte 0x07, 0x22, 0x3E, 0x02, 0xA5, 0xE3, 0xC9, 0x8A, 0xAD, 0x25, 0x49, 0xCE, 0x83, 0xB6, 0x8C, 0xA4 + .byte 0xAE, 0xBA, 0x99, 0xA5, 0x65, 0x5A, 0x30, 0x8F, 0x9A, 0x54, 0x5E, 0x42, 0x35, 0x02, 0x7A, 0x3C + .byte 0x24, 0xB8, 0x3E, 0xCA, 0x9C, 0x08, 0x55, 0x4A, 0x2D, 0x9E, 0x19, 0xB0, 0x54, 0xA5, 0x55, 0x02 + .byte 0x5F, 0xEE, 0xA8, 0xC5, 0x49, 0xD8, 0x54, 0xE4, 0x2C, 0xB3, 0x27, 0x61, 0xB5, 0xA1, 0x9E, 0xDA + .byte 0x5A, 0xDD, 0xA4, 0xF7, 0xE5, 0xFA, 0x41, 0x13, 0x98, 0x5B, 0xC3, 0xED, 0x00, 0x18, 0xF0, 0x60 + .byte 0x07, 0x98, 0x25, 0x50, 0x71, 0x7A, 0x35, 0x9E, 0x2D, 0x5C, 0x00, 0xE3, 0xFE, 0x9E, 0xBD, 0x58 + .byte 0x7C, 0x62, 0x50, 0x62, 0x5C, 0x92, 0x75, 0xF5, 0xED, 0x39, 0xE2, 0xEE, 0x51, 0xD2, 0x4E, 0x59 + .byte 0x6B, 0x74, 0xAA, 0xDC, 0xEE, 0xDF, 0x7B, 0x1C, 0x3B, 0x7B, 0xFF, 0x3A, 0x1A, 0xBC, 0x93, 0x96 + .byte 0x1E, 0xE3, 0xF8, 0x7B, 0x75, 0x6E, 0x71, 0x63, 0xA7, 0x53, 0x51, 0xF9, 0x26, 0x9F, 0x52, 0x92 + .byte 0x13, 0xFC, 0x6F, 0x02, 0xDC, 0xEA, 0x1E, 0x17, 0x65, 0x1D, 0x52, 0x7F, 0xD9, 0xE5, 0x16, 0xF8 + .byte 0xC8, 0x0F, 0x74, 0x3D, 0x7D, 0xE5, 0xA0, 0x24, 0x39, 0xF2, 0x1D, 0x5F, 0x91, 0x70, 0xF2, 0xA5 + .byte 0x6C, 0x61, 0xA7, 0x48, 0x4B, 0xC5, 0x60, 0xB0, 0xE2, 0xB2, 0x30, 0xBC, 0x97, 0x46, 0xB4, 0x60 + .byte 0x55, 0x29, 0x9E, 0xD3, 0x0E, 0x3F, 0xF7, 0x47, 0x31, 0x15, 0xA7, 0xC2, 0x85, 0x99, 0x67, 0xF2 + .byte 0xFB, 0x0E, 0x3A, 0x46, 0xD4, 0x9B, 0xF7, 0xB6, 0x4E, 0x28, 0x73, 0xE6, 0x6E, 0x27, 0x46, 0xC4 + .byte 0x51, 0xE4, 0x97, 0x5F, 0x23, 0x8F, 0xA7, 0x54, 0xA4, 0x4E, 0x17, 0x29, 0xE8, 0x7F, 0x1B, 0xE4 + .byte 0x8E, 0x56, 0x2A, 0x62, 0xF2, 0x22, 0x19, 0x40, 0x4A, 0x8C, 0x26, 0xB9, 0xB4, 0x6D, 0x7D, 0x05 + .byte 0x51, 0x14, 0x64, 0x75, 0xA4, 0x0C, 0xC9, 0x48, 0x5B, 0xE1, 0x72, 0x44, 0x60, 0x8D, 0x28, 0xEE + .byte 0xE4, 0x53, 0x50, 0xD6, 0x75, 0x69, 0x16, 0xC0, 0xF6, 0x3D, 0x79, 0xAA, 0xAA, 0xF6, 0xAF, 0xFC + .byte 0x0B, 0x14, 0x71, 0xAF, 0x21, 0x3B, 0xF8, 0x7C, 0x1C, 0x6A, 0xC0, 0x7C, 0xF8, 0xE8, 0x6A, 0xDC + .byte 0x3B, 0xBB, 0xB3, 0xB1, 0x25, 0xCA, 0x71, 0x1B, 0x07, 0xEB, 0xC6, 0xB2, 0xE1, 0x76, 0xAE, 0xED + .byte 0x8A, 0x1F, 0x9D, 0xAB, 0x5A, 0x95, 0x28, 0x76, 0x00, 0xE8, 0xF3, 0xF8, 0xD1, 0x5E, 0xD5, 0x0D + .byte 0x1A, 0x88, 0xBE, 0x3F, 0x52, 0x30, 0x5B, 0x5A, 0x1B, 0x22, 0x0C, 0xFD, 0x98, 0xBB, 0xEB, 0x23 + .byte 0xDB, 0x88, 0xCF, 0x36, 0x1E, 0xF7, 0xAD, 0x1E, 0xE0, 0xA0, 0x17, 0xB1, 0xFE, 0xEC, 0xBE, 0x18 + .byte 0x74, 0x7D, 0x58, 0xC7, 0xAD, 0xB4, 0x21, 0xC9, 0xD6, 0x2E, 0xC7, 0x6E, 0xEA, 0xB2, 0x91, 0xC5 + .byte 0x3B, 0x61, 0xFB, 0x59, 0x58, 0xA8, 0x78, 0x38, 0x49, 0x8F, 0xE9, 0x48, 0x7B, 0xA8, 0x61, 0xF0 + .byte 0x25, 0xBA, 0xB7, 0xD3, 0x6E, 0xD9, 0x9D, 0x45, 0x08, 0x64, 0xB4, 0xF2, 0x16, 0x46, 0xB7, 0x51 + .byte 0xA7, 0xB3, 0xAB, 0xFF, 0x5C, 0x23, 0x38, 0xA6, 0xB2, 0x22, 0xEE, 0x2E, 0xCA, 0x4F, 0x1E, 0xF0 + .byte 0x09, 0xD5, 0xC4, 0x78, 0xAF, 0x62, 0xBD, 0xB7, 0xC6, 0x72, 0xA9, 0xDD, 0xB8, 0x61, 0x2F, 0x5F + .byte 0x15, 0xDA, 0x5F, 0x71, 0xFE, 0x97, 0x17, 0xB1, 0xB9, 0x06, 0xDF, 0x84, 0x56, 0xFE, 0x75, 0x60 + .byte 0xD3, 0x3A, 0xD8, 0x83, 0x9C, 0x96, 0x3A, 0x63, 0x08, 0xE3, 0x40, 0xC1, 0x45, 0x6F, 0x20, 0x5A + .byte 0x4A, 0x7F, 0xCC, 0x49, 0x17, 0xE4, 0xFA, 0xD1, 0xEA, 0xDA, 0x56, 0x40, 0xD8, 0xCB, 0xA0, 0xAC + .byte 0x06, 0x79, 0x2F, 0xA3, 0x10, 0x69, 0x06, 0x19, 0x4D, 0x47, 0xDA, 0x92, 0xB7, 0xFB, 0xED, 0x02 + .byte 0x7B, 0xB9, 0x4B, 0x93, 0x9D, 0x45, 0x64, 0x88, 0x20, 0xBA, 0xC9, 0xF8, 0x86, 0x6A, 0xA5, 0x8D + .byte 0xE4, 0xD5, 0x30, 0xF4, 0x3E, 0x37, 0x0E, 0x8C, 0x7E, 0xE9, 0x1F, 0x35, 0xE5, 0x0C, 0x37, 0x60 + .byte 0xC6, 0x82, 0xF3, 0x64, 0xC8, 0x58, 0xED, 0xE9, 0x13, 0xB6, 0xE2, 0x99, 0x21, 0x87, 0x27, 0x05 + .byte 0x5C, 0x57, 0xFA, 0x9B, 0x8E, 0x09, 0x28, 0x0C, 0xF2, 0x47, 0x42, 0xD7, 0x54, 0x7A, 0x38, 0x1B + .byte 0xFD, 0x2C, 0x7F, 0xC5, 0x84, 0x6D, 0xAF, 0x98, 0x23, 0x91, 0x32, 0x45, 0x18, 0x59, 0x4A, 0x75 + .byte 0xB0, 0x44, 0x11, 0x3F, 0x4D, 0x39, 0x4C, 0x40, 0x81, 0x8E, 0x18, 0xD5, 0x09, 0x51, 0xF1, 0x06 + .byte 0x7D, 0x71, 0xCC, 0x02, 0xDE, 0x7B, 0x9A, 0x02, 0x0C, 0xCC, 0x47, 0x25, 0x26, 0x91, 0x9A, 0xD6 + .byte 0xD6, 0xAB, 0x16, 0x24, 0xE4, 0x62, 0x65, 0x66, 0xF1, 0x7D, 0x3B, 0xFA, 0xCE, 0x2C, 0x00, 0x4C + .byte 0x9D, 0xCC, 0x4F, 0x7C, 0x48, 0xEA, 0x7E, 0x54, 0xB7, 0xC5, 0x79, 0xDD, 0x57, 0x14, 0xB4, 0x2D + .byte 0xC0, 0xCA, 0x51, 0xA4, 0x2D, 0xB6, 0x0A, 0x1E, 0x34, 0x46, 0x19, 0x03, 0x73, 0x1A, 0x4F, 0x11 + .byte 0xE7, 0x9E, 0x8D, 0x2F, 0x88, 0x0B, 0x84, 0x3F, 0xD0, 0xFD, 0x1D, 0x27, 0x12, 0xD1, 0x55, 0xD2 + .byte 0x9B, 0xA7, 0x77, 0xC8, 0x5E, 0x82, 0xE7, 0x92, 0xC8, 0x00, 0x95, 0x3C, 0x1A, 0xE5, 0x4D, 0x01 + .byte 0x84, 0xDA, 0x31, 0x0D, 0xE6, 0xB5, 0x4D, 0xB7, 0xB2, 0x6A, 0xDE, 0xC5, 0x3B, 0x34, 0x97, 0xD6 + .byte 0xDB, 0x0E, 0x9E, 0x39, 0x90, 0x85, 0xCC, 0x59, 0x86, 0x62, 0x95, 0xA0, 0x47, 0xE3, 0xA2, 0xCB + .byte 0xBD, 0xD3, 0xD9, 0xA4, 0x88, 0x26, 0x5B, 0x3B, 0x90, 0x3A, 0x00, 0xCB, 0x6E, 0x97, 0xA1, 0x4A + .byte 0xA6, 0x40, 0x84, 0x36, 0xC6, 0x50, 0x8F, 0x4D, 0xB3, 0x25, 0xED, 0xFA, 0x08, 0x90, 0xC6, 0xC6 + .byte 0x64, 0x9F, 0x6A, 0xEC, 0xC5, 0xC5, 0x28, 0x55, 0x00, 0x29, 0x21, 0x6E, 0xC1, 0xC3, 0xB9, 0x67 + .byte 0x04, 0x3D, 0x9D, 0xCA, 0x8E, 0x2D, 0x17, 0x41, 0x52, 0x05, 0x3C, 0x5A, 0x96, 0x02, 0x21, 0xFA + .byte 0xA2, 0x8B, 0xE6, 0x68, 0x51, 0x0F, 0xBE, 0x51, 0x38, 0xDF, 0xC0, 0xF9, 0xA2, 0x79, 0x60, 0xA6 + .byte 0xB7, 0xFE, 0x71, 0x45, 0x2B, 0x89, 0x86, 0x7E, 0x8E, 0xC3, 0xD9, 0x25, 0xC5, 0xFA, 0x1F, 0x68 + .byte 0x85, 0x05, 0xD0, 0xD7, 0x15, 0x8E, 0x28, 0x4D, 0x6E, 0xE9, 0x47, 0x10, 0x63, 0xA8, 0xB7, 0x1A + .byte 0xA6, 0x29, 0x60, 0xD2, 0xB2, 0xE7, 0x51, 0x41, 0xAA, 0x2A, 0x66, 0x70, 0x24, 0x85, 0xD8, 0xAA + .byte 0x8B, 0xA9, 0x81, 0xA0, 0x37, 0xAA, 0xEE, 0xA6, 0x94, 0x35, 0xB7, 0xF7, 0xDE, 0x6E, 0x12, 0x84 + .byte 0x97, 0x72, 0x57, 0x4A, 0x5A, 0xA8, 0x8B, 0x04, 0xD3, 0xF1, 0x74, 0xF8, 0x77, 0x4D, 0xA3, 0x02 + .byte 0xF6, 0x25, 0xA3, 0x2E, 0xCF, 0x91, 0xD4, 0x64, 0xC7, 0x8B, 0x5C, 0xA5, 0xFA, 0x6E, 0x2A, 0x91 + .byte 0xE1, 0x82, 0xDB, 0x3B, 0x2B, 0x67, 0x40, 0xFE, 0x59, 0xB4, 0xF6, 0xD0, 0x01, 0x9A, 0xD3, 0xF8 + .byte 0xBF, 0x76, 0x26, 0x8E, 0x08, 0xFA, 0xF3, 0xCF, 0x86, 0x4F, 0x75, 0x80, 0xBE, 0x9F, 0x11, 0x9F + .byte 0x22, 0xED, 0xDB, 0x4D, 0x55, 0x1B, 0x4B, 0xAE, 0xCF, 0x42, 0x7E, 0xD1, 0xDC, 0x51, 0xC9, 0x9B + .byte 0xC8, 0xF0, 0x2A, 0xD0, 0xEA, 0x1E, 0xA0, 0x71, 0x6D, 0x15, 0xF1, 0x2B, 0xB5, 0x03, 0xCB, 0xD7 + .byte 0xF0, 0xA6, 0x24, 0x46, 0xC1, 0x70, 0xF4, 0x91, 0xB3, 0x73, 0x62, 0x90, 0xC5, 0x2C, 0x2C, 0x8D + .byte 0x1C, 0x57, 0x5E, 0x07, 0x75, 0xFE, 0x78, 0xE3, 0x14, 0x69, 0x0E, 0xC9, 0x6C, 0xD9, 0xA0, 0x5D + .byte 0x80, 0xC5, 0xA3, 0x41, 0x36, 0x98, 0xD2, 0xE9, 0x0B, 0x35, 0x79, 0xD0, 0x62, 0xA6, 0x5D, 0x7E + .byte 0xFD, 0xBC, 0x86, 0x73, 0xBA, 0xFE, 0x56, 0xCE, 0x68, 0x64, 0x98, 0xD5, 0x3E, 0x39, 0x33, 0xBF + .byte 0xFE, 0xD7, 0x00, 0x34, 0x6F, 0xD3, 0x1E, 0x7A, 0x09, 0x98, 0x4B, 0x6B, 0x3E, 0xA8, 0xEA, 0x3C + .byte 0x64, 0x70, 0xAF, 0x1F, 0x6E, 0x05, 0xEE, 0xD7, 0x6A, 0x86, 0xAC, 0xA9, 0xBF, 0xDF, 0x68, 0xBE + .byte 0xB7, 0x68, 0xF3, 0x26, 0x3C, 0x11, 0xA1, 0x45, 0xAA, 0xEC, 0xB0, 0xE9, 0x95, 0x9B, 0x25, 0xF9 + .byte 0x0B, 0xD4, 0x19, 0x7A, 0xDA, 0x07, 0x51, 0x44, 0x8E, 0xFE, 0xED, 0x4E, 0xDE, 0x55, 0x0D, 0x95 + .byte 0xBE, 0x00, 0xBB, 0xFB, 0x12, 0x5D, 0x40, 0xBC, 0x49, 0xF1, 0xA6, 0xDE, 0x8C, 0xCB, 0xD8, 0x98 + .byte 0xA0, 0xF1, 0x12, 0x7A, 0xF9, 0x63, 0xBE, 0x88, 0x61, 0xAC, 0xD6, 0x40, 0x01, 0xE3, 0xD5, 0xC0 + .byte 0xE4, 0x91, 0xBB, 0xF6, 0xEE, 0xFC, 0xB3, 0x37, 0xED, 0x59, 0x16, 0x7A, 0x25, 0xEE, 0x12, 0xC5 + .byte 0xE0, 0x24, 0x3F, 0xD9, 0x88, 0xFE, 0x62, 0xEA, 0xAA, 0x38, 0x2A, 0xAC, 0x1C, 0x00, 0x6C, 0x00 + .byte 0x91, 0x27, 0xF6, 0x7F, 0x24, 0xAA, 0xB7, 0x12, 0x04, 0xCD, 0x8C, 0x29, 0xBB, 0x9F, 0xEE, 0x9C + .byte 0xC4, 0x2E, 0x76, 0x4D, 0x2C, 0xD8, 0x37, 0xD6, 0x10, 0x62, 0x82, 0x2C, 0x63, 0xEF, 0x2C, 0xF4 + .byte 0x17, 0x23, 0x74, 0x3B, 0xCE, 0x2C, 0x4D, 0xD2, 0xF9, 0xDA, 0xFC, 0xB5, 0x79, 0xEA, 0x51, 0x3E + .byte 0x19, 0xC7, 0x8B, 0x45, 0x9F, 0xC3, 0x1C, 0xB0, 0x26, 0x9F, 0xDD, 0x89, 0x8F, 0x0A, 0x7E, 0xA6 + .byte 0x2D, 0xF2, 0xE1, 0xFC, 0x1E, 0x2F, 0xCE, 0x18, 0x09, 0xCB, 0xCD, 0x83, 0xB6, 0x1F, 0xC1, 0xCF + .byte 0xE7, 0x4D, 0x15, 0x87, 0x10, 0x31, 0x37, 0x37, 0xD1, 0x14, 0xC0, 0x60, 0x1F, 0x3E, 0x06, 0x4C + .byte 0x31, 0xE8, 0x49, 0x50, 0x17, 0x18, 0x68, 0x21, 0xE3, 0x36, 0xA5, 0x99, 0x55, 0x66, 0x68, 0x3D + .byte 0xB4, 0x7D, 0xC4, 0xC5, 0xAF, 0xFB, 0xFC, 0x80, 0x10, 0xBC, 0xE0, 0x2F, 0xFB, 0xE7, 0x7C, 0x2C + .byte 0xD0, 0xC5, 0x7D, 0xE7, 0xDD, 0xE5, 0x09, 0xC0, 0x1C, 0xAE, 0x5A, 0x72, 0x15, 0xC2, 0xAF, 0xC9 + .byte 0x3F, 0x73, 0x8E, 0xEF, 0x6F, 0x8B, 0x6F, 0x80, 0x47, 0x50, 0xAF, 0x43, 0x37, 0x2C, 0x6F, 0x07 + .byte 0xF2, 0xED, 0xEF, 0xD0, 0xD2, 0xF9, 0x91, 0xEF, 0xA7, 0xEB, 0x61, 0xBD, 0xAD, 0x10, 0x87, 0xED + .byte 0x84, 0x16, 0xDC, 0xF3, 0xA1, 0x4C, 0x73, 0xE8, 0x9C, 0x23, 0x2B, 0xD4, 0x4F, 0x9B, 0xDC, 0x42 + .byte 0x88, 0xCB, 0x12, 0x5B, 0xC5, 0xA3, 0x4B, 0x6D, 0x8E, 0xAC, 0x2A, 0x3C, 0xBD, 0xB1, 0x29, 0x41 + .byte 0xC7, 0x06, 0x34, 0x68, 0x52, 0xA8, 0x51, 0xEE, 0xCB, 0x7D, 0xC2, 0x1B, 0x19, 0x9E, 0x5D, 0xA2 + .byte 0x6A, 0x70, 0xFE, 0x2F, 0x13, 0x49, 0x9C, 0xA2, 0xF5, 0xC7, 0xDF, 0xB2, 0x79, 0x08, 0xF3, 0x41 + .byte 0x0E, 0x28, 0xA9, 0x61, 0xD0, 0xFB, 0x4F, 0x9B, 0x79, 0x12, 0xB7, 0x92, 0xB1, 0x15, 0x35, 0x1C + .byte 0x85, 0x33, 0x4C, 0x99, 0x7C, 0xE9, 0x3B, 0x72, 0xB1, 0x1A, 0x24, 0x2A, 0x23, 0x18, 0x6B, 0x32 + .byte 0x41, 0x15, 0x93, 0x11, 0x10, 0xE3, 0xAD, 0x8A, 0xF6, 0x64, 0x1C, 0xA8, 0x7A, 0x51, 0xC4, 0xFF + .byte 0x85, 0x11, 0x98, 0x02, 0xFB, 0xD4, 0x74, 0xAC, 0xEF, 0x99, 0xD6, 0x12, 0xB2, 0x41, 0x45, 0xF3 + .byte 0x56, 0xD8, 0x04, 0x67, 0xBC, 0xB2, 0xF1, 0xB3, 0x17, 0x0E, 0x5B, 0x91, 0x60, 0x20, 0x90, 0xE5 + .byte 0x31, 0x29, 0xE7, 0x2C, 0xFD, 0x5C, 0xD9, 0xEC, 0xF5, 0xAF, 0xFF, 0xA7, 0xF0, 0x44, 0x9A, 0x47 + .byte 0x1D, 0x9F, 0xAF, 0xD9, 0x52, 0xA0, 0x8C, 0x69, 0xAF, 0xE8, 0xFB, 0x0F, 0x08, 0x8C, 0xF5, 0x3A + .byte 0xB5, 0xDD, 0x67, 0xB3, 0x39, 0x40, 0x9F, 0x2E, 0xEF, 0x9E, 0xD6, 0xE0, 0xE3, 0x71, 0x28, 0x00 + .byte 0x11, 0xD7, 0xDA, 0x63, 0x78, 0x67, 0xCD, 0x27, 0x4F, 0xC9, 0x36, 0x58, 0x55, 0x2C, 0x92, 0x0B + .byte 0x09, 0xF9, 0xBE, 0x42, 0x39, 0x5E, 0x71, 0x29, 0xFD, 0x48, 0x09, 0xE0, 0xB9, 0x31, 0xE0, 0xCA + .byte 0x09, 0xBB, 0x2E, 0x81, 0x22, 0xFC, 0xA8, 0x72, 0xC5, 0xDF, 0xCA, 0x1A, 0x0B, 0x5C, 0x25, 0x14 + .byte 0x56, 0xE4, 0x57, 0x90, 0x42, 0xC9, 0xB9, 0x3F, 0x11, 0xC3, 0x1F, 0xCA, 0xF5, 0x00, 0x95, 0xFE + .byte 0xBC, 0xC4, 0x7F, 0xDF, 0xC0, 0x27, 0x51, 0x85, 0x07, 0x1B, 0xA0, 0x12, 0x78, 0xC6, 0x27, 0xCE + .byte 0xAA, 0x7E, 0x5E, 0xEC, 0x48, 0x18, 0x2C, 0x59, 0xDB, 0x4C, 0x24, 0xD0, 0x4D, 0xBA, 0xCF, 0x09 + .byte 0x7E, 0x4E, 0xE8, 0x3E, 0x76, 0x3A, 0xC4, 0x7E, 0x55, 0x64, 0x90, 0xCE, 0x2A, 0xB8, 0x9C, 0xD4 + .byte 0x37, 0xFB, 0xC1, 0x7F, 0x14, 0xEE, 0xD8, 0xEF, 0x3A, 0xFD, 0xC0, 0x88, 0xB7, 0x90, 0x92, 0x36 + .byte 0xDE, 0x7A, 0x75, 0x55, 0xB5, 0x39, 0xD3, 0x0A, 0x9E, 0x64, 0xD9, 0xC8, 0x1C, 0x76, 0x9D, 0x53 + .byte 0x71, 0x5F, 0xD2, 0x86, 0x4D, 0xAB, 0x76, 0x88, 0xA9, 0x36, 0x11, 0x61, 0xC6, 0xA3, 0x97, 0xA5 + .byte 0x1E, 0x0D, 0xFB, 0xD3, 0x46, 0xCF, 0xDE, 0xE5, 0x34, 0xB7, 0xAD, 0x50, 0x2D, 0x4B, 0xA4, 0x9F + .byte 0xAA, 0x77, 0x25, 0xF8, 0x22, 0x9B, 0x80, 0xCC, 0xD2, 0x91, 0x2D, 0x99, 0x35, 0xC5, 0x3F, 0x53 + .byte 0xD2, 0x3B, 0x26, 0x19, 0x0A, 0x04, 0xFE, 0x3E, 0xBB, 0xAC, 0x8F, 0xE9, 0xF7, 0x33, 0x88, 0xA1 + .byte 0xAA, 0xAE, 0x9A, 0xCD, 0x49, 0x1A, 0x99, 0x1C, 0xAC, 0xC6, 0xB5, 0xE1, 0x8B, 0xF5, 0x34, 0x5E + .byte 0x30, 0x5B, 0x77, 0x3B, 0x5F, 0x76, 0x79, 0x1B, 0x22, 0x09, 0x04, 0x19, 0x3C, 0x8D, 0xBB, 0xE7 + .byte 0x3B, 0x55, 0xB5, 0x85, 0x70, 0x4E, 0xA1, 0x1D, 0x15, 0x57, 0xFE, 0xA1, 0x4C, 0x33, 0xFF, 0x7C + .byte 0x8F, 0x77, 0xB7, 0xEF, 0xED, 0x31, 0x0A, 0x0F, 0x3A, 0x0F, 0x29, 0x77, 0x9D, 0xE4, 0x5F, 0xD8 + .byte 0x39, 0x14, 0x5E, 0xAA, 0x62, 0xFF, 0xC7, 0x77, 0x56, 0xC5, 0x18, 0xA2, 0xF9, 0x18, 0x1F, 0x88 + .byte 0x8F, 0xD6, 0x78, 0x7C, 0x07, 0x82, 0x8C, 0x42, 0x92, 0xB5, 0xBA, 0x30, 0x99, 0x19, 0x09, 0xD3 + .byte 0x2D, 0x67, 0x7D, 0x90, 0x66, 0x44, 0x08, 0xBD, 0x0A, 0x21, 0x60, 0x04, 0x39, 0x7F, 0x8D, 0xC8 + .byte 0x56, 0x05, 0x45, 0x5D, 0x88, 0xD1, 0xA0, 0x1B, 0x86, 0x5A, 0x4B, 0x1F, 0x74, 0x54, 0xF3, 0xA1 + .byte 0xBB, 0x70, 0x31, 0x22, 0xB4, 0x3A, 0xE0, 0xBF, 0x5B, 0x40, 0xC3, 0x94, 0xC0, 0x50, 0x5D, 0x16 + .byte 0x55, 0xA2, 0x74, 0xDD, 0x74, 0x15, 0xF8, 0xFA, 0x6F, 0x44, 0x1A, 0xE3, 0x98, 0x0D, 0x85, 0x54 + .byte 0x7D, 0xB7, 0x77, 0x32, 0xF1, 0x58, 0xF1, 0x4C, 0x98, 0xB4, 0xE1, 0x59, 0x05, 0x3F, 0x70, 0x5A + .byte 0xE1, 0xE4, 0x38, 0x55, 0xF9, 0x31, 0x50, 0x69, 0x75, 0x6A, 0x4D, 0x0E, 0x77, 0xD2, 0x63, 0xF4 + .byte 0x89, 0xDA, 0x26, 0x7B, 0x32, 0x18, 0xC8, 0xCB, 0xCC, 0xA9, 0x25, 0xD1, 0xE8, 0x95, 0x2C, 0xCA + .byte 0x79, 0x65, 0x20, 0x73, 0x96, 0x70, 0xDC, 0x0C, 0xDA, 0x2A, 0x1B, 0x51, 0xFC, 0x7E, 0x46, 0x86 + .byte 0x59, 0x6D, 0x01, 0x8C, 0x85, 0xC9, 0x57, 0x52, 0x73, 0x7D, 0x24, 0x5C, 0x12, 0x51, 0x26, 0x8C + .byte 0xB6, 0x46, 0xFF, 0x4D, 0xB7, 0xDC, 0x5A, 0x91, 0x06, 0x75, 0xE3, 0x03, 0xF4, 0x2A, 0x89, 0x4D + .byte 0x97, 0x8B, 0xD9, 0x1D, 0x54, 0x31, 0x70, 0xC8, 0xAE, 0x95, 0x24, 0xC0, 0xE6, 0x4B, 0x4C, 0x9D + .byte 0x91, 0x4C, 0xEB, 0x49, 0x29, 0x45, 0xDA, 0x2F, 0xBB, 0xBE, 0x33, 0xAF, 0xE8, 0xBC, 0xFC, 0x80 + .byte 0x48, 0xD6, 0x9E, 0x9D, 0x07, 0x0F, 0x65, 0xB5, 0xA4, 0x89, 0x75, 0x8B, 0xD4, 0xC2, 0x28, 0x66 + .byte 0x0E, 0x13, 0xAF, 0x38, 0x59, 0x8A, 0x67, 0x14, 0x49, 0x9B, 0xC4, 0x32, 0x57, 0xC0, 0xB3, 0x9F + .byte 0x97, 0x51, 0x3C, 0x9E, 0x60, 0xA2, 0x53, 0x05, 0x2C, 0xC9, 0x90, 0x01, 0x8C, 0xB8, 0x68, 0x9B + .byte 0xCC, 0x18, 0xD3, 0x26, 0xA3, 0x3A, 0x3A, 0xEC, 0xD5, 0xFF, 0x1E, 0x2D, 0xC0, 0xD1, 0xCD, 0x57 + .byte 0x23, 0x0A, 0xF5, 0x84, 0xAD, 0x49, 0x89, 0xD9, 0x12, 0x19, 0xDA, 0x9E, 0xD2, 0x42, 0x39, 0x9E + .byte 0x5B, 0x0C, 0xC4, 0xFE, 0x47, 0xFF, 0xEA, 0x1D, 0xFE, 0x09, 0x4B, 0xBE, 0xDB, 0x19, 0x15, 0xFE + .byte 0x24, 0x0A, 0x83, 0xD1, 0x54, 0x0C, 0xAA, 0x66, 0x26, 0x85, 0x05, 0xF8, 0xC8, 0x3F, 0x96, 0x23 + .byte 0x4C, 0x5B, 0x21, 0x93, 0x5A, 0x0C, 0xB1, 0x58, 0x15, 0xFD, 0x17, 0xF1, 0x16, 0x2C, 0xF0, 0x3A + .byte 0x37, 0x73, 0x0C, 0x8B, 0x7F, 0xB6, 0xF2, 0xA6, 0x3C, 0xF8, 0x9E, 0x05, 0x37, 0x34, 0x29, 0x83 + .byte 0x8F, 0x4A, 0x17, 0xEA, 0x57, 0xC8, 0x42, 0x6D, 0xC5, 0x5A, 0x5E, 0xDC, 0x87, 0x4E, 0x17, 0xBF + .byte 0xC1, 0x23, 0x4B, 0x41, 0xDA, 0x3D, 0xE7, 0x16, 0x35, 0x85, 0x1B, 0x6D, 0xBA, 0x45, 0xF0, 0x4A + .byte 0x8F, 0x07, 0x34, 0xE7, 0xD0, 0x77, 0x54, 0x96, 0xD1, 0xB2, 0x72, 0x58, 0x01, 0x89, 0x17, 0xC2 + .byte 0xAC, 0x62, 0x04, 0x86, 0xA0, 0xEB, 0x9D, 0xD5, 0x71, 0xB9, 0x42, 0x2C, 0xFE, 0x33, 0x76, 0x8E + .byte 0x3A, 0xAA, 0x75, 0x0B, 0x21, 0xCA, 0xA1, 0xF2, 0x7C, 0x13, 0x4A, 0x7D, 0x9D, 0x62, 0x40, 0x4A + .byte 0xC4, 0x44, 0xD1, 0x64, 0x30, 0x6E, 0x3A, 0xA2, 0x28, 0x7D, 0xCE, 0x26, 0xB0, 0x44, 0xB4, 0xEB + .byte 0xEE, 0x2A, 0xF6, 0x10, 0xF4, 0x97, 0x02, 0x71, 0xAB, 0x4D, 0xEF, 0x49, 0xAF, 0x30, 0x93, 0x74 + .byte 0x75, 0x65, 0xD8, 0xA5, 0xD3, 0x13, 0x48, 0xFB, 0x90, 0x16, 0x22, 0x41, 0x5A, 0xD7, 0x2C, 0x49 + .byte 0x01, 0x23, 0x59, 0xF6, 0xBB, 0x5C, 0x68, 0x67, 0xA9, 0x57, 0xB0, 0x59, 0x88, 0x44, 0xCD, 0xFD + .byte 0xA9, 0xA6, 0xA2, 0x7D, 0xB9, 0xEB, 0x79, 0x49, 0x01, 0x9B, 0x8B, 0x5C, 0x72, 0xB7, 0xA6, 0x74 + .byte 0xDA, 0x00, 0x6A, 0x95, 0x5C, 0xD2, 0xFC, 0x06, 0x2A, 0xAD, 0x5F, 0xB2, 0xF2, 0x2D, 0xAF, 0x9B + .byte 0xD3, 0x52, 0x19, 0x8D, 0x3E, 0x92, 0xD7, 0x3F, 0x2D, 0x62, 0x9C, 0x9F, 0x19, 0x42, 0x13, 0xF4 + .byte 0x42, 0x7E, 0x8A, 0x9F, 0x51, 0x87, 0xA6, 0x7B, 0x34, 0x06, 0x2E, 0x27, 0x33, 0xDE, 0xC2, 0x07 + .byte 0x31, 0xDB, 0x94, 0x6F, 0x6D, 0x6B, 0xAF, 0x9B, 0xCD, 0x4B, 0x3B, 0xE7, 0x8D, 0x4E, 0xDB, 0xD0 + .byte 0xCD, 0x65, 0x70, 0x1E, 0xED, 0x16, 0x9A, 0x22, 0x1C, 0xC8, 0x49, 0x50, 0xA7, 0x0B, 0x57, 0xD8 + .byte 0xE7, 0xEB, 0x48, 0x55, 0x57, 0xF7, 0xF0, 0x24, 0x42, 0x2B, 0x0B, 0xD0, 0x7A, 0xE7, 0xA0, 0x47 + .byte 0x4D, 0x11, 0x66, 0x3A, 0x27, 0x00, 0x5C, 0x44, 0xC8, 0xA5, 0x94, 0x6F, 0xB1, 0xEB, 0x48, 0x99 + .byte 0xD7, 0x90, 0xEE, 0x2E, 0x87, 0xDF, 0x53, 0xCA, 0x0B, 0x5F, 0x9A, 0x86, 0x46, 0x3B, 0xCD, 0x93 + .byte 0x4C, 0x34, 0xCE, 0x74, 0x34, 0x2A, 0xB8, 0xFC, 0xD0, 0x4C, 0x6C, 0x81, 0x38, 0xB5, 0x1A, 0x0F + .byte 0x45, 0x09, 0x3E, 0xCD, 0xE8, 0x92, 0x97, 0xF4, 0xF1, 0x32, 0x7A, 0x38, 0x6E, 0x48, 0xCC, 0xBB + .byte 0x7C, 0x9A, 0x2F, 0xB0, 0xC4, 0xE7, 0xAD, 0x94, 0x34, 0x1A, 0x16, 0x6C, 0xCF, 0x30, 0x7C, 0x15 + .byte 0x39, 0xBB, 0xE2, 0x22, 0x4D, 0x7A, 0x16, 0x3F, 0xAD, 0x90, 0x77, 0x1B, 0xD8, 0x43, 0xD6, 0x54 + .byte 0xDD, 0x06, 0x05, 0xA2, 0xEE, 0xB2, 0x37, 0x22, 0xCC, 0x4D, 0x8F, 0x9C, 0x7E, 0x0C, 0xB1, 0xB8 + .byte 0xC8, 0x94, 0xDA, 0x15, 0x0E, 0xF1, 0x55, 0xBC, 0x81, 0xCC, 0xD7, 0x5A, 0x10, 0xAE, 0xAF, 0xEE + .byte 0xB4, 0xB4, 0x91, 0xA3, 0x67, 0xC9, 0xC5, 0x34, 0x17, 0x55, 0xD0, 0x95, 0x62, 0x81, 0x4E, 0x2A + .byte 0x15, 0x28, 0x40, 0x24, 0x19, 0x95, 0xE0, 0x9B, 0x62, 0xB8, 0xF6, 0x73, 0x66, 0xA5, 0x61, 0x1B + .byte 0x5A, 0xF3, 0xBE, 0xC2, 0xBC, 0x84, 0xF7, 0xD3, 0xDA, 0xC7, 0x68, 0x3C, 0x49, 0xB6, 0x67, 0x5E + .byte 0xDF, 0xA7, 0x83, 0xF9, 0x3D, 0x64, 0x95, 0x9F, 0x1C, 0x8B, 0x12, 0x83, 0x31, 0x74, 0x9F, 0x8C + .byte 0x67, 0x5E, 0x4F, 0x23, 0xE3, 0x46, 0xF7, 0xBD, 0x0D, 0x5F, 0xFA, 0x57, 0x16, 0x62, 0xB6, 0xF6 + .byte 0x09, 0x39, 0xF0, 0x47, 0x9D, 0x85, 0xE7, 0xBA, 0x11, 0xF9, 0x3D, 0x43, 0x6E, 0xDC, 0xCF, 0xD6 + .byte 0x3A, 0x1F, 0xFA, 0x1D, 0x65, 0xF1, 0xDB, 0x73, 0x51, 0xD6, 0xCA, 0x68, 0x38, 0x80, 0x5E, 0x41 + .byte 0xBA, 0x4F, 0x89, 0x57, 0xD4, 0x70, 0x11, 0xE5, 0x69, 0x4F, 0x28, 0xD8, 0x2C, 0xF8, 0xAF, 0x66 + .byte 0x18, 0xA9, 0x84, 0x7D, 0x9B, 0x60, 0xF1, 0xEC, 0x36, 0xBB, 0x55, 0x6E, 0x3C, 0xB4, 0xB0, 0xF6 + .byte 0x03, 0x39, 0x4E, 0xD7, 0xA9, 0x60, 0xBD, 0x13, 0xAF, 0xE6, 0xEB, 0xDB, 0xDF, 0x9B, 0x42, 0xF7 + .byte 0x44, 0xC7, 0x75, 0xDF, 0x27, 0x66, 0xCC, 0x5D, 0x22, 0x22, 0xCC, 0x5E, 0xD6, 0x7C, 0x55, 0xD9 + .byte 0xB5, 0xA4, 0xB1, 0x5F, 0x04, 0x6F, 0x72, 0xB4, 0x56, 0x5E, 0x90, 0x35, 0xF9, 0xD3, 0x2D, 0x3E + .byte 0x9B, 0xA3, 0x1D, 0xC2, 0x09, 0xEA, 0x20, 0x2C, 0x0C, 0xED, 0x8B, 0xE3, 0x69, 0xE0, 0xBD, 0x1F + .byte 0x85, 0x6E, 0x7E, 0x89, 0xDE, 0xF0, 0x3E, 0x34, 0x4E, 0xCF, 0x6A, 0x48, 0xA2, 0x97, 0x86, 0x3D + .byte 0x3A, 0xA4, 0x00, 0x44, 0x8F, 0x21, 0x71, 0x9B, 0x0E, 0xFC, 0x7F, 0x77, 0xDD, 0x3C, 0x97, 0x62 + .byte 0xAB, 0x15, 0xEC, 0x89, 0x06, 0x2A, 0xBD, 0x55, 0xF9, 0x27, 0x9D, 0x9C, 0xBF, 0x23, 0xDA, 0xFA + .byte 0xC7, 0xDA, 0x3F, 0x56, 0xFB, 0xB0, 0xF2, 0x09, 0xAC, 0x72, 0x81, 0x89, 0xAE, 0x18, 0xEC, 0x59 + .byte 0x2D, 0xD8, 0xE3, 0x33, 0x03, 0xA0, 0x89, 0xFD, 0xC8, 0x26, 0x99, 0x88, 0x4A, 0x74, 0x82, 0x12 + .byte 0x4E, 0xC2, 0x68, 0x4A, 0x72, 0x5B, 0x53, 0x1E, 0xCE, 0xD4, 0xA8, 0x7C, 0xED, 0x94, 0xD6, 0x1A + .byte 0x6D, 0xB9, 0x4E, 0x71, 0x5A, 0xD7, 0x6E, 0x22, 0xFE, 0x08, 0xAB, 0x48, 0x7C, 0x2E, 0x5A, 0xCA + .byte 0xF0, 0xC3, 0x14, 0x62, 0x1F, 0x68, 0x81, 0xED, 0x3D, 0x29, 0x69, 0x2A, 0xBE, 0x40, 0x45, 0x2C + .byte 0xF9, 0x94, 0x9D, 0x53, 0x6C, 0x0B, 0x76, 0x6A, 0x13, 0x21, 0xB3, 0x90, 0x50, 0x0D, 0x5A, 0x40 + .byte 0xD1, 0x6F, 0xA2, 0xF0, 0xD8, 0x23, 0xDD, 0x15, 0x4D, 0x47, 0x40, 0x0C, 0x87, 0x85, 0x38, 0x81 + .byte 0x1A, 0xD5, 0xD4, 0x86, 0xE1, 0x4B, 0xF1, 0xF4, 0x6D, 0xA4, 0x85, 0xBD, 0xB2, 0xE0, 0xFD, 0x83 + .byte 0x4F, 0xA0, 0x73, 0x28, 0xC3, 0x51, 0x3D, 0x11, 0x98, 0x7E, 0x1D, 0x20, 0x04, 0x55, 0xA1, 0x1E + .byte 0x2B, 0x76, 0xA5, 0x0C, 0xC1, 0x96, 0x01, 0x2E, 0x3B, 0x86, 0xEC, 0xED, 0x66, 0xE9, 0x70, 0xB6 + .byte 0x8A, 0xE4, 0xDE, 0x4E, 0x35, 0x1C, 0x5F, 0xCE, 0x9A, 0x7C, 0xEE, 0x9E, 0xD2, 0x8F, 0xBC, 0xFD + .byte 0x05, 0x62, 0x09, 0xC7, 0xF8, 0x0A, 0xF6, 0x34, 0x90, 0xE2, 0x21, 0xF7, 0xCC, 0x92, 0xAD, 0x56 + .byte 0x77, 0x8B, 0xA4, 0xAC, 0xA7, 0x03, 0x7A, 0x42, 0x80, 0x69, 0xE0, 0x52, 0xF8, 0x9D, 0x50, 0xFE + .byte 0xFF, 0x59, 0xC5, 0xF8, 0x64, 0xBB, 0x2C, 0xF5, 0x9E, 0x4E, 0xEC, 0x6A, 0xE0, 0x99, 0xC1, 0x57 + .byte 0x25, 0x65, 0x04, 0xCD, 0x69, 0x7F, 0x0F, 0xEA, 0xE8, 0xEF, 0x3D, 0xE1, 0x8D, 0x8D, 0xE0, 0x8C + .byte 0xE6, 0xA5, 0x85, 0x4B, 0x61, 0xB1, 0x40, 0xFF, 0xFF, 0x2C, 0x6A, 0xE0, 0xC6, 0x2B, 0x38, 0xEB + .byte 0x91, 0x3C, 0xB8, 0xFA, 0xBC, 0xC7, 0xE5, 0xA4, 0xB7, 0x22, 0x86, 0x44, 0xAF, 0x66, 0xD1, 0x96 + .byte 0x0C, 0x56, 0xE1, 0x6E, 0x08, 0x21, 0x6D, 0x08, 0x4E, 0xD8, 0xE8, 0x14, 0x03, 0x20, 0x00, 0x94 + .byte 0x5D, 0xB8, 0x8F, 0x19, 0x80, 0x75, 0xBE, 0x38, 0x97, 0x45, 0x7D, 0x46, 0xAC, 0x4F, 0xDD, 0xB8 + .byte 0xA5, 0xBE, 0x26, 0xAE, 0xE0, 0x94, 0xB6, 0x2F, 0x6C, 0x9F, 0x43, 0x70, 0xC0, 0x44, 0x05, 0x1D + .byte 0xFD, 0x95, 0x37, 0x7E, 0x0A, 0xF6, 0xB6, 0xA1, 0x3B, 0x33, 0xE8, 0xE7, 0x82, 0xC5, 0xA0, 0x28 + .byte 0x83, 0xC7, 0xD7, 0x64, 0x5C, 0x8D, 0x93, 0xC9, 0x2C, 0xD7, 0x3A, 0xED, 0x1B, 0x3F, 0x0A, 0x19 + .byte 0xD4, 0x42, 0x97, 0xDF, 0x38, 0x4D, 0x80, 0x74, 0x81, 0x69, 0x5C, 0x04, 0x2E, 0xFD, 0x2D, 0xB2 + .byte 0xC4, 0x04, 0x16, 0x21, 0x92, 0xAA, 0xEB, 0xBF, 0x81, 0x25, 0xAC, 0x9D, 0x64, 0xB6, 0xB6, 0x39 + .byte 0xF9, 0x4E, 0x19, 0x31, 0x9B, 0x99, 0xA6, 0x1D, 0x03, 0x02, 0x21, 0x31, 0x00, 0x4E, 0xE4, 0xC5 + .byte 0x52, 0xFA, 0xE6, 0xE4, 0xA5, 0xD1, 0xA3, 0x26, 0xF6, 0x4F, 0xC4, 0x5B, 0x06, 0x7B, 0x95, 0x00 + .byte 0xC9, 0xAE, 0x31, 0x65, 0x48, 0xD8, 0x82, 0x4B, 0xDB, 0xA3, 0x7D, 0xDB, 0xF2, 0x61, 0xA0, 0x45 + .byte 0x5C, 0x86, 0x2A, 0x01, 0x58, 0xCD, 0x28, 0x4F, 0x1D, 0xEC, 0xAA, 0x24, 0x68, 0x40, 0x24, 0x31 + .byte 0xEE, 0x56, 0x96, 0x36, 0x2E, 0x19, 0x82, 0x0A, 0xBD, 0xFF, 0xE5, 0xAF, 0x60, 0x85, 0xF4, 0xBC + .byte 0x0C, 0x1E, 0xBD, 0x64, 0xEC, 0xE6, 0xB4, 0x0A, 0xD2, 0x5E, 0x2F, 0x3B, 0x9E, 0x53, 0x6C, 0x8D + .byte 0xAA, 0x03, 0xC4, 0xD9, 0x1C, 0x46, 0xE3, 0xDA, 0x45, 0xC9, 0x89, 0xA6, 0x4E, 0x7E, 0x62, 0x5B + .byte 0x9D, 0x20, 0xC0, 0x8A, 0x06, 0x74, 0x94, 0xD9, 0xD3, 0xC4, 0x14, 0x72, 0x18, 0x81, 0xFF, 0xC2 + .byte 0x85, 0xC3, 0x9C, 0xA2, 0x0A, 0x80, 0x7C, 0x4F, 0x49, 0x06, 0xF6, 0x98, 0x84, 0x58, 0xF3, 0x22 + .byte 0x79, 0xB4, 0xAC, 0x80, 0x28, 0x41, 0x5A, 0xFC, 0x05, 0x6F, 0x6E, 0x1D, 0xF0, 0x6E, 0xE0, 0x76 + .byte 0x32, 0x7C, 0x18, 0x3C, 0xFC, 0x95, 0x8C, 0x46, 0x9B, 0x82, 0xDE, 0x20, 0xDB, 0xD2, 0x42, 0x55 + .byte 0x86, 0xEE, 0xD6, 0xAE, 0x2F, 0x30, 0xAB, 0x34, 0x9F, 0x19, 0x52, 0x90, 0x88, 0x32, 0x07, 0xBA + .byte 0xAF, 0x1F, 0xF7, 0xAC, 0xB5, 0x84, 0xF2, 0x50, 0x06, 0xD0, 0x70, 0xE2, 0xA2, 0xB2, 0x38, 0x28 + .byte 0xA1, 0x0E, 0xD7, 0xD0, 0x3F, 0x82, 0x05, 0xDE, 0x9C, 0x58, 0x6F, 0x24, 0x8B, 0x76, 0xDE, 0x3A + .byte 0x96, 0xD5, 0xE6, 0x4B, 0x59, 0xD8, 0x9B, 0x60, 0xA8, 0x0C, 0x43, 0x4B, 0xBE, 0x7B, 0x73, 0x60 + .byte 0x8A, 0x4B, 0x31, 0xC9, 0xCD, 0x36, 0xA8, 0x69, 0x8F, 0x17, 0x8D, 0x1A, 0x8E, 0x6C, 0x54, 0x24 + .byte 0x42, 0x3A, 0x6F, 0x9C, 0x13, 0x0B, 0xFD, 0xBC, 0x17, 0x40, 0x07, 0xD6, 0xBC, 0x7B, 0x36, 0x46 + .byte 0xC7, 0x67, 0x10, 0x94, 0x9E, 0xB8, 0xFE, 0x2D, 0xCF, 0x8C, 0x47, 0x5D, 0xF8, 0x9B, 0x81, 0x3B + .byte 0xD6, 0xF1, 0xD7, 0xEA, 0xFC, 0xD4, 0xA6, 0x14, 0x15, 0xAE, 0xEA, 0xD2, 0x2A, 0x21, 0x18, 0xF1 + .byte 0x89, 0x28, 0x86, 0x27, 0xE0, 0x84, 0x55, 0xB0, 0x11, 0x9C, 0x0D, 0x0A, 0x38, 0x8F, 0x45, 0x0F + .byte 0x81, 0x1D, 0xF9, 0x7D, 0xF2, 0xA0, 0x91, 0x07, 0x4F, 0x7C, 0xD9, 0x79, 0x9E, 0xF2, 0x6A, 0x27 + .byte 0x1B, 0xF0, 0x4F, 0xFB, 0x75, 0xA4, 0xAC, 0x86, 0x41, 0xB9, 0x91, 0x7A, 0x49, 0xD6, 0x89, 0xCA + .byte 0xF3, 0x83, 0x48, 0xE5, 0x24, 0xDA, 0xED, 0x73, 0x56, 0xC7, 0xEC, 0xF5, 0xB9, 0x57, 0x1C, 0xD4 + .byte 0x48, 0x6B, 0xD0, 0xBE, 0x10, 0x7C, 0x45, 0x51, 0x36, 0xD6, 0xCB, 0x80, 0xAD, 0x55, 0x4A, 0xA0 + .byte 0xD9, 0x93, 0x86, 0xFD, 0x6D, 0x74, 0x71, 0xC4, 0x3B, 0x5D, 0xB9, 0xF4, 0xB5, 0xD5, 0xC9, 0xFE + .byte 0x41, 0x99, 0xBC, 0x51, 0x16, 0x01, 0xA3, 0x4D, 0xD8, 0x6E, 0xCD, 0x85, 0xC3, 0x17, 0x26, 0x9D + .byte 0xAB, 0xAC, 0x9A, 0x18, 0x21, 0x0B, 0xDC, 0x5C, 0x69, 0x96, 0x51, 0x1E, 0x6C, 0x1B, 0x1C, 0xAD + .byte 0xB5, 0xD9, 0xFF, 0xCB, 0xDB, 0xA2, 0x18, 0xB3, 0x11, 0xE5, 0x38, 0xD4, 0xFD, 0x5E, 0x71, 0xA8 + .byte 0x0B, 0x0C, 0xC1, 0x2C, 0x18, 0x9E, 0x89, 0x81, 0x34, 0xDA, 0xA0, 0xA0, 0xF5, 0xBD, 0x4E, 0xAB + .byte 0x96, 0x4D, 0x76, 0x71, 0xF0, 0x8F, 0x24, 0x01, 0x74, 0x5D, 0xD5, 0x72, 0xBB, 0x47, 0x1B, 0xC7 + .byte 0x54, 0xDC, 0xF3, 0x6C, 0x7A, 0x7C, 0xED, 0xAE, 0x57, 0x8E, 0x4F, 0x4D, 0x4B, 0x9D, 0xF8, 0xE2 + .byte 0xEA, 0x6F, 0x53, 0xDA, 0xFE, 0x78, 0xDB, 0x73, 0xD6, 0xB1, 0xE5, 0x92, 0xF9, 0x00, 0x59, 0x4E + .byte 0xDD, 0x4C, 0xBA, 0x57, 0xC9, 0xA8, 0x06, 0x20, 0x36, 0x55, 0x6E, 0x81, 0xF2, 0x67, 0x64, 0xDD + .byte 0xD6, 0xB8, 0xB8, 0xD4, 0x30, 0x94, 0x47, 0x07, 0x46, 0x2D, 0x99, 0x40, 0x2D, 0xF2, 0x8E, 0x0B + .byte 0x3E, 0x49, 0x62, 0x08, 0xF1, 0x69, 0x29, 0x27, 0xBE, 0x97, 0xA9, 0xB1, 0xFE, 0x0D, 0x8F, 0xD5 + .byte 0xC5, 0x48, 0xA9, 0xF6, 0xDD, 0xF1, 0xFE, 0x24, 0x1E, 0x97, 0x64, 0x4C, 0x89, 0xF3, 0x57, 0xC8 + .byte 0x3C, 0xBA, 0xD1, 0x2D, 0x23, 0xFA, 0x55, 0xE2, 0x92, 0xFF, 0x94, 0x91, 0x0D, 0x24, 0x66, 0xD3 + .byte 0x6C, 0x10, 0xCA, 0x4A, 0x01, 0xC8, 0x6E, 0x1F, 0x60, 0xD2, 0x6B, 0xE9, 0xC5, 0xC2, 0xB2, 0x01 + .byte 0x7C, 0x83, 0x2F, 0xA0, 0x7D, 0x85, 0x82, 0x10, 0x85, 0x16, 0xA1, 0x92, 0x3A, 0x08, 0x66, 0xA7 + .byte 0x18, 0x30, 0xF1, 0x19, 0xF9, 0x5F, 0x38, 0x59, 0x32, 0xA3, 0x43, 0xF7, 0x66, 0xF5, 0xF9, 0xE2 + .byte 0x78, 0x29, 0x83, 0xF6, 0xAF, 0x05, 0x06, 0x34, 0x1C, 0xA8, 0xC6, 0x57, 0xB0, 0x2D, 0xFF, 0xC8 + .byte 0x5D, 0xF0, 0xE1, 0x57, 0x50, 0x19, 0xB0, 0x82, 0xBD, 0xF3, 0x7A, 0x23, 0xE9, 0x74, 0x06, 0x62 + .byte 0x9D, 0x89, 0x59, 0x4D, 0x8F, 0x60, 0x81, 0xAC, 0x08, 0x48, 0x03, 0xB9, 0x75, 0x02, 0x81, 0xD2 + .byte 0xF3, 0x63, 0x2A, 0x44, 0x7D, 0xDB, 0xC6, 0x3B, 0xCF, 0x41, 0x5E, 0xB8, 0xB5, 0x65, 0x1B, 0x53 + .byte 0xEF, 0x74, 0xA0, 0x7F, 0xD4, 0x22, 0x2B, 0xDD, 0x6A, 0x2F, 0x96, 0xDF, 0x32, 0x18, 0xB2, 0x25 + .byte 0x7B, 0xDC, 0x6A, 0xF9, 0xB7, 0x31, 0x34, 0x86, 0x72, 0x93, 0x3F, 0x28, 0xF9, 0x5A, 0x7C, 0xE8 + .byte 0xCE, 0x1D, 0x67, 0xA3, 0x3F, 0x93, 0x80, 0xA9, 0xC2, 0x17, 0x88, 0xF4, 0x2F, 0x3A, 0x1A, 0xAB + .byte 0x17, 0x84, 0xA4, 0xCF, 0xB5, 0xD9, 0x56, 0x28, 0x6C, 0x95, 0x50, 0x65, 0xF0, 0xCD, 0x4E, 0xBF + .byte 0xEA, 0xB6, 0x62, 0x29, 0x49, 0xE3, 0xD3, 0x0B, 0xFA, 0x5C, 0xFF, 0x2A, 0x97, 0x1A, 0xD5, 0xAE + .byte 0x9E, 0x7A, 0x7D, 0x53, 0x54, 0xD4, 0x7B, 0xC0, 0x69, 0xCC, 0x26, 0x59, 0x99, 0x74, 0x18, 0x83 + .byte 0x2A, 0x7B, 0xAD, 0x74, 0x5E, 0x81, 0x7F, 0x59, 0xDD, 0x7F, 0x83, 0x74, 0x99, 0x59, 0x23, 0x38 + .byte 0xD4, 0xA1, 0x8B, 0x28, 0x75, 0x07, 0xE9, 0xDF, 0xD4, 0x10, 0x38, 0x6D, 0x84, 0x51, 0xF1, 0xAF + .byte 0xCC, 0x9E, 0x23, 0x2B, 0x20, 0xA3, 0x84, 0xFD, 0x23, 0x08, 0x72, 0xBD, 0x61, 0x95, 0xF5, 0x36 + .byte 0x37, 0x81, 0x5F, 0xAC, 0x89, 0x48, 0x8B, 0x5D, 0x58, 0xC4, 0xCA, 0xDD, 0x15, 0xBB, 0x8D, 0xE2 + .byte 0x5A, 0xB1, 0x0D, 0x7A, 0x54, 0x92, 0x78, 0x78, 0x9A, 0xEA, 0x35, 0xFC, 0x80, 0x2B, 0x32, 0xB7 + .byte 0xAC, 0x91, 0x64, 0x35, 0xDA, 0xF0, 0x93, 0x32, 0xB4, 0x5D, 0x10, 0xCA, 0x19, 0x9D, 0xAD, 0x74 + .byte 0x4E, 0xBB, 0xEE, 0xA3, 0x4D, 0x67, 0x1C, 0xE8, 0x52, 0x51, 0xE4, 0xD2, 0x7D, 0x16, 0x8A, 0x2A + .byte 0xA8, 0xEF, 0x60, 0x82, 0xDF, 0xF3, 0xB5, 0x94, 0x50, 0xC5, 0x5F, 0x6A, 0x63, 0x0C, 0xDE, 0xB1 + .byte 0xC7, 0xCC, 0x55, 0x15, 0x34, 0x71, 0xFD, 0x86, 0xC3, 0xE1, 0x59, 0x40, 0xF8, 0xE4, 0x6B, 0xA1 + .byte 0xD3, 0xCB, 0x24, 0xB3, 0xBE, 0xD9, 0x48, 0x0F, 0x9F, 0xA7, 0x79, 0x02, 0xB4, 0x57, 0xB4, 0x7C + .byte 0x24, 0x09, 0x91, 0x58, 0x7B, 0x8F, 0xDF, 0x3F, 0x71, 0x38, 0x80, 0x69, 0x1C, 0xEB, 0x0B, 0xF0 + .byte 0xB6, 0x2F, 0xA3, 0x74, 0x09, 0xEB, 0x83, 0xA8, 0x92, 0xFD, 0xAB, 0x47, 0x54, 0x5F, 0xC3, 0x78 + .byte 0x69, 0x54, 0xD0, 0xE4, 0xE4, 0xAF, 0x23, 0x55, 0xE8, 0xA3, 0xBF, 0x04, 0x8E, 0xCA, 0xF5, 0x45 + .byte 0xFA, 0x98, 0xB9, 0x03, 0x84, 0x3D, 0xAB, 0x17, 0x3A, 0x56, 0x5E, 0x8F, 0xB6, 0x21, 0x07, 0x1F + .byte 0x76, 0xD8, 0x04, 0x5A, 0x88, 0x27, 0xAF, 0x70, 0xCB, 0x6F, 0x75, 0x5A, 0x39, 0x6A, 0x9F, 0x33 + .byte 0x03, 0x59, 0x37, 0x87, 0x96, 0xE3, 0x9E, 0xD1, 0x3A, 0xFC, 0x60, 0xF0, 0x1E, 0x68, 0x10, 0x94 + .byte 0x40, 0x14, 0xEF, 0xC9, 0x3B, 0x9F, 0x39, 0x07, 0x0E, 0xAE, 0x61, 0x48, 0x19, 0x00, 0x7C, 0x1C + .byte 0x59, 0xB3, 0xA3, 0xF0, 0x97, 0x42, 0xC2, 0xD1, 0x3E, 0x23, 0xC1, 0x5D, 0x8B, 0xD2, 0xF2, 0xCC + .byte 0xE6, 0xE1, 0x95, 0x22, 0x81, 0xCF, 0x29, 0x90, 0x7E, 0x8A, 0xD8, 0x97, 0x8A, 0x55, 0xB4, 0xE4 + .byte 0x09, 0x57, 0xD4, 0xA0, 0x9A, 0x97, 0x71, 0xD8, 0xBA, 0x33, 0x36, 0x46, 0x05, 0x28, 0x12, 0xEB + .byte 0x09, 0xA8, 0x0D, 0x8B, 0x77, 0x36, 0x1B, 0xF5, 0xC1, 0xF3, 0x8C, 0x4B, 0x49, 0x41, 0x30, 0x52 + .byte 0x99, 0x05, 0xF2, 0x33, 0x9C, 0x64, 0x0C, 0x56, 0x98, 0x42, 0x9C, 0x9D, 0x6A, 0xAF, 0x89, 0x74 + .byte 0x57, 0x97, 0xFF, 0xCF, 0xCE, 0x1A, 0xC4, 0x8F, 0x0E, 0x51, 0xDB, 0x57, 0x92, 0x0B, 0xA9, 0x2B + .byte 0x10, 0x9C, 0x5F, 0xAD, 0x01, 0x6B, 0x03, 0x99, 0xAD, 0xA0, 0x36, 0x17, 0x50, 0xC0, 0x8C, 0xA8 + .byte 0x57, 0x8B, 0x77, 0x26, 0xA5, 0x3C, 0xB5, 0xB3, 0x8D, 0x91, 0x0B, 0x20, 0x9C, 0xB5, 0x4C, 0xAD + .byte 0x51, 0xAB, 0x5B, 0x52, 0x17, 0x5E, 0xEC, 0xC4, 0xFF, 0x23, 0xDC, 0x50, 0xE3, 0x68, 0xF8, 0x3B + .byte 0xF3, 0x70, 0x61, 0x99, 0xAC, 0x16, 0x4C, 0x39, 0xA8, 0x58, 0x5A, 0x45, 0x0D, 0xA6, 0xF2, 0x5E + .byte 0x52, 0x4D, 0xB1, 0x69, 0xAC, 0x9D, 0x2E, 0xAC, 0xC0, 0x0A, 0xFC, 0xA4, 0x73, 0xF5, 0xDF, 0x67 + .byte 0x65, 0x41, 0x00, 0x11, 0x58, 0x4D, 0x4B, 0x00, 0xA5, 0xA5, 0x45, 0xB2, 0x4C, 0x38, 0x11, 0x9E + .byte 0x86, 0xC3, 0x07, 0x33, 0x61, 0x35, 0xDF, 0x22, 0x40, 0xDC, 0xC6, 0xB4, 0xD2, 0xA6, 0x1B, 0x37 + .byte 0xE7, 0x1C, 0x49, 0x40, 0x69, 0x94, 0x40, 0x0F, 0x39, 0x85, 0xC2, 0x85, 0xBD, 0xD4, 0x24, 0x44 + .byte 0x97, 0x2B, 0x77, 0xF8, 0x61, 0x56, 0x1B, 0xA2, 0x33, 0xE2, 0x56, 0x05, 0x89, 0x71, 0x3D, 0x71 + .byte 0x8D, 0x86, 0xB1, 0xF7, 0x1A, 0xF1, 0x06, 0x54, 0x77, 0xC9, 0xDA, 0x34, 0x9D, 0xFE, 0x79, 0x34 + .byte 0x2A, 0xF0, 0x2D, 0x8C, 0x47, 0x49, 0x2E, 0x7A, 0x2B, 0x84, 0x80, 0xB4, 0xF5, 0xBD, 0x25, 0x83 + .byte 0x43, 0xD6, 0x7A, 0x5E, 0xC8, 0x81, 0xB2, 0x3F, 0x4A, 0x8C, 0x74, 0xE8, 0x8B, 0xED, 0x1C, 0xB5 + .byte 0xDD, 0x4A, 0x41, 0x24, 0x93, 0x70, 0x9F, 0xBF, 0xF4, 0x20, 0x73, 0xEA, 0xDD, 0x99, 0x6D, 0x21 + .byte 0x6F, 0xE8, 0x7F, 0x37, 0x69, 0x32, 0x77, 0xB4, 0xBE, 0xEB, 0x9D, 0x4A, 0xD8, 0xB9, 0x00, 0xB6 + .byte 0x04, 0x42, 0xDB, 0x98, 0xB2, 0x7B, 0x57, 0xA6, 0x9B, 0xCA, 0x90, 0x78, 0x63, 0xFE, 0x9A, 0xD3 + .byte 0xE6, 0x19, 0x0B, 0x50, 0x4C, 0x83, 0x05, 0x0B, 0x6E, 0xA2, 0x55, 0x47, 0x5C, 0x55, 0xFE, 0x60 + .byte 0x97, 0xD9, 0xF8, 0x4A, 0x54, 0x50, 0xF0, 0xEF, 0x1B, 0x81, 0x68, 0x7E, 0x7F, 0x02, 0x52, 0x65 + .byte 0x1C, 0x5E, 0xB5, 0x68, 0xE1, 0xBA, 0x73, 0x50, 0x5C, 0xC9, 0x97, 0xB8, 0x1E, 0x96, 0x19, 0xB6 + .byte 0x6F, 0x12, 0x00, 0xC4, 0x62, 0xF1, 0xB4, 0x7D, 0x72, 0x1D, 0xFC, 0xF2, 0x20, 0x4F, 0x57, 0x3C + .byte 0xAD, 0x0D, 0xA5, 0x8F, 0xC8, 0x19, 0xDF, 0x24, 0xE3, 0x77, 0xDD, 0x02, 0x0D, 0xF7, 0xB8, 0x7D + .byte 0x09, 0xB9, 0x41, 0x6C, 0xAB, 0xF6, 0xEA, 0x1D, 0x13, 0xE6, 0x10, 0x33, 0x36, 0x67, 0x70, 0xE4 + .byte 0x75, 0x16, 0x73, 0x3D, 0x30, 0x53, 0x62, 0x13, 0xCA, 0x40, 0x15, 0xD8, 0x37, 0xCE, 0x55, 0x41 + .byte 0x88, 0x97, 0xAD, 0x33, 0x8D, 0x98, 0x51, 0xA1, 0x7F, 0x61, 0xD5, 0xB5, 0xC9, 0x45, 0x99, 0x3E + .byte 0x5C, 0x0C, 0x7C, 0x8C, 0x60, 0xDE, 0xA0, 0x2A, 0x1E, 0xB6, 0x02, 0x55, 0x84, 0x57, 0x97, 0x0D + .byte 0xEF, 0x44, 0x40, 0x7C, 0xDD, 0x91, 0x1E, 0x5C, 0xF3, 0xF3, 0x11, 0xBC, 0x39, 0xAA, 0xFB, 0x95 + .byte 0xB7, 0x77, 0x22, 0x17, 0x55, 0xC2, 0x42, 0x74, 0x79, 0x44, 0xC9, 0xFE, 0x9C, 0x61, 0x0B, 0x8B + .byte 0xA6, 0x4B, 0x08, 0x83, 0xDD, 0x27, 0xDF, 0xD1, 0x1A, 0xF0, 0x8E, 0x53, 0x9B, 0x89, 0xE9, 0x53 + .byte 0x00, 0x0B, 0x6B, 0x56, 0xCE, 0xAD, 0xCA, 0x47, 0xF2, 0x94, 0x45, 0x8E, 0xF5, 0x50, 0x1A, 0x9B + .byte 0x9C, 0x23, 0x1E, 0x7A, 0x4A, 0xFE, 0x4B, 0x65, 0xEE, 0xD9, 0xB8, 0x8A, 0x63, 0xA2, 0xDD, 0x63 + .byte 0xAD, 0x48, 0xBA, 0x7B, 0xF5, 0x85, 0xC3, 0xE7, 0x19, 0x08, 0x76, 0x0F, 0x59, 0x91, 0xAB, 0xF5 + .byte 0xB4, 0xC9, 0x70, 0xFF, 0xC8, 0xBC, 0x64, 0xB6, 0x95, 0x1D, 0x41, 0xF9, 0xBF, 0x1E, 0x5C, 0x6D + .byte 0x67, 0x17, 0xE9, 0x5D, 0x9C, 0xAC, 0x45, 0xB6, 0xB4, 0xBB, 0xC5, 0x0E, 0x4D, 0x70, 0x04, 0x02 + .byte 0x3A, 0x74, 0x01, 0x02, 0x30, 0x66, 0xB9, 0xC6, 0x83, 0xFA, 0xBF, 0x43, 0x19, 0x1C, 0xB0, 0x81 + .byte 0x34, 0x9A, 0xDE, 0xD0, 0x46, 0x23, 0x86, 0xFB, 0xDF, 0x4C, 0x09, 0x2D, 0xBC, 0x0D, 0x2F, 0xF7 + .byte 0x82, 0x30, 0xFA, 0xB2, 0x96, 0xB3, 0x79, 0x1A, 0xAE, 0x39, 0x5D, 0xC8, 0x55, 0x0E, 0x49, 0x89 + .byte 0xA8, 0x28, 0x5A, 0xEF, 0x4C, 0xE1, 0xEA, 0x2B, 0x2D, 0xF4, 0x58, 0xEA, 0x02, 0x88, 0xE1, 0x84 + .byte 0xB8, 0xDB, 0x37, 0x4F, 0x8F, 0xB0, 0x69, 0x3E, 0xE9, 0xC7, 0x07, 0x3F, 0xD5, 0x51, 0xC9, 0x7E + .byte 0x79, 0x23, 0x6D, 0xC5, 0x04, 0x58, 0xF1, 0x31, 0x4D, 0x4A, 0x1C, 0x4F, 0xD2, 0xFE, 0xD3, 0x8B + .byte 0xD9, 0x0B, 0xDA, 0x69, 0xBC, 0x43, 0xA8, 0xA5, 0x0A, 0xAF, 0xE5, 0xE0, 0x00, 0xAE, 0x5E, 0x7A + .byte 0xD2, 0xCC, 0x40, 0xD6, 0x25, 0x31, 0x08, 0x72, 0x7C, 0x25, 0xC1, 0x4E, 0x23, 0x95, 0xD9, 0xFD + .byte 0xA0, 0xB4, 0x66, 0x5C, 0xF7, 0x0F, 0x02, 0x02, 0xBF, 0xE7, 0xE3, 0xC0, 0x96, 0x41, 0x3A, 0x69 + .byte 0x0E, 0x7A, 0x3F, 0x33, 0xAC, 0x48, 0xA5, 0x28, 0x6D, 0x66, 0x77, 0x91, 0xFC, 0x51, 0x8E, 0x9C + .byte 0x05, 0xF5, 0xF8, 0xFD, 0x04, 0xFB, 0x00, 0xC4, 0xE3, 0xE3, 0x84, 0x79, 0x25, 0xBF, 0xE2, 0x33 + .byte 0x39, 0x22, 0x66, 0xE6, 0x6B, 0x0C, 0x0E, 0xD9, 0x73, 0x86, 0x6A, 0x6F, 0xD7, 0xF8, 0x0B, 0xDD + .byte 0xEE, 0x04, 0xDA, 0xF2, 0xFF, 0xDB, 0xB6, 0xE2, 0xBE, 0x3B, 0x5C, 0xE3, 0xFA, 0x3F, 0x17, 0x33 + .byte 0x62, 0x7E, 0x1A, 0xCD, 0x8A, 0x29, 0xA7, 0xFE, 0xAF, 0x11, 0x6D, 0x87, 0x0A, 0x79, 0x64, 0xF8 + .byte 0x7D, 0x3F, 0xEB, 0x7D, 0x1A, 0xA2, 0x60, 0xD9, 0xDD, 0xBC, 0xBC, 0xD7, 0xFC, 0xD4, 0x0B, 0x5E + .byte 0x52, 0x25, 0x2C, 0xDC, 0x4F, 0xD4, 0xDA, 0xFE, 0xE6, 0x48, 0x85, 0xF1, 0xC1, 0xEA, 0xEA, 0x3F + .byte 0x2A, 0xD5, 0xBC, 0x44, 0x78, 0x1C, 0x1E, 0x55, 0xD9, 0xDB, 0x2D, 0xD6, 0xAF, 0x38, 0x35, 0x01 + .byte 0x5E, 0x62, 0xDE, 0xAD, 0x36, 0xB9, 0xAC, 0x1D, 0x01, 0x32, 0x0E, 0xC2, 0x1C, 0xF8, 0x01, 0x46 + .byte 0xCD, 0xBE, 0x8B, 0x45, 0xDB, 0xA9, 0x9B, 0xB4, 0x84, 0xC8, 0x8B, 0x34, 0x01, 0xC0, 0x35, 0x5F + .byte 0x22, 0x13, 0x0D, 0x59, 0xCC, 0xB9, 0x76, 0xCD, 0xEC, 0x84, 0x90, 0x09, 0x7C, 0x92, 0x50, 0x4A + .byte 0x50, 0xDB, 0x90, 0x2B, 0x85, 0x2C, 0xE0, 0x0A, 0xF4, 0x6B, 0x3E, 0xF6, 0x2C, 0x74, 0x56, 0x4E + .byte 0x87, 0x63, 0xA8, 0x54, 0x1D, 0x1E, 0x21, 0x0A, 0xA2, 0xB2, 0x13, 0x1F, 0x44, 0x63, 0x6A, 0x95 + .byte 0x3F, 0xFB, 0xC1, 0xC4, 0x27, 0xA1, 0xCF, 0x1C, 0x0D, 0x0E, 0x12, 0x39, 0x82, 0x68, 0x88, 0x0A + .byte 0xCC, 0x30, 0x5E, 0xEA, 0x4F, 0x80, 0xF4, 0xF2, 0x32, 0x07, 0x11, 0x77, 0x6A, 0x7C, 0x0D, 0xA9 + .byte 0x77, 0xCE, 0x6E, 0x9E, 0x70, 0x3E, 0xBB, 0x7E, 0x4C, 0xCD, 0xB8, 0xCF, 0x36, 0x40, 0xD9, 0x03 + .byte 0x71, 0x38, 0xED, 0xC0, 0xB8, 0xE2, 0xB2, 0xEB, 0xE9, 0xC4, 0x63, 0x54, 0x41, 0x70, 0xFE, 0xB8 + .byte 0x3F, 0x6D, 0x57, 0xAF, 0xAB, 0x12, 0x2D, 0xF8, 0xE0, 0xE5, 0xC8, 0x16, 0x26, 0xA1, 0x1A, 0x98 + .byte 0xDA, 0x07, 0x58, 0x92, 0xE9, 0x0B, 0x7E, 0xD3, 0xD0, 0xE1, 0x28, 0x11, 0x52, 0x26, 0xCA, 0x91 + .byte 0x93, 0x21, 0x41, 0x3F, 0x34, 0x6E, 0x37, 0x14, 0x54, 0xFF, 0x2B, 0x7B, 0xA1, 0x45, 0x13, 0x7B + .byte 0x4D, 0x6C, 0x0E, 0x37, 0x77, 0x8D, 0x0A, 0x47, 0x6F, 0x32, 0x59, 0xC1, 0x59, 0x23, 0x53, 0xEC + .byte 0x44, 0x94, 0x2C, 0x79, 0x02, 0x63, 0x8E, 0x57, 0x63, 0xB9, 0xD3, 0x04, 0xFF, 0xE6, 0x80, 0x4C + .byte 0x52, 0x8F, 0x83, 0xCA, 0x1C, 0x8E, 0x12, 0x8B, 0xC1, 0x6B, 0x4D, 0x1A, 0x8E, 0xA0, 0x07, 0xD3 + .byte 0x34, 0x33, 0x4D, 0x37, 0x97, 0xDB, 0x8F, 0xFA, 0x95, 0x62, 0xFF, 0x94, 0x48, 0x80, 0xE1, 0x9B + .byte 0x0F, 0x65, 0x65, 0x2C, 0xF3, 0x77, 0xB7, 0xB4, 0xE2, 0x05, 0xCF, 0x71, 0xA5, 0xD6, 0x45, 0xD9 + .byte 0x0A, 0x92, 0x11, 0xA1, 0x6D, 0xA0, 0x9C, 0x02, 0x02, 0x9B, 0x97, 0x4B, 0x1C, 0x78, 0xE6, 0x2B + .byte 0xDD, 0x4B, 0x57, 0xD1, 0xC3, 0x0F, 0x86, 0xA5, 0x14, 0x55, 0x17, 0xB9, 0x2C, 0x5D, 0x93, 0x37 + .byte 0xEF, 0xA4, 0xD9, 0x5D, 0x45, 0x75, 0x60, 0x47, 0x11, 0xF7, 0x93, 0x2D, 0x70, 0x79, 0x59, 0x4E + .byte 0xC5, 0xB0, 0x1F, 0x88, 0xC0, 0xA6, 0x2E, 0xD4, 0xFC, 0x45, 0x8E, 0x29, 0xA2, 0x22, 0x60, 0x92 + .byte 0xC7, 0x39, 0xEF, 0x0C, 0xAE, 0x50, 0x54, 0xC0, 0x48, 0xE7, 0xED, 0xB8, 0x60, 0x46, 0x06, 0x25 + .byte 0xF7, 0x26, 0xAD, 0xB7, 0xCD, 0xDC, 0x8C, 0xC9, 0x21, 0x1A, 0xF2, 0xC4, 0x3D, 0x52, 0x56, 0x04 + .byte 0x8C, 0x46, 0x10, 0x3A, 0x96, 0x65, 0xFA, 0xDE, 0x4C, 0xE8, 0x97, 0xAD, 0x2E, 0x9E, 0xD3, 0x26 + .byte 0xC4, 0x81, 0xDD, 0x92, 0x5D, 0x69, 0x5B, 0x7E, 0x84, 0x4D, 0x43, 0xC1, 0xA0, 0x9A, 0xC6, 0x2C + .byte 0xE0, 0xD6, 0x67, 0x77, 0x3B, 0x62, 0x55, 0x88, 0x4A, 0xEC, 0x35, 0x79, 0x8A, 0x09, 0x9F, 0x4F + .byte 0x8A, 0x7D, 0xE1, 0xE7, 0xE7, 0x3D, 0x66, 0x6C, 0x8B, 0xAA, 0x2D, 0x2B, 0x44, 0xF3, 0x57, 0x24 + .byte 0xCA, 0xBF, 0x9B, 0x06, 0x21, 0xF1, 0x8F, 0x6B, 0xDE, 0xC4, 0xE5, 0x69, 0xCE, 0x85, 0xB9, 0x58 + .byte 0x02, 0x9B, 0x40, 0xE9, 0xD8, 0xA7, 0x55, 0x63, 0x51, 0x83, 0x8E, 0x95, 0x77, 0xE6, 0xBA, 0x42 + .byte 0xA5, 0x56, 0x49, 0xC7, 0x47, 0xD8, 0x32, 0x25, 0x9D, 0x18, 0x8E, 0x6B, 0x9D, 0x48, 0xC4, 0x9F + .byte 0xE3, 0x04, 0x89, 0xBB, 0xAB, 0xDF, 0x1F, 0xFD, 0x62, 0xAD, 0x92, 0xDA, 0x94, 0x4D, 0x1C, 0x3A + .byte 0xA3, 0x65, 0x01, 0xEA, 0x3E, 0x34, 0x10, 0xDB, 0x4C, 0x9F, 0x46, 0xE9, 0xE7, 0x0A, 0x89, 0xCA + .byte 0x0F, 0x13, 0x86, 0xBA, 0xF2, 0xA5, 0xB8, 0x55, 0x53, 0x4A, 0x2F, 0xE7, 0x98, 0x4C, 0x22, 0x3B + .byte 0xB2, 0x23, 0x26, 0xF0, 0x58, 0x36, 0xCB, 0xA4, 0xD6, 0x12, 0x8E, 0xBD, 0x1D, 0x18, 0x88, 0x2C + .byte 0x2B, 0x0E, 0xE7, 0x1D, 0xB4, 0x9F, 0x72, 0x07, 0xEA, 0xA2, 0xEF, 0x82, 0xEE, 0x11, 0xBD, 0xA1 + .byte 0x35, 0xE3, 0x91, 0x8D, 0x1A, 0x5D, 0x32, 0xF0, 0x70, 0xC1, 0xAE, 0x8D, 0xD9, 0x36, 0xB9, 0x04 + .byte 0x45, 0xA0, 0x22, 0xF9, 0x3F, 0x95, 0x01, 0x2A, 0x37, 0xF0, 0xAC, 0x26, 0x02, 0x69, 0xC8, 0x38 + .byte 0x4D, 0x59, 0xC6, 0x67, 0xB7, 0xF9, 0x57, 0x27, 0xBA, 0x05, 0xB5, 0x93, 0x3C, 0x6E, 0x98, 0x82 + .byte 0x0F, 0xBA, 0x7B, 0x4F, 0x50, 0x7D, 0x79, 0x88, 0x6E, 0x25, 0xAE, 0x70, 0x8F, 0x76, 0xA9, 0xDC + .byte 0xD0, 0x6F, 0x43, 0x88, 0x69, 0x9B, 0xB0, 0x23, 0xA1, 0x65, 0xB7, 0xDD, 0xD4, 0x4F, 0x5F, 0xE3 + .byte 0x0A, 0xDB, 0x32, 0x5A, 0x58, 0xAC, 0xE2, 0xC6, 0xD2, 0x91, 0x37, 0x61, 0x08, 0xE1, 0x3D, 0xD9 + .byte 0x50, 0x81, 0x61, 0xBA, 0x1C, 0x11, 0xDD, 0xBD, 0x76, 0x94, 0x9B, 0x4A, 0xE4, 0xFA, 0x2E, 0xEE + .byte 0xD6, 0x61, 0x49, 0x2E, 0x0D, 0x2C, 0xF5, 0xE0, 0xBE, 0x2C, 0x41, 0xC6, 0x0D, 0x7F, 0xA0, 0x5E + .byte 0x00, 0x01, 0x18, 0x1D, 0x13, 0xF6, 0xDB, 0x8A, 0x8A, 0x76, 0xD5, 0x6E, 0x71, 0x03, 0x5D, 0x47 + .byte 0x64, 0xA7, 0x75, 0x72, 0xD4, 0x6B, 0x53, 0x92, 0x97, 0x94, 0x59, 0xA5, 0x13, 0xF9, 0x04, 0x14 + .byte 0xFB, 0x1D, 0x31, 0x0E, 0x13, 0x0C, 0x98, 0x9E, 0x83, 0x6D, 0x0D, 0xF4, 0x71, 0x6B, 0x3B, 0xD6 + .byte 0x12, 0xB1, 0x49, 0xE6, 0x1C, 0x9C, 0x79, 0xB4, 0x30, 0xD2, 0x5A, 0x44, 0xCC, 0x5E, 0x59, 0xC7 + .byte 0x7C, 0x8A, 0xD6, 0x8F, 0x97, 0x6F, 0x2E, 0x1A, 0xDD, 0x3B, 0x0E, 0x4E, 0xA6, 0x4A, 0x25, 0xB9 + .byte 0xFB, 0x6E, 0xA0, 0x18, 0x0A, 0x19, 0xCC, 0x3B, 0xEC, 0x26, 0x80, 0xB9, 0x85, 0xD9, 0x80, 0x01 + .byte 0x64, 0x57, 0x91, 0xFB, 0xC6, 0xBF, 0x16, 0xA3, 0xFB, 0x25, 0xF2, 0xA1, 0x6F, 0x17, 0x5B, 0x6B + .byte 0x86, 0xFB, 0x83, 0x91, 0x15, 0x50, 0xCC, 0x01, 0x77, 0x4D, 0xBA, 0xFC, 0x27, 0x3B, 0xFE, 0x8B + .byte 0x93, 0x90, 0x87, 0x59, 0x4F, 0x9E, 0xFD, 0x4A, 0xC3, 0xEF, 0xEC, 0x33, 0x07, 0x48, 0x9E, 0x8D + .byte 0x43, 0x22, 0x1E, 0x59, 0x73, 0xEB, 0x5B, 0xEA, 0x38, 0x16, 0xE7, 0x5F, 0x51, 0xE6, 0xEB, 0xE5 + .byte 0x76, 0x72, 0x3E, 0xC5, 0x10, 0x3B, 0x10, 0xD4, 0x2B, 0xFC, 0x07, 0x32, 0x44, 0xA6, 0xC0, 0x88 + .byte 0xC9, 0xDE, 0xE1, 0x3C, 0xCA, 0x3C, 0x27, 0x03, 0x53, 0x0E, 0x62, 0xA4, 0xF4, 0x4E, 0x89, 0x6A + .byte 0xC1, 0xC8, 0x30, 0xD1, 0x04, 0x40, 0xA6, 0x30, 0x3D, 0xAD, 0x62, 0x82, 0x54, 0x23, 0x0B, 0x1E + .byte 0x01, 0xED, 0x5A, 0xCB, 0x29, 0x81, 0xCE, 0x7C, 0x90, 0x31, 0x21, 0x85, 0x80, 0xAB, 0xF0, 0x41 + .byte 0x74, 0x20, 0x12, 0x78, 0x61, 0xB9, 0xA8, 0x9F, 0x66, 0x0B, 0x21, 0xBB, 0x2E, 0x2C, 0xD9, 0x30 + .byte 0x19, 0x34, 0xFC, 0x43, 0xB6, 0xCB, 0xC0, 0x46, 0xFD, 0xE2, 0xCC, 0x7D, 0x8E, 0xBC, 0xBE, 0x02 + .byte 0xDD, 0xD1, 0x7B, 0x3E, 0x8A, 0x24, 0xDD, 0xF1, 0x30, 0xFF, 0xAD, 0x5F, 0x2C, 0x86, 0x90, 0x46 + .byte 0xBB, 0x8D, 0x8A, 0x71, 0x58, 0x4A, 0xB8, 0x56, 0x2D, 0x84, 0xD3, 0xBC, 0x40, 0x92, 0xBF, 0x1D + .byte 0x64, 0x3A, 0x5C, 0xEF, 0x5F, 0x3A, 0xE0, 0x90, 0x39, 0x8E, 0xF0, 0x65, 0x14, 0x80, 0xAC, 0xCF + .byte 0x0D, 0x36, 0x40, 0x66, 0x81, 0xF9, 0xBC, 0xAE, 0x7D, 0x90, 0x6B, 0xBE, 0x23, 0x2A, 0xDC, 0x88 + .byte 0x65, 0x38, 0x77, 0xC5, 0x72, 0x58, 0x55, 0xAC, 0xE6, 0x45, 0x11, 0xFB, 0xC6, 0xBE, 0xCA, 0xD3 + .byte 0xF4, 0x0B, 0x3A, 0x75, 0x04, 0xF7, 0x24, 0x82, 0x87, 0x8F, 0x40, 0xAB, 0xB9, 0x1D, 0x33, 0x1F + .byte 0x55, 0xAB, 0xE4, 0xC8, 0x03, 0x39, 0x74, 0xEA, 0x7F, 0x86, 0xE5, 0x45, 0x44, 0xAF, 0x19, 0x38 + .byte 0xBB, 0x53, 0xAE, 0xC0, 0x4A, 0xD2, 0x43, 0xD2, 0x62, 0x84, 0x7E, 0x1C, 0xA1, 0xB2, 0x3B, 0xF6 + .byte 0x5D, 0x1F, 0xBE, 0x60, 0x59, 0x33, 0x4A, 0xD9, 0xB9, 0x30, 0x1E, 0xFE, 0xE0, 0x38, 0x37, 0x9B + .byte 0x8C, 0xE5, 0x5C, 0xD6, 0xB7, 0x9F, 0xA9, 0x1A, 0x23, 0x28, 0x36, 0xC4, 0xDA, 0x71, 0xBB, 0x37 + .byte 0x91, 0x7A, 0x98, 0xEB, 0xAD, 0xE2, 0xC4, 0x67, 0x13, 0xE3, 0x66, 0xF3, 0x1B, 0x9D, 0x8E, 0xA7 + .byte 0x82, 0xEB, 0x7E, 0x3A, 0x8B, 0x28, 0x54, 0xAF, 0x50, 0x8B, 0x73, 0x2A, 0xFC, 0x2F, 0x61, 0x8E + .byte 0xA9, 0xF9, 0x79, 0x57, 0xDC, 0x3D, 0xBF, 0xEF, 0x20, 0x25, 0xE2, 0x3C, 0xC3, 0x71, 0xE3, 0x45 + .byte 0x5D, 0x62, 0x80, 0xE8, 0x8A, 0xD4, 0x97, 0xDB, 0x5F, 0x0B, 0x05, 0x5C, 0x3B, 0x67, 0xEA, 0xE4 + .byte 0x61, 0x64, 0x3C, 0x3D, 0xA1, 0xFC, 0x2D, 0xC2, 0x22, 0x10, 0xFF, 0xE5, 0x82, 0xE2, 0x2A, 0xDF + .byte 0x45, 0xAA, 0xC7, 0xD0, 0x7F, 0x5F, 0xAB, 0xDF, 0x6B, 0xB0, 0x3C, 0xA6, 0x17, 0x27, 0x8B, 0x78 + .byte 0x8B, 0xC7, 0xB6, 0x2D, 0xC4, 0xE4, 0xEF, 0xE6, 0xF4, 0xEF, 0xCB, 0x77, 0xD1, 0xF6, 0x56, 0x17 + .byte 0xA1, 0x1E, 0xE7, 0x21, 0x7D, 0x92, 0x01, 0xE9, 0x43, 0x3D, 0x8F, 0x5B, 0x64, 0x1A, 0xD4, 0xF0 + .byte 0xE2, 0x8A, 0x1D, 0xA6, 0x6E, 0x0D, 0x8C, 0x63, 0xFC, 0x58, 0xDA, 0xCE, 0x4F, 0x31, 0xE5, 0xF0 + .byte 0x4F, 0xCD, 0x12, 0xCD, 0x5F, 0x13, 0xB6, 0xA3, 0x50, 0x45, 0xFE, 0xB5, 0x60, 0xD2, 0xA5, 0x42 + .byte 0x5C, 0xC3, 0xE8, 0xCB, 0xD0, 0x75, 0x2F, 0xCC, 0xCE, 0x0A, 0x9A, 0x1D, 0x3B, 0x80, 0x0E, 0x8B + .byte 0x4D, 0x21, 0x58, 0xAD, 0x34, 0x0F, 0x50, 0x85, 0x55, 0x4E, 0x3B, 0xB5, 0x20, 0xE1, 0xF8, 0x7D + .byte 0xA4, 0xE1, 0x49, 0x74, 0x57, 0x79, 0x41, 0x25, 0x83, 0xDB, 0x43, 0xBF, 0x5C, 0x52, 0x4A, 0xA9 + .byte 0x73, 0xA3, 0x57, 0xA8, 0xB2, 0xA7, 0x2E, 0x08, 0xF6, 0x69, 0xBE, 0x17, 0x4A, 0xB6, 0x95, 0xEE + .byte 0x98, 0xDE, 0x63, 0xEF, 0x57, 0xA4, 0x15, 0xDB, 0x80, 0x59, 0x9A, 0xDC, 0xAC, 0xE5, 0x86, 0x20 + .byte 0x88, 0xDD, 0xC8, 0x3B, 0x85, 0xF7, 0x43, 0x7C, 0x60, 0x02, 0x93, 0xAB, 0xB9, 0x28, 0x9A, 0x51 + .byte 0x07, 0xFD, 0x40, 0x5F, 0xA2, 0x56, 0x3A, 0x22, 0xAF, 0xD5, 0xFE, 0x5B, 0xBA, 0x85, 0x7B, 0x43 + .byte 0x63, 0x44, 0x7E, 0xE8, 0x3B, 0xC2, 0x65, 0x9C, 0xC5, 0xF8, 0x48, 0x7E, 0x21, 0xE2, 0xCF, 0x28 + .byte 0xE0, 0x10, 0x87, 0x82, 0x67, 0xC2, 0xA4, 0x16, 0x98, 0xA3, 0x72, 0x53, 0x29, 0xEE, 0x96, 0x8C + .byte 0x32, 0x15, 0x75, 0x6E, 0xD7, 0xDA, 0x0B, 0x9C, 0xD3, 0x53, 0x1B, 0xF4, 0x35, 0xEB, 0x1C, 0x15 + .byte 0xFC, 0xA4, 0x98, 0x63, 0x67, 0x3D, 0x7A, 0xFF, 0xE0, 0xEC, 0x52, 0x0A, 0xDA, 0xE9, 0x96, 0x0D + .byte 0xFE, 0x0B, 0x7C, 0xD5, 0xE6, 0x87, 0x72, 0xB9, 0xDA, 0x8E, 0xAD, 0x0F, 0x79, 0xCA, 0x25, 0x75 + .byte 0x6E, 0xBE, 0xD8, 0xD5, 0xFB, 0x52, 0xD5, 0xDC, 0x3E, 0x27, 0xE6, 0x19, 0x10, 0x7D, 0x27, 0x0E + .byte 0x88, 0xA3, 0xE4, 0x6E, 0x2A, 0x57, 0x28, 0x05, 0xE5, 0xD5, 0x15, 0x5E, 0x9F, 0x3A, 0xD4, 0x0D + .byte 0xF9, 0xAC, 0xE3, 0xF4, 0xFE, 0xB8, 0xD1, 0x3D, 0xE0, 0xB8, 0x57, 0xF1, 0x35, 0x7F, 0x00, 0xBD + .byte 0x22, 0xE5, 0x2C, 0x4D, 0x3C, 0x54, 0x52, 0x22, 0x2A, 0x68, 0x81, 0xC9, 0xA3, 0x55, 0xD7, 0x9C + .byte 0x02, 0xBA, 0x91, 0x00, 0x73, 0x62, 0x3E, 0x54, 0x1A, 0x96, 0x45, 0x4F, 0x15, 0x45, 0x0D, 0x38 + .byte 0x2B, 0x3A, 0x85, 0x68, 0x8F, 0xD8, 0x8A, 0xB9, 0x40, 0x0C, 0x83, 0xE3, 0x61, 0x5B, 0x80, 0x63 + .byte 0x15, 0x11, 0x64, 0x89, 0x73, 0xA3, 0xDD, 0x8E, 0x3A, 0x23, 0xDE, 0x4F, 0x69, 0xEC, 0x87, 0x94 + .byte 0x27, 0x0D, 0xFC, 0xB7, 0xE6, 0x87, 0x71, 0x27, 0x93, 0xF4, 0x0B, 0xF5, 0x4F, 0x8C, 0x59, 0x65 + .byte 0x9D, 0xBE, 0xEF, 0x11, 0x62, 0xCD, 0xA0, 0x9C, 0xF0, 0x7E, 0xEC, 0x59, 0x6B, 0x74, 0xEE, 0x92 + .byte 0x81, 0xEB, 0x49, 0x68, 0x72, 0xBA, 0x90, 0x06, 0xAF, 0x9C, 0xFC, 0xFE, 0x28, 0x56, 0x64, 0xC5 + .byte 0x14, 0x53, 0xD7, 0x76, 0x20, 0x77, 0x13, 0x11, 0xF5, 0xFF, 0x6B, 0x61, 0x73, 0x59, 0xF3, 0xF5 + .byte 0x45, 0x3D, 0x5E, 0xB7, 0xF7, 0xEE, 0xBE, 0xA6, 0x8B, 0xBB, 0xA5, 0xB3, 0x11, 0x09, 0x79, 0x25 + .byte 0x5D, 0x50, 0x9C, 0x7D, 0xC7, 0xAF, 0x8F, 0xBD, 0xAE, 0xFA, 0x1E, 0x22, 0x53, 0x12, 0x17, 0x98 + .byte 0x4F, 0x75, 0x50, 0x46, 0x63, 0x0F, 0xED, 0xEE, 0xCA, 0x92, 0xA2, 0xDC, 0x9C, 0x1B, 0x01, 0xF9 + .byte 0x6B, 0x9E, 0x77, 0x33, 0x4E, 0x06, 0xF1, 0xFC, 0x00, 0x0F, 0x1F, 0x54, 0x21, 0x36, 0xED, 0x70 + .byte 0xAB, 0x3D, 0xB7, 0x0F, 0x4D, 0xA4, 0xFE, 0x18, 0x37, 0xA0, 0xF4, 0xD3, 0xBC, 0xF5, 0xCD, 0x28 + .byte 0x94, 0x44, 0x5C, 0xE2, 0x4B, 0x4D, 0xDF, 0x4C, 0x5C, 0xFE, 0xA0, 0x7E, 0x34, 0x8D, 0xEE, 0xE0 + .byte 0xCB, 0xA6, 0xF0, 0x18, 0x4A, 0xEE, 0x30, 0x81, 0x8F, 0x25, 0x55, 0x4C, 0x1B, 0x22, 0x74, 0xAF + .byte 0x67, 0xD0, 0x91, 0xB2, 0x1D, 0x71, 0xFE, 0x7A, 0x70, 0x9F, 0xF8, 0xA4, 0x2C, 0xE7, 0x85, 0xF8 + .byte 0x8E, 0x75, 0x11, 0xD8, 0x64, 0x42, 0x5A, 0xF3, 0x67, 0xB0, 0x3F, 0x82, 0xD3, 0xB4, 0x31, 0x3A + .byte 0x85, 0xC3, 0xED, 0xA3, 0x35, 0xEC, 0x1D, 0xA5, 0x8B, 0x16, 0x4A, 0xB8, 0xFE, 0xCF, 0xB0, 0x8C + .byte 0x45, 0xC2, 0x65, 0xA9, 0x04, 0xC0, 0x9D, 0x6B, 0x71, 0xDD, 0xED, 0x44, 0x91, 0x1F, 0x7E, 0x16 + .byte 0xE3, 0x6B, 0xB9, 0x18, 0x57, 0xD7, 0xBD, 0xE3, 0xEE, 0x07, 0x9B, 0xEC, 0xD7, 0x4C, 0x79, 0x1C + .byte 0x0F, 0xDF, 0xC5, 0x13, 0xA0, 0x63, 0x7F, 0x11, 0x40, 0x6D, 0x55, 0xD1, 0x8C, 0xD4, 0xE8, 0x6F + .byte 0x3F, 0xA2, 0x87, 0x97, 0x79, 0x44, 0x7B, 0x68, 0x4C, 0x17, 0x54, 0x23, 0x64, 0xCE, 0x3F, 0x73 + .byte 0xAE, 0x05, 0x86, 0x4E, 0x68, 0x06, 0x60, 0xA8, 0x73, 0xB6, 0x7A, 0xFF, 0x8A, 0x62, 0x6F, 0xCA + .byte 0x04, 0xF6, 0x62, 0x7E, 0x3B, 0xDD, 0xE6, 0x87, 0xF4, 0x3B, 0xAB, 0x58, 0x0A, 0xEA, 0xCC, 0xB8 + .byte 0xEF, 0x53, 0x07, 0x58, 0x59, 0x68, 0x00, 0xCC, 0x1E, 0x7A, 0xCC, 0xA8, 0xDD, 0x3B, 0x72, 0xE2 + .byte 0x31, 0xD4, 0x60, 0x6D, 0xB2, 0x47, 0xF5, 0xA6, 0x83, 0xA0, 0xFF, 0x8D, 0x8B, 0xCC, 0x46, 0x7A + .byte 0x1F, 0x4E, 0xD3, 0x78, 0xB6, 0xD3, 0x45, 0xD5, 0x4E, 0x11, 0x7D, 0x2C, 0x4C, 0xF0, 0x0E, 0x7E + .byte 0xC4, 0x6F, 0xEC, 0x77, 0xB6, 0xE1, 0x1D, 0x39, 0x82, 0x1D, 0xC7, 0x0D, 0xE9, 0x0D, 0x88, 0x09 + .byte 0x5C, 0x5B, 0x81, 0x12, 0x2F, 0xC7, 0xE7, 0x7D, 0xD8, 0x65, 0xA9, 0x25, 0x55, 0xB8, 0xA3, 0x1A + .byte 0x27, 0x90, 0x91, 0xDD, 0x71, 0xAF, 0x17, 0xF3, 0xCD, 0xDE, 0x00, 0xB6, 0xEC, 0x88, 0xBF, 0x48 + .byte 0xE4, 0x41, 0x5B, 0x13, 0x09, 0x43, 0x90, 0xE1, 0xA8, 0x3A, 0x07, 0xFE, 0xF3, 0xAB, 0x18, 0x1A + .byte 0x3B, 0xAA, 0xF8, 0xAC, 0x59, 0x0F, 0xA0, 0x26, 0xEE, 0xA1, 0xDD, 0xDB, 0x2A, 0x9D, 0x23, 0x0E + .byte 0xDF, 0x7E, 0x21, 0xE8, 0xC2, 0xB2, 0xCA, 0x6A, 0xED, 0xD1, 0x68, 0xE0, 0x7C, 0x81, 0xFA, 0xB7 + .byte 0x2B, 0xF3, 0x64, 0x85, 0x02, 0x04, 0xAB, 0xF1, 0xA6, 0x89, 0xCC, 0xD1, 0x26, 0xF0, 0xDF, 0x05 + .byte 0x6F, 0x01, 0xEE, 0x31, 0xB4, 0xB8, 0x9B, 0xA1, 0x89, 0x04, 0x82, 0x05, 0x85, 0x7C, 0xBC, 0xB1 + .byte 0x6F, 0x20, 0x36, 0x72, 0x25, 0xE1, 0x64, 0xCB, 0x6B, 0x30, 0x9C, 0x91, 0x20, 0x7C, 0x97, 0x90 + .byte 0x7D, 0x85, 0xC1, 0x32, 0x3D, 0x5D, 0xD3, 0xC6, 0x61, 0x55, 0xCC, 0xE7, 0xD2, 0x88, 0x98, 0x42 + .byte 0xA8, 0xCE, 0xB5, 0xCE, 0xB0, 0x19, 0x9A, 0x1B, 0x49, 0x37, 0xAD, 0x6A, 0xB3, 0x45, 0xFA, 0x31 + .byte 0xCA, 0xBC, 0x63, 0x08, 0x19, 0x37, 0xCF, 0x7B, 0x8D, 0x9B, 0x62, 0x5F, 0x23, 0xFB, 0xA1, 0xCC + .byte 0xCA, 0x57, 0x9A, 0x7A, 0x70, 0x35, 0x96, 0xBA, 0x6C, 0x44, 0x24, 0x20, 0x89, 0x1F, 0x52, 0x53 + .byte 0xDC, 0xB6, 0x5C, 0xF5, 0xEE, 0x2B, 0x71, 0x7B, 0xC6, 0xD3, 0xDA, 0xEA, 0xCF, 0x7C, 0xB6, 0x99 + .byte 0xD3, 0x51, 0x14, 0x44, 0x86, 0xAA, 0xFE, 0xF3, 0xEF, 0x23, 0x14, 0x78, 0x43, 0x66, 0xCC, 0x1F + .byte 0x1D, 0x28, 0x15, 0x0B, 0x54, 0x86, 0x86, 0x1A, 0x5A, 0x61, 0x04, 0x29, 0xDE, 0xBB, 0xC3, 0xB2 + .byte 0x0D, 0xD7, 0xF6, 0x94, 0x82, 0xF4, 0x87, 0x71, 0x17, 0x9C, 0xE9, 0x5A, 0x03, 0xB6, 0x7A, 0x20 + .byte 0xDE, 0x8F, 0x2C, 0x33, 0x16, 0xB3, 0x4D, 0x70, 0x15, 0x52, 0x9A, 0xF3, 0x0E, 0x5D, 0xA6, 0x1B + .byte 0x35, 0x9C, 0xAF, 0xB7, 0x90, 0x37, 0x29, 0xA8, 0xD3, 0x12, 0x03, 0xD7, 0xC9, 0x7D, 0xF7, 0xA8 + .byte 0x0D, 0x24, 0xDB, 0x23, 0xD7, 0x28, 0x94, 0xED, 0x7B, 0x2F, 0xE0, 0x89, 0x8D, 0x86, 0xA5, 0xC2 + .byte 0x23, 0x54, 0x79, 0xB4, 0x8C, 0xA2, 0x5C, 0x60, 0xB5, 0x60, 0x37, 0x7F, 0xDE, 0x2F, 0x27, 0xEB + .byte 0x53, 0x02, 0x0F, 0x2B, 0x2B, 0xA4, 0x18, 0xA6, 0xD3, 0xF9, 0x30, 0x60, 0x7F, 0xD5, 0x22, 0xA3 + .byte 0x2A, 0x9C, 0x57, 0xB7, 0x3F, 0xB4, 0x17, 0xF5, 0x14, 0x4E, 0x74, 0xF2, 0x7E, 0x9B, 0xDE, 0xD1 + .byte 0x9E, 0xED, 0xFD, 0xC9, 0x91, 0x15, 0x70, 0x65, 0x0E, 0xA1, 0xC5, 0x8E, 0x77, 0xE8, 0x31, 0xA2 + .byte 0x84, 0x89, 0x59, 0xC4, 0x3D, 0x71, 0xB9, 0x51, 0xC0, 0x2D, 0x44, 0x3E, 0xC9, 0x22, 0x10, 0x67 + .byte 0x10, 0x0D, 0x31, 0xA2, 0x22, 0xA2, 0x07, 0x31, 0x43, 0xCC, 0xC0, 0xBB, 0xB5, 0xF2, 0x5D, 0x39 + .byte 0x7B, 0xB6, 0xFD, 0xB8, 0x27, 0xB7, 0x0A, 0xE7, 0xE5, 0x4E, 0x26, 0xAE, 0x70, 0x36, 0x16, 0x81 + .byte 0x43, 0x48, 0x23, 0x66, 0xEA, 0x2B, 0x98, 0x2E, 0xF8, 0x58, 0xE9, 0xAD, 0x4A, 0x46, 0xE6, 0xC6 + .byte 0xFD, 0xE4, 0x7E, 0x25, 0x9B, 0x88, 0x0C, 0x80, 0xD6, 0x33, 0x2F, 0x47, 0x69, 0x45, 0xC9, 0xAC + .byte 0x8E, 0xEC, 0x13, 0x78, 0x17, 0xAB, 0xA6, 0x0F, 0x04, 0x8F, 0xBD, 0x4F, 0xD6, 0xA3, 0x15, 0xD3 + .byte 0x88, 0x93, 0xF8, 0x24, 0x1C, 0x05, 0xA5, 0xF3, 0x38, 0xD4, 0x3B, 0xA1, 0x1A, 0x04, 0x4E, 0xA8 + .byte 0xF0, 0x61, 0x21, 0x08, 0x0D, 0xC7, 0x18, 0x11, 0x57, 0xD5, 0x60, 0x2D, 0x79, 0x75, 0x01, 0x02 + .byte 0x09, 0xF9, 0x26, 0x26, 0xFF, 0xCB, 0x19, 0x37, 0xA0, 0x54, 0xD8, 0xBA, 0x58, 0x27, 0x63, 0x49 + .byte 0x89, 0x84, 0x52, 0x96, 0x4C, 0x6B, 0xA8, 0xA3, 0x40, 0x08, 0xD1, 0xBA, 0x7E, 0xD2, 0xBC, 0x88 + .byte 0xCB, 0xE2, 0xAE, 0xCA, 0xAE, 0xC7, 0x02, 0x4E, 0x1C, 0xDB, 0x09, 0x74, 0x02, 0x6C, 0xBE, 0x8B + .byte 0xF1, 0x10, 0x22, 0x3D, 0x7B, 0xCA, 0xE1, 0xBC, 0xD3, 0xB2, 0x76, 0x52, 0x84, 0x33, 0xDA, 0x50 + .byte 0x16, 0x89, 0x1B, 0xC4, 0x51, 0x1D, 0x13, 0x6D, 0xF8, 0x1C, 0xE2, 0xFB, 0x89, 0xA0, 0x87, 0x7B + .byte 0xB1, 0xA9, 0xB8, 0x2D, 0x74, 0x99, 0xE9, 0x47, 0x4C, 0x60, 0x99, 0xD0, 0x93, 0x74, 0x21, 0xA9 + .byte 0xFD, 0x3C, 0x6E, 0x4E, 0x59, 0x81, 0xBC, 0x52, 0x9E, 0x9E, 0x4E, 0x27, 0x3F, 0xD5, 0xA2, 0xF1 + .byte 0x7F, 0x5B, 0x1E, 0xF3, 0xF5, 0x08, 0x3B, 0x41, 0x68, 0xD4, 0x12, 0xFC, 0x49, 0x33, 0xA6, 0x46 + .byte 0x70, 0x15, 0x95, 0xCA, 0x96, 0x51, 0x1C, 0x34, 0xF0, 0x6B, 0x5C, 0x30, 0x40, 0xFF, 0x21, 0xBF + .byte 0x5B, 0x40, 0xB2, 0x50, 0x48, 0xEE, 0x92, 0xB0, 0xC3, 0xA5, 0xAD, 0x0C, 0xD9, 0x54, 0x53, 0x49 + .byte 0x69, 0xE8, 0x13, 0xFF, 0x3A, 0x30, 0x34, 0x2B, 0x9B, 0x91, 0x5B, 0xDC, 0x91, 0x7D, 0x9B, 0xEC + .byte 0xBD, 0x4E, 0x3C, 0x05, 0x3C, 0xCF, 0xB6, 0xFF, 0x74, 0x64, 0x0C, 0x4E, 0xB8, 0x5F, 0x97, 0x21 + .byte 0x48, 0xAB, 0x21, 0x83, 0xDC, 0x56, 0xAE, 0x77, 0xE8, 0x0A, 0x53, 0x79, 0x88, 0xEF, 0x65, 0x46 + .byte 0x3E, 0xA2, 0x4B, 0x7A, 0x72, 0x02, 0x7A, 0xE7, 0x66, 0x86, 0x35, 0x1F, 0xE6, 0xCC, 0x40, 0x2E + .byte 0x78, 0x62, 0xB2, 0x54, 0xB9, 0x61, 0xCC, 0xA1, 0x6B, 0x1F, 0x1A, 0xF4, 0x0F, 0x80, 0x3A, 0x4D + .byte 0x22, 0x86, 0xC8, 0x94, 0x88, 0x42, 0x7B, 0xEF, 0xC9, 0xB0, 0x0E, 0xAF, 0x7D, 0x4F, 0xDE, 0xF6 + .byte 0xB2, 0x90, 0x4A, 0x6B, 0xF1, 0x16, 0x0C, 0x5D, 0x36, 0x27, 0x51, 0x45, 0xA7, 0x8C, 0x92, 0xCA + .byte 0x12, 0x5A, 0x5E, 0x9B, 0x9D, 0xDA, 0x8A, 0x67, 0x8B, 0x99, 0x16, 0x09, 0xE8, 0xF5, 0xFF, 0x9A + .byte 0x85, 0x49, 0x06, 0x77, 0x60, 0x13, 0xD4, 0x96, 0x3B, 0x26, 0xDB, 0xE2, 0xB2, 0x6E, 0xAD, 0xC5 + .byte 0xC9, 0x0B, 0x60, 0x67, 0xE6, 0xEB, 0xCE, 0x71, 0x84, 0xE5, 0x7B, 0x6D, 0xDA, 0x7A, 0x08, 0x60 + .byte 0xC4, 0x0E, 0xD7, 0x24, 0x22, 0xAB, 0xBA, 0x5D, 0xD2, 0x96, 0x3F, 0x85, 0x05, 0xEC, 0x4A, 0xCF + .byte 0xF8, 0xAB, 0x36, 0xDF, 0x96, 0x04, 0x51, 0x1B, 0xE9, 0xCC, 0x88, 0xC3, 0x46, 0x90, 0x23, 0x0A + .byte 0x9F, 0xFB, 0x2E, 0xC1, 0xA7, 0xE9, 0x1E, 0x79, 0x80, 0x5E, 0xFF, 0x85, 0x4B, 0x4A, 0x54, 0x44 + .byte 0xF5, 0x8B, 0x23, 0x8C, 0x8F, 0x74, 0xA8, 0x79, 0x41, 0x30, 0x3D, 0x87, 0xC1, 0x61, 0x92, 0x61 + .byte 0x5C, 0xC1, 0x22, 0x03, 0xAB, 0x41, 0x7D, 0x2B, 0xA0, 0x7C, 0xB1, 0xEB, 0xC6, 0x06, 0x2F, 0xBC + .byte 0x91, 0x53, 0x49, 0x21, 0xC8, 0xF1, 0x9A, 0x09, 0x22, 0xD7, 0x91, 0xE4, 0x38, 0x24, 0x45, 0x94 + .byte 0xE5, 0x68, 0x98, 0x90, 0xAA, 0x15, 0xBB, 0x4A, 0x92, 0x6D, 0x35, 0x59, 0x73, 0x65, 0x16, 0x05 + .byte 0xB9, 0x5F, 0x26, 0x81, 0x51, 0xC0, 0x8B, 0x73, 0x97, 0x1D, 0x57, 0xD0, 0x41, 0x9D, 0x64, 0x26 + .byte 0x05, 0xFD, 0xB7, 0xB0, 0x12, 0x73, 0xFA, 0xA5, 0xE0, 0x2F, 0xFE, 0x54, 0x95, 0x14, 0x59, 0x4E + .byte 0x74, 0x7F, 0xD0, 0xC5, 0x40, 0x5C, 0x38, 0xD8, 0x79, 0x90, 0xA8, 0xBB, 0x2E, 0x0D, 0xE2, 0x34 + .byte 0x0A, 0x99, 0xE4, 0x1D, 0x0C, 0xDE, 0xC2, 0xED, 0x0E, 0xC1, 0x41, 0xA3, 0xD6, 0x9A, 0xF2, 0x4A + .byte 0x1A, 0xC3, 0x0F, 0x5A, 0x20, 0x48, 0x33, 0x99, 0xD9, 0xDB, 0x55, 0x07, 0xE9, 0x37, 0x3B, 0xF4 + .byte 0xD0, 0x20, 0x11, 0xDC, 0xFE, 0xD4, 0xC9, 0x0D, 0x96, 0x0B, 0xB0, 0x6C, 0xA5, 0xA3, 0xB7, 0xC0 + .byte 0x67, 0xC7, 0x1B, 0x87, 0x0F, 0x4E, 0x21, 0xE9, 0x2A, 0x76, 0xF1, 0x13, 0xAD, 0x2D, 0x08, 0x7D + .byte 0x4D, 0x1A, 0x5A, 0x4B, 0xEE, 0x24, 0x58, 0x85, 0x2F, 0x09, 0xF2, 0xD5, 0xAD, 0xA9, 0x95, 0x14 + .byte 0x70, 0xB1, 0x9C, 0x80, 0x00, 0xBD, 0x69, 0x2A, 0x33, 0x5B, 0x3E, 0xE0, 0x88, 0x46, 0x5E, 0xD5 + .byte 0x60, 0xB9, 0x21, 0x4F, 0xDD, 0x7A, 0xD5, 0x0C, 0x84, 0xC7, 0xE2, 0x32, 0x70, 0x78, 0x47, 0xE0 + .byte 0x29, 0xE3, 0x61, 0x29, 0xA0, 0xCB, 0x54, 0xD4, 0x26, 0x93, 0xB5, 0xAE, 0xDA, 0x13, 0x84, 0x3B + .byte 0xCC, 0xA6, 0x8B, 0xAA, 0x21, 0x60, 0xB6, 0xA5, 0x27, 0x99, 0xD8, 0x97, 0x11, 0x1F, 0x78, 0x3A + .byte 0x02, 0xDA, 0x64, 0xA3, 0xA5, 0xB9, 0x77, 0xCB, 0x4D, 0x2D, 0x7A, 0x27, 0x40, 0xFF, 0x63, 0x0D + .byte 0xA5, 0xEE, 0xB7, 0xC7, 0x4E, 0x6E, 0x6C, 0x76, 0x07, 0x45, 0x0E, 0x19, 0x64, 0x87, 0x54, 0x67 + .byte 0x61, 0xB9, 0x0A, 0x06, 0x72, 0x82, 0xD2, 0xBF, 0xB0, 0x4D, 0xE7, 0xF0, 0x4D, 0x4A, 0xFE, 0xF3 + .byte 0x39, 0xB6, 0xBA, 0x87, 0x25, 0x27, 0xFE, 0x2C, 0x6C, 0x0C, 0x46, 0xD0, 0x94, 0x9A, 0x38, 0xF5 + .byte 0x53, 0x43, 0xFC, 0xC5, 0xC6, 0xCF, 0x85, 0x76, 0x1D, 0x6D, 0x67, 0x6A, 0xB7, 0x65, 0x5D, 0xF0 + .byte 0x1C, 0x18, 0x78, 0x41, 0x3F, 0x77, 0x6E, 0xAB, 0x84, 0xB4, 0x7C, 0x18, 0x4E, 0xB4, 0x0E, 0xA1 + .byte 0xF8, 0x0A, 0x67, 0xBE, 0xDA, 0xED, 0x34, 0xF7, 0x5A, 0x9B, 0x62, 0x12, 0x01, 0xC0, 0x03, 0x1D + .byte 0xD8, 0x7C, 0x5E, 0x18, 0xF3, 0xCD, 0xC4, 0x77, 0x81, 0x40, 0x8F, 0xD0, 0xF5, 0x9E, 0x72, 0xEE + .byte 0xA8, 0xDA, 0xAC, 0x83, 0xC7, 0xE0, 0x7A, 0x22, 0x7C, 0xDC, 0x35, 0x7D, 0x9D, 0x39, 0x9A, 0x75 + .byte 0xB5, 0xF9, 0x8D, 0xA8, 0xC6, 0x52, 0x20, 0x48, 0x93, 0xB0, 0x18, 0x89, 0x4E, 0x8B, 0x77, 0xF7 + .byte 0x65, 0x23, 0x7A, 0x2D, 0x03, 0xF5, 0x4F, 0x7F, 0xD2, 0x85, 0xFD, 0x6F, 0xBE, 0x97, 0xE4, 0x73 + .byte 0x91, 0x72, 0x1C, 0x58, 0xC4, 0x3D, 0xA1, 0x58, 0xED, 0xBA, 0xE1, 0x3C, 0x45, 0x58, 0x33, 0xAA + .byte 0x7B, 0xAE, 0xD7, 0x7F, 0xA3, 0x27, 0xFF, 0x75, 0xAC, 0xFC, 0xE4, 0x6B, 0x94, 0xC9, 0xDE, 0x25 + .byte 0x3C, 0xFB, 0x7E, 0x01, 0x38, 0x1F, 0x59, 0x26, 0xDA, 0x3A, 0x63, 0x1F, 0x92, 0x96, 0xC9, 0x0E + .byte 0x45, 0xA1, 0x8D, 0xE8, 0xC8, 0x8C, 0x5D, 0x75, 0x88, 0x42, 0xE0, 0x1C, 0x0B, 0xBF, 0x42, 0x48 + .byte 0xBA, 0xC1, 0x49, 0xF3, 0xE1, 0xA2, 0x1A, 0xBB, 0xDD, 0x7D, 0xDA, 0x6F, 0x13, 0xA4, 0x7D, 0x58 + .byte 0x45, 0x0B, 0x41, 0x0E, 0x97, 0x9F, 0x83, 0x20, 0xE1, 0x64, 0x3D, 0xED, 0x23, 0x7F, 0x35, 0xDE + .byte 0x40, 0x7E, 0xD1, 0x22, 0x21, 0xEB, 0xDD, 0xFE, 0x68, 0xB8, 0x6E, 0x7C, 0x5C, 0xEC, 0xD5, 0xA2 + .byte 0xF7, 0x17, 0xB0, 0x8F, 0xB6, 0x34, 0xAF, 0x97, 0x98, 0xED, 0x85, 0xBC, 0x6C, 0xBA, 0x9A, 0xAD + .byte 0x39, 0x6C, 0xCF, 0x5A, 0x57, 0xAD, 0x59, 0xC0, 0x65, 0xC7, 0x3D, 0xC2, 0xB4, 0x13, 0x64, 0xAC + .byte 0x2A, 0x15, 0x3B, 0xE0, 0x4A, 0xEB, 0x78, 0xE3, 0xD8, 0xFD, 0x9F, 0x45, 0xB8, 0x39, 0xF3, 0xF1 + .byte 0xA5, 0xC3, 0x4C, 0xFD, 0x70, 0xA5, 0xBE, 0xD6, 0x6D, 0xFC, 0x98, 0x22, 0x0F, 0xFD, 0xCE, 0x3A + .byte 0x13, 0x0A, 0x1A, 0x5D, 0xF5, 0x93, 0x40, 0xCE, 0x90, 0xDF, 0x14, 0x49, 0x19, 0x07, 0x3A, 0xBF + .byte 0xCA, 0x87, 0xBD, 0x3A, 0x2D, 0x7B, 0x11, 0x9A, 0x78, 0xA9, 0xBD, 0x87, 0xA7, 0x8B, 0xC1, 0xBA + .byte 0x95, 0xDC, 0x18, 0x8B, 0x6F, 0x58, 0x5A, 0x00, 0x38, 0x6E, 0x49, 0x52, 0x75, 0x84, 0x11, 0x40 + .byte 0x0B, 0xCF, 0x7A, 0x38, 0x4B, 0x8C, 0xD3, 0xC3, 0x36, 0x90, 0x4B, 0xDD, 0x1C, 0x0D, 0x98, 0xB2 + .byte 0xE9, 0xB0, 0x3E, 0x59, 0x09, 0x98, 0x5A, 0x42, 0x07, 0xA3, 0x94, 0x7D, 0x28, 0xA6, 0xBD, 0x33 + .byte 0x76, 0x37, 0x6C, 0xC1, 0xC4, 0x40, 0x84, 0xFA, 0xD1, 0xD0, 0xD7, 0xED, 0xDD, 0x6F, 0xA0, 0xC6 + .byte 0x20, 0xDE, 0x20, 0x2A, 0x77, 0x7A, 0x6C, 0x7F, 0x1E, 0x01, 0xFC, 0x46, 0xA8, 0xB9, 0x7A, 0x1E + .byte 0xF1, 0xE7, 0xE0, 0xB5, 0x27, 0x65, 0xAF, 0xF8, 0x35, 0x87, 0xE6, 0x12, 0xF7, 0x86, 0xD9, 0x17 + .byte 0x65, 0xFA, 0x41, 0xDD, 0x74, 0xAE, 0x5C, 0x92, 0xB0, 0x59, 0xD9, 0x59, 0x12, 0x53, 0x78, 0x03 + .byte 0x3A, 0x58, 0xB9, 0x62, 0xBD, 0x68, 0x5A, 0xF3, 0xF0, 0x41, 0x06, 0xE7, 0xC8, 0xE0, 0xFE, 0x2E + .byte 0xDA, 0x40, 0x0B, 0x4E, 0xEF, 0x68, 0xE1, 0x9F, 0xC1, 0xBA, 0xF8, 0xD4, 0x0E, 0x70, 0xD8, 0x49 + .byte 0xC9, 0x91, 0xAB, 0x87, 0xFA, 0x06, 0x7A, 0xEA, 0x48, 0x81, 0xD1, 0x10, 0x61, 0xD0, 0x3E, 0x3B + .byte 0x11, 0x4A, 0x8A, 0x00, 0xB3, 0x6C, 0xA0, 0x75, 0x27, 0x99, 0x49, 0x36, 0x09, 0x21, 0x7F, 0xD3 + .byte 0xB3, 0x2B, 0x5A, 0xAE, 0x32, 0xD5, 0x98, 0x7A, 0x56, 0x6A, 0x8B, 0xB7, 0x3B, 0xC9, 0xF3, 0x4C + .byte 0x14, 0x7E, 0x4D, 0xC7, 0xEB, 0xED, 0x3C, 0x12, 0x86, 0x86, 0x48, 0x90, 0xA7, 0xC8, 0x63, 0x5B + .byte 0xF4, 0xBE, 0x09, 0x26, 0x93, 0xA2, 0xA1, 0xEA, 0x0D, 0x2C, 0xA1, 0x48, 0xF6, 0x95, 0x94, 0x0B + .byte 0x14, 0xE1, 0xD2, 0xFF, 0xCF, 0x0F, 0x11, 0x55, 0x95, 0x5A, 0xE6, 0x3D, 0x23, 0x49, 0x98, 0x17 + .byte 0x08, 0xA2, 0x3E, 0x9B, 0x45, 0xE0, 0x85, 0x52, 0x0D, 0x27, 0x9A, 0x03, 0xBD, 0x2F, 0x0E, 0xD1 + .byte 0x11, 0xE1, 0xD0, 0xE0, 0xF0, 0xE2, 0x35, 0x86, 0x3C, 0x1B, 0xC3, 0x5F, 0x65, 0x5C, 0x77, 0x6E + .byte 0xFF, 0xB5, 0x09, 0x44, 0x96, 0x8F, 0x96, 0xA3, 0xB7, 0x31, 0xA7, 0x74, 0x60, 0xB6, 0x45, 0x71 + .byte 0x97, 0x16, 0x51, 0x88, 0xF8, 0x87, 0x0E, 0x35, 0xA3, 0xD2, 0x95, 0x09, 0x2F, 0x0C, 0x77, 0x2E + .byte 0xC2, 0x81, 0x73, 0x59, 0x10, 0x09, 0xFC, 0xC7, 0x3A, 0xA3, 0x3C, 0x9B, 0x59, 0x82, 0x0C, 0xF1 + .byte 0x98, 0x5D, 0x79, 0x91, 0xE5, 0x88, 0xC7, 0x88, 0x5B, 0x5C, 0x91, 0x8A, 0x69, 0x09, 0xB9, 0x2C + .byte 0x8A, 0x2C, 0x85, 0x9A, 0x35, 0x81, 0x62, 0x70, 0x25, 0x9F, 0x0B, 0x7F, 0x21, 0x18, 0x70, 0xBA + .byte 0x75, 0xEA, 0x4B, 0x5B, 0x72, 0x12, 0xE3, 0xCD, 0x6F, 0x75, 0x58, 0xD9, 0x7E, 0x11, 0x05, 0x09 + .byte 0x3D, 0x8B, 0xA3, 0x73, 0x0D, 0x06, 0xE4, 0x32, 0xA5, 0xEF, 0xB1, 0xC7, 0x07, 0x21, 0x81, 0x7D + .byte 0x0B, 0xCD, 0xD9, 0x7E, 0xE0, 0xBC, 0x4C, 0x4F, 0x32, 0xA4, 0x28, 0xB1, 0xB5, 0x2E, 0xBA, 0xF3 + .byte 0xB9, 0x5E, 0x66, 0xC6, 0x65, 0x4A, 0xF9, 0x0A, 0x3A, 0xAA, 0xD2, 0x42, 0xCC, 0x53, 0xC0, 0xD8 + .byte 0x20, 0x99, 0x56, 0x00, 0x56, 0xA2, 0x50, 0x88, 0x47, 0x79, 0x3A, 0xFD, 0xA7, 0xF4, 0xF0, 0x61 + .byte 0x52, 0x57, 0x28, 0xB7, 0xA1, 0x21, 0xC2, 0xDC, 0xCB, 0x94, 0x1F, 0x97, 0xE8, 0xE0, 0x70, 0x08 + .byte 0x79, 0xC6, 0x09, 0xD0, 0x69, 0x59, 0x59, 0xB1, 0xD2, 0x93, 0xAE, 0x7A, 0x87, 0x9E, 0xDB, 0xDA + .byte 0xF5, 0x03, 0x92, 0x97, 0x24, 0x55, 0x74, 0xF0, 0xEA, 0x93, 0x88, 0xD2, 0x74, 0xF8, 0xDB, 0xED + .byte 0xBF, 0xE5, 0xBD, 0x28, 0x3F, 0x17, 0xD9, 0x12, 0xAA, 0x88, 0x8C, 0x32, 0x27, 0x68, 0x0D, 0x1C + .byte 0x6C, 0x9F, 0xB4, 0x91, 0xF5, 0x29, 0x81, 0xDF, 0xBD, 0x0A, 0xB2, 0x31, 0x02, 0x8E, 0x1F, 0xC1 + .byte 0x73, 0xDC, 0xEA, 0xB3, 0xF4, 0xC4, 0xC5, 0x9E, 0x4C, 0x51, 0xD0, 0x73, 0xBA, 0xDE, 0x90, 0x26 + .byte 0x7E, 0x45, 0xB7, 0x73, 0x6E, 0x38, 0x53, 0x2C, 0x42, 0x06, 0x5D, 0x45, 0x94, 0x7C, 0x07, 0x08 + .byte 0x59, 0xF1, 0xBB, 0x4D, 0xB6, 0x80, 0xEC, 0x03, 0xD2, 0xBD, 0x77, 0x8C, 0x9B, 0x08, 0xB2, 0x19 + .byte 0x4D, 0x6A, 0x8D, 0xBC, 0xA2, 0xE0, 0xE8, 0xE5, 0xE6, 0x46, 0x2B, 0x7B, 0xC2, 0x32, 0x84, 0x1C + .byte 0x24, 0x3F, 0x6A, 0xDB, 0xC0, 0x56, 0xDE, 0x93, 0x13, 0x56, 0x20, 0xAE, 0x5E, 0xD3, 0xC8, 0xAB + .byte 0x3D, 0x55, 0x68, 0xE0, 0x35, 0x51, 0xC6, 0x1C, 0x97, 0xF1, 0x98, 0x5A, 0x24, 0x1C, 0x76, 0x49 + .byte 0x5C, 0xE0, 0x24, 0x1D, 0x37, 0x03, 0xB0, 0x4A, 0x59, 0xD1, 0xF9, 0xB7, 0xA4, 0xC1, 0x63, 0xE1 + .byte 0x17, 0xCB, 0xC1, 0x4D, 0x1D, 0x87, 0x69, 0xB4, 0x79, 0x02, 0x0E, 0x9D, 0x1E, 0x85, 0xE6, 0x7A + .byte 0x66, 0x0A, 0x98, 0x9E, 0x0E, 0x49, 0xE8, 0x67, 0x1A, 0xE2, 0x1F, 0xBE, 0xA3, 0x82, 0x9F, 0xBB + .byte 0x4E, 0x60, 0x08, 0x6B, 0xE8, 0x72, 0x20, 0x61, 0x74, 0x2F, 0xFE, 0x92, 0xB5, 0xE5, 0x0D, 0x1B + .byte 0xF0, 0xA6, 0xB9, 0xFE, 0xEF, 0xA2, 0x66, 0x09, 0x84, 0x85, 0xC7, 0x28, 0x08, 0x67, 0xE3, 0x57 + .byte 0xC8, 0xEC, 0xC2, 0xB0, 0x5E, 0xE3, 0x12, 0xD2, 0x12, 0x11, 0x65, 0xC7, 0xF6, 0x73, 0xE3, 0xE6 + .byte 0x19, 0x9D, 0xE5, 0x08, 0x40, 0x4B, 0x12, 0xC5, 0xD1, 0xDA, 0xED, 0xD9, 0x41, 0xD1, 0x30, 0x09 + .byte 0xBD, 0xF3, 0xBA, 0x1C, 0xD7, 0xCD, 0xEE, 0xE9, 0xDE, 0x54, 0xB1, 0xD4, 0xC7, 0x95, 0xBB, 0xE1 + .byte 0x33, 0xA1, 0xEA, 0x73, 0xED, 0xFC, 0x39, 0xBE, 0xD6, 0x26, 0x98, 0x18, 0xF8, 0xC9, 0x21, 0xB6 + .byte 0xBD, 0xDC, 0xD2, 0x94, 0xA9, 0xC1, 0x7E, 0x87, 0x16, 0x2F, 0x5C, 0xDD, 0xC5, 0x18, 0xBF, 0xF8 + .byte 0xBA, 0xA9, 0x6C, 0xA7, 0xA5, 0xA5, 0x66, 0x7C, 0xCC, 0xFE, 0x94, 0xC5, 0xC8, 0xB6, 0x7B, 0x85 + .byte 0x92, 0x4E, 0x19, 0x3C, 0x10, 0x97, 0xC4, 0x26, 0xC7, 0x21, 0x04, 0x8C, 0x39, 0xC3, 0x85, 0xF4 + .byte 0x6C, 0xF2, 0x9C, 0x12, 0x97, 0x02, 0x8E, 0x64, 0x01, 0x23, 0x29, 0xC9, 0xD9, 0xA5, 0x4E, 0x6C + .byte 0xF4, 0x68, 0xA8, 0x04, 0xFF, 0x6C, 0x2B, 0xC7, 0x8D, 0x2F, 0x54, 0xC7, 0xF2, 0xD9, 0xBB, 0x5F + .byte 0xCB, 0x57, 0x71, 0x63, 0x5A, 0x00, 0xC8, 0x5B, 0x24, 0xF2, 0x25, 0xFD, 0x97, 0x73, 0x69, 0x8C + .byte 0xDC, 0x11, 0x91, 0xDB, 0x7E, 0xBC, 0xA3, 0x0C, 0xEB, 0xF7, 0xD3, 0xDE, 0xD0, 0x8F, 0x3D, 0x9C + .byte 0xE7, 0xAF, 0x00, 0x41, 0xB0, 0xC8, 0x9C, 0xD4, 0xBA, 0xC1, 0xD1, 0x52, 0x35, 0x3B, 0xDE, 0x11 + .byte 0x4D, 0x6F, 0xED, 0xCB, 0x2C, 0x90, 0xD7, 0x17, 0x87, 0xAB, 0xF5, 0x58, 0x3A, 0x33, 0xF4, 0x21 + .byte 0xE2, 0xF4, 0x62, 0x92, 0xBD, 0xFF, 0x67, 0x77, 0xC1, 0x38, 0xC9, 0xF7, 0x74, 0xA8, 0x09, 0xC1 + .byte 0x18, 0xF7, 0x8D, 0x44, 0x87, 0x64, 0x5B, 0x0F, 0x10, 0x51, 0x67, 0x4A, 0x84, 0x5C, 0x6C, 0x67 + .byte 0x51, 0xCF, 0xFA, 0x0E, 0xCF, 0x61, 0x86, 0x91, 0x9A, 0x4F, 0x88, 0x0E, 0xF8, 0x92, 0xCF, 0x10 + .byte 0x89, 0x5D, 0x54, 0x10, 0xC1, 0xB0, 0x20, 0xD2, 0x02, 0x87, 0x1D, 0x86, 0xE3, 0x89, 0xEE, 0x35 + .byte 0x59, 0xE8, 0x43, 0x28, 0x49, 0xC9, 0xB9, 0xE4, 0x19, 0x42, 0xF2, 0x12, 0xD5, 0xC2, 0x22, 0x5E + .byte 0x1F, 0x77, 0x6F, 0xE1, 0x28, 0x8F, 0xB3, 0x2A, 0x16, 0xD1, 0xB0, 0xFA, 0x5A, 0x9E, 0x2F, 0xB4 + .byte 0x87, 0x73, 0xDD, 0xD1, 0x3D, 0x97, 0xB5, 0x56, 0xD9, 0xA8, 0x69, 0xAE, 0x6B, 0x8B, 0x0D, 0x8A + .byte 0x03, 0x7C, 0x6C, 0x2B, 0x0B, 0x20, 0x55, 0x22, 0xF1, 0x06, 0x1D, 0x4C, 0xA5, 0x4D, 0x00, 0x2C + .byte 0xC0, 0xDD, 0xFD, 0xFE, 0x74, 0xB3, 0x55, 0x4E, 0x5C, 0xBE, 0xFD, 0xC7, 0x49, 0x0A, 0x52, 0x4C + .byte 0x87, 0xBE, 0x78, 0x92, 0xDF, 0xCD, 0xB5, 0xD0, 0xD4, 0xD2, 0x1D, 0x79, 0x1F, 0x1E, 0xA5, 0xE0 + .byte 0xFB, 0xA3, 0xDE, 0x70, 0x57, 0x33, 0xBF, 0xB3, 0xF1, 0xBD, 0x7A, 0x3B, 0xC8, 0xCC, 0x88, 0x4F + .byte 0x8B, 0x00, 0xE2, 0x6A, 0xCE, 0x97, 0x3B, 0xA2, 0x69, 0x58, 0x1B, 0x89, 0x76, 0xC1, 0x69, 0x72 + .byte 0x65, 0x47, 0xE3, 0xBD, 0x7B, 0xA3, 0x70, 0x6C, 0x60, 0xEB, 0xA7, 0x28, 0xB8, 0x2F, 0x78, 0x44 + .byte 0x30, 0x5A, 0xAE, 0xFE, 0xF2, 0xEA, 0xA0, 0x5B, 0x43, 0xBC, 0xE5, 0xBA, 0x7D, 0x4E, 0x2D, 0xE3 + .byte 0x96, 0x10, 0xA0, 0x11, 0xB4, 0x10, 0x7E, 0x14, 0xFC, 0x26, 0x3D, 0xB4, 0x55, 0xB5, 0xF9, 0x86 + .byte 0x10, 0xA8, 0x84, 0x02, 0x92, 0x25, 0x5E, 0xD6, 0xE1, 0x43, 0x90, 0x5F, 0x92, 0xBD, 0x42, 0x28 + .byte 0xCE, 0xE2, 0x3A, 0x82, 0xF3, 0xB9, 0x97, 0xF0, 0xDF, 0xD4, 0xA5, 0x35, 0x8A, 0x9E, 0xBB, 0x9A + .byte 0x46, 0x3F, 0x9D, 0xD8, 0x64, 0xFB, 0xAE, 0x46, 0x3E, 0x3F, 0xA5, 0xD0, 0xFC, 0xE7, 0xF9, 0xCB + .byte 0xCA, 0x34, 0x4D, 0xBD, 0xED, 0xE4, 0xAE, 0xCC, 0xB9, 0x53, 0x02, 0x43, 0xF1, 0xBD, 0xDE, 0x37 + .byte 0xFD, 0x7B, 0x10, 0x62, 0x76, 0xBE, 0xA8, 0xB4, 0xFE, 0x4E, 0x85, 0xFA, 0x35, 0x7F, 0xC5, 0x00 + .byte 0xB3, 0x13, 0xBE, 0xA1, 0xF7, 0x6C, 0x6D, 0xB1, 0xBF, 0x70, 0xF4, 0xB0, 0x2D, 0xD2, 0xE7, 0x2B + .byte 0x4E, 0xF7, 0x8D, 0xC4, 0xB6, 0x36, 0x79, 0xB4, 0x84, 0xFF, 0xAF, 0xBA, 0x7E, 0x75, 0xBB, 0x31 + .byte 0x89, 0x79, 0xD2, 0x81, 0xE5, 0x40, 0x32, 0xA5, 0xB1, 0x26, 0x55, 0xDE, 0xF9, 0x3D, 0x0A, 0x47 + .byte 0x35, 0x98, 0x0C, 0xEC, 0xCE, 0x85, 0xA1, 0x53, 0x85, 0x51, 0x0E, 0x03, 0xC6, 0xC9, 0x35, 0x50 + .byte 0x43, 0x08, 0xD1, 0x29, 0x49, 0x03, 0xCE, 0xFA, 0x2A, 0x24, 0xD9, 0x24, 0x61, 0xE3, 0x6C, 0x97 + .byte 0x7B, 0x78, 0x83, 0x4A, 0xFE, 0x24, 0x9E, 0x83, 0x75, 0xAD, 0x86, 0x3C, 0x77, 0xBC, 0x8C, 0xBA + .byte 0xC4, 0x5D, 0xE4, 0x0D, 0x61, 0xB2, 0x07, 0x8B, 0xD6, 0xE0, 0xB0, 0x38, 0xC4, 0x1C, 0xCF, 0x40 + .byte 0x94, 0x52, 0x8B, 0x93, 0x76, 0x29, 0x17, 0xEC, 0xD7, 0x9E, 0x29, 0x4E, 0x5A, 0xB5, 0x09, 0x1E + .byte 0x13, 0xED, 0x2C, 0x74, 0x9F, 0x33, 0x00, 0x76, 0x14, 0xB1, 0xAE, 0xD9, 0xCD, 0x7D, 0x19, 0x62 + .byte 0xD0, 0xA4, 0xF5, 0x47, 0xCE, 0x0C, 0x33, 0xA5, 0xAA, 0x5C, 0xF3, 0x05, 0x12, 0xFD, 0x23, 0x25 + .byte 0xEA, 0x50, 0x9A, 0x8A, 0x84, 0x9B, 0x01, 0x98, 0x4C, 0xAF, 0x72, 0x1A, 0x2D, 0x8B, 0x7C, 0xFD + .byte 0x30, 0x72, 0x44, 0xFE, 0x7F, 0x78, 0xA3, 0x2A, 0xD4, 0x97, 0x2F, 0xE7, 0x94, 0x53, 0x0D, 0x7F + .byte 0xA4, 0xA8, 0x09, 0x28, 0x43, 0x0A, 0xC1, 0x90, 0xBA, 0x33, 0xAB, 0xE7, 0xBE, 0x28, 0xE5, 0xEE + .byte 0x9A, 0x29, 0xEC, 0x1A, 0xA1, 0x90, 0x45, 0x76, 0x27, 0x75, 0x5E, 0xBC, 0xC8, 0x6B, 0x3B, 0x6D + .byte 0x13, 0x45, 0x95, 0x57, 0x50, 0x56, 0xE8, 0x0A, 0x89, 0x93, 0xF2, 0x48, 0xBB, 0xD7, 0x37, 0x56 + .byte 0x01, 0x24, 0x70, 0xA3, 0xB4, 0xB5, 0x19, 0xDC, 0x2B, 0x78, 0x98, 0xF3, 0xE3, 0xD4, 0x60, 0xF6 + .byte 0x19, 0xF6, 0x4E, 0x69, 0x4C, 0x36, 0x74, 0xD6, 0xC9, 0x66, 0x1E, 0x85, 0x3E, 0x56, 0xDB, 0x3F + .byte 0x7A, 0x4B, 0xE2, 0x2F, 0x01, 0xFC, 0x0B, 0x2C, 0x74, 0xA4, 0x20, 0x58, 0x78, 0x81, 0x4E, 0x92 + .byte 0x78, 0x9D, 0xFC, 0xC4, 0xD3, 0x70, 0x9A, 0x9D, 0xD7, 0xB9, 0x22, 0x16, 0x0F, 0xFD, 0x55, 0x89 + .byte 0x49, 0x38, 0xB8, 0x4B, 0x35, 0xC4, 0x78, 0xA9, 0x69, 0x99, 0x01, 0xE1, 0x1A, 0x50, 0x74, 0x92 + .byte 0xED, 0x70, 0x57, 0xC1, 0xE1, 0xF2, 0x5E, 0xB9, 0xAB, 0x80, 0xCF, 0xBB, 0x7D, 0x25, 0x44, 0xC7 + .byte 0x5D, 0xFD, 0x12, 0x92, 0xC2, 0x8A, 0x3C, 0x2B, 0x23, 0x3E, 0x0D, 0x3E, 0x8F, 0x81, 0xD1, 0x7D + .byte 0xF2, 0x29, 0x3E, 0xD4, 0x1B, 0x9C, 0x8D, 0xC7, 0x1C, 0x5D, 0x82, 0x9A, 0x82, 0xC7, 0x61, 0xE0 + .byte 0xC5, 0x73, 0x73, 0x87, 0xFE, 0xAF, 0xB2, 0x22, 0xEE, 0xC0, 0x60, 0x7D, 0x41, 0x32, 0xFA, 0x34 + .byte 0x5B, 0x39, 0x08, 0x76, 0xD5, 0x95, 0x3E, 0xF2, 0xF2, 0xC0, 0x8C, 0x74, 0x87, 0xEE, 0x55, 0x4C + .byte 0x62, 0xC8, 0xD4, 0x60, 0x77, 0x87, 0x82, 0x66, 0x47, 0xE3, 0xE4, 0x89, 0x15, 0xDF, 0xBD, 0x71 + .byte 0x18, 0xC5, 0xE8, 0xED, 0x5A, 0x26, 0xE0, 0x4D, 0xE6, 0x6D, 0xC2, 0x6E, 0x5B, 0x17, 0xBB, 0xBD + .byte 0xDF, 0x8F, 0x1E, 0x57, 0x16, 0xA1, 0xBE, 0x5D, 0x84, 0xA2, 0xE7, 0x9A, 0x81, 0xA4, 0x0B, 0x99 + .byte 0x69, 0xF4, 0x87, 0xC4, 0x1A, 0x68, 0x11, 0x01, 0xD5, 0xD4, 0x6F, 0x30, 0xEC, 0x2B, 0xEE, 0xCB + .byte 0xBA, 0x0C, 0x23, 0xD1, 0xAD, 0xE1, 0x2F, 0x32, 0x84, 0x16, 0xCC, 0x05, 0xBA, 0xD8, 0x9F, 0x24 + .byte 0xCC, 0x27, 0xE8, 0xE7, 0x8F, 0xFA, 0xE8, 0x65, 0xCE, 0x58, 0x95, 0xBA, 0x83, 0x84, 0x86, 0x3E + .byte 0x90, 0xAA, 0x0F, 0x3E, 0x8C, 0x3F, 0x70, 0x10, 0x55, 0x3C, 0x16, 0x10, 0x15, 0xB6, 0x34, 0xE1 + .byte 0xDE, 0x1C, 0xC8, 0x6D, 0x16, 0xB1, 0xD3, 0xE5, 0x09, 0x68, 0xA0, 0x8D, 0xEC, 0x26, 0xCB, 0x7D + .byte 0xD1, 0xDB, 0xBB, 0x5D, 0x1A, 0x2C, 0x6E, 0x70, 0x69, 0x84, 0x80, 0x7E, 0x3B, 0xB4, 0x60, 0x19 + .byte 0xD1, 0x28, 0x87, 0xE8, 0xDA, 0x5A, 0xCD, 0xE3, 0xC3, 0x6E, 0x71, 0xB0, 0x94, 0x3C, 0x2E, 0x66 + .byte 0x18, 0xE9, 0xC3, 0x33, 0x16, 0x31, 0xA3, 0x7F, 0xB6, 0x24, 0xFE, 0xF2, 0xD9, 0x5E, 0x0B, 0xAA + .byte 0x87, 0x93, 0x92, 0x61, 0xED, 0x60, 0x45, 0xB1, 0xCE, 0xB6, 0x61, 0x63, 0xF3, 0x8F, 0xC9, 0x0B + .byte 0x79, 0x8D, 0x3E, 0x8F, 0xBE, 0xE2, 0x0F, 0x75, 0x07, 0x0D, 0x67, 0xE0, 0x6B, 0x73, 0x8A, 0xF2 + .byte 0x06, 0x1D, 0x54, 0xF4, 0x7D, 0x99, 0xA5, 0x4C, 0x4F, 0x07, 0xAF, 0x42, 0x96, 0x79, 0x4E, 0x10 + .byte 0x06, 0x8D, 0xA0, 0xC5, 0x6F, 0xAF, 0x3B, 0x77, 0xBD, 0xA2, 0x57, 0x29, 0x15, 0xE1, 0x1B, 0x1C + .byte 0xFF, 0x70, 0x10, 0x7D, 0x09, 0xB5, 0xC9, 0x58, 0xBC, 0x79, 0x9B, 0x53, 0xF3, 0xE9, 0x63, 0xF9 + .byte 0x76, 0x04, 0xBF, 0xE6, 0xB4, 0xFA, 0x5D, 0x71, 0x9D, 0xB4, 0x9A, 0xB3, 0x96, 0xB6, 0xCF, 0x96 + .byte 0x26, 0xDF, 0x13, 0x30, 0x94, 0xDD, 0x88, 0x51, 0x56, 0x24, 0xA4, 0x4A, 0x0D, 0x08, 0x44, 0x84 + .byte 0x0D, 0x03, 0x6B, 0xC1, 0xFE, 0xC8, 0x32, 0x9B, 0x7D, 0xCD, 0x4E, 0x14, 0x84, 0x1D, 0xAA, 0xAB + .byte 0xFD, 0xBE, 0xDB, 0x92, 0x9B, 0x64, 0xE3, 0xF2, 0x88, 0x88, 0x3C, 0x96, 0x91, 0x80, 0x1A, 0x9E + .byte 0x84, 0x86, 0x5F, 0x82, 0x4F, 0x92, 0x1E, 0xCC, 0x5F, 0x6D, 0xE1, 0xE4, 0x8B, 0x8C, 0x8F, 0x88 + .byte 0x4A, 0x6B, 0x1A, 0xE5, 0xCF, 0xFD, 0xD7, 0x58, 0x86, 0x14, 0xEE, 0x17, 0x94, 0x09, 0xB5, 0x19 + .byte 0x8F, 0x14, 0x9C, 0xDE, 0xA6, 0xBA, 0xAB, 0x06, 0x28, 0x8D, 0xEB, 0xB3, 0x19, 0x7A, 0x3B, 0x63 + .byte 0xE6, 0x56, 0x49, 0xB5, 0x54, 0x20, 0x0E, 0xDA, 0x34, 0xFC, 0xF1, 0xC9, 0x06, 0xA7, 0xE2, 0x96 + .byte 0xBB, 0x7E, 0x74, 0x62, 0x39, 0x20, 0x69, 0x61, 0xAD, 0x54, 0x14, 0xC6, 0xCF, 0x50, 0x2A, 0xB5 + .byte 0xA6, 0x73, 0x6B, 0xFA, 0x93, 0x79, 0xD5, 0xC8, 0x76, 0xC6, 0x92, 0x7C, 0x6D, 0x74, 0x12, 0x29 + .byte 0xF3, 0x87, 0x8C, 0x2D, 0xA7, 0xF5, 0x8E, 0x55, 0x49, 0xA3, 0x1B, 0x18, 0xF3, 0x45, 0xCD, 0x9A + .byte 0xB8, 0x38, 0x95, 0x4C, 0xB1, 0x6A, 0x15, 0x28, 0x31, 0xA7, 0xA5, 0x9F, 0x1C, 0xB7, 0xC9, 0x0F + .byte 0x3F, 0x55, 0x3C, 0xE7, 0x4A, 0xCB, 0x3C, 0x93, 0x6E, 0x57, 0xAC, 0x62, 0x9D, 0x7A, 0xFC, 0x56 + .byte 0xB2, 0x91, 0xA2, 0x64, 0xFC, 0xB7, 0x8C, 0x2D, 0x5F, 0x32, 0xCC, 0x7B, 0xE9, 0x95, 0x8B, 0x29 + .byte 0xEB, 0xC8, 0x10, 0x35, 0x93, 0x4D, 0xC9, 0x01, 0xA5, 0x75, 0x63, 0x42, 0xEF, 0x60, 0x99, 0xA2 + .byte 0xF1, 0x3C, 0x07, 0xED, 0xF4, 0x94, 0x1B, 0x53, 0xC6, 0xE8, 0xCE, 0xB0, 0x7E, 0x5A, 0xD9, 0x69 + .byte 0x22, 0xEA, 0x9E, 0xB5, 0x38, 0x68, 0xB6, 0xDD, 0xDE, 0x1A, 0x20, 0xCE, 0x7A, 0xB9, 0x70, 0x6C + .byte 0xF5, 0x78, 0x5A, 0xE9, 0x0C, 0x75, 0x3D, 0xD2, 0x5D, 0x0C, 0x83, 0xDC, 0x66, 0x5D, 0x45, 0x88 + .byte 0x47, 0xE4, 0x3D, 0x80, 0x4C, 0xF4, 0x5D, 0x2A, 0x0E, 0x7E, 0xF8, 0x89, 0x38, 0x69, 0xF6, 0x2E + .byte 0xE1, 0x50, 0x18, 0xED, 0xC6, 0x55, 0xC0, 0x24, 0x61, 0x43, 0x00, 0xC7, 0xA0, 0x45, 0x50, 0xE8 + .byte 0x2A, 0x8D, 0x69, 0x76, 0x81, 0xC7, 0xA1, 0x90, 0x45, 0x9A, 0x1A, 0x7E, 0x04, 0x10, 0xAC, 0xE5 + .byte 0x61, 0xC5, 0xD3, 0x27, 0x1B, 0x94, 0x4C, 0x7C, 0xD8, 0x4C, 0x44, 0x79, 0x92, 0x94, 0x61, 0xBC + .byte 0x22, 0xCA, 0x33, 0xA3, 0x92, 0xD5, 0x34, 0xD7, 0x6F, 0x4F, 0x55, 0x73, 0x5F, 0x02, 0x59, 0xC1 + .byte 0xC7, 0x2D, 0xE9, 0xE2, 0xC1, 0x35, 0x5F, 0x99, 0x82, 0xA4, 0x12, 0x14, 0x39, 0x74, 0xD1, 0x5B + .byte 0x3F, 0x05, 0xFF, 0xD1, 0xDA, 0x33, 0xA9, 0x4A, 0x82, 0xFF, 0xBE, 0xE2, 0x02, 0x18, 0xA4, 0xCA + .byte 0x45, 0x8D, 0xAD, 0x07, 0xC2, 0x0C, 0xA0, 0x45, 0xB1, 0xB3, 0x59, 0xEA, 0x28, 0x2B, 0x45, 0x67 + .byte 0x31, 0x44, 0x39, 0x0C, 0x78, 0xE3, 0x57, 0xFB, 0xE2, 0x15, 0xDE, 0xE4, 0x2E, 0x82, 0xAE, 0x74 + .byte 0x0F, 0x5B, 0x7B, 0xD2, 0x68, 0x1C, 0x17, 0x19, 0xCF, 0x71, 0x04, 0xF8, 0x9D, 0x49, 0x60, 0xCE + .byte 0x8E, 0x99, 0xDA, 0x07, 0x7C, 0x31, 0x02, 0x5F, 0x47, 0xE1, 0x43, 0x75, 0x63, 0xF2, 0xE9, 0x72 + .byte 0x4D, 0x65, 0x44, 0xB6, 0x81, 0x5C, 0xCF, 0x51, 0xCD, 0xD3, 0x49, 0x6A, 0x1D, 0xA9, 0x39, 0xAC + .byte 0x43, 0x13, 0xB3, 0xC0, 0x45, 0xB6, 0x1F, 0x8D, 0x97, 0x63, 0x03, 0xFB, 0x55, 0xED, 0x6D, 0xA3 + .byte 0x52, 0xB2, 0x59, 0xD3, 0x0F, 0x29, 0x24, 0xDC, 0xFD, 0x6E, 0x47, 0x1B, 0x18, 0x80, 0xC7, 0x5B + .byte 0x94, 0x7B, 0x1C, 0xDA, 0x32, 0x3C, 0x67, 0xCA, 0x9F, 0x6A, 0xC5, 0xF5, 0x58, 0x33, 0x99, 0xAA + .byte 0xE6, 0xF3, 0x7E, 0xF5, 0x1C, 0xA3, 0xD2, 0x1A, 0x11, 0x1A, 0x35, 0x29, 0x9B, 0xFD, 0x85, 0x30 + .byte 0x78, 0xA2, 0x0A, 0xAB, 0xDE, 0x72, 0x76, 0x7E, 0xDD, 0x3B, 0x74, 0x35, 0x6F, 0x0D, 0xDF, 0x55 + .byte 0x00, 0x5D, 0x4B, 0x1D, 0x00, 0x1E, 0x37, 0x12, 0x38, 0x6D, 0x3C, 0xD3, 0x6A, 0xC2, 0x03, 0xE3 + .byte 0x64, 0x0E, 0x8E, 0x43, 0x80, 0x05, 0xC1, 0x5D, 0x40, 0x36, 0x93, 0xB0, 0x43, 0x73, 0x06, 0x44 + .byte 0xD1, 0x52, 0x61, 0xD2, 0x70, 0x99, 0xE4, 0xA8, 0x06, 0x21, 0x7C, 0x71, 0xE3, 0x80, 0x54, 0x48 + .byte 0x8E, 0xE3, 0x8B, 0x0F, 0xE8, 0x4D, 0x6D, 0x29, 0x83, 0x00, 0xD9, 0xC6, 0x73, 0xE0, 0x0B, 0x45 + .byte 0x32, 0x6D, 0x17, 0xA2, 0x06, 0xFB, 0x4B, 0x0D, 0x1D, 0xC7, 0x7E, 0x00, 0x48, 0xD2, 0x48, 0xD6 + .byte 0xB6, 0xD3, 0xE5, 0x9E, 0x21, 0x52, 0xC7, 0xA4, 0x52, 0xA1, 0x6B, 0xC6, 0x81, 0x76, 0x0B, 0xB3 + .byte 0xE3, 0x22, 0x56, 0xEA, 0x1E, 0xA1, 0xF8, 0x3B, 0x69, 0x76, 0x3C, 0xB1, 0x49, 0x84, 0x87, 0xFF + .byte 0x58, 0x6D, 0x9E, 0x79, 0xBF, 0x65, 0x1E, 0x12, 0x07, 0x89, 0xD9, 0x88, 0xFF, 0xE4, 0x3C, 0xE3 + .byte 0x07, 0x92, 0xCD, 0x26, 0x33, 0xC5, 0x62, 0x9D, 0x3C, 0x9E, 0x4E, 0x86, 0x23, 0xD6, 0x86, 0x7C + .byte 0x43, 0x24, 0xF6, 0x02, 0x8A, 0x15, 0x15, 0x91, 0x9E, 0xEE, 0x19, 0x9E, 0xD3, 0x56, 0x81, 0xDB + .byte 0xE8, 0x4F, 0x01, 0x1C, 0x14, 0x64, 0xB9, 0x51, 0x03, 0x07, 0xD7, 0x27, 0xDD, 0x5D, 0xA4, 0x21 + .byte 0x82, 0x9A, 0x24, 0x0C, 0xAF, 0x39, 0x9D, 0x4E, 0x28, 0xB7, 0xEC, 0xFB, 0x0D, 0x6D, 0xD6, 0xF6 + .byte 0xBC, 0xD8, 0x12, 0xD1, 0x3C, 0xCB, 0x23, 0x40, 0xD3, 0xFB, 0x67, 0xB1, 0x58, 0x0B, 0xD2, 0xDA + .byte 0xA6, 0xF6, 0xE7, 0x56, 0x30, 0x85, 0xA4, 0x58, 0x3C, 0x90, 0x54, 0x4A, 0xFE, 0x2A, 0x41, 0xBA + .byte 0x03, 0x53, 0x8C, 0x3F, 0x1F, 0xAF, 0x7F, 0xF2, 0xAA, 0xE7, 0xA3, 0x03, 0xF2, 0x76, 0xDE, 0x98 + .byte 0x6C, 0xC6, 0xEE, 0x9D, 0x4B, 0x93, 0xF5, 0x88, 0x23, 0x49, 0xD2, 0x22, 0x74, 0x14, 0xDD, 0x77 + .byte 0x67, 0x69, 0xB7, 0x86, 0x19, 0x37, 0x78, 0xC4, 0x1E, 0x1C, 0xC8, 0x11, 0x92, 0xA7, 0xAA, 0xFF + .byte 0x6D, 0x99, 0x9D, 0xB8, 0x2C, 0x93, 0x40, 0x50, 0xDC, 0x13, 0x72, 0x51, 0x27, 0x4F, 0xC8, 0x8F + .byte 0xB8, 0x80, 0x15, 0xD2, 0xB7, 0x8E, 0x97, 0xD6, 0xAB, 0x5F, 0xE7, 0x3E, 0x06, 0x91, 0x3E, 0x74 + .byte 0x2A, 0xDB, 0x2D, 0x57, 0x6E, 0x6D, 0xA7, 0x4B, 0x81, 0x19, 0x9C, 0xA9, 0x68, 0x65, 0x38, 0x21 + .byte 0xE6, 0x4E, 0xF4, 0x9D, 0xDD, 0x8B, 0x74, 0x89, 0xEB, 0x5C, 0xC7, 0xF2, 0xED, 0x05, 0x66, 0x18 + .byte 0xE1, 0x93, 0x6F, 0x4F, 0x01, 0x17, 0x9A, 0x83, 0x30, 0x37, 0x2D, 0x99, 0x9C, 0x66, 0xBB, 0x83 + .byte 0xB4, 0xAF, 0x21, 0x92, 0x3B, 0x95, 0x1B, 0x26, 0xF1, 0xE3, 0x19, 0xDF, 0xE8, 0x7F, 0xF8, 0xC9 + .byte 0x13, 0x68, 0x19, 0x15, 0x7F, 0xB3, 0x98, 0xB0, 0xEB, 0xC6, 0x49, 0x88, 0x2C, 0x05, 0x0B, 0xE1 + .byte 0xB4, 0x2C, 0x73, 0xF0, 0xC1, 0x8F, 0x17, 0xB3, 0x72, 0x30, 0x93, 0x5B, 0xAF, 0x8B, 0x25, 0xC3 + .byte 0xF3, 0x3E, 0xD8, 0x73, 0xF2, 0x71, 0x23, 0xDD, 0x37, 0x6C, 0x65, 0x64, 0x72, 0x70, 0x45, 0x26 + .byte 0x9C, 0xB9, 0x17, 0x5E, 0x48, 0x2E, 0x12, 0xBB, 0x5E, 0xA5, 0x17, 0x0E, 0x30, 0x3C, 0xD1, 0x24 + .byte 0x7B, 0xAA, 0x97, 0x6D, 0x1B, 0xBA, 0x4A, 0x53, 0x27, 0xB0, 0xB7, 0x99, 0x21, 0xFD, 0xC0, 0xBE + .byte 0xB6, 0xD8, 0x1C, 0xFF, 0x06, 0x2E, 0xBB, 0x64, 0xD3, 0xD2, 0x72, 0x04, 0x0F, 0x44, 0x28, 0x8A + .byte 0xEE, 0xC0, 0xF7, 0x0A, 0x7B, 0x42, 0x5E, 0xA3, 0xF3, 0x16, 0x3D, 0x14, 0x13, 0xFD, 0xD2, 0xC9 + .byte 0xD6, 0xEF, 0xC9, 0xDC, 0x1E, 0x84, 0x40, 0xF2, 0x57, 0xB3, 0xF6, 0x66, 0xF7, 0x1F, 0xF0, 0xE6 + .byte 0xE0, 0xE8, 0xF1, 0x5B, 0x2B, 0x4F, 0xFE, 0x1E, 0x65, 0x3B, 0x33, 0x78, 0x39, 0x06, 0x42, 0x0F + .byte 0xF6, 0x0B, 0xEC, 0x14, 0x90, 0x2C, 0x07, 0xE7, 0xE0, 0xFE, 0x4D, 0xD8, 0x1D, 0x3E, 0xBE, 0xFE + .byte 0x27, 0xB0, 0x59, 0x52, 0xFF, 0x58, 0x71, 0x65, 0x94, 0xA5, 0xDD, 0xCD, 0xAC, 0x20, 0xDD, 0xA2 + .byte 0x2C, 0xC9, 0xB7, 0xBC, 0xF6, 0xBE, 0xA4, 0xD7, 0xBC, 0xF1, 0xAF, 0xDA, 0x30, 0x6E, 0xD8, 0x57 + .byte 0x1E, 0x32, 0xAA, 0x1E, 0x8A, 0x1B, 0x83, 0x1E, 0xC1, 0x61, 0xEC, 0x6D, 0x81, 0xCA, 0x0F, 0xAD + .byte 0x94, 0xC6, 0x6A, 0x8B, 0x85, 0x0E, 0x62, 0x42, 0x00, 0x12, 0x1C, 0x30, 0x80, 0xF5, 0x88, 0x9F + .byte 0x27, 0x32, 0xBD, 0xB1, 0x4E, 0x40, 0xD0, 0x0F, 0xA1, 0xBC, 0x7C, 0x23, 0x87, 0x8C, 0xD1, 0x1B + .byte 0x53, 0x3B, 0xA6, 0xD8, 0x4A, 0x09, 0x1A, 0x4A, 0x1B, 0x37, 0x7B, 0x9B, 0x2C, 0x03, 0x3A, 0x53 + .byte 0x36, 0xF7, 0x05, 0x84, 0x38, 0xD5, 0x94, 0xD9, 0x92, 0x11, 0xFD, 0x19, 0x9D, 0xCE, 0x35, 0xF1 + .byte 0x0A, 0xDC, 0xCA, 0x54, 0xE5, 0xE5, 0x9F, 0x01, 0x1C, 0x1B, 0x9C, 0x49, 0x1E, 0xD7, 0x9D, 0x55 + .byte 0xCF, 0xA2, 0xD9, 0x07, 0x78, 0x6E, 0xE1, 0x0B, 0x7F, 0xDF, 0x25, 0x1C, 0xAD, 0x5A, 0x0E, 0xB7 + .byte 0x37, 0xD8, 0x0C, 0x1C, 0xBD, 0xAB, 0x1E, 0xDA, 0xC6, 0xBA, 0x23, 0xE5, 0x92, 0xC0, 0x3A, 0x61 + .byte 0x63, 0x14, 0x69, 0xDB, 0x82, 0x4B, 0xE6, 0x02, 0x2A, 0x0B, 0x1F, 0xD8, 0x66, 0x2D, 0x90, 0x9D + .byte 0x05, 0x9C, 0xBA, 0xC3, 0x48, 0xD8, 0x9D, 0x0E, 0x93, 0xC1, 0xF4, 0x25, 0x81, 0x2F, 0x87, 0xE5 + .byte 0x44, 0xF1, 0xC0, 0xC7, 0x3D, 0xA7, 0xC9, 0x68, 0xB3, 0xE8, 0x40, 0x19, 0x15, 0xD0, 0xB7, 0x1B + .byte 0x6C, 0x71, 0xDE, 0xB4, 0x4A, 0x7C, 0xC3, 0xDD, 0x3D, 0xB8, 0x03, 0xBF, 0xE8, 0x8A, 0xA4, 0x2C + .byte 0x7C, 0x64, 0xF3, 0xB9, 0x0C, 0xBD, 0x21, 0xBF, 0xA5, 0x62, 0xD8, 0xBB, 0x32, 0x8F, 0xD6, 0x9F + .byte 0x01, 0xB5, 0x54, 0x4B, 0x31, 0x18, 0x29, 0x6E, 0xD1, 0x2C, 0x2D, 0xB9, 0xB7, 0xD1, 0xE6, 0x34 + .byte 0x36, 0xDA, 0xED, 0x43, 0x97, 0x0F, 0x02, 0x3D, 0x72, 0xDB, 0xF8, 0xA5, 0x6B, 0xCF, 0x45, 0x6C + .byte 0x84, 0x99, 0xB8, 0xB5, 0xB2, 0xE2, 0x23, 0x84, 0x0E, 0x51, 0x3D, 0xC6, 0x23, 0x24, 0xFA, 0x5A + .byte 0xFE, 0xE8, 0x9D, 0x96, 0xF8, 0x9F, 0xD3, 0x6A, 0x7B, 0xCC, 0x0F, 0xE6, 0x9B, 0x54, 0x53, 0x1F + .byte 0xEE, 0x0C, 0xD5, 0xA1, 0xEE, 0xF9, 0x25, 0xFC, 0x4A, 0x63, 0xC3, 0x6E, 0x87, 0xBD, 0xC8, 0x86 + .byte 0xA6, 0x65, 0x1C, 0x9E, 0x05, 0xF0, 0x08, 0x81, 0xBC, 0x18, 0x67, 0x58, 0x6D, 0xBB, 0x77, 0x5B + .byte 0xC7, 0x4D, 0xFD, 0xB6, 0x46, 0x22, 0xB2, 0x91, 0x85, 0x76, 0x00, 0x0D, 0x34, 0xC8, 0x93, 0xDA + .byte 0x2E, 0xAF, 0x78, 0x34, 0x9F, 0x81, 0xB5, 0x5C, 0x9A, 0x1D, 0xB4, 0x07, 0xD9, 0x2C, 0x63, 0xA0 + .byte 0x79, 0x61, 0x56, 0xC0, 0x83, 0x09, 0x51, 0x09, 0x80, 0x52, 0x17, 0xB4, 0x1A, 0xAA, 0x8E, 0x49 + .byte 0x5A, 0x07, 0x7D, 0xFA, 0x89, 0x33, 0x56, 0x24, 0x50, 0x0A, 0x2C, 0x29, 0x36, 0x90, 0xCA, 0xB0 + .byte 0xF1, 0x21, 0x70, 0x74, 0x2B, 0xC2, 0x7E, 0xAB, 0x14, 0x95, 0x60, 0x2F, 0x40, 0xEF, 0x78, 0x9A + .byte 0xF7, 0xF6, 0x95, 0x81, 0x29, 0xEB, 0xA5, 0x79, 0xF6, 0xD1, 0xA3, 0x2D, 0x61, 0x6E, 0xDD, 0x52 + .byte 0x90, 0x4E, 0xC7, 0xBB, 0x11, 0x46, 0x67, 0x25, 0xDC, 0xC8, 0x55, 0x1C, 0xB7, 0xCD, 0xB7, 0xAE + .byte 0xC4, 0x4C, 0x2F, 0xED, 0x38, 0xD5, 0x67, 0x2E, 0xA6, 0x0A, 0x5B, 0x08, 0x79, 0x38, 0x5B, 0x09 + .byte 0x87, 0x23, 0xC4, 0x98, 0x69, 0x2C, 0xBE, 0x46, 0xF4, 0x13, 0x63, 0xAC, 0xE1, 0x1A, 0x5B, 0xA5 + .byte 0x67, 0x8A, 0x93, 0x9F, 0x60, 0xFA, 0xCD, 0x07, 0x04, 0x29, 0x0F, 0x7D, 0x62, 0x6B, 0x87, 0xE9 + .byte 0x8E, 0x4C, 0x82, 0xF8, 0x78, 0x40, 0x3F, 0x6D, 0x54, 0xA2, 0x19, 0x36, 0xBC, 0x74, 0xDC, 0x24 + .byte 0xFF, 0x6F, 0xC3, 0x5F, 0x69, 0x91, 0x66, 0x6E, 0xBB, 0x76, 0xEC, 0x1D, 0xE1, 0x73, 0x07, 0x70 + .byte 0xBF, 0x89, 0x69, 0x38, 0xCA, 0xA8, 0xA5, 0x1E, 0x4A, 0xBF, 0x55, 0x07, 0x34, 0x31, 0x2B, 0x34 + .byte 0xA0, 0xEF, 0x93, 0x0A, 0x81, 0xFA, 0x79, 0x3C, 0x71, 0x65, 0x5A, 0x52, 0xD9, 0x61, 0xC3, 0x99 + .byte 0xEB, 0x2C, 0xD1, 0xB5, 0xD5, 0x77, 0xD4, 0x20, 0x37, 0x29, 0x27, 0x6B, 0x5A, 0x53, 0x9F, 0xFB + .byte 0x43, 0x33, 0x06, 0xC4, 0x2D, 0x7F, 0x01, 0x9F, 0xE4, 0x5C, 0xF1, 0xBE, 0xBD, 0xB5, 0x57, 0xA9 + .byte 0xE2, 0x29, 0x5E, 0xB7, 0xA1, 0x32, 0xD7, 0xD8, 0x5C, 0xFF, 0x43, 0xB6, 0x53, 0xE3, 0xB2, 0x96 Index: tags/1.2/verify/lxp32/src/firmware/test019.asm =================================================================== --- tags/1.2/verify/lxp32/src/firmware/test019.asm (nonexistent) +++ tags/1.2/verify/lxp32/src/firmware/test019.asm (revision 10) @@ -0,0 +1,35 @@ +/* + * This test verifies non-returnable interrupt handling + * Note: "iret" is never called here + */ + + lc r100, 0x10000000 // test result output pointer + lcs r101, halt + lc r102, failure + lc r103, 0x20000000 // timer: number of pulses (0xFFFFFFFF - infinite) + lc r104, 0x20000004 // timer: delay between pulses (in cycles) + lcs r105, success + + lcs r32, 0 // counter + + lcs iv0, test_loop@1 // set IRF to mark the interrupt as non-returnable + mov cr, 1 // enable timer interrupt + sw r104, 100 // delay between interrupts + sw r103, 100 // generate 100 interrupts + hlt // wait for a non-returnable interrupt + +test_loop: + add r32, r32, 1 + cjmpuge r105, r32, 100 // success + hlt // wait for a non-returnable interrupt + +failure: + sw r100, 2 // should never reach here + jmp r101 // halt + +success: + sw r100, 1 // success + +halt: + hlt + jmp r101 // halt Index: tags/1.2/verify/lxp32/src/firmware/test020.asm =================================================================== --- tags/1.2/verify/lxp32/src/firmware/test020.asm (nonexistent) +++ tags/1.2/verify/lxp32/src/firmware/test020.asm (revision 10) @@ -0,0 +1,39 @@ +/* + * Check that there are no pipeline hazards + */ + + lc r100, 0x10000000 // test result output pointer + lcs r101, halt + lcs r102, failure + lcs r103, success + + add r0, 100, 50 // r0:=150 + add r1, r0, 3 // r1:=153, potential RAW hazard + mul r2, r1, 109 // r2:=16677, potential RAW hazard + mul r3, r2, r0 // r3:=2501550, potential RAW hazard + sub r4, r3, 15 // r4:=2501535, potential RAW hazard + + mul r5, 50, 117 // r2:=5850 + sub r5, 100, 9 // r2:=91, overwrites previous result, potential WAW hazard + + lc r6, 1800 + mul r7, r6, 49 // r7:=88200, potential RAW hazard + mov r6, 1 // r6:=1, potential WAR hazard + + lc r0, 2501535 + cjmpne r102, r4, r0 // failure + cjmpne r102, r5, 91 // failure + lcs r0, 88200 + cjmpne r102, r7, r0 // failure + jmp r103 // success + +failure: + sw r100, 2 + jmp r101 // halt + +success: + sw r100, 1 // success + +halt: + hlt + jmp r101 // halt Index: tags/1.2/verify/lxp32/src/make/sources.make =================================================================== --- tags/1.2/verify/lxp32/src/make/sources.make (nonexistent) +++ tags/1.2/verify/lxp32/src/make/sources.make (revision 10) @@ -0,0 +1,80 @@ +# CPU RTL + +LXP32_DIR=../../../../rtl +LXP32_RTL=$(LXP32_DIR)/lxp32_mul16x16.vhd\ + $(LXP32_DIR)/lxp32_mul_dsp.vhd\ + $(LXP32_DIR)/lxp32_mul_opt.vhd\ + $(LXP32_DIR)/lxp32_mul_seq.vhd\ + $(LXP32_DIR)/lxp32_compl.vhd\ + $(LXP32_DIR)/lxp32_divider.vhd\ + $(LXP32_DIR)/lxp32_shifter.vhd\ + $(LXP32_DIR)/lxp32_alu.vhd\ + $(LXP32_DIR)/lxp32_dbus.vhd\ + $(LXP32_DIR)/lxp32_execute.vhd\ + $(LXP32_DIR)/lxp32_decode.vhd\ + $(LXP32_DIR)/lxp32_ubuf.vhd\ + $(LXP32_DIR)/lxp32_fetch.vhd\ + $(LXP32_DIR)/lxp32_ram256x32.vhd\ + $(LXP32_DIR)/lxp32_interrupt_mux.vhd\ + $(LXP32_DIR)/lxp32_scratchpad.vhd\ + $(LXP32_DIR)/lxp32_cpu.vhd\ + $(LXP32_DIR)/lxp32u_top.vhd\ + $(LXP32_DIR)/lxp32_icache.vhd\ + $(LXP32_DIR)/lxp32c_top.vhd + +# Common package + +COMMON_PKG_DIR=../../../common_pkg +COMMON_SRC=$(COMMON_PKG_DIR)/common_pkg.vhd $(COMMON_PKG_DIR)/common_pkg_body.vhd + +# Platform RTL + +PLATFORM_DIR=../../src/platform +PLATFORM_RTL=$(PLATFORM_DIR)/generic_dpram.vhd\ + $(PLATFORM_DIR)/scrambler.vhd\ + $(PLATFORM_DIR)/dbus_monitor.vhd\ + $(PLATFORM_DIR)/program_ram.vhd\ + $(PLATFORM_DIR)/timer.vhd\ + $(PLATFORM_DIR)/coprocessor.vhd\ + $(PLATFORM_DIR)/intercon.vhd\ + $(PLATFORM_DIR)/ibus_adapter.vhd\ + $(PLATFORM_DIR)/platform.vhd + +# Testbench sources + +COMMON_PKG_DIR=../../../common_pkg +TB_DIR=../../src/tb +TB_SRC=$(TB_DIR)/tb_pkg.vhd\ + $(TB_DIR)/tb_pkg_body.vhd\ + $(TB_DIR)/monitor.vhd\ + $(TB_DIR)/tb.vhd + +TB_MOD=tb + +# Firmware + +FW_SRC_DIR=../../src/firmware +FIRMWARE=test001.ram\ + test002.ram\ + test003.ram\ + test004.ram\ + test005.ram\ + test006.ram\ + test007.ram\ + test008.ram\ + test009.ram\ + test010.ram\ + test011.ram\ + test012.ram\ + test013.ram\ + test014.ram\ + test015.ram\ + test016.ram\ + test017.ram\ + test018.ram\ + test019.ram\ + test020.ram + +# LXP32 assembler executable + +ASM=../../../../tools/bin/lxp32asm Index: tags/1.2/verify/lxp32/src/platform/coprocessor.vhd =================================================================== --- tags/1.2/verify/lxp32/src/platform/coprocessor.vhd (nonexistent) +++ tags/1.2/verify/lxp32/src/platform/coprocessor.vhd (revision 10) @@ -0,0 +1,97 @@ +--------------------------------------------------------------------- +-- Coprocessor +-- +-- Part of the LXP32 test platform +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- Performs a simple arithmetic operation, uses interrupt to wake +-- up the CPU. +-- +-- Note: regardless of whether this description is synthesizable, +-- it was designed exclusively for simulation purposes. +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity coprocessor is + port( + clk_i: in std_logic; + rst_i: in std_logic; + + wbs_cyc_i: in std_logic; + wbs_stb_i: in std_logic; + wbs_we_i: in std_logic; + wbs_sel_i: in std_logic_vector(3 downto 0); + wbs_ack_o: out std_logic; + wbs_adr_i: in std_logic_vector(27 downto 2); + wbs_dat_i: in std_logic_vector(31 downto 0); + wbs_dat_o: out std_logic_vector(31 downto 0); + + irq_o: out std_logic + ); +end entity; + +architecture rtl of coprocessor is + +signal value: unsigned(31 downto 0):=(others=>'0'); +signal result: unsigned(31 downto 0):=(others=>'0'); +signal cnt: integer range 0 to 5:=0; +signal irq: std_logic:='0'; + +begin + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' then + value<=(others=>'0'); + cnt<=0; + irq<='0'; + else + if cnt>0 then + cnt<=cnt-1; + end if; + + if cnt=1 then + irq<='1'; + else + irq<='0'; + end if; + + if wbs_cyc_i='1' and wbs_stb_i='1' and wbs_we_i='1' then + for i in wbs_sel_i'range loop + if wbs_sel_i(i)='1' then + if wbs_adr_i="00"&X"000000" then + value(i*8+7 downto i*8)<= + unsigned(wbs_dat_i(i*8+7 downto i*8)); + cnt<=5; + end if; + end if; + end loop; + end if; + end if; + end if; +end process; + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' then + result<=(others=>'0'); + else + result<=shift_left(value,1)+value; + end if; + end if; +end process; + +wbs_ack_o<=wbs_cyc_i and wbs_stb_i; +wbs_dat_o<=std_logic_vector(value) when wbs_adr_i="00"&X"000000" else + std_logic_vector(result) when wbs_adr_i="00"&X"000001" else + (others=>'-'); + +irq_o<=irq; + +end architecture; Index: tags/1.2/verify/lxp32/src/platform/dbus_monitor.vhd =================================================================== --- tags/1.2/verify/lxp32/src/platform/dbus_monitor.vhd (nonexistent) +++ tags/1.2/verify/lxp32/src/platform/dbus_monitor.vhd (revision 10) @@ -0,0 +1,117 @@ +--------------------------------------------------------------------- +-- DBUS monitor +-- +-- Part of the LXP32 test platform +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- Monitors LXP32 data bus transactions, optionally throttles them. +-- +-- Note: regardless of whether this description is synthesizable, +-- it was designed exclusively for simulation purposes. +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity dbus_monitor is + generic( + THROTTLE: boolean + ); + port( + clk_i: in std_logic; + rst_i: in std_logic; + + wbs_cyc_i: in std_logic; + wbs_stb_i: in std_logic; + wbs_we_i: in std_logic; + wbs_sel_i: in std_logic_vector(3 downto 0); + wbs_ack_o: out std_logic; + wbs_adr_i: in std_logic_vector(31 downto 2); + wbs_dat_i: in std_logic_vector(31 downto 0); + wbs_dat_o: out std_logic_vector(31 downto 0); + + wbm_cyc_o: out std_logic; + wbm_stb_o: out std_logic; + wbm_we_o: out std_logic; + wbm_sel_o: out std_logic_vector(3 downto 0); + wbm_ack_i: in std_logic; + wbm_adr_o: out std_logic_vector(31 downto 2); + wbm_dat_o: out std_logic_vector(31 downto 0); + wbm_dat_i: in std_logic_vector(31 downto 0) + ); +end entity; + +architecture rtl of dbus_monitor is + +signal prbs: std_logic; +signal cycle: std_logic:='0'; + +signal cyc_ff: std_logic:='0'; +signal ack_ff: std_logic:='0'; + +begin + +-- Manage throttling + +gen_throttling: if THROTTLE generate + throttle_inst: entity work.scrambler(rtl) + generic map(TAP1=>6,TAP2=>7) + port map(clk_i=>clk_i,rst_i=>rst_i,ce_i=>'1',d_o=>prbs); +end generate; + +gen_no_throttling: if not THROTTLE generate + prbs<='0'; +end generate; + +-- CPU interface + +wbs_ack_o<=wbm_ack_i; +wbs_dat_o<=wbm_dat_i when wbm_ack_i='1' else (others=>'-'); + +-- Interconnect interface + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' then + cycle<='0'; + elsif prbs='0' and wbs_cyc_i='1' then + cycle<='1'; + elsif wbs_cyc_i='0' then + cycle<='0'; + end if; + end if; +end process; + +wbm_cyc_o<=wbs_cyc_i and (not prbs or cycle); +wbm_stb_o<=wbs_stb_i and (not prbs or cycle); +wbm_we_o<=wbs_we_i; +wbm_sel_o<=wbs_sel_i; +wbm_adr_o<=wbs_adr_i; +wbm_dat_o<=wbs_dat_i; + +-- Check handshake correctness + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' then + cyc_ff<='0'; + ack_ff<='0'; + else + cyc_ff<=wbs_cyc_i; + ack_ff<=wbm_ack_i; + + assert wbm_ack_i='0' or (wbs_cyc_i and (not prbs or cycle))='1' + report "DBUS error: ACK asserted without CYC" + severity failure; + + assert not (wbs_cyc_i='0' and cyc_ff='1' and ack_ff/='1') + report "DBUS error: cycle terminated prematurely" + severity failure; + end if; + end if; +end process; + +end architecture; Index: tags/1.2/verify/lxp32/src/platform/generic_dpram.vhd =================================================================== --- tags/1.2/verify/lxp32/src/platform/generic_dpram.vhd (nonexistent) +++ tags/1.2/verify/lxp32/src/platform/generic_dpram.vhd (revision 10) @@ -0,0 +1,162 @@ +--------------------------------------------------------------------- +-- Generic FPGA memory block +-- +-- Copyright (c) 2015 by Alex I. Kuznetsov +-- +-- Portable description of a dual-port memory block with one write +-- port. +-- +-- Parameters: +-- * DATA_WIDTH: data port width +-- * ADDR_WIDTH: address port width +-- * SIZE: memory size +-- * MODE: read/write synchronization mode for port A +-- DONTCARE: choose the most efficient design +-- WR_FIRST: feed written value to the output +-- RD_FIRST: read old value +-- NOCHANGE: don't change output during write +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity generic_dpram is + generic( + DATA_WIDTH: integer; + ADDR_WIDTH: integer; + SIZE: integer; + MODE: string:="DONTCARE" + ); + port( + clka_i: in std_logic; + cea_i: in std_logic; + wea_i: in std_logic; + addra_i: in std_logic_vector(ADDR_WIDTH-1 downto 0); + da_i: in std_logic_vector(DATA_WIDTH-1 downto 0); + da_o: out std_logic_vector(DATA_WIDTH-1 downto 0); + + clkb_i: in std_logic; + ceb_i: in std_logic; + addrb_i: in std_logic_vector(ADDR_WIDTH-1 downto 0); + db_o: out std_logic_vector(DATA_WIDTH-1 downto 0) + ); +end entity; + +architecture rtl of generic_dpram is + +type ram_type is array(SIZE-1 downto 0) of std_logic_vector(DATA_WIDTH-1 downto 0); +signal ram: ram_type; + +attribute syn_ramstyle: string; +attribute syn_ramstyle of ram: signal is "no_rw_check"; +attribute ram_style: string; -- for Xilinx +attribute ram_style of ram: signal is "block"; + +begin + +-- Ensure that generics have valid values + +assert SIZE<=2**ADDR_WIDTH + report "SIZE must be less or equal than 2^ADDR_WIDTH" + severity failure; + +assert MODE="DONTCARE" or MODE="WR_FIRST" or MODE="RD_FIRST" or MODE="NOCHANGE" + report "Unrecognized MODE value (DONTCARE, WR_FIRST, RD_FIRST or NOCHANGE expected)" + severity failure; + +-- Port A (read/write) + +port_a_dont_care_gen: if MODE="DONTCARE" generate + process (clka_i) is + begin + if rising_edge(clka_i) then + if cea_i='1' then + if wea_i='1' then + ram(to_integer(unsigned(addra_i)))<=da_i; + da_o<=(others=>'-'); + else + if is_x(addra_i) then + da_o<=(others=>'X'); + else + da_o<=ram(to_integer(unsigned(addra_i))); + end if; + end if; + end if; + end if; + end process; +end generate; + +port_a_write_first_gen: if MODE="WR_FIRST" generate + process (clka_i) is + begin + if rising_edge(clka_i) then + if cea_i='1' then + if wea_i='1' then + ram(to_integer(unsigned(addra_i)))<=da_i; + da_o<=da_i; + else + if is_x(addra_i) then + da_o<=(others=>'X'); + else + da_o<=ram(to_integer(unsigned(addra_i))); + end if; + end if; + end if; + end if; + end process; +end generate; + +port_a_read_first_gen: if MODE="RD_FIRST" generate + process (clka_i) is + begin + if rising_edge(clka_i) then + if cea_i='1' then + if wea_i='1' then + ram(to_integer(unsigned(addra_i)))<=da_i; + end if; + if is_x(addra_i) then + da_o<=(others=>'X'); + else + da_o<=ram(to_integer(unsigned(addra_i))); + end if; + end if; + end if; + end process; +end generate; + +port_a_no_change_gen: if MODE="NOCHANGE" generate + process (clka_i) is + begin + if rising_edge(clka_i) then + if cea_i='1' then + if wea_i='1' then + ram(to_integer(unsigned(addra_i)))<=da_i; + else + if is_x(addra_i) then + da_o<=(others=>'X'); + else + da_o<=ram(to_integer(unsigned(addra_i))); + end if; + end if; + end if; + end if; + end process; +end generate; + +-- Port B (read only) + +process (clkb_i) is +begin + if rising_edge(clkb_i) then + if ceb_i='1' then + if is_x(addrb_i) then + db_o<=(others=>'X'); + else + db_o<=ram(to_integer(unsigned(addrb_i))); + end if; + end if; + end if; +end process; + +end architecture; Index: tags/1.2/verify/lxp32/src/platform/ibus_adapter.vhd =================================================================== --- tags/1.2/verify/lxp32/src/platform/ibus_adapter.vhd (nonexistent) +++ tags/1.2/verify/lxp32/src/platform/ibus_adapter.vhd (revision 10) @@ -0,0 +1,101 @@ +--------------------------------------------------------------------- +-- IBUS adapter +-- +-- Part of the LXP32 test platform +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- Converts the Low Latency Interface to WISHBONE registered +-- feedback protocol. +-- +-- Note: regardless of whether this description is synthesizable, +-- it was designed exclusively for simulation purposes. +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity ibus_adapter is + port( + clk_i: in std_logic; + rst_i: in std_logic; + + ibus_cyc_i: in std_logic; + ibus_stb_i: in std_logic; + ibus_cti_i: in std_logic_vector(2 downto 0); + ibus_bte_i: in std_logic_vector(1 downto 0); + ibus_ack_o: out std_logic; + ibus_adr_i: in std_logic_vector(29 downto 0); + ibus_dat_o: out std_logic_vector(31 downto 0); + + lli_re_o: out std_logic; + lli_adr_o: out std_logic_vector(29 downto 0); + lli_dat_i: in std_logic_vector(31 downto 0); + lli_busy_i: in std_logic + ); +end entity; + +architecture rtl of ibus_adapter is + +constant burst_delay: integer:=5; +signal burst_delay_cnt: integer:=0; +signal delay_burst: std_logic; + +signal re: std_logic; +signal requested: std_logic:='0'; +signal adr: unsigned(29 downto 0); +signal ack: std_logic; + +begin + +-- Insert burst delay + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' then + burst_delay_cnt<=0; + elsif ibus_cyc_i='0' then + burst_delay_cnt<=burst_delay; + elsif burst_delay_cnt/=0 then + burst_delay_cnt<=burst_delay_cnt-1; + end if; + end if; +end process; + +delay_burst<='1' when burst_delay_cnt/=0 else '0'; + +-- Generate ACK signal + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' then + requested<='0'; + elsif lli_busy_i='0' then + requested<=re; + end if; + end if; +end process; + +ack<=requested and not lli_busy_i; + +-- Generate LLI signals + +re<=(ibus_cyc_i and ibus_stb_i and not delay_burst) when ack='0' or + (ibus_cti_i="010" and ibus_bte_i="00") else '0'; + +adr<=unsigned(ibus_adr_i) when re='1' and ack='0' else + unsigned(ibus_adr_i)+1 when re='1' and ack='1' else + (others=>'-'); + +lli_re_o<=re; +lli_adr_o<=std_logic_vector(adr); + +-- Generate IBUS signals + +ibus_ack_o<=ack; +ibus_dat_o<=lli_dat_i when ack='1' else (others=>'-'); + +end architecture; Index: tags/1.2/verify/lxp32/src/platform/intercon.vhd =================================================================== --- tags/1.2/verify/lxp32/src/platform/intercon.vhd (nonexistent) +++ tags/1.2/verify/lxp32/src/platform/intercon.vhd (revision 10) @@ -0,0 +1,215 @@ +--------------------------------------------------------------------- +-- Simple WISHBONE interconnect +-- +-- Generated by wigen at 02/16/16 06:15:08 +-- +-- Configuration: +-- Number of masters: 2 +-- Number of slaves: 4 +-- Master address width: 32 +-- Slave address width: 28 +-- Port size: 32 +-- Port granularity: 8 +-- Entity name: intercon +-- Pipelined arbiter: no +-- Registered feedback: no +-- Unsafe slave decoder: no +-- +-- Command line: +-- wigen -e intercon 2 4 32 28 32 8 +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity intercon is + port( + clk_i: in std_logic; + rst_i: in std_logic; + + s0_cyc_i: in std_logic; + s0_stb_i: in std_logic; + s0_we_i: in std_logic; + s0_sel_i: in std_logic_vector(3 downto 0); + s0_ack_o: out std_logic; + s0_adr_i: in std_logic_vector(31 downto 2); + s0_dat_i: in std_logic_vector(31 downto 0); + s0_dat_o: out std_logic_vector(31 downto 0); + + s1_cyc_i: in std_logic; + s1_stb_i: in std_logic; + s1_we_i: in std_logic; + s1_sel_i: in std_logic_vector(3 downto 0); + s1_ack_o: out std_logic; + s1_adr_i: in std_logic_vector(31 downto 2); + s1_dat_i: in std_logic_vector(31 downto 0); + s1_dat_o: out std_logic_vector(31 downto 0); + + m0_cyc_o: out std_logic; + m0_stb_o: out std_logic; + m0_we_o: out std_logic; + m0_sel_o: out std_logic_vector(3 downto 0); + m0_ack_i: in std_logic; + m0_adr_o: out std_logic_vector(27 downto 2); + m0_dat_o: out std_logic_vector(31 downto 0); + m0_dat_i: in std_logic_vector(31 downto 0); + + m1_cyc_o: out std_logic; + m1_stb_o: out std_logic; + m1_we_o: out std_logic; + m1_sel_o: out std_logic_vector(3 downto 0); + m1_ack_i: in std_logic; + m1_adr_o: out std_logic_vector(27 downto 2); + m1_dat_o: out std_logic_vector(31 downto 0); + m1_dat_i: in std_logic_vector(31 downto 0); + + m2_cyc_o: out std_logic; + m2_stb_o: out std_logic; + m2_we_o: out std_logic; + m2_sel_o: out std_logic_vector(3 downto 0); + m2_ack_i: in std_logic; + m2_adr_o: out std_logic_vector(27 downto 2); + m2_dat_o: out std_logic_vector(31 downto 0); + m2_dat_i: in std_logic_vector(31 downto 0); + + m3_cyc_o: out std_logic; + m3_stb_o: out std_logic; + m3_we_o: out std_logic; + m3_sel_o: out std_logic_vector(3 downto 0); + m3_ack_i: in std_logic; + m3_adr_o: out std_logic_vector(27 downto 2); + m3_dat_o: out std_logic_vector(31 downto 0); + m3_dat_i: in std_logic_vector(31 downto 0) + ); +end entity; + +architecture rtl of intercon is + +signal request: std_logic_vector(1 downto 0); +signal grant_next: std_logic_vector(1 downto 0); +signal grant: std_logic_vector(1 downto 0); +signal grant_reg: std_logic_vector(1 downto 0):=(others=>'0'); + +signal select_slave: std_logic_vector(4 downto 0); + +signal cyc_mux: std_logic; +signal stb_mux: std_logic; +signal we_mux: std_logic; +signal sel_mux: std_logic_vector(3 downto 0); +signal adr_mux: std_logic_vector(31 downto 2); +signal wdata_mux: std_logic_vector(31 downto 0); + +signal ack_mux: std_logic; +signal rdata_mux: std_logic_vector(31 downto 0); + +begin + +-- ARBITER +-- Selects the active master. Masters with lower port numbers +-- have higher priority. Ongoing cycles are not interrupted. + +request<=s1_cyc_i&s0_cyc_i; + +grant_next<="01" when request(0)='1' else + "10" when request(1)='1' else + (others=>'0'); + +grant<=grant_reg when (request and grant_reg)/="00" else grant_next; + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' then + grant_reg<=(others=>'0'); + else + grant_reg<=grant; + end if; + end if; +end process; + +-- MASTER->SLAVE MUX + +cyc_mux<=(s0_cyc_i and grant(0)) or + (s1_cyc_i and grant(1)); + +stb_mux<=(s0_stb_i and grant(0)) or + (s1_stb_i and grant(1)); + +we_mux<=(s0_we_i and grant(0)) or + (s1_we_i and grant(1)); + +sel_mux_gen: for i in sel_mux'range generate + sel_mux(i)<=(s0_sel_i(i) and grant(0)) or + (s1_sel_i(i) and grant(1)); +end generate; + +adr_mux_gen: for i in adr_mux'range generate + adr_mux(i)<=(s0_adr_i(i) and grant(0)) or + (s1_adr_i(i) and grant(1)); +end generate; + +wdata_mux_gen: for i in wdata_mux'range generate + wdata_mux(i)<=(s0_dat_i(i) and grant(0)) or + (s1_dat_i(i) and grant(1)); +end generate; + +-- MASTER->SLAVE DEMUX + +select_slave<="00001" when adr_mux(31 downto 28)="0000" else + "00010" when adr_mux(31 downto 28)="0001" else + "00100" when adr_mux(31 downto 28)="0010" else + "01000" when adr_mux(31 downto 28)="0011" else + "10000"; -- fallback slave + +m0_cyc_o<=cyc_mux and select_slave(0); +m0_stb_o<=stb_mux and select_slave(0); +m0_we_o<=we_mux; +m0_sel_o<=sel_mux; +m0_adr_o<=adr_mux(m0_adr_o'range); +m0_dat_o<=wdata_mux; + +m1_cyc_o<=cyc_mux and select_slave(1); +m1_stb_o<=stb_mux and select_slave(1); +m1_we_o<=we_mux; +m1_sel_o<=sel_mux; +m1_adr_o<=adr_mux(m1_adr_o'range); +m1_dat_o<=wdata_mux; + +m2_cyc_o<=cyc_mux and select_slave(2); +m2_stb_o<=stb_mux and select_slave(2); +m2_we_o<=we_mux; +m2_sel_o<=sel_mux; +m2_adr_o<=adr_mux(m2_adr_o'range); +m2_dat_o<=wdata_mux; + +m3_cyc_o<=cyc_mux and select_slave(3); +m3_stb_o<=stb_mux and select_slave(3); +m3_we_o<=we_mux; +m3_sel_o<=sel_mux; +m3_adr_o<=adr_mux(m3_adr_o'range); +m3_dat_o<=wdata_mux; + +-- SLAVE->MASTER MUX + +ack_mux<=(m0_ack_i and select_slave(0)) or + (m1_ack_i and select_slave(1)) or + (m2_ack_i and select_slave(2)) or + (m3_ack_i and select_slave(3)) or + (cyc_mux and stb_mux and select_slave(4)); -- fallback slave + +rdata_mux_gen: for i in rdata_mux'range generate + rdata_mux(i)<=(m0_dat_i(i) and select_slave(0)) or + (m1_dat_i(i) and select_slave(1)) or + (m2_dat_i(i) and select_slave(2)) or + (m3_dat_i(i) and select_slave(3)); +end generate; + +-- SLAVE->MASTER DEMUX + +s0_ack_o<=ack_mux and grant(0); +s0_dat_o<=rdata_mux; + +s1_ack_o<=ack_mux and grant(1); +s1_dat_o<=rdata_mux; + +end architecture; Index: tags/1.2/verify/lxp32/src/platform/platform.vhd =================================================================== --- tags/1.2/verify/lxp32/src/platform/platform.vhd (nonexistent) +++ tags/1.2/verify/lxp32/src/platform/platform.vhd (revision 10) @@ -0,0 +1,356 @@ +--------------------------------------------------------------------- +-- LXP32 platform top-level design unit +-- +-- Part of the LXP32 test platform +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- A SoC-like simulation platform for the LXP32 CPU, containing +-- a few peripherals such as program RAM, timer and coprocessor. +-- +-- Note: regardless of whether this description is synthesizable, +-- it was designed exclusively for simulation purposes. +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity platform is + generic( + CPU_DBUS_RMW: boolean; + CPU_MUL_ARCH: string; + MODEL_LXP32C: boolean; + THROTTLE_DBUS: boolean; + THROTTLE_IBUS: boolean + ); + port( + clk_i: in std_logic; + rst_i: in std_logic; + cpu_rst_i: in std_logic; + + wbm_cyc_o: out std_logic; + wbm_stb_o: out std_logic; + wbm_we_o: out std_logic; + wbm_sel_o: out std_logic_vector(3 downto 0); + wbm_ack_i: in std_logic; + wbm_adr_o: out std_logic_vector(27 downto 2); + wbm_dat_o: out std_logic_vector(31 downto 0); + wbm_dat_i: in std_logic_vector(31 downto 0); + + wbs_cyc_i: in std_logic; + wbs_stb_i: in std_logic; + wbs_we_i: in std_logic; + wbs_sel_i: in std_logic_vector(3 downto 0); + wbs_ack_o: out std_logic; + wbs_adr_i: in std_logic_vector(31 downto 2); + wbs_dat_i: in std_logic_vector(31 downto 0); + wbs_dat_o: out std_logic_vector(31 downto 0); + + gp_io: inout std_logic_vector(31 downto 0) + ); +end entity; + +architecture rtl of platform is + +type wbm_type is record + cyc: std_logic; + stb: std_logic; + we: std_logic; + sel: std_logic_vector(3 downto 0); + ack: std_logic; + adr: std_logic_vector(31 downto 2); + wdata: std_logic_vector(31 downto 0); + rdata: std_logic_vector(31 downto 0); +end record; + +type wbs_type is record + cyc: std_logic; + stb: std_logic; + we: std_logic; + sel: std_logic_vector(3 downto 0); + ack: std_logic; + adr: std_logic_vector(27 downto 2); + wdata: std_logic_vector(31 downto 0); + rdata: std_logic_vector(31 downto 0); +end record; + +type ibus_type is record + cyc: std_logic; + stb: std_logic; + cti: std_logic_vector(2 downto 0); + bte: std_logic_vector(1 downto 0); + ack: std_logic; + adr: std_logic_vector(29 downto 0); + dat: std_logic_vector(31 downto 0); +end record; + +signal cpu_rst: std_logic; +signal cpu_irq: std_logic_vector(7 downto 0); +signal cpu_dbus: wbm_type; +signal cpu_ibus: ibus_type; + +signal lli_re: std_logic; +signal lli_adr: std_logic_vector(29 downto 0); +signal lli_dat: std_logic_vector(31 downto 0); +signal lli_busy: std_logic; + +signal monitor_dbus: wbm_type; + +signal ram_wb: wbs_type; + +signal timer_wb: wbs_type; +signal timer_elapsed: std_logic; + +signal coprocessor_wb: wbs_type; +signal coprocessor_irq: std_logic; + +begin + +-- Interconnect + +intercon_inst: entity work.intercon(rtl) + port map( + clk_i=>clk_i, + rst_i=>rst_i, + + s0_cyc_i=>wbs_cyc_i, + s0_stb_i=>wbs_stb_i, + s0_we_i=>wbs_we_i, + s0_sel_i=>wbs_sel_i, + s0_ack_o=>wbs_ack_o, + s0_adr_i=>wbs_adr_i, + s0_dat_i=>wbs_dat_i, + s0_dat_o=>wbs_dat_o, + + s1_cyc_i=>monitor_dbus.cyc, + s1_stb_i=>monitor_dbus.stb, + s1_we_i=>monitor_dbus.we, + s1_sel_i=>monitor_dbus.sel, + s1_ack_o=>monitor_dbus.ack, + s1_adr_i=>monitor_dbus.adr, + s1_dat_i=>monitor_dbus.wdata, + s1_dat_o=>monitor_dbus.rdata, + + m0_cyc_o=>ram_wb.cyc, + m0_stb_o=>ram_wb.stb, + m0_we_o=>ram_wb.we, + m0_sel_o=>ram_wb.sel, + m0_ack_i=>ram_wb.ack, + m0_adr_o=>ram_wb.adr, + m0_dat_o=>ram_wb.wdata, + m0_dat_i=>ram_wb.rdata, + + m1_cyc_o=>wbm_cyc_o, + m1_stb_o=>wbm_stb_o, + m1_we_o=>wbm_we_o, + m1_sel_o=>wbm_sel_o, + m1_ack_i=>wbm_ack_i, + m1_adr_o=>wbm_adr_o, + m1_dat_o=>wbm_dat_o, + m1_dat_i=>wbm_dat_i, + + m2_cyc_o=>timer_wb.cyc, + m2_stb_o=>timer_wb.stb, + m2_we_o=>timer_wb.we, + m2_sel_o=>timer_wb.sel, + m2_ack_i=>timer_wb.ack, + m2_adr_o=>timer_wb.adr, + m2_dat_o=>timer_wb.wdata, + m2_dat_i=>timer_wb.rdata, + + m3_cyc_o=>coprocessor_wb.cyc, + m3_stb_o=>coprocessor_wb.stb, + m3_we_o=>coprocessor_wb.we, + m3_sel_o=>coprocessor_wb.sel, + m3_ack_i=>coprocessor_wb.ack, + m3_adr_o=>coprocessor_wb.adr, + m3_dat_o=>coprocessor_wb.wdata, + m3_dat_i=>coprocessor_wb.rdata + ); + +-- CPU + +cpu_rst<=cpu_rst_i or rst_i; + +-- Note: we connect the timer IRQ to 2 CPU channels to test +-- handling of simultaneously arriving interrupt requests. + +cpu_irq<="00000"&coprocessor_irq&timer_elapsed&timer_elapsed; + +gen_lxp32u: if not MODEL_LXP32C generate + lxp32u_top_inst: entity work.lxp32u_top(rtl) + generic map( + DBUS_RMW=>CPU_DBUS_RMW, + DIVIDER_EN=>true, + MUL_ARCH=>CPU_MUL_ARCH, + START_ADDR=>(others=>'0') + ) + port map( + clk_i=>clk_i, + rst_i=>cpu_rst, + + lli_re_o=>lli_re, + lli_adr_o=>lli_adr, + lli_dat_i=>lli_dat, + lli_busy_i=>lli_busy, + + dbus_cyc_o=>cpu_dbus.cyc, + dbus_stb_o=>cpu_dbus.stb, + dbus_we_o=>cpu_dbus.we, + dbus_sel_o=>cpu_dbus.sel, + dbus_ack_i=>cpu_dbus.ack, + dbus_adr_o=>cpu_dbus.adr, + dbus_dat_o=>cpu_dbus.wdata, + dbus_dat_i=>cpu_dbus.rdata, + + irq_i=>cpu_irq + ); +end generate; + +gen_lxp32c: if MODEL_LXP32C generate + lxp32c_top_inst: entity work.lxp32c_top(rtl) + generic map( + DBUS_RMW=>CPU_DBUS_RMW, + DIVIDER_EN=>true, + IBUS_BURST_SIZE=>16, + IBUS_PREFETCH_SIZE=>32, + MUL_ARCH=>CPU_MUL_ARCH, + START_ADDR=>(others=>'0') + ) + port map( + clk_i=>clk_i, + rst_i=>cpu_rst, + + ibus_cyc_o=>cpu_ibus.cyc, + ibus_stb_o=>cpu_ibus.stb, + ibus_cti_o=>cpu_ibus.cti, + ibus_bte_o=>cpu_ibus.bte, + ibus_ack_i=>cpu_ibus.ack, + ibus_adr_o=>cpu_ibus.adr, + ibus_dat_i=>cpu_ibus.dat, + + dbus_cyc_o=>cpu_dbus.cyc, + dbus_stb_o=>cpu_dbus.stb, + dbus_we_o=>cpu_dbus.we, + dbus_sel_o=>cpu_dbus.sel, + dbus_ack_i=>cpu_dbus.ack, + dbus_adr_o=>cpu_dbus.adr, + dbus_dat_o=>cpu_dbus.wdata, + dbus_dat_i=>cpu_dbus.rdata, + + irq_i=>cpu_irq + ); + + ibus_adapter_inst: entity work.ibus_adapter(rtl) + port map( + clk_i=>clk_i, + rst_i=>rst_i, + + ibus_cyc_i=>cpu_ibus.cyc, + ibus_stb_i=>cpu_ibus.stb, + ibus_cti_i=>cpu_ibus.cti, + ibus_bte_i=>cpu_ibus.bte, + ibus_ack_o=>cpu_ibus.ack, + ibus_adr_i=>cpu_ibus.adr, + ibus_dat_o=>cpu_ibus.dat, + + lli_re_o=>lli_re, + lli_adr_o=>lli_adr, + lli_dat_i=>lli_dat, + lli_busy_i=>lli_busy + ); +end generate; + +-- DBUS monitor + +dbus_monitor_inst: entity work.dbus_monitor(rtl) + generic map( + THROTTLE=>THROTTLE_DBUS + ) + port map( + clk_i=>clk_i, + rst_i=>rst_i, + + wbs_cyc_i=>cpu_dbus.cyc, + wbs_stb_i=>cpu_dbus.stb, + wbs_we_i=>cpu_dbus.we, + wbs_sel_i=>cpu_dbus.sel, + wbs_ack_o=>cpu_dbus.ack, + wbs_adr_i=>cpu_dbus.adr, + wbs_dat_i=>cpu_dbus.wdata, + wbs_dat_o=>cpu_dbus.rdata, + + wbm_cyc_o=>monitor_dbus.cyc, + wbm_stb_o=>monitor_dbus.stb, + wbm_we_o=>monitor_dbus.we, + wbm_sel_o=>monitor_dbus.sel, + wbm_ack_i=>monitor_dbus.ack, + wbm_adr_o=>monitor_dbus.adr, + wbm_dat_o=>monitor_dbus.wdata, + wbm_dat_i=>monitor_dbus.rdata + ); + +-- Program RAM + +program_ram_inst: entity work.program_ram(rtl) + generic map( + THROTTLE=>THROTTLE_IBUS + ) + port map( + clk_i=>clk_i, + rst_i=>rst_i, + + wbs_cyc_i=>ram_wb.cyc, + wbs_stb_i=>ram_wb.stb, + wbs_we_i=>ram_wb.we, + wbs_sel_i=>ram_wb.sel, + wbs_ack_o=>ram_wb.ack, + wbs_adr_i=>ram_wb.adr, + wbs_dat_i=>ram_wb.wdata, + wbs_dat_o=>ram_wb.rdata, + + lli_re_i=>lli_re, + lli_adr_i=>lli_adr, + lli_dat_o=>lli_dat, + lli_busy_o=>lli_busy + ); + +-- Timer + +timer_inst: entity work.timer(rtl) + port map( + clk_i=>clk_i, + rst_i=>rst_i, + + wbs_cyc_i=>timer_wb.cyc, + wbs_stb_i=>timer_wb.stb, + wbs_we_i=>timer_wb.we, + wbs_sel_i=>timer_wb.sel, + wbs_ack_o=>timer_wb.ack, + wbs_adr_i=>timer_wb.adr, + wbs_dat_i=>timer_wb.wdata, + wbs_dat_o=>timer_wb.rdata, + + elapsed_o=>timer_elapsed + ); + +-- Coprocessor + +coprocessor_inst: entity work.coprocessor(rtl) + port map( + clk_i=>clk_i, + rst_i=>rst_i, + + wbs_cyc_i=>coprocessor_wb.cyc, + wbs_stb_i=>coprocessor_wb.stb, + wbs_we_i=>coprocessor_wb.we, + wbs_sel_i=>coprocessor_wb.sel, + wbs_ack_o=>coprocessor_wb.ack, + wbs_adr_i=>coprocessor_wb.adr, + wbs_dat_i=>coprocessor_wb.wdata, + wbs_dat_o=>coprocessor_wb.rdata, + + irq_o=>coprocessor_irq + ); + +end architecture; Index: tags/1.2/verify/lxp32/src/platform/program_ram.vhd =================================================================== --- tags/1.2/verify/lxp32/src/platform/program_ram.vhd (nonexistent) +++ tags/1.2/verify/lxp32/src/platform/program_ram.vhd (revision 10) @@ -0,0 +1,145 @@ +--------------------------------------------------------------------- +-- Program RAM +-- +-- Part of the LXP32 test platform +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- Program RAM for the LXP32 test platform. Has two interfaces: +-- WISHBONE (for data access) and LLI (for LXP32 instruction bus). +-- Optionally performs throttling. +-- +-- Note: regardless of whether this description is synthesizable, +-- it was designed exclusively for simulation purposes. +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.common_pkg.all; + +entity program_ram is + generic( + THROTTLE: boolean + ); + port( + clk_i: in std_logic; + rst_i: in std_logic; + + wbs_cyc_i: in std_logic; + wbs_stb_i: in std_logic; + wbs_we_i: in std_logic; + wbs_sel_i: in std_logic_vector(3 downto 0); + wbs_ack_o: out std_logic; + wbs_adr_i: in std_logic_vector(27 downto 2); + wbs_dat_i: in std_logic_vector(31 downto 0); + wbs_dat_o: out std_logic_vector(31 downto 0); + + lli_re_i: in std_logic; + lli_adr_i: in std_logic_vector(29 downto 0); + lli_dat_o: out std_logic_vector(31 downto 0); + lli_busy_o: out std_logic + ); +end entity; + +architecture rtl of program_ram is + +signal ram_a_we: std_logic_vector(3 downto 0); +signal ram_a_rdata: std_logic_vector(31 downto 0); + +signal ram_b_re: std_logic; +signal ram_b_rdata: std_logic_vector(31 downto 0); + +signal ack_write: std_logic; +signal ack_read: std_logic; + +signal prbs: std_logic; +signal lli_busy: std_logic:='0'; + +begin + +-- The total memory size is 16384 words, i.e. 64K bytes + +gen_dprams: for i in 3 downto 0 generate + generic_dpram_inst: entity work.generic_dpram(rtl) + generic map( + DATA_WIDTH=>8, + ADDR_WIDTH=>14, + SIZE=>16384, + MODE=>"DONTCARE" + ) + port map( + clka_i=>clk_i, + cea_i=>'1', + wea_i=>ram_a_we(i), + addra_i=>wbs_adr_i(15 downto 2), + da_i=>wbs_dat_i(i*8+7 downto i*8), + da_o=>ram_a_rdata(i*8+7 downto i*8), + + clkb_i=>clk_i, + ceb_i=>ram_b_re, + addrb_i=>lli_adr_i(13 downto 0), + db_o=>ram_b_rdata(i*8+7 downto i*8) + ); +end generate; + +-- WISHBONE interface + +gen_ram_a_we: for i in 3 downto 0 generate + ram_a_we(i)<='1' when wbs_cyc_i='1' and wbs_stb_i='1' and wbs_we_i='1' + and wbs_sel_i(i)='1' and wbs_adr_i(27 downto 16)="000000000000" else '0'; +end generate; + +process (clk_i) is +begin + if rising_edge(clk_i) then + ack_read<=wbs_cyc_i and wbs_stb_i and not wbs_we_i and not ack_read; + end if; +end process; + +ack_write<=wbs_cyc_i and wbs_stb_i and wbs_we_i; + +wbs_ack_o<=ack_read or ack_write; +wbs_dat_o<=ram_a_rdata; + +-- Low Latency Interface (with optional pseudo-random throttling) + +process (clk_i) is +begin + if rising_edge(clk_i) then + assert lli_re_i='0' or lli_adr_i(lli_adr_i'high downto 14)=X"0000" + report "Attempted to fetch instruction from a non-existent address 0x"& + hex_string(lli_adr_i&"00") + severity failure; + end if; +end process; + +gen_throttling: if THROTTLE generate + throttle_inst: entity work.scrambler(rtl) + generic map(TAP1=>9,TAP2=>11) + port map(clk_i=>clk_i,rst_i=>rst_i,ce_i=>'1',d_o=>prbs); +end generate; + +gen_no_throttling: if not THROTTLE generate + prbs<='0'; +end generate; + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' then + lli_busy<='0'; + elsif prbs='1' and lli_re_i='1' then + lli_busy<='1'; + elsif prbs='0' then + lli_busy<='0'; + end if; + end if; +end process; + +ram_b_re<=lli_re_i and not lli_busy; + +lli_busy_o<=lli_busy; +lli_dat_o<=ram_b_rdata when lli_busy='0' else (others=>'-'); + +end architecture; Index: tags/1.2/verify/lxp32/src/platform/scrambler.vhd =================================================================== --- tags/1.2/verify/lxp32/src/platform/scrambler.vhd (nonexistent) +++ tags/1.2/verify/lxp32/src/platform/scrambler.vhd (revision 10) @@ -0,0 +1,54 @@ +--------------------------------------------------------------------- +-- Scrambler +-- +-- Part of the LXP32 test platform +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- Generates a pseudo-random binary sequence using a Linear-Feedback +-- Shift Register (LFSR). +-- +-- In order to generate a maximum-length sequence, 1+x^TAP1+x^TAP2 +-- must be a primitive polynomial. Typical polynomials include: +-- (6,7), (9,11), (14,15). +-- +-- Note: regardless of whether this description is synthesizable, +-- it was designed exclusively for simulation purposes. +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity scrambler is + generic( + TAP1: integer; + TAP2: integer + ); + port( + clk_i: in std_logic; + rst_i: in std_logic; + ce_i: in std_logic; + d_o: out std_logic + ); +end entity; + +architecture rtl of scrambler is + +signal reg: std_logic_vector(TAP2 downto 1):=(others=>'1'); + +begin + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' then + reg<=(others=>'1'); + elsif ce_i='1' then + reg<=reg(TAP2-1 downto 1)&(reg(TAP2) xor reg(TAP1)); + end if; + end if; +end process; + +d_o<=reg(1); + +end architecture; Index: tags/1.2/verify/lxp32/src/platform/timer.vhd =================================================================== --- tags/1.2/verify/lxp32/src/platform/timer.vhd (nonexistent) +++ tags/1.2/verify/lxp32/src/platform/timer.vhd (revision 10) @@ -0,0 +1,98 @@ +--------------------------------------------------------------------- +-- Timer +-- +-- Part of the LXP32 test platform +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- A simple programmable interval timer. +-- +-- Note: regardless of whether this description is synthesizable, +-- it was designed exclusively for simulation purposes. +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity timer is + port( + clk_i: in std_logic; + rst_i: in std_logic; + + wbs_cyc_i: in std_logic; + wbs_stb_i: in std_logic; + wbs_we_i: in std_logic; + wbs_sel_i: in std_logic_vector(3 downto 0); + wbs_ack_o: out std_logic; + wbs_adr_i: in std_logic_vector(27 downto 2); + wbs_dat_i: in std_logic_vector(31 downto 0); + wbs_dat_o: out std_logic_vector(31 downto 0); + + elapsed_o: out std_logic + ); +end entity; + +architecture rtl of timer is + +signal pulses: unsigned(31 downto 0):=(others=>'0'); +signal interval: unsigned(31 downto 0):=(others=>'0'); +signal cnt: unsigned(31 downto 0):=(others=>'0'); +signal elapsed: std_logic:='0'; + +begin + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' then + pulses<=(others=>'0'); + interval<=(others=>'0'); + cnt<=(others=>'0'); + elapsed<='0'; + else + elapsed<='0'; + if pulses/=X"00000000" or cnt/=X"00000000" then + if cnt=X"00000000" then + if pulses/=X"FFFFFFFF" then + pulses<=pulses-1; + end if; + if pulses/=X"00000000" then + cnt<=interval; + end if; + else + cnt<=cnt-1; + end if; + if cnt=X"00000001" then + elapsed<='1'; + end if; + end if; + + if wbs_cyc_i='1' and wbs_stb_i='1' and wbs_we_i='1' then + for i in wbs_sel_i'range loop + if wbs_sel_i(i)='1' then + if wbs_adr_i="00"&X"000000" then + pulses(i*8+7 downto i*8)<= + unsigned(wbs_dat_i(i*8+7 downto i*8)); + cnt<=(others=>'0'); + end if; + if wbs_adr_i="00"&X"000001" then + interval(i*8+7 downto i*8)<= + unsigned(wbs_dat_i(i*8+7 downto i*8)); + cnt<=(others=>'0'); + end if; + end if; + end loop; + end if; + end if; + end if; +end process; + +wbs_ack_o<=wbs_cyc_i and wbs_stb_i; +wbs_dat_o<=std_logic_vector(pulses) when wbs_adr_i="00"&X"000000" else + std_logic_vector(interval) when wbs_adr_i="00"&X"000001" else + (others=>'-'); + +elapsed_o<=elapsed; + +end architecture; Index: tags/1.2/verify/lxp32/src/tb/monitor.vhd =================================================================== --- tags/1.2/verify/lxp32/src/tb/monitor.vhd (nonexistent) +++ tags/1.2/verify/lxp32/src/tb/monitor.vhd (revision 10) @@ -0,0 +1,80 @@ +--------------------------------------------------------------------- +-- Test monitor +-- +-- Part of the LXP32 testbench +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- Provide means for a test platform to interact with the testbench. +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.common_pkg.all; +use work.tb_pkg.all; + +entity monitor is + generic( + VERBOSE: boolean + ); + port( + clk_i: in std_logic; + rst_i: in std_logic; + + wbs_cyc_i: in std_logic; + wbs_stb_i: in std_logic; + wbs_we_i: in std_logic; + wbs_sel_i: in std_logic_vector(3 downto 0); + wbs_ack_o: out std_logic; + wbs_adr_i: in std_logic_vector(27 downto 2); + wbs_dat_i: in std_logic_vector(31 downto 0); + wbs_dat_o: out std_logic_vector(31 downto 0); + + finished_o: out std_logic; + result_o: out std_logic_vector(31 downto 0) + ); +end entity; + +architecture sim of monitor is + +signal result: std_logic_vector(31 downto 0):=(others=>'0'); +signal finished: std_logic:='0'; + +begin + +wbs_ack_o<=wbs_cyc_i and wbs_stb_i; +wbs_dat_o<=(others=>'0'); + +finished_o<=finished; +result_o<=result; + +process (clk_i) is +begin + if rising_edge(clk_i) then + if rst_i='1' then + finished<='0'; + result<=(others=>'0'); + elsif wbs_cyc_i='1' and wbs_stb_i='1' and wbs_we_i='1' then + assert wbs_sel_i="1111" + report "Monitor doesn't support byte-granular access "& + "(SEL_I() is 0x"&hex_string(wbs_sel_i)&")" + severity failure; + + if VERBOSE then + report "Monitor: value "& + "0x"&hex_string(wbs_dat_i)& + " written to address "& + "0x"&hex_string(wbs_adr_i); + end if; + + if unsigned(wbs_adr_i)=to_unsigned(0,wbs_adr_i'length) then + result<=wbs_dat_i; + finished<='1'; + end if; + end if; + end if; +end process; + +end architecture; Index: tags/1.2/verify/lxp32/src/tb/tb.vhd =================================================================== --- tags/1.2/verify/lxp32/src/tb/tb.vhd (nonexistent) +++ tags/1.2/verify/lxp32/src/tb/tb.vhd (revision 10) @@ -0,0 +1,147 @@ +--------------------------------------------------------------------- +-- LXP32 verification environment (self-checking testbench) +-- +-- Part of the LXP32 testbench +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- Simulates LXP32 test platform, verifies results. +-- +-- Parameters: +-- CPU_DBUS_RMW: DBUS_RMW CPU generic +-- CPU_MUL_ARCH: MUL_ARCH CPU generic +-- MODEL_LXP32C: when true, simulates LXP32C variant (with +-- instruction cache), otherwise LXP32U +-- TEST_CASE: If non-empty, selects a test case to run. +-- If empty, all tests are executed. +-- THROTTLE_IBUS: perform pseudo-random instruction bus +-- throttling +-- THROTTLE_DBUS: perform pseudo-random data bus throttling +-- VERBOSE: report everything that is written to the +-- test monitor address space +--------------------------------------------------------------------- + +use std.textio.all; + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.tb_pkg.all; + +entity tb is + generic( + CPU_DBUS_RMW: boolean:=false; + CPU_MUL_ARCH: string:="dsp"; + MODEL_LXP32C: boolean:=true; + TEST_CASE: string:=""; + THROTTLE_DBUS: boolean:=true; + THROTTLE_IBUS: boolean:=true; + VERBOSE: boolean:=false + ); +end entity; + +architecture testbench of tb is + +signal clk: std_logic:='0'; + +signal globals: soc_globals_type:=(others=>'1'); +signal soc_wbs_in: soc_wbs_in_type; +signal soc_wbs_out: soc_wbs_out_type; +signal soc_wbm_in: soc_wbm_in_type; +signal soc_wbm_out: soc_wbm_out_type; + +signal monitor_out: monitor_out_type; + +signal finish: std_logic:='0'; + +begin + +dut: entity work.platform(rtl) + generic map( + CPU_DBUS_RMW=>CPU_DBUS_RMW, + CPU_MUL_ARCH=>CPU_MUL_ARCH, + MODEL_LXP32C=>MODEL_LXP32C, + THROTTLE_DBUS=>THROTTLE_DBUS, + THROTTLE_IBUS=>THROTTLE_IBUS + ) + port map( + clk_i=>clk, + rst_i=>globals.rst_i, + cpu_rst_i=>globals.cpu_rst_i, + + wbm_cyc_o=>soc_wbm_out.cyc, + wbm_stb_o=>soc_wbm_out.stb, + wbm_we_o=>soc_wbm_out.we, + wbm_sel_o=>soc_wbm_out.sel, + wbm_ack_i=>soc_wbm_in.ack, + wbm_adr_o=>soc_wbm_out.adr, + wbm_dat_o=>soc_wbm_out.dat, + wbm_dat_i=>soc_wbm_in.dat, + + wbs_cyc_i=>soc_wbs_in.cyc, + wbs_stb_i=>soc_wbs_in.stb, + wbs_we_i=>soc_wbs_in.we, + wbs_sel_i=>soc_wbs_in.sel, + wbs_ack_o=>soc_wbs_out.ack, + wbs_adr_i=>soc_wbs_in.adr, + wbs_dat_i=>soc_wbs_in.dat, + wbs_dat_o=>soc_wbs_out.dat + ); + +monitor_inst: entity work.monitor(sim) + generic map( + VERBOSE=>VERBOSE + ) + port map( + clk_i=>clk, + rst_i=>globals.rst_i, + + wbs_cyc_i=>soc_wbm_out.cyc, + wbs_stb_i=>soc_wbm_out.stb, + wbs_we_i=>soc_wbm_out.we, + wbs_sel_i=>soc_wbm_out.sel, + wbs_ack_o=>soc_wbm_in.ack, + wbs_adr_i=>soc_wbm_out.adr, + wbs_dat_i=>soc_wbm_out.dat, + wbs_dat_o=>soc_wbm_in.dat, + + finished_o=>monitor_out.valid, + result_o=>monitor_out.data + ); + +clk<=not clk and not finish after 5 ns; + +process is +begin + if TEST_CASE'length=0 then + run_test("test001.ram",clk,globals,soc_wbs_in,soc_wbs_out,monitor_out); + run_test("test002.ram",clk,globals,soc_wbs_in,soc_wbs_out,monitor_out); + run_test("test003.ram",clk,globals,soc_wbs_in,soc_wbs_out,monitor_out); + run_test("test004.ram",clk,globals,soc_wbs_in,soc_wbs_out,monitor_out); + run_test("test005.ram",clk,globals,soc_wbs_in,soc_wbs_out,monitor_out); + run_test("test006.ram",clk,globals,soc_wbs_in,soc_wbs_out,monitor_out); + run_test("test007.ram",clk,globals,soc_wbs_in,soc_wbs_out,monitor_out); + run_test("test008.ram",clk,globals,soc_wbs_in,soc_wbs_out,monitor_out); + run_test("test009.ram",clk,globals,soc_wbs_in,soc_wbs_out,monitor_out); + run_test("test010.ram",clk,globals,soc_wbs_in,soc_wbs_out,monitor_out); + run_test("test011.ram",clk,globals,soc_wbs_in,soc_wbs_out,monitor_out); + run_test("test012.ram",clk,globals,soc_wbs_in,soc_wbs_out,monitor_out); + run_test("test013.ram",clk,globals,soc_wbs_in,soc_wbs_out,monitor_out); + run_test("test014.ram",clk,globals,soc_wbs_in,soc_wbs_out,monitor_out); + run_test("test015.ram",clk,globals,soc_wbs_in,soc_wbs_out,monitor_out); + run_test("test016.ram",clk,globals,soc_wbs_in,soc_wbs_out,monitor_out); + run_test("test017.ram",clk,globals,soc_wbs_in,soc_wbs_out,monitor_out); + run_test("test018.ram",clk,globals,soc_wbs_in,soc_wbs_out,monitor_out); + run_test("test019.ram",clk,globals,soc_wbs_in,soc_wbs_out,monitor_out); + run_test("test020.ram",clk,globals,soc_wbs_in,soc_wbs_out,monitor_out); + else + run_test(TEST_CASE,clk,globals,soc_wbs_in,soc_wbs_out,monitor_out); + end if; + + report "ALL TESTS WERE COMPLETED SUCCESSFULLY"; + finish<='1'; + wait; +end process; + +end architecture; Index: tags/1.2/verify/lxp32/src/tb/tb_pkg.vhd =================================================================== --- tags/1.2/verify/lxp32/src/tb/tb_pkg.vhd (nonexistent) +++ tags/1.2/verify/lxp32/src/tb/tb_pkg.vhd (revision 10) @@ -0,0 +1,70 @@ +--------------------------------------------------------------------- +-- LXP32 testbench package +-- +-- Part of the LXP32 testbench +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- Auxiliary package declaration for the LXP32 testbench +--------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +package tb_pkg is + constant c_max_program_size: integer:=8192; + + type soc_globals_type is record + rst_i: std_logic; + cpu_rst_i: std_logic; + end record; + + type soc_wbs_in_type is record + cyc: std_logic; + stb: std_logic; + we: std_logic; + sel: std_logic_vector(3 downto 0); + adr: std_logic_vector(31 downto 2); + dat: std_logic_vector(31 downto 0); + end record; + + type soc_wbs_out_type is record + ack: std_logic; + dat: std_logic_vector(31 downto 0); + end record; + + type soc_wbm_in_type is record + ack: std_logic; + dat: std_logic_vector(31 downto 0); + end record; + + type soc_wbm_out_type is record + cyc: std_logic; + stb: std_logic; + we: std_logic; + sel: std_logic_vector(3 downto 0); + adr: std_logic_vector(27 downto 2); + dat: std_logic_vector(31 downto 0); + end record; + + type monitor_out_type is record + data: std_logic_vector(31 downto 0); + valid: std_logic; + end record; + + procedure load_ram( + filename: string; + signal clk: in std_logic; + signal soc_in: out soc_wbs_in_type; + signal soc_out: in soc_wbs_out_type + ); + + procedure run_test( + filename: string; + signal clk: in std_logic; + signal globals: out soc_globals_type; + signal soc_in: out soc_wbs_in_type; + signal soc_out: in soc_wbs_out_type; + signal result: in monitor_out_type + ); +end package; Index: tags/1.2/verify/lxp32/src/tb/tb_pkg_body.vhd =================================================================== --- tags/1.2/verify/lxp32/src/tb/tb_pkg_body.vhd (nonexistent) +++ tags/1.2/verify/lxp32/src/tb/tb_pkg_body.vhd (revision 10) @@ -0,0 +1,100 @@ +--------------------------------------------------------------------- +-- LXP32 testbench package body +-- +-- Part of the LXP32 testbench +-- +-- Copyright (c) 2016 by Alex I. Kuznetsov +-- +-- Auxiliary package body for the LXP32 testbench +--------------------------------------------------------------------- + +use std.textio.all; + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.common_pkg.all; + +package body tb_pkg is + procedure load_ram( + filename: string; + signal clk: in std_logic; + signal soc_in: out soc_wbs_in_type; + signal soc_out: in soc_wbs_out_type + ) is + file f: text open read_mode is filename; + variable i: integer:=0; + variable l: line; + variable v: bit_vector(31 downto 0); + begin + wait until rising_edge(clk); + + report "Loading program RAM from """&filename&""""; + + while not endfile(f) loop + readline(f,l); + read(l,v); + + assert i'1'); + soc_in.adr<=std_logic_vector(to_unsigned(i,30)); + soc_in.dat<=to_stdlogicvector(v); + + wait until rising_edge(clk) and soc_out.ack='1'; + + i:=i+1; + end loop; + + report integer'image(i)&" words loaded from """&filename&""""; + + soc_in.cyc<='0'; + soc_in.stb<='0'; + + wait until rising_edge(clk); + end procedure; + + procedure run_test( + filename: string; + signal clk: in std_logic; + signal globals: out soc_globals_type; + signal soc_in: out soc_wbs_in_type; + signal soc_out: in soc_wbs_out_type; + signal result: in monitor_out_type + ) is + begin + -- Assert SoC and CPU resets + wait until rising_edge(clk); + globals.rst_i<='1'; + globals.cpu_rst_i<='1'; + wait until rising_edge(clk); + + -- Deassert SoC reset, leave CPU in reset state for now + globals.rst_i<='0'; + wait until rising_edge(clk); + + -- Load RAM + load_ram(filename,clk,soc_in,soc_out); + + -- Deassert CPU reset + globals.cpu_rst_i<='0'; + + while result.valid/='1' loop + wait until rising_edge(clk); + end loop; + + -- Analyze result + + if result.data=X"00000001" then + report "TEST """&filename&""" RESULT: SUCCESS (return code 0x"& + hex_string(result.data)&")"; + else + report "TEST """&filename&""" RESULT: FAILURE (return code 0x"& + hex_string(result.data)&")" severity failure; + end if; + end procedure; +end package body;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.