NAME=Printing il statements in various formats
FILE=bins/elf/avr-sbrx-rjmp.elf
CMDS=<<EOF
echo -- oneline
aoi 5
echo -- pretty
aoip 5
echo -- graph
agI
EOF
EXPECT=<<EOF
-- oneline
0x0 (seq (storew 0 (- (cast 32 false (var sp)) (bv 32 0x3)) (bv 32 0x2)) (set sp (- (var sp) (bv 16 0x4))) (jmp (bv 32 0x2)))
0x2 (seq (storew 0 (- (cast 32 false (var sp)) (bv 32 0x3)) (bv 32 0x4)) (set sp (- (var sp) (bv 16 0x4))) (jmp (bv 32 0x4)))
0x4 (set r28 (cast 8 false (>> (var sp) (bv 32 0x8) false)))
0x6 (set r29 (cast 8 false (var sp)))
0x8 (set r24 (bv 8 0x1))
-- pretty
0x0
(seq
  (storew 0
    (-
      (cast 32
        false
        (var sp))
      (bv 32 0x3))
    (bv 32 0x2))
  (set sp
    (-
      (var sp)
      (bv 16 0x4)))
  (jmp
    (bv 32 0x2)))
0x2
(seq
  (storew 0
    (-
      (cast 32
        false
        (var sp))
      (bv 32 0x3))
    (bv 32 0x4))
  (set sp
    (-
      (var sp)
      (bv 16 0x4)))
  (jmp
    (bv 32 0x4)))
0x4
(set r28
  (cast 8
    false
    (>>
      (var sp)
      (bv 32 0x8)
      false)))
0x6
(set r29
  (cast 8
    false
    (var sp)))
0x8
(set r24
  (bv 8 0x1))
-- graph
                                                  .-------------.
                                                  |  rcall 0x2  |
                                                  `-------------'
                                                     v v v
                                                     | | |
                                                     | | '------------------.
                              .----------------------' '--.                 |
                              |                           |                 |
                              |                           |                 |
                          .-------------.             .-----------.     .----------.
                          |  storew: 0  |             |  set: sp  |     |  jmp     |
                          `-------------'             `-----------'     `----------'
                                v v                       v                 v
                                | |                       |                 |
                      .---------' |                       |                 |
                      |           '---.                   |                 |
                      |               |                   |               .-'
                      |               |                   |               |
                  .-----------.   .--------------.    .-----------.   .--------------.
                  |  sub      |   |  bv: 32 0x2  |    |  sub      |   |  bv: 32 0x2  |
                  `-----------'   `--------------'    `-----------'   `--------------'
                        v v                                 v v
                        | |                                 | |
           .------------' |                                 | |
           |              '--.                              | |
           |                 |                   .----------' |
           |                 |                   |            '--.
           |                 |                   |               |
       .------------.    .--------------.    .-----------.   .--------------.
       |  cast: 32  |    |  bv: 32 0x3  |    |  var: sp  |   |  bv: 16 0x4  |
       `------------'    `--------------'    `-----------'   `--------------'
             v v
             | |
    .--------' |
    |          '----.
    |               |
.----------.    .-----------.
|  false   |    |  var: sp  |
`----------'    `-----------'
EOF
RUN

NAME=fmul 1.5 * 1.25
FILE=malloc://512
CMDS=<<EOF
e asm.arch=avr
wa "ldi r16, 0xC0 ; ldi r17, 0xA0 ; fmul r16, r17"
aezi
aezse 3
EOF
EXPECT=<<EOF
pc_write(old: 0x0, new: 0x2)
var_write(name: r16, old: 0x0, new: 0xc0)
pc_write(old: 0x2, new: 0x4)
var_write(name: r17, old: 0x0, new: 0xa0)
pc_write(old: 0x4, new: 0x6)
var_write(name: r1, old: 0x0, new: 0xf0)
var_write(name: r0, old: 0x0, new: 0x0)
var_write(name: zf, old: 0x0, new: 0x0)
var_write(name: cf, old: 0x0, new: 0x1)
EOF
RUN

