Skip to content

Commit 8baa254

Browse files
committed
move all assembly to asm.rs
1 parent e80d5cc commit 8baa254

File tree

5 files changed

+183
-215
lines changed

5 files changed

+183
-215
lines changed

.github/workflows/riscv-rt.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
on:
22
push:
3-
branches: [ master ]
3+
branches: [ master, riscv-rt-asm ]
44
pull_request:
55
merge_group:
66

riscv-rt/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
2727

2828
### Changed
2929

30+
- Removed _start_rust. Now, assembly directly jumps to main
3031
- Removed U-mode interrupts to align with latest RISC-V specification
3132
- Changed `Vector` union. Now, it uses `Option<fn>`, which is more idiomatic in Rust
3233
- Removed riscv-target dependency for build

riscv-rt/macros/src/lib.rs

Lines changed: 62 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -212,46 +212,59 @@ pub fn pre_init(args: TokenStream, input: TokenStream) -> TokenStream {
212212

213213
struct AsmLoopArgs {
214214
asm_template: String,
215-
count: usize,
215+
count_from: usize,
216+
count_to: usize,
216217
}
217218

218219
impl Parse for AsmLoopArgs {
219220
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
220221
let template: LitStr = input.parse().unwrap();
221222
_ = input.parse::<Token![,]>().unwrap();
222223
let count: LitInt = input.parse().unwrap();
223-
224-
Ok(Self {
225-
asm_template: template.value(),
226-
count: count.base10_parse().unwrap(),
227-
})
224+
if input.parse::<Token![,]>().is_ok() {
225+
let count_to: LitInt = input.parse().unwrap();
226+
Ok(Self {
227+
asm_template: template.value(),
228+
count_from: count.base10_parse().unwrap(),
229+
count_to: count_to.base10_parse().unwrap(),
230+
})
231+
} else {
232+
Ok(Self {
233+
asm_template: template.value(),
234+
count_from: 0,
235+
count_to: count.base10_parse().unwrap(),
236+
})
237+
}
228238
}
229239
}
230240

