The Spawn Architecture Description Language (SADL)

The Spawn tool was designed to generate the machine specific parts of the Executable Editing Library (EEL). Spawn reads a detailed instruction set architecture description written in SADL, and specializes the machine specific C++ code used by EEL to manipulate these machine instructions. Architecture descriptions capture the binary instruction encodings, instruction semantics, and architectural register descriptions of several RISC processors. From analysis of these descriptions Spawn can distinguish between different kinds of instructions (e.g., loads, stores, jumps, branches, floating point or integer computation, traps), determine which registers are read from or written to, and lots of other useful information. There is enough information contained in the description of most instructions for Spawn to generate C++ code to simulate the instruction's semantic operation.

A brief description of Spawn, SADL, and their relation to EEL is given in "EEL: Machine-Independent Executable Editing," appearing in the Proceedings of the SIGPLAN Conference on Programming Language Design and Implementation (PLDI), June 1995. Spawn and SADL were later extended to provide information for instruction scheduling as part EEL's editing of an executable. Another paper, appearing in MICRO29, shows that simple instruction scheduling can hide 20-65% of the cost of some program instrumentation.

-- Return to FastSim home. --


A SADL Example: SPARC-V8

Instruction Encoding

///////////////////////////////////////////////////////////////////////////////
//
// Spawn description file for the SPARC instruction encodings.
//

encode{32} instruction fields op 30:31, op2 22:24, op3 19:24, opf 5:13,
        rd 25:29, rs1 14:18, rs2 0:4, iflag 13:13, simm13 0:12, imm22 0:21,
        disp22 0:21, disp30 0:29, cond 25:28, aflag 29:29, asi 5:12

pat [op0inst call op2inst op3inst] is op=[0..3]

//
// Macro patterns to insure bits are zero based on
// the use or lack of the immediate value field.

pat noasi is (iflag=0 && asi=0) || iflag=1
pat trapn is (iflag=0 && asi=0) || (iflag=1 && instruction{7:12}=0)

//
// branch & other op0 instructions

pat sethi is op0inst && op2=0b100
pat nop is sethi && rd=0 && imm22=0
pat unimp is op0inst && op2=0b000 && rd=0

pat [   bn      be      ble     bl      bleu    bcs     bneg    bvs
        ba      bne     bg      bge     bgu     bcc     bpos    bvc
        fbn     fbne    fblg    fbul    fbl     fbug    fbg     fbu
        fba     fbe     fbue    fbge    fbuge   fble    fbule   fbo
        cbn     cb123   cb12    cb13    cb1     cb23    cb2     cb3
        cba     cb0     cb03    cb02    cb023   cb01    cb013   cb012   ]
 is op0inst && op2=[0b010 0b110 0b111] && cond=[0..15]

//
// load & store instructions

pat [   ld      ldub    lduh    ldd     st      stb     sth     std
        _       ldsb    ldsh    _       _       ldstub  _       swap
        lda     lduba   lduha   ldda    sta     stba    stha    stda
        _       ldsba   ldsha   _       _       ldstuba _       swapa   ]
 is op3inst && op3=[0b000000..0b011111]

pat [   ldf     ldfsr   _       lddf    stf     stfsr   stdfq   stdf
        ldc     ldcsr   _       lddc    stc     stcsr   stdcq   stdc    ]
 is op3inst && (op3=[0b100000..0b100111] || op3=[0b110000..0b110111]) && noasi

//
// op2 instructions

pat [   add     and     or      xor     sub     andn    orn     xnor
        addx    _       umul    smul    subx    _       udiv    sdiv
        addcc   andcc   orcc    xorcc   subcc   andncc  orncc   xnorcc
        addxcc  _       umulcc  smulcc  subxcc  _       udivcc  sdivcc
        taddcc  tsubcc  taddcctv tsubcctv mulscc _      _       _
        _       _       _       _       _       _       _       _
        wranc   wrpsr   wrwim   wrtbr   _       _       _       _
        jmpl    _       _       _       save    restore _       _       ]
 is op2inst && op3=[0b000000..0b111111] && noasi

pat [sll srl sra] is op2inst && op3=[0b100101..0b100111] && asi=0

pat [fpop1 fpop2 cpop1 cpop2] is op2inst && op3=[0b110100..0b110111]

pat [rett flush] is op2inst && op3=[0b111001 0b111011] && rd=0 && noasi

pat [rdanc rdpsr rdwim rdtbr]
 is op2inst && op3=[0b101000..0b101011] && iflag=0 && simm13=0

pat rdy is rdanc && rs1=0
pat rdasr is rdanc // && rs1=[1..31]
pat wry is wranc && rs1=0
pat wrasr is wranc // && rs1=[1..31]
pat stbar is op2inst && op3=0b101000 && rd=0 && rs1=0b01111 && iflag=0 && simm13=0

pat [   tn      te      tle     tl      tleu    tcs     tneg    tvs
        ta      tne     tg      tge     tgu     tcc     tpos    tvc     ]
 is op2inst && aflag=0 && cond=[0..15] && op3=0b111010 && trapn

pat [   fabss           faddd           faddq           fadds
        fdivd           fdivq           fdivs           fdmulq
        fdtoi           fdtoq           fdtos           fitod
        fitoq           fitos           fmovs           fmuld
        fmulq           fmuls           fnegs           fqtod
        fqtoi           fqtos           fsmuld          fsqrtd
        fsqrtq          fsqrts          fstod           fstoi
        fstoq           fsubd           fsubq           fsubs           ]
 is fpop1 && opf
  = [   0b000001001     0b001000010     0b001000011     0b001000001
        0b001001110     0b001001111     0b001001101     0b001101110
        0b011010010     0b011001110     0b011000110     0b011001000
        0b011001100     0b011000100     0b000000001     0b001001010
        0b001001011     0b001001001     0b000000101     0b011001011
        0b011010011     0b011000111     0b001101001     0b000101010
        0b000101011     0b000101001     0b011001001     0b011010001
        0b011001101     0b001000110     0b001000111     0b001000101     ]

pat [ fcmpd fcmpq fcmps fcmped fcmpeq fcmpes ]
 is fpop2 && opf = [ 0b001010010 0b001010011 0b001010001
                     0b001010110 0b001010111 0b001010101 ]

Registers and Memory

///////////////////////////////////////////////////////////////////////////////
//
// Resource Definitions
//

val [% +] is [(\s1:unsigned{32}.\s2. umod32 (unsigned{64}s1) s2) uadd32]

//
// Integer Data Path (IDP)

type address

register untyped{32} pc         // program counter

register untyped{32} R[35]      // general purpose register set
alias untyped{32} zero is R[0]
alias untyped{32} irpc is R[31]
alias untyped{32} orpc is R[15]
alias untyped{32} sp is R[14]
alias untyped{32} fp is R[30]
alias untyped{32} PSR is R[32]
alias untyped{32} FSR is R[33]
alias untyped{32} Y is R[34]

alias signed{32} R4r[i] is R[i]                 // ALU read from register set
alias unsigned{32} uR4r[i] is R[i]

alias signed{32} R4w[i] is R[i]                 // ALU write to register set
alias unsigned{32} uR4w[i] is R[i]

alias address{32} aR4r[i] is R[i]               // LSU read address reg
alias untyped{32} R4r'[i] is R[i]               // LSU read from register set
alias untyped{32} R4w'[i] is R[i]               // LSU write to register set

// double word LSU access to register set
alias untyped{64} R8r'[i: unsigned{32}i%2=0] is R[i]::R[unsigned{32}i + 1]
alias untyped{64} R8w'[i: unsigned{32}i%2=0] is R[i]::R[unsigned{32}i + 1]

//
// Floating-Point Unit (FPU)

type float

register untyped{32} F[32]      // floating-point register set

// FP read 4 and 8 byte values
alias float{32} F4r[i] is isFloat, F[i]
alias float{64} F8r[i: unsigned{32}i%2=0]
   is isFloat, (F[i]::F[unsigned{32}i + 1])
alias signed{32} FIr[i] is isFloat, F[i]

// FP write 4 and 8 byte values
alias float{32} F4w[i] is isFloat, F[i]
alias float{64} F8w[i: unsigned{32}i%2=0]
   is isFloat, (F[i]::F[unsigned{32}i + 1])
alias signed{32} FIw[i] is isFloat, F[i]

// FP load/store: read 4 and 8 byte values
alias untyped{32} F4r'[i] is isFloat, F[i]
alias untyped{64} F8r'[i: unsigned{32}i%2=0]
   is isFloat, (F[i]::F[unsigned{32}i + 1])

