202 lines
4.7 KiB
Rust
202 lines
4.7 KiB
Rust
use crate::push_bytes;
|
|
|
|
/// ## mov(register: u8, operand: u32)
|
|
/// - 0: opcode
|
|
/// - 1: register
|
|
/// - 2..5: operand
|
|
pub const MOV_INT: u8 = 0x01;
|
|
|
|
pub const MOV_LONG: u8 = 0x02;
|
|
pub const MOV_DOUBLE: u8 = 0x03;
|
|
|
|
/// ## mov(target_register: u8, source_register: u8)
|
|
/// 0: opcode
|
|
/// 1: target_register
|
|
/// 2: source_register
|
|
pub const MOV_REGISTER: u8 = 0x04;
|
|
|
|
/// ## alloc(register: u8, size: u32)
|
|
/// 0: opcode
|
|
/// 1: register
|
|
/// 2..5: size
|
|
pub const ALLOC: u8 = 0x05;
|
|
|
|
/// ## dealloc(register: u8)
|
|
/// 0: opcode
|
|
/// 1: register
|
|
pub const DEALLOC: u8 = 0x06;
|
|
|
|
/// ## mov_int_to(register: u8, offset: u32, operand: u32)
|
|
/// 0: opcode
|
|
/// 1: register
|
|
/// 2..5: offset
|
|
/// 6..9: operand
|
|
pub const MOV_INT_TO: u8 = 0x07;
|
|
|
|
pub const MOV_LONG_TO: u8 = 0x08;
|
|
pub const MOV_DOUBLE_TO: u8 = 0x09;
|
|
pub const MOV_REGISTER_TO: u8 = 0x0a;
|
|
|
|
pub const MOV_CONST: u8 = 0x0b;
|
|
|
|
pub const ALLOC_RAW: u8 = 0x0d;
|
|
pub const DEALLOC_RAW: u8 = 0x0e;
|
|
|
|
pub const PLATFORM_CALL: u8 = 0x10;
|
|
pub const INVOKE_FN: u8 = 0x11;
|
|
pub const INVOKE_VIRTUAL: u8 = 0x12;
|
|
pub const INVOKE_DYNAMIC: u8 = 0x14;
|
|
|
|
pub const MOV_SIZE_OF: u8 = 0x30;
|
|
|
|
pub const MULTIPLY: u8 = 0x40;
|
|
|
|
pub const LOAD: u8 = 0x50;
|
|
|
|
pub const STORE: u8 = 0x60;
|
|
|
|
macro_rules! push_number {
|
|
( $dest: expr, $num: expr ) => {
|
|
push_bytes!($dest, $num.to_le_bytes())
|
|
};
|
|
}
|
|
|
|
macro_rules! push_string {
|
|
( $dest: expr, $s: expr ) => {
|
|
push_bytes!($dest, $s.bytes())
|
|
};
|
|
}
|
|
|
|
pub fn add_mov_int(code: &mut Vec<u8>, register: u8, operand: u32) {
|
|
code.push(MOV_INT);
|
|
code.push(register);
|
|
push_number!(code, operand);
|
|
}
|
|
|
|
pub fn add_mov_register(code: &mut Vec<u8>, target_register: u8, source_register: u8) {
|
|
code.push(MOV_REGISTER);
|
|
code.push(target_register);
|
|
code.push(source_register);
|
|
}
|
|
|
|
pub fn add_alloc(code: &mut Vec<u8>, target_register: u8, implementation_name: &str) {
|
|
code.push(ALLOC);
|
|
code.push(target_register);
|
|
push_number!(code, implementation_name.len() as u32);
|
|
push_string!(code, implementation_name);
|
|
}
|
|
|
|
pub fn add_alloc_raw_from(code: &mut Vec<u8>, target_register: u8, source_register: u8) {
|
|
code.push(ALLOC_RAW);
|
|
code.push(target_register);
|
|
code.push(source_register);
|
|
}
|
|
|
|
pub fn add_dealloc(code: &mut Vec<u8>, register: u8) {
|
|
code.push(DEALLOC);
|
|
code.push(register);
|
|
}
|
|
|
|
pub fn add_mov_int_to(code: &mut Vec<u8>, register: u8, offset: u32, operand: u32) {
|
|
code.push(MOV_INT_TO);
|
|
code.push(register);
|
|
push_number!(code, offset);
|
|
push_number!(code, operand);
|
|
}
|
|
|
|
pub fn add_mov_register_to(
|
|
code: &mut Vec<u8>,
|
|
target_register: u8,
|
|
offset: u32,
|
|
source_register: u8,
|
|
) {
|
|
code.push(MOV_REGISTER_TO);
|
|
code.push(target_register);
|
|
push_number!(code, offset);
|
|
code.push(source_register);
|
|
}
|
|
|
|
pub fn add_load(
|
|
code: &mut Vec<u8>,
|
|
target_register: u8,
|
|
source_register: u8,
|
|
field_index: usize
|
|
) {
|
|
code.push(LOAD);
|
|
code.push(target_register);
|
|
code.push(source_register);
|
|
push_number!(code, field_index);
|
|
}
|
|
|
|
pub fn add_store(
|
|
code: &mut Vec<u8>,
|
|
target_register: u8,
|
|
field_index: usize,
|
|
source_register: u8,
|
|
) {
|
|
code.push(STORE);
|
|
code.push(target_register);
|
|
push_number!(code, field_index);
|
|
code.push(source_register);
|
|
}
|
|
|
|
pub fn add_mov_const(
|
|
code: &mut Vec<u8>,
|
|
address_register: u8,
|
|
size_register: u8,
|
|
lib_name: &str,
|
|
const_id: u32,
|
|
) {
|
|
code.push(MOV_CONST);
|
|
code.push(address_register);
|
|
code.push(size_register);
|
|
push_number!(code, lib_name.len() as u32);
|
|
push_string!(code, lib_name);
|
|
push_number!(code, const_id);
|
|
}
|
|
|
|
pub fn add_platform_call(
|
|
code: &mut Vec<u8>,
|
|
symbol_name: &str,
|
|
return_register: u8,
|
|
arg_registers: &[u8],
|
|
) {
|
|
code.push(PLATFORM_CALL);
|
|
push_number!(code, symbol_name.len() as u32);
|
|
push_string!(code, symbol_name);
|
|
push_number!(code, return_register);
|
|
push_number!(code, arg_registers.len() as u8);
|
|
for &b in arg_registers {
|
|
code.push(b);
|
|
}
|
|
}
|
|
|
|
pub fn add_invoke_fn(code: &mut Vec<u8>, fn_name: &str, return_register: u8, arg_registers: &[u8]) {
|
|
code.push(INVOKE_FN);
|
|
push_number!(code, fn_name.len() as u32);
|
|
push_string!(code, fn_name);
|
|
push_number!(code, return_register);
|
|
push_number!(code, arg_registers.len() as u8);
|
|
for &b in arg_registers {
|
|
code.push(b);
|
|
}
|
|
}
|
|
|
|
pub fn add_mov_size_of(code: &mut Vec<u8>, target_register: u8, source_register: u8) {
|
|
code.push(MOV_SIZE_OF);
|
|
code.push(target_register);
|
|
code.push(source_register);
|
|
}
|
|
|
|
pub fn add_multiply(
|
|
code: &mut Vec<u8>,
|
|
target_register: u8,
|
|
left_register: u8,
|
|
right_register: u8,
|
|
) {
|
|
code.push(MULTIPLY);
|
|
code.push(target_register);
|
|
code.push(left_register);
|
|
code.push(right_register);
|
|
}
|