forked from AbleOS/ableos
Arguments are actually passed into programs
This commit is contained in:
parent
f2e561e242
commit
f074527e42
|
@ -1,37 +1,46 @@
|
|||
mod memory;
|
||||
|
||||
use core::{arch::{asm, global_asm}, fmt::Write};
|
||||
use alloc::boxed::Box;
|
||||
use sbi::system_reset::{ResetType, ResetReason, system_reset};
|
||||
use spin::{Mutex, Once};
|
||||
use uart_16550::MmioSerialPort;
|
||||
use {
|
||||
alloc::boxed::Box,
|
||||
core::{
|
||||
arch::{asm, global_asm},
|
||||
fmt::Write,
|
||||
},
|
||||
sbi::system_reset::{system_reset, ResetReason, ResetType},
|
||||
spin::{Mutex, Once},
|
||||
uart_16550::MmioSerialPort,
|
||||
};
|
||||
|
||||
use crate::{allocator, memory::PhysicalAddress, arch::riscv64::memory::{PAGE_TABLE, PageEntryFlags, PageSize, PageTable}};
|
||||
use crate::{
|
||||
allocator,
|
||||
arch::riscv64::memory::{PageEntryFlags, PageSize, PageTable, PAGE_TABLE},
|
||||
memory::PhysicalAddress,
|
||||
};
|
||||
|
||||
global_asm!(include_str!("entry.s"));
|
||||
global_asm!(include_str!("memory_regions.s"));
|
||||
|
||||
pub const PAGE_SIZE: usize = 4096;
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
static TEXT_START: PhysicalAddress;
|
||||
static TEXT_END: PhysicalAddress;
|
||||
|
||||
static RODATA_START: PhysicalAddress;
|
||||
static RODATA_END: PhysicalAddress;
|
||||
|
||||
|
||||
static DATA_START: PhysicalAddress;
|
||||
static DATA_END: PhysicalAddress;
|
||||
|
||||
static SDATA_START: PhysicalAddress;
|
||||
static SDATA_END: PhysicalAddress;
|
||||
|
||||
|
||||
static BSS_START: PhysicalAddress;
|
||||
static BSS_END: PhysicalAddress;
|
||||
|
||||
|
||||
static INITIAL_KERNEL_HEAP_START: PhysicalAddress;
|
||||
static INITIAL_KERNEL_HEAP_SIZE: usize;
|
||||
|
||||
|
||||
static USABLE_MEMORY_START: PhysicalAddress;
|
||||
static USABLE_MEMORY_SIZE: usize;
|
||||
}
|
||||
|
@ -39,12 +48,15 @@ extern {
|
|||
static SERIAL_CONSOLE: Once<Mutex<MmioSerialPort>> = Once::new();
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern fn _kernel_start() -> ! {
|
||||
unsafe extern "C" fn _kernel_start() -> ! {
|
||||
SERIAL_CONSOLE.call_once(|| Mutex::new(unsafe { MmioSerialPort::new(0x1000_0000) }));
|
||||
crate::logger::init().expect("failed to set logger");
|
||||
log::info!("Initialising AKern {}", crate::VERSION);
|
||||
|
||||
allocator::init(INITIAL_KERNEL_HEAP_START.as_mut_ptr::<u8>(), INITIAL_KERNEL_HEAP_SIZE);
|
||||
allocator::init(
|
||||
INITIAL_KERNEL_HEAP_START.as_mut_ptr::<u8>(),
|
||||
INITIAL_KERNEL_HEAP_SIZE,
|
||||
);
|
||||
memory::init(USABLE_MEMORY_START.into(), USABLE_MEMORY_SIZE / PAGE_SIZE);
|
||||
|
||||
let mut page_table_addr = PAGE_TABLE.get().unwrap().lock();
|
||||
|
@ -61,9 +73,17 @@ unsafe extern fn _kernel_start() -> ! {
|
|||
// Map bss section (includes stack and initial kernel heap)
|
||||
page_table.identity_map_range(BSS_START, BSS_END, PageEntryFlags::ReadWrite);
|
||||
// Map usable memory range (as rw so not executable)
|
||||
page_table.identity_map_range(USABLE_MEMORY_START, USABLE_MEMORY_START + USABLE_MEMORY_SIZE.into(), PageEntryFlags::ReadWrite);
|
||||
page_table.identity_map_range(
|
||||
USABLE_MEMORY_START,
|
||||
USABLE_MEMORY_START + USABLE_MEMORY_SIZE.into(),
|
||||
PageEntryFlags::ReadWrite,
|
||||
);
|
||||
// Map Uart so we can continue using serial
|
||||
page_table.identity_map(0x1000_0000_usize.into(), PageEntryFlags::ReadWrite, PageSize::Size4KiB);
|
||||
page_table.identity_map(
|
||||
0x1000_0000_usize.into(),
|
||||
PageEntryFlags::ReadWrite,
|
||||
PageSize::Size4KiB,
|
||||
);
|
||||
|
||||
let table_ppn = page_table_addr.as_addr() as usize >> 12;
|
||||
let satp_value = 8 << 60 | table_ppn;
|
||||
|
|
|
@ -1,72 +1 @@
|
|||
use {
|
||||
crate::kmain::DEVICE_TREE,
|
||||
able_graphics_library::raw_pixel::Display,
|
||||
embedded_graphics::{pixelcolor::Rgb888, prelude::*},
|
||||
limine::{Framebuffer, FramebufferRequest, NonNullPtr},
|
||||
spin::{Lazy, Mutex},
|
||||
};
|
||||
|
||||
pub static DISPLAY: Lazy<Mutex<Display>> = Lazy::new(|| {
|
||||
static FB_REQ: FramebufferRequest = FramebufferRequest::new(0);
|
||||
let fb1: &NonNullPtr<Framebuffer> = &FB_REQ.get_response().get().unwrap().framebuffers()[0];
|
||||
|
||||
{
|
||||
use crate::alloc::string::ToString;
|
||||
let mut dt = DEVICE_TREE.lock();
|
||||
let mut disp = xml::XMLElement::new("display_0");
|
||||
|
||||
disp.set_attribute("width", fb1.width);
|
||||
disp.set_attribute("height", fb1.height);
|
||||
disp.set_attribute("bits per pixel", fb1.bpp);
|
||||
disp.set_attribute("pitch", fb1.pitch);
|
||||
// disp.set_attribute("fb ptr", fb1.address.as_ptr().unwrap());
|
||||
dt.devices.insert("Displays".to_string(), alloc::vec![disp]);
|
||||
}
|
||||
let _size: usize = (fb1.width * fb1.height).try_into().unwrap();
|
||||
let back_buffer: alloc::vec::Vec<u32> = alloc::vec![0; 800*600];
|
||||
|
||||
let m = Mutex::new(Display {
|
||||
fb: fb1.address.as_ptr().unwrap().cast(),
|
||||
bb: back_buffer.as_slice().as_ptr() as *mut u32,
|
||||
size: Size::new(fb1.width as u32, fb1.height as u32),
|
||||
color: Rgb888::WHITE,
|
||||
});
|
||||
log::info!("Graphics initialised");
|
||||
log::info!(
|
||||
"Graphics front ptr {:?}",
|
||||
fb1.address.as_ptr().unwrap() as *const u8
|
||||
);
|
||||
m
|
||||
});
|
||||
|
||||
pub fn init() {
|
||||
Lazy::force(&DISPLAY);
|
||||
}
|
||||
// pub fn virtio_gpu<T: Transport>(transport: T) {
|
||||
// let mut gpu = VirtIOGpu::<AbleosHal, T>::new(transport).expect("failed to create gpu driver");
|
||||
// let (width, height) = gpu.resolution().expect("failed to get resolution");
|
||||
// let width = width as usize;
|
||||
// let height = height as usize;
|
||||
// log::info!("GPU resolution is {}x{}", width, height);
|
||||
// let fb = gpu.setup_framebuffer().expect("failed to get fb");
|
||||
// for y in 0..height {
|
||||
// for x in 0..width {
|
||||
// let idx = (y * width + x) * 4;
|
||||
// fb[idx] = x as u8;
|
||||
// fb[idx + 1] = y as u8;
|
||||
// fb[idx + 2] = (x + y) as u8;
|
||||
// }
|
||||
// }
|
||||
// gpu.flush().expect("failed to flush");
|
||||
// //delay some time
|
||||
// log::info!("virtio-gpu show graphics....");
|
||||
// for _ in 0..100000 {
|
||||
// for _ in 0..100000 {
|
||||
// unsafe {
|
||||
// core::arch::asm!("nop");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// log::info!("virtio-gpu test finished");
|
||||
// }
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
use {
|
||||
crate::{arch::x86_64::graphics::DISPLAY, bootmodules::BootModule},
|
||||
core::arch::asm,
|
||||
embedded_graphics::pixelcolor::Rgb888,
|
||||
log::warn,
|
||||
rdrand::RdSeed,
|
||||
crate::bootmodules::BootModule, core::arch::asm, embedded_graphics::pixelcolor::Rgb888,
|
||||
log::warn, rdrand::RdSeed,
|
||||
};
|
||||
pub mod memory;
|
||||
|
||||
|
@ -83,51 +80,51 @@ unsafe extern "C" fn start() -> ! {
|
|||
device_info_collector::collect_device_info();
|
||||
|
||||
// Graphics test
|
||||
{
|
||||
graphics::init();
|
||||
let mut dis = DISPLAY.lock();
|
||||
use embedded_graphics::prelude::RgbColor;
|
||||
// {
|
||||
// graphics::init();
|
||||
// let mut dis = DISPLAY.lock();
|
||||
// use embedded_graphics::prelude::RgbColor;
|
||||
|
||||
let _ = dis.set_color(Rgb888::YELLOW);
|
||||
let thick = 6;
|
||||
let p1 = (400, 30);
|
||||
let p2 = (200, 150);
|
||||
let p3 = (600, 150);
|
||||
let p4 = (200, 350);
|
||||
let p5 = (600, 350);
|
||||
let p6 = (400, 470);
|
||||
// let _ = dis.set_color(Rgb888::YELLOW);
|
||||
// let thick = 6;
|
||||
// let p1 = (400, 30);
|
||||
// let p2 = (200, 150);
|
||||
// let p3 = (600, 150);
|
||||
// let p4 = (200, 350);
|
||||
// let p5 = (600, 350);
|
||||
// let p6 = (400, 470);
|
||||
|
||||
{
|
||||
//HEXAGON
|
||||
// {
|
||||
// //HEXAGON
|
||||
|
||||
let _ = dis.line(p1.0, p1.1, p2.0, p2.1, thick);
|
||||
let _ = dis.line(p1.0, p1.1, p3.0, p3.1, thick);
|
||||
let _ = dis.line(p2.0, p2.1, p4.0, p4.1, thick);
|
||||
let _ = dis.line(p3.0, p3.1, p5.0, p5.1, thick);
|
||||
let _ = dis.line(p6.0, p6.1, p4.0, p4.1, thick);
|
||||
let _ = dis.line(p6.0, p6.1, p5.0, p5.1, thick);
|
||||
}
|
||||
{
|
||||
let _ = dis.line(600, 150, 200, 350, thick);
|
||||
let _ = dis.line(600, 350, 400, 250, thick);
|
||||
}
|
||||
// let _ = dis.line(p1.0, p1.1, p2.0, p2.1, thick);
|
||||
// let _ = dis.line(p1.0, p1.1, p3.0, p3.1, thick);
|
||||
// let _ = dis.line(p2.0, p2.1, p4.0, p4.1, thick);
|
||||
// let _ = dis.line(p3.0, p3.1, p5.0, p5.1, thick);
|
||||
// let _ = dis.line(p6.0, p6.1, p4.0, p4.1, thick);
|
||||
// let _ = dis.line(p6.0, p6.1, p5.0, p5.1, thick);
|
||||
// }
|
||||
// {
|
||||
// let _ = dis.line(600, 150, 200, 350, thick);
|
||||
// let _ = dis.line(600, 350, 400, 250, thick);
|
||||
// }
|
||||
|
||||
{
|
||||
let _ = dis.set_color(Rgb888::WHITE);
|
||||
let hp1 = (350, 150);
|
||||
let hp2 = (350, 350);
|
||||
let hp3 = (450, 250);
|
||||
let hp4 = (350, 250);
|
||||
let hp5 = (450, 150);
|
||||
let hp6 = (450, 350);
|
||||
// {
|
||||
// let _ = dis.set_color(Rgb888::WHITE);
|
||||
// let hp1 = (350, 150);
|
||||
// let hp2 = (350, 350);
|
||||
// let hp3 = (450, 250);
|
||||
// let hp4 = (350, 250);
|
||||
// let hp5 = (450, 150);
|
||||
// let hp6 = (450, 350);
|
||||
|
||||
let _ = dis.line(hp1.0, hp1.1, hp2.0, hp2.1, thick);
|
||||
let _ = dis.line(hp3.0, hp3.1, hp4.0, hp4.1, thick);
|
||||
let _ = dis.line(hp5.0, hp5.1, hp6.0, hp6.1, thick);
|
||||
}
|
||||
// let _ = dis.line(hp1.0, hp1.1, hp2.0, hp2.1, thick);
|
||||
// let _ = dis.line(hp3.0, hp3.1, hp4.0, hp4.1, thick);
|
||||
// let _ = dis.line(hp5.0, hp5.1, hp6.0, hp6.1, thick);
|
||||
// }
|
||||
|
||||
dis.swap_buffers();
|
||||
};
|
||||
// dis.swap_buffers();
|
||||
// };
|
||||
|
||||
// TODO: Add in rdseed and rdrand as sources for randomness
|
||||
let _rand = xml::XMLElement::new("Random");
|
||||
|
|
|
@ -25,6 +25,11 @@ pub struct ExecThread<'p> {
|
|||
|
||||
unsafe impl<'p> Send for ExecThread<'p> {}
|
||||
impl<'p> ExecThread<'p> {
|
||||
pub fn set_arguments(&mut self, ptr: u64, length: u64) {
|
||||
self.vm.registers[1] = hbvm::value::Value(ptr);
|
||||
self.vm.registers[2] = hbvm::value::Value(length);
|
||||
}
|
||||
|
||||
pub unsafe fn new(program: &'p [u8], entrypoint: Address) -> Self {
|
||||
ExecThread {
|
||||
vm: unsafe {
|
||||
|
|
|
@ -1,19 +1,17 @@
|
|||
//! AbleOS Kernel Entrypoint
|
||||
|
||||
use {hashbrown::HashMap, hbvm::mem::Address};
|
||||
|
||||
use crate::{
|
||||
capabilities,
|
||||
holeybytes::ExecThread,
|
||||
ipc::buffer::{self, IpcBuffer},
|
||||
};
|
||||
// use crate::arch::sloop;
|
||||
use {
|
||||
crate::{
|
||||
bootmodules::{build_cmd, BootModules},
|
||||
capabilities,
|
||||
device_tree::DeviceTree,
|
||||
holeybytes::ExecThread,
|
||||
ipc::buffer::{self, IpcBuffer},
|
||||
},
|
||||
alloc::format,
|
||||
hashbrown::HashMap,
|
||||
hbvm::mem::Address,
|
||||
limine::{Framebuffer, FramebufferRequest, NonNullPtr},
|
||||
log::{debug, info, trace},
|
||||
spin::{Lazy, Mutex},
|
||||
xml::XMLElement,
|
||||
|
@ -32,6 +30,7 @@ pub fn kmain(cmdline: &str, boot_modules: BootModules) -> ! {
|
|||
// TODO: pass into the program
|
||||
// Pass CMDLine into an IPCBuffer and put the ptr to the IPCBuffer in r200
|
||||
_bmcmd = build_cmd(name, bm.cmd.clone());
|
||||
log::info!("{:?}", _bmcmd);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -47,12 +46,47 @@ pub fn kmain(cmdline: &str, boot_modules: BootModules) -> ! {
|
|||
// TODO: Schedule the VFS from initramfs
|
||||
// TODO: schedule the init system from the initramfs
|
||||
|
||||
drop(dt);
|
||||
|
||||
let fb1: &NonNullPtr<Framebuffer> = &FB_REQ.get_response().get().unwrap().framebuffers()[0];
|
||||
|
||||
{
|
||||
use crate::alloc::string::ToString;
|
||||
let mut dt = DEVICE_TREE.lock();
|
||||
let mut disp = xml::XMLElement::new("display_0");
|
||||
|
||||
disp.set_attribute("width", fb1.width);
|
||||
disp.set_attribute("height", fb1.height);
|
||||
disp.set_attribute("bits per pixel", fb1.bpp);
|
||||
disp.set_attribute("pitch", fb1.pitch);
|
||||
dt.devices.insert("Displays".to_string(), alloc::vec![disp]);
|
||||
}
|
||||
log::info!("Graphics initialised");
|
||||
log::info!(
|
||||
"Graphics front ptr {:?}",
|
||||
fb1.address.as_ptr().unwrap() as *const u8
|
||||
);
|
||||
|
||||
let mut executor = crate::task::Executor::default();
|
||||
let bm_take = boot_modules.len();
|
||||
unsafe {
|
||||
for module in boot_modules.into_iter().take(bm_take) {
|
||||
let mut cmd = module.cmd;
|
||||
{
|
||||
// Remove the quotes
|
||||
cmd.remove(0);
|
||||
cmd.pop();
|
||||
}
|
||||
let cmd_len = cmd.as_bytes().len() as u64;
|
||||
|
||||
log::info!("Spawning {} with arguments \"{}\"", module.path, cmd);
|
||||
|
||||
executor.spawn(async move {
|
||||
if let Err(e) = ExecThread::new(&module.bytes, Address::new(0)).await {
|
||||
let mut thr = ExecThread::new(&module.bytes, Address::new(0));
|
||||
if cmd_len > 0 {
|
||||
thr.set_arguments(cmd.as_bytes().as_ptr() as u64, cmd_len);
|
||||
}
|
||||
if let Err(e) = thr.await {
|
||||
log::error!("{e:?}");
|
||||
}
|
||||
});
|
||||
|
@ -68,6 +102,7 @@ pub static DEVICE_TREE: Lazy<Mutex<DeviceTree>> = Lazy::new(|| {
|
|||
let dt = DeviceTree::new();
|
||||
Mutex::new(dt)
|
||||
});
|
||||
pub static FB_REQ: FramebufferRequest = FramebufferRequest::new(0);
|
||||
|
||||
use alloc::vec::Vec;
|
||||
pub type IpcBuffers = HashMap<u64, IpcBuffer>;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
extern crate kernel;
|
||||
|
|
|
@ -139,9 +139,7 @@ fn get_fs() -> Result<FileSystem<impl ReadWriteSeek>, io::Error> {
|
|||
io::copy(
|
||||
&mut File::open("limine/BOOTAA64.EFI")
|
||||
.map_err(Report::from)
|
||||
.attach_printable(
|
||||
"Copying Limine (ARM): have you pulled the submodule?",
|
||||
)?,
|
||||
.attach_printable("Copying Limine (ARM): have you pulled the submodule?")?,
|
||||
&mut bootdir.create_file("bootaa64.efi")?,
|
||||
)?;
|
||||
|
||||
|
@ -233,6 +231,7 @@ fn run(release: bool, target: Target) -> Result<(), Error> {
|
|||
"-drive", "file=target/disk.img,format=raw",
|
||||
"-m", "4G",
|
||||
"-smp", "cores=4",
|
||||
// "-enable-kvm",
|
||||
"-cpu", "Broadwell-v4"
|
||||
]);
|
||||
}
|
||||
|
|
|
@ -31,4 +31,4 @@ TERM_BACKDROP=008080
|
|||
MODULE_CMDLINE=""
|
||||
|
||||
MODULE_PATH=boot:///limine_framebuffer_driver.hbf
|
||||
MODULE_CMDLINE=""
|
||||
MODULE_CMDLINE="height=10 width=10 arch=${ARCH}"
|
|
@ -4,26 +4,134 @@
|
|||
// Use std abstractions if they exist like logging functionality
|
||||
import "sysdata/test-programs/hblib/std" as std;
|
||||
|
||||
// Define main
|
||||
fn main(){
|
||||
std::Info("Starting the limine framebuffer driver.");
|
||||
// Color
|
||||
li64(r1, 0xffffffff);
|
||||
// iterator
|
||||
li32(r2, 0);
|
||||
// count
|
||||
li64(r3, 12);
|
||||
// Label here
|
||||
let start = label();
|
||||
// Write to the memory
|
||||
st(r1, r2, 0xFFFF8000C0000000, 1);
|
||||
// Increment
|
||||
addi64(r2, r2, 1);
|
||||
// std::Info("abc");
|
||||
jltu(r2, r3, start);
|
||||
|
||||
// Terminate execution.
|
||||
tx();
|
||||
fn rect(reg_x, reg_y, w, h, color) {
|
||||
li64(r3, 0);
|
||||
li64(r4, 0);
|
||||
li64(r5, w);
|
||||
li64(r6, h);
|
||||
|
||||
let start_y = label();
|
||||
|
||||
let start_x = label();
|
||||
|
||||
add64(r9, r3, reg_x);
|
||||
add64(r10, r4, reg_y);
|
||||
pixel(r9, r10, color);
|
||||
|
||||
li64(r1, 1);
|
||||
add64(r3, r3, r1);
|
||||
|
||||
jltu(r3, r5, start_x);
|
||||
|
||||
li64(r1, 1);
|
||||
add64(r4, r4, r1);
|
||||
|
||||
li64(r3, 0);
|
||||
|
||||
jltu(r4, r6, start_y);
|
||||
}
|
||||
|
||||
main();
|
||||
fn pixel(reg_x, reg_y, color) {
|
||||
let BUFFER = 0xFFFF8000C0000000;
|
||||
let WIDTH = 1024;
|
||||
|
||||
// r1 = y * WIDTH
|
||||
li64(r1, WIDTH);
|
||||
mul64(r1, reg_y, r1);
|
||||
|
||||
// r2 = x + r2
|
||||
add64(r2, reg_x, r1);
|
||||
|
||||
// r2 = r2 * 4
|
||||
li64(r1, 4);
|
||||
mul64(r2, r2, r1);
|
||||
|
||||
// store pixel value
|
||||
li64(r1, color);
|
||||
st(r1, r2, BUFFER, 4);
|
||||
}
|
||||
|
||||
fn clear() {
|
||||
// rect(r0, r0, 1024, 768, 0xff222222);
|
||||
|
||||
let BUFFER = 0xFFFF8000C0000000;
|
||||
// on arm the FB is at 0xFFFF8000BC430000
|
||||
// FIXME: get the framebuffer pointer from the starting arguments
|
||||
|
||||
li64(r1, 0xff222222);
|
||||
li64(r2, 0);
|
||||
li64(r3, 1);
|
||||
li64(r4, 1024 * 768);
|
||||
li64(r5, 4);
|
||||
let start = label();
|
||||
mul64(r6, r2, r5);
|
||||
st(r1, r6, BUFFER, 4);
|
||||
add64(r2, r2, r3);
|
||||
jltu(r2, r4, start);
|
||||
}
|
||||
|
||||
// Define main
|
||||
fn main(){
|
||||
std::Info("Starting the limine framebuffer driver.");
|
||||
|
||||
li64(r100, 300);
|
||||
li64(r101, 300);
|
||||
li64(r102, 1);
|
||||
li64(r103, 1);
|
||||
li64(r104, 1024 - 20);
|
||||
li64(r105, 768 - 20);
|
||||
li64(r106, 0);
|
||||
li64(r107, 0);
|
||||
|
||||
clear();
|
||||
|
||||
let start = label();
|
||||
|
||||
rect(r100, r101, 20, 20, 0xff222222);
|
||||
//clear();
|
||||
|
||||
add64(r100, r100, r102);
|
||||
add64(r101, r101, r103);
|
||||
|
||||
let after_x_right = declabel();
|
||||
jltu(r100, r104, after_x_right);
|
||||
li64(r102, -1);
|
||||
here(after_x_right);
|
||||
|
||||
let after_x_left = declabel();
|
||||
jgtu(r100, r106, after_x_left);
|
||||
li64(r102, 1);
|
||||
li64(r100, 0);
|
||||
here(after_x_left);
|
||||
|
||||
let after_y_right = declabel();
|
||||
jltu(r101, r105, after_y_right);
|
||||
li64(r103, -1);
|
||||
here(after_y_right);
|
||||
|
||||
let after_y_left = declabel();
|
||||
jgtu(r101, r107, after_y_left);
|
||||
li64(r103, 1);
|
||||
li64(r101, 0);
|
||||
here(after_y_left);
|
||||
|
||||
rect(r100, r101, 20, 20, 0xffffffff);
|
||||
|
||||
li64(r200, 0);
|
||||
li64(r201, 1);
|
||||
li64(r202, 10000);
|
||||
let wait = label();
|
||||
add64(r200, r200, r201);
|
||||
jltu(r200, r202, wait);
|
||||
|
||||
jeq(r0, r0, start);
|
||||
//jmp(start);
|
||||
|
||||
std::Info("done");
|
||||
|
||||
// Terminate execution.
|
||||
tx();
|
||||
}
|
||||
|
||||
main();
|
||||
|
|
Loading…
Reference in a new issue