// FP load/store: write 4 and 8 byte values
alias untyped{32} F4w'[i] is isFloat, F[i]
alias untyped{64} F8w'[i: unsigned{32}i%2=0]
   is isFloat, (F[i]::F[unsigned{32}i + 1])

//
// Special Registers

register untyped{32} WIM, TBR, CWP
register untyped{64} FQ

//
// Memory

memory untyped{ 8} M1[address{32}]
memory untyped{16} M2[address{32}]
memory untyped{32} M4[address{32}]
memory untyped{64} M8[address{32}]

// operators used in definition of memory aliases
val % is \a:address{32}.\i. (unsigned a) % i

alias untyped{32} M1[i]         is (untyped{24}0)::M1[i]
alias untyped{32} M2[i: i%2=0]  is (untyped{16}0)::M2[i]
alias untyped{16} M2[i: i%2=0]  is M2[i]
alias untyped{32} M4[i: i%4=0]  is M4[i]
alias untyped{64} M8[i: i%8=0]  is M8[i]

// Load of 1, 2, 4, and 8 byte values
alias untyped{ 8} M1r[i] is ARf Memory, M1[i]
alias untyped{32} M1r[i] is ARf Memory, M1[i]
alias untyped{16} M2r[i] is ARf Memory, M2[i]
alias untyped{32} M2r[i] is ARf Memory, M2[i]
alias untyped{32} M4r[i] is ARf Memory, M4[i]
alias untyped{64} M8r[i] is ARf Memory, M8[i]

// Store of 1, 2, 4, and 8 byte values
alias untyped{ 8} M1w[i] is M1[i]
alias untyped{32} M1w[i] is M1[i]
alias untyped{16} M2w[i] is M2[i]
alias untyped{32} M2w[i] is M2[i]
alias untyped{32} M4w[i] is M4[i]
alias untyped{64} M8w[i] is M8[i]

Instruction Semantics

///////////////////////////////////////////////////////////////////////////////
//
// Operator Definitions
//

