fixing relative jumps to not offset from immidiate adress but from instruction adress
This commit is contained in:
parent
cf99091a45
commit
7435218999
207
hblang/build.rs
207
hblang/build.rs
|
@ -1,95 +1,136 @@
|
||||||
#![feature(iter_next_chunk)]
|
#![feature(iter_next_chunk)]
|
||||||
|
use std::fmt::Write;
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
println!("cargo:rerun-if-changed=build.rs");
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
println!("cargo:rerun-if-changed=../hbbytecode/instructions.in");
|
println!("cargo:rerun-if-changed=../hbbytecode/instructions.in");
|
||||||
|
|
||||||
let instructions = include_str!("../hbbytecode/instructions.in");
|
|
||||||
|
|
||||||
let mut generated = String::new();
|
let mut generated = String::new();
|
||||||
use std::fmt::Write;
|
|
||||||
|
|
||||||
writeln!(&mut generated, "impl crate::codegen::Func {{")?;
|
gen_max_size(&mut generated)?;
|
||||||
|
gen_encodes(&mut generated)?;
|
||||||
for line in instructions.lines() {
|
gen_structs(&mut generated)?;
|
||||||
let line = line.strip_suffix(";").unwrap();
|
gen_name_list(&mut generated)?;
|
||||||
let [opcode, name, ty, doc] = line.splitn(4, ',').map(str::trim).next_chunk().unwrap();
|
|
||||||
|
|
||||||
writeln!(&mut generated, "/// {}", doc.trim_matches('"'))?;
|
|
||||||
write!(&mut generated, "pub fn {}(&mut self", name.to_lowercase())?;
|
|
||||||
for (i, c) in ty.chars().enumerate() {
|
|
||||||
let (name, ty) = match c {
|
|
||||||
'N' => continue,
|
|
||||||
'R' => ("reg", "u8"),
|
|
||||||
'B' => ("imm", "u8"),
|
|
||||||
'H' => ("imm", "u16"),
|
|
||||||
'W' => ("imm", "u32"),
|
|
||||||
'D' => ("imm", "u64"),
|
|
||||||
'P' => ("offset", "u32"),
|
|
||||||
'O' => ("offset", "u32"),
|
|
||||||
'A' => ("addr", "u64"),
|
|
||||||
_ => panic!("unknown type: {}", c),
|
|
||||||
};
|
|
||||||
write!(&mut generated, ", {name}{i}: {ty}")?;
|
|
||||||
}
|
|
||||||
writeln!(&mut generated, ") {{")?;
|
|
||||||
|
|
||||||
let mut offset = 1;
|
|
||||||
for (i, c) in ty.chars().enumerate() {
|
|
||||||
let width = match c {
|
|
||||||
'N' => 0,
|
|
||||||
'R' => 1,
|
|
||||||
'B' => 1,
|
|
||||||
'H' => 2,
|
|
||||||
'W' => 4,
|
|
||||||
'D' => 8,
|
|
||||||
'A' => 8,
|
|
||||||
'P' => 2,
|
|
||||||
'O' => 4,
|
|
||||||
_ => panic!("unknown type: {}", c),
|
|
||||||
};
|
|
||||||
|
|
||||||
if matches!(c, 'P' | 'O') {
|
|
||||||
writeln!(
|
|
||||||
&mut generated,
|
|
||||||
" self.offset(offset{i}, {offset}, {width});",
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
offset += width;
|
|
||||||
}
|
|
||||||
|
|
||||||
write!(
|
|
||||||
&mut generated,
|
|
||||||
" self.extend(crate::as_bytes(&crate::Args({opcode}"
|
|
||||||
)?;
|
|
||||||
for (i, c) in ty.chars().enumerate() {
|
|
||||||
let name = match c {
|
|
||||||
'N' => continue,
|
|
||||||
'R' => "reg",
|
|
||||||
'B' | 'H' | 'W' | 'D' => "imm",
|
|
||||||
'P' => "0u16",
|
|
||||||
'O' => "0u32",
|
|
||||||
'A' => "addr",
|
|
||||||
_ => panic!("unknown type: {}", c),
|
|
||||||
};
|
|
||||||
|
|
||||||
if matches!(c, 'P' | 'O') {
|
|
||||||
write!(&mut generated, ", {name}")?;
|
|
||||||
} else {
|
|
||||||
write!(&mut generated, ", {name}{i}")?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _ in ty.len() - (ty == "N") as usize..4 {
|
|
||||||
write!(&mut generated, ", ()")?;
|
|
||||||
}
|
|
||||||
writeln!(&mut generated, ")));")?;
|
|
||||||
|
|
||||||
writeln!(&mut generated, "}}")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
writeln!(&mut generated, "}}")?;
|
|
||||||
|
|
||||||
std::fs::write("src/instrs.rs", generated)?;
|
std::fs::write("src/instrs.rs", generated)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn gen_name_list(generated: &mut String) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
writeln!(
|
||||||
|
generated,
|
||||||
|
"pub const NAMES: [&str; {}] = [",
|
||||||
|
instructions().count()
|
||||||
|
)?;
|
||||||
|
for [_, name, _, _] in instructions() {
|
||||||
|
writeln!(generated, " \"{}\",", name.to_lowercase())?;
|
||||||
|
}
|
||||||
|
writeln!(generated, "];")?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_max_size(generated: &mut String) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let max = instructions()
|
||||||
|
.map(|[_, _, ty, _]| {
|
||||||
|
if ty == "N" {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
iter_args(ty).map(|(_, c)| arg_to_width(c)).sum::<usize>() + 1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.max()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
writeln!(generated, "pub const MAX_SIZE: usize = {};", max)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_encodes(generated: &mut String) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
for [op, name, ty, doc] in instructions() {
|
||||||
|
writeln!(generated, "/// {}", doc.trim_matches('"'))?;
|
||||||
|
let name = name.to_lowercase();
|
||||||
|
let args = comma_sep(
|
||||||
|
iter_args(ty).map(|(i, c)| format!("{}{i}: {}", arg_to_name(c), arg_to_type(c))),
|
||||||
|
);
|
||||||
|
writeln!(
|
||||||
|
generated,
|
||||||
|
"pub fn {name}({args}) -> (usize, [u8; MAX_SIZE]) {{"
|
||||||
|
)?;
|
||||||
|
let arg_names = comma_sep(iter_args(ty).map(|(i, c)| format!("{}{i}", arg_to_name(c))));
|
||||||
|
writeln!(
|
||||||
|
generated,
|
||||||
|
" unsafe {{ crate::encode({ty}({op}, {arg_names})) }}"
|
||||||
|
)?;
|
||||||
|
writeln!(generated, "}}")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_structs(generated: &mut String) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let mut seen = std::collections::HashSet::new();
|
||||||
|
for [_, _, ty, _] in instructions() {
|
||||||
|
if !seen.insert(ty) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let types = comma_sep(iter_args(ty).map(|(_, c)| arg_to_type(c).to_string()));
|
||||||
|
writeln!(generated, "#[repr(packed)] pub struct {ty}(u8, {types});")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn comma_sep(items: impl Iterator<Item = String>) -> String {
|
||||||
|
items
|
||||||
|
.map(|item| item.to_string())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn instructions() -> impl Iterator<Item = [&'static str; 4]> {
|
||||||
|
include_str!("../hbbytecode/instructions.in")
|
||||||
|
.lines()
|
||||||
|
.filter_map(|line| line.strip_suffix(';'))
|
||||||
|
.map(|line| line.splitn(4, ',').map(str::trim).next_chunk().unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn arg_to_type(arg: char) -> &'static str {
|
||||||
|
match arg {
|
||||||
|
'R' | 'B' => "u8",
|
||||||
|
'H' => "u16",
|
||||||
|
'W' => "u32",
|
||||||
|
'D' | 'A' => "u64",
|
||||||
|
'P' => "i16",
|
||||||
|
'O' => "i32",
|
||||||
|
_ => panic!("unknown type: {}", arg),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn arg_to_width(arg: char) -> usize {
|
||||||
|
match arg {
|
||||||
|
'R' | 'B' => 1,
|
||||||
|
'H' => 2,
|
||||||
|
'W' => 4,
|
||||||
|
'D' | 'A' => 8,
|
||||||
|
'P' => 2,
|
||||||
|
'O' => 4,
|
||||||
|
_ => panic!("unknown type: {}", arg),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn arg_to_name(arg: char) -> &'static str {
|
||||||
|
match arg {
|
||||||
|
'R' => "reg",
|
||||||
|
'B' | 'H' | 'W' | 'D' => "imm",
|
||||||
|
'P' | 'O' => "offset",
|
||||||
|
'A' => "addr",
|
||||||
|
_ => panic!("unknown type: {}", arg),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn iter_args(ty: &'static str) -> impl Iterator<Item = (usize, char)> {
|
||||||
|
ty.chars().enumerate().filter(|(_, c)| *c != 'N')
|
||||||
|
}
|
||||||
|
|
6
hblang/examples/variables.hb
Normal file
6
hblang/examples/variables.hb
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
main := ||: int {
|
||||||
|
a := 1;
|
||||||
|
b := 2;
|
||||||
|
a = a + 1;
|
||||||
|
return a - b;
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
lexer,
|
instrs, lexer,
|
||||||
parser::{self, Expr},
|
parser::{self, Expr},
|
||||||
},
|
},
|
||||||
std::rc::Rc,
|
std::rc::Rc,
|
||||||
|
@ -27,6 +27,11 @@ struct Reloc {
|
||||||
size: u16,
|
size: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct StackReloc {
|
||||||
|
offset: u32,
|
||||||
|
size: u16,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Func {
|
pub struct Func {
|
||||||
code: Vec<u8>,
|
code: Vec<u8>,
|
||||||
|
@ -46,31 +51,48 @@ impl Func {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn encode(&mut self, (len, instr): (usize, [u8; instrs::MAX_SIZE])) {
|
||||||
|
let name = instrs::NAMES[instr[0] as usize];
|
||||||
|
println!(
|
||||||
|
"{}: {}",
|
||||||
|
name,
|
||||||
|
instr
|
||||||
|
.iter()
|
||||||
|
.take(len)
|
||||||
|
.skip(1)
|
||||||
|
.map(|b| format!("{:02x}", b))
|
||||||
|
.collect::<String>()
|
||||||
|
);
|
||||||
|
self.code.extend_from_slice(&instr[..len]);
|
||||||
|
}
|
||||||
|
|
||||||
fn push(&mut self, value: Reg, size: usize) {
|
fn push(&mut self, value: Reg, size: usize) {
|
||||||
self.st(value, STACK_PTR, 0, size as _);
|
self.subi64(STACK_PTR, STACK_PTR, size as _);
|
||||||
self.addi64(STACK_PTR, STACK_PTR, size as _);
|
self.encode(instrs::st(value, STACK_PTR, 0, size as _));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pop(&mut self, value: Reg, size: usize) {
|
fn pop(&mut self, value: Reg, size: usize) {
|
||||||
self.addi64(STACK_PTR, STACK_PTR, (size as u64).wrapping_neg());
|
self.encode(instrs::ld(value, STACK_PTR, 0, size as _));
|
||||||
self.ld(value, STACK_PTR, 0, size as _);
|
self.encode(instrs::addi64(STACK_PTR, STACK_PTR, size as _));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn subi64(&mut self, dest: Reg, src: Reg, imm: u64) {
|
||||||
|
self.encode(instrs::addi64(dest, src, imm.wrapping_neg()));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&mut self, func: LabelId) {
|
fn call(&mut self, func: LabelId) {
|
||||||
self.jal(RET_ADDR, ZERO, func);
|
self.offset(func, 3, 4);
|
||||||
|
self.encode(instrs::jal(RET_ADDR, ZERO, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ret(&mut self) {
|
fn ret(&mut self) {
|
||||||
self.jala(ZERO, RET_ADDR, 0);
|
self.pop(RET_ADDR, 8);
|
||||||
|
self.encode(instrs::jala(ZERO, RET_ADDR, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prelude(&mut self, entry: LabelId) {
|
fn prelude(&mut self, entry: LabelId) {
|
||||||
self.call(entry);
|
self.call(entry);
|
||||||
self.tx();
|
self.encode(instrs::tx());
|
||||||
}
|
|
||||||
|
|
||||||
fn div64(&mut self, reg0: Reg, reg1: Reg, reg2: Reg) {
|
|
||||||
self.diru64(reg0, ZERO, reg1, reg2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn relocate(&mut self, labels: &[Label], shift: i64) {
|
fn relocate(&mut self, labels: &[Label], shift: i64) {
|
||||||
|
@ -131,6 +153,12 @@ struct Label {
|
||||||
name: Rc<str>,
|
name: Rc<str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Variable<'a> {
|
||||||
|
name: Rc<str>,
|
||||||
|
offset: u64,
|
||||||
|
ty: Expr<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Codegen<'a> {
|
pub struct Codegen<'a> {
|
||||||
path: &'a std::path::Path,
|
path: &'a std::path::Path,
|
||||||
ret: Expr<'a>,
|
ret: Expr<'a>,
|
||||||
|
@ -138,6 +166,10 @@ pub struct Codegen<'a> {
|
||||||
code: Func,
|
code: Func,
|
||||||
temp: Func,
|
temp: Func,
|
||||||
labels: Vec<Label>,
|
labels: Vec<Label>,
|
||||||
|
stack_size: u64,
|
||||||
|
vars: Vec<Variable<'a>>,
|
||||||
|
|
||||||
|
stack_relocs: Vec<StackReloc>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Codegen<'a> {
|
impl<'a> Codegen<'a> {
|
||||||
|
@ -149,6 +181,10 @@ impl<'a> Codegen<'a> {
|
||||||
code: Default::default(),
|
code: Default::default(),
|
||||||
temp: Default::default(),
|
temp: Default::default(),
|
||||||
labels: Default::default(),
|
labels: Default::default(),
|
||||||
|
stack_size: 0,
|
||||||
|
vars: Default::default(),
|
||||||
|
|
||||||
|
stack_relocs: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,6 +200,53 @@ impl<'a> Codegen<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn loc_to_reg(&mut self, loc: Loc) -> Reg {
|
||||||
|
match loc {
|
||||||
|
Loc::Reg(reg) => reg,
|
||||||
|
Loc::Imm(imm) => {
|
||||||
|
let reg = self.gpa.allocate();
|
||||||
|
self.code.encode(instrs::li64(reg, imm));
|
||||||
|
reg
|
||||||
|
}
|
||||||
|
Loc::Stack(offset) => {
|
||||||
|
let reg = self.gpa.allocate();
|
||||||
|
self.load_stack(reg, offset, 8);
|
||||||
|
reg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn alloc_stack(&mut self, size: u32) -> u64 {
|
||||||
|
let offset = self.stack_size;
|
||||||
|
self.stack_size += size as u64;
|
||||||
|
offset
|
||||||
|
}
|
||||||
|
|
||||||
|
fn store_stack(&mut self, reg: Reg, offset: u64, size: u16) {
|
||||||
|
self.stack_relocs.push(StackReloc {
|
||||||
|
offset: self.code.code.len() as u32 + 3,
|
||||||
|
size,
|
||||||
|
});
|
||||||
|
self.code.encode(instrs::st(reg, STACK_PTR, offset, size));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_stack(&mut self, reg: Reg, offset: u64, size: u16) {
|
||||||
|
self.stack_relocs.push(StackReloc {
|
||||||
|
offset: self.code.code.len() as u32 + 3,
|
||||||
|
size,
|
||||||
|
});
|
||||||
|
self.code.encode(instrs::ld(reg, STACK_PTR, offset, size));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reloc_stack(&mut self, stack_height: u64) {
|
||||||
|
for reloc in self.stack_relocs.drain(..) {
|
||||||
|
let dest = &mut self.code.code[reloc.offset as usize..][..reloc.size as usize];
|
||||||
|
let value = u64::from_ne_bytes(dest.try_into().unwrap());
|
||||||
|
let offset = stack_height - value;
|
||||||
|
dest.copy_from_slice(&offset.to_ne_bytes());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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 {
|
||||||
|
@ -175,19 +258,39 @@ impl<'a> Codegen<'a> {
|
||||||
self.gpa.init_caller();
|
self.gpa.init_caller();
|
||||||
self.ret = **ret;
|
self.ret = **ret;
|
||||||
self.expr(body, None);
|
self.expr(body, None);
|
||||||
|
let stack = std::mem::take(&mut self.stack_size);
|
||||||
|
self.reloc_stack(stack);
|
||||||
self.write_fn_prelude(frame);
|
self.write_fn_prelude(frame);
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
E::Decl { name, val } => {
|
||||||
|
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();
|
||||||
|
Some(Value {
|
||||||
|
ty: var.ty,
|
||||||
|
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 {
|
||||||
panic!("expected {:?}, got {:?}", self.ret, val.ty);
|
panic!("expected {:?}, got {:?}", self.ret, val.ty);
|
||||||
}
|
}
|
||||||
match val.loc {
|
self.assign(
|
||||||
Loc::Reg(reg) => self.code.cp(1, reg),
|
Value {
|
||||||
Loc::Imm(imm) => self.code.li64(1, imm),
|
ty: self.ret,
|
||||||
}
|
loc: Loc::Reg(1),
|
||||||
|
},
|
||||||
|
val,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
self.ret();
|
self.ret();
|
||||||
None
|
None
|
||||||
|
@ -206,36 +309,19 @@ impl<'a> Codegen<'a> {
|
||||||
let left = self.expr(left, expeted).unwrap();
|
let left = self.expr(left, expeted).unwrap();
|
||||||
let right = self.expr(right, Some(left.ty)).unwrap();
|
let right = self.expr(right, Some(left.ty)).unwrap();
|
||||||
|
|
||||||
type Op = fn(&mut Func, u8, u8, u8);
|
|
||||||
type ImmOp = fn(&mut Func, u8, u8, u64);
|
|
||||||
|
|
||||||
let op = match op {
|
let op = match op {
|
||||||
T::Plus => Func::add64 as Op,
|
T::Plus => instrs::add64,
|
||||||
T::Minus => Func::sub64 as Op,
|
T::Minus => instrs::sub64,
|
||||||
T::Star => Func::mul64 as Op,
|
T::Star => instrs::mul64,
|
||||||
T::FSlash => Func::div64 as Op,
|
T::FSlash => |reg0, reg1, reg2| instrs::diru64(reg0, ZERO, reg1, reg2),
|
||||||
|
T::Assign => return self.assign(left, right),
|
||||||
_ => unimplemented!("{:#?}", op),
|
_ => unimplemented!("{:#?}", op),
|
||||||
};
|
};
|
||||||
|
|
||||||
let lhs = match left.loc {
|
let lhs = self.loc_to_reg(left.loc);
|
||||||
Loc::Reg(reg) => reg,
|
let rhs = self.loc_to_reg(right.loc);
|
||||||
Loc::Imm(imm) => {
|
|
||||||
let reg = self.gpa.allocate();
|
|
||||||
self.code.li64(reg, imm);
|
|
||||||
reg
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let rhs = match right.loc {
|
self.code.encode(op(lhs, lhs, rhs));
|
||||||
Loc::Reg(reg) => reg,
|
|
||||||
Loc::Imm(imm) => {
|
|
||||||
let reg = self.gpa.allocate();
|
|
||||||
self.code.li64(reg, imm);
|
|
||||||
reg
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
op(&mut self.code, lhs, lhs, rhs);
|
|
||||||
self.gpa.free(rhs);
|
self.gpa.free(rhs);
|
||||||
|
|
||||||
Some(Value {
|
Some(Value {
|
||||||
|
@ -247,6 +333,17 @@ impl<'a> Codegen<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn assign(&mut self, left: Value<'a>, right: Value<'a>) -> Option<Value<'a>> {
|
||||||
|
let rhs = self.loc_to_reg(right.loc);
|
||||||
|
match left.loc {
|
||||||
|
Loc::Reg(reg) => self.code.encode(instrs::cp(reg, rhs)),
|
||||||
|
Loc::Stack(offset) => self.store_stack(rhs, offset, 8),
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
self.gpa.free(rhs);
|
||||||
|
Some(left)
|
||||||
|
}
|
||||||
|
|
||||||
fn get_or_reserve_label(&mut self, name: &str) -> LabelId {
|
fn get_or_reserve_label(&mut self, name: &str) -> LabelId {
|
||||||
if let Some(label) = self.labels.iter().position(|l| l.name.as_ref() == name) {
|
if let Some(label) = self.labels.iter().position(|l| l.name.as_ref() == name) {
|
||||||
label as u32
|
label as u32
|
||||||
|
@ -287,9 +384,11 @@ impl<'a> Codegen<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_fn_prelude(&mut self, frame: Frame) {
|
fn write_fn_prelude(&mut self, frame: Frame) {
|
||||||
|
self.temp.push(RET_ADDR, 8);
|
||||||
for ® in self.gpa.used.clone().iter() {
|
for ® in self.gpa.used.clone().iter() {
|
||||||
self.temp.push(reg, 8);
|
self.temp.push(reg, 8);
|
||||||
}
|
}
|
||||||
|
self.temp.subi64(STACK_PTR, STACK_PTR, self.stack_size as _);
|
||||||
|
|
||||||
for reloc in &mut self.code.relocs[frame.prev_relocs..] {
|
for reloc in &mut self.code.relocs[frame.prev_relocs..] {
|
||||||
reloc.offset += self.temp.code.len() as u32;
|
reloc.offset += self.temp.code.len() as u32;
|
||||||
|
@ -302,6 +401,11 @@ impl<'a> Codegen<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ret(&mut self) {
|
fn ret(&mut self) {
|
||||||
|
self.stack_relocs.push(StackReloc {
|
||||||
|
offset: self.code.code.len() as u32 + 3,
|
||||||
|
size: 8,
|
||||||
|
});
|
||||||
|
self.code.encode(instrs::addi64(STACK_PTR, STACK_PTR, 0));
|
||||||
for reg in self.gpa.used.clone().iter().rev() {
|
for reg in self.gpa.used.clone().iter().rev() {
|
||||||
self.code.pop(*reg, 8);
|
self.code.pop(*reg, 8);
|
||||||
}
|
}
|
||||||
|
@ -317,6 +421,14 @@ impl<'a> Codegen<'a> {
|
||||||
out.write_all(&self.temp.code)?;
|
out.write_all(&self.temp.code)?;
|
||||||
out.write_all(&self.code.code)
|
out.write_all(&self.code.code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn decl_var(&mut self, name: &str, offset: u64, ty: Expr<'a>) {
|
||||||
|
self.vars.push(Variable {
|
||||||
|
name: name.into(),
|
||||||
|
offset,
|
||||||
|
ty,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Value<'a> {
|
pub struct Value<'a> {
|
||||||
|
@ -327,6 +439,7 @@ pub struct Value<'a> {
|
||||||
pub enum Loc {
|
pub enum Loc {
|
||||||
Reg(Reg),
|
Reg(Reg),
|
||||||
Imm(u64),
|
Imm(u64),
|
||||||
|
Stack(u64),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -381,7 +494,10 @@ mod tests {
|
||||||
hbvm::Vm::<TestMem, 0>::new(TestMem, hbvm::mem::Address::new(out.as_ptr() as u64))
|
hbvm::Vm::<TestMem, 0>::new(TestMem, hbvm::mem::Address::new(out.as_ptr() as u64))
|
||||||
};
|
};
|
||||||
|
|
||||||
vm.write_reg(super::STACK_PTR, stack.as_mut_ptr() as u64);
|
vm.write_reg(
|
||||||
|
super::STACK_PTR,
|
||||||
|
unsafe { stack.as_mut_ptr().add(stack.len()) } as u64,
|
||||||
|
);
|
||||||
|
|
||||||
let stat = loop {
|
let stat = loop {
|
||||||
match vm.run() {
|
match vm.run() {
|
||||||
|
@ -398,5 +514,6 @@ mod tests {
|
||||||
crate::run_tests! { generate:
|
crate::run_tests! { generate:
|
||||||
example => include_str!("../examples/main_fn.hb");
|
example => include_str!("../examples/main_fn.hb");
|
||||||
arithmetic => include_str!("../examples/arithmetic.hb");
|
arithmetic => include_str!("../examples/arithmetic.hb");
|
||||||
|
variables => include_str!("../examples/variables.hb");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,497 +1,623 @@
|
||||||
impl crate::codegen::Func {
|
pub const MAX_SIZE: usize = 13;
|
||||||
/// Cause an unreachable code trap
|
/// Cause an unreachable code trap
|
||||||
pub fn un(&mut self) {
|
pub fn un() -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x00, (), (), (), ())));
|
unsafe { crate::encode(N(0x00, )) }
|
||||||
}
|
}
|
||||||
/// Termiante execution
|
/// Termiante execution
|
||||||
pub fn tx(&mut self) {
|
pub fn tx() -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x01, (), (), (), ())));
|
unsafe { crate::encode(N(0x01, )) }
|
||||||
}
|
}
|
||||||
/// Do nothing
|
/// Do nothing
|
||||||
pub fn nop(&mut self) {
|
pub fn nop() -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x02, (), (), (), ())));
|
unsafe { crate::encode(N(0x02, )) }
|
||||||
}
|
}
|
||||||
/// Addition (8b)
|
/// Addition (8b)
|
||||||
pub fn add8(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn add8(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x03, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x03, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Addition (16b)
|
/// Addition (16b)
|
||||||
pub fn add16(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn add16(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x04, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x04, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Addition (32b)
|
/// Addition (32b)
|
||||||
pub fn add32(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn add32(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x05, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x05, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Addition (64b)
|
/// Addition (64b)
|
||||||
pub fn add64(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn add64(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x06, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x06, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Subtraction (8b)
|
/// Subtraction (8b)
|
||||||
pub fn sub8(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn sub8(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x07, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x07, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Subtraction (16b)
|
/// Subtraction (16b)
|
||||||
pub fn sub16(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn sub16(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x08, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x08, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Subtraction (32b)
|
/// Subtraction (32b)
|
||||||
pub fn sub32(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn sub32(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x09, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x09, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Subtraction (64b)
|
/// Subtraction (64b)
|
||||||
pub fn sub64(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn sub64(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x0A, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x0A, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Multiplication (8b)
|
/// Multiplication (8b)
|
||||||
pub fn mul8(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn mul8(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x0B, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x0B, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Multiplication (16b)
|
/// Multiplication (16b)
|
||||||
pub fn mul16(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn mul16(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x0C, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x0C, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Multiplication (32b)
|
/// Multiplication (32b)
|
||||||
pub fn mul32(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn mul32(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x0D, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x0D, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Multiplication (64b)
|
/// Multiplication (64b)
|
||||||
pub fn mul64(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn mul64(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x0E, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x0E, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Bitand
|
/// Bitand
|
||||||
pub fn and(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn and(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x0F, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x0F, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Bitor
|
/// Bitor
|
||||||
pub fn or(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn or(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x10, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x10, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Bitxor
|
/// Bitxor
|
||||||
pub fn xor(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn xor(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x11, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x11, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Unsigned left bitshift (8b)
|
/// Unsigned left bitshift (8b)
|
||||||
pub fn slu8(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn slu8(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x12, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x12, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Unsigned left bitshift (16b)
|
/// Unsigned left bitshift (16b)
|
||||||
pub fn slu16(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn slu16(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x13, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x13, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Unsigned left bitshift (32b)
|
/// Unsigned left bitshift (32b)
|
||||||
pub fn slu32(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn slu32(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x14, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x14, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Unsigned left bitshift (64b)
|
/// Unsigned left bitshift (64b)
|
||||||
pub fn slu64(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn slu64(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x15, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x15, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Unsigned right bitshift (8b)
|
/// Unsigned right bitshift (8b)
|
||||||
pub fn sru8(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn sru8(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x16, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x16, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Unsigned right bitshift (16b)
|
/// Unsigned right bitshift (16b)
|
||||||
pub fn sru16(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn sru16(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x17, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x17, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Unsigned right bitshift (32b)
|
/// Unsigned right bitshift (32b)
|
||||||
pub fn sru32(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn sru32(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x18, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x18, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Unsigned right bitshift (64b)
|
/// Unsigned right bitshift (64b)
|
||||||
pub fn sru64(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn sru64(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x19, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x19, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Signed right bitshift (8b)
|
/// Signed right bitshift (8b)
|
||||||
pub fn srs8(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn srs8(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x1A, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x1A, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Signed right bitshift (16b)
|
/// Signed right bitshift (16b)
|
||||||
pub fn srs16(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn srs16(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x1B, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x1B, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Signed right bitshift (32b)
|
/// Signed right bitshift (32b)
|
||||||
pub fn srs32(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn srs32(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x1C, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x1C, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Signed right bitshift (64b)
|
/// Signed right bitshift (64b)
|
||||||
pub fn srs64(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn srs64(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x1D, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x1D, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Unsigned comparsion
|
/// Unsigned comparsion
|
||||||
pub fn cmpu(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn cmpu(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x1E, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x1E, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Signed comparsion
|
/// Signed comparsion
|
||||||
pub fn cmps(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn cmps(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x1F, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x1F, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Merged divide-remainder (unsigned 8b)
|
/// Merged divide-remainder (unsigned 8b)
|
||||||
pub fn diru8(&mut self, reg0: u8, reg1: u8, reg2: u8, reg3: u8) {
|
pub fn diru8(reg0: u8, reg1: u8, reg2: u8, reg3: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x20, reg0, reg1, reg2, reg3)));
|
unsafe { crate::encode(RRRR(0x20, reg0, reg1, reg2, reg3)) }
|
||||||
}
|
}
|
||||||
/// Merged divide-remainder (unsigned 16b)
|
/// Merged divide-remainder (unsigned 16b)
|
||||||
pub fn diru16(&mut self, reg0: u8, reg1: u8, reg2: u8, reg3: u8) {
|
pub fn diru16(reg0: u8, reg1: u8, reg2: u8, reg3: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x21, reg0, reg1, reg2, reg3)));
|
unsafe { crate::encode(RRRR(0x21, reg0, reg1, reg2, reg3)) }
|
||||||
}
|
}
|
||||||
/// Merged divide-remainder (unsigned 32b)
|
/// Merged divide-remainder (unsigned 32b)
|
||||||
pub fn diru32(&mut self, reg0: u8, reg1: u8, reg2: u8, reg3: u8) {
|
pub fn diru32(reg0: u8, reg1: u8, reg2: u8, reg3: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x22, reg0, reg1, reg2, reg3)));
|
unsafe { crate::encode(RRRR(0x22, reg0, reg1, reg2, reg3)) }
|
||||||
}
|
}
|
||||||
/// Merged divide-remainder (unsigned 64b)
|
/// Merged divide-remainder (unsigned 64b)
|
||||||
pub fn diru64(&mut self, reg0: u8, reg1: u8, reg2: u8, reg3: u8) {
|
pub fn diru64(reg0: u8, reg1: u8, reg2: u8, reg3: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x23, reg0, reg1, reg2, reg3)));
|
unsafe { crate::encode(RRRR(0x23, reg0, reg1, reg2, reg3)) }
|
||||||
}
|
}
|
||||||
/// Merged divide-remainder (signed 8b)
|
/// Merged divide-remainder (signed 8b)
|
||||||
pub fn dirs8(&mut self, reg0: u8, reg1: u8, reg2: u8, reg3: u8) {
|
pub fn dirs8(reg0: u8, reg1: u8, reg2: u8, reg3: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x24, reg0, reg1, reg2, reg3)));
|
unsafe { crate::encode(RRRR(0x24, reg0, reg1, reg2, reg3)) }
|
||||||
}
|
}
|
||||||
/// Merged divide-remainder (signed 16b)
|
/// Merged divide-remainder (signed 16b)
|
||||||
pub fn dirs16(&mut self, reg0: u8, reg1: u8, reg2: u8, reg3: u8) {
|
pub fn dirs16(reg0: u8, reg1: u8, reg2: u8, reg3: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x25, reg0, reg1, reg2, reg3)));
|
unsafe { crate::encode(RRRR(0x25, reg0, reg1, reg2, reg3)) }
|
||||||
}
|
}
|
||||||
/// Merged divide-remainder (signed 32b)
|
/// Merged divide-remainder (signed 32b)
|
||||||
pub fn dirs32(&mut self, reg0: u8, reg1: u8, reg2: u8, reg3: u8) {
|
pub fn dirs32(reg0: u8, reg1: u8, reg2: u8, reg3: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x26, reg0, reg1, reg2, reg3)));
|
unsafe { crate::encode(RRRR(0x26, reg0, reg1, reg2, reg3)) }
|
||||||
}
|
}
|
||||||
/// Merged divide-remainder (signed 64b)
|
/// Merged divide-remainder (signed 64b)
|
||||||
pub fn dirs64(&mut self, reg0: u8, reg1: u8, reg2: u8, reg3: u8) {
|
pub fn dirs64(reg0: u8, reg1: u8, reg2: u8, reg3: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x27, reg0, reg1, reg2, reg3)));
|
unsafe { crate::encode(RRRR(0x27, reg0, reg1, reg2, reg3)) }
|
||||||
}
|
}
|
||||||
/// Bit negation
|
/// Bit negation
|
||||||
pub fn neg(&mut self, reg0: u8, reg1: u8) {
|
pub fn neg(reg0: u8, reg1: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x28, reg0, reg1, (), ())));
|
unsafe { crate::encode(RR(0x28, reg0, reg1)) }
|
||||||
}
|
}
|
||||||
/// Logical negation
|
/// Logical negation
|
||||||
pub fn not(&mut self, reg0: u8, reg1: u8) {
|
pub fn not(reg0: u8, reg1: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x29, reg0, reg1, (), ())));
|
unsafe { crate::encode(RR(0x29, reg0, reg1)) }
|
||||||
}
|
}
|
||||||
/// Sign extend 8b to 64b
|
/// Sign extend 8b to 64b
|
||||||
pub fn sxt8(&mut self, reg0: u8, reg1: u8) {
|
pub fn sxt8(reg0: u8, reg1: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x2A, reg0, reg1, (), ())));
|
unsafe { crate::encode(RR(0x2A, reg0, reg1)) }
|
||||||
}
|
}
|
||||||
/// Sign extend 16b to 64b
|
/// Sign extend 16b to 64b
|
||||||
pub fn sxt16(&mut self, reg0: u8, reg1: u8) {
|
pub fn sxt16(reg0: u8, reg1: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x2B, reg0, reg1, (), ())));
|
unsafe { crate::encode(RR(0x2B, reg0, reg1)) }
|
||||||
}
|
}
|
||||||
/// Sign extend 32b to 64b
|
/// Sign extend 32b to 64b
|
||||||
pub fn sxt32(&mut self, reg0: u8, reg1: u8) {
|
pub fn sxt32(reg0: u8, reg1: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x2C, reg0, reg1, (), ())));
|
unsafe { crate::encode(RR(0x2C, reg0, reg1)) }
|
||||||
}
|
}
|
||||||
/// Addition with immediate (8b)
|
/// Addition with immediate (8b)
|
||||||
pub fn addi8(&mut self, reg0: u8, reg1: u8, imm2: u8) {
|
pub fn addi8(reg0: u8, reg1: u8, imm2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x2D, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRB(0x2D, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Addition with immediate (16b)
|
/// Addition with immediate (16b)
|
||||||
pub fn addi16(&mut self, reg0: u8, reg1: u8, imm2: u16) {
|
pub fn addi16(reg0: u8, reg1: u8, imm2: u16) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x2E, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRH(0x2E, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Addition with immediate (32b)
|
/// Addition with immediate (32b)
|
||||||
pub fn addi32(&mut self, reg0: u8, reg1: u8, imm2: u32) {
|
pub fn addi32(reg0: u8, reg1: u8, imm2: u32) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x2F, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRW(0x2F, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Addition with immediate (64b)
|
/// Addition with immediate (64b)
|
||||||
pub fn addi64(&mut self, reg0: u8, reg1: u8, imm2: u64) {
|
pub fn addi64(reg0: u8, reg1: u8, imm2: u64) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x30, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRD(0x30, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Multiplication with immediate (8b)
|
/// Multiplication with immediate (8b)
|
||||||
pub fn muli8(&mut self, reg0: u8, reg1: u8, imm2: u8) {
|
pub fn muli8(reg0: u8, reg1: u8, imm2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x31, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRB(0x31, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Multiplication with immediate (16b)
|
/// Multiplication with immediate (16b)
|
||||||
pub fn muli16(&mut self, reg0: u8, reg1: u8, imm2: u16) {
|
pub fn muli16(reg0: u8, reg1: u8, imm2: u16) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x32, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRH(0x32, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Multiplication with immediate (32b)
|
/// Multiplication with immediate (32b)
|
||||||
pub fn muli32(&mut self, reg0: u8, reg1: u8, imm2: u32) {
|
pub fn muli32(reg0: u8, reg1: u8, imm2: u32) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x33, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRW(0x33, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Multiplication with immediate (64b)
|
/// Multiplication with immediate (64b)
|
||||||
pub fn muli64(&mut self, reg0: u8, reg1: u8, imm2: u64) {
|
pub fn muli64(reg0: u8, reg1: u8, imm2: u64) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x34, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRD(0x34, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Bitand with immediate
|
/// Bitand with immediate
|
||||||
pub fn andi(&mut self, reg0: u8, reg1: u8, imm2: u64) {
|
pub fn andi(reg0: u8, reg1: u8, imm2: u64) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x35, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRD(0x35, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Bitor with immediate
|
/// Bitor with immediate
|
||||||
pub fn ori(&mut self, reg0: u8, reg1: u8, imm2: u64) {
|
pub fn ori(reg0: u8, reg1: u8, imm2: u64) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x36, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRD(0x36, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Bitxor with immediate
|
/// Bitxor with immediate
|
||||||
pub fn xori(&mut self, reg0: u8, reg1: u8, imm2: u64) {
|
pub fn xori(reg0: u8, reg1: u8, imm2: u64) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x37, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRD(0x37, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Unsigned left bitshift with immedidate (8b)
|
/// Unsigned left bitshift with immedidate (8b)
|
||||||
pub fn slui8(&mut self, reg0: u8, reg1: u8, imm2: u8) {
|
pub fn slui8(reg0: u8, reg1: u8, imm2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x38, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRB(0x38, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Unsigned left bitshift with immedidate (16b)
|
/// Unsigned left bitshift with immedidate (16b)
|
||||||
pub fn slui16(&mut self, reg0: u8, reg1: u8, imm2: u8) {
|
pub fn slui16(reg0: u8, reg1: u8, imm2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x39, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRB(0x39, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Unsigned left bitshift with immedidate (32b)
|
/// Unsigned left bitshift with immedidate (32b)
|
||||||
pub fn slui32(&mut self, reg0: u8, reg1: u8, imm2: u8) {
|
pub fn slui32(reg0: u8, reg1: u8, imm2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x3A, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRB(0x3A, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Unsigned left bitshift with immedidate (64b)
|
/// Unsigned left bitshift with immedidate (64b)
|
||||||
pub fn slui64(&mut self, reg0: u8, reg1: u8, imm2: u8) {
|
pub fn slui64(reg0: u8, reg1: u8, imm2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x3B, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRB(0x3B, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Unsigned right bitshift with immediate (8b)
|
/// Unsigned right bitshift with immediate (8b)
|
||||||
pub fn srui8(&mut self, reg0: u8, reg1: u8, imm2: u8) {
|
pub fn srui8(reg0: u8, reg1: u8, imm2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x3C, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRB(0x3C, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Unsigned right bitshift with immediate (16b)
|
/// Unsigned right bitshift with immediate (16b)
|
||||||
pub fn srui16(&mut self, reg0: u8, reg1: u8, imm2: u8) {
|
pub fn srui16(reg0: u8, reg1: u8, imm2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x3D, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRB(0x3D, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Unsigned right bitshift with immediate (32b)
|
/// Unsigned right bitshift with immediate (32b)
|
||||||
pub fn srui32(&mut self, reg0: u8, reg1: u8, imm2: u8) {
|
pub fn srui32(reg0: u8, reg1: u8, imm2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x3E, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRB(0x3E, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Unsigned right bitshift with immediate (64b)
|
/// Unsigned right bitshift with immediate (64b)
|
||||||
pub fn srui64(&mut self, reg0: u8, reg1: u8, imm2: u8) {
|
pub fn srui64(reg0: u8, reg1: u8, imm2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x3F, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRB(0x3F, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Signed right bitshift with immediate
|
/// Signed right bitshift with immediate
|
||||||
pub fn srsi8(&mut self, reg0: u8, reg1: u8, imm2: u8) {
|
pub fn srsi8(reg0: u8, reg1: u8, imm2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x40, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRB(0x40, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Signed right bitshift with immediate
|
/// Signed right bitshift with immediate
|
||||||
pub fn srsi16(&mut self, reg0: u8, reg1: u8, imm2: u8) {
|
pub fn srsi16(reg0: u8, reg1: u8, imm2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x41, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRB(0x41, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Signed right bitshift with immediate
|
/// Signed right bitshift with immediate
|
||||||
pub fn srsi32(&mut self, reg0: u8, reg1: u8, imm2: u8) {
|
pub fn srsi32(reg0: u8, reg1: u8, imm2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x42, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRB(0x42, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Signed right bitshift with immediate
|
/// Signed right bitshift with immediate
|
||||||
pub fn srsi64(&mut self, reg0: u8, reg1: u8, imm2: u8) {
|
pub fn srsi64(reg0: u8, reg1: u8, imm2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x43, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRB(0x43, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Unsigned compare with immediate
|
/// Unsigned compare with immediate
|
||||||
pub fn cmpui(&mut self, reg0: u8, reg1: u8, imm2: u64) {
|
pub fn cmpui(reg0: u8, reg1: u8, imm2: u64) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x44, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRD(0x44, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Signed compare with immediate
|
/// Signed compare with immediate
|
||||||
pub fn cmpsi(&mut self, reg0: u8, reg1: u8, imm2: u64) {
|
pub fn cmpsi(reg0: u8, reg1: u8, imm2: u64) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x45, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRD(0x45, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Copy register
|
/// Copy register
|
||||||
pub fn cp(&mut self, reg0: u8, reg1: u8) {
|
pub fn cp(reg0: u8, reg1: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x46, reg0, reg1, (), ())));
|
unsafe { crate::encode(RR(0x46, reg0, reg1)) }
|
||||||
}
|
}
|
||||||
/// Swap registers
|
/// Swap registers
|
||||||
pub fn swa(&mut self, reg0: u8, reg1: u8) {
|
pub fn swa(reg0: u8, reg1: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x47, reg0, reg1, (), ())));
|
unsafe { crate::encode(RR(0x47, reg0, reg1)) }
|
||||||
}
|
}
|
||||||
/// Load immediate (8b)
|
/// Load immediate (8b)
|
||||||
pub fn li8(&mut self, reg0: u8, imm1: u8) {
|
pub fn li8(reg0: u8, imm1: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x48, reg0, imm1, (), ())));
|
unsafe { crate::encode(RB(0x48, reg0, imm1)) }
|
||||||
}
|
}
|
||||||
/// Load immediate (16b)
|
/// Load immediate (16b)
|
||||||
pub fn li16(&mut self, reg0: u8, imm1: u16) {
|
pub fn li16(reg0: u8, imm1: u16) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x49, reg0, imm1, (), ())));
|
unsafe { crate::encode(RH(0x49, reg0, imm1)) }
|
||||||
}
|
}
|
||||||
/// Load immediate (32b)
|
/// Load immediate (32b)
|
||||||
pub fn li32(&mut self, reg0: u8, imm1: u32) {
|
pub fn li32(reg0: u8, imm1: u32) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x4A, reg0, imm1, (), ())));
|
unsafe { crate::encode(RW(0x4A, reg0, imm1)) }
|
||||||
}
|
}
|
||||||
/// Load immediate (64b)
|
/// Load immediate (64b)
|
||||||
pub fn li64(&mut self, reg0: u8, imm1: u64) {
|
pub fn li64(reg0: u8, imm1: u64) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x4B, reg0, imm1, (), ())));
|
unsafe { crate::encode(RD(0x4B, reg0, imm1)) }
|
||||||
}
|
}
|
||||||
/// Load relative address
|
/// Load relative address
|
||||||
pub fn lra(&mut self, reg0: u8, reg1: u8, offset2: u32) {
|
pub fn lra(reg0: u8, reg1: u8, offset2: i32) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.offset(offset2, 3, 4);
|
unsafe { crate::encode(RRO(0x4C, reg0, reg1, offset2)) }
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x4C, reg0, reg1, 0u32, ())));
|
|
||||||
}
|
}
|
||||||
/// Load from absolute address
|
/// Load from absolute address
|
||||||
pub fn ld(&mut self, reg0: u8, reg1: u8, addr2: u64, imm3: u16) {
|
pub fn ld(reg0: u8, reg1: u8, addr2: u64, imm3: u16) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x4D, reg0, reg1, addr2, imm3)));
|
unsafe { crate::encode(RRAH(0x4D, reg0, reg1, addr2, imm3)) }
|
||||||
}
|
}
|
||||||
/// Store to absolute address
|
/// Store to absolute address
|
||||||
pub fn st(&mut self, reg0: u8, reg1: u8, addr2: u64, imm3: u16) {
|
pub fn st(reg0: u8, reg1: u8, addr2: u64, imm3: u16) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x4E, reg0, reg1, addr2, imm3)));
|
unsafe { crate::encode(RRAH(0x4E, reg0, reg1, addr2, imm3)) }
|
||||||
}
|
}
|
||||||
/// Load from relative address
|
/// Load from relative address
|
||||||
pub fn ldr(&mut self, reg0: u8, reg1: u8, offset2: u32, imm3: u16) {
|
pub fn ldr(reg0: u8, reg1: u8, offset2: i32, imm3: u16) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.offset(offset2, 3, 4);
|
unsafe { crate::encode(RROH(0x4F, reg0, reg1, offset2, imm3)) }
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x4F, reg0, reg1, 0u32, imm3)));
|
|
||||||
}
|
}
|
||||||
/// Store to relative address
|
/// Store to relative address
|
||||||
pub fn str(&mut self, reg0: u8, reg1: u8, offset2: u32, imm3: u16) {
|
pub fn str(reg0: u8, reg1: u8, offset2: i32, imm3: u16) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.offset(offset2, 3, 4);
|
unsafe { crate::encode(RROH(0x50, reg0, reg1, offset2, imm3)) }
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x50, reg0, reg1, 0u32, imm3)));
|
|
||||||
}
|
}
|
||||||
/// Copy block of memory
|
/// Copy block of memory
|
||||||
pub fn bmc(&mut self, reg0: u8, reg1: u8, imm2: u16) {
|
pub fn bmc(reg0: u8, reg1: u8, imm2: u16) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x51, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRH(0x51, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Copy register block
|
/// Copy register block
|
||||||
pub fn brc(&mut self, reg0: u8, reg1: u8, imm2: u8) {
|
pub fn brc(reg0: u8, reg1: u8, imm2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x52, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRB(0x52, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Relative jump
|
/// Relative jump
|
||||||
pub fn jmp(&mut self, offset0: u32) {
|
pub fn jmp(offset0: i32) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.offset(offset0, 1, 4);
|
unsafe { crate::encode(O(0x53, offset0)) }
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x53, 0u32, (), (), ())));
|
|
||||||
}
|
}
|
||||||
/// Linking relative jump
|
/// Linking relative jump
|
||||||
pub fn jal(&mut self, reg0: u8, reg1: u8, offset2: u32) {
|
pub fn jal(reg0: u8, reg1: u8, offset2: i32) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.offset(offset2, 3, 4);
|
unsafe { crate::encode(RRO(0x54, reg0, reg1, offset2)) }
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x54, reg0, reg1, 0u32, ())));
|
|
||||||
}
|
}
|
||||||
/// Linking absolute jump
|
/// Linking absolute jump
|
||||||
pub fn jala(&mut self, reg0: u8, reg1: u8, addr2: u64) {
|
pub fn jala(reg0: u8, reg1: u8, addr2: u64) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x55, reg0, reg1, addr2, ())));
|
unsafe { crate::encode(RRA(0x55, reg0, reg1, addr2)) }
|
||||||
}
|
}
|
||||||
/// Branch on equal
|
/// Branch on equal
|
||||||
pub fn jeq(&mut self, reg0: u8, reg1: u8, offset2: u32) {
|
pub fn jeq(reg0: u8, reg1: u8, offset2: i16) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.offset(offset2, 3, 2);
|
unsafe { crate::encode(RRP(0x56, reg0, reg1, offset2)) }
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x56, reg0, reg1, 0u16, ())));
|
|
||||||
}
|
}
|
||||||
/// Branch on nonequal
|
/// Branch on nonequal
|
||||||
pub fn jne(&mut self, reg0: u8, reg1: u8, offset2: u32) {
|
pub fn jne(reg0: u8, reg1: u8, offset2: i16) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.offset(offset2, 3, 2);
|
unsafe { crate::encode(RRP(0x57, reg0, reg1, offset2)) }
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x57, reg0, reg1, 0u16, ())));
|
|
||||||
}
|
}
|
||||||
/// Branch on lesser-than (unsigned)
|
/// Branch on lesser-than (unsigned)
|
||||||
pub fn jltu(&mut self, reg0: u8, reg1: u8, offset2: u32) {
|
pub fn jltu(reg0: u8, reg1: u8, offset2: i16) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.offset(offset2, 3, 2);
|
unsafe { crate::encode(RRP(0x58, reg0, reg1, offset2)) }
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x58, reg0, reg1, 0u16, ())));
|
|
||||||
}
|
}
|
||||||
/// Branch on greater-than (unsigned)
|
/// Branch on greater-than (unsigned)
|
||||||
pub fn jgtu(&mut self, reg0: u8, reg1: u8, offset2: u32) {
|
pub fn jgtu(reg0: u8, reg1: u8, offset2: i16) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.offset(offset2, 3, 2);
|
unsafe { crate::encode(RRP(0x59, reg0, reg1, offset2)) }
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x59, reg0, reg1, 0u16, ())));
|
|
||||||
}
|
}
|
||||||
/// Branch on lesser-than (signed)
|
/// Branch on lesser-than (signed)
|
||||||
pub fn jlts(&mut self, reg0: u8, reg1: u8, offset2: u32) {
|
pub fn jlts(reg0: u8, reg1: u8, offset2: i16) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.offset(offset2, 3, 2);
|
unsafe { crate::encode(RRP(0x5A, reg0, reg1, offset2)) }
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x5A, reg0, reg1, 0u16, ())));
|
|
||||||
}
|
}
|
||||||
/// Branch on greater-than (signed)
|
/// Branch on greater-than (signed)
|
||||||
pub fn jgts(&mut self, reg0: u8, reg1: u8, offset2: u32) {
|
pub fn jgts(reg0: u8, reg1: u8, offset2: i16) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.offset(offset2, 3, 2);
|
unsafe { crate::encode(RRP(0x5B, reg0, reg1, offset2)) }
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x5B, reg0, reg1, 0u16, ())));
|
|
||||||
}
|
}
|
||||||
/// Environment call trap
|
/// Environment call trap
|
||||||
pub fn eca(&mut self) {
|
pub fn eca() -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x5C, (), (), (), ())));
|
unsafe { crate::encode(N(0x5C, )) }
|
||||||
}
|
}
|
||||||
/// Environment breakpoint
|
/// Environment breakpoint
|
||||||
pub fn ebp(&mut self) {
|
pub fn ebp() -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x5D, (), (), (), ())));
|
unsafe { crate::encode(N(0x5D, )) }
|
||||||
}
|
}
|
||||||
/// Floating point addition (32b)
|
/// Floating point addition (32b)
|
||||||
pub fn fadd32(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn fadd32(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x5E, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x5E, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Floating point addition (64b)
|
/// Floating point addition (64b)
|
||||||
pub fn fadd64(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn fadd64(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x5F, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x5F, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Floating point subtraction (32b)
|
/// Floating point subtraction (32b)
|
||||||
pub fn fsub32(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn fsub32(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x60, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x60, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Floating point subtraction (64b)
|
/// Floating point subtraction (64b)
|
||||||
pub fn fsub64(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn fsub64(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x61, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x61, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Floating point multiply (32b)
|
/// Floating point multiply (32b)
|
||||||
pub fn fmul32(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn fmul32(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x62, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x62, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Floating point multiply (64b)
|
/// Floating point multiply (64b)
|
||||||
pub fn fmul64(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn fmul64(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x63, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x63, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Floating point division (32b)
|
/// Floating point division (32b)
|
||||||
pub fn fdiv32(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn fdiv32(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x64, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x64, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Floating point division (64b)
|
/// Floating point division (64b)
|
||||||
pub fn fdiv64(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn fdiv64(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x65, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x65, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Float fused multiply-add (32b)
|
/// Float fused multiply-add (32b)
|
||||||
pub fn fma32(&mut self, reg0: u8, reg1: u8, reg2: u8, reg3: u8) {
|
pub fn fma32(reg0: u8, reg1: u8, reg2: u8, reg3: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x66, reg0, reg1, reg2, reg3)));
|
unsafe { crate::encode(RRRR(0x66, reg0, reg1, reg2, reg3)) }
|
||||||
}
|
}
|
||||||
/// Float fused multiply-add (64b)
|
/// Float fused multiply-add (64b)
|
||||||
pub fn fma64(&mut self, reg0: u8, reg1: u8, reg2: u8, reg3: u8) {
|
pub fn fma64(reg0: u8, reg1: u8, reg2: u8, reg3: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x67, reg0, reg1, reg2, reg3)));
|
unsafe { crate::encode(RRRR(0x67, reg0, reg1, reg2, reg3)) }
|
||||||
}
|
}
|
||||||
/// Float reciprocal (32b)
|
/// Float reciprocal (32b)
|
||||||
pub fn finv32(&mut self, reg0: u8, reg1: u8) {
|
pub fn finv32(reg0: u8, reg1: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x68, reg0, reg1, (), ())));
|
unsafe { crate::encode(RR(0x68, reg0, reg1)) }
|
||||||
}
|
}
|
||||||
/// Float reciprocal (64b)
|
/// Float reciprocal (64b)
|
||||||
pub fn finv64(&mut self, reg0: u8, reg1: u8) {
|
pub fn finv64(reg0: u8, reg1: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x69, reg0, reg1, (), ())));
|
unsafe { crate::encode(RR(0x69, reg0, reg1)) }
|
||||||
}
|
}
|
||||||
/// Flaot compare less than (32b)
|
/// Flaot compare less than (32b)
|
||||||
pub fn fcmplt32(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn fcmplt32(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x6A, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x6A, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Flaot compare less than (64b)
|
/// Flaot compare less than (64b)
|
||||||
pub fn fcmplt64(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn fcmplt64(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x6B, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x6B, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Flaot compare greater than (32b)
|
/// Flaot compare greater than (32b)
|
||||||
pub fn fcmpgt32(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn fcmpgt32(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x6C, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x6C, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Flaot compare greater than (64b)
|
/// Flaot compare greater than (64b)
|
||||||
pub fn fcmpgt64(&mut self, reg0: u8, reg1: u8, reg2: u8) {
|
pub fn fcmpgt64(reg0: u8, reg1: u8, reg2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x6D, reg0, reg1, reg2, ())));
|
unsafe { crate::encode(RRR(0x6D, reg0, reg1, reg2)) }
|
||||||
}
|
}
|
||||||
/// Int to 32 bit float
|
/// Int to 32 bit float
|
||||||
pub fn itf32(&mut self, reg0: u8, reg1: u8) {
|
pub fn itf32(reg0: u8, reg1: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x6E, reg0, reg1, (), ())));
|
unsafe { crate::encode(RR(0x6E, reg0, reg1)) }
|
||||||
}
|
}
|
||||||
/// Int to 64 bit float
|
/// Int to 64 bit float
|
||||||
pub fn itf64(&mut self, reg0: u8, reg1: u8) {
|
pub fn itf64(reg0: u8, reg1: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x6F, reg0, reg1, (), ())));
|
unsafe { crate::encode(RR(0x6F, reg0, reg1)) }
|
||||||
}
|
}
|
||||||
/// Float 32 to int
|
/// Float 32 to int
|
||||||
pub fn fti32(&mut self, reg0: u8, reg1: u8, imm2: u8) {
|
pub fn fti32(reg0: u8, reg1: u8, imm2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x70, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRB(0x70, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Float 64 to int
|
/// Float 64 to int
|
||||||
pub fn fti64(&mut self, reg0: u8, reg1: u8, imm2: u8) {
|
pub fn fti64(reg0: u8, reg1: u8, imm2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x71, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRB(0x71, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Float 64 to Float 32
|
/// Float 64 to Float 32
|
||||||
pub fn fc32t64(&mut self, reg0: u8, reg1: u8) {
|
pub fn fc32t64(reg0: u8, reg1: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x72, reg0, reg1, (), ())));
|
unsafe { crate::encode(RR(0x72, reg0, reg1)) }
|
||||||
}
|
}
|
||||||
/// Float 32 to Float 64
|
/// Float 32 to Float 64
|
||||||
pub fn fc64t32(&mut self, reg0: u8, reg1: u8, imm2: u8) {
|
pub fn fc64t32(reg0: u8, reg1: u8, imm2: u8) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x73, reg0, reg1, imm2, ())));
|
unsafe { crate::encode(RRB(0x73, reg0, reg1, imm2)) }
|
||||||
}
|
}
|
||||||
/// Load relative immediate (16 bit)
|
/// Load relative immediate (16 bit)
|
||||||
pub fn lra16(&mut self, reg0: u8, reg1: u8, offset2: u32) {
|
pub fn lra16(reg0: u8, reg1: u8, offset2: i16) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.offset(offset2, 3, 2);
|
unsafe { crate::encode(RRP(0x74, reg0, reg1, offset2)) }
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x74, reg0, reg1, 0u16, ())));
|
|
||||||
}
|
}
|
||||||
/// Load from relative address (16 bit)
|
/// Load from relative address (16 bit)
|
||||||
pub fn ldr16(&mut self, reg0: u8, reg1: u8, offset2: u32, imm3: u16) {
|
pub fn ldr16(reg0: u8, reg1: u8, offset2: i16, imm3: u16) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.offset(offset2, 3, 2);
|
unsafe { crate::encode(RRPH(0x75, reg0, reg1, offset2, imm3)) }
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x75, reg0, reg1, 0u16, imm3)));
|
|
||||||
}
|
}
|
||||||
/// Store to relative address (16 bit)
|
/// Store to relative address (16 bit)
|
||||||
pub fn str16(&mut self, reg0: u8, reg1: u8, offset2: u32, imm3: u16) {
|
pub fn str16(reg0: u8, reg1: u8, offset2: i16, imm3: u16) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.offset(offset2, 3, 2);
|
unsafe { crate::encode(RRPH(0x76, reg0, reg1, offset2, imm3)) }
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x76, reg0, reg1, 0u16, imm3)));
|
|
||||||
}
|
}
|
||||||
/// Relative jump (16 bit)
|
/// Relative jump (16 bit)
|
||||||
pub fn jmp16(&mut self, offset0: u32) {
|
pub fn jmp16(offset0: i16) -> (usize, [u8; MAX_SIZE]) {
|
||||||
self.offset(offset0, 1, 2);
|
unsafe { crate::encode(P(0x77, offset0)) }
|
||||||
self.extend(crate::as_bytes(&crate::Args(0x77, 0u16, (), (), ())));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
#[repr(packed)] pub struct N(u8, );
|
||||||
|
#[repr(packed)] pub struct RRR(u8, u8, u8, u8);
|
||||||
|
#[repr(packed)] pub struct RRRR(u8, u8, u8, u8, u8);
|
||||||
|
#[repr(packed)] pub struct RR(u8, u8, u8);
|
||||||
|
#[repr(packed)] pub struct RRB(u8, u8, u8, u8);
|
||||||
|
#[repr(packed)] pub struct RRH(u8, u8, u8, u16);
|
||||||
|
#[repr(packed)] pub struct RRW(u8, u8, u8, u32);
|
||||||
|
#[repr(packed)] pub struct RRD(u8, u8, u8, u64);
|
||||||
|
#[repr(packed)] pub struct RB(u8, u8, u8);
|
||||||
|
#[repr(packed)] pub struct RH(u8, u8, u16);
|
||||||
|
#[repr(packed)] pub struct RW(u8, u8, u32);
|
||||||
|
#[repr(packed)] pub struct RD(u8, u8, u64);
|
||||||
|
#[repr(packed)] pub struct RRO(u8, u8, u8, i32);
|
||||||
|
#[repr(packed)] pub struct RRAH(u8, u8, u8, u64, u16);
|
||||||
|
#[repr(packed)] pub struct RROH(u8, u8, u8, i32, u16);
|
||||||
|
#[repr(packed)] pub struct O(u8, i32);
|
||||||
|
#[repr(packed)] pub struct RRA(u8, u8, u8, u64);
|
||||||
|
#[repr(packed)] pub struct RRP(u8, u8, u8, i16);
|
||||||
|
#[repr(packed)] pub struct RRPH(u8, u8, u8, i16, u16);
|
||||||
|
#[repr(packed)] pub struct P(u8, i16);
|
||||||
|
pub const NAMES: [&str; 120] = [
|
||||||
|
"un",
|
||||||
|
"tx",
|
||||||
|
"nop",
|
||||||
|
"add8",
|
||||||
|
"add16",
|
||||||
|
"add32",
|
||||||
|
"add64",
|
||||||
|
"sub8",
|
||||||
|
"sub16",
|
||||||
|
"sub32",
|
||||||
|
"sub64",
|
||||||
|
"mul8",
|
||||||
|
"mul16",
|
||||||
|
"mul32",
|
||||||
|
"mul64",
|
||||||
|
"and",
|
||||||
|
"or",
|
||||||
|
"xor",
|
||||||
|
"slu8",
|
||||||
|
"slu16",
|
||||||
|
"slu32",
|
||||||
|
"slu64",
|
||||||
|
"sru8",
|
||||||
|
"sru16",
|
||||||
|
"sru32",
|
||||||
|
"sru64",
|
||||||
|
"srs8",
|
||||||
|
"srs16",
|
||||||
|
"srs32",
|
||||||
|
"srs64",
|
||||||
|
"cmpu",
|
||||||
|
"cmps",
|
||||||
|
"diru8",
|
||||||
|
"diru16",
|
||||||
|
"diru32",
|
||||||
|
"diru64",
|
||||||
|
"dirs8",
|
||||||
|
"dirs16",
|
||||||
|
"dirs32",
|
||||||
|
"dirs64",
|
||||||
|
"neg",
|
||||||
|
"not",
|
||||||
|
"sxt8",
|
||||||
|
"sxt16",
|
||||||
|
"sxt32",
|
||||||
|
"addi8",
|
||||||
|
"addi16",
|
||||||
|
"addi32",
|
||||||
|
"addi64",
|
||||||
|
"muli8",
|
||||||
|
"muli16",
|
||||||
|
"muli32",
|
||||||
|
"muli64",
|
||||||
|
"andi",
|
||||||
|
"ori",
|
||||||
|
"xori",
|
||||||
|
"slui8",
|
||||||
|
"slui16",
|
||||||
|
"slui32",
|
||||||
|
"slui64",
|
||||||
|
"srui8",
|
||||||
|
"srui16",
|
||||||
|
"srui32",
|
||||||
|
"srui64",
|
||||||
|
"srsi8",
|
||||||
|
"srsi16",
|
||||||
|
"srsi32",
|
||||||
|
"srsi64",
|
||||||
|
"cmpui",
|
||||||
|
"cmpsi",
|
||||||
|
"cp",
|
||||||
|
"swa",
|
||||||
|
"li8",
|
||||||
|
"li16",
|
||||||
|
"li32",
|
||||||
|
"li64",
|
||||||
|
"lra",
|
||||||
|
"ld",
|
||||||
|
"st",
|
||||||
|
"ldr",
|
||||||
|
"str",
|
||||||
|
"bmc",
|
||||||
|
"brc",
|
||||||
|
"jmp",
|
||||||
|
"jal",
|
||||||
|
"jala",
|
||||||
|
"jeq",
|
||||||
|
"jne",
|
||||||
|
"jltu",
|
||||||
|
"jgtu",
|
||||||
|
"jlts",
|
||||||
|
"jgts",
|
||||||
|
"eca",
|
||||||
|
"ebp",
|
||||||
|
"fadd32",
|
||||||
|
"fadd64",
|
||||||
|
"fsub32",
|
||||||
|
"fsub64",
|
||||||
|
"fmul32",
|
||||||
|
"fmul64",
|
||||||
|
"fdiv32",
|
||||||
|
"fdiv64",
|
||||||
|
"fma32",
|
||||||
|
"fma64",
|
||||||
|
"finv32",
|
||||||
|
"finv64",
|
||||||
|
"fcmplt32",
|
||||||
|
"fcmplt64",
|
||||||
|
"fcmpgt32",
|
||||||
|
"fcmpgt64",
|
||||||
|
"itf32",
|
||||||
|
"itf64",
|
||||||
|
"fti32",
|
||||||
|
"fti64",
|
||||||
|
"fc32t64",
|
||||||
|
"fc64t32",
|
||||||
|
"lra16",
|
||||||
|
"ldr16",
|
||||||
|
"str16",
|
||||||
|
"jmp16",
|
||||||
|
];
|
||||||
|
|
|
@ -22,6 +22,7 @@ pub enum TokenKind {
|
||||||
LBrack,
|
LBrack,
|
||||||
RBrack,
|
RBrack,
|
||||||
Decl,
|
Decl,
|
||||||
|
Assign,
|
||||||
Plus,
|
Plus,
|
||||||
Minus,
|
Minus,
|
||||||
Star,
|
Star,
|
||||||
|
@ -47,6 +48,7 @@ impl std::fmt::Display for TokenKind {
|
||||||
T::LBrack => "[",
|
T::LBrack => "[",
|
||||||
T::RBrack => "]",
|
T::RBrack => "]",
|
||||||
T::Decl => ":=",
|
T::Decl => ":=",
|
||||||
|
T::Assign => "=",
|
||||||
T::Plus => "+",
|
T::Plus => "+",
|
||||||
T::Minus => "-",
|
T::Minus => "-",
|
||||||
T::Star => "*",
|
T::Star => "*",
|
||||||
|
@ -64,11 +66,12 @@ impl std::fmt::Display for TokenKind {
|
||||||
|
|
||||||
impl TokenKind {
|
impl TokenKind {
|
||||||
pub fn precedence(&self) -> Option<u8> {
|
pub fn precedence(&self) -> Option<u8> {
|
||||||
match self {
|
Some(match self {
|
||||||
Self::Plus | Self::Minus => Some(2),
|
Self::Assign => 1,
|
||||||
Self::Star | Self::FSlash => Some(3),
|
Self::Plus | Self::Minus => 2,
|
||||||
_ => None,
|
Self::Star | Self::FSlash => 3,
|
||||||
}
|
_ => return None,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,6 +165,7 @@ impl<'a> Iterator for Lexer<'a> {
|
||||||
false => T::Colon,
|
false => T::Colon,
|
||||||
},
|
},
|
||||||
b';' => T::Semi,
|
b';' => T::Semi,
|
||||||
|
b'=' => T::Assign,
|
||||||
b'+' => T::Plus,
|
b'+' => T::Plus,
|
||||||
b'-' => T::Minus,
|
b'-' => T::Minus,
|
||||||
b'*' => T::Star,
|
b'*' => T::Star,
|
||||||
|
|
|
@ -22,12 +22,9 @@ mod parser;
|
||||||
mod tests;
|
mod tests;
|
||||||
mod typechk;
|
mod typechk;
|
||||||
|
|
||||||
#[repr(packed)]
|
#[inline]
|
||||||
struct Args<A, B, C, D>(u8, A, B, C, D);
|
unsafe fn encode<T>(instr: T) -> (usize, [u8; instrs::MAX_SIZE]) {
|
||||||
fn as_bytes<T>(args: &T) -> &[u8] {
|
let mut buf = [0; instrs::MAX_SIZE];
|
||||||
unsafe { core::slice::from_raw_parts(args as *const _ as *const u8, core::mem::size_of::<T>()) }
|
std::ptr::write(buf.as_mut_ptr() as *mut T, instr);
|
||||||
}
|
(std::mem::size_of::<T>(), buf)
|
||||||
|
|
||||||
pub fn try_block<R>(f: impl FnOnce() -> R) -> R {
|
|
||||||
f()
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -195,7 +195,7 @@ impl<'a> std::fmt::Display for Expr<'a> {
|
||||||
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 = crate::try_block(|| {
|
let res = (|| {
|
||||||
for stmt in stmts {
|
for stmt in stmts {
|
||||||
for _ in 0..INDENT.with(|i| i.get()) {
|
for _ in 0..INDENT.with(|i| i.get()) {
|
||||||
write!(f, " ")?;
|
write!(f, " ")?;
|
||||||
|
@ -203,7 +203,7 @@ impl<'a> std::fmt::Display for Expr<'a> {
|
||||||
writeln!(f, "{}", stmt)?;
|
writeln!(f, "{}", stmt)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
})();
|
||||||
INDENT.with(|i| i.set(i.get() - 1));
|
INDENT.with(|i| i.set(i.get() - 1));
|
||||||
write!(f, "}}")?;
|
write!(f, "}}")?;
|
||||||
res
|
res
|
||||||
|
|
0
hblang/tests/hblang::codegen::tests::variables.txt
Normal file
0
hblang/tests/hblang::codegen::tests::variables.txt
Normal file
|
@ -173,7 +173,7 @@ where
|
||||||
LI64 => handler!(self, |OpsRD(tg, imm)| self.write_reg(tg, imm)),
|
LI64 => handler!(self, |OpsRD(tg, imm)| self.write_reg(tg, imm)),
|
||||||
LRA => handler!(self, |OpsRRO(tg, reg, off)| self.write_reg(
|
LRA => handler!(self, |OpsRRO(tg, reg, off)| self.write_reg(
|
||||||
tg,
|
tg,
|
||||||
self.pcrel(off, 3)
|
self.pcrel(off)
|
||||||
.wrapping_add(self.read_reg(reg).cast::<i64>())
|
.wrapping_add(self.read_reg(reg).cast::<i64>())
|
||||||
.get(),
|
.get(),
|
||||||
)),
|
)),
|
||||||
|
@ -186,13 +186,13 @@ where
|
||||||
LDR => handler!(self, |OpsRROH(dst, base, off, count)| self.load(
|
LDR => handler!(self, |OpsRROH(dst, base, off, count)| self.load(
|
||||||
dst,
|
dst,
|
||||||
base,
|
base,
|
||||||
self.pcrel(off, 3).get(),
|
self.pcrel(off).get(),
|
||||||
count
|
count
|
||||||
)?),
|
)?),
|
||||||
STR => handler!(self, |OpsRROH(dst, base, off, count)| self.store(
|
STR => handler!(self, |OpsRROH(dst, base, off, count)| self.store(
|
||||||
dst,
|
dst,
|
||||||
base,
|
base,
|
||||||
self.pcrel(off, 3).get(),
|
self.pcrel(off).get(),
|
||||||
count
|
count
|
||||||
)?),
|
)?),
|
||||||
BMC => {
|
BMC => {
|
||||||
|
@ -252,7 +252,7 @@ where
|
||||||
|
|
||||||
self.write_reg(save, self.pc.next::<OpsRRO>());
|
self.write_reg(save, self.pc.next::<OpsRRO>());
|
||||||
self.pc = self
|
self.pc = self
|
||||||
.pcrel(offset, 3)
|
.pcrel(offset)
|
||||||
.wrapping_add(self.read_reg(reg).cast::<i64>());
|
.wrapping_add(self.read_reg(reg).cast::<i64>());
|
||||||
}
|
}
|
||||||
JALA => {
|
JALA => {
|
||||||
|
@ -269,7 +269,7 @@ where
|
||||||
JNE => {
|
JNE => {
|
||||||
let OpsRRP(a0, a1, ja) = self.decode();
|
let OpsRRP(a0, a1, ja) = self.decode();
|
||||||
if self.read_reg(a0).cast::<u64>() != self.read_reg(a1).cast::<u64>() {
|
if self.read_reg(a0).cast::<u64>() != self.read_reg(a1).cast::<u64>() {
|
||||||
self.pc = self.pcrel(ja, 3);
|
self.pc = self.pcrel(ja);
|
||||||
} else {
|
} else {
|
||||||
self.bump_pc::<OpsRRP>();
|
self.bump_pc::<OpsRRP>();
|
||||||
}
|
}
|
||||||
|
@ -346,18 +346,18 @@ where
|
||||||
LDR16 => handler!(self, |OpsRRPH(dst, base, off, count)| self.load(
|
LDR16 => handler!(self, |OpsRRPH(dst, base, off, count)| self.load(
|
||||||
dst,
|
dst,
|
||||||
base,
|
base,
|
||||||
self.pcrel(off, 3).get(),
|
self.pcrel(off).get(),
|
||||||
count
|
count
|
||||||
)?),
|
)?),
|
||||||
STR16 => handler!(self, |OpsRRPH(dst, base, off, count)| self.store(
|
STR16 => handler!(self, |OpsRRPH(dst, base, off, count)| self.store(
|
||||||
dst,
|
dst,
|
||||||
base,
|
base,
|
||||||
self.pcrel(off, 3).get(),
|
self.pcrel(off).get(),
|
||||||
count
|
count
|
||||||
)?),
|
)?),
|
||||||
JMP16 => {
|
JMP16 => {
|
||||||
let OpsP(off) = self.decode();
|
let OpsP(off) = self.decode();
|
||||||
self.pc = self.pcrel(off, 1);
|
self.pc = self.pcrel(off);
|
||||||
}
|
}
|
||||||
op => return Err(VmRunError::InvalidOpcode(op)),
|
op => return Err(VmRunError::InvalidOpcode(op)),
|
||||||
}
|
}
|
||||||
|
@ -532,8 +532,8 @@ where
|
||||||
|
|
||||||
/// Calculate pc-relative address
|
/// Calculate pc-relative address
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn pcrel(&self, offset: impl AddressOp, pos: u8) -> Address {
|
fn pcrel(&self, offset: impl AddressOp) -> Address {
|
||||||
self.pc.wrapping_add(pos).wrapping_add(offset)
|
self.pc.wrapping_add(offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Jump at `PC + #3` if ordering on `#0 <=> #1` is equal to expected
|
/// Jump at `PC + #3` if ordering on `#0 <=> #1` is equal to expected
|
||||||
|
@ -546,7 +546,7 @@ where
|
||||||
.cmp(&self.read_reg(a1).cast::<T>())
|
.cmp(&self.read_reg(a1).cast::<T>())
|
||||||
== expected
|
== expected
|
||||||
{
|
{
|
||||||
self.pc = self.pcrel(ja, 3);
|
self.pc = self.pcrel(ja);
|
||||||
} else {
|
} else {
|
||||||
self.bump_pc::<OpsRRP>();
|
self.bump_pc::<OpsRRP>();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue