<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Jun 6, 2015 at 9:33 AM, tim Rowledge <span dir="ltr">&lt;<a href="mailto:tim@rowledge.org" target="_blank">tim@rowledge.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class=""><br>
On 06-06-2015, at 8:15 AM, Eliot Miranda &lt;<a href="mailto:eliot.miranda@gmail.com">eliot.miranda@gmail.com</a>&gt; wrote:<br>
&gt;     so yesterday I finally switched on the Raspberry Pi Doug gave me as an xmas present, built the Spur ARM Cog VM and ... we definitely have a working VM.<br>
<br>
</span>It’s really nice to get to this. There are still some ‘exciting’ parts to get working though… floating point for example.<br>
<span class=""><br>
&gt;  I was able to update a Spur image from mid February all the way to tip and run tests.  3751 run, 3628 passes, 24 expected failures, 89 failures, 10 errors, 0 unexpected passes<br>
<br>
</span>Did this include the FloatMathPluginTests? Because on my Pi2 that segfaults in all versions of the vm - interpreter, stack, cog. Then again my Pi2 is segfaulting on any vm compiled with -O2 right now whereas Eliot’s PiB is just fine with that. Good old GCC strikes again.<br>
<span class=""><br>
&gt; Fun!  So I want to revisit the literal load question.<br>
</span><span class="">&gt; In ARMv6T2 and later, MOV can load any 16-bit number, giving a range of 0x0-0xFFFF (0-65535).<br>
&gt; The following table shows the range of 8-bit values that can be loaded in a single ARM MOV or MVN instruction (for data processing operations). The value to load must be a multiple of the value shown in the Step column.<br>
&gt;<br>
</span>Sadly the Pi B/+ are NOT 6T2 cpus. I checked this with Eben a while back. One of the side-effects of the flexibility ARM provides to actual manufacturers is a fairly complex range of possible features within any particular architecture level.<br>
<br>
That doesn’t mean we can’t do tricks to make the Pi_2_ use the nice v7 features whilst using out of line data loads on the older machines. In the best case, where the data is already in the cache (we can use  PLD to help with that) a LDR takes 2 cycles as opposed to the 4 currently used by our mov/orr^3 unit. Using the v7 MOVT/H is also two instructions but *always* two cycles with possibility of an out-of-cache delay, so I still think it is probably better.<br></blockquote><div><br></div><div>Ha!  Turns out that at least for sends we&#39;re in the clear for out-of-line literal load.  i.e. from <a href="https://www.raspberrypi.org/forums/viewtopic.php?f=72&amp;t=78090">https://www.raspberrypi.org/forums/viewtopic.php?f=72&amp;t=78090</a></div><div><br></div><span class="Apple-style-span" style="color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,Arial,sans-serif;font-size:14px;line-height:20px"><i>Looking at the ARM1176jzf-s TRM, section &quot;Cycle timings and interlock behaviour&quot; we see that:<br><br>MOV Rn, x -&gt; 1 cycle<br>MVN Rn, x -&gt; 1 cycle<br></i></span><div><i><span class="Apple-style-span" style="color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,Arial,sans-serif;font-size:14px;line-height:20px">LDR Rn, [PC, #constant] -&gt; 1 cycle, with a latency of 3 cycles on Rn</span> </i></div><div><br></div><div><br></div><div>And the send sequence would look like</div><div><br></div><div>    LDR Rclass. [PC, #constant]</div><div>    BLX method.entry</div><div><br></div><div>with the entry code being</div><div><br></div><div><div>00001828: ands<span class="Apple-tab-span" style="white-space:pre">        </span>r0, r0, #1</div><div>0000182c: b<span class="Apple-tab-span" style="white-space:pre">        </span>0x00001844</div><div>entry:</div><div>00001830: ands<span class="Apple-tab-span" style="white-space:pre">        </span>r0, r7, #3</div><div>00001834: bne<span class="Apple-tab-span" style="white-space:pre">        </span>0x00001828</div><div>00001838: ldr<span class="Apple-tab-span" style="white-space:pre">        </span>r0, [r7]</div><div>0000183c: mvn<span class="Apple-tab-span" style="white-space:pre">        </span>ip, #0</div><div>00001840: ands<span class="Apple-tab-span" style="white-space:pre">        </span>r0, r0, ip, lsr #10</div><div>00001844: cmp<span class="Apple-tab-span" style="white-space:pre">        </span>r0, Rclass</div><div>00001848: bne<span class="Apple-tab-span" style="white-space:pre">        </span>0x00001820</div><div>noCheckEntry:</div></div><div><br></div><div>i.e. we don&#39;t actually access the register loaded in the LDR for at least 7 cycles.  So it should work a lot better; 11 cycles vs 14 cycles for the send sequence.  In fact the only code that should be impacted by the latency is a conditional branch of a method result (we subtract true or false from the result) or a constant assign.  Most of the time a literal will be passed as an argument and there will be quite a few cycles before it is used.</div><div><br></div><div>OK, so that implies doing the out-of-line literal load, with the advantage that there&#39;s a single VM, and the same approach is used for the 64-bit ARM system.</div><div><br></div><div><br></div><div><br></div><div>    </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
<br>
tim<br>
--<br>
tim Rowledge; <a href="mailto:tim@rowledge.org">tim@rowledge.org</a>; <a href="http://www.rowledge.org/tim" target="_blank">http://www.rowledge.org/tim</a><br>
</span>Strange OpCodes: EIV: Erase IPL Volume<br>
<br>
<br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature">best,<div>Eliot</div></div>
</div></div>