50 lines
1.5 KiB
Markdown
50 lines
1.5 KiB
Markdown
# Phase 8.2 - First GCC Program
|
|
|
|
## Context
|
|
|
|
The first compiled program proves your hardware can execute compiler-generated code, not
|
|
just carefully hand-authored assembly.
|
|
|
|
## Goals
|
|
|
|
- Compile a tiny C firmware for `rv32im`.
|
|
- Convert the ELF into a memory image.
|
|
- Print through UART MMIO from C.
|
|
|
|
## New Concepts
|
|
|
|
- `-march`: compiler ISA target string.
|
|
- `-mabi`: ABI selection, here `ilp32` for 32-bit integer/long/pointer.
|
|
- objcopy: tool that converts ELF into raw binary or other formats.
|
|
- Disassembly: readable assembly representation of generated machine code.
|
|
|
|
## How To Think About It
|
|
|
|
Treat the compiler as an external producer of instructions. Your job is to verify that
|
|
every emitted instruction is implemented or fails loudly.
|
|
|
|
## Learning Tasks
|
|
|
|
- Compare C source to generated assembly.
|
|
- Identify every load/store used for UART access.
|
|
- Confirm no CSR or `fence.i` instructions appear before Phase 12.
|
|
|
|
## Pitfalls
|
|
|
|
- Using the wrong `-march` and accidentally generating unsupported instructions.
|
|
- Forgetting `volatile` on MMIO accesses in firmware.
|
|
- Assuming the compiler will preserve simple-looking loops exactly.
|
|
|
|
## Tooling And Testing
|
|
|
|
- Always inspect early firmware with objdump.
|
|
- Build at low optimization first, then compare optimized output later.
|
|
- Keep firmware small enough to single-step mentally.
|
|
|
|
## References
|
|
|
|
- GCC RISC-V options: https://gcc.gnu.org/onlinedocs/gcc/RISC-V-Options.html
|
|
- RISC-V ELF psABI: https://github.com/riscv-non-isa/riscv-elf-psabi-doc
|
|
- GNU objcopy: https://sourceware.org/binutils/docs/binutils/objcopy.html
|
|
|