231241
/// Loops an asm expression n times.
232242
///
233-
/// `loop_asm!` takes 2 arguments, the first is a string literal and the second is a number literal
234-
/// See [the formatting syntax documentation in `std::fmt`](../std/fmt/index.html)
235-
/// for details.
243+
/// `loop_asm!` takes 2 or 3 arguments, the first is a string literal and the rest are a number literal
244+
/// See [the formatting syntax documentation in `std::fmt`](../std/fmt/index.html) for details.
236245
///
237246
/// Argument 1 is an assembly expression, all "{}" in this assembly expression will be replaced with the
238247
/// current loop index.
239248
///
240-
/// Argument 2 is the number of loops to do with the provided expression.
249+
/// If 2 arguments are provided, the loop will start at 0 and end at the number provided in argument 2.
250+
///
251+
/// If 3 arguments are provided, the loop will start at the number provided in argument 2 and end at
252+
/// the number provided in argument 3.
241253
///
242254
/// # Examples
243255
///
244256
/// ```
245257
/// # use riscv_rt_macros::loop_asm;
246258
/// unsafe {
247259
/// loop_asm!("fmv.w.x f{}, x0", 32); // => core::arch::asm!("fmv.w.x f0, x0") ... core::arch::asm!("fmv.w.x f31, x0")
260+
/// loop_asm!("fmv.w.x f{}, x0", 1, 32); // => core::arch::asm!("fmv.w.x f1, x0") ... core::arch::asm!("fmv.w.x f31, x0")
248261
/// }
249262
/// ```
250263
#[proc_macro]
251264
pub fn loop_asm(input: TokenStream) -> TokenStream {
252265
let args = parse_macro_input!(input as AsmLoopArgs);
253266

254-
let tokens = (0..args.count)
267+
let tokens = (args.count_from..args.count_to)
255268
.map(|i| {
256269
let i = i.to_string();
257270
let asm = args.asm_template.replace("{}", &i);
@@ -261,3 +274,41 @@ pub fn loop_asm(input: TokenStream) -> TokenStream {
261274
.join("\n");
262275
tokens.parse().unwrap()
263276
}
277+
278+
/// Loops a global_asm expression n times.
279+
///
280+
/// `loop_global_asm!` takes 2 or 3 arguments, the first is a string literal and the rest are a number literal
281+
/// See [the formatting syntax documentation in `std::fmt`](../std/fmt/index.html) for details.
282+
///
283+
/// Argument 1 is an assembly expression, all "{}" in this assembly expression will be replaced with the
284+
/// current loop index.
285+
///
286+
/// If 2 arguments are provided, the loop will start at 0 and end at the number provided in argument 2.
287+
///
288+
/// If 3 arguments are provided, the loop will start at the number provided in argument 2 and end at
289+
/// the number provided in argument 3.
290+
///
291+
/// # Examples
292+
///
293+
/// ```
294+
/// # use riscv_rt_macros::loop_global_asm;
295+
/// unsafe {
296+
/// loop_global_asm!("fmv.w.x f{}, x0", 32); // => core::arch::global_asm!("fmv.w.x f0, x0") ... core::arch::global_asm!("fmv.w.x f31, x0")
297+
/// loop_global_asm!("fmv.w.x f{}, x0", 1, 32); // => core::arch::global_asm!("fmv.w.x f1, x0") ... core::arch::global_asm!("fmv.w.x f31, x0")
298+
/// }
299+
/// ```
300+
#[proc_macro]
301+
pub fn loop_global_asm(input: TokenStream) -> TokenStream {
302+
let args = parse_macro_input!(input as AsmLoopArgs);
303+
304+
let instructions = (args.count_from..args.count_to)
305+
.map(|i| {
306+
let i = i.to_string();
307+
args.asm_template.replace("{}", &i)
308+
})
309+
.collect::<Vec<String>>()
310+
.join("\n");
311+
312+
let res = format!("core::arch::global_asm!(\n\"{}\"\n);", instructions);
313+
res.parse().unwrap()
314+
}

riscv-rt/src/asm.rs

Lines changed: 119 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -72,54 +72,36 @@ _abs_start:
7272
#[cfg(not(feature = "s-mode"))]
7373
"csrw mie, 0
7474
csrw mip, 0",
75-
"li x1, 0
76-
li x2, 0
77-
li x3, 0
78-
li x4, 0
79-
li x5, 0
80-
li x6, 0
81-
li x7, 0
82-
li x8, 0
83-
li x9, 0
84-
// a0..a2 (x10..x12) skipped
85-
li x13, 0
86-
li x14, 0
87-
li x15, 0
88-
li x16, 0
89-
li x17, 0
90-
li x18, 0
91-
li x19, 0
92-
li x20, 0
93-
li x21, 0
94-
li x22, 0
95-
li x23, 0
96-
li x24, 0
97-
li x25, 0
98-
li x26, 0
99-
li x27, 0
100-
li x28, 0
101-
li x29, 0
102-
li x30, 0
103-
li x31, 0
75+
);
76+
77+
// ZERO OUT GENERAL-PURPOSE REGISTERS
78+
riscv_rt_macros::loop_global_asm!(" li x{}, 0", 1, 10);
79+
// a0..a2 (x10..x12) skipped
80+
riscv_rt_macros::loop_global_asm!(" li x{}, 0", 13, 32);
10481

105-
.option push
82+
// INITIALIZE GLOBAL POINTER
83+
cfg_global_asm!(
84+
".option push
10685
.option norelax
10786
la gp, __global_pointer$
108-
.option pop
109-
// Allocate stacks",
110-
#[cfg(all(not(feature = "single-hart"), feature = "s-mode"))]
87+
.option pop",
88+
);
89+
90+
// INITIALIZE STACK POINTER AND FRAME POINTER
91+
#[cfg(not(feature = "single-hart"))]
92+
cfg_global_asm!(
93+
#[cfg(feature = "s-mode")]
11194
"mv t2, a0 // the hartid is passed as parameter by SMODE",
112-
#[cfg(all(not(feature = "single-hart"), not(feature = "s-mode")))]
95+
#[cfg(not(feature = "s-mode"))]
11396
"csrr t2, mhartid",
114-
#[cfg(not(feature = "single-hart"))]
11597
"lui t0, %hi(_max_hart_id)
11698
add t0, t0, %lo(_max_hart_id)
11799
bgtu t2, t0, abort
118100
lui t0, %hi(_hart_stack_size)
119101
add t0, t0, %lo(_hart_stack_size)",
120-
#[cfg(all(not(feature = "single-hart"), riscvm))]
102+
#[cfg(riscvm)]
121103
"mul t0, t2, t0",
122-
#[cfg(all(not(feature = "single-hart"), not(riscvm)))]
104+
#[cfg(not(riscvm))]
123105
"beqz t2, 2f // Jump if single-hart
124106
mv t1, t2
125107
mv t3, t0
@@ -129,14 +111,109 @@ _abs_start:
129111
bnez t1, 1b
130112
2: ",
131113
"la t1, _stack_start",
132-
#[cfg(not(feature = "single-hart"))]
133114
"sub t1, t1, t0",
134-
"andi sp, t1, -16 // Force 16-byte alignment
135-
// Set frame pointer
136-
add s0, sp, zero
115+
);
116+
cfg_global_asm!(
117+
"andi sp, t1, -16 // align stack to 16-bytes
118+
add s0, sp, zero",
119+
);
120+
121+
// STORE A0..A2 IN THE STACK, AS THEY WILL BE NEEDED LATER BY main
122+
cfg_global_asm!(
123+
#[cfg(riscv32)]
124+
"addi sp, sp, -4 * 3
125+
sw a0, 4 * 0(sp)
126+
sw a1, 4 * 1(sp)
127+
sw a2, 4 * 2(sp)",
128+
#[cfg(riscv64)]
129+
"addi sp, sp, -8 * 3
130+
sd a0, 8 * 0(sp)
131+
sd a1, 8 * 1(sp)
132+
sd a2, 8 * 2(sp)",
133+
);
137134

138-
jal zero, _start_rust
135+
// SKIP RAM INITIALIZATION IF CURRENT HART IS NOT THE BOOT HART
136+
#[cfg(not(feature = "single-hart"))]
137+
cfg_global_asm!(
138+
#[cfg(not(feature = "s-mode"))]
139+
"csrr a0, mhartid",
140+
"call _mp_hook
141+
mv t0, a0
142+
143+
beqz a0, 4f",
144+
);
145+
// IF CURRENT HART IS THE BOOT HART CALL __pre_init AND INITIALIZE RAM
146+
cfg_global_asm!(
147+
"call __pre_init
148+
// Copy .data from flash to RAM
149+
la t0, _sdata
150+
la t2, _edata
151+
la t1, _sidata
152+
bgeu t0, t2, 2f
153+
1: ",
154+
#[cfg(target_arch = "riscv32")]
155+
"lw t3, 0(t1)
156+
addi t1, t1, 4
157+
sw t3, 0(t0)
158+
addi t0, t0, 4
159+
bltu t0, t2, 1b",
160+
#[cfg(target_arch = "riscv64")]
161+
"ld t3, 0(t1)
162+
addi t1, t1, 8
163+
sd t3, 0(t0)
164+
addi t0, t0, 8
165+
bltu t0, t2, 1b",
166+
"
167+
2: // Zero out .bss
168+
la t0, _sbss
169+
la t2, _ebss
170+
bgeu t0, t2, 4f
171+
3: ",
172+
#[cfg(target_arch = "riscv32")]
173+
"sw zero, 0(t0)
174+
addi t0, t0, 4
175+
bltu t0, t2, 3b",
176+
#[cfg(target_arch = "riscv64")]
177+
"sd zero, 0(t0)
178+
addi t0, t0, 8
179+
bltu t0, t2, 3b",
180+
"
181+
4: // RAM initilized",
182+
);
139183

184+
// INITIALIZE FLOATING POINT UNIT
185+
#[cfg(any(riscvf, riscvd))]
186+
cfg_global_asm!(
187+
#[cfg(feature = "s-mode")]
188+
"csrrc x0, sstatus, 0x4000
189+
csrrs x0, sstatus, 0x2000",
190+
#[cfg(not(feature = "s-mode"))]
191+
"csrrc x0, mstatus, 0x4000
192+
csrrs x0, mstatus, 0x2000",
193+
"fscsr x0",
194+
);
195+
// ZERO OUT FLOATING POINT REGISTERS
196+
#[cfg(all(riscv32, riscvd))]
197+
riscv_rt_macros::loop_global_asm!(" fcvt.d.w f{}, x0", 32);
198+
#[cfg(all(riscv64, riscvd))]
199+
riscv_rt_macros::loop_global_asm!(" fmv.d.x f{}, x0", 32);
200+
#[cfg(all(riscvf, not(riscvd)))]
201+
riscv_rt_macros::loop_global_asm!(" fmv.w.x f{}, x0", 32);
202+
203+
// SET UP INTERRUPTS, RESTORE a0..a2, AND JUMP TO MAIN RUST FUNCTION
204+
cfg_global_asm!(
205+
"call _setup_interrupts",
206+
#[cfg(riscv32)]
207+
"lw a0, 4 * 0(sp)
208+
lw a1, 4 * 1(sp)
209+
lw a2, 4 * 2(sp)
210+
addi sp, sp, 4 * 3",
211+
#[cfg(riscv64)]
212+
"ld a0, 8 * 0(sp)
213+
ld a1, 8 * 1(sp)
214+
ld a2, 8 * 2(sp)
215+
addi sp, sp, 8 * 3",
216+
"jal zero, main
140217
.cfi_endproc",
141218
);
142219

0 commit comments

Comments
 (0)