NAME=fmul test 2
FILE=malloc://512
CMDS=<<EOF
e asm.arch=avr
wa "ldi r16, 0xec ; ldi r17, 0x17 ; fmul r16, r17"
aezi
aezse 3
EOF
EXPECT=<<EOF
pc_write(old: 0x0, new: 0x2)
var_write(name: r16, old: 0x0, new: 0xec)
pc_write(old: 0x2, new: 0x4)
var_write(name: r17, old: 0x0, new: 0x17)
pc_write(old: 0x4, new: 0x6)
var_write(name: r1, old: 0x0, new: 0x2a)
var_write(name: r0, old: 0x0, new: 0x68)
var_write(name: zf, old: 0x0, new: 0x0)
var_write(name: cf, old: 0x0, new: 0x0)
EOF
RUN

NAME=fmuls -0.75 * -0.125
FILE=malloc://512
CMDS=<<EOF
e asm.arch=avr
wa "ldi r16, 0xA0 ; ldi r17, 0xF0 ; fmuls r16, r17"
aezi
aezse 3
EOF
EXPECT=<<EOF
pc_write(old: 0x0, new: 0x2)
var_write(name: r16, old: 0x0, new: 0xa0)
pc_write(old: 0x2, new: 0x4)
var_write(name: r17, old: 0x0, new: 0xf0)
pc_write(old: 0x4, new: 0x6)
var_write(name: r1, old: 0x0, new: 0xc)
var_write(name: r0, old: 0x0, new: 0x0)
var_write(name: zf, old: 0x0, new: 0x0)
var_write(name: cf, old: 0x0, new: 0x0)
EOF
RUN

NAME=fmuls test 2
FILE=malloc://512
CMDS=<<EOF
e asm.arch=avr
wa "ldi r16, 0x0f ; ldi r17, 0x1f ; fmuls r16, r17"
aezi
aezse 3
EOF
EXPECT=<<EOF
pc_write(old: 0x0, new: 0x2)
var_write(name: r16, old: 0x0, new: 0xf)
pc_write(old: 0x2, new: 0x4)
var_write(name: r17, old: 0x0, new: 0x1f)
pc_write(old: 0x4, new: 0x6)
var_write(name: r1, old: 0x0, new: 0x3)
var_write(name: r0, old: 0x0, new: 0xa2)
var_write(name: zf, old: 0x0, new: 0x0)
var_write(name: cf, old: 0x0, new: 0x0)
EOF
RUN

NAME=fmulsu -0.5 * 0.75
FILE=malloc://512
CMDS=<<EOF
e asm.arch=avr
wa "ldi r16, 0xc0 ; ldi r17, 0x60 ; fmulsu r16, r17"
aezi
aezse 3
EOF
EXPECT=<<EOF
pc_write(old: 0x0, new: 0x2)
var_write(name: r16, old: 0x0, new: 0xc0)
pc_write(old: 0x2, new: 0x4)
var_write(name: r17, old: 0x0, new: 0x60)
pc_write(old: 0x4, new: 0x6)
var_write(name: r1, old: 0x0, new: 0xd0)
var_write(name: r0, old: 0x0, new: 0x0)
var_write(name: zf, old: 0x0, new: 0x0)
var_write(name: cf, old: 0x0, new: 0x1)
EOF
RUN

NAME=fmulsu test 2
FILE=malloc://512
CMDS=<<EOF
e asm.arch=avr
wa "ldi r16, 0xff ; ldi r17, 0x50 ; fmulsu r16, r17"
aezi
aezse 3
EOF
EXPECT=<<EOF
pc_write(old: 0x0, new: 0x2)
var_write(name: r16, old: 0x0, new: 0xff)
pc_write(old: 0x2, new: 0x4)
var_write(name: r17, old: 0x0, new: 0x50)
pc_write(old: 0x4, new: 0x6)
var_write(name: r1, old: 0x0, new: 0xb0)
var_write(name: r0, old: 0x0, new: 0xa0)
var_write(name: zf, old: 0x0, new: 0x0)
var_write(name: cf, old: 0x0, new: 0x1)
EOF
RUN

