forked from AbleOS/holey-bytes
foo bar
This commit is contained in:
parent
ebefc85566
commit
b794fa7c3c
|
@ -80,7 +80,7 @@ unsafe impl BytecodeItem for u8 {}
|
||||||
/// ```text
|
/// ```text
|
||||||
/// Types consist of letters meaning a single field
|
/// Types consist of letters meaning a single field
|
||||||
/// | Type | Size (B) | Meaning |
|
/// | Type | Size (B) | Meaning |
|
||||||
/// |:-----|:---------|:------------------------|
|
/// fn():------------------------|
|
||||||
/// | N | 0 | Empty |
|
/// | N | 0 | Empty |
|
||||||
/// | R | 1 | Register |
|
/// | R | 1 | Register |
|
||||||
/// | A | 8 | Absolute address |
|
/// | A | 8 | Absolute address |
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
main := ||: int {
|
main := fn(): int {
|
||||||
return 10 - 20 / 2 + 4 * (2 + 2) - 4 * 4 + 1;
|
return 10 - 20 / 2 + 4 * (2 + 2) - 4 * 4 + 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
|
|
||||||
main := ||: int {
|
main := fn(): int {
|
||||||
return add_one(10) + add_two(20);
|
return add_one(10) + add_two(20);
|
||||||
}
|
}
|
||||||
|
|
||||||
add_two := |x: int|: int {
|
add_two := fn(x: int): int {
|
||||||
return x + 2;
|
return x + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
add_one := |x: int|: int {
|
add_one := fn(x: int): int {
|
||||||
return x + 1;
|
return x + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
|
|
||||||
main := ||: int {
|
main := fn(): int {
|
||||||
return fib(10);
|
return fib(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
fib := |x: int|: int {
|
fib := fn(x: int): int {
|
||||||
if x <= 2 {
|
if x <= 2 {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
main := ||: int {
|
main := fn(): int {
|
||||||
return fib(10);
|
return fib(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
fib := |n: int|: int {
|
fib := fn(n: int): int {
|
||||||
a := 0;
|
a := 0;
|
||||||
b := 1;
|
b := 1;
|
||||||
loop {
|
loop {
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
main := ||: int {
|
main := fn(): int {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
main := ||: int {
|
main := fn(): int {
|
||||||
a := 1;
|
a := 1;
|
||||||
b := 2;
|
b := 2;
|
||||||
a = a + 1;
|
a = a + 1;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
instrs, lexer,
|
instrs, lexer, log,
|
||||||
parser::{self, Expr},
|
parser::{self, Expr},
|
||||||
},
|
},
|
||||||
std::rc::Rc,
|
std::rc::Rc,
|
||||||
|
@ -9,6 +9,42 @@ use {
|
||||||
type LabelId = u32;
|
type LabelId = u32;
|
||||||
type Reg = u8;
|
type Reg = u8;
|
||||||
type MaskElem = u64;
|
type MaskElem = u64;
|
||||||
|
type Type = u32;
|
||||||
|
|
||||||
|
mod bt {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
const fn builtin_type(id: u32) -> Type {
|
||||||
|
Type::MAX - id
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! builtin_type {
|
||||||
|
($($name:ident;)*) => {$(
|
||||||
|
pub const $name: Type = builtin_type(${index(0)});
|
||||||
|
)*};
|
||||||
|
}
|
||||||
|
|
||||||
|
builtin_type! {
|
||||||
|
INT;
|
||||||
|
BOOL;
|
||||||
|
MAX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum TypeKind {
|
||||||
|
Builtin(Type),
|
||||||
|
Struct(Type),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypeKind {
|
||||||
|
fn from_ty(ty: Type) -> Self {
|
||||||
|
if ty > bt::MAX {
|
||||||
|
Self::Builtin(ty)
|
||||||
|
} else {
|
||||||
|
Self::Struct(ty)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const STACK_PTR: Reg = 254;
|
const STACK_PTR: Reg = 254;
|
||||||
const ZERO: Reg = 0;
|
const ZERO: Reg = 0;
|
||||||
|
@ -55,7 +91,7 @@ impl Func {
|
||||||
|
|
||||||
fn encode(&mut self, (len, instr): (usize, [u8; instrs::MAX_SIZE])) {
|
fn encode(&mut self, (len, instr): (usize, [u8; instrs::MAX_SIZE])) {
|
||||||
let name = instrs::NAMES[instr[0] as usize];
|
let name = instrs::NAMES[instr[0] as usize];
|
||||||
println!(
|
log::dbg!(
|
||||||
"{:08x}: {}: {}",
|
"{:08x}: {}: {}",
|
||||||
self.code.len(),
|
self.code.len(),
|
||||||
name,
|
name,
|
||||||
|
@ -107,7 +143,7 @@ impl Func {
|
||||||
label.offset as i64 - reloc.offset as i64
|
label.offset as i64 - reloc.offset as i64
|
||||||
} + shift;
|
} + shift;
|
||||||
|
|
||||||
dbg!(
|
log::dbg!(
|
||||||
label.name.as_ref(),
|
label.name.as_ref(),
|
||||||
offset,
|
offset,
|
||||||
reloc.size,
|
reloc.size,
|
||||||
|
@ -184,6 +220,11 @@ struct Loop {
|
||||||
relocs: Vec<RetReloc>,
|
relocs: Vec<RetReloc>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Struct {
|
||||||
|
name: Rc<str>,
|
||||||
|
fields: Vec<(Rc<str>, Type)>,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Codegen<'a> {
|
pub struct Codegen<'a> {
|
||||||
path: &'a std::path::Path,
|
path: &'a std::path::Path,
|
||||||
ret: Expr<'a>,
|
ret: Expr<'a>,
|
||||||
|
@ -196,13 +237,14 @@ pub struct Codegen<'a> {
|
||||||
stack_relocs: Vec<StackReloc>,
|
stack_relocs: Vec<StackReloc>,
|
||||||
ret_relocs: Vec<RetReloc>,
|
ret_relocs: Vec<RetReloc>,
|
||||||
loops: Vec<Loop>,
|
loops: Vec<Loop>,
|
||||||
|
records: Vec<Struct>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Codegen<'a> {
|
impl<'a> Codegen<'a> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
path: std::path::Path::new(""),
|
path: std::path::Path::new(""),
|
||||||
ret: Expr::Return { val: None },
|
ret: Expr::Return { val: None, pos: 0 },
|
||||||
gpa: Default::default(),
|
gpa: Default::default(),
|
||||||
code: Default::default(),
|
code: Default::default(),
|
||||||
temp: Default::default(),
|
temp: Default::default(),
|
||||||
|
@ -213,6 +255,7 @@ impl<'a> Codegen<'a> {
|
||||||
stack_relocs: Default::default(),
|
stack_relocs: Default::default(),
|
||||||
ret_relocs: Default::default(),
|
ret_relocs: Default::default(),
|
||||||
loops: Default::default(),
|
loops: Default::default(),
|
||||||
|
records: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,9 +332,12 @@ impl<'a> Codegen<'a> {
|
||||||
fn expr(&mut self, expr: &'a parser::Expr<'a>, expeted: Option<Expr<'a>>) -> Option<Value<'a>> {
|
fn expr(&mut self, expr: &'a parser::Expr<'a>, expeted: Option<Expr<'a>>) -> Option<Value<'a>> {
|
||||||
use {lexer::TokenKind as T, parser::Expr as E};
|
use {lexer::TokenKind as T, parser::Expr as E};
|
||||||
match *expr {
|
match *expr {
|
||||||
E::Decl {
|
E::BinOp {
|
||||||
name,
|
left: E::Ident { name, .. },
|
||||||
val: E::Closure { ret, body, args },
|
op: T::Decl,
|
||||||
|
right: E::Closure {
|
||||||
|
ret, body, args, ..
|
||||||
|
},
|
||||||
} => {
|
} => {
|
||||||
let frame = self.add_label(name);
|
let frame = self.add_label(name);
|
||||||
for (i, &(name, ty)) in args.iter().enumerate() {
|
for (i, &(name, ty)) in args.iter().enumerate() {
|
||||||
|
@ -310,8 +356,20 @@ impl<'a> Codegen<'a> {
|
||||||
self.ret();
|
self.ret();
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
E::BinOp {
|
||||||
|
left: E::Ident { name, .. },
|
||||||
|
op: T::Decl,
|
||||||
|
right,
|
||||||
|
} => {
|
||||||
|
let val = self.expr(right, None).unwrap();
|
||||||
|
let reg = self.loc_to_reg(val.loc);
|
||||||
|
let offset = self.alloc_stack(8);
|
||||||
|
self.decl_var(name, offset, val.ty);
|
||||||
|
self.store_stack(reg, offset, 8);
|
||||||
|
None
|
||||||
|
}
|
||||||
E::Call {
|
E::Call {
|
||||||
func: E::Ident { name },
|
func: E::Ident { name, .. },
|
||||||
args,
|
args,
|
||||||
} => {
|
} => {
|
||||||
for (i, arg) in args.iter().enumerate() {
|
for (i, arg) in args.iter().enumerate() {
|
||||||
|
@ -328,22 +386,14 @@ impl<'a> Codegen<'a> {
|
||||||
loc: Loc::Reg(reg),
|
loc: Loc::Reg(reg),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
E::Decl { name, val } => {
|
E::Ident { name, .. } => {
|
||||||
let val = self.expr(val, None).unwrap();
|
|
||||||
let reg = self.loc_to_reg(val.loc);
|
|
||||||
let offset = self.alloc_stack(8);
|
|
||||||
self.decl_var(name, offset, val.ty);
|
|
||||||
self.store_stack(reg, offset, 8);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
E::Ident { name } => {
|
|
||||||
let var = self.vars.iter().find(|v| v.name.as_ref() == name).unwrap();
|
let var = self.vars.iter().find(|v| v.name.as_ref() == name).unwrap();
|
||||||
Some(Value {
|
Some(Value {
|
||||||
ty: var.ty,
|
ty: var.ty,
|
||||||
loc: Loc::Stack(var.offset),
|
loc: Loc::Stack(var.offset),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
E::Return { val } => {
|
E::Return { val, .. } => {
|
||||||
if let Some(val) = val {
|
if let Some(val) = val {
|
||||||
let val = self.expr(val, Some(self.ret)).unwrap();
|
let val = self.expr(val, Some(self.ret)).unwrap();
|
||||||
if val.ty != self.ret {
|
if val.ty != self.ret {
|
||||||
|
@ -365,21 +415,33 @@ impl<'a> Codegen<'a> {
|
||||||
self.code.encode(instrs::jmp(0));
|
self.code.encode(instrs::jmp(0));
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
E::Block { stmts } => {
|
E::Block { stmts, .. } => {
|
||||||
for stmt in stmts {
|
for stmt in stmts {
|
||||||
self.expr(stmt, None);
|
self.expr(stmt, None);
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
E::Number { value } => Some(Value {
|
E::Number { value, .. } => Some(Value {
|
||||||
ty: expeted.unwrap_or(Expr::Ident { name: "int" }),
|
ty: expeted.unwrap_or(Expr::Ident {
|
||||||
|
name: "int",
|
||||||
|
pos: 0,
|
||||||
|
}),
|
||||||
loc: Loc::Imm(value),
|
loc: Loc::Imm(value),
|
||||||
}),
|
}),
|
||||||
E::If { cond, then, else_ } => {
|
E::If {
|
||||||
let cond = self.expr(cond, Some(Expr::Ident { name: "bool" })).unwrap();
|
cond, then, else_, ..
|
||||||
|
} => {
|
||||||
|
let cond = self
|
||||||
|
.expr(
|
||||||
|
cond,
|
||||||
|
Some(Expr::Ident {
|
||||||
|
name: "bool",
|
||||||
|
pos: 0,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
let reg = self.loc_to_reg(cond.loc);
|
let reg = self.loc_to_reg(cond.loc);
|
||||||
let jump_offset = self.code.code.len() as u32;
|
let jump_offset = self.code.code.len() as u32;
|
||||||
println!("jump_offset: {:02x}", jump_offset);
|
|
||||||
self.code.encode(instrs::jeq(reg, 0, 0));
|
self.code.encode(instrs::jeq(reg, 0, 0));
|
||||||
self.gpa.free(reg);
|
self.gpa.free(reg);
|
||||||
|
|
||||||
|
@ -389,7 +451,6 @@ impl<'a> Codegen<'a> {
|
||||||
|
|
||||||
if let Some(else_) = else_ {
|
if let Some(else_) = else_ {
|
||||||
let else_jump_offset = self.code.code.len() as u32;
|
let else_jump_offset = self.code.code.len() as u32;
|
||||||
println!("jump_offset: {:02x}", jump_offset);
|
|
||||||
self.code.encode(instrs::jmp(0));
|
self.code.encode(instrs::jmp(0));
|
||||||
|
|
||||||
jump = self.code.code.len() as i16 - jump_offset as i16;
|
jump = self.code.code.len() as i16 - jump_offset as i16;
|
||||||
|
@ -397,20 +458,18 @@ impl<'a> Codegen<'a> {
|
||||||
self.expr(else_, None);
|
self.expr(else_, None);
|
||||||
|
|
||||||
let jump = self.code.code.len() as i32 - else_jump_offset as i32;
|
let jump = self.code.code.len() as i32 - else_jump_offset as i32;
|
||||||
println!("jump: {:02x}", jump);
|
|
||||||
self.code.code[else_jump_offset as usize + 1..][..4]
|
self.code.code[else_jump_offset as usize + 1..][..4]
|
||||||
.copy_from_slice(&jump.to_ne_bytes());
|
.copy_from_slice(&jump.to_ne_bytes());
|
||||||
} else {
|
} else {
|
||||||
jump = self.code.code.len() as i16 - jump_offset as i16;
|
jump = self.code.code.len() as i16 - jump_offset as i16;
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("jump: {:02x}", jump);
|
|
||||||
self.code.code[jump_offset as usize + 3..][..2]
|
self.code.code[jump_offset as usize + 3..][..2]
|
||||||
.copy_from_slice(&jump.to_ne_bytes());
|
.copy_from_slice(&jump.to_ne_bytes());
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
E::Loop { body } => {
|
E::Loop { body, .. } => {
|
||||||
let loop_start = self.code.code.len() as u32;
|
let loop_start = self.code.code.len() as u32;
|
||||||
self.loops.push(Loop {
|
self.loops.push(Loop {
|
||||||
offset: loop_start,
|
offset: loop_start,
|
||||||
|
@ -434,7 +493,7 @@ impl<'a> Codegen<'a> {
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
E::Break => {
|
E::Break { .. } => {
|
||||||
let loop_ = self.loops.last_mut().unwrap();
|
let loop_ = self.loops.last_mut().unwrap();
|
||||||
let offset = self.code.code.len() as u32;
|
let offset = self.code.code.len() as u32;
|
||||||
self.code.encode(instrs::jmp(0));
|
self.code.encode(instrs::jmp(0));
|
||||||
|
@ -445,7 +504,7 @@ impl<'a> Codegen<'a> {
|
||||||
});
|
});
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
E::Continue => {
|
E::Continue { .. } => {
|
||||||
let loop_ = self.loops.last().unwrap();
|
let loop_ = self.loops.last().unwrap();
|
||||||
let offset = self.code.code.len() as u32;
|
let offset = self.code.code.len() as u32;
|
||||||
self.code
|
self.code
|
||||||
|
@ -468,7 +527,10 @@ impl<'a> Codegen<'a> {
|
||||||
self.gpa.free(rhs);
|
self.gpa.free(rhs);
|
||||||
self.code.encode(instrs::cmpui(lhs, lhs, 1));
|
self.code.encode(instrs::cmpui(lhs, lhs, 1));
|
||||||
return Some(Value {
|
return Some(Value {
|
||||||
ty: Expr::Ident { name: "bool" },
|
ty: Expr::Ident {
|
||||||
|
name: "bool",
|
||||||
|
pos: 0,
|
||||||
|
},
|
||||||
loc: Loc::Reg(lhs),
|
loc: Loc::Reg(lhs),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -478,7 +540,10 @@ impl<'a> Codegen<'a> {
|
||||||
self.code.encode(instrs::cmpui(lhs, lhs, 0));
|
self.code.encode(instrs::cmpui(lhs, lhs, 0));
|
||||||
self.code.encode(instrs::not(lhs, lhs));
|
self.code.encode(instrs::not(lhs, lhs));
|
||||||
return Some(Value {
|
return Some(Value {
|
||||||
ty: Expr::Ident { name: "bool" },
|
ty: Expr::Ident {
|
||||||
|
name: "bool",
|
||||||
|
pos: 0,
|
||||||
|
},
|
||||||
loc: Loc::Reg(lhs),
|
loc: Loc::Reg(lhs),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -612,7 +677,7 @@ pub enum Loc {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::instrs;
|
use crate::{instrs, log};
|
||||||
|
|
||||||
struct TestMem;
|
struct TestMem;
|
||||||
|
|
||||||
|
@ -624,7 +689,7 @@ mod tests {
|
||||||
target: *mut u8,
|
target: *mut u8,
|
||||||
count: usize,
|
count: usize,
|
||||||
) -> Result<(), hbvm::mem::LoadError> {
|
) -> Result<(), hbvm::mem::LoadError> {
|
||||||
println!(
|
log::dbg!(
|
||||||
"read: {:x} {} {:?}",
|
"read: {:x} {} {:?}",
|
||||||
addr.get(),
|
addr.get(),
|
||||||
count,
|
count,
|
||||||
|
@ -646,14 +711,14 @@ mod tests {
|
||||||
source: *const u8,
|
source: *const u8,
|
||||||
count: usize,
|
count: usize,
|
||||||
) -> Result<(), hbvm::mem::StoreError> {
|
) -> Result<(), hbvm::mem::StoreError> {
|
||||||
println!("write: {:x} {}", addr.get(), count);
|
log::dbg!("write: {:x} {}", addr.get(), count);
|
||||||
unsafe { core::ptr::copy(source, addr.get() as *mut u8, count) }
|
unsafe { core::ptr::copy(source, addr.get() as *mut u8, count) }
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn prog_read<T: Copy>(&mut self, addr: hbvm::mem::Address) -> T {
|
unsafe fn prog_read<T: Copy>(&mut self, addr: hbvm::mem::Address) -> T {
|
||||||
println!(
|
log::dbg!(
|
||||||
"read-typed: {:x} {} {:?}",
|
"read-typed: {:x} {} {:?}",
|
||||||
addr.get(),
|
addr.get(),
|
||||||
std::any::type_name::<T>(),
|
std::any::type_name::<T>(),
|
||||||
|
|
|
@ -11,87 +11,104 @@ impl Token {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
macro_rules! gen_token_kind {
|
||||||
pub enum TokenKind {
|
($(
|
||||||
Ident,
|
#[$atts:meta])*
|
||||||
Number,
|
$vis:vis enum $name:ident {
|
||||||
LParen,
|
#[patterns] $(
|
||||||
RParen,
|
$pattern:ident,
|
||||||
LBrace,
|
)*
|
||||||
RBrace,
|
#[keywords] $(
|
||||||
LBrack,
|
$keyword:ident = $keyword_lit:literal,
|
||||||
RBrack,
|
)*
|
||||||
Decl,
|
#[punkt] $(
|
||||||
Assign,
|
$punkt:ident = $punkt_lit:literal,
|
||||||
Plus,
|
)*
|
||||||
Minus,
|
#[ops] $(
|
||||||
Star,
|
#[prec = $prec:literal] $(
|
||||||
FSlash,
|
$op:ident = $op_lit:literal,
|
||||||
Bor,
|
)*
|
||||||
Or,
|
)*
|
||||||
Le,
|
|
||||||
Eq,
|
|
||||||
Semi,
|
|
||||||
Colon,
|
|
||||||
Comma,
|
|
||||||
Return,
|
|
||||||
If,
|
|
||||||
Else,
|
|
||||||
Loop,
|
|
||||||
Break,
|
|
||||||
Continue,
|
|
||||||
Eof,
|
|
||||||
Error,
|
|
||||||
}
|
}
|
||||||
|
) => {
|
||||||
impl std::fmt::Display for TokenKind {
|
impl std::fmt::Display for $name {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
use TokenKind as T;
|
let s = match *self {
|
||||||
let s = match self {
|
$( Self::$pattern => concat!('<', stringify!($pattern), '>'), )*
|
||||||
T::Ident => "<identifier>",
|
|
||||||
T::Number => "<number>",
|
$( Self::$keyword => stringify!($keyword_lit), )*
|
||||||
T::LParen => "(",
|
$( Self::$punkt => stringify!($punkt_lit), )*
|
||||||
T::RParen => ")",
|
$($( Self::$op => $op_lit, )*)*
|
||||||
T::LBrace => "{",
|
|
||||||
T::RBrace => "}",
|
|
||||||
T::LBrack => "[",
|
|
||||||
T::RBrack => "]",
|
|
||||||
T::Decl => ":=",
|
|
||||||
T::Assign => "=",
|
|
||||||
T::Plus => "+",
|
|
||||||
T::Minus => "-",
|
|
||||||
T::Star => "*",
|
|
||||||
T::FSlash => "/",
|
|
||||||
T::Bor => "|",
|
|
||||||
T::Or => "||",
|
|
||||||
T::Le => "<=",
|
|
||||||
T::Eq => "==",
|
|
||||||
T::Semi => ";",
|
|
||||||
T::Colon => ":",
|
|
||||||
T::Comma => ",",
|
|
||||||
T::Return => "return",
|
|
||||||
T::If => "if",
|
|
||||||
T::Else => "else",
|
|
||||||
T::Loop => "loop",
|
|
||||||
T::Break => "break",
|
|
||||||
T::Continue => "continue",
|
|
||||||
T::Eof => "<eof>",
|
|
||||||
T::Error => "<error>",
|
|
||||||
};
|
};
|
||||||
write!(f, "{}", s)
|
f.write_str(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TokenKind {
|
impl $name {
|
||||||
|
#[inline(always)]
|
||||||
pub fn precedence(&self) -> Option<u8> {
|
pub fn precedence(&self) -> Option<u8> {
|
||||||
Some(match self {
|
Some(match self {
|
||||||
Self::Assign => 1,
|
$($(Self::$op)|* => $prec,)*
|
||||||
Self::Le | Self::Eq => 21,
|
|
||||||
Self::Plus | Self::Minus => 23,
|
|
||||||
Self::Star | Self::FSlash => 24,
|
|
||||||
_ => return None,
|
_ => return None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn from_ident(ident: &[u8]) -> Self {
|
||||||
|
match ident {
|
||||||
|
$($keyword_lit => Self::$keyword,)*
|
||||||
|
_ => Self::Ident,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
|
$vis enum $name {
|
||||||
|
$( $pattern, )*
|
||||||
|
$( $keyword, )*
|
||||||
|
$( $punkt, )*
|
||||||
|
$($( $op, )*)*
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
gen_token_kind! {
|
||||||
|
pub enum TokenKind {
|
||||||
|
#[patterns]
|
||||||
|
Ident,
|
||||||
|
Number,
|
||||||
|
Eof,
|
||||||
|
Error,
|
||||||
|
#[keywords]
|
||||||
|
Return = b"return",
|
||||||
|
If = b"if",
|
||||||
|
Else = b"else",
|
||||||
|
Loop = b"loop",
|
||||||
|
Break = b"break",
|
||||||
|
Continue = b"continue",
|
||||||
|
Fn = b"fn",
|
||||||
|
#[punkt]
|
||||||
|
LParen = b'(',
|
||||||
|
RParen = b')',
|
||||||
|
LBrace = b'{',
|
||||||
|
RBrace = b'}',
|
||||||
|
Semi = b';',
|
||||||
|
Colon = b':',
|
||||||
|
Comma = b',',
|
||||||
|
#[ops]
|
||||||
|
#[prec = 1]
|
||||||
|
Decl = ":=",
|
||||||
|
Assign = "=",
|
||||||
|
#[prec = 21]
|
||||||
|
Le = "<=",
|
||||||
|
Eq = "==",
|
||||||
|
#[prec = 23]
|
||||||
|
Plus = "+",
|
||||||
|
Minus = "-",
|
||||||
|
#[prec = 24]
|
||||||
|
Star = "*",
|
||||||
|
FSlash = "/",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Lexer<'a> {
|
pub struct Lexer<'a> {
|
||||||
|
@ -174,44 +191,23 @@ impl<'a> Iterator for Lexer<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let ident = &self.bytes[start as usize..self.pos as usize];
|
let ident = &self.bytes[start as usize..self.pos as usize];
|
||||||
match ident {
|
T::from_ident(ident)
|
||||||
b"return" => T::Return,
|
|
||||||
b"if" => T::If,
|
|
||||||
b"else" => T::Else,
|
|
||||||
b"loop" => T::Loop,
|
|
||||||
b"break" => T::Break,
|
|
||||||
b"continue" => T::Continue,
|
|
||||||
_ => T::Ident,
|
|
||||||
}
|
}
|
||||||
}
|
b':' if self.advance_if(b'=') => T::Decl,
|
||||||
b':' => match self.advance_if(b'=') {
|
b':' => T::Colon,
|
||||||
true => T::Decl,
|
|
||||||
false => T::Colon,
|
|
||||||
},
|
|
||||||
b',' => T::Comma,
|
b',' => T::Comma,
|
||||||
b';' => T::Semi,
|
b';' => T::Semi,
|
||||||
b'=' => match self.advance_if(b'=') {
|
b'=' if self.advance_if(b'=') => T::Eq,
|
||||||
true => T::Eq,
|
b'=' => T::Assign,
|
||||||
false => T::Assign,
|
b'<' if self.advance_if(b'=') => T::Le,
|
||||||
},
|
|
||||||
b'<' => match self.advance_if(b'=') {
|
|
||||||
true => T::Le,
|
|
||||||
false => T::Error,
|
|
||||||
},
|
|
||||||
b'+' => T::Plus,
|
b'+' => T::Plus,
|
||||||
b'-' => T::Minus,
|
b'-' => T::Minus,
|
||||||
b'*' => T::Star,
|
b'*' => T::Star,
|
||||||
b'/' => T::FSlash,
|
b'/' => T::FSlash,
|
||||||
b'|' => match self.advance_if(b'|') {
|
|
||||||
true => T::Or,
|
|
||||||
false => T::Bor,
|
|
||||||
},
|
|
||||||
b'(' => T::LParen,
|
b'(' => T::LParen,
|
||||||
b')' => T::RParen,
|
b')' => T::RParen,
|
||||||
b'{' => T::LBrace,
|
b'{' => T::LBrace,
|
||||||
b'}' => T::RBrace,
|
b'}' => T::RBrace,
|
||||||
b'[' => T::LBrack,
|
|
||||||
b']' => T::RBrack,
|
|
||||||
_ => T::Error,
|
_ => T::Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#![feature(noop_waker)]
|
#![feature(noop_waker)]
|
||||||
|
#![feature(macro_metavar_expr)]
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
#![feature(non_null_convenience)]
|
#![feature(non_null_convenience)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
@ -18,6 +19,7 @@ mod codegen;
|
||||||
mod ident;
|
mod ident;
|
||||||
mod instrs;
|
mod instrs;
|
||||||
mod lexer;
|
mod lexer;
|
||||||
|
mod log;
|
||||||
mod parser;
|
mod parser;
|
||||||
mod tests;
|
mod tests;
|
||||||
mod typechk;
|
mod typechk;
|
||||||
|
|
48
hblang/src/log.rs
Normal file
48
hblang/src/log.rs
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
#![allow(unused_macros)]
|
||||||
|
|
||||||
|
#[derive(PartialOrd, PartialEq, Ord, Eq, Debug)]
|
||||||
|
pub enum Level {
|
||||||
|
Err,
|
||||||
|
Wrn,
|
||||||
|
Inf,
|
||||||
|
Dbg,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const LOG_LEVEL: Level = match option_env!("LOG_LEVEL") {
|
||||||
|
Some(val) => match val.as_bytes()[0] {
|
||||||
|
b'e' => Level::Err,
|
||||||
|
b'w' => Level::Wrn,
|
||||||
|
b'i' => Level::Inf,
|
||||||
|
b'd' => Level::Dbg,
|
||||||
|
_ => panic!("Invalid log level."),
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
Level::Dbg
|
||||||
|
} else {
|
||||||
|
Level::Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
macro_rules! log {
|
||||||
|
($level:expr, $fmt:literal $($expr:tt)*) => {
|
||||||
|
if $level <= $crate::log::LOG_LEVEL {
|
||||||
|
println!("{:?}: {}", $level, format_args!($fmt $($expr)*));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
($level:expr, $($arg:expr),*) => {
|
||||||
|
if $level <= $crate::log::LOG_LEVEL {
|
||||||
|
$(println!("[{}{}{}][{:?}]: {} = {:?}", line!(), column!(), file!(), $level, stringify!($arg), $arg);)*
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! err { ($($arg:tt)*) => { $crate::log::log!($crate::log::Level::Err, $($arg)*) }; }
|
||||||
|
macro_rules! wrn { ($($arg:tt)*) => { $crate::log::log!($crate::log::Level::Wrn, $($arg)*) }; }
|
||||||
|
macro_rules! inf { ($($arg:tt)*) => { $crate::log::log!($crate::log::Level::Inf, $($arg)*) }; }
|
||||||
|
macro_rules! dbg { ($($arg:tt)*) => { $crate::log::log!($crate::log::Level::Dbg, $($arg)*) }; }
|
||||||
|
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
pub(crate) use {dbg, err, inf, log, wrn};
|
|
@ -70,69 +70,61 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unit_expr(&mut self) -> Expr<'a> {
|
fn unit_expr(&mut self) -> Expr<'a> {
|
||||||
|
use {Expr as E, TokenKind as T};
|
||||||
let token = self.next();
|
let token = self.next();
|
||||||
let mut expr = match token.kind {
|
let mut expr = match token.kind {
|
||||||
TokenKind::Ident => {
|
T::Ident => E::Ident {
|
||||||
let name = self.arena.alloc_str(self.lexer.slice(token));
|
pos: token.start,
|
||||||
if self.advance_if(TokenKind::Decl) {
|
name: self.arena.alloc_str(self.lexer.slice(token)),
|
||||||
let val = self.ptr_expr();
|
},
|
||||||
Expr::Decl { name, val }
|
T::If => E::If {
|
||||||
} else {
|
pos: token.start,
|
||||||
Expr::Ident { name }
|
cond: self.ptr_expr(),
|
||||||
}
|
then: self.ptr_expr(),
|
||||||
}
|
else_: self.advance_if(T::Else).then(|| self.ptr_expr()),
|
||||||
TokenKind::If => {
|
},
|
||||||
let cond = self.ptr_expr();
|
T::Loop => E::Loop {
|
||||||
let then = self.ptr_expr();
|
pos: token.start,
|
||||||
let else_ = self.advance_if(TokenKind::Else).then(|| self.ptr_expr());
|
|
||||||
Expr::If { cond, then, else_ }
|
|
||||||
}
|
|
||||||
TokenKind::Loop => Expr::Loop {
|
|
||||||
body: self.ptr_expr(),
|
body: self.ptr_expr(),
|
||||||
},
|
},
|
||||||
TokenKind::Break => Expr::Break,
|
T::Break => E::Break { pos: token.start },
|
||||||
TokenKind::Continue => Expr::Continue,
|
T::Continue => E::Continue { pos: token.start },
|
||||||
TokenKind::Return => Expr::Return {
|
T::Return => E::Return {
|
||||||
val: (self.token.kind != TokenKind::Semi).then(|| self.ptr_expr()),
|
pos: token.start,
|
||||||
|
val: (self.token.kind != T::Semi).then(|| self.ptr_expr()),
|
||||||
},
|
},
|
||||||
TokenKind::Or => {
|
T::Fn => E::Closure {
|
||||||
self.expect_advance(TokenKind::Colon);
|
pos: token.start,
|
||||||
let ret = self.ptr_expr();
|
args: {
|
||||||
let body = self.ptr_expr();
|
self.expect_advance(T::LParen);
|
||||||
Expr::Closure {
|
self.collect_list(T::Comma, T::RParen, |s| {
|
||||||
ret,
|
let name = s.expect_advance(T::Ident);
|
||||||
body,
|
|
||||||
args: &[],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TokenKind::Bor => {
|
|
||||||
let args = self.collect(|s| {
|
|
||||||
s.advance_if(TokenKind::Bor).not().then(|| {
|
|
||||||
let name = s.expect_advance(TokenKind::Ident);
|
|
||||||
let name = s.arena.alloc_str(s.lexer.slice(name));
|
let name = s.arena.alloc_str(s.lexer.slice(name));
|
||||||
s.expect_advance(TokenKind::Colon);
|
s.expect_advance(T::Colon);
|
||||||
let val = s.expr();
|
let val = s.expr();
|
||||||
s.advance_if(TokenKind::Comma);
|
|
||||||
(name, val)
|
(name, val)
|
||||||
})
|
})
|
||||||
});
|
|
||||||
self.expect_advance(TokenKind::Colon);
|
|
||||||
let ret = self.ptr_expr();
|
|
||||||
let body = self.ptr_expr();
|
|
||||||
Expr::Closure { args, ret, body }
|
|
||||||
}
|
|
||||||
TokenKind::LBrace => Expr::Block {
|
|
||||||
stmts: self.collect(|s| (!s.advance_if(TokenKind::RBrace)).then(|| s.expr())),
|
|
||||||
},
|
},
|
||||||
TokenKind::Number => Expr::Number {
|
ret: {
|
||||||
|
self.expect_advance(T::Colon);
|
||||||
|
self.ptr_expr()
|
||||||
|
},
|
||||||
|
body: self.ptr_expr(),
|
||||||
|
},
|
||||||
|
T::LBrace => E::Block {
|
||||||
|
pos: token.start,
|
||||||
|
stmts: self.collect_list(T::Semi, T::RBrace, Self::expr),
|
||||||
|
},
|
||||||
|
T::Number => E::Number {
|
||||||
|
pos: token.start,
|
||||||
value: match self.lexer.slice(token).parse() {
|
value: match self.lexer.slice(token).parse() {
|
||||||
Ok(value) => value,
|
Ok(value) => value,
|
||||||
Err(e) => self.report(format_args!("invalid number: {e}")),
|
Err(e) => self.report(format_args!("invalid number: {e}")),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
TokenKind::LParen => {
|
T::LParen => {
|
||||||
let expr = self.expr();
|
let expr = self.expr();
|
||||||
self.expect_advance(TokenKind::RParen);
|
self.expect_advance(T::RParen);
|
||||||
expr
|
expr
|
||||||
}
|
}
|
||||||
tok => self.report(format_args!("unexpected token: {tok:?}")),
|
tok => self.report(format_args!("unexpected token: {tok:?}")),
|
||||||
|
@ -144,13 +136,7 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
self.next();
|
self.next();
|
||||||
Expr::Call {
|
Expr::Call {
|
||||||
func: self.arena.alloc(expr),
|
func: self.arena.alloc(expr),
|
||||||
args: self.collect(|s| {
|
args: self.collect_list(TokenKind::Comma, TokenKind::RParen, Self::expr),
|
||||||
s.advance_if(TokenKind::RParen).not().then(|| {
|
|
||||||
let arg = s.expr();
|
|
||||||
s.advance_if(TokenKind::Comma);
|
|
||||||
arg
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => break,
|
_ => break,
|
||||||
|
@ -162,6 +148,21 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
expr
|
expr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn collect_list<T: Copy>(
|
||||||
|
&mut self,
|
||||||
|
delim: TokenKind,
|
||||||
|
end: TokenKind,
|
||||||
|
mut f: impl FnMut(&mut Self) -> T,
|
||||||
|
) -> &'a [T] {
|
||||||
|
self.collect(|s| {
|
||||||
|
s.advance_if(end).not().then(|| {
|
||||||
|
let val = f(s);
|
||||||
|
s.advance_if(delim);
|
||||||
|
val
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn collect<T: Copy>(&mut self, mut f: impl FnMut(&mut Self) -> Option<T>) -> &'a [T] {
|
fn collect<T: Copy>(&mut self, mut f: impl FnMut(&mut Self) -> Option<T>) -> &'a [T] {
|
||||||
let vec = std::iter::from_fn(|| f(self)).collect::<Vec<_>>();
|
let vec = std::iter::from_fn(|| f(self)).collect::<Vec<_>>();
|
||||||
self.arena.alloc_slice(&vec)
|
self.arena.alloc_slice(&vec)
|
||||||
|
@ -195,13 +196,14 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum Expr<'a> {
|
pub enum Expr<'a> {
|
||||||
Break,
|
Break {
|
||||||
Continue,
|
pos: u32,
|
||||||
Decl {
|
},
|
||||||
name: &'a str,
|
Continue {
|
||||||
val: &'a Expr<'a>,
|
pos: u32,
|
||||||
},
|
},
|
||||||
Closure {
|
Closure {
|
||||||
|
pos: u32,
|
||||||
args: &'a [(&'a str, Expr<'a>)],
|
args: &'a [(&'a str, Expr<'a>)],
|
||||||
ret: &'a Expr<'a>,
|
ret: &'a Expr<'a>,
|
||||||
body: &'a Expr<'a>,
|
body: &'a Expr<'a>,
|
||||||
|
@ -211,15 +213,19 @@ pub enum Expr<'a> {
|
||||||
args: &'a [Expr<'a>],
|
args: &'a [Expr<'a>],
|
||||||
},
|
},
|
||||||
Return {
|
Return {
|
||||||
|
pos: u32,
|
||||||
val: Option<&'a Expr<'a>>,
|
val: Option<&'a Expr<'a>>,
|
||||||
},
|
},
|
||||||
Ident {
|
Ident {
|
||||||
|
pos: u32,
|
||||||
name: &'a str,
|
name: &'a str,
|
||||||
},
|
},
|
||||||
Block {
|
Block {
|
||||||
|
pos: u32,
|
||||||
stmts: &'a [Expr<'a>],
|
stmts: &'a [Expr<'a>],
|
||||||
},
|
},
|
||||||
Number {
|
Number {
|
||||||
|
pos: u32,
|
||||||
value: u64,
|
value: u64,
|
||||||
},
|
},
|
||||||
BinOp {
|
BinOp {
|
||||||
|
@ -228,11 +234,13 @@ pub enum Expr<'a> {
|
||||||
right: &'a Expr<'a>,
|
right: &'a Expr<'a>,
|
||||||
},
|
},
|
||||||
If {
|
If {
|
||||||
|
pos: u32,
|
||||||
cond: &'a Expr<'a>,
|
cond: &'a Expr<'a>,
|
||||||
then: &'a Expr<'a>,
|
then: &'a Expr<'a>,
|
||||||
else_: Option<&'a Expr<'a>>,
|
else_: Option<&'a Expr<'a>>,
|
||||||
},
|
},
|
||||||
Loop {
|
Loop {
|
||||||
|
pos: u32,
|
||||||
body: &'a Expr<'a>,
|
body: &'a Expr<'a>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -244,18 +252,21 @@ impl<'a> std::fmt::Display for Expr<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
Self::Break => write!(f, "break;"),
|
Self::Break { .. } => write!(f, "break;"),
|
||||||
Self::Continue => write!(f, "continue;"),
|
Self::Continue { .. } => write!(f, "continue;"),
|
||||||
Self::If { cond, then, else_ } => {
|
Self::If {
|
||||||
|
cond, then, else_, ..
|
||||||
|
} => {
|
||||||
write!(f, "if {} {}", cond, then)?;
|
write!(f, "if {} {}", cond, then)?;
|
||||||
if let Some(else_) = else_ {
|
if let Some(else_) = else_ {
|
||||||
write!(f, " else {}", else_)?;
|
write!(f, " else {}", else_)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Self::Loop { body } => write!(f, "loop {}", body),
|
Self::Loop { body, .. } => write!(f, "loop {}", body),
|
||||||
Self::Decl { name, val } => write!(f, "{} := {}", name, val),
|
Self::Closure {
|
||||||
Self::Closure { ret, body, args } => {
|
ret, body, args, ..
|
||||||
|
} => {
|
||||||
write!(f, "|")?;
|
write!(f, "|")?;
|
||||||
let first = &mut true;
|
let first = &mut true;
|
||||||
for (name, val) in args {
|
for (name, val) in args {
|
||||||
|
@ -277,10 +288,10 @@ impl<'a> std::fmt::Display for Expr<'a> {
|
||||||
}
|
}
|
||||||
write!(f, ")")
|
write!(f, ")")
|
||||||
}
|
}
|
||||||
Self::Return { val: Some(val) } => write!(f, "return {};", val),
|
Self::Return { val: Some(val), .. } => write!(f, "return {};", val),
|
||||||
Self::Return { val: None } => write!(f, "return;"),
|
Self::Return { val: None, .. } => write!(f, "return;"),
|
||||||
Self::Ident { name } => write!(f, "{}", name),
|
Self::Ident { name, .. } => write!(f, "{}", name),
|
||||||
Self::Block { stmts } => {
|
Self::Block { stmts, .. } => {
|
||||||
writeln!(f, "{{")?;
|
writeln!(f, "{{")?;
|
||||||
INDENT.with(|i| i.set(i.get() + 1));
|
INDENT.with(|i| i.set(i.get() + 1));
|
||||||
let res = (|| {
|
let res = (|| {
|
||||||
|
@ -296,7 +307,7 @@ impl<'a> std::fmt::Display for Expr<'a> {
|
||||||
write!(f, "}}")?;
|
write!(f, "}}")?;
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
Self::Number { value } => write!(f, "{}", value),
|
Self::Number { value, .. } => write!(f, "{}", value),
|
||||||
Self::BinOp { left, right, op } => {
|
Self::BinOp { left, right, op } => {
|
||||||
let display_branch = |f: &mut std::fmt::Formatter, expr: &Self| {
|
let display_branch = |f: &mut std::fmt::Formatter, expr: &Self| {
|
||||||
if let Self::BinOp { op: lop, .. } = expr
|
if let Self::BinOp { op: lop, .. } = expr
|
||||||
|
|
BIN
hblang/test.bin
BIN
hblang/test.bin
Binary file not shown.
|
@ -1,6 +1,8 @@
|
||||||
Ident "main"
|
Ident "main"
|
||||||
Decl ":="
|
Decl ":="
|
||||||
Or "||"
|
Fn "fn"
|
||||||
|
LParen "("
|
||||||
|
RParen ")"
|
||||||
Colon ":"
|
Colon ":"
|
||||||
Ident "int"
|
Ident "int"
|
||||||
LBrace "{"
|
LBrace "{"
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
Ident "main"
|
Ident "main"
|
||||||
Decl ":="
|
Decl ":="
|
||||||
Or "||"
|
Fn "fn"
|
||||||
|
LParen "("
|
||||||
|
RParen ")"
|
||||||
Colon ":"
|
Colon ":"
|
||||||
Ident "int"
|
Ident "int"
|
||||||
LBrace "{"
|
LBrace "{"
|
||||||
|
|
84
spec.md
84
spec.md
|
@ -50,7 +50,7 @@ of offset in the code. Not from the beginning of current or following instructio
|
||||||
|
|
||||||
## Rounding modes
|
## Rounding modes
|
||||||
| Rounding mode | Value |
|
| Rounding mode | Value |
|
||||||
|:-------------------------|:------|
|
fn():------|
|
||||||
| To nearest, ties to even | 0b00 |
|
| To nearest, ties to even | 0b00 |
|
||||||
| Towards 0 (truncate) | 0b01 |
|
| Towards 0 (truncate) | 0b01 |
|
||||||
| Towards +∞ (up) | 0b10 |
|
| Towards +∞ (up) | 0b10 |
|
||||||
|
@ -89,7 +89,7 @@ Program counter stays on the currently executed instruction
|
||||||
- Type `N`
|
- Type `N`
|
||||||
|
|
||||||
| Opcode | Mnemonic | Action |
|
| Opcode | Mnemonic | Action |
|
||||||
|:-------|:---------|:--------------------------------------------|
|
fn():--------------------------------------------|
|
||||||
| 0x00 | UN | Throw unreachable code exception |
|
| 0x00 | UN | Throw unreachable code exception |
|
||||||
| 0x01 | TX | Terminate execution (eg. on end of program) |
|
| 0x01 | TX | Terminate execution (eg. on end of program) |
|
||||||
| 0x02 | NOP | Do nothing |
|
| 0x02 | NOP | Do nothing |
|
||||||
|
@ -100,7 +100,7 @@ Program counter stays on the currently executed instruction
|
||||||
|
|
||||||
## Addition (`+`)
|
## Addition (`+`)
|
||||||
| Opcode | Mnemonic | Type |
|
| Opcode | Mnemonic | Type |
|
||||||
|:-------|:---------|:-----|
|
fn():-----|
|
||||||
| 0x03 | ADD8 | Xi8 |
|
| 0x03 | ADD8 | Xi8 |
|
||||||
| 0x04 | ADD16 | Xi16 |
|
| 0x04 | ADD16 | Xi16 |
|
||||||
| 0x05 | ADD32 | Xi32 |
|
| 0x05 | ADD32 | Xi32 |
|
||||||
|
@ -108,7 +108,7 @@ Program counter stays on the currently executed instruction
|
||||||
|
|
||||||
## Subtraction (`-`)
|
## Subtraction (`-`)
|
||||||
| Opcode | Mnemonic | Type |
|
| Opcode | Mnemonic | Type |
|
||||||
|:-------|:---------|:-----|
|
fn():-----|
|
||||||
| 0x07 | SUB8 | Xi8 |
|
| 0x07 | SUB8 | Xi8 |
|
||||||
| 0x08 | SUB16 | Xi16 |
|
| 0x08 | SUB16 | Xi16 |
|
||||||
| 0x09 | SUB32 | Xi32 |
|
| 0x09 | SUB32 | Xi32 |
|
||||||
|
@ -116,7 +116,7 @@ Program counter stays on the currently executed instruction
|
||||||
|
|
||||||
## Multiplication (`*`)
|
## Multiplication (`*`)
|
||||||
| Opcode | Mnemonic | Type |
|
| Opcode | Mnemonic | Type |
|
||||||
|:-------|:---------|:-----|
|
fn():-----|
|
||||||
| 0x0B | MUL8 | Xi8 |
|
| 0x0B | MUL8 | Xi8 |
|
||||||
| 0x0C | MUL16 | Xi16 |
|
| 0x0C | MUL16 | Xi16 |
|
||||||
| 0x0D | MUL32 | Xi32 |
|
| 0x0D | MUL32 | Xi32 |
|
||||||
|
@ -124,14 +124,14 @@ Program counter stays on the currently executed instruction
|
||||||
|
|
||||||
## Bitwise ops (type: Xi64)
|
## Bitwise ops (type: Xi64)
|
||||||
| Opcode | Mnemonic | Operation |
|
| Opcode | Mnemonic | Operation |
|
||||||
|:-------|:---------|:--------------------|
|
fn():--------------------|
|
||||||
| 0x0F | AND | Conjunction (&) |
|
| 0x0F | AND | Conjunction (&) |
|
||||||
| 0x10 | OR | Disjunction (\|) |
|
| 0x10 | OR | Disjunction (\|) |
|
||||||
| 0x11 | XOR | Non-equivalence (^) |
|
| 0x11 | XOR | Non-equivalence (^) |
|
||||||
|
|
||||||
## Unsigned left bitshift (`<<`)
|
## Unsigned left bitshift (`<<`)
|
||||||
| Opcode | Mnemonic | Type |
|
| Opcode | Mnemonic | Type |
|
||||||
|:-------|:---------|:-----|
|
fn():-----|
|
||||||
| 0x12 | SLU8 | Ui8 |
|
| 0x12 | SLU8 | Ui8 |
|
||||||
| 0x13 | SLU16 | Ui16 |
|
| 0x13 | SLU16 | Ui16 |
|
||||||
| 0x14 | SLU32 | Ui32 |
|
| 0x14 | SLU32 | Ui32 |
|
||||||
|
@ -139,7 +139,7 @@ Program counter stays on the currently executed instruction
|
||||||
|
|
||||||
## Unsigned right bitshift (`>>`)
|
## Unsigned right bitshift (`>>`)
|
||||||
| Opcode | Mnemonic | Type |
|
| Opcode | Mnemonic | Type |
|
||||||
|:-------|:---------|:-----|
|
fn():-----|
|
||||||
| 0x16 | SRU8 | Ui8 |
|
| 0x16 | SRU8 | Ui8 |
|
||||||
| 0x17 | SRU16 | Ui16 |
|
| 0x17 | SRU16 | Ui16 |
|
||||||
| 0x18 | SRU32 | Ui32 |
|
| 0x18 | SRU32 | Ui32 |
|
||||||
|
@ -147,7 +147,7 @@ Program counter stays on the currently executed instruction
|
||||||
|
|
||||||
## Signed right bitshift (`>>`)
|
## Signed right bitshift (`>>`)
|
||||||
| Opcode | Mnemonic | Type |
|
| Opcode | Mnemonic | Type |
|
||||||
|:-------|:---------|:-----|
|
fn():-----|
|
||||||
| 0x1A | SRS8 | Si8 |
|
| 0x1A | SRS8 | Si8 |
|
||||||
| 0x1B | SRS16 | Si16 |
|
| 0x1B | SRS16 | Si16 |
|
||||||
| 0x1C | SRS32 | Si32 |
|
| 0x1C | SRS32 | Si32 |
|
||||||
|
@ -158,13 +158,13 @@ Program counter stays on the currently executed instruction
|
||||||
- Operation: `#0 ← #1 <=> #2`
|
- Operation: `#0 ← #1 <=> #2`
|
||||||
|
|
||||||
| Ordering | Number |
|
| Ordering | Number |
|
||||||
|:---------|:-------|
|
fn():-------|
|
||||||
| < | -1 |
|
| < | -1 |
|
||||||
| = | 0 |
|
| = | 0 |
|
||||||
| > | 1 |
|
| > | 1 |
|
||||||
|
|
||||||
| Opcode | Mnemonic | Type |
|
| Opcode | Mnemonic | Type |
|
||||||
|:-------|:---------|:-----|
|
fn():-----|
|
||||||
| 0x1E | CMPU | Ui64 |
|
| 0x1E | CMPU | Ui64 |
|
||||||
| 0x1F | CMPS | Si64 |
|
| 0x1F | CMPS | Si64 |
|
||||||
|
|
||||||
|
@ -179,7 +179,7 @@ Program counter stays on the currently executed instruction
|
||||||
- `#1 ← #2`
|
- `#1 ← #2`
|
||||||
|
|
||||||
| Opcode | Mnemonic | Type |
|
| Opcode | Mnemonic | Type |
|
||||||
|:-------|:---------|:-----|
|
fn():-----|
|
||||||
| 0x20 | DIRU8 | Ui8 |
|
| 0x20 | DIRU8 | Ui8 |
|
||||||
| 0x21 | DIRU16 | Ui16 |
|
| 0x21 | DIRU16 | Ui16 |
|
||||||
| 0x22 | DIRU32 | Ui32 |
|
| 0x22 | DIRU32 | Ui32 |
|
||||||
|
@ -194,7 +194,7 @@ Program counter stays on the currently executed instruction
|
||||||
- Operation: `#0 ← <OP> #1`
|
- Operation: `#0 ← <OP> #1`
|
||||||
|
|
||||||
| Opcode | Mnemonic | Operation |
|
| Opcode | Mnemonic | Operation |
|
||||||
|:-------|:---------|:-------------------------|
|
fn():-------------------------|
|
||||||
| 0x28 | NEG | Bitwise complement (`~`) |
|
| 0x28 | NEG | Bitwise complement (`~`) |
|
||||||
| 0x29 | NOT | Logical negation (`!`) |
|
| 0x29 | NOT | Logical negation (`!`) |
|
||||||
|
|
||||||
|
@ -202,7 +202,7 @@ Program counter stays on the currently executed instruction
|
||||||
- Operation: `#0 ← Si64(#1)`
|
- Operation: `#0 ← Si64(#1)`
|
||||||
|
|
||||||
| Opcode | Mnemonic | Source type |
|
| Opcode | Mnemonic | Source type |
|
||||||
|:-------|:---------|:------------|
|
fn():------------|
|
||||||
| 0x2A | SXT8 | Si8 |
|
| 0x2A | SXT8 | Si8 |
|
||||||
| 0x2B | SXT16 | Si16 |
|
| 0x2B | SXT16 | Si16 |
|
||||||
| 0x2C | SXT32 | Si32 |
|
| 0x2C | SXT32 | Si32 |
|
||||||
|
@ -213,7 +213,7 @@ Program counter stays on the currently executed instruction
|
||||||
|
|
||||||
## Addition (`+`)
|
## Addition (`+`)
|
||||||
| Opcode | Mnemonic | Type |
|
| Opcode | Mnemonic | Type |
|
||||||
|:-------|:---------|:-----|
|
fn():-----|
|
||||||
| 0x2D | ADDI8 | Xi8 |
|
| 0x2D | ADDI8 | Xi8 |
|
||||||
| 0x2E | ADDI16 | Xi16 |
|
| 0x2E | ADDI16 | Xi16 |
|
||||||
| 0x2F | ADDI32 | Xi32 |
|
| 0x2F | ADDI32 | Xi32 |
|
||||||
|
@ -221,7 +221,7 @@ Program counter stays on the currently executed instruction
|
||||||
|
|
||||||
## Multiplication (`*`)
|
## Multiplication (`*`)
|
||||||
| Opcode | Mnemonic | Type |
|
| Opcode | Mnemonic | Type |
|
||||||
|:-------|:---------|:-----|
|
fn():-----|
|
||||||
| 0x31 | MULI8 | Xi8 |
|
| 0x31 | MULI8 | Xi8 |
|
||||||
| 0x32 | MULI16 | Xi16 |
|
| 0x32 | MULI16 | Xi16 |
|
||||||
| 0x33 | MULI32 | Xi32 |
|
| 0x33 | MULI32 | Xi32 |
|
||||||
|
@ -229,7 +229,7 @@ Program counter stays on the currently executed instruction
|
||||||
|
|
||||||
## Bitwise ops (type: Xi64)
|
## Bitwise ops (type: Xi64)
|
||||||
| Opcode | Mnemonic | Operation |
|
| Opcode | Mnemonic | Operation |
|
||||||
|:-------|:---------|:--------------------|
|
fn():--------------------|
|
||||||
| 0x35 | ANDI | Conjunction (&) |
|
| 0x35 | ANDI | Conjunction (&) |
|
||||||
| 0x36 | ORI | Disjunction (\|) |
|
| 0x36 | ORI | Disjunction (\|) |
|
||||||
| 0x37 | XORI | Non-equivalence (^) |
|
| 0x37 | XORI | Non-equivalence (^) |
|
||||||
|
@ -240,7 +240,7 @@ Program counter stays on the currently executed instruction
|
||||||
|
|
||||||
## Unsigned left bitshift (`<<`)
|
## Unsigned left bitshift (`<<`)
|
||||||
| Opcode | Mnemonic | Type |
|
| Opcode | Mnemonic | Type |
|
||||||
|:-------|:---------|:-----|
|
fn():-----|
|
||||||
| 0x38 | SLUI8 | Ui8 |
|
| 0x38 | SLUI8 | Ui8 |
|
||||||
| 0x39 | SLUI16 | Ui16 |
|
| 0x39 | SLUI16 | Ui16 |
|
||||||
| 0x3A | SLUI32 | Ui32 |
|
| 0x3A | SLUI32 | Ui32 |
|
||||||
|
@ -248,7 +248,7 @@ Program counter stays on the currently executed instruction
|
||||||
|
|
||||||
## Unsigned right bitshift (`>>`)
|
## Unsigned right bitshift (`>>`)
|
||||||
| Opcode | Mnemonic | Type |
|
| Opcode | Mnemonic | Type |
|
||||||
|:-------|:---------|:-----|
|
fn():-----|
|
||||||
| 0x3C | SRUI8 | Ui8 |
|
| 0x3C | SRUI8 | Ui8 |
|
||||||
| 0x3D | SRUI16 | Ui16 |
|
| 0x3D | SRUI16 | Ui16 |
|
||||||
| 0x3E | SRUI32 | Ui32 |
|
| 0x3E | SRUI32 | Ui32 |
|
||||||
|
@ -256,7 +256,7 @@ Program counter stays on the currently executed instruction
|
||||||
|
|
||||||
## Signed right bitshift (`>>`)
|
## Signed right bitshift (`>>`)
|
||||||
| Opcode | Mnemonic | Type |
|
| Opcode | Mnemonic | Type |
|
||||||
|:-------|:---------|:-----|
|
fn():-----|
|
||||||
| 0x40 | SRSI8 | Si8 |
|
| 0x40 | SRSI8 | Si8 |
|
||||||
| 0x41 | SRSI16 | Si16 |
|
| 0x41 | SRSI16 | Si16 |
|
||||||
| 0x42 | SRSI32 | Si32 |
|
| 0x42 | SRSI32 | Si32 |
|
||||||
|
@ -268,7 +268,7 @@ Program counter stays on the currently executed instruction
|
||||||
- Comparsion table same for register-register one
|
- Comparsion table same for register-register one
|
||||||
|
|
||||||
| Opcode | Mnemonic | Type |
|
| Opcode | Mnemonic | Type |
|
||||||
|:-------|:---------|:-----|
|
fn():-----|
|
||||||
| 0x44 | CMPUI | Ui64 |
|
| 0x44 | CMPUI | Ui64 |
|
||||||
| 0x45 | CMPSI | Si64 |
|
| 0x45 | CMPSI | Si64 |
|
||||||
|
|
||||||
|
@ -276,7 +276,7 @@ Program counter stays on the currently executed instruction
|
||||||
- Type: `RR`
|
- Type: `RR`
|
||||||
|
|
||||||
| Opcode | Mnemonic | Operation |
|
| Opcode | Mnemonic | Operation |
|
||||||
|:-------|:---------|:---------------------------------|
|
fn():---------------------------------|
|
||||||
| 0x46 | CP | Copy register value (`#0 ← #1`) |
|
| 0x46 | CP | Copy register value (`#0 ← #1`) |
|
||||||
| 0x47 | SWA | Swap register values (`#0 ⇆ #1`) |
|
| 0x47 | SWA | Swap register values (`#0 ⇆ #1`) |
|
||||||
|
|
||||||
|
@ -286,7 +286,7 @@ Program counter stays on the currently executed instruction
|
||||||
- Operation: `#0 ← $1`
|
- Operation: `#0 ← $1`
|
||||||
|
|
||||||
| Opcode | Mnemonic | Type |
|
| Opcode | Mnemonic | Type |
|
||||||
|:-------|:---------|:-----|
|
fn():-----|
|
||||||
| 0x48 | LI8 | Xi8 |
|
| 0x48 | LI8 | Xi8 |
|
||||||
| 0x49 | LI16 | Xi16 |
|
| 0x49 | LI16 | Xi16 |
|
||||||
| 0x4A | Li32 | Xi32 |
|
| 0x4A | Li32 | Xi32 |
|
||||||
|
@ -298,7 +298,7 @@ Program counter stays on the currently executed instruction
|
||||||
- Operation: `#0 ← pc + #1 + $2`
|
- Operation: `#0 ← pc + #1 + $2`
|
||||||
|
|
||||||
| Opcode | Mnemonic |
|
| Opcode | Mnemonic |
|
||||||
|:-------|:---------|
|
fn():---------|
|
||||||
| 0x4C | LRA |
|
| 0x4C | LRA |
|
||||||
|
|
||||||
# Memory access operations
|
# Memory access operations
|
||||||
|
@ -313,7 +313,7 @@ Program counter stays on the currently executed instruction
|
||||||
- Computes address from base register and absolute offset
|
- Computes address from base register and absolute offset
|
||||||
|
|
||||||
| Opcode | Mnemonic | Operation |
|
| Opcode | Mnemonic | Operation |
|
||||||
|:-------|:---------|:-------------------|
|
fn():-------------------|
|
||||||
| 0x4D | LD | `#0 ← $3[#1 + $2]` |
|
| 0x4D | LD | `#0 ← $3[#1 + $2]` |
|
||||||
| 0x4E | ST | `$3[#1 + $2] ← #0` |
|
| 0x4E | ST | `$3[#1 + $2] ← #0` |
|
||||||
|
|
||||||
|
@ -322,7 +322,7 @@ Program counter stays on the currently executed instruction
|
||||||
- Computes address from register and offset from program counter
|
- Computes address from register and offset from program counter
|
||||||
|
|
||||||
| Opcode | Mnemonic | Operation |
|
| Opcode | Mnemonic | Operation |
|
||||||
|:-------|:---------|:------------------------|
|
fn():------------------------|
|
||||||
| 0x4F | LDR | `#0 ← $3[pc + #1 + $2]` |
|
| 0x4F | LDR | `#0 ← $3[pc + #1 + $2]` |
|
||||||
| 0x50 | STR | `$3[pc + #1 + $2] ← #0` |
|
| 0x50 | STR | `$3[pc + #1 + $2] ← #0` |
|
||||||
|
|
||||||
|
@ -331,7 +331,7 @@ Program counter stays on the currently executed instruction
|
||||||
- Copies block of `$3` bytes from memory location on address on `#0` to `#1`
|
- Copies block of `$3` bytes from memory location on address on `#0` to `#1`
|
||||||
|
|
||||||
| Opcode | Mnemonic | Operation |
|
| Opcode | Mnemonic | Operation |
|
||||||
|:-------|:---------|:------------------|
|
fn():------------------|
|
||||||
| 0x51 | BMC | `$3[#1] ← $3[x0]` |
|
| 0x51 | BMC | `$3[#1] ← $3[x0]` |
|
||||||
|
|
||||||
# Block register copy
|
# Block register copy
|
||||||
|
@ -340,14 +340,14 @@ Program counter stays on the currently executed instruction
|
||||||
- Copying over the 256 registers causes an exception
|
- Copying over the 256 registers causes an exception
|
||||||
|
|
||||||
| Opcode | Mnemonic | Operation |
|
| Opcode | Mnemonic | Operation |
|
||||||
|:-------|:---------|:--------------|
|
fn():--------------|
|
||||||
| 0x52 | BRC | `$3#1 ← $3#0` |
|
| 0x52 | BRC | `$3#1 ← $3#0` |
|
||||||
|
|
||||||
# Relative jump
|
# Relative jump
|
||||||
- Type: `O`
|
- Type: `O`
|
||||||
|
|
||||||
| Opcode | Mnemonic | Operation |
|
| Opcode | Mnemonic | Operation |
|
||||||
|:-------|:---------|:---------------|
|
fn():---------------|
|
||||||
| 0x53 | JMP | `pc ← pc + $0` |
|
| 0x53 | JMP | `pc ← pc + $0` |
|
||||||
|
|
||||||
# Linking jump
|
# Linking jump
|
||||||
|
@ -357,7 +357,7 @@ Program counter stays on the currently executed instruction
|
||||||
- Jump to specified address
|
- Jump to specified address
|
||||||
|
|
||||||
| Opcode | Mnemonic | Instruction type | Address |
|
| Opcode | Mnemonic | Instruction type | Address |
|
||||||
|:-------|:---------|:------------------|:-------------------------|
|
fn():-------------------------|
|
||||||
| 0x54 | JAL | RRO (size = 6 B) | Relative, `pc + #1 + $2` |
|
| 0x54 | JAL | RRO (size = 6 B) | Relative, `pc + #1 + $2` |
|
||||||
| 0x55 | JALA | RRA (size = 10 B) | Absolute, `#1 + $2` |
|
| 0x55 | JALA | RRA (size = 10 B) | Absolute, `#1 + $2` |
|
||||||
|
|
||||||
|
@ -367,7 +367,7 @@ Program counter stays on the currently executed instruction
|
||||||
- Operation: `if #0 <CMP> #1 { pc ← pc + $2 }`
|
- Operation: `if #0 <CMP> #1 { pc ← pc + $2 }`
|
||||||
|
|
||||||
| Opcode | Mnemonic | Condition | Type |
|
| Opcode | Mnemonic | Condition | Type |
|
||||||
|:-------|:---------|:-------------------|:-----|
|
fn():-----|
|
||||||
| 0x56 | JEQ | Equals (`=`) | Xi64 |
|
| 0x56 | JEQ | Equals (`=`) | Xi64 |
|
||||||
| 0x57 | JNE | Not-equals (`≠`) | Xi64 |
|
| 0x57 | JNE | Not-equals (`≠`) | Xi64 |
|
||||||
| 0x58 | JLTU | Less-than (`<`) | Ui64 |
|
| 0x58 | JLTU | Less-than (`<`) | Ui64 |
|
||||||
|
@ -380,7 +380,7 @@ Program counter stays on the currently executed instruction
|
||||||
- Type: `N`
|
- Type: `N`
|
||||||
|
|
||||||
| Opcode | Mnemonic | Trap type |
|
| Opcode | Mnemonic | Trap type |
|
||||||
|:-------|:---------|:-----------------|
|
fn():-----------------|
|
||||||
| 0x5C | ECA | Environment call |
|
| 0x5C | ECA | Environment call |
|
||||||
| 0x5D | EBP | Breakpoint |
|
| 0x5D | EBP | Breakpoint |
|
||||||
|
|
||||||
|
@ -389,7 +389,7 @@ Program counter stays on the currently executed instruction
|
||||||
- Operation: `#0 ← #1 <OP> #2`
|
- Operation: `#0 ← #1 <OP> #2`
|
||||||
|
|
||||||
| Opcode | Mnemonic | Operation | Type |
|
| Opcode | Mnemonic | Operation | Type |
|
||||||
|:-------|:---------|:---------------------|:-----|
|
fn():-----|
|
||||||
| 0x5E | FADD32 | Addition (`+`) | Fl32 |
|
| 0x5E | FADD32 | Addition (`+`) | Fl32 |
|
||||||
| 0x5F | FADD64 | Addition (`+`) | Fl64 |
|
| 0x5F | FADD64 | Addition (`+`) | Fl64 |
|
||||||
| 0x60 | FSUB32 | Subtraction (`-`) | Fl32 |
|
| 0x60 | FSUB32 | Subtraction (`-`) | Fl32 |
|
||||||
|
@ -404,7 +404,7 @@ Program counter stays on the currently executed instruction
|
||||||
- Operation: `#0 ← (#1 * #2) + #3`
|
- Operation: `#0 ← (#1 * #2) + #3`
|
||||||
|
|
||||||
| Opcode | Mnemonic | Type |
|
| Opcode | Mnemonic | Type |
|
||||||
|:-------|:---------|:-----|
|
fn():-----|
|
||||||
| 0x66 | FMA32 | Fl32 |
|
| 0x66 | FMA32 | Fl32 |
|
||||||
| 0x67 | FMA64 | Fl64 |
|
| 0x67 | FMA64 | Fl64 |
|
||||||
|
|
||||||
|
@ -415,7 +415,7 @@ Program counter stays on the currently executed instruction
|
||||||
- NaN is less-than/greater-than depends on variant
|
- NaN is less-than/greater-than depends on variant
|
||||||
|
|
||||||
| Opcode | Mnemonic | Type | NaN is |
|
| Opcode | Mnemonic | Type | NaN is |
|
||||||
|:-------|:---------|:-----|:-------|
|
fn():-------|
|
||||||
| 0x6A | FCMPLT32 | Fl32 | < |
|
| 0x6A | FCMPLT32 | Fl32 | < |
|
||||||
| 0x6B | FCMPLT64 | Fl64 | < |
|
| 0x6B | FCMPLT64 | Fl64 | < |
|
||||||
| 0x6C | FCMPGT32 | Fl32 | > |
|
| 0x6C | FCMPGT32 | Fl32 | > |
|
||||||
|
@ -427,7 +427,7 @@ Program counter stays on the currently executed instruction
|
||||||
- Operation: `#0 ← Fl<SIZE>(#1)`
|
- Operation: `#0 ← Fl<SIZE>(#1)`
|
||||||
|
|
||||||
| Opcode | Mnemonic | Type |
|
| Opcode | Mnemonic | Type |
|
||||||
|:-------|:---------|:-----|
|
fn():-----|
|
||||||
| 0x6E | ITF32 | Fl32 |
|
| 0x6E | ITF32 | Fl32 |
|
||||||
| 0x6F | ITF64 | Fl64 |
|
| 0x6F | ITF64 | Fl64 |
|
||||||
|
|
||||||
|
@ -437,7 +437,7 @@ Program counter stays on the currently executed instruction
|
||||||
- Immediate `$2` specifies rounding mode
|
- Immediate `$2` specifies rounding mode
|
||||||
|
|
||||||
| Opcode | Mnemonic | Type |
|
| Opcode | Mnemonic | Type |
|
||||||
|:-------|:---------|:-----|
|
fn():-----|
|
||||||
| 0x70 | FTI32 | Fl32 |
|
| 0x70 | FTI32 | Fl32 |
|
||||||
| 0x71 | FTI64 | Fl64 |
|
| 0x71 | FTI64 | Fl64 |
|
||||||
|
|
||||||
|
@ -446,7 +446,7 @@ Program counter stays on the currently executed instruction
|
||||||
- Operation: `#0 ← Fl64(#1)`
|
- Operation: `#0 ← Fl64(#1)`
|
||||||
|
|
||||||
| Opcode | Mnemonic |
|
| Opcode | Mnemonic |
|
||||||
|:-------|:---------|
|
fn():---------|
|
||||||
| 0x72 | FC32T64 |
|
| 0x72 | FC32T64 |
|
||||||
|
|
||||||
# Fl64 to Fl32
|
# Fl64 to Fl32
|
||||||
|
@ -455,13 +455,13 @@ Program counter stays on the currently executed instruction
|
||||||
- Immediate `$2` specified rounding mode
|
- Immediate `$2` specified rounding mode
|
||||||
|
|
||||||
| Opcode | Mnemonic |
|
| Opcode | Mnemonic |
|
||||||
|:-------|:---------|
|
fn():---------|
|
||||||
| 0x73 | FC64T32 |
|
| 0x73 | FC64T32 |
|
||||||
|
|
||||||
# 16-bit relative address instruction variants
|
# 16-bit relative address instruction variants
|
||||||
|
|
||||||
| Opcode | Mnemonic | Type | Variant of |
|
| Opcode | Mnemonic | Type | Variant of |
|
||||||
|:-------|:---------|:-----|:-----------|
|
fn():-----------|
|
||||||
| 0x74 | LRA16 | RRP | LRA |
|
| 0x74 | LRA16 | RRP | LRA |
|
||||||
| 0x75 | LDR16 | RRPH | LDR |
|
| 0x75 | LDR16 | RRPH | LDR |
|
||||||
| 0x76 | STR16 | RRPH | STR |
|
| 0x76 | STR16 | RRPH | STR |
|
||||||
|
@ -472,7 +472,7 @@ Program counter stays on the currently executed instruction
|
||||||
- One byte is 8 bits
|
- One byte is 8 bits
|
||||||
|
|
||||||
| C Type | Description | Byte sizes |
|
| C Type | Description | Byte sizes |
|
||||||
|:------------|:-------------------------|:-----------|
|
fn():-----------|
|
||||||
| char | Character / byte | 1 |
|
| char | Character / byte | 1 |
|
||||||
| short | Short integer | 2 |
|
| short | Short integer | 2 |
|
||||||
| int | Integer | 4 |
|
| int | Integer | 4 |
|
||||||
|
@ -491,7 +491,7 @@ Program counter stays on the currently executed instruction
|
||||||
- Registers r32 – r255 are callee saved
|
- Registers r32 – r255 are callee saved
|
||||||
|
|
||||||
| Register | Description | Saver |
|
| Register | Description | Saver |
|
||||||
|:-----------|:--------------------|:-------|
|
fn():-------|
|
||||||
| r0 | Hard-wired zero | N/A |
|
| r0 | Hard-wired zero | N/A |
|
||||||
| r1 - r2 | Return values | Caller |
|
| r1 - r2 | Return values | Caller |
|
||||||
| r2 - r11 | Function parameters | Caller |
|
| r2 - r11 | Function parameters | Caller |
|
||||||
|
|
Loading…
Reference in a new issue