aboutsummaryrefslogtreecommitdiffstats
path: root/README.md
blob: cd47df9a2f8915cc07fa676c9cc9bb98ba51ffda (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# SubV

This is a wip clone of [SubX][mu] for the RISC-V RV31I base ISA.

    $ <label_test.subv ./format.py | ./survey.py | ./pack.py | ./elf.py >out.elf
    $ ./qemu.sh out.elf

## Status

Features:

- ELF output: ✔️
- Free arg order: ❌
- SubX cross-asm: ❌

Instruction Groups:

- OP-IMM: ✔️✔️
- OP: ✔️❌
- LUI: ✔️✔️
- AIUPC: ✔️❌
- JAL: ✔️✔️
- JALR: ✔️❌
- BRANCH: ❌❌
- LOAD: ✔️❌
- STORE: ✔️✔️

(✔️❌: implemented but untested)

## Pipeline

back to front:

- `elf.py`: takes hex bytes and segment headers, outputs an ELF file
- `pack.py`: packs bitfields (`3/3 1/1 f/4`) into hex bytes (`fb`)
- `format.py`: bit-packs ops into ISA format
- `survey.py`: replaces label references by their addresses
- `validate.py`: checks op-arguments and puts them into canonical order

and now front to back with a little example:

    $ ./validate.py <ex.subv  >ex.valid
    $ ./survey.py  <ex.valid  >ex.survey
    $ ./format.py  <ex.survey >ex.format
    $ ./pack.py    <ex.format >ex.pack
    $ ./elf.py     <ex.pack   >ex.elf
    $ ./qemu.sh ex.elf

`ex.subv`: hand-writable.

    == code 0x80000000
    # repeatedly print "Hi\\n"
    main:
      # load 0x10010000 (UART0) into t0
      37/lui 5/rd/t0 0x10010/imm20
      # store 0x48 (H) in UART0+0
      13/opi 0/subop/add 6/rd/t1 0/rs/x0 48/imm12
      23/store 2/subop/word 5/rs/t0 6/rs/t1 0/off12
      # store 0x69 (i) in UART0+0
      13/opi 0/subop/add 6/rd/t1 0/rs/x0 69/imm12
      23/store 2/subop/word 5/rs/t0 6/rs/t1 0/off12
      # store 0x0a (\n) in UART0+0
      13/opi 0/subop/add 6/rd/t1 0/rs/x0 0a/imm12
      23/store 2/subop/word 5/rs/t0 6/rs/t1 0/off12
      # jump back up to the top
      6f/jal 0/rd/x0 main/off21

`ex.format`: mnemonics validated and discarded

    == code 0x80000000
    # repeatedly print "Hi\n"
    main:
    # load 0x10010000 (UART0) into t0
    37/u 05/rd 10010/imm20
    # store 0x48 (H) in UART0+0
    13/i 0/subop 6/rd 0/rs 48/imm12
    23/s 2/subop 5/rs2 6/rs1 0/off12
    # store 0x69 (i) in UART0+0
    13/i 0/subop 6/rd 0/rs 69/imm12
    23/s 2/subop 5/rs2 6/rs1 0/off12
    # store 0x0a (\n) in UART0+0
    13/i 0/subop 6/rd 0/rs 0a/imm12
    23/s 2/subop 5/rs2 6/rs1 0/off12
    # jump back up to the top
    6f/j 0/4d main/off21

`ex.survey`: references resolved and labels removed

    == code 0x80000000
    # repeatedly print "Hi\n"
    # main:
    # load 0x10010000 (UART0) into t0
    37/u 05/rd 10010/imm20
    # store 0x48 (H) in UART0+0
    13/i 0/subop 6/rd 0/rs 48/imm12
    23/s 2/subop 5/rs2 6/rs1 0/off12
    # store 0x69 (i) in UART0+0
    13/i 0/subop 6/rd 0/rs 69/imm12
    23/s 2/subop 5/rs2 6/rs1 0/off12
    # store 0x0a (\n) in UART0+0
    13/i 0/subop 6/rd 0/rs 0a/imm12
    23/s 2/subop 5/rs2 6/rs1 0/off12
    # jump back up to the top
    6f/j 0/4d fffe4/off21

`ex.format`: arguments sliced and diced and put into the ISA order.

    == code 0x80000000
    # repeatedly print "Hi\n"
    # main:
    # load 0x10010000 (UART0) into t0
    37/7 05/5 10010/20
    # store 0x48 (H) in UART0+0
    13/7 06/5 00/3 00/5 48/12
    23/7 00/5 02/3 05/5 06/5 00/7
    # store 0x69 (i) in UART0+0
    13/7 06/5 00/3 00/5 69/12
    23/7 00/5 02/3 05/5 06/5 00/7
    # store 0x0a (\n) in UART0+0
    13/7 06/5 00/3 00/5 0a/12
    23/7 00/5 02/3 05/5 06/5 00/7
    # jump back up to the top
    6f/7 00/5 ff/8 01/1 3f2/10 01/1

`ex.pack`: fully packed, ready to run bare-metal

    == code 0x80000000
    # repeatedly print "Hi\n"
    # main:
    # load 0x10010000 (UART0) into t0
    b7 02 01 10
    # store 0x48 (H) in UART0+0
    13 03 80 04
    23 a0 62 00
    # store 0x69 (i) in UART0+0
    13 03 90 06
    23 a0 62 00
    # store 0x0a (\n) in UART0+0
    13 03 a0 00
    23 a0 62 00
    # jump back up to the top
    6f f0 5f fe

`ex.elf`: binary file for use with `qemu` (see next section).

## Debugging

You can hook gdb into `qemu` using the `-s` flag, and make it halt on start
using the `-S` flag. `gdb` can be attached using `target remote localhost:1234`:

    $ ./qemu.sh out.elf -S -s
    # in another terminal
    $ riscv32-elf-gdb -iex "target remote localhost:1234"
    layout asm # show assembly trace
    nexti      # step forward one instruction
    c          # free-run forward

[mu]: https://github.com/akkartik/mu