NAME=push & pop
FILE=malloc://512
CMDS=<<EOF
e asm.arch=avr
wa "ldi r16, 0xC0 ; ldi r17, 0xA0 ; push r16 ; push r17 ; pop r16 ; pop r17"
aezi
ar SP=0x3F
aezs 2
ar r16
ar r17
aezs 1
ar sp
px 16 @ 0x30
aezs 1
ar sp
px 16 @ 0x30
aezs 1
ar r16
ar sp
aezs 1
ar r17
ar sp
EOF
EXPECT=<<EOF
r16 = 0xc0
r17 = 0xa0
sp = 0x003e
- offset -   0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x00000030  0000 0000 0000 0000 0000 0000 0000 00c0  ................
sp = 0x003d
- offset -   0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x00000030  0000 0000 0000 0000 0000 0000 0000 a0c0  ................
r16 = 0xa0
sp = 0x003e
r17 = 0xc0
sp = 0x003f
EOF
RUN

NAME=Subtract r17:r16 from r31:r30
FILE=malloc://512
CMDS=<<EOF
e asm.arch=avr
wa "ldi r31, 0x11 ; ldi r30, 0xEE ; subi r30, 0x50 ; sbci r31, 0x72"
aezi
aezs 2
ar r31
ar r30
aezse 2~name
ar r31
ar r30
EOF
EXPECT=<<EOF
r31 = 0x11
r30 = 0xee
var_write(name: zf, old: 0x0, new: 0x0)
var_write(name: hf, old: 0x0, new: 0x0)
var_write(name: vf, old: 0x0, new: 0x0)
var_write(name: nf, old: 0x0, new: 0x1)
var_write(name: cf, old: 0x0, new: 0x0)
var_write(name: sf, old: 0x0, new: 0x1)
var_write(name: r30, old: 0xee, new: 0x9e)
var_write(name: zf, old: 0x0, new: 0x0)
var_write(name: hf, old: 0x0, new: 0x1)
var_write(name: vf, old: 0x0, new: 0x0)
var_write(name: nf, old: 0x1, new: 0x1)
var_write(name: cf, old: 0x0, new: 0x1)
var_write(name: sf, old: 0x1, new: 0x1)
var_write(name: r31, old: 0x11, new: 0x9f)
r31 = 0x9f
r30 = 0x9e
EOF
RUN

NAME=Perform SWAP
FILE=malloc://512
CMDS=<<EOF
e asm.arch=avr
wa "inc r1 ; swap r1 ; inc r1 ; swap r1 ; inc r1"
aezi
echo increase r1
aezs
ar r1
echo swap nibbles
aezs
ar r1
echo increase r1
aezs
ar r1
echo swap nibbles
aezs
ar r1
echo increase r1
aezs
ar r1
EOF
EXPECT=<<EOF
increase r1
r1 = 0x01
swap nibbles
r1 = 0x10
increase r1
r1 = 0x11
swap nibbles
r1 = 0x11
increase r1
r1 = 0x12
EOF
RUN

NAME=Add r17:r16 to r31:r30
FILE=malloc://512
CMDS=<<EOF
e asm.arch=avr
wa "ldi r17, 0x7f" @ 0x0
wa "ldi r16, 0x50" @ 0x2
wa "ldi r31, 0x11" @ 0x4
wa "ldi r30, 0xEE" @ 0x6
wa "add r30, r16" @ 0x8
wa "adc r31, r17" @ 0xa   
aezi
aezse 4~name
echo add
aezse
echo add with carry
aezse
EOF
EXPECT=<<EOF
var_write(name: r17, old: 0x0, new: 0x7f)
var_write(name: r16, old: 0x0, new: 0x50)
var_write(name: r31, old: 0x0, new: 0x11)
var_write(name: r30, old: 0x0, new: 0xee)
add
pc_write(old: 0x8, new: 0xa)
var_write(name: hf, old: 0x0, new: 0x0)
var_write(name: vf, old: 0x0, new: 0x0)
var_write(name: nf, old: 0x0, new: 0x0)
var_write(name: zf, old: 0x0, new: 0x0)
var_write(name: cf, old: 0x0, new: 0x1)
var_write(name: sf, old: 0x0, new: 0x0)
var_write(name: r30, old: 0xee, new: 0x3e)
add with carry
pc_write(old: 0xa, new: 0xc)
var_write(name: hf, old: 0x0, new: 0x1)
var_write(name: vf, old: 0x0, new: 0x1)
var_write(name: nf, old: 0x0, new: 0x1)
var_write(name: zf, old: 0x0, new: 0x0)
var_write(name: cf, old: 0x1, new: 0x0)
var_write(name: sf, old: 0x0, new: 0x0)
var_write(name: r31, old: 0x11, new: 0x91)
EOF
RUN

