Skip to content

Commit f3e755e

Browse files
committed
move all assembly to asm.rs
1 parent d9b9df3 commit f3e755e

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
@@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1818

1919
### Changed
2020

21+
- Removed _start_rust. Now, assembly directly jumps to main
2122
- Removed U-mode interrupts to align with latest RISC-V specification
2223
- Changed `Vector` union. Now, it uses `Option<fn>`, which is more idiomatic in Rust
2324
- 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
@@ -52,54 +52,36 @@ _abs_start:
5252
#[cfg(not(feature = "s-mode"))]
5353
"csrw mie, 0
5454
csrw mip, 0",
55-
"li x1, 0
56-
li x2, 0
57-
li x3, 0
58-
li x4, 0
59-
li x5, 0
60-
li x6, 0
61-
li x7, 0
62-
li x8, 0
63-
li x9, 0
64-
// a0..a2 (x10..x12) skipped
65-
li x13, 0
66-
li x14, 0
67-
li x15, 0
68-
li x16, 0
69-
li x17, 0
70-
li x18, 0
71-
li x19, 0
72-
li x20, 0
73-
li x21, 0
74-
li x22, 0
75-
li x23, 0
76-
li x24, 0
77-
li x25, 0
78-
li x26, 0
79-
li x27, 0
80-
li x28, 0
81-
li x29, 0
82-
li x30, 0
83-
li x31, 0
55+
);
56+
57+
// ZERO OUT GENERAL-PURPOSE REGISTERS
58+
riscv_rt_macros::loop_global_asm!(" li x{}, 0", 1, 10);
59+
// a0..a2 (x10..x12) skipped
60+
riscv_rt_macros::loop_global_asm!(" li x{}, 0", 13, 32);
8461

85-
.option push
62+
// INITIALIZE GLOBAL POINTER
63+
cfg_global_asm!(
64+
".option push
8665
.option norelax
8766
la gp, __global_pointer$
88-
.option pop
89-
// Allocate stacks",
90-
#[cfg(all(not(feature = "single-hart"), feature = "s-mode"))]
67+
.option pop",
68+
);
69+
70+
// INITIALIZE STACK POINTER AND FRAME POINTER
71+
#[cfg(not(feature = "single-hart"))]
72+
cfg_global_asm!(
73+
#[cfg(feature = "s-mode")]
9174
"mv t2, a0 // the hartid is passed as parameter by SMODE",
92-
#[cfg(all(not(feature = "single-hart"), not(feature = "s-mode")))]
75+
#[cfg(not(feature = "s-mode"))]
9376
"csrr t2, mhartid",
94-
#[cfg(not(feature = "single-hart"))]
9577
"lui t0, %hi(_max_hart_id)
9678
add t0, t0, %lo(_max_hart_id)
9779
bgtu t2, t0, abort
9880
lui t0, %hi(_hart_stack_size)
9981
add t0, t0, %lo(_hart_stack_size)",
100-
#[cfg(all(not(feature = "single-hart"), riscvm))]
82+
#[cfg(riscvm)]
10183
"mul t0, t2, t0",
102-
#[cfg(all(not(feature = "single-hart"), not(riscvm)))]
84+
#[cfg(not(riscvm))]
10385
"beqz t2, 2f // Jump if single-hart
10486
mv t1, t2
10587
mv t3, t0
@@ -109,14 +91,109 @@ _abs_start:
10991
bnez t1, 1b
11092
2: ",
11193
"la t1, _stack_start",
112-
#[cfg(not(feature = "single-hart"))]
11394
"sub t1, t1, t0",
114-
"andi sp, t1, -16 // Force 16-byte alignment
115-
// Set frame pointer
116-
add s0, sp, zero
95+
);
96+
cfg_global_asm!(
97+
"andi sp, t1, -16 // align stack to 16-bytes
98+
add s0, sp, zero",
99+
);
100+
101+
// STORE A0..A2 IN THE STACK, AS THEY WILL BE NEEDED LATER BY main
102+
cfg_global_asm!(
103+
#[cfg(riscv32)]
104+
"addi sp, sp, -4 * 3
105+
sw a0, 4 * 0(sp)
106+
sw a1, 4 * 1(sp)
107+
sw a2, 4 * 2(sp)",
108+
#[cfg(riscv64)]
109+
"addi sp, sp, -8 * 3
110+
sd a0, 8 * 0(sp)
111+
sd a1, 8 * 1(sp)
112+
sd a2, 8 * 2(sp)",
113+
);
117114

