[Openmcl-devel] ARM immediates, subprims and NIL

James Bielman jamesjb at jamesjb.com
Sun Jul 10 18:29:34 PDT 2005


I've made a fair bit of progress on the LAP assembler for my OpenMCL
ARM port.  Now that I've started messing around with it a bit, I've
got some more architectural problems to solve.

The format of immediates in ARM data processing instructions is rather
weird.  Instead of an N-bit integer, an immediate is encoded as an
8-bit integer rotated right by an even number of bits.

So, the following immediates are legal (using ARM LAP syntax):

    (mov imm0 #xff)          ; #xff rotated right 0 bits
    (mov imm0 #x2000)        ; #x80 rotated right 6 bits
    (mov imm0 #xf000000f)    ; #xff rotated right 28 bits

but these arent:

    (mov imm0 #x101)
    (mov arg_z #x2015)
    (mov pc #x5000)

So, assuming I want to be able to load NIL into a register in a single
instruction (which seems like a good goal), I'll need to shuffle
things around a bit.

Furthermore, Windows CE helpfully declares the first 64k of memory as
off-limits, so this wouldn't work there anyway.

I'm thinking that nil will need to go in a register, since even if I
move nil to a location representable as a rotated immediate,
nil-relative objects probably won't be.  I'm not sure which register
to give up for this.

So that leaves me with:

   (mov arg_z rnil)               ; return nil
   (add arg_z rnil t_offset)      ; return t

(This is also a problem for loading immediate fixnums.  I've read it
can take up to three instructions to load an arbitrary 32-bit constant
using arithmetic instructions.  Maybe fixnums that can't be
represented as immediates can go in the function's constant vector
like other constant objects?  ARM assemblers do something similar with
"literal pools".  Perhaps in the future I could do something fancier
when optimize speed > optimize size or something...)

There is a similar problem with subprimitives.  ARM doesn't have a
branch absolute instruction, but you can use PC as a destination
register in data processing instructions.

Because of the immediate representation, I can't do:

   (mov lr pc)
   (mov pc #x50bc)   ; this would have to be >#xffff on wince

I'm not sure what the best way to solve this is yet.  Could I move the
subprimitive jump table relative to nil as well?  If this worked, a
subprim call could look something like:

   (mov lr pc)
   (add pc rnil .SPwhatever-offset)
   ;; or maybe even (ldr pc (rnil .SPwhatever-offset))

There's probably some sneakier, better way to do this...


More information about the Openmcl-devel mailing list