NAME=Add Immediate to Word
FILE=malloc://512
CMDS=<<EOF
e asm.arch=avr
wa "adiw r25:r24, 1 ; adiw r31:r30, 63"
aezi
aezse 2~name
EOF
EXPECT=<<EOF
var_write(name: r25, old: 0x0, new: 0x0)
var_write(name: r24, old: 0x0, new: 0x1)
var_write(name: zf, old: 0x0, new: 0x0)
var_write(name: vf, old: 0x0, new: 0x0)
var_write(name: nf, old: 0x0, new: 0x0)
var_write(name: cf, old: 0x0, new: 0x0)
var_write(name: sf, old: 0x0, new: 0x0)
var_write(name: r31, old: 0x0, new: 0x0)
var_write(name: r30, old: 0x0, new: 0x3f)
var_write(name: zf, old: 0x0, new: 0x0)
var_write(name: vf, old: 0x0, new: 0x0)
var_write(name: nf, old: 0x0, new: 0x0)
var_write(name: cf, old: 0x0, new: 0x0)
var_write(name: sf, old: 0x0, new: 0x0)
EOF
RUN

NAME=Shifts
FILE=malloc://512
CMDS=<<EOF
e asm.arch=avr
# Load decimal 16 into r16
wa "ldi r16, 0x10" @ 0
# r16 /= 2
wa "asr r16" @ 2
# Load -4 in r17
wa "ldi r17, 0xFC" @ 4
# r17 /= 2       
wa "asr r17" @ 6
# r17 *= 2
wa "lsl r17" @ 8
# r16 /= 2
wa "lsr r16" @ 10
aezi
echo Arithmetic Signed Shift Right
aezse 4
echo Logical Shift Left & Right
aezse 2
EOF
EXPECT=<<EOF
Arithmetic Signed Shift Right
pc_write(old: 0x0, new: 0x2)
var_write(name: r16, old: 0x0, new: 0x10)
pc_write(old: 0x2, new: 0x4)
var_write(name: cf, old: 0x0, new: 0x0)
var_write(name: r16, old: 0x10, new: 0x8)
var_write(name: nf, old: 0x0, new: 0x0)
var_write(name: zf, old: 0x0, new: 0x0)
var_write(name: sf, old: 0x0, new: 0x0)
var_write(name: vf, old: 0x0, new: 0x0)
pc_write(old: 0x4, new: 0x6)
var_write(name: r17, old: 0x0, new: 0xfc)
pc_write(old: 0x6, new: 0x8)
var_write(name: cf, old: 0x0, new: 0x0)
var_write(name: r17, old: 0xfc, new: 0xfe)
var_write(name: nf, old: 0x0, new: 0x1)
var_write(name: zf, old: 0x0, new: 0x0)
var_write(name: sf, old: 0x0, new: 0x1)
var_write(name: vf, old: 0x0, new: 0x1)
Logical Shift Left & Right
pc_write(old: 0x8, new: 0xa)
var_write(name: hf, old: 0x0, new: 0x1)
var_write(name: cf, old: 0x0, new: 0x1)
var_write(name: r17, old: 0xfe, new: 0xfc)
var_write(name: nf, old: 0x1, new: 0x1)
var_write(name: zf, old: 0x0, new: 0x0)
var_write(name: sf, old: 0x1, new: 0x0)
var_write(name: vf, old: 0x1, new: 0x0)
pc_write(old: 0xa, new: 0xc)
var_write(name: cf, old: 0x1, new: 0x0)
var_write(name: nf, old: 0x1, new: 0x0)
var_write(name: r16, old: 0x8, new: 0x4)
var_write(name: zf, old: 0x0, new: 0x0)
var_write(name: sf, old: 0x0, new: 0x0)
var_write(name: vf, old: 0x0, new: 0x0)
EOF
RUN

NAME=Status regs & bit Manipulations
FILE=malloc://512
CMDS=<<EOF
e asm.arch=avr
wa "ldi r16, 0x4" @ 0
# Store bit 2 of r16 in T Flag
wa "bst r16, 2" @ 2
# Load T Flag into bit 4 of r0
wa "bld r0, 4" @ 4
# Set vf
wa "bset 3" @ 6
# Set if
wa "bset 7" @ 8
# clear if
wa "bclr 7" @ 10
# clear tf
wa "bclr 6" @ 12
# clear vf
wa "bclr 3" @ 14