118-
jal zero, _start_rust
115+
// SKIP RAM INITIALIZATION IF CURRENT HART IS NOT THE BOOT HART
116+
#[cfg(not(feature = "single-hart"))]
117+
cfg_global_asm!(
118+
#[cfg(not(feature = "s-mode"))]
119+
"csrr a0, mhartid",
120+
"call _mp_hook
121+
mv t0, a0
122+
123+
beqz a0, 4f",
124+
);
125+
// IF CURRENT HART IS THE BOOT HART CALL __pre_init AND INITIALIZE RAM
126+
cfg_global_asm!(
127+
"call __pre_init
128+
// Copy .data from flash to RAM
129+
la t0, _sdata
130+
la t2, _edata
131+
la t1, _sidata
132+
bgeu t0, t2, 2f
133+
1: ",
134+
#[cfg(target_arch = "riscv32")]
135+
"lw t3, 0(t1)
136+
addi t1, t1, 4
137+
sw t3, 0(t0)
138+
addi t0, t0, 4
139+
bltu t0, t2, 1b",
140+
#[cfg(target_arch = "riscv64")]
141+
"ld t3, 0(t1)
142+
addi t1, t1, 8
143+
sd t3, 0(t0)
144+
addi t0, t0, 8
145+
bltu t0, t2, 1b",
146+
"
147+
2: // Zero out .bss
148+
la t0, _sbss
149+
la t2, _ebss
150+
bgeu t0, t2, 4f
151+
3: ",
152+
#[cfg(target_arch = "riscv32")]
153+
"sw zero, 0(t0)
154+
addi t0, t0, 4
155+
bltu t0, t2, 3b",
156+
#[cfg(target_arch = "riscv64")]
157+
"sd zero, 0(t0)
158+
addi t0, t0, 8
159+
bltu t0, t2, 3b",
160+
"
161+
4: // RAM initilized",
162+
);
119163

164+
// INITIALIZE FLOATING POINT UNIT
165+
#[cfg(any(riscvf, riscvd))]
166+
cfg_global_asm!(
167+
#[cfg(feature = "s-mode")]
168+
"csrrc x0, sstatus, 0x4000
169+
csrrs x0, sstatus, 0x2000",
170+
#[cfg(not(feature = "s-mode"))]
171+
"csrrc x0, mstatus, 0x4000
172+
csrrs x0, mstatus, 0x2000",
173+
"fscsr x0",
174+
);
175+
// ZERO OUT FLOATING POINT REGISTERS
176+
#[cfg(all(riscv32, riscvd))]
177+
riscv_rt_macros::loop_global_asm!(" fcvt.d.w f{}, x0", 32);
178+
#[cfg(all(riscv64, riscvd))]
179+
riscv_rt_macros::loop_global_asm!(" fmv.d.x f{}, x0", 32);
180+
#[cfg(all(riscvf, not(riscvd)))]
181+
riscv_rt_macros::loop_global_asm!(" fmv.w.x f{}, x0", 32);
182+
183+
// SET UP INTERRUPTS, RESTORE a0..a2, AND JUMP TO MAIN RUST FUNCTION
184+
cfg_global_asm!(
185+
"call _setup_interrupts",
186+
#[cfg(riscv32)]
187+
"lw a0, 4 * 0(sp)
188+
lw a1, 4 * 1(sp)
189+
lw a2, 4 * 2(sp)
190+
addi sp, sp, 4 * 3",
191+
#[cfg(riscv64)]
192+
"ld a0, 8 * 0(sp)
193+
ld a1, 8 * 1(sp)
194+
ld a2, 8 * 2(sp)
195+
addi sp, sp, 8 * 3",
196+
"jal zero, main
120197
.cfi_endproc",
121198
);
122199

0 commit comments

Comments
 (0)