val Id32 is \a:untyped{32}. untyped{32} a
val Id64 is \a:untyped{64}. untyped{64} a
val [   #       #       #       #       #       ]
 is (\op.\s1. op s1)
  @ [   ext8    ext13   ext16   ext22   ext30   ]

//
// Protocol for reading source registers

val src1 is R4r[rs1]
val src1 is uR4r[rs1]
val src2 is iflag=1 ? #simm13 : R4r[rs2]
val src2 is iflag=1 ? unsigned{32} simm13 : uR4r[rs2]
val addr is _a1:=aR4r[rs1],
        _a2:=(iflag=1 ? address{32}(#simm13) : aR4r[rs2]),
        address(add32 (signed _a1) (signed _a2))

//
// ALU Operators

val [   +       -       &       |       ^       ]
 is (\op.\s1.\s2. op s1 s2)
  @ [   add32   sub32   and32   or32    xor32   ]

val [   :+      :-      ]
 is (\op.\s1.\s2. (??) PSR (op s1 s2))
  @ [   add32   sub32   ]

val [   +'      -'      &'      |'      ^'      ]
 is (\op.\s1.\s2. _x:=op s1 s2, PSR:=(??), _x)
  @ [   add32   sub32   and32   or32    xor32   ]

val [   :+'     :-'     ]
 is (\op.\s1.\s2. _x:=(??) PSR (op s1 s2), PSR:=(??), _x)
  @ [   add32   sub32   ]

val [   <<      >>      >>      ]
 is (\op.\s1.\s2. isShift, op s1 s2)
  @ [   sll32   srl32   sra32   ]

infixl 7 :*'
val :*' is \a:signed{32}.\b:signed{32}. _x:=(??) PSR a b, PSR:=(??), _x

val [   *       $*      /       $/      ]
 is (\op.\s1.\s2. op s1 s2)
  @ [   mul32   umul32  div32   udiv32  ]

val [   *'      $*'     /'      $/'     ]
 is (\op.\s1.\s2. _x:=op s1 s2, PSR:=(??), _x)
  @ [   mul32   umul32  div32   udiv32  ]

val [   !&      !|      !^      !&'     !|'     !^'     ]
 is (\op.\s1.\s2. op s1 (not32 s2))
  @ [   &       |       ^       &'      |'      ^'      ]

//
// FPU Operators

val [   abs     cvt     cvt     cvt     cvt
        mov     ~       cvt     cvt             ]
 is (\op.\s1. op s1)
  @ [   fabss   fdtoi   fdtos   fitod   fitos
        (\a.a)  fnegs   fstod   fstoi           ]

val [   sqrt    sqrt    ]
 is (\op.\s1. op s1)
  @ [   fsqrts  fsqrtd  ]

val [   +       +       -       -       ]
 is (\op.\s1.\s2. op s1 s2)
  @ [   fadds   faddd   fsubs   fsubd   ]

val [   *       *       *       ]
 is (\op.\s1.\s2. op s1 s2)
  @ [   fmuls   fmuld   fsmuld  ]

val [   /       /       ]
 is (\op.\s1.\s2. op s1 s2)
  @ [   fdivs   fdivd   ]

///////////////////////////////////////////////////////////////////////////////
//
// Instruction Semantics
//

sem sethi is uR4w[rd]:=sll32 (unsigned{32}imm22) 10

//
// load & store instructions

sem [   ldsb    ldsh    ldub    lduh    ld      ldf     lddf
        ldsba   ldsha   lduba   lduha   lda                     ]
 is (\r.\m.\sgn. r[rd]:=sgn m[addr])
  @ [   R4w'    R4w'    R4w'    R4w'    R4w'    F4w'    F8w'
        R4w'    R4w'    R4w'    R4w'    R4w'                    ]
  $ [   M1r     M2r     M1r     M2r     M4r     M4r     M8r
        M1r     M2r     M1r     M2r     M4r                     ]
  $ [   #       #       Id32    Id32    Id32    Id32    Id64
        #       #       Id32    Id32    Id32                    ]

sem [   ldd     ldda    ]
 is (\r.\m.\sgn. r[rd]:=sgn m[addr])
  @ [   R8w'    R8w'    ]
  $ [   M8r     M8r     ]
  $ [   Id64    Id64    ]

sem [   stb     sth     st      stf     stdf
        stba    stha    sta     std     stda    ]
 is (\r.\m. m[addr]:=r[rd])
  @ [   R4r'    R4r'    R4r'    F4r'    F8r'
        R4r'    R4r'    R4r'    R8r'    R8r'    ]
  $ [   M1w     M2w     M4w     M4w     M8w
        M1w     M2w     M4w     M8w     M8w     ]

sem ldfsr is FSR:=M4r[addr]
sem stfsr is M4w[addr]:=FSR

sem ldstub is a:=addr, x:=M1r[a], M1[a]:=untyped{8}0xff, R4w[rd]:=x
sem ldstuba is a:=addr, x:=M1r[a], M1[a]:=untyped{8}0xff, R4w[rd]:=x

sem swap is a:=addr, x:=R4r'[rd], y:=M4r[a], M4[a]:=x, R4w[rd]:=y
sem swapa is a:=addr, x:=R4r'[rd], y:=M4r[a], M4[a]:=x, R4w[rd]:=y

sem [   rdy     rdpsr   rdwim   rdtbr   ]
 is (\r. R4w[rd]:=r)
  @ [   Y       PSR     WIM     TBR     ]

sem [   wry     wrpsr   wrwim   wrtbr   ]
 is (\r. r:=src1^src2)
  @ [   Y       PSR     WIM     TBR     ]

sem flush is iflag=1 ? ()

//
// Integer computation instructions

sem [   add     addcc   addx    addxcc
        sub     subcc   subx    subxcc  sra     ]
 is (\op. R4w[rd]:=op src1 src2)
  @ [   +       +'      :+      :+'
        -       -'      :-      :-'     >>      ]

sem [   and     andcc   andn    andncc  or      orcc    orn     orncc
        xor     xorcc   xnor    xnorcc  sll     srl                     ]
 is (\op. uR4w[rd]:=op src1 src2)
  @ [   &       &'      !&      !&'     |       |'      !|      !|'
        ^       ^'      !^      !^'     <<      >>                      ]

sem [   taddcctv        tsubcctv        ]
 is (\op. R4w[rd]:=op src1 src2)
  @ [   +'              -'              ]

sem mulscc is R4w[rd]:=src1:*'src2

sem [   smul    smulcc  umul    umulcc  ]
 is (\op. x:=op src1 src2, Y:=x{32:63}, uR4w[rd]:=x{0:31})
  @ [   *       *'      $*      $*'     ]

sem [   sdiv    sdivcc  ]
 is (\op. s1:=signed{64}(Y::((\a:unsigned.a)src1)), R4w[rd]:=op s1 src2)
  @ [   /       /'      ]

sem [   udiv    udivcc  ]
 is (\op. s1:=(Y::((\a:unsigned.a)src1)), uR4w[rd]:=op s1 src2)
  @ [   $/      $/'     ]

sem [   save    restore ]
 is (\op. s1:=src1, s2:=src2, CWP:=op CWP 1, R4w[rd]:=s1+s2)
  @ [   usub32  uadd32  ]

//
// FP computation instructions

sem [   fabss   fdtoi   fdtos   fitod   fitos   fmovs
        fnegs   fstod   fstoi   fsqrtd  fsqrts          ]
 is (\op.\r.\w. w[rd]:=op r[rs2])
  @ [   abs     cvt     cvt     cvt     cvt     mov
        ~       cvt     cvt     sqrt    sqrt            ]
  $ [   F4r     F8r     F8r     FIr     FIr     F4r
        F4r     F4r     F4r     F8r     F4r             ]
  $ [   F4w     FIw     F4w     F8w     F4w     F4w
        F4w     F8w     FIw     F8w     F4w             ]

sem [   faddd   fadds   fsubd   fsubs
        fdivd   fdivs   fmuld   fmuls   fsmuld  ]
 is (\op.\r.\w. w[rd]:=op r[rs1] r[rs2])
  @ [   +       +       -       -
        /       /       *       *       *       ]
  $ [   F8r     F4r     F8r     F4r
        F8r     F4r     F8r     F4r     F4r     ]
  $ [   F8w     F4w     F8w     F4w
        F8w     F4w     F8w     F4w     F8w     ]

sem [   fcmpd   fcmped  fcmpes  fcmps   ]
 is (\r. (??):=r[rs1]-r[rs2], FSR:=(??))
  @ [   F8r     F8r     F4r     F4r     ]

//
// control transfer instructions

val target is add32 (signed{32} pc) (signed (sll32 (unsigned (#disp22)) 2))
val branch is \r.\op. (); op r ? pc:=target : aflag=1 ? annul
val trap is \op. op PSR ? system ((\a:signed.a)src2) : ()
val baf is aflag=1 ? pc:=target : ((); pc:=target)
val bnf is aflag=1 ? pc:=pc+8

sem [ba fba] is [baf baf]
sem [bn fbn] is [bnf bnf]

sem [bne be] is branch PSR @ [test1 test2]
sem [bg ble] is branch PSR @ [test1 test2]
sem [bge bl] is branch PSR @ [test1 test2]
sem [bgu bleu] is branch PSR @ [test1 test2]
sem [bcc bcs] is branch PSR @ [test1 test2]
sem [bpos bneg] is branch PSR @ [test1 test2]
sem [bvc bvs] is branch PSR @ [test1 test2]

sem [fbu fbo] is branch FSR @ [test1 test2]
sem [fbg fbule] is branch FSR @ [test1 test2]
sem [fbug fble] is branch FSR @ [test1 test2]
sem [fbl fbuge] is branch FSR @ [test1 test2]
sem [fbul fbge] is branch FSR @ [test1 test2]
sem [fblg fbue] is branch FSR @ [test1 test2]
sem [fbne fbe] is branch FSR @ [test1 test2]

sem call is t:=uadd32 pc (sll32 (unsigned{32}disp30) 2), uR4w[15]:=pc; pc:=t
sem jmpl is t:=addr, uR4w[rd]:=pc; pc:=t
sem rett is t:=addr, PSR:=(??); pc:=t

sem ta is system ((\a:signed{32}.a)src2)
sem tn is iflag=1 ? ()

sem [tne te] is trap @ [test1 test2]
sem [tg tle] is trap @ [test1 test2]
sem [tge tl] is trap @ [test1 test2]
sem [tgu tleu] is trap @ [test1 test2]
sem [tcc tcs] is trap @ [test1 test2]
sem [tpos tneg] is trap @ [test1 test2]
sem [tvc tvs] is trap @ [test1 test2]

-- Return to FastSim home. --