<?xml version="1.0" encoding="us-ascii"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Psellos Blog</title><link href="http://psellos.com/"/><link href="http://psellos.com/atom.xml" rel="self"/><id>http://psellos.com/</id><author><name>Psellos</name></author><updated>2013-05-26T02:48:18Z</updated><generator uri="http://search.cpan.org/dist/XML-Atom-SimpleFeed/" version="0.86">XML::Atom::SimpleFeed</generator><entry><title>When iOS Simulator Apps Go AWOL</title><link href="http://psellos.com/2012/11/2012.11.iossim-apps-awol.html"/><id>http://psellos.com/2012/11/2012.11.iossim-apps-awol.html</id><updated>2012-11-15T11:00:00-08:00</updated><content type="html">&lt;!--#include virtual=&#34;${Base_URL}/templates/header.html&#34; --&gt;&lt;div class=&#34;date&#34;&gt;November 15, 2012&lt;/div&gt;

&lt;p&gt;I&#38;#8217;ve just finished work on version 2.0 of &lt;code&gt;runsim&lt;/code&gt;, a small shell script
that installs and runs apps in the iOS Simulator.  For this version I
added the ability to start apps in the simulator automatically from the
command line. I also separated out the different functions, so you can
install, uninstall, list, and run apps as separate operations.&lt;/p&gt;

&lt;div class=&#34;flowaroundimg&#34; style=&#34;margin-top: 1.0em;&#34;&gt;
&lt;a href=&#34;http://psellos.com/ios/iossim-command-line.html&#34;&gt;&lt;img src=&#34;http://psellos.com/images/psi-p2.png&#34; alt=&#34;Psi example app in iOS Simulator&#34;&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;You can read the full details on &lt;a href=&#34;http://psellos.com/ios/iossim-command-line.html&#34;&gt;Run iOS Simulator from the Command
Line&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can also download &lt;code&gt;runsim&lt;/code&gt; from the following link:&lt;/p&gt;

&lt;ul class=&#34;rightoffloat&#34;&gt;
&lt;li&gt;&lt;a href=&#34;http://psellos.com/pub/ocamlxsim/runsim&#34;&gt;runsim &#38;#8212; run app in iOS Simulator from command line&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before using it, however, I suggest you read the full description linked
above. There are some complexities in using the automatic start-up
facility that you want to understand beforehand.&lt;/p&gt;

&lt;p&gt;The new automatic start-up uses &lt;code&gt;instruments&lt;/code&gt;, the command-line version
of the Xcode Instruments tool. While getting it working I had one
persistent problem: Instruments kept reporting that the monitored app
had gone AWOL.  For the benefit of other folks working from the command
line, I&#38;#8217;ll show how to elicit this legendary error and what I did to
correct it.&lt;/p&gt;

