We are currently in the process of converting the website to the new design. Some pages, like this one, are still broken. We appreciate your patience.
Bitwise»Episode Guide
RISC-V Dynamic Assembler
?
?

Keyboard Navigation

Global Keys

[, < / ], > Jump to previous / next episode
W, K, P / S, J, N Jump to previous / next marker
t / T Toggle theatre / SUPERtheatre mode
V Revert filter to original state Y Select link (requires manual Ctrl-c)

Menu toggling

q Quotes r References f Filter y Link c Credits

In-Menu Movement

a
w
s
d
h j k l


Quotes and References Menus

Enter Jump to timecode

Quotes, References and Credits Menus

o Open URL (in new tab)

Filter Menu

x, Space Toggle category and focus next
X, ShiftSpace Toggle category and focus previous
v Invert topics / media as per focus

Filter and Link Menus

z Toggle filter / linking mode

Credits Menu

Enter Open URL (in new tab)
0:08Recap and set the stage for the day
🗩
0:08Recap and set the stage for the day
🗩
0:08Recap and set the stage for the day
🗩
1:38Review the new bits() function to replace the old ad hoc bit manipulation1
📖
1:38Review the new bits() function to replace the old ad hoc bit manipulation1
📖
1:38Review the new bits() function to replace the old ad hoc bit manipulation1
📖
7:56Review step() with a note that the encoding and decoding of instructions are performed separately
📖
7:56Review step() with a note that the encoding and decoding of instructions are performed separately
📖
7:56Review step() with a note that the encoding and decoding of instructions are performed separately
📖
9:35Review encode_instruction() with a few words on software vs hardware decoding2
📖
9:35Review encode_instruction() with a few words on software vs hardware decoding2
📖
9:35Review encode_instruction() with a few words on software vs hardware decoding2
📖
16:11A few words on the benefit of writing the encoder and decoder independently
🗩
16:11A few words on the benefit of writing the encoder and decoder independently
🗩
16:11A few words on the benefit of writing the encoder and decoder independently
🗩
16:59Review the test code for the encoder and decoder
📖
16:59Review the test code for the encoder and decoder
📖
16:59Review the test code for the encoder and decoder
📖
21:49Review the test code for the simulator
📖
21:49Review the test code for the simulator
📖
21:49Review the test code for the simulator
📖
22:42Run the simulator
🏃
22:42Run the simulator
🏃
22:42Run the simulator
🏃
23:24Setup to start writing the main assembler
🗩
23:24Setup to start writing the main assembler
🗩
23:24Setup to start writing the main assembler
🗩
24:59Q&A
🗩
24:59Q&A
🗩
24:59Q&A
🗩
25:29nxsy Hyper-relevant question: Why Hart?
🗪
25:29nxsy Hyper-relevant question: Why Hart?
🗪
25:29nxsy Hyper-relevant question: Why Hart?
🗪
26:26Static assembler
🗩
26:26Static assembler
🗩
26:26Static assembler
🗩
28:45rygorous Am I the only one who hears that weird audio interference thing?
🗪
28:45rygorous Am I the only one who hears that weird audio interference thing?
🗪
28:45rygorous Am I the only one who hears that weird audio interference thing?
🗪
29:41Static assembler, continued
🗩
29:41Static assembler, continued
🗩
29:41Static assembler, continued
🗩
30:53Dynamic assembler
🗩
30:53Dynamic assembler
🗩
30:53Dynamic assembler
🗩
35:35Data labels3
🗩
35:35Data labels3
🗩
35:35Data labels3
🗩
40:38Instruction labels4
🗩
40:38Instruction labels4
🗩
40:38Instruction labels4
🗩
43:50Handling of instruction labels by static vs dynamic assemblers
🗩
43:50Handling of instruction labels by static vs dynamic assemblers
🗩
43:50Handling of instruction labels by static vs dynamic assemblers
🗩
47:58Multi-pass vs back-patching assembling
🗩
47:58Multi-pass vs back-patching assembling
🗩
47:58Multi-pass vs back-patching assembling
🗩
49:57Q&A
🗩
49:57Q&A
🗩
49:57Q&A
🗩
50:18dghelneshi I imagine this is very difficult for variable length encodings since you can't know where the labels are without encoding the instructions which you can't encode (optimally) without knowing how far away the label is
🗪
50:18dghelneshi I imagine this is very difficult for variable length encodings since you can't know where the labels are without encoding the instructions which you can't encode (optimally) without knowing how far away the label is
🗪
50:18dghelneshi I imagine this is very difficult for variable length encodings since you can't know where the labels are without encoding the instructions which you can't encode (optimally) without knowing how far away the label is
🗪
51:42rygorous You don't need to do a full pass
🗪
51:42rygorous You don't need to do a full pass
🗪
51:42rygorous You don't need to do a full pass
🗪
52:28Dive into writing our back-patching dynamic assembler, introducing Asm struct and def_byte(), def_half(), def_word(), def_bytes(), def_str() and check_overflow()
52:28Dive into writing our back-patching dynamic assembler, introducing Asm struct and def_byte(), def_half(), def_word(), def_bytes(), def_str() and check_overflow()
52:28Dive into writing our back-patching dynamic assembler, introducing Asm struct and def_byte(), def_half(), def_word(), def_bytes(), def_str() and check_overflow()
1:02:51Introduce Reg enum, using uint8 as the storage type
1:02:51Introduce Reg enum, using uint8 as the storage type
1:02:51Introduce Reg enum, using uint8 as the storage type
1:05:12Introduce emit_instr() and emission functions for add(), addi() and slli(), renaming the previous def_ functions to emit_*
1:05:12Introduce emit_instr() and emission functions for add(), addi() and slli(), renaming the previous def_ functions to emit_*
1:05:12Introduce emit_instr() and emission functions for add(), addi() and slli(), renaming the previous def_ functions to emit_*
1:10:44Introduce init_asm() and test our assembler
1:10:44Introduce init_asm() and test our assembler
1:10:44Introduce init_asm() and test our assembler
1:12:47Run it to see that it works
🏃
1:12:47Run it to see that it works
🏃
1:12:47Run it to see that it works
🏃
1:13:10Create instruction labels, introducing new_sym(), set_sym_here(), new_sym_here() and related structs
1:13:10Create instruction labels, introducing new_sym(), set_sym_here(), new_sym_here() and related structs
1:13:10Create instruction labels, introducing new_sym(), set_sym_here(), new_sym_here() and related structs
1:29:43Introduce emit_lw() to emit a load global instruction, and emit_auipc() and emit_lw_reg()5
1:29:43Introduce emit_lw() to emit a load global instruction, and emit_auipc() and emit_lw_reg()5
1:29:43Introduce emit_lw() to emit a load global instruction, and emit_auipc() and emit_lw_reg()5
1:36:11Test our label emission, also introducing get_sym_addr() for emit_lw() to call
1:36:11Test our label emission, also introducing get_sym_addr() for emit_lw() to call
1:36:11Test our label emission, also introducing get_sym_addr() for emit_lw() to call
1:39:34Step through new_sym() to see what it produces, and that we may not be sign-extending correctly
🏃
1:39:34Step through new_sym() to see what it produces, and that we may not be sign-extending correctly
🏃
1:39:34Step through new_sym() to see what it produces, and that we may not be sign-extending correctly
🏃
1:44:58Conditional sign-extension of immediates
🗩
1:44:58Conditional sign-extension of immediates
🗩
1:44:58Conditional sign-extension of immediates
🗩
1:49:02Introduce imm_hi() and imm_lo(), and make emit_lw() use imm_lo() in its call to emit_lw_reg()
1:49:02Introduce imm_hi() and imm_lo(), and make emit_lw() use imm_lo() in its call to emit_lw_reg()
1:49:02Introduce imm_hi() and imm_lo(), and make emit_lw() use imm_lo() in its call to emit_lw_reg()
1:51:25Run it to see that it works
🏃
1:51:25Run it to see that it works
🏃
1:51:25Run it to see that it works
🏃
1:52:23Q&A
🗩
1:52:23Q&A
🗩
1:52:23Q&A
🗩
1:52:36miotatsu pervognsen ((VALUE + 0x800) & HI20_MASK >> 12) & LO20_MASK, I don't think & with HI20_MASK is actually necessary(?) but I believe the LO20_MASK would handle the >> 12 doing an arithmetic right shift if the high bits ended up set
🗪
1:52:36miotatsu pervognsen ((VALUE + 0x800) & HI20_MASK >> 12) & LO20_MASK, I don't think & with HI20_MASK is actually necessary(?) but I believe the LO20_MASK would handle the >> 12 doing an arithmetic right shift if the high bits ended up set
🗪
1:52:36miotatsu pervognsen ((VALUE + 0x800) & HI20_MASK >> 12) & LO20_MASK, I don't think & with HI20_MASK is actually necessary(?) but I believe the LO20_MASK would handle the >> 12 doing an arithmetic right shift if the high bits ended up set
🗪
1:52:52Change imm_hi() to straight up return imm + 0x800
1:52:52Change imm_hi() to straight up return imm + 0x800
1:52:52Change imm_hi() to straight up return imm + 0x800
1:53:20Run it to see that this works, and explain why
🏃
1:53:20Run it to see that this works, and explain why
🏃
1:53:20Run it to see that this works, and explain why
🏃
1:55:48Try doing a load of emit_uint32() to test this imm_hi()
1:55:48Try doing a load of emit_uint32() to test this imm_hi()
1:55:48Try doing a load of emit_uint32() to test this imm_hi()
1:56:12Run it to see that this doesn't work
🏃
1:56:12Run it to see that this doesn't work
🏃
1:56:12Run it to see that this doesn't work
🏃
1:56:28Revert imm_hi() to the old bit-shifting version
1:56:28Revert imm_hi() to the old bit-shifting version
1:56:28Revert imm_hi() to the old bit-shifting version
1:57:17Run it to see the same buggy result
🏃
1:57:17Run it to see the same buggy result
🏃
1:57:17Run it to see the same buggy result
🏃
1:57:58Try emitting fewer instructions, to try and determine where it breaks
🏃
🖮
1:57:58Try emitting fewer instructions, to try and determine where it breaks
🏃
🖮
1:57:58Try emitting fewer instructions, to try and determine where it breaks
🏃
🖮
1:59:28binjimin The sign-extension of the 12-bit immediate either produces 0 or -1 in the top 20 bits, so you need to add 0 or 1 to the top bits to counteract it
🗪
1:59:28binjimin The sign-extension of the 12-bit immediate either produces 0 or -1 in the top 20 bits, so you need to add 0 or 1 to the top bits to counteract it
🗪
1:59:28binjimin The sign-extension of the 12-bit immediate either produces 0 or -1 in the top 20 bits, so you need to add 0 or 1 to the top bits to counteract it
🗪
2:00:08Scour the code for the culprit
2:00:08Scour the code for the culprit
2:00:08Scour the code for the culprit
2:01:11Make imm_hi() return imm + 0x800
2:01:11Make imm_hi() return imm + 0x800
2:01:11Make imm_hi() return imm + 0x800
2:02:09Step in to emit_lw() and spot that the addr was at the max capacity of our RAM
2:02:09Step in to emit_lw() and spot that the addr was at the max capacity of our RAM
2:02:09Step in to emit_lw() and spot that the addr was at the max capacity of our RAM
2:02:50Add more RAM
2:02:50Add more RAM
2:02:50Add more RAM
2:03:18Run it to see that this totally works
🏃
2:03:18Run it to see that this totally works
🏃
2:03:18Run it to see that this totally works
🏃
2:04:10Make check_overflow() assert on a bounds-checking failure
2:04:10Make check_overflow() assert on a bounds-checking failure
2:04:10Make check_overflow() assert on a bounds-checking failure
2:04:18Run it with a smaller amount of RAM, and hit that assertion
🏃
2:04:18Run it with a smaller amount of RAM, and hit that assertion
🏃
2:04:18Run it with a smaller amount of RAM, and hit that assertion
🏃
2:04:39Cut over to the extra stream
🗩
2:04:39Cut over to the extra stream
🗩
2:04:39Cut over to the extra stream
🗩