On this page:
define-isa
1.1 ISA Structs
isa0
add-isa-opcode!
opcarg
opcarg-bitw
opcode
ent0
ent0-bits
1.1.1 Phase 1 ISA Structs
isa1
isa
ent1
entity
not-entity
1.2 ISA Opcode
define-opcode
allow-private-opcodes
1.3 Entities Encoding
define-entity
allow-raw-entities
1.4 ISA Decoder Tree
optn
optl
opterr
optree
build-optree
print-optree
match-optree-opcode
optu
optu-bits
analyze-optree
analyze-optree-depth
1.5 ISA Syntaxes
define-n-bit-stx-class
letter
maybe-id
1.6 ISA Utilities
isa-evaluator
print-isa-tree
isa-disassembler
isa-analyze-unused
isa-analyze-depth
1.7 Opcode Emitter
opcode-emitter
1.8 Opcode Visualizer
opcode-mask-pict
ompict-colors
ompict-order
9.2

1 Instruction Set Architecture🔗

 (require ledum/define/isa) package: ledum-definers

This module allows for defining custom ISA. It provides syntax forms for extending the ISA and facilities for encoding, decoding and evaluating the ISA in both source and binary forms.

Reexports isa0 struct from ledum/define/isa/struct0.

syntax

(define-isa maybe-option isa)

 
maybe-option = 
  | #:bits bits maybe-option
  | #:signeds (sl ...) maybe-option
  | #:doc (doc ...) maybe-option
     
sl = letter
 
  isa : identifier?
  bits : exact-exact-positive-integer?
Creates a new ISA and defines its opcode definer and its word syntax class. Default bits is 16.

The list of #:signeds is used to determine which opcode bitmask letters represent signed immediate value.

syntax

(define-isa-opcode maybe-private (name args maybe-order)
  maybe-doc
  body ...)
 
maybe-private = 
  | #:private
     
name = identifier?
     
args = bits-wide bitmask
     
maybe-order = 
  | #:order arg ...
     
maybe-doc = 
  | #:doc (doc ...)
Defines a new opcode for given ISA using define-opcode.

Adds the new opcode to given isa.

The body ... expressions should be the behavioral description used for emulation.

syntax class

isa-word

A bits-bits integer which can be used in macro instruction specification patterns.

syntax

(define-isa-entity ex ...)

Expands to (define-entity isa ex ...). See define-entity for more information.

syntax

(define-isa-next ex ...)

Specifies a procedure for fetching the next instruction on this ISA.

1.1 ISA Structs🔗

 (require ledum/define/isa/struct0) package: ledum-definers

This module contains the structs required by ISA specification which do not pull in unnecessary dependencies.

struct

(struct isa0 (opcodes tree))

  opcodes : (listof opcode?)
  tree : optree?
A struct representing the defined ISA. This contains runtime information that can be used by disassembler and/or emulator. The tree is a cached version and if opcodes are updated (typically by extending them with new instructions), the tree gets invalidated and rebuilt upon next usage.

procedure

(add-isa-opcode! isa opc)  void?

  isa : isa0?
  opc : opcode?
Adds a new opcode opc to given ISA isa.

struct

(struct opcarg (id bits))

  id : symbol?
  bits : (listof exact-nonnegative-integer?)
Represents single opcode argument. The id is the letter from the opcode bitmask and the bits list is the list of bit indices starting at 0.

procedure

(opcarg-bitw oa)  exact-positive-integer?

  oa : opcarg?
Returns the length of the bits field of given oa.

struct

(struct opcode (name mask value eval enc args bitw dec))

  name : symbol?
  mask : exact-nonnegative-integer?
  value : nonegative-integer?
  eval : (-> exact-nonnegative-integer? void?)
  enc : procedure?
  args : (listof opcarg?)
  bitw : exact-positive-integer?
  dec : (-> exact-nonnegative-integer? list?)
This struct is returned by the transformer binding created by define-opcode if used as stand-alone identifier. It is further used by assembler, disassembler and evaluator.

struct

(struct ent0 (ids chars nums ctr))

  ids : (listof symbol?)
  chars : (listof symbol?)
  nums : (listof exact-nonnegative-integer?)
  ctr : (-> any/c boolean?)
Used for storing runtime information about entity definition.

procedure

(ent0-bits e)  exact-positive-integer?

  e : ent0?
Returns the number of bits required to encode given entity e. Always rounds up.

1.1.1 Phase 1 ISA Structs🔗

 (require ledum/define/isa/struct1) package: ledum-definers

These structures are used during expansion.

struct

(struct isa1 (trans entmap signs))

  trans : procedure?
  entmap : hash?
  signs : (listof symbol?)
Represents the ISA during expansion phase. The trans procedure is a transformer used when the binding is used as an identifier binding to retrieve the appropriate isa0? struct.