&lt;p&gt;To keep the example simple, I&#38;#8217;ll use &lt;code&gt;Psi&lt;/code&gt;, an iOS app I wrote to be be
as small as possible and to require no supporting files.  (Get the
source from &lt;a href=&#34;http://psellos.com/2012/05/2012.05.tiny-ios-app.html&#34;&gt;Tiny iOS App in One Source File&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;Every app in the Apple universe has an &lt;code&gt;Info.plist&lt;/code&gt; file that describes
its basic attributes. The core of the AWOL app problem is that Xcode has
begun to add internal attributes to this file behind the scenes. You can
see why Apple would do things this way, but it makes it a little more
difficult for &#38;#8220;enthusiasts&#38;#8221; to do new things with the tools.&lt;/p&gt;

&lt;p&gt;Here is an &lt;code&gt;Info.plist&lt;/code&gt; file for &lt;code&gt;Psi&lt;/code&gt; as it is presented to users of
Xcode:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&#38;lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&#38;gt;
&#38;lt;!DOCTYPE plist PUBLIC &#34;-//Apple//DTD PLIST 1.0//EN&#34; &#34;http://www.apple.com/DTDs/PropertyList-1.0.dtd&#34;&#38;gt;
&#38;lt;plist version=&#34;1.0&#34;&#38;gt;
&#38;lt;dict&#38;gt;
        &#38;lt;key&#38;gt;CFBundleDevelopmentRegion&#38;lt;/key&#38;gt;
        &#38;lt;string&#38;gt;English&#38;lt;/string&#38;gt;
        &#38;lt;key&#38;gt;CFBundleDisplayName&#38;lt;/key&#38;gt;
        &#38;lt;string&#38;gt;Psi&#38;lt;/string&#38;gt;
        &#38;lt;key&#38;gt;CFBundleExecutable&#38;lt;/key&#38;gt;
        &#38;lt;string&#38;gt;Psi&#38;lt;/string&#38;gt;
        &#38;lt;key&#38;gt;CFBundleIconFile&#38;lt;/key&#38;gt;
        &#38;lt;string&#38;gt;Icon.png&#38;lt;/string&#38;gt;
        &#38;lt;key&#38;gt;CFBundleIcons&#38;lt;/key&#38;gt;
        &#38;lt;dict&#38;gt;
                &#38;lt;key&#38;gt;CFBundlePrimaryIcon&#38;lt;/key&#38;gt;
                &#38;lt;dict&#38;gt;
                        &#38;lt;key&#38;gt;CFBundleIconFiles&#38;lt;/key&#38;gt;
                        &#38;lt;array&#38;gt;
                                &#38;lt;string&#38;gt;Icon.png&#38;lt;/string&#38;gt;
                        &#38;lt;/array&#38;gt;
                &#38;lt;/dict&#38;gt;
        &#38;lt;/dict&#38;gt;
        &#38;lt;key&#38;gt;CFBundleIdentifier&#38;lt;/key&#38;gt;
        &#38;lt;string&#38;gt;com.psellos.Psi&#38;lt;/string&#38;gt;
        &#38;lt;key&#38;gt;CFBundleInfoDictionaryVersion&#38;lt;/key&#38;gt;
        &#38;lt;string&#38;gt;6.0&#38;lt;/string&#38;gt;
        &#38;lt;key&#38;gt;CFBundleName&#38;lt;/key&#38;gt;
        &#38;lt;string&#38;gt;Psi&#38;lt;/string&#38;gt;
        &#38;lt;key&#38;gt;CFBundlePackageType&#38;lt;/key&#38;gt;
        &#38;lt;string&#38;gt;APPL&#38;lt;/string&#38;gt;
        &#38;lt;key&#38;gt;CFBundleSignature&#38;lt;/key&#38;gt;
        &#38;lt;string&#38;gt;????&#38;lt;/string&#38;gt;
        &#38;lt;key&#38;gt;CFBundleShortVersionString&#38;lt;/key&#38;gt;
        &#38;lt;string&#38;gt;1.0&#38;lt;/string&#38;gt;
        &#38;lt;key&#38;gt;CFBundleVersion&#38;lt;/key&#38;gt;
        &#38;lt;string&#38;gt;1.0.1&#38;lt;/string&#38;gt;
        &#38;lt;key&#38;gt;UIStatusBarStyle&#38;lt;/key&#38;gt;
        &#38;lt;string&#38;gt;UIStatusBarStyleBlackOpaque&#38;lt;/string&#38;gt;
        &#38;lt;key&#38;gt;LSRequiresIPhoneOS&#38;lt;/key&#38;gt;
        &#38;lt;true/&#38;gt;
&#38;lt;/dict&#38;gt;
&#38;lt;/plist&#38;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you try to start up &lt;code&gt;Psi&lt;/code&gt; with this exact &lt;code&gt;Info.plist&lt;/code&gt;, however,
&lt;code&gt;instruments&lt;/code&gt; reports that the app has gone AWOL:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;&lt;code&gt;$&#38;#160;PSID=&#34;$HOME/Library/Application&#38;#160;Support/iPhone&#38;#160;Simulator/6.0/Applications/72002825-3566-4EF2-B87B-872836AD29C6/Psi.app&#34;&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;strong&gt;&lt;code&gt;$&#38;#160;TRC=/Applications/Xcode.app/Contents/Applications/Instruments.app/Contents/PlugIns/AutomationInstrument.bundle/Contents/Resources/Automation.tracetemplate&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;strong&gt;&lt;code&gt;$ instruments instruments -t &#34;$TRC&#34; &#34;$PSID&#34;&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;code&gt;2012-11-15 12:32:51.586 instruments[56628:1207] Automation Instrument ran into an exception while trying to run the script.  UIATargetHasGoneAWOLException&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;2012-11-15 20:32:51 +0000 Fail: An error occurred while trying to run the script.&lt;/code&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you let Xcode install the app, it modifies &lt;code&gt;Info.plist&lt;/code&gt; internally to
include the following extra attributes:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;        &#38;lt;key&#38;gt;CFBundleSupportedPlatforms&#38;lt;/key&#38;gt;
        &#38;lt;array&#38;gt;
                &#38;lt;string&#38;gt;iPhoneSimulator&#38;lt;/string&#38;gt;
        &#38;lt;/array&#38;gt;
        &#38;lt;key&#38;gt;DTPlatformName&#38;lt;/key&#38;gt;
        &#38;lt;string&#38;gt;iphonesimulator&#38;lt;/string&#38;gt;
        &#38;lt;key&#38;gt;DTSDKName&#38;lt;/key&#38;gt;
        &#38;lt;string&#38;gt;iphonesimulator6.0&#38;lt;/string&#38;gt;
        &#38;lt;key&#38;gt;UIDeviceFamily&#38;lt;/key&#38;gt;
        &#38;lt;array&#38;gt;
                &#38;lt;integer&#38;gt;1&#38;lt;/integer&#38;gt;
        &#38;lt;/array&#38;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In essence, these are device attributes for the iOS Simulator&#38;#8217;s iPhone
simulation. If you add these attributes to the &lt;code&gt;Info.plist&lt;/code&gt; file,
&lt;code&gt;instruments&lt;/code&gt; runs as expected. It starts up the iPhone Simulator and
then starts up &lt;code&gt;Psi&lt;/code&gt; in the simulator.&lt;/p&gt;

&lt;p&gt;Inside &lt;code&gt;runsim&lt;/code&gt; 2.0 there&#38;#8217;s a little Python script that adds these
attributes to an &lt;code&gt;Info.plist&lt;/code&gt; file. If you&#38;#8217;re encountering the AWOL
problem, maybe this little script will help. (You can download &lt;code&gt;runsum&lt;/code&gt;
from the link above.)&lt;/p&gt;

&lt;p&gt;If you have any comments, corrections, or suggestions, leave them below
or email me at &lt;a href=&#34;&#38;#x6d;&#38;#x61;&#38;#x69;&#38;#108;&#38;#x74;&#38;#x6f;&#38;#x3a;j&#38;#x65;&#38;#x66;&#38;#x66;&#38;#115;&#38;#099;&#38;#x6f;&#38;#064;&#38;#112;&#38;#115;&#38;#x65;l&#38;#x6c;&#38;#x6f;s&#38;#046;&#38;#x63;&#38;#x6f;&#38;#x6d;&#34;&gt;&#38;#106;e&#38;#102;&#38;#x66;&#38;#115;&#38;#099;o&#38;#064;&#38;#112;&#38;#115;&#38;#x65;&#38;#108;l&#38;#x6f;&#38;#x73;&#38;#x2e;&#38;#x63;&#38;#111;&#38;#109;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Posted by: &lt;a href=&#34;http://psellos.com/aboutus.html#jeffreya.scofieldphd&#34;&gt;Jeffrey&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;style type=&#34;text/css&#34;&gt;
.flowaroundimg {
       float: left;
       margin: 0em 1em 0em 0em;
}
.rightoffloat li {
    position: relative;
    left: 1em;
}
pre {
    white-space: pre-wrap;
    width: 96%;
    margin-bottom: 24px;
    overflow: hidden;
    padding: 3px 10px;
    -webkit-border-radius: 3px;
    background-color: #fed;
    border: 1px solid #dcb;
}
pre code {
    white-space: pre-wrap;
    border: none;
    padding: 0;
    background-color: transparent;
    -webkit-border-radius: 0;
}
&lt;/style&gt;&lt;/p&gt;
&lt;!--#include virtual=&#34;${Base_URL}/templates/footer.html&#34; --&gt;</content></entry><entry><title>OCamlXSim 3.1 for Mountain Lion</title><link href="http://psellos.com/2012/10/2012.10.ocamlxsim-mountain-lion.html"/><id>http://psellos.com/2012/10/2012.10.ocamlxsim-mountain-lion.html</id><updated>2012-10-23T11:00:00-08:00</updated><content type="html">&lt;!--#include virtual=&#34;${Base_URL}/templates/header.html&#34; --&gt;&lt;div class=&#34;date&#34;&gt;October 23, 2012&lt;/div&gt;

&lt;p&gt;For those interested in building iOS Simulator apps in OCaml 4, I&#38;#8217;ve
just revamped &lt;a href=&#34;http://psellos.com/ocaml/compile-to-iossim.html&#34;&gt;OCamlXSim 3.1&lt;/a&gt; for the
latest OS X release, OS X 10.8 (Mountain Lion).  The only difference is
in the default iOS SDK, which I changed from iOS 5.1 to iOS 6.0.
Otherwise, this was just a recompile.&lt;/p&gt;

&lt;div class=&#34;flowaroundimg&#34; style=&#34;margin-top: 1.0em;&#34;&gt;
&lt;a href=&#34;http://psellos.com/ocaml/compile-to-iossim.html&#34;&gt;&lt;img src=&#34;http://psellos.com/images/vorolambda-b3-p2.png&#34;&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;You can get binary releases of OCamlXSim here:&lt;/p&gt;

&lt;ul class=&#34;rightoffloat&#34;&gt;
&lt;li&gt;&lt;a href=&#34;http://psellos.com/pub/ocamlxsim/ocaml-4.00.0+xsim-3.1.6.dmg&#34;&gt;OCamlXSim 3.1.6 for Lion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://psellos.com/pub/ocamlxsim/ocaml-4.00.0+xsim-3.1.7.dmg&#34;&gt;OCamlXSim 3.1.7 for Mountain Lion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For information on how to build from sources and how to test an
installation, see the updated version of &lt;a href=&#34;http://psellos.com/ocaml/compile-to-iossim.html&#34;&gt;Compile OCaml for iOS
Simulator&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you&#38;#8217;re new to this site, you might also be interested in OCamlXARM, a
modified version of OCaml 4.00.0 that builds iOS apps.  I also revamped
it recently to work under Mountain Lion.  You can read about it on
&lt;a href=&#34;http://psellos.com/ocaml/compile-to-iphone.html&#34;&gt;Compile OCaml for iOS&lt;/a&gt;&lt;/p&gt;

&lt;div style=&#34;clear: both&#34;&gt;&lt;/div&gt;

&lt;h3 id=&#34;ocamlcrosscompilationbuildhowto&#34;&gt;OCaml Cross Compilation Build Howto&lt;/h3&gt;

&lt;p&gt;OCamlXSim and OCamlXARM are both cross compilers, and they&#38;#8217;re built
using exactly the same approach.  I think the strategy could be useful
for building other OCaml cross compilers, so I thought I&#38;#8217;d explain how
the build process works in some detail.  I&#38;#8217;m not claiming that the
method is original; however, I did develop it independently and it works
for my host and targets.&lt;/p&gt;

&lt;p&gt;Since the stock version of OCaml doesn&#38;#8217;t want to be a cross compiler,
the overall goal is to beguile it into being one without disrupting the
build process too much.  To keep things simple for now, I build a
bytecode cross compiler that generates native code for the target; i.e.,
a cross-compiling version of &lt;code&gt;ocamlopt&lt;/code&gt;.  The approach requires that
OCaml already supports the host system with at least a bytecode
implementation, and the target system with a native code implementation.&lt;/p&gt;

&lt;p&gt;Building the equivalent &#38;#8220;optimized&#38;#8221; cross compiler (&lt;code&gt;ocamlopt.opt&lt;/code&gt;)
doesn&#38;#8217;t seem &lt;em&gt;too&lt;/em&gt; much harder, given a native OCaml compiler for the
host system.  I&#38;#8217;d like to get this working at some point.&lt;/p&gt;

&lt;h4 id=&#34;compilersourcechanges&#34;&gt;Compiler Source Changes&lt;/h4&gt;

&lt;p&gt;This note just describes the commands I use to build the cross
compilers.  It doesn&#38;#8217;t describe the changes to the compiler source
itself.  These will vary a lot depending on the target and the
differences between the host and the target.&lt;/p&gt;

&lt;p&gt;There are no source changes for OCamlXSIM when building a 32-bit OS X
host executable, because the host and target have virtually identical
properties.  Even for a 64-bit OS X executable, the changes are minimal,
because the host and target are quite similar.  There is one change in
&lt;code&gt;asmrun/signals_osdep.h&lt;/code&gt;, which must be modified to include the proper
signal handling code in a cross-compiling environment (when the host and
the target architectures are different).  Another change in the code
generator makes sure that emitted native int values don&#38;#8217;t exceed 32
bits.&lt;/p&gt;

&lt;p&gt;The compiler source changes for OCamlXARM are much more extensive,
because the iOS target isn&#38;#8217;t directly supported in the stock OCaml
release.  The same signal-handling change was required, and many
(reasonably straightforward) changes were required in the emission of
assembly code to allow for the particular syntax of the iOS assembler.&lt;/p&gt;

&lt;p&gt;In cases where the host and target machines are very different, it may
be necessary to make significant changes to the architecture-dependent
code that emits instructions and data.&lt;/p&gt;

&lt;p&gt;If you&#38;#8217;re interested in the exact compiler changes for OCamlXSim or
OCamlXARM, see their associated pages (linked above) for a description
of how to retrieve the patches.&lt;/p&gt;

&lt;h4 id=&#34;ordinaryocamlbuild&#34;&gt;Ordinary OCaml Build&lt;/h4&gt;

&lt;p&gt;As a starting point for the build process, consider the ordinary OCaml
build process:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;&lt;code&gt;$ ./configure&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;strong&gt;&lt;code&gt;$ make world&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;strong&gt;&lt;code&gt;$ make opt&lt;/code&gt;&lt;/strong&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;configure&lt;/code&gt; step does many things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Guess the CPU type and operating system of the host.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Find a C compiler and associated assembler and linker.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Determine properties of the machine (integer sizes, endianness).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Determine properties of the system (available system calls and
libraries).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since OCaml sees itself as a native compiler, all these configuration
properties are assumed to apply both to the compiler itself and to the
programs it generates.  This isn&#38;#8217;t the case for a cross compiler, and
the key undertaking is to separate the two.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;make world&lt;/code&gt; step builds the bytecode compiler (&lt;code&gt;ocamlc&lt;/code&gt;) and
bytecode runtime.  The bytecode runtime consists of a native-code
program named &lt;code&gt;ocamlrun&lt;/code&gt; and a set of dynamically loadable executables
for extra libraries.  &lt;code&gt;ocamlrun&lt;/code&gt;, in turn, consists of a bytecode
interpreter and native-code primitives.  Each dynamic library contains
bytecode plus extra native-code primitives.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;make opt&lt;/code&gt; step builds the native code compiler (&lt;code&gt;ocamlopt&lt;/code&gt;) and a
native runtime.  The native runtime consists of a set of native
libraries, very similar to the bytecode runtime minus the interpreter.&lt;/p&gt;

&lt;p&gt;When you do an ordinary compile of an OCaml program with &lt;code&gt;ocamlopt&lt;/code&gt;,
&lt;code&gt;ocamlopt&lt;/code&gt; itself uses the bytecode runtime created in the &lt;code&gt;make world&lt;/code&gt;
step.  The compiled program links against the native runtime created in
the &lt;code&gt;make opt&lt;/code&gt; step.&lt;/p&gt;

&lt;h4 id=&#34;crosscompilingrequirements&#34;&gt;Cross Compiling Requirements&lt;/h4&gt;

&lt;p&gt;To get a cross compiler using the same build system requires a
reconsideration of the configuration properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The CPU type is used to select the correct native code generator.  So
the CPU type of the host isn&#38;#8217;t so interesting.  We want to specify the
CPU type of the target.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The C compiler and linker are needed for building the bytecode runtime
for the host.  However, we also want a &lt;em&gt;target&lt;/em&gt; toolchain C compiler,
assembler, and linker to be used for generated programs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Similarly, the machine and system properties are correct for building
the bytecode runtime on the host.  But we want the &lt;em&gt;target&lt;/em&gt; machine
and system properties for building the runtime to be used by generated
programs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This suggests a two-phase build process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Phase 1: run &lt;code&gt;configure&lt;/code&gt; as usual to determine the properties of the
host system.  Post-modify the configuration properties just enough to
create a native-code cross compiler for the target.  Then build the
native-code compiler as usual.  This native-code compiler runs on the
bytecode interpreter (&lt;code&gt;ocamlrun&lt;/code&gt;) of the host, and generates native
code for the target.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Phase 2: run &lt;code&gt;configure&lt;/code&gt; on the target system to determine the
properties of the target system.  Then rebuild just the runtime on the
host using the target toolchain and these properties of the target
system.  The resulting runtime works for the compiled programs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the target system is insufficiently Unix-like to run the &lt;code&gt;configure&lt;/code&gt;
script, it will be necessary to determine the configuration parameters
by some other method.&lt;/p&gt;

&lt;p&gt;This is how both OCamlXARM and OCamlXSim are built.  For people really
interested in the details, the following sections show the build process
for OCamlXSim 3.1.7.  You&#38;#8217;ll find the code in an OS X shell script named
&lt;code&gt;xsim-build&lt;/code&gt;.&lt;/p&gt;

&lt;h4 id=&#34;phase1&#34;&gt;Phase 1&lt;/h4&gt;

&lt;p&gt;The configuration step of Phase 1 looks essentially like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;export&#38;#160;PLT=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform
export SDK=/Developer/SDKs/iPhoneSimulator6.0.sdk

config1 () {
    # Configure for building bytecode interpreter to run on Intel OS X.
    # But specify iOSSim parameters for assembly and partial link.
    ./configure \
            -cc &#34;gcc&#34; \
            -as &#34;$PLT/Developer/usr/bin/gcc -arch i386 -c&#34; \
            -aspp &#34;$PLT/Developer/usr/bin/gcc -arch i386 -c&#34;
    # Post-modify config/Makefile to select i386 back end for ocamlopt
    # (i386 assembly code).
    sed \
        -e &#39;s/^ARCH[    ]*=.*/ARCH=i386/&#39; \
        -e &#39;s/^MODEL[    ]*=.*/MODEL=default/&#39; \
        -e &#34;s#^PARTIALLD[    ]*=.*#PARTIALLD=$PLT/Developer/usr/bin/ld -r#&#34; \
        config/Makefile
    # Post-modify utils/config.ml.
    make utils/config.ml
    sed \
        -e &#39;s#let[      ][      ]*mkexe[        ]*=.*#let mkexe =&#34;&#39;&#34;$PLT/Developer/usr/bin/gcc -arch i386 -Wl,-objc_abi_version,2 -Wl,-no_pie -gdwarf-2 -isysroot $PLT$SDK&#34;&#39;&#34;#&#39; \
        -e &#39;s#let[      ][      ]*bytecomp_c_compiler[  ]*=.*#let bytecomp_c_compiler =&#34;&#39;&#34;$PLT/Developer/usr/bin/gcc -arch i386 -gdwarf-2 -isysroot $PLT$SDK&#34;&#39;&#34;#&#39; \
        -e &#39;s#let[      ][      ]*native_c_compiler[    ]*=.*#let native_c_compiler =&#34;&#39;&#34;$PLT/Developer/usr/bin/gcc -arch i386 -gdwarf-2 -isysroot $PLT$SDK&#34;&#39;&#34;#&#39; \
        utils/config.ml
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;configure&lt;/code&gt; step itself specifies the C compiler of the host
(&lt;code&gt;gcc&lt;/code&gt;), which is needed to build the bytecode runtime.  The assembler,
however, isn&#38;#8217;t needed in this phase.  So the &lt;code&gt;configure&lt;/code&gt; step can
specify the &lt;em&gt;target&lt;/em&gt; tools for the two types of assembly&#38;#8212;in both cases,
it specifies the &lt;code&gt;gcc&lt;/code&gt; of the target toolchain.  This means that the
generated cross compiler will run the proper tools when it assembles its
generated native code.&lt;/p&gt;

&lt;p&gt;After generating configuration information for the host, the script then
post-modifies it to become a cross compiler.  Most importantly, it
modifies &lt;code&gt;config/Makefile&lt;/code&gt; to set its &lt;code&gt;ARCH&lt;/code&gt; variable to the target
architecture.  As mentioned above, this is the key step that attaches
the target code generator to the host compiler.  The other changes
specify a more particular model of CPU (not really used for OCamlXSim)
and the target tool chain command for doing partial linking.&lt;/p&gt;

&lt;p&gt;Note that for OCamlXSim, the target architecture is &lt;code&gt;i386&lt;/code&gt;.  The iOS
Simulator is a 32-bit Intel hardware environment with libraries that
recreate the software environment of iOS devices.  In the build script
for OCamlXARM, the target architecture is &lt;code&gt;armv7&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This leaves the question of how the cross compiler should compile any C
programs that are given on its command line, and how it should link the
results into an OCaml executable.  These commands are inserted at an
even deeper level, to avoid interfering with the compilation and linking
of the cross compiler runtime.  The second set of modifications works by
generating &lt;code&gt;utils/config.ml&lt;/code&gt; and modifying its commands to be those of
the target toolchain.&lt;/p&gt;

&lt;p&gt;The build step of Phase 1 looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;build1 () {
    # Don&#39;t assemble asmrun/i386.S for Phase 1 build.  Modify
    # asmrun/Makefile temporarily to disable.  Be really sure to put
    # back for Phase 2.
    trap &#39;mv -f asmrun/Makefile.aside asmrun/Makefile&#39; EXIT
    grep -q &#39;^[         ]*ASMOBJS[      ]*=&#39; asmrun/Makefile &#38;amp;&#38;amp; \
        mv -f asmrun/Makefile asmrun/Makefile.aside
    sed -e &#39;/^[        ]*ASMOBJS[      ]*=/s/^/#/&#39; \
        asmrun/Makefile.aside &#38;gt; asmrun/Makefile
    make world &#38;amp;&#38;amp; make opt
    mv -f asmrun/Makefile.aside asmrun/Makefile
    trap - EXIT
    # Save the Phase 1 shared (dynamically loadable) libraries and
    # restore them after Phase 2.  They&#39;re required by some OCaml
    # utilities, such as camlp4.
    #
    find . -name &#39;*.so&#39; -exec mv {} {}phase1 \;
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This step basically just runs &lt;code&gt;make world&lt;/code&gt; and &lt;code&gt;make opt&lt;/code&gt; as usual.
However, it turns out to be necessary to make some tricky changes before
and after.&lt;/p&gt;

&lt;p&gt;First, the assembled output of &lt;code&gt;asmrun/i386.S&lt;/code&gt; won&#38;#8217;t be compatible with
the rest of the bytecode runtime.  So we remove it from the build rule
of &lt;code&gt;asmrun/Makefile&lt;/code&gt;, and restore it later.  This works because this
file is needed only for native executables, and we&#38;#8217;re producing only
bytecode executables at this point.&lt;/p&gt;

&lt;p&gt;Second, the dynamically loadable libraries of the bytecode runtime will
be overwritten during Phase 2.  These libraries &lt;em&gt;are&lt;/em&gt; needed by the
bytecode executables.  So we move them aside temporarily, and restore
them at the end of Phase 2.&lt;/p&gt;

&lt;h4 id=&#34;phase2&#34;&gt;Phase 2&lt;/h4&gt;

&lt;p&gt;For Phase 2, we&#38;#8217;d like to run &lt;code&gt;configure&lt;/code&gt; on our target system.  This
can be tricky in general, but for OCamlXSim it&#38;#8217;s relatively easy.  The
iOS Simulator actually runs as a separate software environment on OS X,
our host system.  It&#38;#8217;s possible to generate and run code in this
environment by specifying the proper command-line options.&lt;/p&gt;

&lt;p&gt;If you aren&#38;#8217;t so lucky, the requirement is to generate three files:
&lt;code&gt;config/s.h&lt;/code&gt;, &lt;code&gt;config/m.h&lt;/code&gt;, and &lt;code&gt;config/Makefile&lt;/code&gt;.  A possible plan is
to generate these by running &lt;code&gt;configure&lt;/code&gt; on a Unix-like system that&#38;#8217;s as
similar as possible to your target, then make any other modifications by
hand.&lt;/p&gt;

&lt;p&gt;The configuration step of Phase 2 looks essentially like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;config2 () {
    # Clean out OS X runtime
    cd asmrun; make clean; cd ..
    cd stdlib; make clean; cd ..
    cd otherlibs/bigarray; make clean; cd ../..
    cd otherlibs/dynlink; make clean; cd ../..
    cd otherlibs/num; make clean; cd ../..
    cd otherlibs/str; make clean; cd ../..
    cd otherlibs/systhreads; make clean; cd ../..
    cd otherlibs/threads; make clean; cd ../..
    cd otherlibs/unix; make clean; cd ../..
    # Reconfigure for iOSSim environment
    ./configure \
            -host i386-apple-darwin10.0.0d3 \
            -cc &#34;$PLT/Developer/usr/bin/gcc -arch i386 -gdwarf-2 -isysroot $PLT$SDK&#34; \
            -as &#34;$PLT/Developer/usr/bin/gcc -arch i386 -c&#34; \
            -aspp &#34;$PLT/Developer/usr/bin/gcc -arch i386 -c&#34;
    # Rebuild ocamlmklib, so libraries work with iOSSim.
    rm myocamlbuild_config.ml
    cd tools
    make ocamlmklib
    cd ..
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The purpose of Phase 2 is to build a runtime for the target.  So we
start by clearing out the old runtime for the host.  Now that we&#38;#8217;ve
built the cross compiler, it won&#38;#8217;t be needed.&lt;/p&gt;

&lt;p&gt;Next, we rerun &lt;code&gt;configure&lt;/code&gt;, specifying the C compiler and assembler of
the target toolchain (in our case, the iOS Simulator).  We also specify
a specific &lt;code&gt;-host&lt;/code&gt;, so that &lt;code&gt;configure&lt;/code&gt; doesn&#38;#8217;t attempt to guess the CPU
and operating system.&lt;/p&gt;

&lt;p&gt;Then we rebuild ocamlmklib so it works with the target toolchain rather
than the host toolchain.&lt;/p&gt;

&lt;p&gt;The build step of Phase 2 looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;build2 () {
    # Make iOSSim runtime
    cd asmrun; make all; cd ..
    cd stdlib; make all allopt; cd ..
    cd otherlibs/unix; make all allopt; cd ../..
    cd otherlibs/str; make all allopt; cd ../..
    cd otherlibs/num; make all allopt; cd ../..
    cd otherlibs/dynlink; make all allopt; cd ../..
    cd otherlibs/bigarray; make all allopt; cd ../..
    cd otherlibs/systhreads; make all allopt; cd ../..
    cd otherlibs/threads; make all allopt; cd ../..
    # Restore the saved Phase 1 .so files (see above).
    find . -name &#39;*.sophase1&#39; -print | \
        while read f; do \
            fso=&#34;$(expr &#34;$f&#34; : &#39;\(.*\)sophase1$&#39;)so&#34;; mv -f $f $fso; \
        done
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;These commands rebuild the runtime using the new toolchain, then restore
the dynamically loaded libraries of the host runtime that were saved at
the end of Phase 1.  These libraries are used by some of the compiling
tools&#38;#8212;notably, the &lt;code&gt;camlp4&lt;/code&gt; family uses the Unix library.&lt;/p&gt;

&lt;p&gt;Serendipitously, the resulting executables and objects look just like
those of a traditional OCaml release.  So they can be installed using
the unmodified &lt;code&gt;install&lt;/code&gt; rule of the top-level Makefile.  It works out
this way because there are two distinct parts: the bytecode subsystem
(which works on the host), and the native-code subsystem (which works on
the target).  Things don&#38;#8217;t have to be separated this way, but it&#38;#8217;s
convenient for now.&lt;/p&gt;

&lt;p&gt;If you have comments or questions, please leave them below, or email me
at &lt;a href=&#34;&#38;#x6d;&#38;#x61;&#38;#x69;&#38;#108;&#38;#x74;&#38;#x6f;&#38;#x3a;j&#38;#x65;&#38;#x66;&#38;#x66;&#38;#115;&#38;#099;&#38;#x6f;&#38;#064;&#38;#112;&#38;#115;&#38;#x65;l&#38;#x6c;&#38;#x6f;s&#38;#046;&#38;#x63;&#38;#x6f;&#38;#x6d;&#34;&gt;&#38;#106;e&#38;#102;&#38;#x66;&#38;#115;&#38;#099;o&#38;#064;&#38;#112;&#38;#115;&#38;#x65;&#38;#108;l&#38;#x6f;&#38;#x73;&#38;#x2e;&#38;#x63;&#38;#111;&#38;#109;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Posted by: &lt;a href=&#34;http://psellos.com/aboutus.html#jeffreya.scofieldphd&#34;&gt;Jeffrey&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;style type=&#34;text/css&#34;&gt;
.flowaroundimg {
       float: left;
       margin: 0em 1em 0em 0em;
}
.rightoffloat li {
       position: relative;
       left: 1em;
}
&lt;/style&gt;&lt;/p&gt;
&lt;!--#include virtual=&#34;${Base_URL}/templates/footer.html&#34; --&gt;</content></entry><entry><title>OCamlXARM 3.1 for Mountain Lion</title><link href="http://psellos.com/2012/10/2012.10.ocamlxarm-mountain-lion.html"/><id>http://psellos.com/2012/10/2012.10.ocamlxarm-mountain-lion.html</id><updated>2012-10-18T11:00:00-08:00</updated><content type="html">&lt;!--#include virtual=&#34;${Base_URL}/templates/header.html&#34; --&gt;&lt;div class=&#34;date&#34;&gt;October 18, 2012&lt;/div&gt;

&lt;p&gt;For those interested in building iOS apps in OCaml 4, I&#38;#8217;ve just revamped
&lt;a href=&#34;http://psellos.com/ocaml/compile-to-iphone.html&#34;&gt;OCamlXARM 3.1&lt;/a&gt; for the latest OS X
release, OS X 10.8 (Mountain Lion).  The only difference is in the
default iOS SDK, which I changed from iOS 5.1 to iOS 6.0.  Otherwise,
this was just a recompile.&lt;/p&gt;

&lt;div class=&#34;flowaroundimg&#34; style=&#34;margin-top: 1.0em;&#34;&gt;
&lt;a href=&#34;http://psellos.com/ocaml/compile-to-iphone.html&#34;&gt;&lt;img src=&#34;http://psellos.com/images/ipad-mirror-man.png&#34;&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;You can get binary releases of OCamlXARM here:&lt;/p&gt;

&lt;ul class=&#34;rightoffloat&#34;&gt;
&lt;li&gt;&lt;a href=&#34;http://psellos.com/pub/ocamlxarm/ocaml-4.00.0+xarm-3.1.7.dmg&#34;&gt;OCamlXARM 3.1.7 for Lion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://psellos.com/pub/ocamlxarm/ocaml-4.00.0+xarm-3.1.8.dmg&#34;&gt;OCamlXARM 3.1.8 for Mountain Lion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For information on how to build from sources and how to test an
installation, see &lt;a href=&#34;http://psellos.com/ocaml/compile-to-iphone.html&#34;&gt;Compile OCaml for
iOS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;My next plan is to make a Mountain Lion release of OCamlXSim, which will
build against the iOS 6 Simulator by default.&lt;/p&gt;

&lt;p&gt;In the background I&#38;#8217;m trying to invent an iPad app that will encourage
you to live in the present moment.  An old friend suggests that it could
be based on managing a complex undertaking on-screen.  Say, something
like organizing eighty middle school kids as they perform a Motown
adaptation of &lt;em&gt;The Tempest&lt;/em&gt;.  This is an intriguing idea, and the
soundtrack would be excellent.&lt;/p&gt;

&lt;p&gt;However, I&#38;#8217;m thinking that the app should focus more on &lt;em&gt;you&lt;/em&gt; (the
person running the app).  I imagine that the app shows you on the
screen, and you can manipulate the image of yourself by touching and
dragging your arms and legs, etc.  In the app, your iPad is lost
somewhere in your house.  Your goal is to solve a series of logistical
puzzles to find the missing iPad, and then run the same app in the app
that you&#38;#8217;re running in real life.  If you succeed, there&#38;#8217;s a
time-tunnel-like graphic that transports you through a kaleidoscopic
hall of mirrors into the present moment.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The largest living land mammal is the absent mind. &#38;#8212;Don Van Vliet
  (1941&#38;#8211;2010)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As I&#38;#8217;ve said before, OCaml is such a powerful language it gives me great
ideas for apps.&lt;/p&gt;

&lt;p&gt;If you have comments or questions, please leave them below, or email me
at &lt;a href=&#34;&#38;#x6d;&#38;#x61;&#38;#x69;&#38;#108;&#38;#x74;&#38;#x6f;&#38;#x3a;j&#38;#x65;&#38;#x66;&#38;#x66;&#38;#115;&#38;#099;&#38;#x6f;&#38;#064;&#38;#112;&#38;#115;&#38;#x65;l&#38;#x6c;&#38;#x6f;s&#38;#046;&#38;#x63;&#38;#x6f;&#38;#x6d;&#34;&gt;&#38;#106;e&#38;#102;&#38;#x66;&#38;#115;&#38;#099;o&#38;#064;&#38;#112;&#38;#115;&#38;#x65;&#38;#108;l&#38;#x6f;&#38;#x73;&#38;#x2e;&#38;#x63;&#38;#111;&#38;#109;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Posted by: &lt;a href=&#34;http://psellos.com/aboutus.html#jeffreya.scofieldphd&#34;&gt;Jeffrey&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;style type=&#34;text/css&#34;&gt;
.flowaroundimg {
       float: left;
       margin: 0em 1em 0em 0em;
}
.rightoffloat li {
       position: relative;
       left: 1em;
}
&lt;/style&gt;&lt;/p&gt;
&lt;!--#include virtual=&#34;${Base_URL}/templates/footer.html&#34; --&gt;</content></entry><entry><title>Archimedean Solids in OCaml</title><link href="http://psellos.com/2012/10/2012.10.eurekaslam-1.html"/><id>http://psellos.com/2012/10/2012.10.eurekaslam-1.html</id><updated>2012-10-13T11:00:00-08:00</updated><content type="html">&lt;!--#include virtual=&#34;${Base_URL}/templates/header.html&#34; --&gt;&lt;div class=&#34;date&#34;&gt;October 13, 2012&lt;/div&gt;

&lt;p&gt;One of the many ideas I have on the back burner is to apply
&#38;#8220;crowdsourcing&#38;#8221; to the age-old question of whether the Platonic solids
or the Archimedean solids are cooler.  One day I&#38;#8217;d like to make an OCaml
iOS app that shows a pair of the different masters&#38;#8217; polyhedra and lets
you vote on which is cooler.&lt;/p&gt;

&lt;div class=&#34;flowaroundimg&#34; style=&#34;margin-top: 1.0em;&#34;&gt;
&lt;a href=&#34;https://forge.ocamlcore.org/projects/polydroml/&#34;&gt;&lt;img src=&#34;http://psellos.com/images/girco-waikawa-p3.png&#34;&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;Recently I was delighted to find that there&#38;#8217;s a little OCaml library
called &lt;a href=&#34;https://forge.ocamlcore.org/projects/polydroml/&#34;&gt;Polydroml&lt;/a&gt; that calculates geometric information for
nearly all the uniform polyhedra.  It&#38;#8217;s based on the &lt;a href=&#34;http://en.wikipedia.org/wiki/Wythoff_construction&#34;&gt;Wythoff
construction&lt;/a&gt;, which unifies all the different polyhedra
through the single idea of tiling the surface of the sphere with
spherical triangles.&lt;/p&gt;

&lt;p&gt;Polydroml is the work of Fabian Pijcke and Pierre Hauweele.  The current
Polydroml code supports all but four of the Archimedean solids.  I&#38;#8217;m the
kind of guy who likes to collect the whole set, so I spent a couple days
adding support for two more polyhedra to the library.&lt;/p&gt;

&lt;p&gt;The two I added are the &lt;a href=&#34;http://en.wikipedia.org/wiki/Truncated_cuboctahedron&#34;&gt;great rhombicuboctahedron&lt;/a&gt; (shown in the
figure) and the &lt;a href=&#34;http://en.wikipedia.org/wiki/Truncated_icosidodecahedron&#34;&gt;great rhombicosidodecahedron&lt;/a&gt;.  They&#38;#8217;re
characterized by the fact that their vertices are located &lt;em&gt;inside&lt;/em&gt; the
spherical triangles of the Wythoff construction&#38;#8212;not on their edges.  As
a result, they have more faces than the simpler polyhedra and hence are
cooler.  (But don&#38;#8217;t let me influence your vote when the app comes out.)&lt;/p&gt;

&lt;p&gt;I fear there aren&#38;#8217;t many people working with polyhedra in OCaml, but
maybe I&#38;#8217;ll be pleasantly surprised.  If you&#38;#8217;re interested you can get
Polydroml itself, my patch to Polydroml, or a version of Polydroml with
my patch already applied, at the following links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://psellos.com/pub/eurekaslam/polydroml-0.1.0.zip&#34;&gt;Polydroml 0.1.0, repackaged as a zipfile&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://psellos.com/pub/eurekaslam/incenter-1.0.0.diff&#34;&gt;Incenter 1.0.0, extra polyhedra patch for Polydroml&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://psellos.com/pub/eurekaslam/polydromlp-0.1.0.zip&#34;&gt;Polydroml 0.1.0, with extra polyhedra patch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(For convenience I&#38;#8217;ve repackaged Polydroml as a zipfile&#38;#8212;see the library
link above for information on the official release.  I have no
relationship to the authors of Polydroml, other than that I think they
must be pretty cool.)&lt;/p&gt;

&lt;p&gt;The final two unimplemented Archimedean solids are so-called &#38;#8220;snub&#38;#8221;
forms, which are possibly the coolest of all the convex uniform
polyhedra (just my opinion&#38;#8212;not an official endorsement).  I&#38;#8217;m hoping to
add support for them pretty soon, after some further study of the
Wythoff construction.&lt;/p&gt;

&lt;p&gt;I enjoyed learning some spherical geometry while working on this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A spherical triangle is determined by its three angles (no similar
triangles on the sphere).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Spherical lines (great circles) intersect in two points!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Need to do constructions on the surface of the sphere, not in the
plane of your triangle!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It gives me newfound respect for Archimedes, who somehow figured it all
out while relaxing in the bath.&lt;/p&gt;

&lt;p&gt;If you have comments or questions, please leave them below, or email me
at &lt;a href=&#34;&#38;#x6d;&#38;#x61;&#38;#x69;&#38;#108;&#38;#x74;&#38;#x6f;&#38;#x3a;j&#38;#x65;&#38;#x66;&#38;#x66;&#38;#115;&#38;#099;&#38;#x6f;&#38;#064;&#38;#112;&#38;#115;&#38;#x65;l&#38;#x6c;&#38;#x6f;s&#38;#046;&#38;#x63;&#38;#x6f;&#38;#x6d;&#34;&gt;&#38;#106;e&#38;#102;&#38;#x66;&#38;#115;&#38;#099;o&#38;#064;&#38;#112;&#38;#115;&#38;#x65;&#38;#108;l&#38;#x6f;&#38;#x73;&#38;#x2e;&#38;#x63;&#38;#111;&#38;#109;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Posted by: &lt;a href=&#34;http://psellos.com/aboutus.html#jeffreya.scofieldphd&#34;&gt;Jeffrey&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;style type=&#34;text/css&#34;&gt;
.flowaroundimg {
       float: left;
       margin: 0em 1em 0em 0em;
}
&lt;/style&gt;&lt;/p&gt;
&lt;!--#include virtual=&#34;${Base_URL}/templates/footer.html&#34; --&gt;</content></entry><entry><title>OCaml 4.00.0 for iOS ARMv6</title><link href="http://psellos.com/2012/10/2012.10.ocamlxarmv6-ocaml4-released.html"/><id>http://psellos.com/2012/10/2012.10.ocamlxarmv6-ocaml4-released.html</id><updated>2012-10-03T11:00:00-08:00</updated><content type="html">&lt;!--#include virtual=&#34;${Base_URL}/templates/header.html&#34; --&gt;&lt;div class=&#34;date&#34;&gt;October 3, 2012&lt;/div&gt;

&lt;p&gt;After testing all the apps I can, I&#38;#8217;m ready to release my port of OCaml
4.00.0 for the earliest iOS devices, the iPhones and iPod Touches with
ARMv6 processors.  Since Apple has dropped support for ARMv6 from the
latest Xcode, this port now has mostly nostalgic value I guess.&lt;/p&gt;

&lt;div class=&#34;flowaroundimg&#34; style=&#34;margin-top: 1.0em;&#34;&gt;
&lt;a href=&#34;http://psellos.com/ocaml/compile-to-iphone-v6.html&#34;&gt;&lt;img src=&#34;http://psellos.com/images/vorolambda-b3-p2.png&#34;&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;On the other hand, I have a couple of first-generation iPhones around my
house, and they&#38;#8217;re still extremely nice little devices.  You often hear
about people who even today have racks of outdated PowerPC Macs in their
basement, running market analysis algorithms and making profitable stock
trades.  Or maybe I&#38;#8217;m the only one who&#38;#8217;s ever heard of people like that.
At any rate, the point is that there are lots of ways to use outdated
equipment creatively.&lt;/p&gt;

&lt;p&gt;After this pep talk, perhaps you&#38;#8217;d like to try OCamlXARMv6, which is
what I&#38;#8217;m calling this compiler.  You can download a &lt;a href=&#34;http://psellos.com/pub/ocamlxarm/ocaml-4.00.0+xarm-3.1.2-v6.dmg&#34;&gt;prebuilt binary of
OCamlXARMv6&lt;/a&gt;.  You can also build OCamlXARMv6 from
sources&#38;#8212;instructions are on the &lt;a href=&#34;http://psellos.com/ocaml/compile-to-iphone-v6.html&#34;&gt;Compile OCaml for Early iOS&lt;/a&gt;
page.&lt;/p&gt;

&lt;p&gt;OCamlXARMv6 runs on OS X and generates apps using the toolchain that
comes with Xcode.  Since these are now nostalgia devices, you need to
use a classic release of Xcode.  The &lt;a href=&#34;http://psellos.com/ocaml/compile-to-iphone-v6.html&#34;&gt;Compile OCaml for Early
iOS&lt;/a&gt; page tells how to get an old Xcode release.&lt;/p&gt;

&lt;p&gt;This project was just a small change to OCamlXARM (which compiles OCaml
4.00.0 for current iOS devices):&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Once again, the majority of the work had already been done by Benedikt
  Meurer, who wrote the new ARM code generator for OCaml 4.00.0.  His
  code generator already supports the ARMv6 architecture.  I just had to
  add a new target system/model and set the defaults properly.&lt;/p&gt;
  
  &lt;p&gt;However, I did have to add support for the VFPv2 floating point
  instruction set, as Meurer&#38;#8217;s generator supports only VFPv3.  This was
  a small change, but it was fun to get it working.  I&#38;#8217;ve already
  written about this change in &lt;a href=&#34;http://psellos.com/2012/09/2012.09.ocaml4-vfpv2.html&#34;&gt;OCaml 4.00.0 Patches for VFPv2&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I spend a lot of time &#38;#8220;monitoring&#38;#8221; this website, Psellos.com.  Something
I&#38;#8217;ve always wanted is a little display that lets me see a summary of the
status&#38;#8212;how many people are reading this blog vs. the Tompa blog, how
many new visitors we&#38;#8217;ve had today, whether the mailer is being attacked
by a Portuguese password guesser, and so on.  It strikes me that an old
iPhone would be great for this.  I can write a quick app in OCaml and
just leave it running on the iPhone a lot of the time.  Even without a
cell contract, it can access the website over WiFi.  There are lots of
cool things you could do with an old iPhone, it seems to me.&lt;/p&gt;

&lt;p&gt;If you have comments or questions, please leave them below, or email me
at &lt;a href=&#34;&#38;#x6d;&#38;#x61;&#38;#x69;&#38;#108;&#38;#x74;&#38;#x6f;&#38;#x3a;j&#38;#x65;&#38;#x66;&#38;#x66;&#38;#115;&#38;#099;&#38;#x6f;&#38;#064;&#38;#112;&#38;#115;&#38;#x65;l&#38;#x6c;&#38;#x6f;s&#38;#046;&#38;#x63;&#38;#x6f;&#38;#x6d;&#34;&gt;&#38;#106;e&#38;#102;&#38;#x66;&#38;#115;&#38;#099;o&#38;#064;&#38;#112;&#38;#115;&#38;#x65;&#38;#108;l&#38;#x6f;&#38;#x73;&#38;#x2e;&#38;#x63;&#38;#111;&#38;#109;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Posted by: &lt;a href=&#34;http://psellos.com/aboutus.html#jeffreya.scofieldphd&#34;&gt;Jeffrey&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;style type=&#34;text/css&#34;&gt;
.flowaroundimg {
       float: left;
       margin: 0em 1em 0em 0em;
}
&lt;/style&gt;&lt;/p&gt;
&lt;!--#include virtual=&#34;${Base_URL}/templates/footer.html&#34; --&gt;</content></entry><entry><title>OCaml 4.00.0 Patches for VFPv2</title><link href="http://psellos.com/2012/09/2012.09.ocaml4-vfpv2.html"/><id>http://psellos.com/2012/09/2012.09.ocaml4-vfpv2.html</id><updated>2012-09-30T11:00:00-08:00</updated><content type="html">&lt;!--#include virtual=&#34;${Base_URL}/templates/header.html&#34; --&gt;&lt;div class=&#34;date&#34;&gt;September 30, 2012&lt;/div&gt;

&lt;p&gt;I&#38;#8217;ve just gotten OCaml 4.00.0 working on the earliest iOS devices, the
ones that have the ARMv6 architecture.  It turns out, though, that Apple
no longer supports these devices for active development&#38;#8212;Xcode 4.5 has
dropped support for ARMv6.  You can see this in the &lt;a href=&#34;https://developer.apple.com/library/etc/redirect/xcode/release_notes&#34;&gt;Xcode 4.5 release
notes&lt;/a&gt;.  Look for &#38;#8220;Changes, General: iOS.&#38;#8221;&lt;/p&gt;

&lt;div class=&#34;flowaroundimg&#34; style=&#34;margin-top: 1.0em;&#34;&gt;
&lt;a href=&#34;http://psellos.com/ocaml/compile-to-iphone.html&#34;&gt;&lt;img src=&#34;http://psellos.com/images/vorolambda-b3-p2.png&#34;&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;An OCaml 4.00.0 cross compiler for old iOS devices still might be useful
to a few people, though, so I&#38;#8217;m going to release it today or tomorrow as
a stand-alone project.  I&#38;#8217;ve personally enjoyed building OCaml 4.00.0
apps with Xcode 4.3 and running them on a couple of ancient iOS devices
I have around my house.&lt;/p&gt;

&lt;p&gt;In the meantime, one of the things I had to do for this port was to add
VFPv2 support to OCaml 4.00.0.  VFP is the (somewhat poorly named)
standard scalar floating point subsystem for ARM.  The OCaml 4.00.0
compiler comes with support for two variants of VFPv3, but the earliest
iOS devices supported only VFPv2, the previous revision of VFP.&lt;/p&gt;

&lt;p&gt;This was a relatively small and straightforward change, but I thought
there might be some others out there who could use it for other OCaml
ports.  So, I back-ported the changes to the 4.00.0 release, and
produced a set of diffs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://psellos.com/pub/ocamlxarm/ocaml4-vfpv2.diff&#34;&gt;VFPv2 patches for OCaml 4.00.0&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To apply them, download the &lt;a href=&#34;http://caml.inria.fr/pub/distrib/ocaml-4.00/ocaml-4.00.0.tar.gz&#34;&gt;OCaml 4.00.0 source tarball&lt;/a&gt; and
untar it.  Then:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;&lt;code&gt;$ cd ocaml-4.00.0&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;strong&gt;&lt;code&gt;$ patch -p0 &#38;lt; ocamlvfpv2.diff&lt;/code&gt;&lt;/strong&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, build the compiler as usual for your ARM device.  To ask the
generated compiler to use VFPv2, use the flag &lt;code&gt;-ffpu vfpv2&lt;/code&gt;.  However,
if you&#38;#8217;re working on an OCaml port to a new ARM device, you&#38;#8217;ll most
likely need to modify the handling of the default ABI and other settings
in &lt;code&gt;asmcomp/arm/arch.ml&lt;/code&gt; (if you haven&#38;#8217;t already).&lt;/p&gt;

&lt;p&gt;If you have comments or questions, please leave them below, or email me
at &lt;a href=&#34;&#38;#x6d;&#38;#x61;&#38;#x69;&#38;#108;&#38;#x74;&#38;#x6f;&#38;#x3a;j&#38;#x65;&#38;#x66;&#38;#x66;&#38;#115;&#38;#099;&#38;#x6f;&#38;#064;&#38;#112;&#38;#115;&#38;#x65;l&#38;#x6c;&#38;#x6f;s&#38;#046;&#38;#x63;&#38;#x6f;&#38;#x6d;&#34;&gt;&#38;#106;e&#38;#102;&#38;#x66;&#38;#115;&#38;#099;o&#38;#064;&#38;#112;&#38;#115;&#38;#x65;&#38;#108;l&#38;#x6f;&#38;#x73;&#38;#x2e;&#38;#x63;&#38;#111;&#38;#109;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Posted by: &lt;a href=&#34;http://psellos.com/aboutus.html#jeffreya.scofieldphd&#34;&gt;Jeffrey&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;style type=&#34;text/css&#34;&gt;
.flowaroundimg {
       float: left;
       margin: 0em 1em 0em 0em;
}
&lt;/style&gt;&lt;/p&gt;
&lt;!--#include virtual=&#34;${Base_URL}/templates/footer.html&#34; --&gt;</content></entry><entry><title>OCaml 4.00.0 on iOS Simulator Is Released</title><link href="http://psellos.com/2012/09/2012.09.ocamlxsim-ocaml4-released.html"/><id>http://psellos.com/2012/09/2012.09.ocamlxsim-ocaml4-released.html</id><updated>2012-09-24T11:00:00-08:00</updated><content type="html">&lt;!--#include virtual=&#34;${Base_URL}/templates/header.html&#34; --&gt;&lt;div class=&#34;date&#34;&gt;September 24, 2012&lt;/div&gt;

&lt;p&gt;I&#38;#8217;ve just released &lt;a href=&#34;http://psellos.com/ocaml/compile-to-iossim.html&#34;&gt;OCamlXSim 3.1.6&lt;/a&gt;, a version of OCaml
4.00.0 for building apps to run in the iOS Simulator.  Once you build
something you like, you can use &lt;a href=&#34;http://psellos.com/ocaml/compile-to-iphone.html&#34;&gt;OCamlXARM&lt;/a&gt; to recompile for
actual iOS devices and release it in the iTunes App Store.&lt;/p&gt;

&lt;div class=&#34;flowaroundimg&#34; style=&#34;margin-top: 1.0em;&#34;&gt;
&lt;a href=&#34;http://psellos.com/ocaml/compile-to-iossim.html&#34;&gt;&lt;img src=&#34;http://psellos.com/images/vorolambda-b3-p2.png&#34;&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;You can download the compiler as a &lt;a href=&#34;http://psellos.com/pub/ocamlxsim/ocaml-4.00.0+xsim-3.1.6.dmg&#34;&gt;binary package named
ocaml-4.00.0+xsim-3.1.6&lt;/a&gt;.  You can also build OCamlXSim from
sources&#38;#8212;instructions are on the &lt;a href=&#34;http://psellos.com/ocaml/compile-to-iossim.html&#34;&gt;Compile OCaml for iOS
Simulator&lt;/a&gt; page.&lt;/p&gt;

&lt;p&gt;OCamlXSim runs on OS X and generates apps for the iOS Simulator using
the toolchain that comes with Xcode.  The key thing to know about the
iOS Simulator is that &lt;a href=&#34;http://psellos.com/2012/04/2012.04.iossim-vs-osx.html&#34;&gt;it&#38;#8217;s not the same as OS X&lt;/a&gt;.  As a
result, generating a compiler for the Simulator is very similar to
generating one for iOS.&lt;/p&gt;

&lt;div style=&#34;clear: both&#34;&gt;&lt;/div&gt;

&lt;p&gt;I&#38;#8217;d say there were two parts to the project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It requires some trickery to convince OCaml to be a cross compiler.
As with OCamlXARM, what I do is build the compiler 1&#38;#189; times.  The full
build creates a cross compiler whose runtime is for OS X.  The half
build creates an iOS Simulator runtime to be used by the compiled
apps.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The i386 code generator of OCaml 4.00.0 works almost without change.
I made some very small changes to support 64-bit OS X executables.
They&#38;#8217;re only about 9% faster, but I found it an interesting challenge
to get them working.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OCaml is such a powerful language it gives me ideas for really great
apps.  Here&#38;#8217;s one I just thought of now.  You know how there are several
popular apps out there that turn your website into articles in a
magazine for the iPad?&lt;/p&gt;

&lt;p&gt;My idea is that nobody reads magazines any more&#38;#8212;what they do is play
multiplayer online games.  So my app would turn any website into a
multiplayer online game.  Each page of the website becomes a small town
in the game, and each visitor to the website becomes a player in the
game.  The players travel from town to town battling monsters
representing the parts of the website that nobody wants to read (such as
sidebars and banner ads).  The useful contents of the website would be
integrated into the towns (posters on walls, books in the library, menus
in the restaurants, movies at the cinema, etc.).  Instead of comments on
the pages, the players would talk to each other in avatar form.&lt;/p&gt;

&lt;p&gt;If you have comments or questions about this idea (or anything else),
please leave them below, or email me at &lt;a href=&#34;&#38;#x6d;&#38;#x61;&#38;#x69;&#38;#108;&#38;#x74;&#38;#x6f;&#38;#x3a;j&#38;#x65;&#38;#x66;&#38;#x66;&#38;#115;&#38;#099;&#38;#x6f;&#38;#064;&#38;#112;&#38;#115;&#38;#x65;l&#38;#x6c;&#38;#x6f;s&#38;#046;&#38;#x63;&#38;#x6f;&#38;#x6d;&#34;&gt;&#38;#106;e&#38;#102;&#38;#x66;&#38;#115;&#38;#099;o&#38;#064;&#38;#112;&#38;#115;&#38;#x65;&#38;#108;l&#38;#x6f;&#38;#x73;&#38;#x2e;&#38;#x63;&#38;#111;&#38;#109;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Posted by: &lt;a href=&#34;http://psellos.com/aboutus.html#jeffreya.scofieldphd&#34;&gt;Jeffrey&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;style type=&#34;text/css&#34;&gt;
.flowaroundimg {
       float: left;
       margin: 0em 1em 0em 0em;
}
&lt;/style&gt;&lt;/p&gt;
&lt;!--#include virtual=&#34;${Base_URL}/templates/footer.html&#34; --&gt;</content></entry><entry><title>OCaml 4.00.0 on iOS Is Released</title><link href="http://psellos.com/2012/09/2012.09.ocamlxarm-ocaml4-released.html"/><id>http://psellos.com/2012/09/2012.09.ocamlxarm-ocaml4-released.html</id><updated>2012-09-14T11:00:00-08:00</updated><content type="html">&lt;!--#include virtual=&#34;${Base_URL}/templates/header.html&#34; --&gt;&lt;div class=&#34;date&#34;&gt;September 14, 2012&lt;/div&gt;

&lt;p&gt;I&#38;#8217;ve just released &lt;a href=&#34;http://psellos.com/ocaml/compile-to-iphone.html&#34;&gt;OCamlXARM 3.1.7&lt;/a&gt;, a version of OCaml
4.00.0 for building iOS apps.  This is the very latest version of OCaml,
which gives you powers other programmers can only envy.  But please use
your powers for good.&lt;/p&gt;

&lt;div class=&#34;flowaroundimg&#34; style=&#34;margin-top: 1.0em;&#34;&gt;
&lt;a href=&#34;http://psellos.com/ocaml/compile-to-iphone.html&#34;&gt;&lt;img src=&#34;http://psellos.com/images/vorolambda-b3-p2.png&#34;&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;You can download the compiler as a &lt;a href=&#34;http://psellos.com/pub/ocamlxarm/ocaml-4.00.0+xarm-3.1.7.dmg&#34;&gt;binary package named
ocaml-4.00.0+xarm-3.1.7&lt;/a&gt;.  You can also build OCamlXARM from
sources&#38;#8212;instructions are on the &lt;a href=&#34;http://psellos.com/ocaml/compile-to-iphone.html&#34;&gt;Compile OCaml for iOS&lt;/a&gt;
page.&lt;/p&gt;

&lt;p&gt;I&#38;#8217;ve recently decided that most good ideas start as jokes.  When I got
the idea of running OCaml on iOS, it seemed slightly crazy.  But as
things have progressed, it seems more and more sane all the time.  Why
use less powerful, flexible, and rigorous languages when OCaml runs on
iOS just fine?  Why spend time worrying about memory management when you
can have garbage collection?&lt;/p&gt;

&lt;p&gt;OK, well, there are good reasons you might want to use other languages
or worry about memory.  But I&#38;#8217;m going to keep suggesting OCaml anyway,
it builds real (occasionally even profitable) iOS apps and lets you
concentrate on solving your problem rather than building defenses
against all the sources of error in the world.&lt;/p&gt;

&lt;p&gt;OCamlXARM runs on OS X and generates apps for iOS using the toolchain
that comes with Xcode.  I&#38;#8217;d say there were three parts of the project:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;It requires some trickery to convince OCaml to be a cross compiler.
  In essence, you want to build the compiler 1&#38;#189; times.  The full build
  creates a cross compiler whose runtime is for OS X.  The half build
  creates an ARM runtime to be used by the compiled apps.&lt;/p&gt;
  
  &lt;p&gt;The majority of the technically difficult work for OCaml 4.00.0 on iOS
  had already been done by Benedikt Meurer, when he wrote the new ARM
  code generator for OCaml 4.00.0.  I just adapted the output for the
  iOS assembler.  This is partly a textual reformatting problem, and
  partly an exercise in working around limitations of the iOS assembler.&lt;/p&gt;
  
  &lt;p&gt;The ARM code generator of OCaml 4.00.0 is targeted at Linux and its
  ABI.  The ABI of iOS differs in a few ways.  For example, I had to
  make some changes to the code emitted for calling external functions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Along the way we (OCamlXARM testers and I) encountered a couple of bugs
in the base OCaml 4.00.0 release, and some bugs in the iOS toolchain.  I
imported fixes for the OCaml bugs from the INRIA development repository,
and I found workarounds for the iOS toolchain bugs.&lt;/p&gt;

&lt;p&gt;You can read about these episodes in my earlier progress reports &lt;a href=&#34;http://psellos.com/2012/07/2012.07.ocamlxarm-ocaml4-1.html&#34;&gt;OCaml
4.00.0 Working on iOS&lt;/a&gt; and &lt;a href=&#34;http://psellos.com/2012/08/2012.08.ocamlxarm-ocaml4-2.html&#34;&gt;OCaml 4.00.0 on iOS: Progress
Report&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I&#38;#8217;d like to thank Benedikt Meurer for help, and the INRIA team for
fixing the bugs we reported.  I&#38;#8217;d also like to thank my colleagues at
&lt;a href=&#34;http://www.seaiq.com&#34;&gt;SEAiq&lt;/a&gt; for their help in testing.  (The SEAiq guys have recently
demonstrated that OCaml threading works under iOS.  I&#38;#8217;ll post more about
this soon.)&lt;/p&gt;

&lt;p&gt;If you have comments or questions, please leave them below, or email me
at &lt;a href=&#34;&#38;#x6d;&#38;#x61;&#38;#x69;&#38;#108;&#38;#x74;&#38;#x6f;&#38;#x3a;j&#38;#x65;&#38;#x66;&#38;#x66;&#38;#115;&#38;#099;&#38;#x6f;&#38;#064;&#38;#112;&#38;#115;&#38;#x65;l&#38;#x6c;&#38;#x6f;s&#38;#046;&#38;#x63;&#38;#x6f;&#38;#x6d;&#34;&gt;&#38;#106;e&#38;#102;&#38;#x66;&#38;#115;&#38;#099;o&#38;#064;&#38;#112;&#38;#115;&#38;#x65;&#38;#108;l&#38;#x6f;&#38;#x73;&#38;#x2e;&#38;#x63;&#38;#111;&#38;#109;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Posted by: &lt;a href=&#34;http://psellos.com/aboutus.html#jeffreya.scofieldphd&#34;&gt;Jeffrey&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;style type=&#34;text/css&#34;&gt;
.flowaroundimg {
       float: left;
       margin: 0em 1em 0em 0em;
}
&lt;/style&gt;&lt;/p&gt;
&lt;!--#include virtual=&#34;${Base_URL}/templates/footer.html&#34; --&gt;</content></entry><entry><title>Convert Linux ARM Assembly Code for iOS (Update 3)</title><link href="http://psellos.com/2012/08/2012.08.arm-as-to-ios-4.html"/><id>http://psellos.com/2012/08/2012.08.arm-as-to-ios-4.html</id><updated>2012-08-28T11:00:00-08:00</updated><content type="html">&lt;!--#include virtual=&#34;${Base_URL}/templates/header.html&#34; --&gt;&lt;div class=&#34;date&#34;&gt;August 28, 2012&lt;/div&gt;

&lt;p&gt;While getting OCaml 4.00.0 working on iOS, I&#38;#8217;ve learned quite a bit
about the differences between the Linux ARM assembler and the iOS ARM
assembler.  The two are related: the iOS assembler is like a cousin of
the Linux assembler whose ancestors left the home country a few
generations back.  However, the differences between the two were one of
the main problems I had to solve.&lt;/p&gt;

&lt;p&gt;This information was hard won: documentation for the iOS assembler seems
rare to nonexistent (email me if you know where to find it).  So I spent
many hours reading the source code of &lt;code&gt;as(1)&lt;/code&gt; at Apple&#38;#8217;s open source
site.  To help others avoid duplicating the effort, I&#38;#8217;m publishing here
the latest version of my Python script &lt;code&gt;arm-as-to-ios&lt;/code&gt; that converts ARM
assembly code from the Linux format to the required iOS format.  This
script contains all the wisdom I&#38;#8217;ve accumulated so far (including some
that&#38;#8217;s not required for the OCaml-on-iOS project).&lt;/p&gt;

&lt;p style=&#34;background-color: #fed; border: 1px solid #dcb; padding: 0.7em;&#34;&gt;
&lt;em&gt;Note&lt;/em&gt;: For this third update, I added a transformation to work
around a problem with incremental linking of generated object files.
You can read the details of the problem and the workaround in my blog
post &lt;a href=&#34;http://psellos.com/2012/08/2012.08.ocamlxarm-ocaml4-2.html&#34;&gt;OCaml 4.00.0 on
iOS: Progress Report&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;I wrote the script specifically to convert the hand-written ARM assembly
files of the OCaml runtime to work on iOS.  The advantages of using a
script are that the conversion is done consistently, and the script
might still be useful if the assembly code is rewritten in the future.&lt;/p&gt;

&lt;p&gt;Another advantage is that the script might help other people who need to
port ARM assembly code from Linux to iOS.  Granted, there probably
aren&#38;#8217;t a lot of people doing this.  But if you are, maybe the script
will be a useful starting point or at least a careful list of
differences between the assemblers.&lt;/p&gt;

&lt;p&gt;The output of the script is upward compatible.  By this I mean that a
converted assembly file works in its originally supported Linux
environments as well as in iOS.  This means that the converted assembly
files can be sent &#38;#8220;upstream&#38;#8221; to maintainers (if they&#38;#8217;re comfortable with
supporting iOS and/or the extra complexity of the code).&lt;/p&gt;

&lt;p&gt;The current version of &lt;code&gt;arm-as-to-ios&lt;/code&gt; is 1.4.0.  In its current form,
it does the following conversions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Declare the ARM architecture for iOS with a &lt;code&gt;.machine&lt;/code&gt; pseudo-op.  The
possibilities are &lt;code&gt;armv6&lt;/code&gt; and &lt;code&gt;armv7&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Specify that &lt;code&gt;armv7&lt;/code&gt; code should use the more space-efficient Thumb
encoding in iOS.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Generate declarations for functions, similar to the &lt;code&gt;.type&lt;/code&gt; pseudo-op
for Linux assemblers.  It appears that Apple requires &lt;code&gt;.thumb_func&lt;/code&gt;
declarations only for Thumb functions.  Other symbols are apparently
assumed to be ARM functions.  To make this work upward-compatibly, I
define an assembly macro named &lt;code&gt;.funtype&lt;/code&gt; that is expanded properly in
the different environments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make sure that global symbols have the right format.  For Linux, they
look like &#38;#8220;&lt;code&gt;abc&lt;/code&gt;&#38;#8221;.  For iOS, they look like &#38;#8220;&lt;code&gt;_abc&lt;/code&gt;&#38;#8221; (with a leading
underscore).  To support upward compatibility, this is handled by a
cpp macro named &lt;code&gt;Glo()&lt;/code&gt; that generates the proper symbol form for each
environment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make sure that assembler-local symbols have the right format.  For
Linux assemblers, they look like &#38;#8220;&lt;code&gt;.Lxxx&lt;/code&gt;&#38;#8221;.  For the iOS assembler,
they look like &#38;#8220;&lt;code&gt;Lxxx&lt;/code&gt;&#38;#8221;.  To support upward compatibly, this is
handled by a cpp macro named &lt;code&gt;Loc()&lt;/code&gt; that generates the proper symbol
form for each environment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Replace uses of &lt;code&gt;=&lt;/code&gt;&lt;em&gt;value&lt;/em&gt; notation by explicit loads from memory.
The Linux ARM assemblers interpret &lt;code&gt;ldr rM, =&lt;/code&gt;&lt;em&gt;value&lt;/em&gt; to mean that the
&lt;em&gt;value&lt;/em&gt; should be loaded into register M immediately (using &lt;code&gt;mov&lt;/code&gt;) if
possible, and loaded from memory (using &lt;code&gt;ldr&lt;/code&gt; with PC-relative
addressing) otherwise.  The Apple assembler seems not to support this,
so &lt;code&gt;arm-as-to-ios&lt;/code&gt; replaces uses of &lt;code&gt;=&lt;/code&gt;&lt;em&gt;value&lt;/em&gt; with explicit memory
loads, emitting the pool of values into the &lt;code&gt;.text&lt;/code&gt; segment at the end
of the file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Convert jump tables (for the &lt;code&gt;tbh&lt;/code&gt; instruction) to a form that works
with the iOS assembler.  The form commonly used in Linux generates a
bad jump table under iOS&#38;#8212;apparently the iOS assembler interprets the
expressions differently.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Convert &#38;#8220;dot relative&#38;#8221; expressions to a form that the iOS assembler
correctly treats as assembly-time constants.  This is a workaround for
what looks very much like an iOS assembler bug that prevents
incremental linking of the generated object files.  (Or possibly it&#38;#8217;s
a bug in the iOS linker.)  Details of the problem and the workaround
are given in my blog post &lt;a href=&#34;http://psellos.com/2012/08/2012.08.ocamlxarm-ocaml4-2.html&#34;&gt;OCaml 4.00.0 on iOS: Progress
Report&lt;/a&gt;.  You can also see
an example of this conversion below.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove uses of two pseudo-ops, &lt;code&gt;.type&lt;/code&gt; and &lt;code&gt;.size&lt;/code&gt;, when assembling
for iOS.  They aren&#38;#8217;t supported by Apple&#38;#8217;s assembler.  This is done by
defining null assembly macros for them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Define a macro &lt;code&gt;cbz&lt;/code&gt; when using ARM encodings for iOS.  The &lt;code&gt;cbz&lt;/code&gt;
instruction is Thumb-only.  The definition replaces it with a pair
of ARM instructions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can download the script here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://psellos.com/pub/ocamlxarm/arm-as-to-ios&#34;&gt;arm-as-to-ios&#38;#8212;modify ARM assembly code for use on iOS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The full text of the script is also included at the end of this post.&lt;/p&gt;

&lt;p&gt;This is the fourth version of &lt;code&gt;arm-as-to-ios&lt;/code&gt;, and there may well be a
few more changes when I work on the &lt;code&gt;armv6&lt;/code&gt; architecture.  As I make
changes, I&#38;#8217;ll keep the linked script up to date.  If there are
significant changes I&#38;#8217;ll make another post about them.&lt;/p&gt;

&lt;p&gt;If you want to try out &lt;code&gt;arm-as-to-ios&lt;/code&gt;, copy and paste the lines from
the end of this post into a file named &lt;code&gt;arm-as-to-ios&lt;/code&gt;, or download it
from the above link.  Mark it as a script with &lt;code&gt;chmod&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ chmod +x arm-as-to-ios&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To use the script, specify the name of an ARM assembly file.  If no
files are given, the script processes its standard input.&lt;/p&gt;

&lt;p&gt;The following small example demonstrates the translations that
&lt;code&gt;arm-as-to-ios&lt;/code&gt; performs.  Here is a small file of Linux ARM assembly
code:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;        .syntax unified
        .text
        .align  2
        .globl  example
        .type example, %function
example:
        sub     r10, r10, 8
        cmp     r10, r11
        bcc     1f
        bx      lr
1:
        ldr     r7, =last_return_address
        str     lr, [r7]
        bl      .Lcall_gc
        ldr     lr, [r7]
        b       example

.Lcall_gc:
        ldr     r12, =bottom_of_stack
        str     sp, [r12]
        bl      garbage_collection
        bx      lr

/* Jump table fragment */

.Ljump:
        tbh     [pc, r4, lsl #1]
        .short  (.Ltest1-.)/2+0
        .short  (.Ltest2-.)/2+1
        .short  (.Ltest3-.)/2+2
.Ltest1:
        ldr     r4, [r4]
.Ltest2:
        str     r6, [sp, 8]
.Ltest3:
        str     r8, [r12]

/* Dot relative (frame table fragment) */

        .word   .L200000 - . + 0xfc000000
        .long   0x1c9080
        .thumb_func     example
        .word   example
        .short  8
        .short  0
.L200000:
        .asciz  &#34;example.ml&#34;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you run &lt;code&gt;arm-as-to-ios&lt;/code&gt; on this file, you get the following output
that works for both Linux and iOS assemblers:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;        .syntax unified

/* Apple compatibility macros */
#if defined(SYS_macosx)
#define Glo(s) _##s
#define Loc(s) L##s
#if defined(MODEL_armv6)
        .machine  armv6
        .macro  .funtype
        .endm
        .macro  cbz
        cmp     $0, #0
        beq     $1
        .endm
#else
        .machine  armv7
        .thumb
        .macro  .funtype
        .thumb_func $0
        .endm
#endif
        .macro  .type
        .endm
        .macro  .size
        .endm
#else
#define Glo(s) s
#define Loc(s) .L##s
        .macro  .funtype symbol
        .type  \symbol, %function
        .endm
#endif
/* End Apple compatibility macros */

        .text
        .align  2
        .globl  Glo(example)
        .funtype  Glo(example)
Glo(example):
        sub     r10, r10, 8
        cmp     r10, r11
        bcc     1f
        bx      lr
1:
        ldr     r7, Loc(Plast_return_address)
        str     lr, [r7]
        bl      Loc(call_gc)
        ldr     lr, [r7]
        b       Glo(example)

Loc(call_gc):
        ldr     r12, Loc(Pbottom_of_stack)
        str     sp, [r12]
        bl      Glo(garbage_collection)
        bx      lr

/* Jump table fragment */

Loc(jump):
        tbh     [pc, r4, lsl #1]
Loc(B27):
        .short  (Loc(test1)-Loc(B27))/2
        .short  (Loc(test2)-Loc(B27))/2
        .short  (Loc(test3)-Loc(B27))/2
Loc(test1):
        ldr     r4, [r4]
Loc(test2):
        str     r6, [sp, 8]
Loc(test3):
        str     r8, [r12]

/* Dot relative (frame table fragment) */

DR40 =   Loc(200000) - . + 0xfc000000
        .word DR40
        .long   0x1c9080
        .thumb_func     Glo(example)
        .word   Glo(example)
        .short  8
        .short  0
Loc(200000):
        .asciz  &#34;example.ml&#34;

/* Pool of addresses loaded into registers */

        .text
        .align 2
Loc(Plast_return_address):
        .long Glo(last_return_address)
Loc(Pbottom_of_stack):
        .long Glo(bottom_of_stack)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The output consists of a fixed prefix followed by the translation of the
input file, followed by the pool of values to be loaded into registers.&lt;/p&gt;

&lt;p&gt;The following shows a successful assembly for iOS of the &lt;code&gt;arm.S&lt;/code&gt; file
from OCaml 4.00.0.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ PLT=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform
$ PLTBIN=$PLT/Developer/usr/bin
$ arm-as-to-ios asmrun/arm.S &#38;gt; armcompat.S
$ $PLTBIN/gcc -c -DSYS_macosx -DMODEL_armv7 -o armcompat.o armcompat.S
$ file armcompat.o
armcompat.o: Mach-O object arm
$ otool -tv armcompat.o | head
armcompat.o:
(__TEXT,__text) section
caml_call_gc:
00000000        f8dfc1e0        ldr.w   ip, [pc, #480]  @ 0x1e4
00000004        f8cce000        str.w   lr, [ip]
00000008        f8dfc1dc        ldr.w   ip, [pc, #476]  @ 0x1e8
0000000c        f8ccd000        str.w   sp, [ip]
00000010        ed2d0b10        vstmdb  sp!, {d0-d7}
00000014        e92d50ff        stmdb   sp!, {r0, r1, r2, r3, r4, r5, r6, r7, ip, lr}
00000018        f8dfc1d0        ldr.w   ip, [pc, #464]  @ 0x1ec&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The following shows the compatible file being generated and assembled
under Debian ARMEL (ARM-based Linux system).  Note that the generated
file &lt;code&gt;armcompat.S&lt;/code&gt; is identical to the above&#38;#8212;the output of
&lt;code&gt;arm-as-to-ios&lt;/code&gt; is a single file that works in both environments.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ ./arm-as-to-ios asmrun/arm.S &#38;gt; armcompat.S
$ gcc -c -DSYS_linux_eabihf -o armcompat.o armcompat.S 
$ file armcompat.o
armcompat.o: ELF 32-bit LSB relocatable, ARM, version 1 (SYSV), not stripped
$ objdump -d armcompat.o | grep -v &#39;^$&#39; | head
armcompat.o:     file format elf32-littlearm
Disassembly of section .text:
00000000 &#38;lt;caml_call_gc&#38;gt;:
   0:   f8df c1e0       ldr.w   ip, [pc, #480]  ; 1e4 &#38;lt;caml_system__code_end&#38;gt;
   4:   f8cc e000       str.w   lr, [ip]
   8:   f8df c1dc       ldr.w   ip, [pc, #476]  ; 1e8 &#38;lt;caml_system__code_end+0x4&#38;gt;
   c:   f8cc d000       str.w   sp, [ip]
  10:   ed2d 0b10       vpush   {d0-d7}
  14:   e92d 50ff       stmdb   sp!, {r0, r1, r2, r3, r4, r5, r6, r7, ip, lr}
  18:   f8df c1d0       ldr.w   ip, [pc, #464]  ; 1ec &#38;lt;caml_system__code_end+0x8&#38;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you have any corrections, improvements, or other comments, leave them
below or email me at &lt;a href=&#34;&#38;#x6d;&#38;#x61;&#38;#x69;&#38;#108;&#38;#x74;&#38;#x6f;&#38;#x3a;j&#38;#x65;&#38;#x66;&#38;#x66;&#38;#115;&#38;#099;&#38;#x6f;&#38;#064;&#38;#112;&#38;#115;&#38;#x65;l&#38;#x6c;&#38;#x6f;s&#38;#046;&#38;#x63;&#38;#x6f;&#38;#x6d;&#34;&gt;&#38;#106;e&#38;#102;&#38;#x66;&#38;#115;&#38;#099;o&#38;#064;&#38;#112;&#38;#115;&#38;#x65;&#38;#108;l&#38;#x6f;&#38;#x73;&#38;#x2e;&#38;#x63;&#38;#111;&#38;#109;&lt;/a&gt;.  I&#38;#8217;d be very pleased to hear
if the script has been helpful to anyone.&lt;/p&gt;

&lt;p&gt;Posted by: &lt;a href=&#34;http://psellos.com/aboutus.html#jeffreya.scofieldphd&#34;&gt;Jeffrey&lt;/a&gt;&lt;/p&gt;

&lt;h4 id=&#34;appendix&#34;&gt;Appendix&lt;/h4&gt;

&lt;pre&gt;&lt;code&gt;#!/usr/bin/env python
#
# arm-as-to-ios     Modify ARM assembly code for the iOS assembler
#
# Copyright (c) 2012 Psellos   http://psellos.com/
# Licensed under the MIT License:
#     http://www.opensource.org/licenses/mit-license.php
#
# Resources for running OCaml on iOS: http://psellos.com/ocaml/
#
import sys
import re

VERSION = &#39;1.4.0&#39;

# Character classes for expression lexing.
#
g_ccid0 = &#39;[$.A-Z_a-z\x80-\xff]&#39;      # Beginning of id
g_ccid =  &#39;[$.0-9A-Z_a-z\x80-\xff]&#39;   # Later in id
def ccc(cc):                          # Complement the class
    if cc[1] == &#39;^&#39;:
        return cc[0] + cc[2:]
    return cc[0] + &#39;^&#39; + cc[1:]
def ccce(cc):                         # Complement the class, include EOL
    return &#39;(?:&#39; + ccc(cc) + &#39;|$)&#39;

# Prefixes for pooled symbol labels and jump table base labels.  They&#39;re
# in the space of Linux assembler local symbols.  Later rules will
# modify them to the Loc() form.
#
g_poolpfx = &#39;.LP&#39;
g_basepfx = &#39;.LB&#39;


def exists(p, l):
    for l1 in l:
        if p(l1):
            return True
    return False


def forall(p, l):
    for l1 in l:
        if not p(l1):
            return False
    return True


def add_prefix(instrs):
    # Add compatibility macros for all systems, plus hardware
    # definitions and compatibility macros for iOS.
    #
    # All systems:
    #
    # Glo()     cpp macro for making global symbols (xxx vs _xxx)
    # Loc()     cpp macro for making local symbols (.Lxxx vs Lxxx)
    # .funtype  Expands to .thumb_func for iOS armv7 (null for armv6)
    #           Expands to .type %function for others
    #
    # iOS:
    #
    # .machine  armv6/armv7
    # .thumb    (for armv7)
    # cbz       Expands to cmp/beq for armv6 (Thumb-only instr)
    # .type     Not supported by Apple assembler
    # .size     Not supported by Apple assembler
    #
    defre = &#39;#[ \t]*if.*def.*SYS&#39;  # Add new defs near first existing ones
    skipre = &#39;$|\.syntax[ \t]&#39;     # Skip comment lines (and .syntax)

    for i in range(len(instrs)):
        if re.match(defre, instrs[i][1]):
            break
    else:
        i = 0
    for i in range(i, len(instrs)):
        if not re.match(skipre, instrs[i][1]):
            break
    instrs[i:0] = [
        (&#39;&#39;, &#39;&#39;, &#39;\n&#39;),
        (&#39;/* Apple compatibility macros */&#39;, &#39;&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;#if defined(SYS_macosx)&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;#define Glo(s) _##s&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;#define Loc(s) L##s&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;#if defined(MODEL_armv6)&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.machine  armv6&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.macro  .funtype&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.endm&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.macro  cbz&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;cmp     $0, #0&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;beq     $1&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.endm&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;#else&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.machine  armv7&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.thumb&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.macro  .funtype&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.thumb_func $0&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.endm&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;#endif&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.macro  .type&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.endm&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.macro  .size&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.endm&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;#else&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;#define Glo(s) s&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;#define Loc(s) .L##s&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.macro  .funtype symbol&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.type  \\symbol, %function&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.endm&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;#endif&#39;, &#39;\n&#39;),
        (&#39;/* End Apple compatibility macros */&#39;, &#39;&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;&#39;, &#39;\n&#39;)
    ]
    return instrs


# Regular expression for modified ldr lines
#
g_ldre = &#39;(ldr[ \t][^,]*,[ \t]*)=(([^ \t\n@,/]|/(?!\*))*)(.*)&#39;


def explicit_address_loads(instrs):
    # Linux assemblers allow the following:
    #
    #     ldr rM, =symbol
    #
    # which loads rM with [mov] (immediately) if possible, or creates an
    # entry in memory for the symbol value and loads it PC-relatively
    # with [ldr].
    #
    # The Apple assembler doesn&#39;t seem to support this notation.  If the
    # value is a suitable constant, it emits a valid [mov].  Otherwise
    # it seems to emit an invalid [ldr] that always generates an error.
    # (At least I have not been able to make it work).  So, change uses
    # of =symbol to explicit PC-relative loads.
    #
    # This requires a pool containing the addresses to be loaded.  For
    # now, we just keep track of it ourselves and emit it into the text
    # segment at the end of the file.
    #
    syms = {}
    result = []

    def repl1((syms, result), (a, b, c)):
        global g_poolpfx
        global g_ldre
        (b1, b2, b3) = parse_iparts(b)
        mo = re.match(g_ldre, b3, re.DOTALL)
        if mo:
            if mo.group(2) not in syms:
                syms[mo.group(2)] = len(syms)
            psym = mo.group(2)
            if psym[0:2] == &#39;.L&#39;:
                psym = psym[2:]
            newb3 = mo.group(1) + g_poolpfx + psym + mo.group(4)
            result.append((a, b1 + b2 + newb3, c))
        else:
            result.append((a, b, c))
        return (syms, result)

    def pool1(result, s):
        global g_poolpfx
        psym = s
        if psym[0:2] == &#39;.L&#39;:
            psym = psym[2:]
        result.append((&#39;&#39;, g_poolpfx + psym + &#39;:&#39;, &#39;\n&#39;))
        result.append((&#39;        &#39;, &#39;.long &#39; + s, &#39;\n&#39;))
        return result

    reduce(repl1, instrs, (syms, result))
    if len(syms) &#38;gt; 0:
        result.append((&#39;&#39;, &#39;&#39;, &#39;\n&#39;))
        result.append((&#39;/* Pool of addresses loaded into registers */&#39;,
                        &#39;&#39;, &#39;\n&#39;))
        result.append((&#39;&#39;, &#39;&#39;, &#39;\n&#39;))
        result.append((&#39;        &#39;, &#39;.text&#39;, &#39;\n&#39;))
        result.append((&#39;        &#39;, &#39;.align 2&#39;, &#39;\n&#39;))
        reduce(pool1, sorted(syms, key=syms.get), result)
    return result


def global_symbols(instrs):
    # The form of a global symbol differs between Linux assemblers and
    # the Apple assember:
    #
    # Linux: xxx
    # Apple: _xxx
    #
    # Change occurrences of global symbols to use the Glo() cpp macro
    # defined in our prefix.
    #
    # We consider a symbol to be global if:
    #
    # a.  It appears in a .globl declaration; or
    # b.  It is referenced, has global form, and is not defined
    #
    glosyms = set()
    refsyms = set()
    defsyms = set()
    result = []

    def findglo1 (glosyms, (a, b, c)):
        if re.match(&#39;#&#39;, b):
            # Preprocessor line; nothing to do
            return glosyms
        (b1, b2, b3) = parse_iparts(b)
        mo = re.match(&#39;(\.globl)&#39; + ccce(g_ccid), b3)
        if mo:
            tokens = parse_expr(b3[len(mo.group(1)):])
            if forall(lambda t: token_type(t) in [&#39;space&#39;, &#39;id&#39;, &#39;,&#39;], tokens):
                for t in tokens:
                    if token_type(t) == &#39;id&#39;:
                        glosyms.add(t)
        return glosyms

    def findref1 ((refsyms, skipct), (a, b, c)):

        def looksglobal(s):
            if re.match(&#39;(r|a|v|p|c|cr|f|s|d|q|mvax|wcgr)[0-9]+$&#39;, s, re.I):
                return False # numbered registers
            if re.match(&#39;(wr|sb|sl|fp|ip|sp|lr|pc)$&#39;, s, re.I):
                return False # named registers
            if re.match(&#39;(fpsid|fpscr|fpexc|mvfr1|mvfr0)$&#39;, s, re.I):
                return False # more named registers
            if re.match(&#39;(mvf|mvd|mvfx|mvdx|dspsc)$&#39;, s, re.I):
                return False # even more named registers
            if re.match(&#39;(wcid|wcon|wcssf|wcasf|acc)$&#39;, s, re.I):
                return False # even more named registers
            if re.match(&#39;\.$|\.L|[0-9]|#&#39;, s):
                return False # dot, local symbol, or number
            if re.match(&#39;(asl|lsl|lsr|asr|ror|rrx)$&#39;, s, re.I):
                return False # shift names
            return True

        if re.match(&#39;#&#39;, b):
            # Preprocessor line; nothing to do
            return (refsyms, skipct)

        # Track nesting of .macro/.endm.  For now, we don&#39;t look for
        # global syms in macro defs.  (Avoiding scoping probs etc.)
        #
        if skipct &#38;gt; 0 and re.match(&#39;\.(endm|endmacro)&#39; + ccce(g_ccid), b):
            return (refsyms, skipct - 1)
        if re.match(&#39;\.macro&#39; + ccce(g_ccid), b):
            return (refsyms, skipct + 1)
        if skipct &#38;gt; 0:
            return (refsyms, skipct)
        if re.match(&#39;\.(type|size|syntax|arch|fpu)&#39; + ccce(g_ccid), b):
            return (refsyms, skipct)

        (b1, b2, b3) = parse_iparts(b)
        rtokens = parse_rexpr(b3)
        if len(rtokens) &#38;gt; 1 and rtokens[1] == &#39;.req&#39;:
            # .req has atypical syntax; no symbol refs there anyway
            return (refsyms, skipct)
        for t in rtokens[1:]:
            if token_type(t) == &#39;id&#39; and looksglobal(t):
                refsyms.add(t)
        return (refsyms, skipct)

    def finddef1(defsyms, (a, b, c)):
        if re.match(&#39;#&#39;, b):
            # Preprocessor line
            return defsyms
        (b1, b2, b3) = parse_iparts(b)
        rtokens = parse_rexpr(b3)
        if b1 != &#39;&#39;:
            defsyms.add(b1)
        if len(rtokens) &#38;gt; 1 and rtokens[1] == &#39;.req&#39;:
            defsyms.add(rtokens[0])
        return defsyms

    def repl1((glosyms, result), (a, b, c)):
        if re.match(&#39;#&#39;, b):
            # Preprocessor line
            result.append((a, b, c))
            return (glosyms, result)
        toglo = lambda s: &#39;Glo(&#39; + s + &#39;)&#39;
        (b1, b2, b3) = parse_iparts(b)
        tokens = parse_expr(b3)

        if b1 in glosyms:
            b1 = toglo(b1)
        for i in range(len(tokens)):
            if token_type(tokens[i]) == &#39;id&#39; and tokens[i] in glosyms:
                tokens[i] = toglo(tokens[i])
        result.append((a, b1 + b2 + &#39;&#39;.join(tokens), c))
        return (glosyms, result)

    reduce(findglo1, instrs, glosyms)
    reduce(findref1, instrs, (refsyms, 0))
    reduce(finddef1, instrs, defsyms)
    glosyms |= (refsyms - defsyms)
    reduce(repl1, instrs, (glosyms, result))
    return result


def local_symbols(instrs):
    # The form of a local symbol differs between Linux assemblers and
    # the Apple assember:
    #
    # Linux: .Lxxx
    # Apple: Lxxx
    #
    # Change occurrences of local symbols to use the Loc() cpp macro
    # defined in our prefix.
    #
    lsyms = set()
    result = []

    def find1 (lsyms, (a, b, c)):
        mo = re.match(&#39;(\.L[^ \t:]*)[ \t]*:&#39;, b)
        if mo:
            lsyms.add(mo.group(1))
        return lsyms

    def repl1((lsyms, result), (a, b, c)):
        matches = list(re.finditer(&#39;\.L[^ \t@:,+*/\-()]+&#39;, b))
        if matches != []:
            matches.reverse()
            newb = b
            for mo in matches:
                if mo.group() in lsyms:
                    newb = newb[0:mo.start()] + \
                            &#39;Loc(&#39; + mo.group()[2:] + &#39;)&#39; + \
                            newb[mo.end():]
            result.append((a, newb, c))
        else:
            result.append((a, b, c))
        return (lsyms, result)

    reduce(find1, instrs, lsyms)
    reduce(repl1, instrs, (lsyms, result))
    return result


def funtypes(instrs):
    # Linux assemblers accept declarations like this:
    #
    #     .type  symbol, %function
    #
    # For Thumb functions, the Apple assembler wants to see:
    #
    #     .thumb_func symbol
    #
    # Handle this by converting declarations to this:
    #
    #     .funtype symbol
    #
    # Our prefix defines an appropriate .funtype macro for each
    # environment.
    #
    result = []

    def repl1(result, (a, b, c)):
        mo = re.match(&#39;.type[ \t]+([^ \t,]*),[ \t]*%function&#39;, b)
        if mo:
            result.append((a, &#39;.funtype  &#39; + mo.group(1), c))
        else:
            result.append((a, b, c))
        return result

    reduce(repl1, instrs, result)
    return result


def jump_tables(instrs):
    # Jump tables for Linux assemblers often look like this:
    #
    #     tbh [pc, rM, lsl #1]
    #     .short (.Labc-.)/2+0
    #     .short (.Ldef-.)/2+1
    #     .short (.Lghi-.)/2+2
    #
    # The Apple assembler disagrees about the meaning of this code,
    # producing jump tables that don&#39;t work.  Convert to the following:
    #
    #     tbh [pc, rM, lsl #1]
    # .LBxxx:
    #     .short (.Labc-.LBxxx)/2
    #     .short (.Ldef-.LBxxx)/2
    #     .short (.Lghi-.LBxxx)/2
    #
    # In fact we just convert sequences of .short pseudo-ops of the
    # right form.  There&#39;s no requirement that they follow a tbh
    # instruction.
    #
    baselabs = []
    result = []

    def short_match(seq, op):
        # Determine whether the op is a .short of the form that needs to
        # be converted: .short (symbol-.)/2+k.  If so, return a pair
        # containing the symbol and the value of k.  If not, return
        # None.  The short can only be converted if there were at least
        # k other .shorts in sequence before the current one.  A summary
        # of the previous .shorts is in seq.
        #
        # (A real parser would do a better job, but this was quick to
        # get working.)
        #
        sp = &#39;([ \t]|/\*.*?\*/)*&#39;              # space
        sp1 = &#39;([ \t]|/\*.*?\*/)+&#39;             # at least 1 space
        spe = &#39;([ \t]|/\*.*?\*/|@[^\n]*)*$&#39;    # end-of-instr space
        expr_re0 = (
            &#39;\.short&#39; + sp + &#39;\(&#39; + sp +       # .short (
            &#39;([^ \t+\-*/@()]+)&#39; + sp +         # symbol
            &#39;-&#39; + sp + &#39;\.&#39; + sp + &#39;\)&#39; + sp + # -.)
            &#39;/&#39; + sp + &#39;2&#39; + spe               # /2 END
        )
        expr_re1 = (
            &#39;\.short&#39; + sp + &#39;\(&#39; + sp +       # .short (
            &#39;([^ \t+\-*/@()]+)&#39; + sp +         # symbol
            &#39;-&#39; + sp + &#39;\.&#39; + sp + &#39;\)&#39; + sp + # -.)
            &#39;/&#39; + sp + &#39;2&#39; + sp +              # /2
            &#39;\+&#39; + sp +                        # +
            &#39;((0[xX])?[0-9]+)&#39; + spe           # k END
        )
        expr_re2 = (
            &#39;\.short&#39; + sp1 +                  # .short
            &#39;((0[xX])?[0-9]+)&#39; + sp +          # k
            &#39;\+&#39; + sp + &#39;\(&#39; + sp +            # +(
            &#39;([^ \t+\-*/@()]+)&#39; + sp +         # symbol
            &#39;-&#39; + sp + &#39;\.&#39; + sp + &#39;\)&#39; + sp + # -.)
            &#39;/&#39; + sp + &#39;2&#39; + spe               # /2 END
        )
        mo = re.match(expr_re0, op)
        if mo:
            return(mo.group(3), 0)
        mo = re.match(expr_re1, op)
        if mo:
            k = int(mo.group(11), 0)
            if k &#38;gt; len(seq):
                return None
            return (mo.group(3), k)
        mo = re.match(expr_re2, op)
        if mo:
            k = int(mo.group(2), 0)
            if k &#38;gt; len(seq):
                return None
            return (mo.group(7), k)
        return None

    def conv1 ((baselabs, shortseq, label, result), (a, b, c)):
        # Convert current instr (a,b,c) if it&#39;s a .short of the right
        # form that spans a previous sequence of .shorts.
        #
        (b1, b2, b3) = parse_iparts(b)

        if b3 == &#39;&#39;:
            # No operation: just note label if present.
            result.append((a, b, c))
            if re.match(&#39;\.L.&#39;, b1):
                return (baselabs, shortseq, b1, result)
            return (baselabs, shortseq, label, result)

        if not re.match(&#39;.short[ \t]+[^ \t@]&#39;, b3):
            # Not a .short: clear shortseq and label
            result.append((a, b, c))
            return (baselabs, [], &#39;&#39;, result)

        # We have a .short: figure out the label if any
        if re.match(&#39;\.L&#39;, b1):
            sl = b1
        else:
            sl = label

        mpair = short_match(shortseq, b3)
        if not mpair:
            # A .short, but not of right form
            shortseq.append((len(result), sl))
            result.append((a, b, c))
            return (baselabs, shortseq, &#39;&#39;, result)

        # OK, we have a .short to convert!
        (sym, k) = mpair
        shortseq.append((len(result), sl))

        # Figure out base label (create one if necessary).
        bx = len(shortseq) - 1 - k
        bl = shortseq[bx][1]
        if bl == &#39;&#39;:
            bl = g_basepfx + str(shortseq[bx][0])
            shortseq[bx] = (shortseq[bx][0], bl)
            baselabs.append(shortseq[bx])

        op = &#39;.short\t(&#39; + sym + &#39;-&#39; + bl + &#39;)/2&#39;

        result.append ((a, b1 + b2 + op, c))
        return (baselabs, shortseq, &#39;&#39;, result)

    # Convert, accumulate result and new labels.
    reduce(conv1, instrs, (baselabs, [], &#39;&#39;, result))

    # Add labels created here to the instruction stream.
    baselabs.reverse()
    for (ix, lab) in baselabs:
        result[ix:0] = [(&#39;&#39;, lab + &#39;:&#39;, &#39;\n&#39;)]

    # That does it
    return result


def dot_relative(instrs):
    # The Apple assembler (or possibly the linker) has trouble with code
    # that looks like this:
    #
    #     .word   .Label - . + 0x80000000
    #     .word   0x1966
    # .Label:
    #     .word   0x1967
    #
    # One way to describe the problem is that the assembler marks the
    # first .word for relocation when in fact it&#39;s an assembly-time
    # constant.  Translate to the following form, which doesn&#39;t generate
    # a relocation marking:
    #
    # DR0 =       .Label - . + 0x80000000
    #     .word   DR0
    #     .word   0x1966
    # .Label:
    #     .word   0x1967
    #
    prefix = &#39;DR&#39;
    pseudos = &#39;(\.byte|\.short|\.word|\.long|\.quad)&#39;
    result = []

    def tok_ok(t):
        return t in [&#39;.&#39;, &#39;+&#39;, &#39;-&#39;, &#39;(&#39;, &#39;)&#39;] or \
            token_type(t) in [&#39;space&#39;, &#39;locid&#39;, &#39;number&#39;]

    def dotrel_match(expr):
        # Determine whether the expression is one that needs to be
        # translated.
        tokens = parse_expr(expr)
        return forall(tok_ok, tokens) and \
            exists(lambda t: token_type(t) == &#39;locid&#39;, tokens) and \
            exists(lambda t: token_type(t) == &#39;number&#39;, tokens) and \
            exists(lambda t: t == &#39;-&#39;, tokens) and \
            exists(lambda t: t == &#39;.&#39;, tokens)

    def conv1(result, (a, b, c)):
        if re.match(&#39;#&#39;, b):
            # Preprocessor line
            result.append((a, b, c))
        else:
            (b1, b2, b3) = parse_iparts(b)
            mo = re.match(pseudos + ccce(g_ccid), b3)
            if mo:
                p = mo.group(1)
                expr = b3[len(p):]
                if dotrel_match(expr):
                    sym = prefix + str(len(result))
                    instr = sym + &#39; =&#39; + expr
                    result.append((&#39;&#39;, instr, &#39;\n&#39;))
                    result.append((a, b1 + b2 + p + &#39; &#39; + sym, c))
                else:
                    result.append((a, b, c))
            else:
                result.append((a, b, c))
        return result

    reduce(conv1, instrs, result)
    return result


def read_input():
    # Concatenate all the input files into a string.
    #
    def fnl(s):
        if s == &#39;&#39; or s[-1] == &#39;\n&#39;:
            return s
        else:
            return s + &#39;\n&#39;

    if len(sys.argv) &#38;lt; 2:
        return fnl(sys.stdin.read())
    else:
        input = &#34;&#34;
        for f in sys.argv[1:]:
            try:
                fd = open(f)
                input = input + fnl(fd.read())
                fd.close()
            except:
                sys.stderr.write(&#39;arm-as-to-ios: cannot open &#39; + f + &#39;\n&#39;)
        return input


def parse_instrs(s):
    # Parse the string into assembly instructions, also noting C
    # preprocessor lines.  Each instruction is represented as a triple:
    # (space/comments, instruction, end).  The end is either &#39;;&#39; or
    # &#39;\n&#39;.
    #
    def goodmo(mo):
        if mo == None:
            # Should never happen
            sys.stderr.write(&#39;arm-as-to-ios: internal parsing error\n&#39;)
            sys.exit(1)

    cpp_re = &#39;([ \t]*)(#([^\n]*\\\\\n)*[^\n]*[^\\\\\n])\n&#39;
    comment_re = &#39;[ \t]*#[^\n]*&#39;
    instr_re = (
        &#39;(([ \t]|/\*.*?\*/|@[^\n]*)*)&#39;  # Spaces &#38;amp; comments
        &#39;(([ \t]|/\*.*?\*/|[^;\n])*)&#39;   # &#34;Instruction&#34;
        &#39;([;\n])&#39;                       # End
    )
    instrs = []
    while s != &#39;&#39;:
        if re.match(&#39;[ \t]*#[ \t]*(if|ifdef|elif|else|endif|define)&#39;, s):
            mo = re.match(cpp_re, s)
            goodmo(mo)
            instrs.append((mo.group(1), mo.group(2), &#39;\n&#39;))
        elif re.match(&#39;[ \t]*#&#39;, s):
            mo = re.match(comment_re, s)
            goodmo(mo)
            instrs.append((mo.group(0), &#39;&#39;, &#39;\n&#39;))
        else:
            mo = re.match(instr_re, s, re.DOTALL)
            goodmo(mo)
            instrs.append((mo.group(1), mo.group(3), mo.group(5)))
        s = s[len(mo.group(0)):]
    return instrs


def parse_iparts(i):
    # Parse an instruction into smaller parts, returning a triple of
    # strings (label, colon, operation).  The colon part also contains
    # any surrounding spaces and comments (making the label and the
    # operation cleaner to process).
    #
    # (Caller warrants that the given string doesn&#39;t start with space or
    # a comment.  This is true for strings returned by the instruction
    # parser.)
    #
    lab_re = (
        &#39;([^ \t:/@]+)&#39;                  # Label
        &#39;(([ \t]|/\*.*?\*/|@[^\n]*)*)&#39;  # Spaces &#38;amp; comments
        &#39;:&#39;                             # Colon
        &#39;(([ \t]|/\*.*?\*/|@[^\n]*)*)&#39;  # Spaces &#38;amp; comments
        &#39;([^\n]*)&#39;                      # Operation
    )

    if len(i) &#38;gt; 0 and i[0] == &#39;#&#39;:
        # C preprocessor line; treat as operation.
        return (&#39;&#39;, &#39;&#39;, i)
    mo = re.match(lab_re, i)
    if mo:
        return (mo.group(1), mo.group(2) + &#39;:&#39; + mo.group(4), mo.group(6))
    # No label, just an operation
    return (&#39;&#39;, &#39;&#39;, i)


def parse_expr(s):
    # Parse a string into a sequence of tokens.  A segment of white
    # space (including comments) is treated as a token, so that the
    # tokens can be reassembled into the string again.
    #
    result = []
    while s != &#39;&#39;:
        mo = re.match(&#39;([ \t]|/\*.*?\*/|@.*)+&#39;, s)
        if not mo:
            # Glo(...) and Loc(...) are single tokens
            mo = re.match(&#39;(Glo|Loc)\([^()]*\)&#39;, s)
        if not mo:
            mo = re.match(&#39;&#34;([^\\\\&#34;]|\\\\.)*&#34;&#39;, s)
        if not mo:
            mo = re.match(g_ccid0 + g_ccid + &#39;*&#39;, s)
        if not mo:
            mo = re.match(&#39;[0-9]+[bf]&#39;, s)
        if not mo:
            mo = re.match(&#39;0[Xx][0-9a-fA-F]+|[0-9]+&#39;, s)
        if not mo:
            mo = re.match(&#39;.&#39;, s)
        result.append(mo.group(0))
        s = s[len(mo.group(0)):]
    return result


def parse_rexpr(s):
    # Like parse_expr(), but return only &#34;real&#34; tokens, not the
    # intervening space.
    #
    return filter(lambda t: token_type(t) != &#39;space&#39;, parse_expr(s))


def token_type(t):
    # Determine the type of a token.  Caller warrants that it was
    # returned by parse_expr() or parse_rexpr().
    #
    if re.match(&#39;[ \t]|/\*|@&#39;, t):
        return &#39;space&#39;
    if re.match(&#39;Glo\(&#39;, t):
        return &#39;gloid&#39;
    if re.match(&#39;Loc\(&#39;, t):
        return &#39;locid&#39;
    if re.match(&#39;&#34;&#39;, t):
        return &#39;string&#39;
    if re.match(g_ccid0, t):
        return &#39;id&#39;
    if re.match(&#39;[0-9]+[bf]&#39;, t):
        return &#39;label&#39;
    if re.match(&#39;[0-9]&#39;, t):
        return &#39;number&#39;
    return t # Sui generis


def debug_parse(a, b, c):
    # Show results of instuction stream parse.
    #
    (b1, b2, b3) = parse_iparts(b)
    newb = &#39;{&#39; + b1 + &#39;}&#39; + &#39;{&#39; + b2 + &#39;}&#39; + &#39;{&#39; + b3 + &#39;}&#39;
    sys.stdout.write(&#39;{&#39; + a + &#39;}&#39; + newb + c)


def main():
    instrs = parse_instrs(read_input())
    instrs = explicit_address_loads(instrs)
    instrs = funtypes(instrs)
    instrs = jump_tables(instrs)
    instrs = global_symbols(instrs)
    instrs = local_symbols(instrs)
    instrs = dot_relative(instrs)
    instrs = add_prefix(instrs)
    for (a, b, c) in instrs:
       sys.stdout.write(a + b + c)


main()&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;style type=&#34;text/css&#34;&gt;
.flowaroundimg {
       float: left;
       margin: 0em 1em 0em 0em;
}
pre {
    white-space: pre-wrap;
    width: 96%;
    margin-bottom: 24px;
    overflow: hidden;
    padding: 3px 10px;
    -webkit-border-radius: 3px;
    background-color: #fed;
    border: 1px solid #dcb;
}
code {
    white-space: nowrap;
    font-size: 1.1em;
}
pre code {
    white-space: pre-wrap;
    font-size: 1.1em;
    padding: 0;
    border: none;
    background-color: transparent;
    -webkit-border-radius: 0;
}
&lt;/style&gt;&lt;/p&gt;
&lt;!--#include virtual=&#34;${Base_URL}/templates/footer.html&#34; --&gt;</content></entry><entry><title>OCaml 4.00.0 on iOS: Progress Report</title><link href="http://psellos.com/2012/08/2012.08.ocamlxarm-ocaml4-2.html"/><id>http://psellos.com/2012/08/2012.08.ocamlxarm-ocaml4-2.html</id><updated>2012-08-25T11:00:00-08:00</updated><content type="html">&lt;!--#include virtual=&#34;${Base_URL}/templates/header.html&#34; --&gt;&lt;div class=&#34;date&#34;&gt;August 25, 2012&lt;/div&gt;

&lt;p&gt;After finding and resolving some problems, two of which were very
interesting, I&#38;#8217;m getting close to releasing a version of OCaml 4.00.0
that cross-compiles for iOS devices.  I&#38;#8217;ve tested it with all the OCaml
iOS apps I can, and my colleagues at &lt;a href=&#34;http://www.seaiq.com&#34;&gt;SEAiq&lt;/a&gt; have tested with their
iOS apps also.&lt;/p&gt;

&lt;p&gt;&lt;p style=&#34;background-color: #fed; border: 1px solid #dcb; padding: 0.7em;&#34;&gt; &lt;em&gt;Update&lt;/em&gt;: OCamlXARM 3.1, based on OCaml 4.00.0, has been
released!  Read my blog post &lt;a href=&#34;http://psellos.com/2012/09/2012.09.ocamlxarm-ocaml4-released.html&#34;&gt; OCaml 4.00.0 on
iOS Is Released&lt;/a&gt;.  The OCaml-on-iOS page &lt;a href=&#34;http://psellos.com/ocaml/compile-to-iphone.html&#34;&gt;Compile OCaml for iOS&lt;/a&gt; has
been updated for OCamlXARM 3.1.&lt;/p&gt;&lt;/p&gt;

&lt;div class=&#34;flowaroundimg&#34; style=&#34;margin-top: 1.0em;&#34;&gt;
&lt;a href=&#34;http://psellos.com/ocaml/compile-to-iphone.html&#34;&gt;&lt;img src=&#34;http://psellos.com/images/ocaml4-apps.png&#34;&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;I call the compiler OCamlXARM because it runs on a Mac, and
cross-compiles for ARM-based iOS devices.  You can read about the
current release of OCamlXARM in &lt;a href=&#34;http://psellos.com/ocaml/compile-to-iphone.html&#34;&gt;Compile OCaml for
iOS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Initially the new version will compile only for armv7/Thumb, which means
the generated apps will only run on moderately recent iOS devices
(including all iPads).  I&#38;#8217;ll release an update that compiles for
armv6/ARM, which will be able to create apps for all the historical iOS
devices.&lt;/p&gt;

&lt;p&gt;If you&#38;#8217;re interested in trying a prerelease of the OCaml 4.00.0 cross
compiler, send me an email.  I recommend this for the adventurous only,
but it&#38;#8217;s extremely useful to me to get feedback on what works and
doesn&#38;#8217;t.  The less adventurous can try the current release, linked
above.  The current release is based on OCaml 3.10.2 (a pretty old
version admittedly), and has been used to create production iOS apps for
a few years now.&lt;/p&gt;

&lt;p&gt;For those interested in the ups and downs of doing the port, I wrote
about earlier development stages in &lt;a href=&#34;http://psellos.com/2012/07/2012.07.ocamlxarm-ocaml4-1.html&#34;&gt;OCaml 4.00.0 Working on iOS&lt;/a&gt;.
Here are the two interesting problems that came up recently.&lt;/p&gt;

&lt;p&gt;While running a test version of our Cassino app I uncovered a code
generation bug in the OCaml 4.00.0 compiler.  It turned out to be in the
scheduling pass, which reorders instructions to make them execute
faster.  This has been fixed by the experts at OCaml HQ&#38;#8212;you can read
about it as &lt;a href=&#34;http://caml.inria.fr/mantis/view.php?id=5731&#34;&gt;Mantis issue 5731&lt;/a&gt;.  The fix will appear in the
next bugfix release of OCaml (scheduled to be 4.00.1), but I&#38;#8217;ve also
merged the fix into OCamlXARM.  Many thanks to (the illustrious) Xavier
Leroy for looking at and fixing the problem.&lt;/p&gt;

&lt;p&gt;I also had the pleasure to discover what I consider a bug in Apple&#38;#8217;s iOS
assembler (or possibly it&#38;#8217;s a problem with the link editor).  You can
see the problem in this simple example, using the cross-development
versions of the assembler and the link editor&#38;#8212;&lt;code&gt;as&lt;/code&gt; and &lt;code&gt;ld&lt;/code&gt;&#38;#8212;from the
Xcode 4.3.3 iOS toolchain:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;&lt;code&gt;$ cat diffplus.s&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;code&gt;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;.data&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;.word Lsym - . + 0x80000000&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;.word 0x1966&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;Lsym:&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;.word 0x1967&lt;/code&gt; &lt;br /&gt;
  &lt;strong&gt;&lt;code&gt;$ as -arch armv7 -o diffplus.o diffplus.s&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;strong&gt;&lt;code&gt;$ otool -d diffplus.o&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;code&gt;diffplus.o:&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;(__DATA,__data) section&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;00000000&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;80000008&#38;#160;00001966&#38;#160;00001967&#38;#160;&lt;/code&gt; &lt;br /&gt;
  &lt;strong&gt;&lt;code&gt;$ otool -rv diffplus.o&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;code&gt;diffplus.o:&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;Relocation information (__DATA,__data) 2 entries&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;address&#38;#160;&#38;#160;pcrel&#38;#160;length&#38;#160;extern&#38;#160;type&#38;#160;&#38;#160;&#38;#160;&#38;#160;scattered&#38;#160;symbolnum/value&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;00000000&#38;#160;False&#38;#160;long&#38;#160;&#38;#160;&#38;#160;n/a&#38;#160;&#38;#160;&#38;#160;&#38;#160;SECTDIFFTrue&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;0x00000008&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;False&#38;#160;long&#38;#160;&#38;#160;&#38;#160;n/a&#38;#160;&#38;#160;&#38;#160;&#38;#160;PAIR&#38;#160;&#38;#160;&#38;#160;&#38;#160;True&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;0x00000000&lt;/code&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What the &lt;code&gt;otool&lt;/code&gt; output shows is that the three generated 32-bit values
have the proper values.  However, the first of the values is marked as a
(somewhat strange) relocatable value.  This is incorrect&#38;#8212;all of the
values are assembly-time constants, and no relocation is required.  This
error seems to prevent some types of linking of the generated object
file:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;&lt;code&gt;$ ld -r -o ldr1.o diffplus.o&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;strong&gt;&lt;code&gt;$ ld -r -o ldr2.o ldr1.o&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;code&gt;ld: in ldr1.o, in section __DATA,__data reloc 0: sectionForAddress(0x80000000) address not in any section for inferred architecture armv7&lt;/code&gt; &lt;br /&gt;
  &lt;strong&gt;&lt;code&gt;$&lt;/code&gt;&lt;/strong&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The purpose of &lt;code&gt;ld -r&lt;/code&gt; is to do &lt;em&gt;incremental linking&lt;/em&gt;, that is, to
combine several object files (&lt;code&gt;.o&lt;/code&gt; files) into one.  For files like
&lt;code&gt;diffplus.o&lt;/code&gt;, however, &lt;code&gt;ld&lt;/code&gt; generates an invalid object file as output.
If you try to process the file with a later run of &lt;code&gt;ld&lt;/code&gt;, you get the
error shown.&lt;/p&gt;

&lt;p&gt;Unfortunately, the OCaml compiler creates output that looks exactly like
&lt;code&gt;diffplus.s&lt;/code&gt; above.  Lines like this are used in the frame tables that
describe OCaml function call sites, used by the garbage collector to
avoid collecting values that will still be live when the call returns.
Furthermore, &lt;code&gt;ld -r&lt;/code&gt; is used internally to implement the OCaml
compiler&#38;#8217;s &lt;code&gt;-output-obj&lt;/code&gt; flag.&lt;/p&gt;

&lt;p&gt;After some experimentation I found a workaround.  The following assembly
code avoids the (seeming) bug in &lt;code&gt;as&lt;/code&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;&lt;code&gt;$ cat diffplusok.s&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;code&gt;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;.data&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;offset001 = Lsym - . + 0x80000000&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;.word offset001&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;.word 0x1966&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;Lsym:&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;.word 0x1967&lt;/code&gt; &lt;br /&gt;
  &lt;strong&gt;&lt;code&gt;$ as -arch armv7 -o diffplusok.o diffplusok.s&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;strong&gt;&lt;code&gt;$ otool -d diffplusok.o&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;code&gt;diffplusok.o:&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;(__DATA,__data) section&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;00000000&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;80000008&#38;#160;00001966&#38;#160;00001967&#38;#160;&lt;/code&gt; &lt;br /&gt;
  &lt;strong&gt;&lt;code&gt;$ otool -rv diffplusok.o&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;code&gt;diffplusok.o:&lt;/code&gt; &lt;br /&gt;
  &lt;strong&gt;&lt;code&gt;$&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;strong&gt;&lt;code&gt;$ ld -r -o ldrok1.o diffplusok.o&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;strong&gt;&lt;code&gt;$ ld -r -o ldrok2.o ldrok1.o&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;strong&gt;&lt;code&gt;$&lt;/code&gt;&lt;/strong&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This transformed version convinces the assembler that the value is
constant at assembly time, so there are no relocation markings in the
generated file.  This doesn&#38;#8217;t present any problems for &lt;code&gt;ld&lt;/code&gt;, and so
incremental linking works OK.&lt;/p&gt;

&lt;p&gt;If no other big problems appear, the new release will be available
shortly.  The new version will be OCamlXARM 3.1.  I&#38;#8217;m looking forward to
trying out some of the more modern OCaml features in my iOS programming,
and I&#38;#8217;d also like to do some timing tests.  I wonder whether armv7/Thumb
code is faster than the armv6/ARM code generated by the previous
OCamlXARM release.  I&#38;#8217;ve also started to be curious how much the
scheduling pass (where the recent bug was fixed) improves the speed of
my code.&lt;/p&gt;

&lt;p&gt;If you have comments or questions, please leave them below, or email me
at &lt;a href=&#34;&#38;#x6d;&#38;#x61;&#38;#x69;&#38;#108;&#38;#x74;&#38;#x6f;&#38;#x3a;j&#38;#x65;&#38;#x66;&#38;#x66;&#38;#115;&#38;#099;&#38;#x6f;&#38;#064;&#38;#112;&#38;#115;&#38;#x65;l&#38;#x6c;&#38;#x6f;s&#38;#046;&#38;#x63;&#38;#x6f;&#38;#x6d;&#34;&gt;&#38;#106;e&#38;#102;&#38;#x66;&#38;#115;&#38;#099;o&#38;#064;&#38;#112;&#38;#115;&#38;#x65;&#38;#108;l&#38;#x6f;&#38;#x73;&#38;#x2e;&#38;#x63;&#38;#111;&#38;#109;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Posted by: &lt;a href=&#34;http://psellos.com/aboutus.html#jeffreya.scofieldphd&#34;&gt;Jeffrey&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;style type=&#34;text/css&#34;&gt;
.flowaroundimg {
       float: left;
       margin: 0em 1em 0em 0em;
}
&lt;/style&gt;&lt;/p&gt;
&lt;!--#include virtual=&#34;${Base_URL}/templates/footer.html&#34; --&gt;</content></entry><entry><title>Run Debian ARMEL Linux on OS X with QEMU</title><link href="http://psellos.com/2012/08/2012.08.qemu-arm-osx.html"/><id>http://psellos.com/2012/08/2012.08.qemu-arm-osx.html</id><updated>2012-08-15T11:00:00-08:00</updated><content type="html">&lt;!--#include virtual=&#34;${Base_URL}/templates/header.html&#34; --&gt;&lt;div class=&#34;date&#34;&gt;August 15, 2012&lt;/div&gt;

&lt;p&gt;While getting OCaml 4.00.0 working on iOS I&#38;#8217;ve often wanted an ARM-based
Linux system for testing out the stock OCaml compiler.  Now I have one,
running inside &lt;a href=&#34;http://wiki.qemu.org/&#34;&gt;QEMU&lt;/a&gt; on my Mac!&lt;/p&gt;

&lt;p&gt;QEMU is an impressive system that emulates ten or twelve different
hardware systems at an amazing level of detail yet with good
performance.  A couple of the emulated systems are based on ARM and let
you boot a Linux system (such as Debian Squeeze, which is what I used).
In essence, QEMU does what I thought the iOS Simulator did, before I
found out how it really works.  I learned about QEMU from Benedikt
Meurer on the OCaml mailing list&#38;#8212;he suggested it for running the OCaml
4.00.0/ARM compiler.&lt;/p&gt;

&lt;p&gt;The only downside is that it&#38;#8217;s extremely tricky to get the ARM subsystem
of QEMU working under OS X right now.  Many things are in flux: new
versions of QEMU, OS X, and Xcode have already come out.  So things
might be working well by the time you read this.  Unfortunately, right
now (August 15, 2012) recent versions of QEMU, OS X, and Xcode don&#38;#8217;t
work together.  And realistically it could be a while until they do.&lt;/p&gt;

&lt;p&gt;After trying many things, I found a &lt;a href=&#34;https://github.com/jeremyckahn/pine/wiki/Installing-QEMU-on-OS-X&#34;&gt;page by Jeremy Kahn&lt;/a&gt; that
explains how to build QEMU for OS X with &lt;a href=&#34;http://mxcl.github.com/homebrew/&#34;&gt;Homebrew&lt;/a&gt;.  Homebrew
is a package manager for OS X based on Ruby and Git.  It seems to be
getting a lot of play these days, and I use it myself.&lt;/p&gt;

&lt;p&gt;I made a couple of corrections to Jeremy&#38;#8217;s steps.  For posterity, here
are the steps I followed to get Debian Squeeze ARMEL working under QEMU
on my Mac.  I have Xcode 4.3.3 and OS X 10.7.4 (Lion).&lt;/p&gt;

&lt;p&gt;(&lt;em&gt;Edit&lt;/em&gt;: Jeremy has updated his page to include my corrections.)&lt;/p&gt;

&lt;h4 id=&#34;preliminaries&#34;&gt;Preliminaries&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Install Xcode.  You can download it for free from the Mac App Store.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In &lt;strong&gt;Xcode -&#38;gt; Preferences&lt;/strong&gt; go to &lt;strong&gt;Downloads -&#38;gt; Components&lt;/strong&gt;.
Install the Command Line Tools.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install Homebrew, as directed on the &lt;a href=&#34;http://mxcl.github.com/homebrew/&#34;&gt;Homebrew Home Page&lt;/a&gt;.
Make sure your Homebrew is up to date:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;&lt;code&gt;$ brew update&lt;/code&gt;&lt;/strong&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&#34;installqemu&#34;&gt;Install QEMU&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Here begins the tricky part.  The ARM subpart of latest QEMU built by
Homebrew doesn&#38;#8217;t work.  It hangs indefinitely at startup, as I can
attest from experience.  You need to trick Homebrew into using version
&lt;code&gt;1.1.0&lt;/code&gt; of QEMU.  You don&#38;#8217;t want version &lt;code&gt;1.1.0-1&lt;/code&gt; (the latest version
as of this writing).  We&#38;#8217;re going to check out an old version of the
Homebrew recipe and use that to build QEMU:&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;&lt;code&gt;$ cd /usr/local&lt;/code&gt;&lt;/strong&gt;&#38;#160;&#38;#160;&#38;#160;&lt;code&gt;# (or wherever you installed Homebrew)&lt;/code&gt; &lt;br /&gt;
  &lt;strong&gt;&lt;code&gt;$ git checkout 2b7b4b3027 Library/Formula/qemu.rb&lt;/code&gt;&lt;/strong&gt;  &lt;/p&gt;
  
  &lt;p&gt;If you look at the replacement recipe you should see that it uses QEMU
  1.1.0 &lt;em&gt;exactly&lt;/em&gt;.&lt;/p&gt;
  
  &lt;p&gt;&lt;strong&gt;&lt;code&gt;$ grep url Library/Formula/qemu.rb&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;code&gt;&#38;#160;&#38;#160;url &#39;http://wiki.qemu.org/download/qemu-1.1.0.tar.bz2&#39;&lt;/code&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Even more trickery is required.  The gcc that comes with the latest
Xcode can&#38;#8217;t be used to build QEMU.  Download an older version as
follows:&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;&lt;code&gt;$ brew install https://raw.github.com/Homebrew/homebrew-dupes/master/apple-gcc42.rb&lt;/code&gt;&lt;/strong&gt;  &lt;/p&gt;
  
  &lt;p&gt;(&lt;em&gt;Warning&lt;/em&gt;: this is a long line.  If you cut and paste, be sure to get
  it all.)&lt;/p&gt;
  
  &lt;p&gt;After this, you should have gcc 4.2:&lt;/p&gt;
  
  &lt;p&gt;&lt;strong&gt;&lt;code&gt;$ which gcc-4.2&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;code&gt;/usr/local/bin/gcc-4.2&lt;/code&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Build and install QEMU using the alternate compiler:&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;&lt;code&gt;$ brew install qemu --use-gcc&lt;/code&gt;&lt;/strong&gt;  &lt;/p&gt;
  
  &lt;p&gt;If it works, you should have qemu-system-arm, the QEMU executable for
    the full-system ARM emulator.&lt;/p&gt;
  
  &lt;p&gt;&lt;strong&gt;&lt;code&gt;$ which qemu-system-arm&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;code&gt;/usr/local/bin/qemu-system-arm&lt;/code&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&#34;installdebiansqueezearmel&#34;&gt;Install Debian Squeeze ARMEL&lt;/h4&gt;

&lt;p&gt;You can download the necessary disk image and support files for booting
Debian on QEMU from &lt;a href=&#34;http://people.debian.org/~aurel32/qemu/armel/&#34;&gt;Aur&#38;#233;lien Jarno&#38;#8217;s ARM QEMU Files at Debian
HQ&lt;/a&gt;.  You need a disk image (&lt;code&gt;debian_*.qcow2&lt;/code&gt;), an initial
ramdisk (&lt;code&gt;initrd.img-*&lt;/code&gt;) and a kernel file (&lt;code&gt;vmlinuz-*&lt;/code&gt;).  Here are the
commands to download the ones I used for Debian Squeeze:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;$&#38;#160;curl&#38;#160;&lt;span style=&#34;white-space: nowrap;&#34;&gt;-O&lt;/span&gt;&#38;#160;http://people.debian.org/~aurel32/qemu/armel/debian_squeeze_armel_standard.qcow2&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;$&#38;#160;curl&#38;#160;&lt;span style=&#34;white-space: nowrap;&#34;&gt;-O&lt;/span&gt;&#38;#160;http://people.debian.org/~aurel32/qemu/armel/initrd.img-2.6.32-5-versatile&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;$&#38;#160;curl&#38;#160;&lt;span style=&#34;white-space: nowrap;&#34;&gt;-O&lt;/span&gt;&#38;#160;http://people.debian.org/~aurel32/qemu/armel/vmlinuz-2.6.32-5-versatile&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;(You might find it more convenient to download from the website.  Otherwise, be
careful of these long command lines.)&lt;/p&gt;

&lt;p&gt;You can now boot Debian Squeeze inside the QEMU emulation of ARM:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;&lt;code&gt;$ qemu-system-arm -nographic -M versatilepb \&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;strong&gt;&lt;code&gt;-kernel vmlinuz-2.6.32-5-versatile \&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;strong&gt;&lt;code&gt;-initrd initrd.img-2.6.32-5-versatile \&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;strong&gt;&lt;code&gt;-hda debian_squeeze_armel_standard.qcow2 \&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;strong&gt;&lt;code&gt;-append &#34;root=/dev/sda1 console=ttyAMA0&#34;&lt;/code&gt;&lt;/strong&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You should see many lines of boot output, then a login prompt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code&gt;debian-armel login:&lt;/code&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The root password is &lt;code&gt;root&lt;/code&gt;.  There is a nonprivileged user account
named &lt;code&gt;user&lt;/code&gt;, whose password is also &lt;code&gt;user&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To exit the emulator, type &#38;#8220;^A x&#38;#8221; (Control-a, then x).&lt;/p&gt;

&lt;p&gt;The emulator works exceptionally well&#38;#8212;well enough that I successfully
built the OCaml 4.00.0 compiler from sources and then ran tests with it.
There is one smallish problem that the (simulated) SCSI disk seems to
encounter hardware errors occasionally.  I&#38;#8217;ve never heard of hardware
errors with a simulated piece of hardware!  (I guess you could say this
makes the simulation even more accurate.)  My web searches suggest that
this is a known problem that will be fixed in a future release of QEMU.&lt;/p&gt;

&lt;p&gt;I find it strangely thrilling to run a simulated ARM system on my Mac.
(Pehaps I&#38;#8217;m too easily thrilled.)&lt;/p&gt;

&lt;p&gt;If you have any corrections, improvements, or other comments, leave them
below or email me at &lt;a href=&#34;&#38;#x6d;&#38;#x61;&#38;#x69;&#38;#108;&#38;#x74;&#38;#x6f;&#38;#x3a;j&#38;#x65;&#38;#x66;&#38;#x66;&#38;#115;&#38;#099;&#38;#x6f;&#38;#064;&#38;#112;&#38;#115;&#38;#x65;l&#38;#x6c;&#38;#x6f;s&#38;#046;&#38;#x63;&#38;#x6f;&#38;#x6d;&#34;&gt;&#38;#106;e&#38;#102;&#38;#x66;&#38;#115;&#38;#099;o&#38;#064;&#38;#112;&#38;#115;&#38;#x65;&#38;#108;l&#38;#x6f;&#38;#x73;&#38;#x2e;&#38;#x63;&#38;#111;&#38;#109;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Posted by: &lt;a href=&#34;http://psellos.com/aboutus.html#jeffreya.scofieldphd&#34;&gt;Jeffrey&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;style type=&#34;text/css&#34;&gt;
.flowaroundimg {
       float: left;
       margin: 0em 1em 0em 0em;
}
pre {
    white-space: pre-wrap;
    width: 96%;
    margin-bottom: 24px;
    padding: 3px 10px;
    -webkit-border-radius: 3px;
    background-color: #fed;
    border: 1px solid #dcb;
    font-size: 230%;
}
code {
    font-size: 110%;
    white-space: pre-wrap;
    white-space: -moz-pre-wrap !important;
    white-space: -pre-wrap;
    white-space: -o-pre-wrap;
    word-wrap: break-word;
    overflow-wrap: break-word;
}
pre code {
    white-space: pre-wrap;
    font-size: 110%;
    padding: 0;
    border: none;
    background-color: transparent;
    -webkit-border-radius: 0;
}
&lt;/style&gt;&lt;/p&gt;
&lt;!--#include virtual=&#34;${Base_URL}/templates/footer.html&#34; --&gt;</content></entry><entry><title>Convert Linux ARM Assembly Code for iOS (Update 2)</title><link href="http://psellos.com/2012/08/2012.08.arm-as-to-ios-3.html"/><id>http://psellos.com/2012/08/2012.08.arm-as-to-ios-3.html</id><updated>2012-08-04T11:00:00-08:00</updated><content type="html">&lt;!--#include virtual=&#34;${Base_URL}/templates/header.html&#34; --&gt;&lt;div class=&#34;date&#34;&gt;August 4, 2012&lt;/div&gt;

&lt;p&gt;While getting OCaml 4.00.0 working on iOS, I&#38;#8217;ve learned quite a bit
about the differences between the Linux ARM assembler and the iOS ARM
assembler.  The two are related: the iOS assembler is like a cousin of
the Linux assembler whose ancestors left the home country a few
generations back.  However, the differences between the two were one of
the main problems I had to solve.&lt;/p&gt;

&lt;p&gt;This information was hard won: documentation for the iOS assembler seems
rare to nonexistent (email me if you know where to find it).  So I spent
many hours reading the source code of &lt;code&gt;as(1)&lt;/code&gt; at Apple&#38;#8217;s open source
site.  To help others avoid duplicating the effort, I&#38;#8217;m publishing here
the latest version of my Python script &lt;code&gt;arm-as-to-ios&lt;/code&gt; that converts ARM
assembly code from the Linux format to the required iOS format.  This
script contains all the wisdom I&#38;#8217;ve accumulated so far (including some
that&#38;#8217;s not required for the OCaml-on-iOS project).&lt;/p&gt;

&lt;p style=&#34;background-color: #fed; border: 1px solid #dcb; padding: 0.7em;&#34;&gt;
&lt;em&gt;Note&lt;/em&gt;: I wrote a new, improved version of this script, described
in &lt;a href=&#34;http://psellos.com/2012/08/2012.08.arm-as-to-ios-4.html&#34;&gt;Convert Linux ARM
Assembly Code for iOS (Update 3)&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;I wrote the script specifically to convert the hand-written ARM assembly
files of the OCaml runtime to work on iOS.  The advantages of using a
script are that the conversion is done consistently, and the script
might still be useful if the assembly code is rewritten in the future.&lt;/p&gt;

&lt;p&gt;Another advantage is that the script might help other people who need to
port ARM assembly code from Linux to iOS.  Granted, there probably
aren&#38;#8217;t a lot of people doing this.  But if you are, maybe the script
will be a useful starting point or at least a careful list of
differences between the assemblers.&lt;/p&gt;

&lt;p&gt;The output of the script is upward compatible.  By this I mean that a
converted assembly file is supposed to work in its originally supported
Linux environments as well as in iOS.  In theory this means that the
converted assembly files could be sent &#38;#8220;upstream&#38;#8221; to maintainers (if
they&#38;#8217;re comfortable with supporting iOS and/or the extra complexity of
the code).&lt;/p&gt;

&lt;p&gt;The current version of &lt;code&gt;arm-as-to-ios&lt;/code&gt; is 1.3.0.  In its current form,
it does the following conversions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Declare the ARM architecture for iOS with a &lt;code&gt;.machine&lt;/code&gt; pseudo-op.  The
possibilities are &lt;code&gt;armv6&lt;/code&gt; and &lt;code&gt;armv7&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Specify that &lt;code&gt;armv7&lt;/code&gt; code should use the more space-efficient Thumb
encoding in iOS.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Generate declarations for functions, similar to the &lt;code&gt;.type&lt;/code&gt; pseudo-op
for Linux assemblers.  It appears that Apple requires &lt;code&gt;.thumb_func&lt;/code&gt;
declarations only for Thumb functions.  Other symbols are apparently
assumed to be ARM functions.  To make this work upward-compatibly, I
define an assembly macro named &lt;code&gt;.funtype&lt;/code&gt; that is expanded properly in
the different environments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make sure that global symbols have the right format.  For Linux, they
look like &#38;#8220;&lt;code&gt;abc&lt;/code&gt;&#38;#8221;.  For iOS, they look like &#38;#8220;&lt;code&gt;_abc&lt;/code&gt;&#38;#8221; (with a leading
underscore).  To support upward compatibility, this is handled by a
cpp macro named &lt;code&gt;Glo()&lt;/code&gt; that generates the proper symbol form for each
environment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make sure that assembler-local symbols have the right format.  For
Linux assemblers, they look like &#38;#8220;&lt;code&gt;.Lxxx&lt;/code&gt;&#38;#8221;.  For the iOS assembler,
they look like &#38;#8220;&lt;code&gt;Lxxx&lt;/code&gt;&#38;#8221;.  To support upward compatibly, this is
handled by a cpp macro named &lt;code&gt;Loc()&lt;/code&gt; that generates the proper symbol
form for each environment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Replace uses of &lt;code&gt;=&lt;/code&gt;&lt;em&gt;value&lt;/em&gt; notation by explicit loads from memory.
The Linux ARM assemblers interpret &lt;code&gt;ldr rM, =&lt;/code&gt;&lt;em&gt;value&lt;/em&gt; to mean that the
&lt;em&gt;value&lt;/em&gt; should be loaded into register M immediately (using &lt;code&gt;mov&lt;/code&gt;) if
possible, and loaded from memory (using &lt;code&gt;ldr&lt;/code&gt; with PC-relative
addressing) otherwise.  The Apple assembler seems not to support this,
so &lt;code&gt;arm-as-to-ios&lt;/code&gt; replaces uses of &lt;code&gt;=&lt;/code&gt;&lt;em&gt;value&lt;/em&gt; with explicit memory
loads, emitting the pool of values into the &lt;code&gt;.text&lt;/code&gt; segment at the end
of the file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Convert jump tables (for the &lt;code&gt;tbh&lt;/code&gt; instruction) to a form that works
with the iOS assembler.  The form commonly used in Linux generates a
bad jump table under iOS&#38;#8212;apparently the iOS assembler interprets the
expressions differently.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove uses of two pseudo-ops, &lt;code&gt;.type&lt;/code&gt; and &lt;code&gt;.size&lt;/code&gt;, when assembling
for iOS.  They aren&#38;#8217;t supported by Apple&#38;#8217;s assembler.  This is done by
defining null assembly macros for them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Define a macro &lt;code&gt;cbz&lt;/code&gt; when using ARM encodings for iOS.  The &lt;code&gt;cbz&lt;/code&gt;
instruction is Thumb-only.  The definition replaces it with a pair
of ARM instructions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can download the script here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://psellos.com/pub/ocamlxarm/arm-as-to-ios&#34;&gt;arm-as-to-ios&#38;#8212;modify ARM assembly code for use on iOS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The full text of the script is also included at the end of this post.&lt;/p&gt;

&lt;p&gt;This is the third version of &lt;code&gt;arm-as-to-ios&lt;/code&gt;, and there may well be a
few more changes when I work on the &lt;code&gt;armv6&lt;/code&gt; architecture.  As I make
changes, I&#38;#8217;ll keep the linked script up to date.  If there are
significant changes I&#38;#8217;ll make another post about them.&lt;/p&gt;

&lt;p&gt;If you want to try out &lt;code&gt;arm-as-to-ios&lt;/code&gt;, copy and paste the lines from
the end of this post into a file named &lt;code&gt;arm-as-to-ios&lt;/code&gt;, or download it
from the above link.  Mark it as a script with &lt;code&gt;chmod&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ chmod +x arm-as-to-ios&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To use the script, specify the name of an ARM assembly file.  If no
files are given, the script processes its standard input.&lt;/p&gt;

&lt;p&gt;The following small example demonstrates the translations that
&lt;code&gt;arm-as-to-ios&lt;/code&gt; performs.  Here is a small file of Linux ARM assembly
code:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;        .syntax unified
        .text
        .align  2
        .globl  example
        .type example, %function
example:
        sub     r10, r10, 8
        cmp     r10, r11
        bcc     1f
        bx      lr
1:
        ldr     r7, =last_return_address
        str     lr, [r7]
        bl      .Lcall_gc
        ldr     lr, [r7]
        b       example

.Lcall_gc:
        ldr     r12, =bottom_of_stack
        str     sp, [r12]
        bl      garbage_collection
        bx      lr

.Ljump:
# A jump table (code fragment).
        tbh     [pc, r4, lsl #1]
        .short  (.Ltest1-.)/2+0
        .short  (.Ltest2-.)/2+1
        .short  (.Ltest3-.)/2+2
.Ltest1:
        ldr     r4, [r4]
.Ltest2:
        str     r6, [sp, 8]
.Ltest3:
        str     r8, [r12]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you run &lt;code&gt;arm-as-to-ios&lt;/code&gt; on this file, you get the following output
that works for both Linux and iOS assemblers:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;        .syntax unified

/* Apple compatibility macros */
#if defined(SYS_macosx)
#define Glo(s) _##s
#define Loc(s) L##s
#if defined(MODEL_armv6)
        .machine  armv6
        .macro  .funtype
        .endm
        .macro  cbz
        cmp     $0, #0
        beq     $1
        .endm
#else
        .machine  armv7
        .thumb
        .macro  .funtype
        .thumb_func $0
        .endm
#endif
        .macro  .type
        .endm
        .macro  .size
        .endm
#else
#define Glo(s) s
#define Loc(s) .L##s
        .macro  .funtype symbol
        .type  \symbol, %function
        .endm
#endif
/* End Apple compatibility macros */

        .text
        .align  2
        .globl  Glo(example)
        .funtype  Glo(example)
Glo(example):
        sub     r10, r10, 8
        cmp     r10, r11
        bcc     1f
        bx      lr
1:
        ldr     r7, Loc(Plast_return_address)
        str     lr, [r7]
        bl      Loc(call_gc)
        ldr     lr, [r7]
        b       Glo(example)

Loc(call_gc):
        ldr     r12, Loc(Pbottom_of_stack)
        str     sp, [r12]
        bl      Glo(garbage_collection)
        bx      lr

Loc(jump):
# A jump table (code fragment).

        tbh     [pc, r4, lsl #1]
Loc(B27):
        .short  (Loc(test1)-Loc(B27))/2
        .short  (Loc(test2)-Loc(B27))/2
        .short  (Loc(test3)-Loc(B27))/2
Loc(test1):
        ldr     r4, [r4]
Loc(test2):
        str     r6, [sp, 8]
Loc(test3):
        str     r8, [r12]

/* Pool of addresses loaded into registers */

        .text
        .align 2
Loc(Plast_return_address):
        .long Glo(last_return_address)
Loc(Pbottom_of_stack):
        .long Glo(bottom_of_stack)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The output consists of a fixed prefix followed by the translation of the
input file, followed by the pool of values to be loaded into registers.&lt;/p&gt;

&lt;p&gt;The following shows a successful assembly of the &lt;code&gt;arm.S&lt;/code&gt; file from OCaml
4.00.0:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ PLT=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform
$ PLTBIN=$PLT/Developer/usr/bin
$ arm-as-to-ios asmrun/arm.S &#38;gt; armios.S
$ $PLTBIN/gcc -c -arch armv7 -DSYS_macosx -DMODEL_armv7 -o armios.o armios.S
$ file armios.o
armios.o: Mach-O object arm
$ otool -tv armios.o | head
armios.o:
(__TEXT,__text) section
caml_call_gc:
00000000        f8dfc1e0        ldr.w   ip, [pc, #480]  @ 0x1e4
00000004        f8cce000        str.w   lr, [ip]
00000008        f8dfc1dc        ldr.w   ip, [pc, #476]  @ 0x1e8
0000000c        f8ccd000        str.w   sp, [ip]
00000010        ed2d0b10        vstmdb  sp!, {d0-d7}
00000014        e92d50ff        stmdb   sp!, {r0, r1, r2, r3, r4, r5, r6, r7, ip, lr}
00000018        f8dfc1d0        ldr.w   ip, [pc, #464]  @ 0x1ec&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you have any corrections, improvements, or other comments, leave them
below or email me at &lt;a href=&#34;&#38;#x6d;&#38;#x61;&#38;#x69;&#38;#108;&#38;#x74;&#38;#x6f;&#38;#x3a;j&#38;#x65;&#38;#x66;&#38;#x66;&#38;#115;&#38;#099;&#38;#x6f;&#38;#064;&#38;#112;&#38;#115;&#38;#x65;l&#38;#x6c;&#38;#x6f;s&#38;#046;&#38;#x63;&#38;#x6f;&#38;#x6d;&#34;&gt;&#38;#106;e&#38;#102;&#38;#x66;&#38;#115;&#38;#099;o&#38;#064;&#38;#112;&#38;#115;&#38;#x65;&#38;#108;l&#38;#x6f;&#38;#x73;&#38;#x2e;&#38;#x63;&#38;#111;&#38;#109;&lt;/a&gt;.  I&#38;#8217;d be very pleased to hear
if the script has been helpful to anyone.&lt;/p&gt;

&lt;p&gt;Posted by: &lt;a href=&#34;http://psellos.com/aboutus.html#jeffreya.scofieldphd&#34;&gt;Jeffrey&lt;/a&gt;&lt;/p&gt;

&lt;h4 id=&#34;appendix&#34;&gt;Appendix&lt;/h4&gt;

&lt;p&gt;Here is the current text of the script:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!/usr/bin/env python
#
# arm-as-to-ios     Modify ARM assembly code for the iOS assembler
#
# Copyright (c) 2012 Psellos   http://psellos.com/
# Licensed under the MIT License:
#     http://www.opensource.org/licenses/mit-license.php
#
# Resources for running OCaml on iOS: http://psellos.com/ocaml/
#
import sys
import re

VERSION = &#39;1.3.0&#39;

# Prefixes for pooled symbol labels and jump table base labels.  They&#39;re
# in the space of Linux assembler local symbols.  Later rules will
# modify them to the Loc() form.
#
g_poolpfx = &#39;.LP&#39;
g_basepfx = &#39;.LB&#39;


def add_prefix(instrs):
    # Add compatibility macros for all systems, plus hardware
    # definitions and compatibility macros for iOS.
    #
    # All systems:
    #
    # Glo()     cpp macro for making global symbols (xxx vs _xxx)
    # Loc()     cpp macro for making local symbols (.Lxxx vs Lxxx)
    # .funtype  Expands to .thumb_func for iOS armv7 (null for armv6)
    #           Expands to .type %function for others
    #
    # iOS:
    #
    # .machine  armv6/armv7
    # .thumb    (for armv7)
    # cbz       Expands to cmp/beq for armv6 (Thumb-only instr)
    # .type     Not supported by Apple assembler
    # .size     Not supported by Apple assembler
    #
    defre = &#39;#[ \t]*if.*def.*SYS&#39;  # Add new defs near first existing ones
    skipre = &#39;$|\.syntax[ \t]&#39;     # Skip comment lines (and .syntax)

    for i in range(len(instrs)):
        if re.match(defre, instrs[i][1]):
            break
    else:
        i = 0
    for i in range(i, len(instrs)):
        if not re.match(skipre, instrs[i][1]):
            break
    instrs[i:0] = [
        (&#39;&#39;, &#39;&#39;, &#39;\n&#39;),
        (&#39;/* Apple compatibility macros */&#39;, &#39;&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;#if defined(SYS_macosx)&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;#define Glo(s) _##s&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;#define Loc(s) L##s&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;#if defined(MODEL_armv6)&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.machine  armv6&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.macro  .funtype&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.endm&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.macro  cbz&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;cmp     $0, #0&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;beq     $1&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.endm&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;#else&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.machine  armv7&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.thumb&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.macro  .funtype&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.thumb_func $0&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.endm&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;#endif&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.macro  .type&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.endm&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.macro  .size&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.endm&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;#else&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;#define Glo(s) s&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;#define Loc(s) .L##s&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.macro  .funtype symbol&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.type  \\symbol, %function&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.endm&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;#endif&#39;, &#39;\n&#39;),
        (&#39;/* End Apple compatibility macros */&#39;, &#39;&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;&#39;, &#39;\n&#39;)
    ]
    return instrs


# Regular expression for modified ldr lines
#
g_ldre = &#39;(ldr[ \t][^,]*,[ \t]*)=(([^ \t\n@,/]|/(?!\*))*)(.*)&#39;


def explicit_address_loads(instrs):
    # Linux assemblers allow the following:
    #
    #     ldr rM, =symbol
    #
    # which loads rM with [mov] (immediately) if possible, or creates an
    # entry in memory for the symbol value and loads it PC-relatively
    # with [ldr].
    #
    # The Apple assembler doesn&#39;t seem to support this notation.  If the
    # value is a suitable constant, it emits a valid [mov].  Otherwise
    # it seems to emit an invalid [ldr] that always generates an error.
    # (At least I have not been able to make it work).  So, change uses
    # of =symbol to explicit PC-relative loads.
    #
    # This requires a pool containing the addresses to be loaded.  For
    # now, we just keep track of it ourselves and emit it into the text
    # segment at the end of the file.
    #
    syms = {}
    result = []

    def repl1((syms, result), (a, b, c)):
        global g_poolpfx
        global g_ldre
        (b1, b2, b3) = parse_iparts(b)
        mo = re.match(g_ldre, b3, re.DOTALL)
        if mo:
            if mo.group(2) not in syms:
                syms[mo.group(2)] = len(syms)
            psym = mo.group(2)
            if psym[0:2] == &#39;.L&#39;:
                psym = psym[2:]
            newb3 = mo.group(1) + g_poolpfx + psym + mo.group(4)
            result.append((a, b1 + b2 + newb3, c))
        else:
            result.append((a, b, c))
        return (syms, result)

    def pool1(result, s):
        global g_poolpfx
        psym = s
        if psym[0:2] == &#39;.L&#39;:
            psym = psym[2:]
        result.append((&#39;&#39;, g_poolpfx + psym + &#39;:&#39;, &#39;\n&#39;))
        result.append((&#39;        &#39;, &#39;.long &#39; + s, &#39;\n&#39;))
        return result

    reduce(repl1, instrs, (syms, result))
    if len(syms) &#38;gt; 0:
        result.append((&#39;&#39;, &#39;&#39;, &#39;\n&#39;))
        result.append((&#39;/* Pool of addresses loaded into registers */&#39;,
                        &#39;&#39;, &#39;\n&#39;))
        result.append((&#39;&#39;, &#39;&#39;, &#39;\n&#39;))
        result.append((&#39;        &#39;, &#39;.text&#39;, &#39;\n&#39;))
        result.append((&#39;        &#39;, &#39;.align 2&#39;, &#39;\n&#39;))
        reduce(pool1, sorted(syms, key=syms.get), result)
    return result


def global_symbols(instrs):
    # The form of a global symbol differs between Linux assemblers and
    # the Apple assember:
    #
    # Linux: xxx
    # Apple: _xxx
    #
    # Change occurrences of global symbols to use the Glo() cpp macro
    # defined in our prefix.
    #
    # We consider a symbol to be global if:
    #
    # a.  It appears in a .globl declaration; or
    # b.  It appears, doesn&#39;t have local form, and is not defined
    #
    endsy = &#39;($|[^a-zA-Z0-9])&#39; # End of a symbol

    allsyms = set()
    defsyms = set()
    glosyms = set()
    result = []

    def findglob1 (glosyms, (a, b, c)):
        mo = re.match(&#39;\.globl[ \t]+([^ \t@:,+\-*/()]+)&#39;, b)
        if mo:
            glosyms.add(mo.group(1))
        return glosyms

    def findany1 ((allsyms, skipct), (a, b, c)):

        def looksglobal(s):
            if re.match(&#39;(r|a|v|p|c|cr|f|s|d|q|mvax|wcgr)[0-9]+$&#39;, s, re.I):
                return False # numbered registers
            if re.match(&#39;(wr|sb|sl|fp|ip|sp|lr|pc)$&#39;, s, re.I):
                return False # named registers
            if re.match(&#39;(fpsid|fpscr|fpexc|mvfr1|mvfr0)$&#39;, s, re.I):
                return False # more named registers
            if re.match(&#39;(mvf|mvd|mvfx|mvdx|dspsc)$&#39;, s, re.I):
                return False # even more named registers
            if re.match(&#39;(wcid|wcon|wcssf|wcasf|acc)$&#39;, s, re.I):
                return False # even more named registers
            if re.match(&#39;\.L|[0-9]|#&#39;, s):
                return False # local symbol or number
            if re.match(&#39;(asl|lsl|lsr|asr|ror|rrx)$&#39;, s, re.I):
                return False # shift names
            return True

        if re.match(&#39;#&#39;, b):
            return (allsyms, skipct)
        # Track nesting of .macro/.endm.  For now, we don&#39;t look for
        # global syms in macro defs.  (Avoiding scoping probs etc.)
        #
        if skipct &#38;gt; 0 and re.match(&#39;\.(endm|endmacro)&#39; + endsy, b):
            return (allsyms, skipct - 1)
        if re.match(&#39;\.macro&#39; + endsy, b):
            return (allsyms, skipct + 1)
        if skipct &#38;gt; 0:
            return (allsyms, skipct)
        if re.match(&#39;\.(type|size|syntax|arch|fpu)&#39; + endsy, b):
            return (allsyms, skipct)
        lb = b
        lb = re.sub(&#39;@.*&#39;, &#39;&#39;, lb)
        lb = re.sub(&#39;/\*.*?\*/&#39;, &#39;&#39;, lb)
        mo = re.match(&#39;[^:]*:[ \t]*(.*)&#39;, lb)
        if mo:
            lb = mo.group(1)
        lb = re.match(&#39;[^ \t]*[ \t]*(.*)&#39;, lb).group(1)
        if re.match(&#39;\.req&#39;, lb):
            return (allsyms, skipct)
        for s in re.findall(&#39;[^ \t@:,+\-*/[\]{}()]+&#39;, lb):
            if looksglobal(s):
                allsyms.add(s)
        return (allsyms, skipct)

    def finddef1(defsyms, (a, b, c)):
        mo = re.match(&#39;([^ \t]+)[ \t]+\.req&#39; + endsy, b) \
                or re.match(&#39;([^ \t:]+)[ \t]*:&#39;, b)
        if mo:
            defsyms.add(mo.group(1))
        return defsyms

    def repl1((glosyms, result), (a, b, c)):
        if re.match(&#39;#&#39;, b):
            # Preprocessor line
            result.append((a, b, c))
        else:
            matches = list(re.finditer(&#39;[^ \t@:,+*/-]+&#39;, b))
            if matches != []:
                matches.reverse()
                newb = b
                for mo in matches:
                    if mo.group() in glosyms:
                        newb = newb[0:mo.start()] + \
                                &#39;Glo(&#39; + mo.group() + &#39;)&#39; + \
                                newb[mo.end():]
                result.append((a, newb, c))
            else:
                result.append((a, b, c))
        return (glosyms, result)

    reduce(findglob1, instrs, glosyms)
    reduce(findany1, instrs, (allsyms, 0))
    reduce(finddef1, instrs, defsyms)
    glosyms |= (allsyms - defsyms)
    reduce(repl1, instrs, (glosyms, result))
    return result


def local_symbols(instrs):
    # The form of a local symbol differs between Linux assemblers and
    # the Apple assember:
    #
    # Linux: .Lxxx
    # Apple: Lxxx
    #
    # Change occurrences of local symbols to use the Loc() cpp macro
    # defined in our prefix.
    #
    lsyms = set()
    result = []

    def find1 (lsyms, (a, b, c)):
        mo = re.match(&#39;(\.L[^ \t:]*)[ \t]*:&#39;, b)
        if mo:
            lsyms.add(mo.group(1))
        return lsyms

    def repl1((lsyms, result), (a, b, c)):
        matches = list(re.finditer(&#39;\.L[^ \t@:,+*/\-()]+&#39;, b))
        if matches != []:
            matches.reverse()
            newb = b
            for mo in matches:
                if mo.group() in lsyms:
                    newb = newb[0:mo.start()] + \
                            &#39;Loc(&#39; + mo.group()[2:] + &#39;)&#39; + \
                            newb[mo.end():]
            result.append((a, newb, c))
        else:
            result.append((a, b, c))
        return (lsyms, result)

    reduce(find1, instrs, lsyms)
    reduce(repl1, instrs, (lsyms, result))
    return result


def funtypes(instrs):
    # Linux assemblers accept declarations like this:
    #
    #     .type  symbol, %function
    #
    # For Thumb functions, the Apple assembler wants to see:
    #
    #     .thumb_func symbol
    #
    # Handle this by converting declarations to this:
    #
    #     .funtype symbol
    #
    # Our prefix defines an appropriate .funtype macro for each
    # environment.
    #
    result = []

    def repl1(result, (a, b, c)):
        mo = re.match(&#39;.type[ \t]+([^ \t,]*),[ \t]*%function&#39;, b)
        if mo:
            result.append((a, &#39;.funtype  &#39; + mo.group(1), c))
        else:
            result.append((a, b, c))
        return result

    reduce(repl1, instrs, result)
    return result


def jump_tables(instrs):
    # Jump tables for Linux assemblers often look like this:
    #
    #     tbh [pc, rM, lsl #1]
    #     .short (.Labc-.)/2+0
    #     .short (.Ldef-.)/2+1
    #     .short (.Lghi-.)/2+2
    #
    # The Apple assembler disagrees about the meaning of this code,
    # producing jump tables that don&#39;t work.  Convert to the following:
    #
    #     tbh [pc, rM, lsl #1]
    # .LBxxx:
    #     .short (.Labc-.LBxxx)/2
    #     .short (.Ldef-.LBxxx)/2
    #     .short (.Lghi-.LBxxx)/2
    #
    # In fact we just convert sequences of .short pseudo-ops of the
    # right form.  There&#39;s no requirement that they follow a tbh
    # instruction.
    #
    baselabs = []
    result = []

    def short_match(seq, op):
        # Determine whether the op is a .short of the form that needs to
        # be converted: .short (symbol-.)/2+k.  If so, return a pair
        # containing the symbol and the value of k.  If not, return
        # None.  The short can only be converted if there were at least
        # k other .shorts in sequence before the current one.  A summary
        # of the previous .shorts is in seq.
        #
        # (A real scanner and parser would do a better job, but this was
        # quick to get working.)
        #
        sp = &#39;([ \t]|/\*.*?\*/)*&#39;              # space
        sp1 = &#39;([ \t]|/\*.*?\*/)+&#39;             # at least 1 space
        spe = &#39;([ \t]|/\*.*?\*/|@[^\n]*)*$&#39;    # end-of-instr space
        expr_re0 = (
            &#39;\.short&#39; + sp + &#39;\(&#39; + sp +       # .short (
            &#39;([^ \t+\-*/@()]+)&#39; + sp +         # symbol
            &#39;-&#39; + sp + &#39;\.&#39; + sp + &#39;\)&#39; + sp + # -.)
            &#39;/&#39; + sp + &#39;2&#39; + spe               # /2 END
        )
        expr_re1 = (
            &#39;\.short&#39; + sp + &#39;\(&#39; + sp +       # .short (
            &#39;([^ \t+\-*/@()]+)&#39; + sp +         # symbol
            &#39;-&#39; + sp + &#39;\.&#39; + sp + &#39;\)&#39; + sp + # -.)
            &#39;/&#39; + sp + &#39;2&#39; + sp +              # /2
            &#39;\+&#39; + sp +                        # +
            &#39;((0[xX])?[0-9]+)&#39; + spe           # k END
        )
        expr_re2 = (
            &#39;\.short&#39; + sp1 +                  # .short
            &#39;((0[xX])?[0-9]+)&#39; + sp +          # k
            &#39;\+&#39; + sp + &#39;\(&#39; + sp +            # +(
            &#39;([^ \t+\-*/@()]+)&#39; + sp +         # symbol
            &#39;-&#39; + sp + &#39;\.&#39; + sp + &#39;\)&#39; + sp + # -.)
            &#39;/&#39; + sp + &#39;2&#39; + spe               # /2 END
        )
        mo = re.match(expr_re0, op)
        if mo:
            return(mo.group(3), 0)
        mo = re.match(expr_re1, op)
        if mo:
            k = int(mo.group(11), 0)
            if k &#38;gt; len(seq):
                return None
            return (mo.group(3), k)
        mo = re.match(expr_re2, op)
        if mo:
            k = int(mo.group(2), 0)
            if k &#38;gt; len(seq):
                return None
            return (mo.group(7), k)
        return None

    def conv1 ((baselabs, shortseq, label, result), (a, b, c)):
        # Convert current instr (a,b,c) if it&#39;s a .short of the right
        # form that spans a previous sequence of .shorts.
        #
        (b1, b2, b3) = parse_iparts(b)

        if b3 == &#39;&#39;:
            # No operation: just note label if present.
            result.append((a, b, c))
            if re.match(&#39;\.L.&#39;, b1):
                return (baselabs, shortseq, b1, result)
            return (baselabs, shortseq, label, result)

        if not re.match(&#39;.short[ \t]+[^ \t@]&#39;, b3):
            # Not a .short: clear shortseq and label
            result.append((a, b, c))
            return (baselabs, [], &#39;&#39;, result)

        # We have a .short: figure out the label if any
        if re.match(&#39;\.L&#39;, b1):
            sl = b1
        else:
            sl = label

        mpair = short_match(shortseq, b3)
        if not mpair:
            # A .short, but not of right form
            shortseq.append((len(result), sl))
            result.append((a, b, c))
            return (baselabs, shortseq, &#39;&#39;, result)

        # OK, we have a .short to convert!
        (sym, k) = mpair
        shortseq.append((len(result), sl))

        # Figure out base label (create one if necessary).
        bx = len(shortseq) - 1 - k
        bl = shortseq[bx][1]
        if bl == &#39;&#39;:
            bl = g_basepfx + str(shortseq[bx][0])
            shortseq[bx] = (shortseq[bx][0], bl)
            baselabs.append(shortseq[bx])

        op = &#39;.short\t(&#39; + sym + &#39;-&#39; + bl + &#39;)/2&#39;

        result.append ((a, b1 + b2 + op, c))
        return (baselabs, shortseq, &#39;&#39;, result)

    # Convert, accumulate result and new labels.
    reduce(conv1, instrs, (baselabs, [], &#39;&#39;, result))

    # Add labels created here to the instruction stream.
    baselabs.reverse()
    for (ix, lab) in baselabs:
        result[ix:0] = [(&#39;&#39;, lab + &#39;:&#39;, &#39;\n&#39;)]

    # That does it
    return result


def read_input():
    # Concatenate all the input files into a string.
    #
    def fnl(s):
        if s == &#39;&#39; or s[-1] == &#39;\n&#39;:
            return s
        else:
            return s + &#39;\n&#39;

    if len(sys.argv) &#38;lt; 2:
        return fnl(sys.stdin.read())
    else:
        input = &#34;&#34;
        for f in sys.argv[1:]:
            try:
                fd = open(f)
                input = input + fnl(fd.read())
                fd.close()
            except:
                sys.stderr.write(&#39;arm-as-to-ios: cannot open &#39; + f + &#39;\n&#39;)
        return input


def parse_instrs(s):
    # Parse the string into assembly instructions, also noting C
    # preprocessor lines.  Each instruction is represented as a triple:
    # (space/comments, instruction, end).  The end is either &#39;;&#39; or
    # &#39;\n&#39;.  Instructions might have embedded comments, but they
    # probably won&#39;t get fixed up if they do.  (I&#39;ve never seen it in
    # real code.)
    #
    def goodmo(mo):
        if mo == None:
            # Should never happen
            sys.stderr.write(&#39;arm-as-to-ios: internal parsing error\n&#39;)
            sys.exit(1)

    cpp_re = &#39;([ \t]*)(#([^\n]*\\\\\n)*[^\n]*[^\\\\\n])\n&#39;
    comment_re = &#39;[ \t]*#[^\n]*&#39;
    instr_re = (
        &#39;(([ \t]|/\*.*?\*/|@[^\n]*)*)&#39;  # Spaces &#38;amp; comments
        &#39;(([ \t]|/\*.*?\*/|[^;\n])*)&#39;   # &#34;Instruction&#34;
        &#39;([;\n])&#39;                       # End
    )
    instrs = []
    while s != &#39;&#39;:
        if re.match(&#39;[ \t]*#[ \t]*(if|ifdef|elif|else|endif|define)&#39;, s):
            mo = re.match(cpp_re, s)
            goodmo(mo)
            instrs.append((mo.group(1), mo.group(2), &#39;\n&#39;))
        elif re.match(&#39;[ \t]*#&#39;, s):
            mo = re.match(comment_re, s)
            goodmo(mo)
            instrs.append((mo.group(0), &#39;&#39;, &#39;\n&#39;))
        else:
            mo = re.match(instr_re, s, re.DOTALL)
            goodmo(mo)
            instrs.append((mo.group(1), mo.group(3), mo.group(5)))
        s = s[len(mo.group(0)):]
    return instrs


def parse_iparts(i):
    # Parse an instruction into smaller parts, returning a triple of
    # strings (label, colon, operation).  The colon part also contains
    # any surrounding spaces and comments (making the label and the
    # operation cleaner to process).
    #
    # (Caller warrants that the given string doesn&#39;t start with space or
    # a comment.  This is true for strings returned by the instruction
    # parser.)
    #
    lab_re = (
        &#39;([^ \t:/@]+)&#39;                  # Label
        &#39;(([ \t]|/\*.*?\*/|@[^\n]*)*)&#39;  # Spaces &#38;amp; comments
        &#39;:&#39;                             # Colon
        &#39;(([ \t]|/\*.*?\*/|@[^\n]*)*)&#39;  # Spaces &#38;amp; comments
        &#39;([^\n]*)&#39;                      # Operation
    )

    if len(i) &#38;gt; 0 and i[0] == &#39;#&#39;:
        # C preprocessor line; treat as operation.
        return (&#39;&#39;, &#39;&#39;, i)
    mo = re.match(lab_re, i)
    if mo:
        return (mo.group(1), mo.group(2) + &#39;:&#39; + mo.group(4), mo.group(6))
    # No label, just an operation
    return (&#39;&#39;, &#39;&#39;, i)


def debug_parse(a, b, c):
    # Show results of instuction stream parse.
    #
    (b1, b2, b3) = parse_iparts(b)
    newb = &#39;{&#39; + b1 + &#39;}&#39; + &#39;{&#39; + b2 + &#39;}&#39; + &#39;{&#39; + b3 + &#39;}&#39;
    sys.stdout.write(&#39;{&#39; + a + &#39;}&#39; + newb + c)


def main():
    instrs = parse_instrs(read_input())
    instrs = explicit_address_loads(instrs)
    instrs = funtypes(instrs)
    instrs = jump_tables(instrs)
    instrs = global_symbols(instrs)
    instrs = local_symbols(instrs)
    instrs = add_prefix(instrs)
    for (a, b, c) in instrs:
       sys.stdout.write(a + b + c)


main()&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;style type=&#34;text/css&#34;&gt;
.flowaroundimg {
       float: left;
       margin: 0em 1em 0em 0em;
}
pre {
    white-space: pre-wrap;
    width: 96%;
    margin-bottom: 24px;
    overflow: hidden;
    padding: 3px 10px;
    -webkit-border-radius: 3px;
    background-color: #fed;
    border: 1px solid #dcb;
}
code {
    white-space: nowrap;
    font-size: 1.1em;
}
pre code {
    white-space: pre-wrap;
    font-size: 1.1em;
    padding: 0;
    border: none;
    background-color: transparent;
    -webkit-border-radius: 0;
}
&lt;/style&gt;&lt;/p&gt;
&lt;!--#include virtual=&#34;${Base_URL}/templates/footer.html&#34; --&gt;</content></entry><entry><title>OCaml 4.00.0 Working on iOS</title><link href="http://psellos.com/2012/07/2012.07.ocamlxarm-ocaml4-1.html"/><id>http://psellos.com/2012/07/2012.07.ocamlxarm-ocaml4-1.html</id><updated>2012-07-31T11:00:00-08:00</updated><content type="html">&lt;!--#include virtual=&#34;${Base_URL}/templates/header.html&#34; --&gt;&lt;div class=&#34;date&#34;&gt;July 31, 2012&lt;/div&gt;

&lt;p&gt;I&#38;#8217;ve been having a great time modifying OCaml 4.00.0 to work on iOS, and today I was able to build the &lt;a href=&#34;http://psellos.com/ocaml/example-app-portland.html&#34;&gt;Portland example app&lt;/a&gt; with my modified compiler, and run it on an iPod Touch.  It seems to be running normally (knock on wood), so things are looking very good.  Before releasing it I want to test some more demanding apps, and also clean up a few loose ends.&lt;/p&gt;

&lt;div class=&#34;flowaroundimg&#34; style=&#34;margin-top: 1.0em;&#34;&gt;
&lt;a href=&#34;http://psellos.com/ocaml/example-app-portland.html&#34;&gt;&lt;img src=&#34;http://psellos.com/images/portland-upside-p3.png&#34;&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;I call the compiler OCamlXARM because it runs on a Mac, and cross-compiles for ARM-based iOS devices.  It requires Apple&#38;#8217;s Xcode, which contains the necessary cross-compilation toolchain and the Cocoa Touch libraries.   Right now my test version builds for armv7/Thumb, which means the generated apps only run on moderately recent iOS devices (including all iPads).  I don&#38;#8217;t foresee any problem creating a version of OCamlXARM  for armv6/ARM, which will support all the historical iOS devices.  It should also be possible to generate code for armv7/ARM.  It should just be a matter of working through the details.&lt;/p&gt;

&lt;p&gt;If you&#38;#8217;re interested in trying a prerelease, send me an email.  I recommend this for the adventurous only.  The less adventurous can try &lt;a href=&#34;http://psellos.com/ocaml/compile-to-iphone.html&#34;&gt;version 1.0.15 of OCamlXARM&lt;/a&gt;, which is based on OCaml 3.10.2 (admittedly, a rather old OCaml release).&lt;/p&gt;

&lt;p&gt;The newly revamped ARM code generation in OCaml 4 is the work of Benedikt Meurer of the University of Siegen.  My modifications just add support for iOS, while leaving the existing Linux support in place.  For any brothers and sisters working at low levels, here are the changes I&#38;#8217;ve made so far.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The runtime assembly language file &lt;code&gt;arm.S&lt;/code&gt; needs to be translated into proper form for the Apple assembler.  Rather than doing this by hand, I wrote a Python script named &lt;code&gt;arm-as-to-ios&lt;/code&gt; that does the translation.  In fact, its output works both with Linux and Apple assemblers.  For those interested, I&#38;#8217;ve written a &lt;a href=&#34;http://psellos.com/2012/08/2012.08.arm-as-to-ios-3.html&#34;&gt;blog post about &lt;code&gt;arm-as-to-ios&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make the same modifications to the code emitted by the OCaml compiler itself.   The native code OCaml compiler works by emitting assembly code and then passing it to an external assembler.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Revamp code emitted for jump tables.  The Apple assembler disagrees about the meaning of the jump table code emitted by the stock compiler, and the resulting code crashes.  The new emitted code is intended to work for both Linux and Apple assemblers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add support for Apple&#38;#8217;s slightly different linkage to C.  In essence, floating values are passed and returned in pairs of integer registers rather than in floating registers.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I&#38;#8217;ll test more thoroughly, then I&#38;#8217;ll release the OCamlXARM patches and binary.  The new version will be OCamlXARM 3.1. I&#38;#8217;m looking forward to trying out the new OCaml language features, and maybe doing some timing tests to see if armv7/Thumb code is faster than the armv6/ARM code generated by the previous OCamlXARM release.&lt;/p&gt;

&lt;p&gt;If you have comments or questions, please leave them below, or email me at &lt;a href=&#34;&#38;#x6d;&#38;#x61;&#38;#x69;&#38;#108;&#38;#x74;&#38;#x6f;&#38;#x3a;j&#38;#x65;&#38;#x66;&#38;#x66;&#38;#115;&#38;#099;&#38;#x6f;&#38;#064;&#38;#112;&#38;#115;&#38;#x65;l&#38;#x6c;&#38;#x6f;s&#38;#046;&#38;#x63;&#38;#x6f;&#38;#x6d;&#34;&gt;&#38;#106;e&#38;#102;&#38;#x66;&#38;#115;&#38;#099;o&#38;#064;&#38;#112;&#38;#115;&#38;#x65;&#38;#108;l&#38;#x6f;&#38;#x73;&#38;#x2e;&#38;#x63;&#38;#111;&#38;#109;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Posted by: &lt;a href=&#34;http://psellos.com/aboutus.html#jeffreya.scofieldphd&#34;&gt;Jeffrey&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;style type=&#34;text/css&#34;&gt;
.flowaroundimg {
       float: left;
       margin: 0em 1em 0em 0em;
}
&lt;/style&gt;&lt;/p&gt;
&lt;!--#include virtual=&#34;${Base_URL}/templates/footer.html&#34; --&gt;</content></entry><entry><title type="html">Convert ARM Assembly Code for Apple&#38;#8217;s iOS Assembler (Update 1)</title><link href="http://psellos.com/2012/07/2012.07.arm-as-to-ios-2.html"/><id>http://psellos.com/2012/07/2012.07.arm-as-to-ios-2.html</id><updated>2012-07-19T11:00:00-08:00</updated><content type="html">&lt;!--#include virtual=&#34;${Base_URL}/templates/header.html&#34; --&gt;&lt;div class=&#34;date&#34;&gt;July 19, 2012&lt;/div&gt;

&lt;p&gt;I&#38;#8217;m making reasonable progress in getting OCaml 4.00.0 working on iOS.
Just now I was able to build the entire system in a hybrid form, where
the compiler is built for the host (OS X i386) and the standard library
is built for the target (iOS ARM).  This is already pretty close to what
you want for a cross compiler.  I&#38;#8217;m hoping to be able to test some
generated code on an iOS device soon.  At the same time, OCaml 4.00.0
has reached the release candidate stage, so things are really starting
to cook.&lt;/p&gt;

&lt;p&gt;While building the libraries for ARM, I learned more about the
incompatibilities between the GNU ARM assembler (for the supported Linux
targets of OCaml) and Apple&#38;#8217;s ARM assembler for iOS.  This led me to
revamp my Python script that converts ARM assembly code from the current
GNU format to the required Apple format.  I also decided I should make
the conversion upward compatible; in other words, the converted assembly
file should continue to work in its originally supported Linux
environments as well as in iOS.&lt;/p&gt;

&lt;p style=&#34;background-color: #fed; border: 1px solid #dcb; padding: 0.7em;&#34;&gt;
&lt;em&gt;Note&lt;/em&gt;: I wrote a new, improved version of this script, described
in &lt;a href=&#34;http://psellos.com/2012/08/2012.08.arm-as-to-ios-4.html&#34;&gt;Convert Linux ARM
Assembly Code for iOS (Update 3)&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;The advantage of using a script is that it keeps the changes consistent,
and it will still be useful if &lt;code&gt;arm.S&lt;/code&gt; is rewritten in the future.  The
script, named &lt;code&gt;arm-as-to-ios&lt;/code&gt;, now does the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Declare the architecture for iOS.  The possibilities are &lt;code&gt;armv6&lt;/code&gt; and
&lt;code&gt;armv7&lt;/code&gt;.  Currently I&#38;#8217;m concentrating on getting &lt;code&gt;armv7&lt;/code&gt; to work, but
the generated file also assembles successfully for &lt;code&gt;armv6&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Specify that &lt;code&gt;armv7&lt;/code&gt; code should use the more space-efficient Thumb
encoding in iOS.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Generate declarations for functions, similar to the &lt;code&gt;.type&lt;/code&gt; pseudo-op
for the Linux targets.  It appears that Apple requires &lt;code&gt;.thumb_func&lt;/code&gt;
declarations only for Thumb functions.  Other symbols are apparently
assumed to be ARM functions.  To make this work upward-compatibly, I
define an assembly macro named &lt;code&gt;.funtype&lt;/code&gt; that is expanded properly in
the different environments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make sure that assembler-local symbols have the right format.  For GNU
assemblers, they look like &#38;#8220;&lt;code&gt;.Lxxx&lt;/code&gt;&#38;#8221;.  For the Apple assembler, they
look like &#38;#8220;&lt;code&gt;Lxxx&lt;/code&gt;&#38;#8221;.  To support upward compatibly, this is handled by a
cpp macro named &lt;code&gt;Loc()&lt;/code&gt; that generates the proper symbol form for each
environment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Replace uses of &lt;code&gt;=&lt;/code&gt;&lt;em&gt;value&lt;/em&gt; notation by explicit loads from memory.
The usual ARM assemblers interpret &lt;code&gt;ldr rM, =&lt;/code&gt;&lt;em&gt;value&lt;/em&gt; to mean that the
&lt;em&gt;value&lt;/em&gt; should be loaded into register M immediately (using &lt;code&gt;mov&lt;/code&gt;) if
possible, and loaded from memory (using &lt;code&gt;ldr&lt;/code&gt; with PC-relative
addressing) otherwise.  The Apple assembler seems not to support this.
&lt;code&gt;arm-as-to-ios&lt;/code&gt; replaces uses of &lt;code&gt;=&lt;/code&gt;&lt;em&gt;value&lt;/em&gt; with explicit memory
loads, emitting the pool of values into the &lt;code&gt;.text&lt;/code&gt; segment at the end
of the file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove uses of two pseudo-ops, &lt;code&gt;.type&lt;/code&gt; and &lt;code&gt;.size&lt;/code&gt;, when assembling
for iOS.  They aren&#38;#8217;t supported by Apple&#38;#8217;s assembler.  This is done by
defining null macros for them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Define a macro &lt;code&gt;cbz&lt;/code&gt; when using ARM encodings for iOS.  The &lt;code&gt;cbz&lt;/code&gt;
instruction is Thumb-only.  The definition replaces it with a pair
of ARM instructions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another advantage of using a script is that it might be useful to other
people who need to port ARM assembly code to iOS.  Granted, there
probably aren&#38;#8217;t a lot of people doing this.  But if you are, maybe the
script will provide a useful starting point.&lt;/p&gt;

&lt;p&gt;You can download the script here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://psellos.com/pub/ocamlxarm/arm-as-to-ios&#34;&gt;arm-as-to-ios&#38;#8212;modify ARM assembly code for use on iOS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The full text of the script is also included at the end of this post.&lt;/p&gt;

&lt;p&gt;As I expected, I&#38;#8217;ve already updated the script based on what I&#38;#8217;ve
learned while doing the OCaml 4-on-iOS project.  As I make changes, I&#38;#8217;ll
keep the linked script up to date.  If there are more large changes I&#38;#8217;ll
make another post about them.&lt;/p&gt;

&lt;p&gt;If you want to try out &lt;code&gt;arm-as-to-ios&lt;/code&gt;, copy and paste the lines from
the end of this post into a file named &lt;code&gt;arm-as-to-ios&lt;/code&gt;, or download it
from the above link.  Mark it as a script with &lt;code&gt;chmod&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ chmod +x arm-as-to-ios&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To use the script, specify the name of an ARM assembly file.  If no
files are given, the script processes its standard input.&lt;/p&gt;

&lt;p&gt;The following small example demonstrates the translations that
&lt;code&gt;arm-as-to-ios&lt;/code&gt; performs.  Here is a small file of Linux (non-Apple) ARM
assembly language:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;        .syntax unified
        .text
        .align  2
        .globl  example
        .type example, %function
example:
        sub     r10, r10, 8
        cmp     r10, r11
        bcc     1f
        bx      lr
1:
        ldr     r7, =last_return_address
        str     lr, [r7]
        bl      .Lcall_gc
        ldr     lr, [r7]
        b       example

.Lcall_gc:
        ldr     r12, =bottom_of_stack
        str     sp, [r12]
        bl      garbage_collection
        bx      lr&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you run &lt;code&gt;arm-as-to-ios&lt;/code&gt; on this file, you get the following output
that works for all assemblers (Linux and Apple):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;        .syntax unified

/* Apple compatibility macros */
#if defined(SYS_macosx)
#define Loc(s) L##s
#if defined(MODEL_armv6)
        .machine  armv6
        .macro  .funtype
        .endm
        .macro  cbz
        cmp     $0, #0
        beq     $1
        .endm
#else
        .machine  armv7
        .thumb
        .macro  .funtype
        .thumb_func $0
        .endm
#endif
        .macro  .type
        .endm
        .macro  .size
        .endm
#else
#define Loc(s) .L##s
        .macro  .funtype symbol
        .type  \symbol, %function
        .endm
#endif
        .text
        .align  2
        .globl  example
        .funtype  example
example:
        sub     r10, r10, 8
        cmp     r10, r11
        bcc     1f
        bx      lr
1:
        ldr     r7, Loc(Plast_return_address)
        str     lr, [r7]
        bl      Loc(call_gc)
        ldr     lr, [r7]
        b       example

Loc(call_gc):
        ldr     r12, Loc(Pbottom_of_stack)
        str     sp, [r12]
        bl      garbage_collection
        bx      lr

/* Pool of addresses loaded into registers */

        .text
        .align 2
Loc(Plast_return_address):
        .long last_return_address
Loc(Pbottom_of_stack):
        .long bottom_of_stack&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The output consists of a fixed prefix followed by the translation of the
input file, followed by the pool of values to be loaded into registers.&lt;/p&gt;

&lt;p&gt;The following shows a successful assembly of &lt;code&gt;arm.S&lt;/code&gt; from OCaml 4.00.0:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ PLT=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform
$ PLTBIN=$PLT/Developer/usr/bin
$ arm-as-to-ios asmrun/arm.S &#38;gt; armios.S
$ $PLTBIN/gcc -c -arch armv7 -DSYS_macosx -DMODEL_armv7 -o armios.o armios.S
$ file armios.o
armios.o: Mach-O object arm
$ otool -tv armios.o | head
armios.o:
(__TEXT,__text) section
caml_call_gc:
00000000        f8dfc1e0        ldr.w   ip, [pc, #480]  @ 0x1e4
00000004        f8cce000        str.w   lr, [ip]
00000008        f8dfc1dc        ldr.w   ip, [pc, #476]  @ 0x1e8
0000000c        f8ccd000        str.w   sp, [ip]
00000010        ed2d0b10        vstmdb  sp!, {d0-d7}
00000014        e92d50ff        stmdb   sp!, {r0, r1, r2, r3, r4, r5, r6, r7, ip, lr}
00000018        f8dfc1d0        ldr.w   ip, [pc, #464]  @ 0x1ec&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you have any corrections, improvements, or other comments, leave them
below or email me at &lt;a href=&#34;&#38;#x6d;&#38;#x61;&#38;#x69;&#38;#108;&#38;#x74;&#38;#x6f;&#38;#x3a;j&#38;#x65;&#38;#x66;&#38;#x66;&#38;#115;&#38;#099;&#38;#x6f;&#38;#064;&#38;#112;&#38;#115;&#38;#x65;l&#38;#x6c;&#38;#x6f;s&#38;#046;&#38;#x63;&#38;#x6f;&#38;#x6d;&#34;&gt;&#38;#106;e&#38;#102;&#38;#x66;&#38;#115;&#38;#099;o&#38;#064;&#38;#112;&#38;#115;&#38;#x65;&#38;#108;l&#38;#x6f;&#38;#x73;&#38;#x2e;&#38;#x63;&#38;#111;&#38;#109;&lt;/a&gt;.  I&#38;#8217;d be very pleased to hear
if the script has been helpful to anyone.&lt;/p&gt;

&lt;p&gt;Posted by: &lt;a href=&#34;http://psellos.com/aboutus.html#jeffreya.scofieldphd&#34;&gt;Jeffrey&lt;/a&gt;&lt;/p&gt;

&lt;h4 id=&#34;appendix&#34;&gt;Appendix&lt;/h4&gt;

&lt;p&gt;Here is the current text of the script:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!/usr/bin/env python
#
# arm-as-to-ios     Modify ARM assembly code for the iOS assembler
#
# Copyright (c) 2012 Psellos   http://psellos.com/
# Licensed under the MIT License:
#     http://www.opensource.org/licenses/mit-license.php
#
# Resources for running OCaml on iOS: http://psellos.com/ocaml/
#
import sys
import re

VERSION = &#39;1.1.0&#39;


def add_prefix(instrs):
    # Add compatibility macros for all systems, plus hardware
    # definitions and compatibility macros for iOS.
    #
    # All systems:
    #
    # Loc()     cpp macro for making local symbols (.Lxxx vs Lxxx)
    # .funtype  Expands to .thumb_func for iOS armv7 (null for armv6)
    #           Expands to .type %function for others
    #
    # iOS:
    #
    # .machine  armv6/armv7
    # .thumb    (for armv7)
    # cbz       Expands to cmp/beq for armv6 (Thumb-only instr)
    # .type     Not supported by Apple assembler
    # .size     Not supported by Apple assembler
    #
    defre = &#39;#[ \t]*if.*def.*SYS&#39;  # Add new defs near first existing ones
    skipre = &#39;$|\.syntax[ \t]&#39;     # Skip comments lines (and .syntax)

    for i in range(len(instrs)):
        if re.match(defre, instrs[i][1]):
            break
    else:
        i = 0
    for i in range(i, len(instrs)):
        if not re.match(skipre, instrs[i][1]):
            break
    instrs[i:0] = [
        (&#39;&#39;, &#39;&#39;, &#39;\n&#39;),
        (&#39;/* Apple compatibility macros */&#39;, &#39;&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;#if defined(SYS_macosx)&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;#define Loc(s) L##s&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;#if defined(MODEL_armv6)&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.machine  armv6&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.macro  .funtype&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.endm&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.macro  cbz&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;cmp     $0, #0&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;beq     $1&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.endm&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;#else&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.machine  armv7&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.thumb&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.macro  .funtype&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.thumb_func $0&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.endm&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;#endif&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.macro  .type&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.endm&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.macro  .size&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.endm&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;#else&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;#define Loc(s) .L##s&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.macro  .funtype symbol&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.type  \\symbol, %function&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.endm&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;#endif&#39;, &#39;\n&#39;)
    ]
    return instrs


# Prefix for pooled symbols.  It&#39;s in the space of local symbols for the
# input file.  Later rules will modify this to the Loc() form.
#
g_prefix = &#39;.LP&#39;

# Regular expression for modified ldr lines
#
g_ldre = &#39;(ldr[ \t][^,]*,[ \t]*)=(([^ \t\n@,/]|/(?!\*))*)(.*)&#39;


def explicit_address_loads(instrs):
    # The Gnu assembler allows the following:
    #
    #     ldr rM, =symbol
    #
    # which loads rM with [mov] (immediately) if possible, or creates an
    # entry in memory for the symbol value and loads it PC-relatively
    # with [ldr].
    #
    # The Apple assembler doesn&#39;t seem to support this notation.  If the
    # value is a suitable constant, it emits a valid [mov].  Otherwise
    # it seems to emit an invalid [ldr] that always generates an error.
    # (At least I have not been able to make it work).  So, change uses
    # of =symbol to explicit PC-relative loads.
    #
    # This requires a pool containing the addresses to be loaded.  For
    # now, we just keep track of it ourselves and emit it into the text
    # segment at the end of the file.
    #
    syms = {}
    result = []

    def repl1((syms, result), (a, b, c)):
        global g_prefix
        global g_ldre
        mo = re.match(g_ldre, b, re.DOTALL)
        if mo:
            if mo.group(2) not in syms:
                syms[mo.group(2)] = len(syms)
            psym = mo.group(2)
            if psym[0:2] == &#39;.L&#39;:
                psym = psym[2:]
            newb = mo.group(1) + g_prefix + psym + mo.group(4)
            result.append((a, newb, c))
        else:
            result.append((a, b, c))
        return (syms, result)

    def pool1(result, s):
        global g_prefix
        psym = s
        if psym[0:2] == &#39;.L&#39;:
            psym = psym[2:]
        result.append((&#39;&#39;, g_prefix + psym + &#39;:&#39;, &#39;\n&#39;))
        result.append((&#39;        &#39;, &#39;.long &#39; + s, &#39;\n&#39;))
        return result

    reduce(repl1, instrs, (syms, result))
    if len(syms) &#38;gt; 0:
        result.append((&#39;&#39;, &#39;&#39;, &#39;\n&#39;))
        result.append((&#39;/* Pool of addresses loaded into registers */&#39;,
                        &#39;&#39;, &#39;\n&#39;))
        result.append((&#39;&#39;, &#39;&#39;, &#39;\n&#39;))
        result.append((&#39;        &#39;, &#39;.text&#39;, &#39;\n&#39;))
        result.append((&#39;        &#39;, &#39;.align 2&#39;, &#39;\n&#39;))
        reduce(pool1, sorted(syms, key=syms.get), result)
    return result


def local_symbols(instrs):
    # The form of a local symbol differs between Gnu assemblers and the
    # Apple assember:
    #
    # Gnu:   .Lxxx
    # Apple: Lxxx
    #
    # Change occurrences of local symbols to use the Loc() cpp macro
    # defined in our prefix.
    #
    lsyms = set()
    result = []

    def find1 (lsyms, (a, b, c)):
        mo = re.match(&#39;(\.L[^ \t:]*)[ \t]*:&#39;, b)
        if mo:
            lsyms.add(mo.group(1))
        return lsyms

    def repl1((lsyms, result), (a, b, c)):
        matches = list(re.finditer(&#39;\.L[^ \t@:,+*/-]+&#39;, b))
        if matches != []:
            matches.reverse()
            newb = b
            for mo in matches:
                if mo.group() in lsyms:
                    newb = newb[0:mo.start()] + \
                            &#39;Loc(&#39; + mo.group()[2:] + &#39;)&#39; + \
                            newb[mo.end():]
            result.append((a, newb, c))
        else:
            result.append((a, b, c))
        return (lsyms, result)

    reduce(find1, instrs, lsyms)
    reduce(repl1, instrs, (lsyms, result))
    return result


def funtypes(instrs):
    # Gnu assemblers accept declarations like this:
    #
    #     .type  symbol, %function
    #
    # For Thumb functions, the Apple assembler wants to see:
    #
    #     .thumb_func symbol
    #
    # Handle this by converting declarations to this:
    #
    #     .funtype symbol
    #
    # Our prefix defines an appropriate .funtype macro for each
    # environment.
    #
    result = []

    def repl1(result, (a, b, c)):
        mo = re.match(&#39;.type[ \t]+([^ \t,]*),[ \t]*%function&#39;, b)
        if mo:
            result.append((a, &#39;.funtype  &#39; + mo.group(1), c))
        else:
            result.append((a, b, c))
        return result

    reduce(repl1, instrs, result)
    return result


def read_input():
    # Concatenate all the input files into a string.
    #
    def fnl(s):
        if s == &#39;&#39; or s[-1] == &#39;\n&#39;:
            return s
        else:
            return s + &#39;\n&#39;

    if len(sys.argv) &#38;lt; 2:
        return fnl(sys.stdin.read())
    else:
        input = &#34;&#34;
        for f in sys.argv[1:]:
            try:
                fd = open(f)
                input = input + fnl(fd.read())
                fd.close()
            except:
                sys.stderr.write(&#39;arm-as-to-ios: cannot open &#39; + f + &#39;\n&#39;)
        return input


def parse_instrs(s):
    # Parse the string into assembly instructions, also noting C
    # preprocessor lines.  Each instruction is represented as a triple:
    # (space/comments, instruction, end).  The end is either &#39;;&#39; or
    # &#39;\n&#39;.  Instructions might have embedded comments, but they
    # probably won&#39;t get fixed up if they do.  (I&#39;ve never seen it in
    # real code.)
    #
    def goodmo(mo):
        if mo == None:
            # Should never happen
            sys.stderr.write(&#39;arm-as-to-ios: internal parsing error\n&#39;)
            sys.exit(1)

    cpp_re = &#39;([ \t]*)(#([^\n]*\\\\\n)*[^\n]*[^\\\\\n])\n&#39;
    comment_re = &#39;[ \t]*#[^\n]*&#39;
    instr_re = (
        &#39;(([ \t]|/\*.*?\*/|@[^\n]*)*)&#39;  # Spaces &#38;amp; comments
        &#39;(([ \t]|/\*.*?\*/|[^;\n])*)&#39;   # &#34;Instruction&#34;
        &#39;([;\n])&#39;                       # End
    )
    instrs = []
    while s != &#39;&#39;:
        if re.match(&#39;[ \t]*#[ \t]*(if|ifdef|elif|else|endif|define)&#39;, s):
            mo = re.match(cpp_re, s)
            goodmo(mo)
            instrs.append((mo.group(1), mo.group(2), &#39;\n&#39;))
        elif re.match(&#39;[ \t]*#&#39;, s):
            mo = re.match(comment_re, s)
            goodmo(mo)
            instrs.append((mo.group(0), &#39;&#39;, &#39;\n&#39;))
        else:
            mo = re.match(instr_re, s, re.DOTALL)
            goodmo(mo)
            instrs.append((mo.group(1), mo.group(3), mo.group(5)))
        s = s[len(mo.group(0)):]
    return instrs


def main():
    instrs = parse_instrs(read_input())
    instrs = explicit_address_loads(instrs)
    instrs = funtypes(instrs)
    instrs = local_symbols(instrs)
    instrs = add_prefix(instrs)
    for (a, b, c) in instrs:
        sys.stdout.write(a + b + c)
#        sys.stdout.write(&#39;{&#39; + a + &#39;}&#39; + &#39;{&#39; + b + &#39;}&#39; + c)


main()&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;style type=&#34;text/css&#34;&gt;
.flowaroundimg {
       float: left;
       margin: 0em 1em 0em 0em;
}
pre {
    white-space: pre-wrap;
    width: 96%;
    margin-bottom: 24px;
    overflow: hidden;
    padding: 3px 10px;
    -webkit-border-radius: 3px;
    background-color: #fed;
    border: 1px solid #dcb;
}
code {
    white-space: nowrap;
    font-size: 1.1em;
}
pre code {
    white-space: pre-wrap;
    font-size: 1.1em;
    padding: 0;
    border: none;
    background-color: transparent;
    -webkit-border-radius: 0;
}
&lt;/style&gt;&lt;/p&gt;
&lt;!--#include virtual=&#34;${Base_URL}/templates/footer.html&#34; --&gt;</content></entry><entry><title type="html">Convert ARM Assembly Code for Apple&#38;#8217;s iOS Assembler</title><link href="http://psellos.com/2012/07/2012.07.arm-as-to-ios.html"/><id>http://psellos.com/2012/07/2012.07.arm-as-to-ios.html</id><updated>2012-07-10T11:00:00-08:00</updated><content type="html">&lt;!--#include virtual=&#34;${Base_URL}/templates/header.html&#34; --&gt;&lt;div class=&#34;date&#34;&gt;July 10, 2012&lt;/div&gt;

&lt;p&gt;Recently I&#38;#8217;ve been working on getting OCaml 4.00.0 working on iOS.  As I
write this, 4.00.0 is the newest version of OCaml, not yet released but
available as a beta.  I&#38;#8217;m treating it as a new project, not trying to
re-use any of the patches we&#38;#8217;ve been using for OCaml 3.10.2.&lt;/p&gt;

&lt;p&gt;The first interesting problem I hit is that Apple&#38;#8217;s ARM assembler for
iOS (called &#38;#8220;&lt;code&gt;as&lt;/code&gt;&#38;#8221;, the traditional Unix name) is quite different from
other ARM assemblers.  Although it derives ultimately from the same GNU
codebase, it appears the Apple assembler split off many years ago and
has followed a separate evolutionary path.&lt;/p&gt;

&lt;p&gt;This needs to be solved for an OCaml-on-iOS port, because part of the
OCaml runtime is written in assembly code&#38;#8212;a file named &lt;code&gt;arm.S&lt;/code&gt;.  For
the work on OCaml 3.10.2, we rewrote &lt;code&gt;arm.S&lt;/code&gt; extensively by hand.  This
time, I decided to write a Python script to convert ARM assembly code
from the current GNU format to the format used by Apple&#38;#8217;s iOS assembler.
This keeps the changes consistent, and it ought to help when &lt;code&gt;arm.S&lt;/code&gt; is
rewritten in the future.&lt;/p&gt;

&lt;p style=&#34;background-color: #fed; border: 1px solid #dcb; padding: 0.7em;&#34;&gt;
&lt;em&gt;Note&lt;/em&gt;: I wrote a new, improved version of this script, described
in &lt;a href=&#34;http://psellos.com/2012/08/2012.08.arm-as-to-ios-4.html&#34;&gt;Convert Linux ARM
Assembly Code for iOS (Update 3)&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;So now I have a script named &lt;code&gt;arm-as-to-ios&lt;/code&gt; that works well enough to
convert &lt;code&gt;arm.S&lt;/code&gt; to a form that can be assembled for iOS.  It&#38;#8217;s nothing
fancy; currently it just makes the following changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Replace uses of &lt;code&gt;=&lt;/code&gt;&lt;em&gt;value&lt;/em&gt; notation by explicit loads from memory.
The usual ARM assemblers interpret &lt;code&gt;ldr rM, =&lt;/code&gt;&lt;em&gt;value&lt;/em&gt; to mean that the
&lt;em&gt;value&lt;/em&gt; should be loaded into register M immediately (using &lt;code&gt;mov&lt;/code&gt;) if
possible, and loaded from memory (using &lt;code&gt;ldr&lt;/code&gt; with PC-relative
addressing) otherwise.  The Apple assembler seems not to support this.
&lt;code&gt;arm-as-to-ios&lt;/code&gt; replaces uses of &lt;code&gt;=&lt;/code&gt;&lt;em&gt;value&lt;/em&gt; with explicit memory
loads, emitting the pool of values into the &lt;code&gt;.text&lt;/code&gt; segment at the end
of the file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove uses of two pseudo-ops, &lt;code&gt;.type&lt;/code&gt; and &lt;code&gt;.size&lt;/code&gt;.  They aren&#38;#8217;t
supported by Apple&#38;#8217;s assembler.  This is done by defining null macros
for them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Define a macro &lt;code&gt;cbz&lt;/code&gt;.  The &lt;code&gt;cbz&lt;/code&gt; instruction is Thumb-only.  This
defininition replaces it with a pair of ARM instructions.  Note that
the macro parameter syntax of Apple&#38;#8217;s assembler is different (possibly
just more restrictive) than the usual GNU tools.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another advantage of using a script is that it might be useful to other
people who need to port assembly code to iOS.  Granted, there probably
aren&#38;#8217;t a lot of people doing this.  But if you are, maybe the script
will provide a useful starting point.&lt;/p&gt;

&lt;p&gt;You can download the script here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://psellos.com/pub/ocamlxarm/arm-as-to-ios&#34;&gt;arm-as-to-ios&#38;#8212;modify ARM assembly code for use on iOS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have no doubt that I&#38;#8217;ll need to update the script as the project
progresses.  I&#38;#8217;ll keep the linked script up to date.  If there are large
changes I&#38;#8217;ll make another post about them.&lt;/p&gt;

&lt;p&gt;Here, also, is the current text of the script:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!/usr/bin/env python
#
# arm-as-to-ios     Modify ARM assembly code for the iOS assembler
#
# Copyright (c) 2012 Psellos   http://psellos.com/
# Licensed under the MIT License:
#     http://www.opensource.org/licenses/mit-license.php
#
# Resources for running OCaml on iOS: http://psellos.com/ocaml/
#
import sys
import re

VERSION = &#39;1.0.0&#39;


def add_macro_defs(instrs):
    # Emit compatibility macros.
    #
    # cbz:    Thumb only; replace with cmp/beq for ARM
    # .type:  Not supported by Apple assembler
    # .size:  Not supported by Apple assembler
    #
    skippable = &#39;$|\.syntax[ \t]&#39;
    i = 0
    for i in range(len(instrs)):
        if not re.match(skippable, instrs[i][1]):
            break
    instrs[i:0] = [
        (&#39;&#39;, &#39;&#39;, &#39;\n&#39;),
        (&#39;/* Apple compatibility macros */&#39;, &#39;&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.macro  cbz&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;cmp     $0, #0&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;beq     $1&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.endm&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.macro  .type&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.endm&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.macro  .size&#39;, &#39;\n&#39;),
        (&#39;        &#39;, &#39;.endm&#39;, &#39;\n&#39;),
        (&#39;&#39;, &#39;&#39;, &#39;\n&#39;)
    ]
    return instrs


# Prefix for derived symbols
#
g_prefix = &#39;PL&#39;

# Regular expression for modified ldr lines
#
g_ldre = &#39;(ldr[ \t][^,]*,[ \t]*)=(([^ \t\n@,/]|/(?!\*))*)(.*)&#39;


def explicit_address_loads(instrs):
    # The Gnu assembler allows the following:
    #
    #     ldr rM, =symbol
    #
    # which loads rM with [mov] (immediately) if possible, or creates an
    # entry in memory for the symbol value and loads it PC-relatively
    # with [ldr].
    #
    # The Apple assembler doesn&#39;t seem to support this notation.  If the
    # value is a suitable constant, it emits a valid [mov].  Otherwise
    # it seems to emit an invalid [ldr] that always generates an error.
    # (At least I have not been able to make it work).  So, change uses
    # of =symbol to explicit PC-relative loads.
    #
    # This requires a pool containing the addresses to be loaded.  For
    # now, we just keep track of it ourselves and emit it into the text
    # segment at the end of the file.
    syms = {}
    result = []

    def change1((syms, result), (a, b, c)):
        global g_prefix
        global g_ldre
        mo = re.match(g_ldre, b, re.DOTALL)
        if mo:
            if mo.group(2) not in syms:
                syms[mo.group(2)] = len(syms)
            newb = (mo.group(1) + g_prefix + mo.group(2) + mo.group(4))
            result.append((a, newb, c))
        else:
            result.append((a, b, c))
        return (syms, result)

    def pool1(result, s):
        global g_prefix
        result.append((&#39;&#39;, g_prefix + s + &#39;:&#39;, &#39;\n&#39;))
        result.append((&#39;        &#39;, &#39;.long &#39; + s, &#39;\n&#39;))
        return result

    reduce(change1, instrs, (syms, result))
    if len(syms) &#38;gt; 0:
        result.append((&#39;&#39;, &#39;&#39;, &#39;\n&#39;))
        result.append((&#39;/* Pool of addresses loaded into registers */&#39;,
                        &#39;&#39;, &#39;\n&#39;))
        result.append((&#39;&#39;, &#39;&#39;, &#39;\n&#39;))
        result.append((&#39;        &#39;, &#39;.text&#39;, &#39;\n&#39;))
        result.append((&#39;        &#39;, &#39;.align 2&#39;, &#39;\n&#39;))
        reduce(pool1, sorted(syms, key=syms.get), result)
    return result


def read_input():
    # Concatenate all the input files into a string.
    #
    def fnl(s):
        if s == &#39;&#39; or s[-1] == &#39;\n&#39;:
            return s
        else:
            return s + &#39;\n&#39;

    if len(sys.argv) &#38;lt; 2:
        return fnl(sys.stdin.read())
    else:
        input = &#34;&#34;
        for f in sys.argv[1:]:
            try:
                fd = open(f)
                input = input + fnl(fd.read())
                fd.close()
            except:
                sys.stderr.write(&#39;arm-as-to-ios: cannot open &#39; + f + &#39;\n&#39;)
        return input


def parse_instrs(s):
    # Parse the string into assembly instructions while tolerating C
    # preprocessor lines.  Each instruction is represented as a triple:
    # (space/comments, instruction, end).  The end is either &#39;;&#39; or
    # &#39;\n&#39;.  Instructions can have embedded comments, but they won&#39;t get
    # fixed up if they do.  (I&#39;ve never seen it in real code.)
    #
    def goodmo(mo):
        if mo == None:
            # Should never happen
            sys.stderr.write(&#39;arm-as-to-ios: internal parsing error\n&#39;)
            sys.exit(1)

    cpp_re = &#39;([ \t]*#([^\n]*\\\\\n)*[^\n]*[^\\\\\n])\n&#39;
    instr_re = (
        &#39;(([ \t]|/\*.*?\*/|@[^\n]*)*)&#39;  # Spaces &#38;amp; comments
        &#39;(([ \t]|/\*.*?\*/|[^;\n])*)&#39;   # &#34;Instruction&#34;
        &#39;([;\n])&#39;                       # End
    )
    instrs = []
    while s != &#39;&#39;:
        if re.match(&#39;[ \t]*#&#39;, s):
            mo = re.match(cpp_re, s)
            goodmo(mo)
            instrs.append((mo.group(1), &#39;&#39;, &#39;\n&#39;))
        else:
            mo = re.match(instr_re, s, re.DOTALL)
            goodmo(mo)
            instrs.append((mo.group(1), mo.group(3), mo.group(5)))
        s = s[len(mo.group(0)):]
    return instrs


def main():
    instrs = parse_instrs(read_input())
    instrs = add_macro_defs(instrs)
    instrs = explicit_address_loads(instrs)
    for (a, b, c) in instrs:
        sys.stdout.write(a + b + c)


main()&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Copy and paste the lines into a file named &lt;code&gt;arm-as-to-ios&lt;/code&gt; (or download
it from the above link).  Mark it as a script with chmod:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ chmod +x arm-as-to-ios&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To use the script, specify the name of an ARM assembly file.  If no
files are given, the script processes its standard input.  The following
shows a successful assembly of &lt;code&gt;arm.S&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ PLT=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform
$ PLTBIN=$PLT/Developer/usr/bin
$ arm-as-to-ios asmrun/arm.S | cpp &#38;gt; armios.S
$ $PLTBIN/as -arch armv6 -o armios.o armios.S
$ file armios.o
armios.o: Mach-O object arm
$ otool -tv armios.o | head
armios.o:
(__TEXT,__text) section
caml_call_gc:
00000000        e59fc2a0        ldr     ip, [pc, #672]  @ 0x2a8
00000004        e58ce000        str     lr, [ip]
.Lcaml_call_gc:
00000008        e59fc29c        ldr     ip, [pc, #668]  @ 0x2ac
0000000c        e58cd000        str     sp, [ip]
00000010        ed2d0b10        vstmdb  sp!, {d0-d7}
00000014        e92d50ff        push    {r0, r1, r2, r3, r4, r5, r6, r7, ip, lr}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you have any corrections, improvements, or other comments, leave them
below or email me at &lt;a href=&#34;&#38;#x6d;&#38;#x61;&#38;#x69;&#38;#108;&#38;#x74;&#38;#x6f;&#38;#x3a;j&#38;#x65;&#38;#x66;&#38;#x66;&#38;#115;&#38;#099;&#38;#x6f;&#38;#064;&#38;#112;&#38;#115;&#38;#x65;l&#38;#x6c;&#38;#x6f;s&#38;#046;&#38;#x63;&#38;#x6f;&#38;#x6d;&#34;&gt;&#38;#106;e&#38;#102;&#38;#x66;&#38;#115;&#38;#099;o&#38;#064;&#38;#112;&#38;#115;&#38;#x65;&#38;#108;l&#38;#x6f;&#38;#x73;&#38;#x2e;&#38;#x63;&#38;#111;&#38;#109;&lt;/a&gt;.  I&#38;#8217;d be very pleased to hear
if the script has been helpful to anyone.&lt;/p&gt;

&lt;p&gt;Posted by: &lt;a href=&#34;http://psellos.com/aboutus.html#jeffreya.scofieldphd&#34;&gt;Jeffrey&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;style type=&#34;text/css&#34;&gt;
.flowaroundimg {
       float: left;
       margin: 0em 1em 0em 0em;
}
pre {
    white-space: pre-wrap;
    width: 96%;
    margin-bottom: 24px;
    overflow: hidden;
    padding: 3px 10px;
    -webkit-border-radius: 3px;
    background-color: #fed;
    border: 1px solid #dcb;
}
code {
    white-space: nowrap;
    font-size: 1.1em;
}
pre code {
    white-space: pre-wrap;
    font-size: 1.1em;
    padding: 0;
    border: none;
    background-color: transparent;
    -webkit-border-radius: 0;
}
&lt;/style&gt;&lt;/p&gt;
&lt;!--#include virtual=&#34;${Base_URL}/templates/footer.html&#34; --&gt;</content></entry><entry><title>Install OCaml on Amazon Linux (EC2)</title><link href="http://psellos.com/2012/06/2012.06.ocaml-amazon-ec2.html"/><id>http://psellos.com/2012/06/2012.06.ocaml-amazon-ec2.html</id><updated>2012-06-19T11:00:00-08:00</updated><content type="html">&lt;!--#include virtual=&#34;${Base_URL}/templates/header.html&#34; --&gt;&lt;div class=&#34;date&#34;&gt;June 19, 2012&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Edited September 2, 2012&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here is a quick way to get OCaml installed on an Amazon EC2 instance
running Amazon Linux.  The problem is that you&#38;#8217;d like to use yum, the
handy package management tool.  But none of the stock repositories in
Amazon Linux contains an OCaml package.&lt;/p&gt;

&lt;div class=&#34;flowaroundimg&#34;&gt;
&lt;a href=&#34;http://psellos.com/ocaml/&#34;&gt;&lt;img src=&#34;http://psellos.com/images/powered-by-ocaml.152x58.gif&#34; alt=&#34;Powered by OCaml&#34;&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;Since Amazon Linux is compatible with CentOS 6, what I ended up doing
was installing the OCaml package from CentOS 6.2.  This gives you OCaml
3.11.2, which is perfectly fine for our current purposes.  We&#38;#8217;ve run a
few tests, and it is working for us.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: if you&#38;#8217;re not committed to using Amazon Linux, another
way to get OCaml support is to use the Ubuntu images instead.  I&#38;#8217;ve run
some tests with the 32-bit version of Ubuntu Server 12.04 LTS, and the
OCaml support seems excellent.  The repository contains OCaml 3.12.1,
which is the latest release (currently).&lt;/p&gt;

&lt;p&gt;For those who want to use OCaml on Amazon Linux, here are the steps I
used to install it.  I assume you&#38;#8217;ve got an active EC2 instance running
Amazon Linux.&lt;/p&gt;

&lt;p&gt;First, add the CentOS 6.2 repository to your yum configuration.  As
root, create a file named &lt;code&gt;/etc/yum.repos.d/centos6.repo&lt;/code&gt; with the
following contents.  The &lt;code&gt;mirrorlist&lt;/code&gt; and &lt;code&gt;gpgkey&lt;/code&gt; lines here might be
wrapped in your browser, but each is one long line (make your browser as
wide as possible to see this).&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code&gt;[centos6]&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;name=Centos 6 Base&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;mirrorlist=http://mirrorlist.centos.org/?release=6.2&#38;amp;arch=$basearch&#38;amp;repo=os&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;gpgcheck=1&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;gpgkey=http://mirror.centos.org/centos-6/6/os/$basearch/RPM-GPG-KEY-CentOS-6&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;priority=2&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;enabled=1&lt;/code&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;(&lt;strong&gt;Added note&lt;/strong&gt;: based on a comment, I changed the &lt;code&gt;gpgkey&lt;/code&gt; URL above.
The old URL had become inaccessible since I originally wrote this up.
To check the validity, you can try visiting the URL to make sure it
exists.  Replace &lt;code&gt;$basearch&lt;/code&gt; with &lt;code&gt;i386&lt;/code&gt; or &lt;code&gt;x86_64&lt;/code&gt; as appropriate.)&lt;/p&gt;

&lt;p&gt;To avoid overriding the stock packages you want to set the priority
lower than the other repositories (i.e., set it to a bigger integer).
All my other repositories are priority 1, so 2 is big enough.&lt;/p&gt;

&lt;p&gt;The use of the &lt;code&gt;basearch&lt;/code&gt; variable means that things will work for both
32- and 64-bit EC2 instances.  The lines below are taken from a 32-bit
instance (but I have tested on both).&lt;/p&gt;

&lt;p&gt;Yum should now see the CentOS OCaml package:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;&lt;code&gt;# yum list ocaml&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;code&gt;Loaded plugins: fastestmirror, priorities, security, update-motd&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;Loading mirror speeds from cached hostfile&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;* amzn-main: packages.us-west-2.amazonaws.com&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;* amzn-updates: packages.us-west-2.amazonaws.com&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;* centos6: mirrors.cat.pdx.edu&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;2125 packages excluded due to repository priority protections&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;Available Packages&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;ocaml.i686&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;3.11.2-2.el6&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;centos6&lt;/code&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can now install OCaml:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;&lt;code&gt;# yum install ocaml&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;code&gt;&#38;#160;&#38;#160;&#38;#160;&#38;#160;. . .&lt;/code&gt; &lt;br /&gt;
  &lt;strong&gt;&lt;code&gt;# ocaml&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;code&gt;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;&#38;#160;Objective Caml version 3.11.2&lt;/code&gt; &lt;br /&gt;
  &lt;code&gt;&#38;#160;&lt;/code&gt; &lt;br /&gt;
  &lt;strong&gt;&lt;code&gt;#&lt;/code&gt;&lt;/strong&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When you&#38;#8217;re done, you might want to change &lt;code&gt;enable=1&lt;/code&gt; to &lt;code&gt;enable=0&lt;/code&gt; in
your &lt;code&gt;centos6.repo&lt;/code&gt; file, to avoid placing unnecessary load on the
CentOS mirrors in the future.&lt;/p&gt;

&lt;p&gt;Please leave any corrections, questions, or comments below, or send them
to me at &lt;a href=&#34;&#38;#x6d;&#38;#x61;&#38;#x69;&#38;#108;&#38;#x74;&#38;#x6f;&#38;#x3a;j&#38;#x65;&#38;#x66;&#38;#x66;&#38;#115;&#38;#099;&#38;#x6f;&#38;#064;&#38;#112;&#38;#115;&#38;#x65;l&#38;#x6c;&#38;#x6f;s&#38;#046;&#38;#x63;&#38;#x6f;&#38;#x6d;&#34;&gt;&#38;#106;e&#38;#102;&#38;#x66;&#38;#115;&#38;#099;o&#38;#064;&#38;#112;&#38;#115;&#38;#x65;&#38;#108;l&#38;#x6f;&#38;#x73;&#38;#x2e;&#38;#x63;&#38;#111;&#38;#109;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Posted by: &lt;a href=&#34;http://psellos.com/aboutus.html#jeffreya.scofieldphd&#34;&gt;Jeffrey&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;style type=&#34;text/css&#34;&gt;
.flowaroundimg {
       float: left;
       margin: 0em 1em 0em 0em;
}
&lt;/style&gt;&lt;/p&gt;
&lt;!--#include virtual=&#34;${Base_URL}/templates/footer.html&#34; --&gt;</content></entry><entry><title>IcosaBlue 2.0, Now with Weekend Teapot!</title><link href="http://psellos.com/2012/06/2012.06.icosablue-2-teapot.html"/><id>http://psellos.com/2012/06/2012.06.icosablue-2-teapot.html</id><updated>2012-06-11T11:00:00-08:00</updated><content type="html">&lt;!--#include virtual=&#34;${Base_URL}/templates/header.html&#34; --&gt;&lt;div class=&#34;date&#34;&gt;June 11, 2012&lt;/div&gt;

&lt;p&gt;I&#38;#8217;ve rewritten &lt;a href=&#34;http://psellos.com/ocaml/example-app-icosablue.html&#34;&gt;IcosaBlue&lt;/a&gt;, an example OCaml app that shows how to use
OpenGL ES 1.1 under iOS.  It works under OS X 10.7 (Lion) and still
displays a rotating blue icosahedron.&lt;/p&gt;

&lt;div class=&#34;flowaroundimg&#34;&gt;
&lt;a href=&#34;http://psellos.com/ocaml/example-app-icosablue.html&#34;&gt;&lt;img src=&#34;http://psellos.com/images/icosablue-weekend-p3.png&#34; alt=&#34;IcosaBlue teapot on iPhone&#34;&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;However, to keep the excitement at a high level, I added a new feature
to IcosaBlue for version 2.0.  On weekdays, it still displays the
traditional rotating blue icosahedron, but on weekends it displays a
rotating blue teapot (shown in screenshot).&lt;/p&gt;

&lt;p&gt;I&#38;#8217;m now thinking about new features to add in future releases.  I&#38;#8217;d
still be interested in coding up some kind of competition for supremacy
among different polyhedra.  But the new teapot display suggests that
some other household objects might be able to compete as well.&lt;/p&gt;

&lt;p&gt;As usual, the old version of IcosaBlue is available in the &lt;a href=&#34;http://psellos.com/ocaml/ocaml-archives.html&#34;&gt;OCaml
Programming Archives&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Please leave any questions or comments below, or send them to me at
&lt;a href=&#34;&#38;#x6d;&#38;#x61;&#38;#x69;&#38;#108;&#38;#x74;&#38;#x6f;&#38;#x3a;j&#38;#x65;&#38;#x66;&#38;#x66;&#38;#115;&#38;#099;&#38;#x6f;&#38;#064;&#38;#112;&#38;#115;&#38;#x65;l&#38;#x6c;&#38;#x6f;s&#38;#046;&#38;#x63;&#38;#x6f;&#38;#x6d;&#34;&gt;&#38;#106;e&#38;#102;&#38;#x66;&#38;#115;&#38;#099;o&#38;#064;&#38;#112;&#38;#115;&#38;#x65;&#38;#108;l&#38;#x6f;&#38;#x73;&#38;#x2e;&#38;#x63;&#38;#111;&#38;#109;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Posted by: &lt;a href=&#34;http://psellos.com/aboutus.html#jeffreya.scofieldphd&#34;&gt;Jeffrey&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;style type=&#34;text/css&#34;&gt;
.flowaroundimg {
       float: left;
       margin: 0em 1em 0em 0em;
}
&lt;/style&gt;&lt;/p&gt;
&lt;!--#include virtual=&#34;${Base_URL}/templates/footer.html&#34; --&gt;</content></entry><entry><title>LablGLES Released for Lion</title><link href="http://psellos.com/2012/06/2012.06.lablgles-lion-released.html"/><id>http://psellos.com/2012/06/2012.06.lablgles-lion-released.html</id><updated>2012-06-04T11:00:00-08:00</updated><content type="html">&lt;!--#include virtual=&#34;${Base_URL}/templates/header.html&#34; --&gt;&lt;div class=&#34;date&#34;&gt;June 4, 2012&lt;/div&gt;

&lt;p&gt;I&#38;#8217;ve just updated &lt;a href=&#34;http://psellos.com/ocaml/lablgles-build.html&#34;&gt;LablGLES&lt;/a&gt;, an OCaml interface for OpenGL ES
1.1.  I use it to write iOS apps in OCaml, but it should work in almost
any OCaml environment with OpenGL ES.  I&#38;#8217;ve rewritten the instructions
to work with OS X 10.7 (Lion) and the latest Xcode (4.3.2).&lt;/p&gt;

&lt;div class=&#34;flowaroundimg&#34;&gt;
&lt;a href=&#34;http://psellos.com/ocaml/lablgles-build.html&#34;&gt;&lt;img src=&#34;http://psellos.com/images/teapot-p3.png&#34; alt=&#34;OpenGL ES teapot on iPhone&#34;&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;I also coded up a simple consistency checker that found quite a few
dangling LablGL symbols in LablGLES.  These are symbols that are defined
in OpenGL but not in OpenGL ES.  Eliminating them will allow the OCaml
compiler to catch errors in LablGLES code that were previously being
caught at runtime.&lt;/p&gt;

&lt;p&gt;LablGLES is based on LablGL, by Jacques Garrigue and others.  As an
interesting sidelight, I just now ran my consistency checker against the
base LablGL release and it seems to have found an error!  Another small
victory for static analysis.&lt;/p&gt;

&lt;p&gt;As usual, the old version of LablGLES will remain available in the
&lt;a href=&#34;http://psellos.com/ocaml/ocaml-archives.html&#34;&gt;OCaml Programming Archives&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Please leave any questions or comments below, or send them to me at
&lt;a href=&#34;&#38;#x6d;&#38;#x61;&#38;#x69;&#38;#108;&#38;#x74;&#38;#x6f;&#38;#x3a;j&#38;#x65;&#38;#x66;&#38;#x66;&#38;#115;&#38;#099;&#38;#x6f;&#38;#064;&#38;#112;&#38;#115;&#38;#x65;l&#38;#x6c;&#38;#x6f;s&#38;#046;&#38;#x63;&#38;#x6f;&#38;#x6d;&#34;&gt;&#38;#106;e&#38;#102;&#38;#x66;&#38;#115;&#38;#099;o&#38;#064;&#38;#112;&#38;#115;&#38;#x65;&#38;#108;l&#38;#x6f;&#38;#x73;&#38;#x2e;&#38;#x63;&#38;#111;&#38;#109;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Posted by: &lt;a href=&#34;http://psellos.com/aboutus.html#jeffreya.scofieldphd&#34;&gt;Jeffrey&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;style type=&#34;text/css&#34;&gt;
.flowaroundimg {
       float: left;
       margin: 0em 1em 0em 0em;
}
&lt;/style&gt;&lt;/p&gt;
&lt;!--#include virtual=&#34;${Base_URL}/templates/footer.html&#34; --&gt;</content></entry><entry><title type="html">OCaml iOS Simulator App &#38;#8220;Voronoi&#38;#8221; Updated for Lion</title><link href="http://psellos.com/2012/05/2012.05.voronoi-app-lion.html"/><id>http://psellos.com/2012/05/2012.05.voronoi-app-lion.html</id><updated>2012-05-29T11:00:00-08:00</updated><content type="html">&lt;!--#include virtual=&#34;${Base_URL}/templates/header.html&#34; --&gt;&lt;div class=&#34;date&#34;&gt;May 29, 2012&lt;/div&gt;

&lt;p&gt;I updated the OCaml iOS Simulator example app, &lt;a href=&#34;http://psellos.com/ocaml/example-app-voronoi.html&#34;&gt;Voronoi&lt;/a&gt;, to build and
run under Lion with the latest Xcode.  It lets you draw
fantastic-looking Voronoi diagrams by placing dots on the screen.  It
also shows how to run OCaml on iOS, with no need for an iOS device.
There&#38;#8217;s a binary version that you can run in the simulator just by
clicking on it.  Or you can download sources and build it yourself.&lt;/p&gt;

&lt;div class=&#34;flowaroundimg&#34;&gt;
&lt;a href=&#34;http://psellos.com/ocaml/example-app-voronoi.html&#34;&gt;&lt;img src=&#34;http://psellos.com/images/voronoi-spiral-p4.png&#34; alt=&#34;iOS Simulator running Voronoi app&#34;&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;The accompanying Voronoi screenshot shows what it looks like&#38;#8212;but
imagine that you can move the dots or add new ones while the shapes and
colors adjust hypnotically.&lt;/p&gt;

&lt;p&gt;Whenever I run this app I get excited by what I can come up with in just
a few minutes, and end up making a big gallery of screenshots.  There
are a few more in the writeup, but I have many more if anybody is
interested.  Or you could make your own screenshots and send them to me.&lt;/p&gt;

&lt;p&gt;The update makes no changes to the OCaml and ObjC code&#38;#8212;Voronoi only
uses parts of iOS that haven&#38;#8217;t changed since iOS 3.1.  However, I built
a launcher app that lets you run Voronoi in the iOS Simulator with just
a few clicks (no command line).  I also repackaged the sources so you
can build and run in the simulator under Xcode with just a few clicks.&lt;/p&gt;

&lt;p&gt;An advantage of using Xcode is that it&#38;#8217;s the supported way of running
apps in the simulator.  For those who actually like to work from the
command line (as I often do) the instructions also show how to build and
run the app that way.&lt;/p&gt;

&lt;p&gt;As always, the previous version of Voronoi is still available in the
&lt;a href=&#34;http://psellos.com/ocaml/ocaml-archives.html&#34;&gt;OCaml Programming Archives&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Posted by: &lt;a href=&#34;http://psellos.com/aboutus.html#jeffreya.scofieldphd&#34;&gt;Jeffrey&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;style type=&#34;text/css&#34;&gt;
.flowaroundimg {
       float: left;
       margin: 0em 1em 0em 0em;
}
&lt;/style&gt;&lt;/p&gt;
&lt;!--#include virtual=&#34;${Base_URL}/templates/footer.html&#34; --&gt;</content></entry><entry><title type="html">OCaml iOS App &#38;#8220;Slide24&#38;#8221; Updated for Lion</title><link href="http://psellos.com/2012/05/2012.05.slide24-app-lion.html"/><id>http://psellos.com/2012/05/2012.05.slide24-app-lion.html</id><updated>2012-05-26T11:00:00-08:00</updated><content type="html">&lt;!--#include virtual=&#34;${Base_URL}/templates/header.html&#34; --&gt;&lt;div class=&#34;date&#34;&gt;May 26, 2012&lt;/div&gt;

&lt;p&gt;I updated the OCaml iOS example app, &lt;a href=&#34;http://psellos.com/ocaml/example-app-slide24.html&#34;&gt;Slide24&lt;/a&gt;, to build under Lion
with the latest Xcode.  It lets you solve the well known 5 &#38;#215; 5 sliding
tile puzzle.  It will also solve it for you if you like, using a tiny
bit of AI.  If you&#38;#8217;re interested in running OCaml on iOS, this app shows
how to interface with GUI elements of Cocoa Touch.  You can download the
sources and build it to run on your own iOS device.&lt;/p&gt;

&lt;div class=&#34;flowaroundimg&#34; style=&#34;margin-top: 1.0em;&#34;&gt;
&lt;a href=&#34;http://psellos.com/ocaml/example-app-slide24.html&#34;&gt;&lt;img src=&#34;http://psellos.com/images/slide24-p3.png&#34; alt=&#34;iPhone running Slide24 app&#34;&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;There are no changes to the OCaml and ObjC code&#38;#8212;all the updates are in
the instructions and in the project metadata used by Xcode.  The
generated app runs on iOS 3.1 and later.&lt;/p&gt;

&lt;p&gt;There seems to be a fairly steady stream of interest in this app, maybe
because it&#38;#8217;s a classic problem for testing heuristic searches.  In fact
an expert in the field offered to help me make my heuristic work better.
(I think he could tell I don&#38;#8217;t know anything about heuristic searching,
beyond what I read in Wikipedia while coding up the app.)  I&#38;#8217;d be really
happy to improve the heuristic someday, and I&#38;#8217;ll also happily accept
patches from anybody who has already done so.&lt;/p&gt;

&lt;p&gt;As always, the previous version of Slide24 is still available in the
&lt;a href=&#34;http://psellos.com/ocaml/ocaml-archives.html&#34;&gt;OCaml Programming Archives&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Posted by: &lt;a href=&#34;http://psellos.com/aboutus.html#jeffreya.scofieldphd&#34;&gt;Jeffrey&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;style type=&#34;text/css&#34;&gt;
.flowaroundimg {
       float: left;
       margin: 0em 1em 0em 0em;
}
&lt;/style&gt;&lt;/p&gt;
&lt;!--#include virtual=&#34;${Base_URL}/templates/footer.html&#34; --&gt;</content></entry><entry><title>Wrap an iOS Simulator App as a Mac App</title><link href="http://psellos.com/2012/05/2012.05.iossim-app-as-mac-app.html"/><id>http://psellos.com/2012/05/2012.05.iossim-app-as-mac-app.html</id><updated>2012-05-25T11:00:00-08:00</updated><content type="html">&lt;!--#include virtual=&#34;${Base_URL}/templates/header.html&#34; --&gt;&lt;div class=&#34;date&#34;&gt;May 25, 2012&lt;/div&gt;

&lt;p&gt;This note shows how to whip up a full-fledged Mac app that just launches
an app in the iOS Simulator under Lion.  It&#38;#8217;s based on
&lt;a href=&#34;http://sveinbjorn.org/platypus&#34;&gt;Platypus&lt;/a&gt;, a free program that wraps up any script as a
Mac app.  The wrapped script is essentially &lt;code&gt;runsim&lt;/code&gt;, which runs an iOS
Simulator app.  See &lt;a href=&#34;http://psellos.com/2012/05/2012.05.iossim-command-line-2.html&#34;&gt;Run iOS Simulator from the Command Line
(Improved)&lt;/a&gt; for the full description of &lt;code&gt;runsim&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Until Apple releases the iOS Simulator as a standard part of OS X (which
would open up all kinds of interesting possibilities for cross-device
apps), the target audience for the generated apps is fairly small.  Only
an iOS developer is going to have the iOS Simulator readily available on
their system.  But, in fact, I often release iOS demo apps for other
developers to look at, and anyway I think it&#38;#8217;s pretty cool how easy it
is to do this with Platypus.&lt;/p&gt;

&lt;p&gt;One problem with running iOS Simulator apps automatically is that the
location of the simulator isn&#38;#8217;t the same on every system.  The simulator
is part of Xcode, which (under Lion) is an ordinary application that can
be located anywhere you like.&lt;/p&gt;

&lt;p&gt;To handle this, I use drag-and-drop: if you drop your &lt;code&gt;Xcode.app&lt;/code&gt; onto
the launcher app, it remembers the location for later.  When you open
the launcher app (double-click on it in the Finder), it uses the
remembered location of Xcode to find the simulator.  (The iOS Simulator
app is literally located inside the Xcode app.)&lt;/p&gt;

&lt;p&gt;So, the script to be wrapped by Platypus looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;case $# in
0)
    ./runsim Psi ;;
*)
    case &#34;$(basename &#34;$1&#34; | tr &#39;[:upper:]&#39; &#39;[:lower:]&#39;)&#34; in
    xcode.app) echo &#34;$1&#34; &#38;gt; runsim.xcloc ;;
    esac
    ;;
esac&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When the wrapped script runs, it can tell whether it was a drag-and-drop
target or not by the number of arguments.  If there is no argument,
nothing was dropped.  The script just uses &lt;code&gt;runsim&lt;/code&gt; to launch the
desired simulator app.  (In this example, it launches &lt;a href=&#34;http://psellos.com/2012/05/2012.05.tiny-ios-app.html&#34;&gt;Psi&lt;/a&gt;, a
tiny example iOS app.)  If there is an argument, something was dropped.
If it&#38;#8217;s named &lt;code&gt;Xcode.app&lt;/code&gt;, the script remembers its location for later.&lt;/p&gt;

&lt;p&gt;I call this script &lt;code&gt;clicksim&lt;/code&gt;.  As given here, it needs to change a
little bit depending on the iOS Simulator app you want to wrap up: you
need to specify the name of your app after &lt;code&gt;runsim&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That&#38;#8217;s really all there is to it.  Platypus handles the details of
wrapping &lt;code&gt;clicksim&lt;/code&gt;, &lt;code&gt;runsim&lt;/code&gt;, the app executable, and any other
associated files into a Mac app.&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;http://psellos.com/images/platypus.png&#34; alt=&#34;Platypus main window&#34;&gt;&lt;/img&gt;&lt;/p&gt;

&lt;p&gt;The figure above shows how to configure Platypus to wrap &lt;code&gt;clicksim&lt;/code&gt; and
&lt;code&gt;runsim&lt;/code&gt;.  The bundled files are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Psi&lt;/code&gt;&#38;#8212;the app executable&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Icon.png&lt;/code&gt;&#38;#8212;icon for the app in the simulator&lt;/li&gt;
&lt;li&gt;&lt;code&gt;runsim&lt;/code&gt;&#38;#8212;the runsim script&lt;/li&gt;
&lt;li&gt;&lt;code&gt;runsim.uuid&lt;/code&gt;&#38;#8212;UUID for the app&lt;/li&gt;
&lt;li&gt;&lt;code&gt;runsim.xcloc&lt;/code&gt;&#38;#8212;location of Xcode&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can generate a UUID using the &lt;code&gt;uuidgen&lt;/code&gt; utility.  A good initial
value for the location of Xcode is &lt;code&gt;/Applications/Xcode.app&lt;/code&gt;.  The
&lt;code&gt;runsim.xcloc&lt;/code&gt; file should be writable so that the script can change its
contents if necessary.&lt;/p&gt;

&lt;p&gt;To make the drag-and-drop facility work more nicely, you can specify the
files that will be accepted by the app.  Click the &lt;strong&gt;Settings&lt;/strong&gt; button,
and you&#38;#8217;ll see a new dialog like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;http://psellos.com/images/platypus-drop.png&#34; alt=&#34;Platypus drag-and-drop dialog&#34;&gt;&lt;/img&gt;&lt;/p&gt;

&lt;p&gt;In this example, we want to accept only files ending with &lt;code&gt;.app&lt;/code&gt;
(applications), and only folders (packages).&lt;/p&gt;

&lt;p&gt;If you want to try this example yourself, I created an archive with all the
parts you need.  First, download &lt;a href=&#34;http://sveinbjorn.org/platypus&#34;&gt;Platypus&lt;/a&gt; from its home page,
and install it.  Then download the archive:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://psellos.com/pub/ocamlxsim/psi-platy-1.0.1.zip&#34;&gt;Archive for wrapping Psi as Mac app with Platypus&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To try out the example from Finder:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Double click the zipfile, then open the generated folder.&lt;/li&gt;
&lt;li&gt;Double click on &lt;code&gt;FillProfile.app&lt;/code&gt;.  This initializes paths in
&lt;code&gt;psilauncher.platypus&lt;/code&gt; for your site.&lt;/li&gt;
&lt;li&gt;Double click on &lt;code&gt;psilauncher.platypus&lt;/code&gt;.  This brings up the Platypus
main window, as shown above.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create&lt;/strong&gt; to create the app.  Choose a convenient location
for the generated app.&lt;/li&gt;
&lt;li&gt;Double-click on the &lt;code&gt;PsiLauncher.app&lt;/code&gt; generated in step 4.  This will
start Psi in the iOS Simulator.  It will be on the second page of
apps&#38;#8212;swipe to the left to see it.&lt;/li&gt;
&lt;li&gt;If Psi doesn&#38;#8217;t show up, you may need to set the simulated iOS
version.  &lt;code&gt;runsim&lt;/code&gt; puts apps into the iOS 5.1 simulator.  Set the
version number to 5.1 with the &lt;strong&gt;Hardware -&#38;gt; Version&lt;/strong&gt; menu.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To try out the example from the command line:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;&lt;code&gt;$ unzip psi-platy-1.0.1.zip&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;strong&gt;&lt;code&gt;$ cd psi-platy-1.0.1&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;strong&gt;&lt;code&gt;$ fillprofile&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;strong&gt;&lt;code&gt;$ platypus -P psilauncher.platypus PsiLauncher.app&lt;/code&gt;&lt;/strong&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To run &lt;code&gt;PsiLauncher.app&lt;/code&gt;, you can double-click on it, or you can run it
from the command line:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;&lt;code&gt;$ open PsiLauncher.app&lt;/code&gt;&lt;/strong&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As above, you may need to set the simulated iOS version to 5.1 for Psi
to show up.&lt;/p&gt;

&lt;p&gt;If you have any comments, corrections, or suggestions, leave them below
or email me at &lt;a href=&#34;&#38;#x6d;&#38;#x61;&#38;#x69;&#38;#108;&#38;#x74;&#38;#x6f;&#38;#x3a;j&#38;#x65;&#38;#x66;&#38;#x66;&#38;#115;&#38;#099;&#38;#x6f;&#38;#064;&#38;#112;&#38;#115;&#38;#x65;l&#38;#x6c;&#38;#x6f;s&#38;#046;&#38;#x63;&#38;#x6f;&#38;#x6d;&#34;&gt;&#38;#106;e&#38;#102;&#38;#x66;&#38;#115;&#38;#099;o&#38;#064;&#38;#112;&#38;#115;&#38;#x65;&#38;#108;l&#38;#x6f;&#38;#x73;&#38;#x2e;&#38;#x63;&#38;#111;&#38;#109;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Posted by: &lt;a href=&#34;http://psellos.com/aboutus.html#jeffreya.scofieldphd&#34;&gt;Jeffrey&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;style type=&#34;text/css&#34;&gt;
.flowaroundimg {
       float: left;
       margin: 0em 1em 0em 0em;
}
pre {
    white-space: pre-wrap;
    width: 96%;
    margin-bottom: 24px;
    overflow: hidden;
    padding: 3px 10px;
    -webkit-border-radius: 3px;
    background-color: #fed;
    border: 1px solid #dcb;
}
pre code {
    white-space: pre-wrap;
    border: none;
    padding: 0;
    background-color: transparent;
    -webkit-border-radius: 0;
}
&lt;/style&gt;&lt;/p&gt;
&lt;!--#include virtual=&#34;${Base_URL}/templates/footer.html&#34; --&gt;</content></entry><entry><title>Tiny iOS App in One Source File</title><link href="http://psellos.com/2012/05/2012.05.tiny-ios-app.html"/><id>http://psellos.com/2012/05/2012.05.tiny-ios-app.html</id><updated>2012-05-22T11:00:00-08:00</updated><content type="html">&lt;!--#include virtual=&#34;${Base_URL}/templates/header.html&#34; --&gt;&lt;div class=&#34;date&#34;&gt;May 22, 2012&lt;/div&gt;

&lt;p&gt;Psi is a tiny, but complete, iOS test app in one source file, around 40
lines of Objective C.  It&#38;#8217;s nothing fancy, it just draws a Greek psi
character on the screen.  But I thought it might be useful to other
folks.  Sometimes it&#38;#8217;s just nice to have a little example.&lt;/p&gt;

&lt;div class=&#34;flowaroundimg&#34; style=&#34;margin-top: 1.0em;&#34;&gt;
&lt;a href=&#34;http://psellos.com/ocaml/&#34;&gt;&lt;img src=&#34;http://psellos.com/images/psi-p2.png&#34; alt=&#34;Psi example app&#34;&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;Psi can be very simple because it&#38;#8217;s targeted at iOS 5, when Apple
generalized the startup process to add storyboard support.  A side
effect is that it&#38;#8217;s now possible to have no startup file (nib or
storyboard file) at all.  Psi shows how this can work.  You can find a
more detailed description of the iOS app launch sequence in a &lt;a href=&#34;http://oleb.net/blog/2012/02/app-launch-sequence-ios-revisited/&#34;&gt;blog post
by Ole Begemann&lt;/a&gt;, which is where I got the idea.&lt;/p&gt;

&lt;div style=&#34;clear: both&#34;&gt;&lt;/div&gt;

&lt;p&gt;You can download the binary of Psi and run it directly in the iOS
Simulator:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://psellos.com/pub/psi/psi-simapp-1.0.0.zip&#34;&gt;Psi Tiny iOS App Binary for iOS Simulator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To try out this version, unzip and double click on the launcher app
&lt;code&gt;PsiLauncher.app&lt;/code&gt;.  You need to have Xcode and the iOS 5.0 Simulator
installed for this to work.  Psi appears on the second screen of
apps&#38;#8212;swipe to the left to see it.  If it&#38;#8217;s not there, you might need to
change the version number to 5.1 in the &lt;strong&gt;Hardware -&#38;gt; Version&lt;/strong&gt; menu.&lt;/p&gt;

&lt;p&gt;Psi is so exceptionally simple that it&#38;#8217;s really not very interesting to
run&#38;#8212;the figure above shows everything there is to see.  However, it
might be interesting to see how I packaged up an OS X app to run Psi in
the simulator.&lt;/p&gt;

&lt;p&gt;You can also download the sources and an Xcode project for building and
running in the iOS Simulator or on an iOS device:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://psellos.com/pub/psi/psi-1.0.0.zip&#34;&gt;Psi Tiny iOS App Sources and Xcode project&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To try out this version, unzip and double click on the Xcode project,
&lt;code&gt;Psi.xcodeproj&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can also build and run from the command line using the &lt;code&gt;runsim&lt;/code&gt;
script if you are so inclined.  After unzipping the sources, here&#38;#8217;s what
you need to do:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;&lt;code&gt;$ cd psi-1.0.0&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;strong&gt;&lt;code&gt;$ make -f Makefile.iossim Psi&lt;/code&gt;&lt;/strong&gt; &lt;br /&gt;
  &lt;strong&gt;&lt;code&gt;$ runsim Psi&lt;/code&gt;&lt;/strong&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If Psi doesn&#38;#8217;t show up, set the simulated iOS version number of the iOS
Simulator to 5.1 with the &lt;strong&gt;Hardware -&#38;gt; Version&lt;/strong&gt; menu.  &lt;code&gt;runsim&lt;/code&gt; places
apps into the iOS 5.1 simulator.&lt;/p&gt;

&lt;p&gt;For more about the &lt;code&gt;runsim&lt;/code&gt; script, see &lt;a href=&#34;http://psellos.com/2012/05/2012.05.iossim-command-line-2.html&#34;&gt;Run iOS Simulator from the
Command Line (Improved)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Finally, here is the full source of Psi.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/* psi.m     Tiny iOS App in one file
 *
 * (It just draws a Greek letter Psi.)
 *
 * Copyright (c) 2012 Psellos   http://psellos.com/
 * Licensed under the MIT License:
 *     http://www.opensource.org/licenses/mit-license.php
 */
#import &#38;lt;UIKit/UIKit.h&#38;gt;

@interface AppDelegate : NSObject &#38;lt;UIApplicationDelegate&#38;gt; {
}
@end

@implementation AppDelegate : NSObject
- (BOOL) application: (UIApplication *) anAppl
                didFinishLaunchingWithOptions: (NSDictionary *) opts
{
    UIViewController *vc = [[UIViewController alloc] init];
    UIWindow *w =
        [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]];
    UILabel *l = [[UILabel alloc] initWithFrame: [w bounds]];
    l.font = [UIFont fontWithName: @&#34;MarkerFelt-Thin&#34; size: 300.0];
    l.text = [NSString stringWithUTF8String: &#34;\xce\xa8&#34;];
    l.textColor =
        [UIColor colorWithRed: 0.141 green: 0.251 blue: 0.439 alpha: 1.0];
    l.textAlignment = UITextAlignmentCenter;
    l.backgroundColor =
        [UIColor colorWithRed: 0.800 green: 0.333 blue: 0.000 alpha: 1.0];
    vc.view = l;
    w.rootViewController = vc;
    [w makeKeyAndVisible];
    return YES;
}
@end

int main(int argc, char *argv[])
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    int retVal = UIApplicationMain(argc, argv, nil, @&#34;AppDelegate&#34;);
    [pool release];
    return retVal;
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you have any comments, corrections, or suggestions, leave them below
or email me at &lt;a href=&#34;&#38;#x6d;&#38;#x61;&#38;#x69;&#38;#108;&#38;#x74;&#38;#x6f;&#38;#x3a;j&#38;#x65;&#38;#x66;&#38;#x66;&#38;#115;&#38;#099;&#38;#x6f;&#38;#064;&#38;#112;&#38;#115;&#38;#x65;l&#38;#x6c;&#38;#x6f;s&#38;#046;&#38;#x63;&#38;#x6f;&#38;#x6d;&#34;&gt;&#38;#106;e&#38;#102;&#38;#x66;&#38;#115;&#38;#099;o&#38;#064;&#38;#112;&#38;#115;&#38;#x65;&#38;#108;l&#38;#x6f;&#38;#x73;&#38;#x2e;&#38;#x63;&#38;#111;&#38;#109;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Posted by: &lt;a href=&#34;http://psellos.com/aboutus.html#jeffreya.scofieldphd&#34;&gt;Jeffrey&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;style type=&#34;text/css&#34;&gt;
.flowaroundimg {
       float: left;
       margin: 0em 1em 0em 0em;
}
pre {
    white-space: pre-wrap;
    width: 96%;
    margin-bottom: 24px;
    overflow: hidden;
    padding: 3px 10px;
    -webkit-border-radius: 3px;
    background-color: #fed;
    border: 1px solid #dcb;
}
/*
code {
    white-space: nowrap;
    font-size: 1.1em;
    padding: 2px;
    -webkit-border-radius: 3px;
    background-color: #fed;
    border: 1px solid #dcb;
}
*/
pre code {
    white-space: pre-wrap;
    border: none;
    padding: 0;
    background-color: transparent;
    -webkit-border-radius: 0;
}
&lt;/style&gt;&lt;/p&gt;
&lt;!--#include virtual=&#34;${Base_URL}/templates/footer.html&#34; --&gt;</content></entry><entry><title>Run iOS Simulator from the Command Line (Improved)</title><link href="http://psellos.com/2012/05/2012.05.iossim-command-line-2.html"/><id>http://psellos.com/2012/05/2012.05.iossim-command-line-2.html</id><updated>2012-05-19T11:00:00-08:00</updated><content type="html">&lt;!--#include virtual=&#34;${Base_URL}/templates/header.html&#34; --&gt;&lt;div class=&#34;date&#34;&gt;May 19, 2012&lt;/div&gt;

&lt;p&gt;I like to run apps in the iOS Simulator from outside Xcode&#38;#8212;it&#38;#8217;s simpler
and faster a lot of the time. So, I wrote a shell script named &lt;code&gt;runsim&lt;/code&gt;
that installs an app in the simulator&#38;#8217;s file system and then asks the
simulator to start up. In version 1.0 of &lt;code&gt;runsim&lt;/code&gt;, you had to start the
app yourself by clicking on its icon.&lt;/p&gt;

&lt;p&gt;I&#38;#8217;ve just finished work on version 2.0 of &lt;code&gt;runsim&lt;/code&gt;. I added the ability
to start apps in the simulator automatically from the command line. I
also separated out the different functions, so you can install,
uninstall, list, and run apps as separate operations.&lt;/p&gt;

&lt;div class=&#34;flowaroundimg&#34; style=&#34;margin-top: 1.0em;&#34;&gt;
&lt;a href=&#34;http://psellos.com/ios/iossim-command-line.html&#34;&gt;&lt;img src=&#34;http://psellos.com/images/psi-in-sim.png&#34; alt=&#34;Lion desktop with Psi example app in iOS Simulator&#34;&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;I use &lt;code&gt;runsim&lt;/code&gt; to demonstrate OCaml iOS Simulator apps built with
&lt;a href=&#34;http://psellos.com/ocaml/compile-to-iossim.html&#34;&gt;OCamlXSim&lt;/a&gt;, but it should be useful to
anybody who occasionally enjoys a &lt;em&gt;dis&lt;/em&gt;integrated development
environment like I do.&lt;/p&gt;

&lt;p&gt;You can read the full details on &lt;a href=&#34;http://psellos.com/ios/iossim-command-line.html&#34;&gt;Run iOS Simulator from the Command
Line&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can also download &lt;code&gt;runsim&lt;/code&gt; from the following link:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://psellos.com/pub/ocamlxsim/runsim&#34;&gt;runsim &#38;#8212; run app in iOS Simulator from command line&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before using it, however, I suggest you read the full description linked
above. There are some complexities in using the automatic start-up
facility that you want to understand beforehand.&lt;/p&gt;

&lt;p&gt;If you have any comments, corrections, or suggestions, leave them below
or email me at &lt;a href=&#34;&#38;#x6d;&#38;#x61;&#38;#x69;&#38;#108;&#38;#x74;&#38;#x6f;&#38;#x3a;j&#38;#x65;&#38;#x66;&#38;#x66;&#38;#115;&#38;#099;&#38;#x6f;&#38;#064;&#38;#112;&#38;#115;&#38;#x65;l&#38;#x6c;&#38;#x6f;s&#38;#046;&#38;#x63;&#38;#x6f;&#38;#x6d;&#34;&gt;&#38;#106;e&#38;#102;&#38;#x66;&#38;#115;&#38;#099;o&#38;#064;&#38;#112;&#38;#115;&#38;#x65;&#38;#108;l&#38;#x6f;&#38;#x73;&#38;#x2e;&#38;#x63;&#38;#111;&#38;#109;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Posted by: &lt;a href=&#34;http://psellos.com/aboutus.html#jeffreya.scofieldphd&#34;&gt;Jeffrey&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;style type=&#34;text/css&#34;&gt;
.flowaroundimg {
       float: left;
       margin: 0em 1em 0em 0em;
}
pre {
    white-space: pre-wrap;
    width: 96%;
    margin-bottom: 24px;
    overflow: hidden;
    padding: 3px 10px;
    -webkit-border-radius: 3px;
    background-color: #fed;
    border: 1px solid #dcb;
}
pre code {
    white-space: pre-wrap;
    border: none;
    padding: 0;
    background-color: transparent;
    -webkit-border-radius: 0;
}
&lt;/style&gt;&lt;/p&gt;
&lt;!--#include virtual=&#34;${Base_URL}/templates/footer.html&#34; --&gt;</content></entry><entry><title type="html">OCaml iOS Simulator App &#38;#8220;Gamut&#38;#8221; Updated for Lion</title><link href="http://psellos.com/2012/05/2012.05.gamut-app-lion.html"/><id>http://psellos.com/2012/05/2012.05.gamut-app-lion.html</id><updated>2012-05-14T11:00:00-08:00</updated><content type="html">&lt;!--#include virtual=&#34;${Base_URL}/templates/header.html&#34; --&gt;&lt;div class=&#34;date&#34;&gt;May 14, 2012&lt;/div&gt;

&lt;p&gt;I updated the basic OCaml iOS Simulator example app, &lt;a href=&#34;http://psellos.com/ocaml/example-app-gamut.html&#34;&gt;Gamut&lt;/a&gt;, to build
under Lion with the latest Xcode.  If you&#38;#8217;re interested in running OCaml
on iOS, building this app and running it in the iOS Simulator is an easy
way to get started.  There&#38;#8217;s also a binary version that you can run in the
simulator just by clicking on it.&lt;/p&gt;

&lt;div class=&#34;flowaroundimg&#34; style=&#34;margin-top: 1.0em;&#34;&gt;
&lt;a href=&#34;http://psellos.com/ocaml/example-app-gamut.html&#34;&gt;&lt;img src=&#34;http://psellos.com/images/gamut-burnt-orange.png&#34; alt=&#34;iPhone running Gamut app&#34;&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;Gamut is a simple app that shows an animation with colors that change as
you touch the screen.  The accompanying screenshot shows what it looks
like&#38;#8212;but imagine that the colors are changing hypnotically.&lt;/p&gt;

&lt;p&gt;The update makes no changes to the OCaml and ObjC code&#38;#8212;Gamut only uses
parts of iOS that haven&#38;#8217;t changed since iOS 3.1.  However, I spent some
time making it easier to try out the app.  I built a launcher app that
lets you run Gamut in the iOS Simulator with just a few clicks (no command
line).  I also repackaged the sources so you can build and run in the
simulator under Xcode with just a few clicks.&lt;/p&gt;

&lt;p&gt;An advantage of using Xcode is that it&#38;#8217;s the supported way of running apps
in the simulator.  For those who actually like to work from the command
line (as I often do) the instructions also show how to build and run the
app that way.&lt;/p&gt;

&lt;p&gt;Internally, the launcher app uses the &lt;code&gt;runsim&lt;/code&gt; script that I described in
a recent blog post &lt;a href=&#34;http://psellos.com/2012/05/2012.05.iossim-command-line.html&#34;&gt;Run iOS Simulator from the Command Line&lt;/a&gt;.
I used &lt;a href=&#34;http://sveinbjorn.org/platypus&#34;&gt;Platypus&lt;/a&gt; (a really nice free Mac app) to transform
&lt;code&gt;runsim&lt;/code&gt; into a Mac app.  In a day or two I&#38;#8217;ll write up a small
description of how to do this.&lt;/p&gt;

&lt;p&gt;As always, the previous version of Gamut is still available in the
&lt;a href=&#34;http://psellos.com/ocaml/ocaml-archives.html&#34;&gt;OCaml Programming Archives&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Posted by: &lt;a href=&#34;http://psellos.com/aboutus.html#jeffreya.scofieldphd&#34;&gt;Jeffrey&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;style type=&#34;text/css&#34;&gt;
.flowaroundimg {
       float: left;
       margin: 0em 1em 0em 0em;
}
&lt;/style&gt;&lt;/p&gt;
&lt;!--#include virtual=&#34;${Base_URL}/templates/footer.html&#34; --&gt;</content></entry><entry><title type="html">OCaml iOS App &#38;#8220;Portland&#38;#8221; Updated for Lion</title><link href="http://psellos.com/2012/05/2012.05.portland-app-lion.html"/><id>http://psellos.com/2012/05/2012.05.portland-app-lion.html</id><updated>2012-05-09T11:00:00-08:00</updated><content type="html">&lt;!--#include virtual=&#34;${Base_URL}/templates/header.html&#34; --&gt;&lt;div class=&#34;date&#34;&gt;May 9, 2012&lt;/div&gt;

&lt;p&gt;I updated the basic OCaml iOS example app, &lt;a href=&#34;http://psellos.com/ocaml/example-app-portland.html&#34;&gt;Portland&lt;/a&gt;, to build under
Lion with the latest Xcode.  It&#38;#8217;s a very simple app that just tells you
which way you&#38;#8217;re holding the phone, as in the accompanying screenshot.
If you want to try running OCaml on iOS, building this app and running
it on your phone might be a good way to get started.&lt;/p&gt;

&lt;div class=&#34;flowaroundimg&#34; style=&#34;margin-top: 1.0em;&#34;&gt;
&lt;a href=&#34;http://psellos.com/ocaml/example-app-portland.html&#34;&gt;&lt;img src=&#34;http://psellos.com/images/portland-upside-p3.png&#34; alt=&#34;iPhone running Portland app&#34;&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;There are no changes to the OCaml and ObjC code&#38;#8212;all the updates are in
the instructions and in the project metadata used by Xcode.  The
generated app runs on iOS 3.1 and later.  It would be an interesting
exercise to rewrite the app to target a more recent iOS version.  I
tried a few variations myself, but in the end I decided to target as
many devices as possible.&lt;/p&gt;

&lt;p&gt;As always, the previous version of Portland is still available in the
&lt;a href=&#34;http://psellos.com/ocaml/ocaml-archives.html&#34;&gt;OCaml Programming Archives&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Posted by: &lt;a href=&#34;http://psellos.com/aboutus.html#jeffreya.scofieldphd&#34;&gt;Jeffrey&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;style type=&#34;text/css&#34;&gt;
.flowaroundimg {
       float: left;
       margin: 0em 1em 0em 0em;
}
&lt;/style&gt;&lt;/p&gt;
&lt;!--#include virtual=&#34;${Base_URL}/templates/footer.html&#34; --&gt;</content></entry></feed>