aezi
aezs
ar r16
aezse 1~name
ar tf
aezse 1~name
ar r0
ar tf
aezse 1~name
ar vf
aezse 1~name
ar if
aezse 1~name
ar if
aezse 1~name
ar tf
aezse 1~name
ar vf
EOF
EXPECT=<<EOF
r16 = 0x04
var_write(name: tf, old: 0x0, new: 0x1)
tf = 0x1
var_write(name: r0, old: 0x0, new: 0x10)
r0 = 0x10
tf = 0x1
var_write(name: vf, old: 0x0, new: 0x1)
vf = 0x1
var_write(name: if, old: 0x0, new: 0x1)
if = 0x1
var_write(name: if, old: 0x1, new: 0x0)
if = 0x0
var_write(name: tf, old: 0x1, new: 0x0)
tf = 0x0
var_write(name: vf, old: 0x1, new: 0x0)
vf = 0x0
EOF
RUN

NAME=Status regs clear and set
FILE=malloc://512
CMDS=<<EOF
e asm.arch=avr
wa "sei ; set ; seh ; ses ; sev ; sen ; sez ; sec"
aezi
aezs 8
ar sreg
wa "cli ; clt ; clh ; cls ; clv ; cln ; clz ; clc"
aezi
aezs 8
ar sreg
EOF
EXPECT=<<EOF
sreg = 0xff
sreg = 0x00
EOF
RUN

NAME=Simple call & ret
FILE=malloc://512
CMDS=<<EOF
e asm.arch=avr
wx "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE" @ 0x70
wa "ldi r16, 0x7F" @ 0
wa "ldi r17, 0xFC" @ 2
# set stack to 0x7F
wa "out 0x3e, r16" @ 4
# call subroutine at 16
wa "call 0x10" @ 6

# clear r17 subroutine using r16
wa "push r16" @ 16
wa "andi r16, 0x08" @ 18
wa "and r17, r16" @ 20
wa "pop r16" @ 22
wa "ret" @ 24

echo instructions
pdq 5
pdq 5 @ 16
echo
echo initial machine status
px 16 @ 0x70
aezi
aezs 3
ar pc
ar sp
ar r16
ar r17
echo
echo call subroutine & stack pointer
aezse 1
ar pc
ar sp
px 16 @ 0x70
echo
echo execute subroutine
aezs 4
ar pc
ar sp
ar r16
ar r17
px 16 @ 0x70
echo
echo execute return
aezs
ar pc
ar sp
ar r16
ar r17
px 16 @ 0x70
EOF
EXPECT=<<EOF
instructions
0x00000000 ldi r16, 0x7f
0x00000002 ldi r17, 0xfc
0x00000004 out 0x3e, r16
0x00000006 call 0x10
0x0000000a nop
0x00000010 push r16
0x00000012 andi r16, 0x08
0x00000014 and r17, r16
0x00000016 pop r16
0x00000018 ret

initial machine status
- offset -   0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x00000070  eeee eeee eeee eeee eeee eeee eeee eeee  ................
pc = 0x00000006
sp = 0x007f
r16 = 0x7f
r17 = 0xfc

call subroutine & stack pointer
pc_write(old: 0x6, new: 0xa)
mem_write(addr: 0x7c, old: 0xeeeeeeee, new: 0xa)
var_write(name: sp, old: 0x7f, new: 0x7b)
pc_write(old: 0xa, new: 0x10)
pc = 0x00000010
sp = 0x007b
- offset -   0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x00000070  eeee eeee eeee eeee eeee eeee 0a00 0000  ................

execute subroutine
pc = 0x00000018
sp = 0x007b
r16 = 0x7f
r17 = 0x08
- offset -   0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x00000070  eeee eeee eeee eeee eeee ee7f 0a00 0000  ................

execute return
pc = 0x0000000a
sp = 0x007f
r16 = 0x7f
r17 = 0x08
- offset -   0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x00000070  eeee eeee eeee eeee eeee ee7f 0a00 0000  ................
EOF
RUN
