mirror of
https://github.com/xenia-project/xell-rs.git
synced 2024-11-23 11:29:43 +00:00
Latest updates
This commit is contained in:
parent
e64f5006ca
commit
91291912ae
@ -2,10 +2,11 @@
|
||||
[build]
|
||||
target = "powerpc64-unknown-linux-gnu"
|
||||
|
||||
[profile]
|
||||
[profile.release]
|
||||
incremental = false
|
||||
opt-level = "z"
|
||||
lto = true
|
||||
|
||||
[target.powerpc64-unknown-linux-gnu]
|
||||
linker = "rust-lld"
|
||||
rustflags = ["-C", "relocation-model=static"]
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
||||
.vscode/
|
||||
**/target
|
||||
|
15
.vscode/tasks.json
vendored
15
.vscode/tasks.json
vendored
@ -1,15 +0,0 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "cargo",
|
||||
"command": "build",
|
||||
"args": ["-Zextra-link-arg"],
|
||||
"problemMatcher": [
|
||||
"$rustc"
|
||||
],
|
||||
"group": "build",
|
||||
"label": "rust: cargo build"
|
||||
}
|
||||
]
|
||||
}
|
13
Cargo.lock
generated
13
Cargo.lock
generated
@ -79,11 +79,24 @@ name = "stage1"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"core_reqs",
|
||||
"xenon-cpu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "volatile"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4c2dbd44eb8b53973357e6e207e370f0c1059990df850aca1eca8947cf464f0"
|
||||
|
||||
[[package]]
|
||||
name = "xenon-cpu"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "xenon-enet"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"smoltcp",
|
||||
"volatile",
|
||||
"xenon-cpu",
|
||||
]
|
||||
|
@ -5,6 +5,7 @@ members = [
|
||||
"boot/stage1",
|
||||
"shared/core_reqs",
|
||||
"shared/display",
|
||||
"shared/xenon-cpu",
|
||||
"shared/xenon-enet",
|
||||
]
|
||||
|
||||
|
@ -7,8 +7,13 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
core_reqs = { path = "../../shared/core_reqs" }
|
||||
xenon-cpu = { path = "../../shared/xenon-cpu" }
|
||||
|
||||
[profile.dev]
|
||||
panic = "abort"
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
opt-level = "s"
|
||||
lto = true
|
||||
|
||||
|
@ -4,7 +4,7 @@ SECTIONS
|
||||
{
|
||||
. = 0x800000001c000000;
|
||||
|
||||
.text : {
|
||||
.text 0x800000001c000000 : {
|
||||
KEEP(*(.text.startup));
|
||||
*(.text .text.*);
|
||||
}
|
||||
@ -12,6 +12,15 @@ SECTIONS
|
||||
.sdata : { *(.sdata) }
|
||||
.rodata : { *(.rodata) }
|
||||
|
||||
.dynsym : { *(.dynsym) }
|
||||
.gnu.hash : { *(.gnu.hash) }
|
||||
.hash : { *(.hash) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.rela.dyn : { *(.rela.dyn) }
|
||||
.rela.opd : { *(.rela.opd) }
|
||||
.eh_frame_hdr : { *(.eh_frame_hdr) }
|
||||
.eh_frame : { *(.eh_frame) }
|
||||
|
||||
.got : {
|
||||
__toc_start = .;
|
||||
|
||||
@ -21,7 +30,7 @@ SECTIONS
|
||||
|
||||
. = ALIGN(256);
|
||||
__bss_start = .;
|
||||
.bss : { *(.bss .bss.*) }
|
||||
.bss (NOLOAD) : { *(.bss .bss.*) }
|
||||
.sbss : { *(.sbss .sbss.*) }
|
||||
__bss_end = .;
|
||||
}
|
||||
|
189
boot/stage1/src/except.rs
Normal file
189
boot/stage1/src/except.rs
Normal file
@ -0,0 +1,189 @@
|
||||
//! This module defines exception handlers.
|
||||
|
||||
use crate::iic::Iic;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[repr(u32)]
|
||||
enum ExceptionType {
|
||||
Reset = 1,
|
||||
MachineCheck = 2,
|
||||
Dsi = 3,
|
||||
Isi = 4,
|
||||
ExternalInterrupt = 5,
|
||||
Alignment = 6,
|
||||
Program = 7,
|
||||
Decrementer = 9,
|
||||
}
|
||||
|
||||
#[repr(C, align(4096))]
|
||||
#[derive(Copy, Clone)]
|
||||
struct CpuContext {
|
||||
r: [u64; 32],
|
||||
lr: u64,
|
||||
ctr: u64,
|
||||
srr0: u64,
|
||||
srr1: u64,
|
||||
}
|
||||
|
||||
impl CpuContext {
|
||||
const fn new() -> Self {
|
||||
Self {
|
||||
r: [0u64; 32],
|
||||
lr: 0,
|
||||
ctr: 0,
|
||||
srr0: 0,
|
||||
srr1: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
static mut EXCEPTION_SAVE_AREA: [CpuContext; 6] = [CpuContext::new(); 6];
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn except(id: ExceptionType, save_area: &mut CpuContext) {
|
||||
match id {
|
||||
ExceptionType::ExternalInterrupt => {
|
||||
let iic = unsafe { Iic::local() };
|
||||
}
|
||||
|
||||
_ => loop {}
|
||||
}
|
||||
|
||||
load_context(save_area);
|
||||
}
|
||||
|
||||
fn load_context(ctx: &CpuContext) -> ! {
|
||||
unsafe {
|
||||
asm!(
|
||||
"ld %r0, 256(%r4)",
|
||||
"mtlr %r0",
|
||||
"ld %r0, 264(%r4)",
|
||||
"mtctr %r0",
|
||||
"ld %r0, 272(%r4)",
|
||||
"mtsrr0 %r0",
|
||||
"ld %r0, 280(%r4)",
|
||||
"mtsrr1 %r0",
|
||||
"ld %r0, 0(%r4)",
|
||||
"ld %r1, 8(%r4)",
|
||||
"ld %r2, 16(%r4)",
|
||||
"ld %r3, 24(%r4)",
|
||||
"ld %r4, 32(%r4)",
|
||||
"ld %r5, 40(%r4)",
|
||||
"ld %r6, 48(%r4)",
|
||||
"ld %r7, 56(%r4)",
|
||||
"ld %r8, 64(%r4)",
|
||||
"ld %r9, 72(%r4)",
|
||||
"ld %r10, 80(%r4)",
|
||||
"ld %r11, 88(%r4)",
|
||||
"ld %r12, 96(%r4)",
|
||||
"ld %r13, 104(%r4)",
|
||||
"ld %r14, 112(%r4)",
|
||||
"ld %r15, 120(%r4)",
|
||||
"ld %r16, 128(%r4)",
|
||||
"ld %r17, 136(%r4)",
|
||||
"ld %r18, 144(%r4)",
|
||||
"ld %r19, 152(%r4)",
|
||||
"ld %r20, 160(%r4)",
|
||||
"ld %r21, 168(%r4)",
|
||||
"ld %r22, 176(%r4)",
|
||||
"ld %r23, 184(%r4)",
|
||||
"ld %r24, 192(%r4)",
|
||||
"ld %r25, 200(%r4)",
|
||||
"ld %r26, 208(%r4)",
|
||||
"ld %r27, 216(%r4)",
|
||||
"ld %r28, 224(%r4)",
|
||||
"ld %r29, 232(%r4)",
|
||||
"ld %r30, 240(%r4)",
|
||||
"ld %r31, 248(%r4)",
|
||||
"rfid",
|
||||
in("4") ctx,
|
||||
options(noreturn),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[naked]
|
||||
unsafe extern "C" fn except_thunk() {
|
||||
asm!(
|
||||
"mtctr %r4", // Reload CTR with original value
|
||||
"mfspr %r4, 1023", // r4 = PIR
|
||||
"sldi %r4, %r4, 32 + 12",
|
||||
"oris %r4, %r4, EXCEPTION_SAVE_AREA@highest",
|
||||
"ori %r4, %r4, EXCEPTION_SAVE_AREA@higher",
|
||||
"rldicr %r4, %r4, 32, 63",
|
||||
"oris %r4, %r4, EXCEPTION_SAVE_AREA@high",
|
||||
"ori %r4, %r4, EXCEPTION_SAVE_AREA@l",
|
||||
// Now save registers.
|
||||
"std %r0, 0(%r4)",
|
||||
"std %r1, 8(%r4)",
|
||||
"subi %r1, %r1, 0x100", // HACK: Subtract 0x100 bytes from r1 to reuse the stack.
|
||||
"std %r2, 16(%r4)",
|
||||
"mfspr %r0, 304", // Reload R3, which was saved in HPSRG0.
|
||||
"std %r0, 24(%r4)",
|
||||
"mfspr %r0, 305", // Reload R4, which was saved in HSPRG1.
|
||||
"std %r0, 32(%r4)",
|
||||
"std %r5, 40(%r4)",
|
||||
"std %r6, 48(%r4)",
|
||||
"std %r7, 56(%r4)",
|
||||
"std %r8, 64(%r4)",
|
||||
"std %r9, 72(%r4)",
|
||||
"std %r10, 80(%r4)",
|
||||
"std %r11, 88(%r4)",
|
||||
"std %r12, 96(%r4)",
|
||||
"std %r13, 104(%r4)",
|
||||
"std %r14, 112(%r4)",
|
||||
"std %r15, 120(%r4)",
|
||||
"std %r16, 128(%r4)",
|
||||
"std %r17, 136(%r4)",
|
||||
"std %r18, 144(%r4)",
|
||||
"std %r19, 152(%r4)",
|
||||
"std %r20, 160(%r4)",
|
||||
"std %r21, 168(%r4)",
|
||||
"std %r22, 176(%r4)",
|
||||
"std %r23, 184(%r4)",
|
||||
"std %r24, 192(%r4)",
|
||||
"std %r25, 200(%r4)",
|
||||
"std %r26, 208(%r4)",
|
||||
"std %r27, 212(%r4)",
|
||||
"std %r28, 220(%r4)",
|
||||
"std %r29, 228(%r4)",
|
||||
"std %r30, 236(%r4)",
|
||||
"std %r31, 244(%r4)",
|
||||
"mflr %r0",
|
||||
"std %r0, 252(%r4)",
|
||||
"mfctr %r0",
|
||||
"std %r0, 260(%r4)",
|
||||
"mfsrr0 %r0",
|
||||
"std %r0, 268(%r4)",
|
||||
"mfsrr1 %r0",
|
||||
"std %r0, 276(%r4)",
|
||||
"bl except",
|
||||
options(noreturn)
|
||||
);
|
||||
}
|
||||
|
||||
/// Create a longjmp for an exception vector.
|
||||
/// This will preverse r3/r4 in HSPRG0 and HSPRG1, respectively.
|
||||
/// r3 will be loaded with the constant specified in the `id` parameter.
|
||||
/// r4 will be loaded with the value of CTR.
|
||||
const fn make_longjmp_exc(id: u16, target: usize) -> [u32; 11] {
|
||||
[
|
||||
0x7C704BA6, // mtspr HSPRG0, %r3
|
||||
0x7C914BA6, // mtspr HSPRG1, %r4
|
||||
(0x3C600000 | ((target >> 48) & 0xFFFF)) as u32, // lis %r3, target[64:48]
|
||||
(0x60630000 | ((target >> 32) & 0xFFFF)) as u32, // ori %r3, %r3, target[48:32]
|
||||
0x786307C6, // rldicr %r3, %r3, 32, 31
|
||||
(0x64630000 | ((target >> 16) & 0xFFFF)) as u32, // oris %r3, %r3, target[32:16]
|
||||
(0x60630000 | ((target >> 00) & 0xFFFF)) as u32, // ori %r3, %r3, target[16:0]
|
||||
0x7C8902A6, // mfctr %r4
|
||||
(0x38600000 | (id as u32)), // li %r3, id
|
||||
0x7C6903A6, // mtctr %r3
|
||||
0x4E800420, // bctr
|
||||
]
|
||||
}
|
||||
|
||||
pub unsafe fn init_except() {
|
||||
let buf = make_longjmp_exc(5, except_thunk as usize);
|
||||
core::ptr::copy_nonoverlapping(buf.as_ptr(), 0x00000500 as *mut u32, buf.len());
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
const IIC_BASE: usize = 0x80000200_00050000;
|
||||
|
||||
//! Integrated Interrupt Controller (IIC)
|
||||
|
||||
const IIC_BASE: u64 = 0x80000200_00050000;
|
||||
|
||||
#[repr(usize)]
|
||||
enum Register {
|
||||
WhoAmI = 0x00,
|
||||
@ -14,3 +15,59 @@ enum Register {
|
||||
Unk70 = 0x70,
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
enum Interrupt {
|
||||
Ipi4 = 2,
|
||||
Ipi3 = 4,
|
||||
Smm = 5,
|
||||
Sfcx = 6,
|
||||
SataHdd = 8,
|
||||
SataCdrom = 9,
|
||||
Ohci0 = 11,
|
||||
Ehci0 = 12,
|
||||
Ohci1 = 13,
|
||||
Ehci1 = 14,
|
||||
Xma = 16,
|
||||
Audio = 17,
|
||||
Enet = 19,
|
||||
Xps = 21,
|
||||
Graphics = 22,
|
||||
Profiler = 24,
|
||||
Biu = 25,
|
||||
Ioc = 26,
|
||||
Fsb = 27,
|
||||
Ipi2 = 28,
|
||||
Clock = 29,
|
||||
Ipi1 = 30,
|
||||
None = 31,
|
||||
}
|
||||
|
||||
pub struct Iic {
|
||||
mmio: &'static mut [u8],
|
||||
}
|
||||
|
||||
impl Iic {
|
||||
pub fn local() -> Self {
|
||||
let id = xenon_cpu::intrin::pir();
|
||||
let base = IIC_BASE + (0x1000 * id);
|
||||
|
||||
// SAFETY: It should always be safe to get a pointer to the current CPU's
|
||||
// interrupt controller.
|
||||
Self {
|
||||
mmio: unsafe { core::slice::from_raw_parts_mut(base as *mut _, 0x1000) },
|
||||
}
|
||||
}
|
||||
|
||||
fn write<T>(&self, reg: Register, val: T) {
|
||||
unsafe { core::ptr::write_volatile(&self.mmio[reg as usize] as *const _ as *mut T, val); }
|
||||
}
|
||||
|
||||
fn read<T>(&self, reg: Register) -> T {
|
||||
unsafe { core::ptr::read_volatile(&self.mmio[reg as usize] as *const _ as *mut T) }
|
||||
}
|
||||
|
||||
pub fn set_priority(&self, prio: Interrupt) {
|
||||
self.write(Register::CurrentTaskPriority, ((prio as u64) << 2));
|
||||
self.read::<u64>(Register::CurrentTaskPriority);
|
||||
}
|
||||
}
|
||||
|
@ -9,13 +9,16 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::{sync::atomic::{AtomicU32, AtomicUsize, Ordering}};
|
||||
use core::sync::atomic::{AtomicU32, AtomicUsize, Ordering};
|
||||
|
||||
global_asm!(include_str!("startup.s"));
|
||||
|
||||
extern crate core_reqs;
|
||||
|
||||
mod except;
|
||||
mod iic;
|
||||
mod panic;
|
||||
mod smc;
|
||||
|
||||
extern "C" {
|
||||
fn start_from_libxenon() -> !;
|
||||
@ -65,6 +68,8 @@ const fn make_reljump(address: usize, target: usize) -> u32 {
|
||||
#[no_mangle]
|
||||
#[link_section = ".text.startup"]
|
||||
pub extern "C" fn __start_rust(pir: u32, _hrmor: u32, _pvr: u32, src: u32) -> ! {
|
||||
unsafe { smc::set_led(1, 0xF0); }
|
||||
|
||||
PROCESSORS.fetch_or(1 << pir, Ordering::Relaxed);
|
||||
if pir != 0 {
|
||||
loop {
|
||||
@ -91,7 +96,11 @@ pub extern "C" fn __start_rust(pir: u32, _hrmor: u32, _pvr: u32, src: u32) -> !
|
||||
let jmpbuf = make_longjmp(start_from_libxenon as usize);
|
||||
|
||||
// Copy the jump buffer to some unused bytes at the beginning of the hypervisor.
|
||||
core::ptr::copy_nonoverlapping(jmpbuf.as_ptr(), 0x000000A0 as *mut u32, jmpbuf.len());
|
||||
core::ptr::copy_nonoverlapping(
|
||||
jmpbuf.as_ptr(),
|
||||
0x000000A0 as *mut u32,
|
||||
jmpbuf.len(),
|
||||
);
|
||||
|
||||
// Ensure the compiler does not reorder instructions.
|
||||
core::sync::atomic::compiler_fence(Ordering::SeqCst);
|
||||
@ -115,15 +124,20 @@ pub extern "C" fn __start_rust(pir: u32, _hrmor: u32, _pvr: u32, src: u32) -> !
|
||||
};
|
||||
|
||||
// Loop...
|
||||
while PROCESSORS.load(Ordering::Relaxed) != 0x3F {}
|
||||
while PROCESSORS.load(Ordering::Relaxed) != 0x3F {
|
||||
unsafe { smc::set_led(1, PROCESSORS.load(Ordering::Relaxed) as u8); }
|
||||
}
|
||||
}
|
||||
|
||||
// Shouldn't hit this case.
|
||||
_ => loop {}
|
||||
_ => loop {},
|
||||
}
|
||||
|
||||
// Now the system is in a defined state. All secondary processors are captured,
|
||||
// and we are free to modify the system.
|
||||
unsafe { except::init_except() };
|
||||
|
||||
unsafe { smc::set_led(1, 0xF0) };
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use core::panic::PanicInfo;
|
||||
use core::{ffi::c_void, panic::PanicInfo};
|
||||
|
||||
#[lang = "eh_personality"]
|
||||
extern fn rust_eh_personality() {}
|
||||
@ -8,3 +8,9 @@ extern fn rust_eh_personality() {}
|
||||
pub fn panic(_info: &PanicInfo) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn _Unwind_Resume(_exception: *mut c_void) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
24
boot/stage1/src/smc.rs
Normal file
24
boot/stage1/src/smc.rs
Normal file
@ -0,0 +1,24 @@
|
||||
//! This file includes routines to communicate with the SMC.
|
||||
const SMC_ADDRESS: *mut u32 = 0x8000_0200_EA00_1000 as *mut u32;
|
||||
|
||||
pub unsafe fn send_message(msg: &[u32; 4]) {
|
||||
while (core::ptr::read_volatile(SMC_ADDRESS.offset(33)) & 0x04000000) == 0 {}
|
||||
|
||||
core::ptr::write_volatile::<u32>(SMC_ADDRESS.offset(33), 0x04000000);
|
||||
core::ptr::write_volatile::<u32>(SMC_ADDRESS.offset(32), msg[0]);
|
||||
core::ptr::write_volatile::<u32>(SMC_ADDRESS.offset(32), msg[1]);
|
||||
core::ptr::write_volatile::<u32>(SMC_ADDRESS.offset(32), msg[2]);
|
||||
core::ptr::write_volatile::<u32>(SMC_ADDRESS.offset(32), msg[3]);
|
||||
core::ptr::write_volatile::<u32>(SMC_ADDRESS.offset(33), 0x00000000);
|
||||
}
|
||||
|
||||
pub unsafe fn set_led(override_val: u8, value: u8) {
|
||||
let buf: [u32; 4] = [
|
||||
0x99000000 | ((override_val as u32) << 16) | ((value as u32) << 8),
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
];
|
||||
|
||||
send_message(&buf);
|
||||
}
|
@ -4,6 +4,7 @@
|
||||
#define ctrlrd 136
|
||||
#define ctrlwr 152
|
||||
#define pvr 287
|
||||
#define sprg0 272
|
||||
#define hsprg0 304
|
||||
#define hsprg1 305
|
||||
#define hdsisr 306
|
||||
@ -124,60 +125,25 @@ start_common:
|
||||
mtspr lpcr, %r10
|
||||
isync
|
||||
|
||||
// set stack
|
||||
// R1 = 0x80000000_1E000000
|
||||
li %r1, 0
|
||||
oris %r1, %r1, 0x8000
|
||||
rldicr %r1, %r1, 32,31
|
||||
oris %r1, %r1, 0x1e00
|
||||
|
||||
1:
|
||||
slwi %r3, %r3, 16 // 64k stack per thread
|
||||
sub %r1, %r1, %r3
|
||||
subi %r1, %r1, 0x80
|
||||
|
||||
// lis %r3, 0x8000
|
||||
// rldicr %r3, %r3, 32,31
|
||||
// oris %r3, %r3, start@high
|
||||
// ori %r3, %r3, start@l
|
||||
// ld %r2, 8(%r3)
|
||||
|
||||
// Set the high bit for PC.
|
||||
bl 1f
|
||||
1:
|
||||
mflr %r10
|
||||
|
||||
lis %r3, 0x8000
|
||||
sldi %r3, %r3, 32
|
||||
or %r3, %r3, %r10
|
||||
addi %r3, %r3, (1f - 1b)
|
||||
mtctr %r3
|
||||
bctr
|
||||
|
||||
1:
|
||||
bl branch_high
|
||||
bl load_toc
|
||||
|
||||
mfspr %r3, pir
|
||||
bl load_stack
|
||||
|
||||
mfspr %r3, pir
|
||||
cmplwi %r3, 0
|
||||
bne 1f
|
||||
|
||||
// Initialize BSS.
|
||||
ld %r10, __bss_start@got(%r2)
|
||||
ld %r11, __bss_end@got(%r2)
|
||||
sub %r11, %r11, %r10
|
||||
srdi %r11, %r11, 2
|
||||
subi %r10, %r10, 1
|
||||
cmplwi %r11, 0
|
||||
beq 1f
|
||||
// Initialize BSS on processor 0 only.
|
||||
bl init_bss
|
||||
|
||||
mtctr %r11
|
||||
li %r11, 0
|
||||
|
||||
.bss_loop:
|
||||
stwu %r11, 4(%r10)
|
||||
bdnz .bss_loop
|
||||
|
||||
1:
|
||||
// Relocate startup source.
|
||||
mr %r6, %r4
|
||||
|
||||
@ -185,11 +151,7 @@ start_common:
|
||||
mfspr %r4, hrmor
|
||||
mfpvr %r5
|
||||
|
||||
// Branch to start_rust via 64-bit ELF ABI.
|
||||
ld %r0, __start_rust@got(%r2)
|
||||
ld %r0, 0(%r0)
|
||||
mtctr %r0
|
||||
bctrl
|
||||
bl __start_rust
|
||||
nop
|
||||
|
||||
b .
|
||||
@ -297,6 +259,57 @@ init_regs:
|
||||
|
||||
blr
|
||||
|
||||
// Initialize BSS
|
||||
// R10 = clobber
|
||||
// R11 = clobber
|
||||
// CTR = clobber
|
||||
init_bss:
|
||||
ld %r10, __bss_start@got(%r2)
|
||||
ld %r11, __bss_end@got(%r2)
|
||||
sub %r11, %r11, %r10
|
||||
srdi %r11, %r11, 2
|
||||
subi %r10, %r10, 1
|
||||
cmplwi %r11, 0
|
||||
beq 1f
|
||||
|
||||
mtctr %r11
|
||||
li %r11, 0
|
||||
|
||||
.bss_loop:
|
||||
stwu %r11, 4(%r10)
|
||||
bdnz .bss_loop
|
||||
|
||||
1:
|
||||
blr
|
||||
|
||||
// Sets the high bit in PC.
|
||||
// R3 = clobber
|
||||
// R10 = clobber
|
||||
branch_high:
|
||||
mflr %r10
|
||||
|
||||
lis %r3, 0x8000
|
||||
sldi %r3, %r3, 32
|
||||
or %r3, %r3, %r10
|
||||
|
||||
mtlr %r3
|
||||
blr
|
||||
|
||||
// Sets up the stack.
|
||||
// R1(out) = stack
|
||||
// R3(in/out) = pir / clobber
|
||||
load_stack:
|
||||
// set stack
|
||||
// R1 = 0x80000000_1E000000
|
||||
lis %r1, 0x8000
|
||||
rldicr %r1, %r1, 32,31
|
||||
oris %r1, %r1, 0x1e00
|
||||
|
||||
slwi %r3, %r3, 16 // 64k stack per thread
|
||||
sub %r1, %r1, %r3
|
||||
subi %r1, %r1, 0x80
|
||||
blr
|
||||
|
||||
// Loads the table of contents pointer into R2.
|
||||
// R0 = clobber
|
||||
// R2 = TOC
|
||||
|
8
shared/xenon-cpu/Cargo.toml
Normal file
8
shared/xenon-cpu/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "xenon-cpu"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
19
shared/xenon-cpu/src/intrin.rs
Normal file
19
shared/xenon-cpu/src/intrin.rs
Normal file
@ -0,0 +1,19 @@
|
||||
#[inline]
|
||||
pub fn mftb() -> u64 {
|
||||
let tb;
|
||||
unsafe {
|
||||
asm!("mftb {}", out(reg) tb);
|
||||
}
|
||||
|
||||
tb
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn pir() -> u64 {
|
||||
let pir;
|
||||
unsafe {
|
||||
asm!("mfspr {}, 1023", out(reg) pir);
|
||||
}
|
||||
|
||||
pir
|
||||
}
|
5
shared/xenon-cpu/src/lib.rs
Normal file
5
shared/xenon-cpu/src/lib.rs
Normal file
@ -0,0 +1,5 @@
|
||||
#![feature(asm)]
|
||||
#![no_std]
|
||||
|
||||
pub mod intrin;
|
||||
pub mod time;
|
13
shared/xenon-cpu/src/time.rs
Normal file
13
shared/xenon-cpu/src/time.rs
Normal file
@ -0,0 +1,13 @@
|
||||
const TIMEBASE_FREQ: u64 = 3192000000 / 64;
|
||||
|
||||
use crate::intrin::mftb;
|
||||
use core::time::Duration;
|
||||
|
||||
fn tdelay(time: u128) {
|
||||
let tgt = time.saturating_add(mftb() as u128) as u64;
|
||||
while mftb() < tgt {}
|
||||
}
|
||||
|
||||
pub fn delay(length: Duration) {
|
||||
tdelay((length.as_micros() * TIMEBASE_FREQ as u128) / 1000000);
|
||||
}
|
Loading…
Reference in New Issue
Block a user