Tue Mar 31 11:13:36 CEST 2009


The assembler contains two things:
    - static description of I/O
    - a 2-way function (equation) relating bit vector to parsed bit vector

Let's look at typed assembler languages and see what the basic ideas
are.  Some form of annotation is required..

box> (instruction-set-tx #f #f #'((addwf (f d a) "0010 01da ffff ffff")))
      (lambda (f d a)
         (ignore-overflow f 8 (ignore-overflow a 1 (ignore-overflow d 1 9)))))
      '(addwf (f d a) ((9 . 6) (d . 1) (a . 1) (f . 8)))))
     (lambda (opcode)
          `(,opcode ())
          (dasm-step 'f 8)
          (dasm-step 'a 1)
          (dasm-step 'd 1)))
        ((d a f) (list 'addwf f d a)))))))

This produces both an assembler and a disassembler.  For static
analysis however, these functions are better turned into
interpretation steps mapping between binary and struct:asm

Probably best to start from scratch since the current code is a bit

So, basic idea: the assembler description is where machine and
compiler meet.  This should eventually be linked to a machine
simulator for verification.

;; Eventually the assembler should include a complete model of the
;; machine's execution engine, which combined with a memory model
;; (including memory mapped io devices) can fully simulate code.

;; The primary relation we're interested in now is the equivalence
;; relation BI <-> SI for asm/dasm.

;; BI = binary instruction
;; SI = symbolic instruction
;;  I = instruction (modulo equivalence, represented by SI)

;; asm  : SI -> BI
;; dasm : BI -> SI
;; sim  : SI -> machine -> machine

To get to know typed scheme I'm trying to express the representation
of the assemblers as ts types.

(define-struct: Bitfield ([value : Number] [width : Number]))
(define-struct: SI ([asm : Assembler] [dasm : Disassembler]))

(define-type-alias Disassembler (Bitfield -> (Listof Bitfield)))
(define-type-alias Assembler    ((Listof Bitfield) -> Bitfield))

Now, what should addwf be?

It needs to be an instance of a type since it will be used as part of
pattern based tree-transformation.

(define-struct: addwf ...)

But each instance of such a struct will be linked to an assembler and
disassembler function that map between this struct and Bitfields.  So
"addwf" is not just a type.

(define-struct: addwf ())
(: addwf-asm  (addwf -> Bitfield))
(: addwf-dasm (Bitfield -> addwf))

  Note: Writing in a typed language it strikes me that in an
        dynamically typed language you get polymorphy for free: types
        are predicate functions.

(define-struct: addwf ([f : (-> Bitfield)] [d : (-> Bitfield)] [a : (-> Bitfield)]))
(: addwf-asm  (addwf -> Bitfield))
(: addwf-dasm (Bitfield -> addwf))

The types of addwf's arguments are thunks.  The important thing to
note here is that they can't be numbers, since they might depend on
addresses.  This cyclic dependency is resolved later in the relaxation
algorithm, where the thunks are re-evaluated.

So, it might be best to include this in the typing too: a bitfield
contains something that depends on a dictionary.

Next: parameterize opcode (for classes of opcodes with same operands).
This is where the simulator needs to be plugged in too.

I.e. for  (addwf f d a)  we need:

     - a class (fda f d a)
     - behaviour in 2 stages: assembly and simulation

simulation is necessary for partial evaluation. (which then needs 2
separate semantics: bit-true and extended types.

  Note: this is starting to make sense.. requiring types for all this
        requires me to think harder about dependencies.  looks like
        figuring out this type system is the next stage for Staapl.  i
        really needed to do this once to know what to write down now..

 * make current implementation of addwf correct
 * add classes + 2-stage behaviour