The entmap entities map contains mapping of letters to particular syntax class. And the signs list contains all the letter symbols used in opcode masks as signed immediates.

syntax class

isa

A syntax class matching identifiers bound to isa1 transformer binding.

struct

(struct ent1 (num cls))

  num : exact-nonnegative-integer?
  cls : symbol?
Represents a single entity during expansion phase. The cls field determines which entity class this entity belongs to and the num represents the binary representation of the particular entity in question.

syntax class

entity

This syntax class matches identifiers bound to ent1 transformer binding.

syntax class

not-entity

This syntax class matches anything that is not any kind of entity.

1.2 ISA Opcode🔗

 (require ledum/define/isa/opcode) package: ledum-definers

syntax

(define-opcode maybe-private isa #:bitw bitw
  (name args maybe-order)
  maybe-doc
  body ...)
 
maybe-private = 
  | #:private
     
args = bit-width-wide bitmask
     
maybe-order = 
  | #:order arg ...
     
maybe-doc = 
  | #:doc (doc ...)
 
  name : identifier?
This syntax is intended to be used internally by define-isa-opcode. The interface is should never be used directly.

Defines a new opcode.

Opcodes defined as #:private can only be used in macro opcode specification - see define-macro-opcode for more information.

The bitmask is an identifier? starting with the : character and having exactly bit-width significant characters. Significant characters are the digits 0 and 1 and any lower-case or upper-case ASCII characters a-z.

In addition to significant characters, spacing characters _ and - can be used to logically group the bits into clearer structure.

The digits specify the opcode mask and value.

The letters specify arguments of the opcode. All bits of the same letter are interpreted as n-bit value with all the bits put together in the same order but without gaps. A binding for each individual letter is created which can be used in the opcode body as normal procedure argument.

Inside the body expressions allow-private-opcodes and allow-raw-entities are enabled.

When the order of the arguments in assembler syntax is to be different than the order of appearance of given argument in the mask, an explicit ordering can be specified with the #:order keyword. In such case all the arguments positions must be explicitly specified.

A default documentation for the assembler syntax form is generated. Any prose text can be added to it with the #:doc keyword. This is especially useful coupled with the at-exp meta-language.

Take the following example code:

(define-isa-opcode (ldl :0001-rrrr-iiii-iiii)
  #:doc @{Load an 8-bit constant @racket[i] into the
          register @racket[r], clearing its higher 8 bits.}
  (displayln `(ldl ,r ,i)))

It produces the documentation as follows:

opcode

(ldl r i)

 
  r : (integer-in 0 15)
  i : (integer-in 0 255)
Load an 8-bit constant i into the register r, clearing its higher 8 bits.

syntax parameter

allow-private-opcodes

When set to #t the opcodes defined with #:private are allowed. They are a expansion error otherwise.

1.3 Entities Encoding🔗

 (require ledum/define/isa/entity) package: ledum-definers

This module adds support for encoded entities like registers or flag groups.

syntax

(define-entity isa cls (eid ...) (l ...) maybe-doc)

 
cls = identifier?
     
eid = identifier?
     
l = letter
     
maybe-doc = 
  | #:doc (doc ...)
 
  isa : isa0?
Defines a new entity cls for given isa. Creates a new syntax class cls which matches only all bindings created by eid ....

The letters l ... are injected into the isa and associated with the generated syntax class.

syntax parameter

allow-raw-entities

When #t any entity syntax class accepts raw numeric values as well. Set in define-macro-opcode to allow free transformations in macro opcodes.

1.4 ISA Decoder Tree🔗

 (require ledum/define/isa/optree) package: ledum-definers

Binary tree for efficient decoding of given ISA. Used both by the disassembler and emulator.

struct

(struct optn (bit left right))

  bit : exact-nonnegative-integer?
  left : (or/c #f optn? optl? opterr?)
  right : (or/c #f optn? optl? opterr?)
Opcode tree node splitting at given bit. The left branch represents 0 and the right branch represents 1 values respectively.

struct

(struct optl (opcode unused bitw))

  opcode : opcode?
  unused : exact-nonnegative-integer?
  bitw : exact-positive-integer?
A leaf node of binary search tree of opcodes containing a single opcode and unused space information. The bitw field is there only for convenience when printing the struct.

struct

(struct opterr (opl)
    #:extra-constructor-name make-opterr)
  opl : (listof opcode?)
A special opcode tree leaf node representing error branch with a list of multiple ambiguous opcodes.

struct

(struct optree (root bitw))

  root : (or/c optn? optl? opterr?)
  bitw : exact-positive-integer?
A compiled binary search tree for all opcodes of given ISA.

procedure

(build-optree opl)  optree?

  opl : (listof opcode?)
Builds an opcode tree from given list of opcodes.

procedure

(print-optree opt)  void?

  opt : optree?
Prints the opcode tree highlighting collisions if there are any.

procedure

(match-optree-opcode opt num)  opcode?

  opt : optree?
  num : exact-nonnegative-integer?
Matches given encoded opcode.

struct

(struct optu (mask value umask bitw))

  mask : exact-nonnegative-integer?
  value : exact-nonnegative-integer?
  umask : exact-nonnegative-integer?
  bitw : exact-positive-integer?
Represents unused opcode tree space.

procedure

(optu-bits ou)  exact-nonnegative-integer?

  ou : optu?
Returns the actual number of unused bits in given unused opcode space.

procedure

(analyze-optree opt)  (listof optu?)

  opt : optree?
Performs unused opcode space analysis for given opt tree and returns a list of unused opcode space structs.

Returns a list of unused bit masks which were not used to recognize any particular opcode in the current opcode tree of given is. The actual number of unused bits cannot be directly used for determining the number of unused opcodes as one of those bits must be used to distinguish some existing opcode tree leaf. Therefore the number of free opcodes is always 2^{n-1} where n is the number of unused bits reported by this procedure.

procedure

(analyze-optree-depth opt)

  (listof exact-nonnegative-integer?)
  opt : optree?
Returns a list of depths of all leaves.

1.5 ISA Syntaxes🔗

 (require ledum/define/isa/syntax) package: ledum-definers

This module contains the syntax abstractions common to other modules.

syntax

(define-n-bit-stx-class id maybe-desc n)

 
id = identifier?
     
maybe-desc = 
  | #:description description-string
 
  n : exact-positive-integer?
Defines a new syntax class id representing a n-bit unsigned number literal. In the description a "$n" placeholder can be used to represent the value of n and a "$m" placeholder represents the maximum value of such number as calculated by (sub1 (arithmetic-shift 1 n)).

syntax class

letter

A syntax class representing a symbol containing a single letter from #\a to #\z or from #\A to #\Z.

syntax class

maybe-id

This syntax class matches literal _ or any identifier. If the match is an identifier it sets its use attribute to #t. Used internally for skipping certain entity encodings.

1.6 ISA Utilities🔗

 (require ledum/define/isa/util) package: ledum-definers

Various ISA utilities, mostly re-exported by ledum/define/isa.

procedure

(isa-evaluator is)  (-> exact-nonnegative-integer? any)

  is : isa0?
Returns evaluator for given ISA. The contract for the first argument of the procedure returned should be understood more strictly to match only integers which fit into given ISA word width.

procedure

(print-isa-tree is)  void?

  is : isa0?
Prints ISA tree with unused regions and collisions highlighted.

procedure

(isa-disassembler is)  (-> exact-nonnegative-integer? list?)

  is : isa0?
Like isa-evaluator which does not run the behavioral description code but rather returns a list representing assembler notation for given instruction with given arguments.

procedure

(isa-analyze-unused isa)  void?

  isa : isa0?
Ensures given isa has a decoding tree built and uses analyze-optree to get the unused space masks list.

procedure

(isa-analyze-depth)  void?

Ensures given isa has a decoding tree built and uses analyze-optree-depth to collect the depths of individual leaves of the tree.

1.7 Opcode Emitter🔗

 (require ledum/define/isa/emitter) package: ledum-definers

A separate module with only the emitter parameter so that it can be required by assembler without pulling in further dependencies.

parameter

(opcode-emitter)  procedure?

(opcode-emitter proc)  void?
  proc : procedure?
A parameter which is used by the generated opcode syntaxes when evaluated at phase 0. The assembler parameterizes it to procedure which emits the binary encoded opcode number.

The default emitter just prints the opcode as hexadecimal number to (current-output-port).

1.8 Opcode Visualizer🔗

 (require ledum/define/isa/ompict) package: ledum-definers

This module is used internally to include visual representations of opcode masks in the documentation. Although it is not intended to be used directly, it can be parameterized to make subtle changes to the generated pictures.

procedure

(opcode-mask-pict s0 [oarg-lst])  pict?

  s0 : (or/c string? symbol?)
  oarg-lst : (listof symbol?) = '()
Creates an opcode mask picture with individual bits connected to their respective labels such as the opcode number or specific arguments.

parameter

(ompict-colors)  (or/c #f 'ibm 'wong 'tol)

(ompict-colors scheme)  void?
  scheme : (or/c #f 'ibm 'wong 'tol)
If non-#f, specifies the color scheme to be used for distinguishing the grid lines of different labels in opcode-mask-pict result.

parameter

(ompict-order)  (or/c #f 'order)

(ompict-order order)  void?
  order : (or/c #f 'order)
If set to 'order the ordering of labels in the visualization will be the same as the on especified by #:order of define-opcode.