From c14a20391f3a2ce33e35c13e328c6919cc1ca7cf Mon Sep 17 00:00:00 2001 From: Werner Date: Sat, 11 Dec 2021 17:32:54 -0300 Subject: [PATCH] Working... --- Cargo.toml | 13 + Config/Bindings.toml | 614 +++++++++++++++++++++++ Examples/Assembler.rs | 27 ++ Examples/Assembly.bin | Bin 0 -> 318 bytes Examples/Loader.rs | 21 + Source/Assembly.rs | 23 + Source/Instruction.rs | 24 + Source/InstructionTable.rs | 45 ++ Source/Mnemonics.rs | 969 +++++++++++++++++++++++++++++++++++++ Source/Stack.rs | 137 +++++- Source/Types.rs | 19 + Source/lib.rs | 13 + 12 files changed, 1895 insertions(+), 10 deletions(-) create mode 100644 Config/Bindings.toml create mode 100644 Examples/Assembler.rs create mode 100644 Examples/Assembly.bin create mode 100644 Examples/Loader.rs create mode 100644 Source/Assembly.rs create mode 100644 Source/Instruction.rs create mode 100644 Source/InstructionTable.rs create mode 100644 Source/Mnemonics.rs diff --git a/Cargo.toml b/Cargo.toml index 30bc9a4..3795ed4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,19 @@ name = "Machine" crate-type = ["rlib"] path = "Source/lib.rs" +[dependencies] +bincode = "1.3.3" +bitflags = "1.3.2" +serde = { version = "1.0", features = ["derive"] } + [[example]] name = "Simple" path = "Examples/Simple.rs" + +[[example]] +name = "Assembler" +path = "Examples/Assembler.rs" + +[[example]] +name = "Loader" +path = "Examples/Loader.rs" diff --git a/Config/Bindings.toml b/Config/Bindings.toml new file mode 100644 index 0000000..0b06e87 --- /dev/null +++ b/Config/Bindings.toml @@ -0,0 +1,614 @@ +# The language to output bindings in +# +# possible values: "C", "C++", "Cython" +# +# default: "C++" +language = "C" + +# Options for wrapping the contents of the header: + +# An optional string of text to output at the beginning of the generated file +# default: doesn't emit anything +header = "// Copyright (c) TribuFu. All Rights Reserved." + +# An optional string of text to output at the end of the generated file +# default: doesn't emit anything +#trailer = "/* Text to put at the end of the generated file */" + +# An optional name to use as an include guard +# default: doesn't emit an include guard +#include_guard = "DEVKIT_H" + +# Whether to add a `#pragma once` guard +# default: doesn't emit a `#pragma once` +pragma_once = true + +# An optional string of text to output between major sections of the generated +# file as a warning against manual editing +# +# default: doesn't emit anything +#autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */" + +# Whether to include a comment with the version of cbindgen used to generate the file +# default: false +include_version = false + +# An optional namespace to output around the generated bindings +# default: doesn't emit a namespace +#namespace = "TribuFu" + +# An optional list of namespaces to output around the generated bindings +# default: [] +namespaces = [] + +# An optional list of namespaces to declare as using with "using namespace" +# default: [] +using_namespaces = [] + +# A list of sys headers to #include (with angle brackets) +# default: [] +sys_includes = ["stdbool.h", "stdint.h"] + +# A list of headers to #include (with quotes) +# default: [] +includes = [] + +# Whether cbindgen's default C/C++ standard imports should be suppressed. These +# imports are included by default because our generated headers tend to require +# them (e.g. for uint32_t). Currently, the generated imports are: +# +# * for C: , , , , +# +# * for C++: , , , , (depending on config) +# +# default: false +no_includes = true + +# Whether to make a C header C++ compatible. +# These will wrap generated functions into a `extern "C"` block, e.g. +# +# #ifdef __cplusplus +# extern "C" { +# #endif // __cplusplus +# +# // Generated functions. +# +# #ifdef __cplusplus +# } // extern "C" +# #endif // __cplusplus +# +# If the language is not C this option won't have any effect. +# +# default: false +cpp_compat = true + +# A list of lines to add verbatim after the includes block +# after_includes = "\n#include \"Macros.h\"" + +# Code Style Options + +# The style to use for curly braces +# +# possible values: "SameLine", "NextLine" +# +# default: "SameLine" +braces = "NextLine" + +# The desired length of a line to use when formatting lines +# default: 100 +line_length = 100 + +# The amount of spaces to indent by +# default: 2 +tab_width = 4 + +# Include doc comments from Rust as documentation +documentation = true + +# How the generated documentation should be commented. +# +# possible values: +# * "c": /* like this */ +# * "c99": // like this +# * "c++": /// like this +# * "doxy": like C, but with leading *'s on each line +# * "auto": "c++" if that's the language, "doxy" otherwise +# +# default: "auto" +documentation_style = "doxy" + +# Codegen Options + +# When generating a C header, the kind of declaration style to use for structs +# or enums. +# +# possible values: +# * "type": typedef struct { ... } MyType; +# * "tag": struct MyType { ... }; +# * "both": typedef struct MyType { ... } MyType; +# +# default: "both" +style = "tag" + +# A list of substitutions for converting cfg's to ifdefs. cfgs which aren't +# defined here will just be discarded. +# +# e.g. +# `#[cfg(target = "freebsd")] ...` +# becomes +# `#if defined(DEFINE_FREEBSD) ... #endif` +[defines] +"target_os = windows" = "PLATFORM_WINDOWS" +"target_os = macos" = "PLATFORM_MAC" +"target_os = linux" = "PLATFORM_LINUX" +"target_os = freebsd" = "PLATFORM_FREEBSD" +"target_os = android" = "PLATFORM_ANDROID" +"target_os = ios" = "PLATFORM_IOS" +"target_arch = wasm32" = "PLATFORM_WEB" + +"target_arch = x86_64" = "PLATFORM_X86_64" +"target_arch = i686" = "PLATFORM_I686" +"target_arch = aarch64" = "PLATFORM_AARCH64" +"target_arch = armv7" = "PLATFORM_ARMV7" + +[export] +# A list of additional items to always include in the generated bindings if they're +# found but otherwise don't appear to be used by the public API. +# +# default: [] +include = [ + "Byte", + "Boolean", + "Int8", + "UInt8", + "Int16", + "UInt16", + "Int32", + "UInt32", + "Int64", + "UInt64", + "Float32", + "Float64", + "Operation", +] + +# A list of items to not include in the generated bindings +# default: [] +exclude = [] + +# A prefix to add before the name of every item +# default: no prefix is added +#prefix = "CAPI_" + +# Types of items that we'll generate. If empty, then all types of item are emitted. +# +# possible items: (TODO: explain these in detail) +# * "constants": +# * "globals": +# * "enums": +# * "structs": +# * "unions": +# * "typedefs": +# * "opaque": +# * "functions": +# +# default: [] +item_types = ["enums", "structs", "typedefs", "functions"] + +# Whether applying rules in export.rename prevents export.prefix from applying. +# +# e.g. given this toml: +# +# [export] +# prefix = "capi_" +# [export.rename] +# "MyType" = "my_cool_type" +# +# You get the following results: +# +# renaming_overrides_prefixing = true: +# "MyType" => "my_cool_type" +# +# renaming_overrides_prefixing = false: +# "MyType => capi_my_cool_type" +# +# default: false +renaming_overrides_prefixing = false + +# Table of name conversions to apply to item names (lhs becomes rhs) +[export.rename] +#"Byte" = "Byte" +#"Boolean" = "Boolean" +#"Int8" = "Int8" +#"UInt8" = "UInt8" +#"Int16" = "Int16" +#"UInt16" = "UInt16" +#"Int32" = "Int32" +#"UInt32" = "UInt32" +#"Int64" = "Int64" +#"UInt64" = "UInt64" +#"Float32" = "Float32" +#"Float64" = "Float64" + +# Table of things to prepend to the body of any struct, union, or enum that has the +# given name. This can be used to add things like methods which don't change ABI, +# mark fields private, etc +[export.pre_body] +"MyType" = """ + MyType() = delete; +private: +""" + +# Table of things to append to the body of any struct, union, or enum that has the +# given name. This can be used to add things like methods which don't change ABI. +[export.body] +"MyType" = """ + void cppMethod() const; +""" + +# Configuration for name mangling +[export.mangle] +# Whether the types should be renamed during mangling, for example +# c_char -> CChar, etc. +#rename_types = "PascalCase" +# Whether the underscores from the mangled name should be omitted. +remove_underscores = false + +[layout] +# A string that should come before the name of any type which has been marked +# as `#[repr(packed)]`. For instance, "__attribute__((packed))" would be a +# reasonable value if targeting gcc/clang. A more portable solution would +# involve emitting the name of a macro which you define in a platform-specific +# way. e.g. "PACKED" +# +# default: `#[repr(packed)]` types will be treated as opaque, since it would +# be unsafe for C callers to use a incorrectly laid-out union. +packed = "PACKED" + +# A string that should come before the name of any type which has been marked +# as `#[repr(align(n))]`. This string must be a function-like macro which takes +# a single argument (the requested alignment, `n`). For instance, a macro +# `#define`d as `ALIGNED(n)` in `header` which translates to +# `__attribute__((aligned(n)))` would be a reasonable value if targeting +# gcc/clang. +# +# default: `#[repr(align(n))]` types will be treated as opaque, since it +# could be unsafe for C callers to use a incorrectly-aligned union. +aligned_n = "ALIGNED" + +[fn] +# An optional prefix to put before every function declaration +# default: no prefix added +# prefix = "NATIVE_API" + +# An optional postfix to put after any function declaration +# default: no postix added +#postfix = "WR_END_FUNC" + +# How to format function arguments +# +# possible values: +# * "horizontal": place all arguments on the same line +# * "vertical": place each argument on its own line +# * "auto": only use vertical if horizontal would exceed line_length +# +# default: "auto" +args = "horizontal" + +# An optional string that should prefix function declarations which have been +# marked as `#[must_use]`. For instance, "__attribute__((warn_unused_result))" +# would be a reasonable value if targeting gcc/clang. A more portable solution +# would involve emitting the name of a macro which you define in a +# platform-specific way. e.g. "MUST_USE_FUNC" +# default: nothing is emitted for must_use functions +#must_use = "MUST_USE_FUNC" + +# An optional string that will be used in the attribute position for functions +# that don't return (that return `!` in Rust). +# +# For instance, `__attribute__((noreturn))` would be a reasonable value if +# targeting gcc/clang. +#no_return = "NO_RETURN" + +# An optional string that, if present, will be used to generate Swift function +# and method signatures for generated functions, for example "CF_SWIFT_NAME". +# If no such macro is available in your toolchain, you can define one using the +# `header` option in cbindgen.toml +# default: no swift_name function attributes are generated +#swift_name_macro = "CF_SWIFT_NAME" + +# A rule to use to rename function argument names. The renaming assumes the input +# is the Rust standard snake_case, however it accepts all the different rename_args +# inputs. This means many options here are no-ops or redundant. +# +# possible values (that actually do something): +# * "CamelCase": my_arg => myArg +# * "PascalCase": my_arg => MyArg +# * "GeckoCase": my_arg => aMyArg +# * "ScreamingSnakeCase": my_arg => MY_ARG +# * "None": apply no renaming +# +# technically possible values (that shouldn't have a purpose here): +# * "SnakeCase": apply no renaming +# * "LowerCase": apply no renaming (actually applies to_lowercase, is this bug?) +# * "UpperCase": same as ScreamingSnakeCase in this context +# * "QualifiedScreamingSnakeCase" => same as ScreamingSnakeCase in this context +# +# default: "None" +rename_args = "PascalCase" + +# This rule specifies the order in which functions will be sorted. +# +# "Name": sort by the name of the function +# "None": keep order in which the functions have been parsed +# +# default: "None" +sort_by = "Name" + +# If this option is true `usize` and `isize` will be converted into `size_t` and `ptrdiff_t` +# instead of `uintptr_t` and `intptr_t` respectively. +#usize_is_size_t = true + +[struct] +# A rule to use to rename struct field names. The renaming assumes the input is +# the Rust standard snake_case, however it acccepts all the different rename_args +# inputs. This means many options here are no-ops or redundant. +# +# possible values (that actually do something): +# * "CamelCase": my_arg => myArg +# * "PascalCase": my_arg => MyArg +# * "GeckoCase": my_arg => mMyArg +# * "ScreamingSnakeCase": my_arg => MY_ARG +# * "None": apply no renaming +# +# technically possible values (that shouldn't have a purpose here): +# * "SnakeCase": apply no renaming +# * "LowerCase": apply no renaming (actually applies to_lowercase, is this bug?) +# * "UpperCase": same as ScreamingSnakeCase in this context +# * "QualifiedScreamingSnakeCase" => same as ScreamingSnakeCase in this context +# +# default: "None" +rename_fields = "PascalCase" + +# An optional string that should come before the name of any struct which has been +# marked as `#[must_use]`. For instance, "__attribute__((warn_unused))" +# would be a reasonable value if targeting gcc/clang. A more portable solution +# would involve emitting the name of a macro which you define in a +# platform-specific way. e.g. "MUST_USE_STRUCT" +# +# default: nothing is emitted for must_use structs +#must_use = "MUST_USE_STRUCT" + +# Whether a Rust type with associated consts should emit those consts inside the +# type's body. Otherwise they will be emitted trailing and with the type's name +# prefixed. This does nothing if the target is C, or if +# [const]allow_static_const = false +# +# default: false +# associated_constants_in_body: false + +# Whether to derive a simple constructor that takes a value for every field. +# default: false +derive_constructor = false + +# Whether to derive an operator== for all structs +# default: false +derive_eq = false + +# Whether to derive an operator!= for all structs +# default: false +derive_neq = false + +# Whether to derive an operator< for all structs +# default: false +derive_lt = false + +# Whether to derive an operator<= for all structs +# default: false +derive_lte = false + +# Whether to derive an operator> for all structs +# default: false +derive_gt = false + +# Whether to derive an operator>= for all structs +# default: false +derive_gte = false + +[enum] +# A rule to use to rename enum variants, and the names of any fields those +# variants have. This should probably be split up into two separate options, but +# for now, they're the same! See the documentation for `[struct]rename_fields` +# for how this applies to fields. Renaming of the variant assumes that the input +# is the Rust standard PascalCase. In the case of QualifiedScreamingSnakeCase, +# it also assumed that the enum's name is PascalCase. +# +# possible values (that actually do something): +# * "CamelCase": MyVariant => myVariant +# * "SnakeCase": MyVariant => my_variant +# * "ScreamingSnakeCase": MyVariant => MY_VARIANT +# * "QualifiedScreamingSnakeCase": MyVariant => ENUM_NAME_MY_VARIANT +# * "LowerCase": MyVariant => myvariant +# * "UpperCase": MyVariant => MYVARIANT +# * "None": apply no renaming +# +# technically possible values (that shouldn't have a purpose for the variants): +# * "PascalCase": apply no renaming +# * "GeckoCase": apply no renaming +# +# default: "None" +rename_variants = "None" + +# Whether an extra "sentinel" enum variant should be added to all generated enums. +# Firefox uses this for their IPC serialization library. +# +# WARNING: if the sentinel is ever passed into Rust, behaviour will be Undefined. +# Rust does not know about this value, and will assume it cannot happen. +# +# default: false +add_sentinel = false + +# Whether enum variant names should be prefixed with the name of the enum. +# default: false +prefix_with_name = false + +# Whether to emit enums using "enum class" when targeting C++. +# default: true +enum_class = false + +# Whether to generate static `::MyVariant(..)` constructors and `bool IsMyVariant()` +# methods for enums with fields. +# +# default: false +derive_helper_methods = false + +# Whether to generate `const MyVariant& AsMyVariant() const` methods for enums with fields. +# default: false +derive_const_casts = false + +# Whether to generate `MyVariant& AsMyVariant()` methods for enums with fields +# default: false +derive_mut_casts = false + +# The name of the macro/function to use for asserting `IsMyVariant()` in the body of +# derived `AsMyVariant()` cast methods. +# +# default: "assert" (but also causes `` to be included by default) +#cast_assert_name = "MOZ_RELEASE_ASSERT" + +# An optional string that should come before the name of any enum which has been +# marked as `#[must_use]`. For instance, "__attribute__((warn_unused))" +# would be a reasonable value if targeting gcc/clang. A more portable solution +# would involve emitting the name of a macro which you define in a +# platform-specific way. e.g. "MUST_USE_ENUM" +# +# Note that this refers to the *output* type. That means this will not apply to an enum +# with fields, as it will be emitted as a struct. `[struct]must_use` will apply there. +# +# default: nothing is emitted for must_use enums +#must_use = "MUST_USE_ENUM" + +# Whether enums with fields should generate destructors. This exists so that generic +# enums can be properly instantiated with payloads that are C++ types with +# destructors. This isn't necessary for structs because C++ has rules to +# automatically derive the correct constructors and destructors for those types. +# +# Care should be taken with this option, as Rust and C++ cannot +# properly interoperate with eachother's notions of destructors. Also, this may +# change the ABI for the type. Either your destructor-full enums must live +# exclusively within C++, or they must only be passed by-reference between +# C++ and Rust. +# +# default: false +derive_tagged_enum_destructor = false + +# Whether enums with fields should generate copy-constructor. See the discussion on +# derive_tagged_enum_destructor for why this is both useful and very dangerous. +# +# default: false +derive_tagged_enum_copy_constructor = false +# Whether enums with fields should generate copy-assignment operators. +# +# This depends on also deriving copy-constructors, and it is highly encouraged +# for this to be set to true. +# +# default: false +derive_tagged_enum_copy_assignment = false + +# Whether enums with fields should generate an empty, private destructor. +# This allows the auto-generated constructor functions to compile, if there are +# non-trivially constructible members. This falls in the same family of +# dangerousness as `derive_tagged_enum_copy_constructor` and co. +# +# default: false +private_default_tagged_enum_constructor = false + +[const] +# Whether a generated constant can be a static const in C++ mode. I have no +# idea why you would turn this off. +# +# default: true +allow_static_const = true + +# Whether a generated constant can be constexpr in C++ mode. +# +# default: false +allow_constexpr = false + +# This rule specifies the order in which constants will be sorted. +# +# "Name": sort by the name of the constant +# "None": keep order in which the constants have been parsed +# +# default: "None" +sort_by = "Name" + +[macro_expansion] +# Whether bindings should be generated for instances of the bitflags! macro. +# default: false +bitflags = false + +# Options for how your Rust library should be parsed + +[parse] +# Whether to parse dependent crates and include their types in the output +# default: false +parse_deps = true + +# A white list of crate names that are allowed to be parsed. If this is defined, +# only crates found in this list will ever be parsed. +# +# default: there is no whitelist (NOTE: this is the opposite of []) +include = ["mintaka"] + +# A black list of crate names that are not allowed to be parsed. +# default: [] +exclude = [] + +# Whether to use a new temporary target directory when running `rustc --pretty=expanded`. +# This may be required for some build processes. +# +# default: false +clean = false + +# Which crates other than the top-level binding crate we should generate +# bindings for. +# +# default: [] +extra_bindings = [] + +[parse.expand] +# A list of crate names that should be run through `cargo expand` before +# parsing to expand any macros. Note that if a crate is named here, it +# will always be parsed, even if the blacklist/whitelist says it shouldn't be. +# +# default: [] +crates = [] + +# If enabled, use the `--all-features` option when expanding. Ignored when +# `features` is set. For backwards-compatibility, this is forced on if +# `expand = ["euclid"]` shorthand is used. +# +# default: false +all_features = false + +# When `all_features` is disabled and this is also disabled, use the +# `--no-default-features` option when expanding. +# +# default: true +default_features = true + +# A list of feature names that should be used when running `cargo expand`. This +# combines with `default_features` like in your `Cargo.toml`. Note that the features +# listed here are features for the current crate being built, *not* the crates +# being expanded. The crate's `Cargo.toml` must take care of enabling the +# appropriate features in its dependencies +# +# default: [] +features = [] + +[ptr] +# An optional string to decorate all pointers that are +# required to be non null. Nullability is inferred from the Rust type: `&T`, +# `&mut T` and `NonNull` all require a valid pointer value. +#non_null_attribute = "_Nonnull" diff --git a/Examples/Assembler.rs b/Examples/Assembler.rs new file mode 100644 index 0000000..867ce52 --- /dev/null +++ b/Examples/Assembler.rs @@ -0,0 +1,27 @@ +#![allow(non_snake_case)] + +use ::Machine::*; +use bincode::Options; +use std::fs; + +fn main() { + let assembly = Assembly { + name: "Serialization Example".into(), + version: 1, + source: AssemblySource { + text: include_bytes!("Bytecode.bin").to_vec(), + data: Vec::new(), + }, + }; + + let options = bincode::options() + .with_big_endian() + .with_fixint_encoding() + .allow_trailing_bytes(); + + let encoded: Vec = options.serialize(&assembly).unwrap(); + fs::write("Examples/Assembly.bin", &encoded).unwrap(); + + //let decoded: Assembly = bincode::deserialize(&encoded[..]).unwrap(); + //assert_eq!(assembly, decoded); +} diff --git a/Examples/Assembly.bin b/Examples/Assembly.bin new file mode 100644 index 0000000000000000000000000000000000000000..71ef9c33e5a44adb0eddb6dc82a906cc9dec1141 GIT binary patch literal 318 zcmZQz00YtB)S}G9oXo1klFa-(1=oti+=84`Mu;S%0GJWL1mrp}Ffs$F5Ega@5KSKV SFL=vDaIMQ)7xJ_Z9$f$qtqptt literal 0 HcmV?d00001 diff --git a/Examples/Loader.rs b/Examples/Loader.rs new file mode 100644 index 0000000..c246630 --- /dev/null +++ b/Examples/Loader.rs @@ -0,0 +1,21 @@ +#![allow(non_snake_case)] + +use ::Machine::*; +use bincode::Options; +use std::fs; + +fn main() { + let encoded: Vec = fs::read("Examples/Assembly.bin").unwrap(); + + let options = bincode::options() + .with_big_endian() + .with_fixint_encoding() + .allow_trailing_bytes(); + + let assembly: Assembly = options.deserialize(&encoded[..]).unwrap(); + + let mut vm = Machine::New([0, 0, 0, 0]); + + vm.LoadProgram(&assembly.source.text); + vm.Execute(); +} diff --git a/Source/Assembly.rs b/Source/Assembly.rs new file mode 100644 index 0000000..b1af3a5 --- /dev/null +++ b/Source/Assembly.rs @@ -0,0 +1,23 @@ +use serde::{Deserialize, Serialize}; +use std::borrow::Cow; + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub struct Assembly { + /// Assembly name. + pub name: Cow<'static, str>, + + /// Assembly version. + pub version: u8, + + /// Assembly bytecode source. + pub source: AssemblySource, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub struct AssemblySource { + /// Source instructions. + pub text: Vec, + + /// Statics and embed data. + pub data: Vec, +} diff --git a/Source/Instruction.rs b/Source/Instruction.rs new file mode 100644 index 0000000..5773527 --- /dev/null +++ b/Source/Instruction.rs @@ -0,0 +1,24 @@ +use crate::Machine; +use crate::Payload::PayloadType; +use crate::Types::Byte; + +pub struct Instruction { + pub code: Byte, + pub name: String, + pub payload: PayloadType, + pub function: InstructionFunction, +} + +pub type InstructionFunction = fn(machine: &mut Machine) -> bool; + +impl Instruction { + #[inline] + pub fn New(code: Byte, name: &str, payload: PayloadType, function: InstructionFunction) -> Self { + Self { + code, + name: name.to_string(), + payload, + function, + } + } +} diff --git a/Source/InstructionTable.rs b/Source/InstructionTable.rs new file mode 100644 index 0000000..57f9230 --- /dev/null +++ b/Source/InstructionTable.rs @@ -0,0 +1,45 @@ +use crate::Instruction; +use crate::Instructions::*; +use crate::Operations::*; +use crate::Payload::PayloadType; +use crate::Types::Byte; +use std::collections::HashMap; + +pub struct InstructionTable { + table: HashMap, +} + +impl Default for InstructionTable { + fn default() -> Self { + Self { + table: HashMap::new(), + } + } +} + +impl InstructionTable { + #[inline] + pub fn New() -> Self { + let mut table = InstructionTable::default(); + + table.Insert(Instruction::New(NOP, "nop", PayloadType::Nothing, Nothing)); + table.Insert(Instruction::New(HLT, "hlt", PayloadType::Nothing, Halt)); + + table + } + + #[inline] + pub fn IsEmpty(&self) -> bool { + self.table.is_empty() + } + + #[inline] + pub fn Get(&self, code: Byte) -> Option<&Instruction> { + self.table.get(&code) + } + + #[inline] + pub fn Insert(&mut self, instr: Instruction) { + self.table.insert(instr.code, instr); + } +} diff --git a/Source/Mnemonics.rs b/Source/Mnemonics.rs new file mode 100644 index 0000000..8621324 --- /dev/null +++ b/Source/Mnemonics.rs @@ -0,0 +1,969 @@ +#[repr(u8)] +#[allow(non_camel_case_types)] +pub enum Mnemonic { + /// **0x00** - No operation. + /// + /// ```no_run + /// nop + /// ``` + NOP = 0x00, + + /// **0x01** - Load register with byte from memory address. + /// + /// ```no_run + /// ldr b r1 r2 // r1 = heap[r2] + /// ``` + LDR_B = 0x01, + + /// **0x02** - Load register with half word from memory address. + /// + /// ```no_run + /// ldr h r1 r2 // r1 = heap[r2..r2 + 2] + /// ``` + LDR_H = 0x02, + + /// **0x03** - Load register with word from memory address. + /// + /// ```no_run + /// ldr w r1 r2 // r1 = heap[r2..r2 + 4] + /// ``` + LDR_W = 0x03, + + /// **0x04** - Load register with double word from memory address. + /// + /// ```no_run + /// ldr d r1 r2 // r1 = heap[r2..r2 + 8] + /// ``` + LDR_D = 0x04, + + /// **0x05** - Load register with quad word from memory address. + /// + /// ```no_run + /// ldr q r1 r2 r3 // r1 = heap[r3..r3 + 8], r2 = heap[r3 + 8..r3 + 16] + /// ``` + LDR_Q = 0x05, + + /// **0x06** - Load register with byte from memory address. + /// + /// ```no_run + /// lda b r1 0050 // r1 = heap[0050] + /// ``` + LDA_B = 0x06, + + /// **0x07** - Load register with half word from memory address. + /// + /// ```no_run + /// lda h r1 0050 // r1 = heap[0050..0050 + 2] + /// ``` + LDA_H = 0x07, + + /// **0x08** - Load register with word from memory address. + /// + /// ```no_run + /// lda w r1 0050 // r1 = heap[0050..0050 + 4] + /// ``` + LDA_W = 0x08, + + /// **0x09** - Load register with double word from memory address. + /// + /// ```no_run + /// lda d r1 0050 // r1 = heap[0050..0050 + 8] + /// ``` + LDA_D = 0x09, + + /// **0x0A** - Load register with quad word from memory address. + /// + /// ```no_run + /// lda q r1 r2 0050 // r1 = heap[0050..0050 + 8], r2 = heap[0050 + 8..0050 + 16] + /// ``` + LDA_Q = 0x0A, + + /// **0x0B** - Load register with byte from imediate value. + /// + /// ```no_run + /// ldi b r1 1 // r1 = 1 + /// ``` + LDI_B = 0x0B, + + /// **0x0C** - Load register with half word from imediate value. + /// + /// ```no_run + /// ldi h r1 1 // r1 = 1 + /// ``` + LDI_H = 0x0C, + + /// **0x0D** - Load register with word from imediate value. + /// + /// ```no_run + /// ldi w r1 1 // r1 = 1 + /// ``` + LDI_W = 0x0D, + + /// **0x0E** - Load register with double word from imediate value. + /// + /// ```no_run + /// ldi d r1 1 // r1 = 1 + /// ``` + LDI_D = 0x0E, + + /// **0x0F** - Load register with quad word from imediate value. + /// + /// ```no_run + /// ldi q r1 r2 11 // r1 = 1, r2 = 1 + /// ``` + LDI_Q = 0x0F, + + /// **0x10** - Store byte in memory address from register. + /// + /// ```no_run + /// str b r1 r2 // heap[r1] = r2 + /// ``` + STR_B = 0x10, + + /// **0x11** - Store half word in memory address from register. + /// + /// ```no_run + /// str h r1 r2 // heap[r1..r1 + 2] = r2 + /// ``` + STR_H = 0x11, + + /// **0x12** - Store word in memory address from register. + /// + /// ```no_run + /// str w r1 r2 // heap[r1..r1 + 4] = r2 + /// ``` + STR_W = 0x12, + + /// **0x13** - Store double word in memory address from register. + /// + /// ```no_run + /// str d r1 r2 // heap[r1..r1 + 8] = r2 + /// ``` + STR_D = 0x13, + + /// **0x14** - Store quad word in memory address from register. + /// + /// ```no_run + /// str q r1 r2 r3 // heap[r1..r1 + 8] = r2, heap[r1 + 8..r1 + 16] = r3 + /// ``` + STR_Q = 0x14, + + /// **0x15** - Store byte in memory address from register. + /// + /// ```no_run + /// sta b 0050 r1 // heap[0050] = r1 + /// ``` + STA_B = 0x15, + + /// **0x16** - Store half word in memory address from register. + /// + /// ```no_run + /// sta h 0050 r1 // heap[0050..0050 + 2] = r1 + /// ``` + STA_H = 0x16, + + /// **0x17** - Store word in memory address from register. + /// + /// ```no_run + /// sta w 0050 r1 // heap[0050..0050 + 4] = r1 + /// ``` + STA_W = 0x17, + + /// **0x18** - Store double word in memory address from register. + /// + /// ```no_run + /// sta d 0050 r1 // heap[0050..0050 + 8] = r1 + /// ``` + STA_D = 0x18, + + /// **0x19** - Store quad word in memory address from register. + /// + /// ```no_run + /// sta q 0050 r1 r2 // heap[0050..0050 + 8] = r1, heap[0050 + 8..0050 + 16] = r2 + /// ``` + STA_Q = 0x19, + + /// **0x1A** - Store byte in memory address from imediate value. + /// + /// ```no_run + /// sti b 0050 1 // heap[0050] = 1 + /// ``` + STI_B = 0x1A, + + /// **0x1B** - Store half word in memory address from imediate value. + /// + /// ```no_run + /// sti h 0050 1 // heap[0050..0050 + 2] = 1 + /// ``` + STI_H = 0x1B, + + /// **0x1C** - Store word in memory address from imediate value. + /// + /// ```no_run + /// sti w 0050 1 // heap[0050..0050 + 4] = 1 + /// ``` + STI_W = 0x1C, + + /// **0x1D** - Store double word in memory address from imediate value. + /// + /// ```no_run + /// sti d 0050 1 // heap[0050..0050 + 8] = 1 + /// ``` + STI_D = 0x1D, + + /// **0x1E** - Store quad word in memory address from imediate value. + /// + /// ```no_run + /// sti q 0050 1 // heap[0050..0050 + 16] = 1 + /// ``` + STI_Q = 0x1E, + + /// **0x1F** - Increment register value. + /// + /// ```no_run + /// inc r1 // r1 += 1 + /// ``` + INC = 0x1F, + + /// **0x20** - Decrement register value. + /// + /// ```no_run + /// dec r1 // r1 -= 1 + /// ``` + DEC = 0x20, + + /// **0x21** - Move register value to other register. + /// + /// ```no_run + /// mov r1 r2 + /// ``` + MOV = 0x21, + + /// **0x22** - Swap values of two registers. + /// + /// ```no_run + /// swp r1 r2 + /// ``` + SWP = 0x22, + + /// **0x23** - Jump to instruction. + /// + /// ```no_run + /// jmp 0050 // pc = 0050 + /// ``` + JMP = 0x23, + + /// **0x24** - Jump to instruction, if stack.peek() == 0. + /// + /// ```no_run + /// jmz 0050 // pc = 0050 + /// ``` + JMZ = 0x24, + + /// **0x25** - Jump to instruction, if last comparation was equals. + /// + /// ```no_run + /// jeq 0050 // pc = 0050 + /// ``` + JEQ = 0x25, + + /// **0x26** - Jump to instruction, if last comparation was not equals. + /// + /// ```no_run + /// jne 0050 // pc = 0050 + /// ``` + JNE = 0x26, + + /// **0x27** - Jump to instruction, if last comparation was less than. + /// + /// ```no_run + /// jlt 0050 // pc = 0050 + /// ``` + JLT = 0x27, + + /// **0x28** - Jump to instruction, if last comparation was less tan or equals. + /// + /// ```no_run + /// jle 0050 // pc = 0050 + /// ``` + JLE = 0x28, + + /// **0x29** - Jump to instruction, if last comparation was greater than. + /// + /// ```no_run + /// jgt 0050 // pc = 0050 + /// ``` + JGT = 0x29, + + /// **0x2A** - Jump to instruction, if last comparation was greater than or equals. + /// + /// ```no_run + /// jge 0050 // pc = 0050 + /// ``` + JGE = 0x2A, + + /// **0x2B** - Call function with label. + /// + /// ```no_run + /// call 0050 // pc = 0050 + /// ``` + CALL = 0x2B, + + /// **0x2C** - Return from the current function. + /// + /// ```no_run + /// ret // pc = lr + /// ``` + RET = 0x2C, + + /// **0x2D** - Push byte from register into stack. + /// + /// ```no_run + /// push b r1 + /// ``` + PUSH_B = 0x2D, + + /// **0x2E** - Push half word from register into stack. + /// + /// ```no_run + /// push h r1 + /// ``` + PUSH_H = 0x2E, + + /// **0x2F** - Push word from register into stack. + /// + /// ```no_run + /// push w r1 + /// ``` + PUSH_W = 0x2F, + + /// **0x30** - Push double word from register into stack. + /// + /// ```no_run + /// push d r1 + /// ``` + PUSH_D = 0x30, + + /// **0x31** - Push quad word from register into stack. + /// + /// ```no_run + /// push q r1 r2 + /// ``` + PUSH_Q = 0x31, + + /// **0x32** - Peek byte from stack into register. + /// + /// ```no_run + /// peek b r1 // r1 = stack[sp] + /// ``` + PEEK_B = 0x32, + + /// **0x33** - Peek half word from stack into register. + /// + /// ```no_run + /// peek h r1 // r1 = stack[sp..sp + 2] + /// ``` + PEEK_H = 0x33, + + /// **0x34** - Peek word from stack into register. + /// + /// ```no_run + /// peek w r1 // r1 = stack[sp..sp + 4] + /// ``` + PEEK_W = 0x34, + + /// **0x35** - Peek double word from stack into register. + /// + /// ```no_run + /// peek d r1 // r1 = stack[sp..sp + 8] + /// ``` + PEEK_D = 0x35, + + /// **0x36** - Peek quad from stack into register. + /// + /// ```no_run + /// peek q r1 r2 // r1 = stack[sp..sp + 8], r2 = stack[sp + 8..sp + 16] + /// ``` + PEEK_Q = 0x36, + + /// **0x37** - Pop byte from stack into register. + /// + /// ```no_run + /// pop b r1 // r1 = stack[sp] + /// ``` + POP_B = 0x37, + + /// **0x38** - Pop half word from stack into register. + /// + /// ```no_run + /// pop h r1 // r1 = stack[sp..sp + 2] + /// ``` + POP_H = 0x38, + + /// **0x39** - Pop word from stack into register. + /// + /// ```no_run + /// pop w r1 // r1 = stack[sp..sp + 4] + /// ``` + POP_W = 0x39, + + /// **0x3A** - Pop double word from stack into register. + /// + /// ```no_run + /// pop d r1 // r1 = stack[sp..sp + 8] + /// ``` + POP_D = 0x3A, + + /// **0x3B** - Pop quad word from stack into register. + /// + /// ```no_run + /// pop q r1 r2 // r1 = stack[sp..sp + 8], r2 = stack[sp + 8..sp + 16] + /// ``` + POP_Q = 0x3B, + + /// **0x3C** - Arithmetic negation `-`. + /// + /// ```no_run + /// neg r1 r2 // r1 = -r2 + /// ``` + NEG = 0x3C, + + /// **0x3D** - No operation. + /// + /// ```no_run + /// add u8 r1 r2 r3 + /// ``` + ADD_U8 = 0x3D, + + /// **0x3E** - No operation. + /// + /// ```no_run + /// add u16 r1 r2 r3 + /// ``` + ADD_U16 = 0x3E, + + /// **0x3F** - No operation. + /// + /// ```no_run + /// add u32 r1 r2 r3 + /// ``` + ADD_U32 = 0x3F, + + /// **0x40** - No operation. + /// + /// ```no_run + /// add u64 r1 r2 r3 + /// ``` + ADD_U64 = 0x40, + + /// **0x41** - No operation. + /// + /// ```no_run + /// add u128 r1 r2 r3 + /// ``` + ADD_U128 = 0x41, + + /// **0x42** - No operation. + /// + /// ```no_run + /// add i8 r1 r2 r3 + /// ``` + ADD_I8 = 0x42, + + /// **0x43** - No operation. + /// + /// ```no_run + /// add i16 r1 r2 r3 + /// ``` + ADD_I16 = 0x43, + + /// **0x44** - No operation. + /// + /// ```no_run + /// add i32 r1 r2 r3 + /// ``` + ADD_I32 = 0x44, + + /// **0x45** - No operation. + /// + /// ```no_run + /// add i64 r1 r2 r3 + /// ``` + ADD_I64 = 0x45, + + /// **0x46** - No operation. + /// + /// ```no_run + /// add i128 r1 r2 r3 r4 r5 + /// ``` + ADD_I128 = 0x46, + + /// **0x47** - No operation. + /// + /// ```no_run + /// add f32 r1 r2 r3 + /// ``` + ADD_F32 = 0x47, + + /// **0x48** - No operation. + /// + /// ```no_run + /// add f64 r1 r2 r3 + /// ``` + ADD_F64 = 0x48, + + /// **0x49** - No operation. + /// + /// ```no_run + /// sub u8 r1 r2 r3 + /// ``` + SUB_U8 = 0x49, + + /// **0x4A** - No operation. + /// + /// ```no_run + /// sub u16 r1 r2 r3 + /// ``` + SUB_U16 = 0x4A, + + /// **0x4B** - No operation. + /// + /// ```no_run + /// sub u32 r1 r2 r3 + /// ``` + SUB_U32 = 0x4B, + + /// **0x4C** - No operation. + /// + /// ```no_run + /// sub u64 r1 r2 r3 + /// ``` + SUB_U64 = 0x4C, + + /// **0x4D** - No operation. + /// + /// ```no_run + /// sub u128 r1 r2 r3 + /// ``` + SUB_U128 = 0x4D, + + /// **0x4E** - No operation. + /// + /// ```no_run + /// sub i8 r1 r2 r3 + /// ``` + SUB_I8 = 0x4E, + + /// **0x4F** - No operation. + /// + /// ```no_run + /// sub i16 r1 r2 r3 + /// ``` + SUB_I16 = 0x4F, + + /// **0x50** - No operation. + /// + /// ```no_run + /// sub i32 r1 r2 r3 + /// ``` + SUB_I32 = 0x50, + + /// **0x51** - No operation. + /// + /// ```no_run + /// sub i64 r1 r2 r3 + /// ``` + SUB_I64 = 0x51, + + /// **0x52** - No operation. + /// + /// ```no_run + /// sub i128 r1 r2 r3 r4 r5 + /// ``` + SUB_I128 = 0x52, + + /// **0x53** - No operation. + /// + /// ```no_run + /// sub f32 r1 r2 r3 + /// ``` + SUB_F32 = 0x53, + + /// **0x54** - No operation. + /// + /// ```no_run + /// sub f64 r1 r2 r3 + /// ``` + SUB_F64 = 0x54, + + /// **0x55** - No operation. + /// + /// ```no_run + /// mul u8 r1 r2 r3 + /// ``` + MUL_U8 = 0x55, + + /// **0x56** - No operation. + /// + /// ```no_run + /// mul u16 r1 r2 r3 + /// ``` + MUL_U16 = 0x56, + + /// **0x57** - No operation. + /// + /// ```no_run + /// mul u32 r1 r2 r3 + /// ``` + MUL_U32 = 0x57, + + /// **0x58** - No operation. + /// + /// ```no_run + /// mul u64 r1 r2 r3 + /// ``` + MUL_U64 = 0x58, + + /// **0x59** - No operation. + /// + /// ```no_run + /// mul u128 r1 r2 r3 + /// ``` + MUL_U128 = 0x59, + + /// **0x5A** - No operation. + /// + /// ```no_run + /// mul i8 r1 r2 r3 + /// ``` + MUL_I8 = 0x5A, + + /// **0x5B** - No operation. + /// + /// ```no_run + /// mul i16 r1 r2 r3 + /// ``` + MUL_I16 = 0x5B, + + /// **0x5C** - No operation. + /// + /// ```no_run + /// mul i32 r1 r2 r3 + /// ``` + MUL_I32 = 0x5C, + + /// **0x5D** - No operation. + /// + /// ```no_run + /// mul i64 r1 r2 r3 + /// ``` + MUL_I64 = 0x5D, + + /// **0x5E** - No operation. + /// + /// ```no_run + /// mul i128 r1 r2 r3 r4 r5 + /// ``` + MUL_I128 = 0x5E, + + /// **0x5F** - No operation. + /// + /// ```no_run + /// mul f32 r1 r2 r3 + /// ``` + MUL_F32 = 0x5F, + + /// **0x60** - No operation. + /// + /// ```no_run + /// mul f64 r1 r2 r3 + /// ``` + MUL_F64 = 0x60, + + /// **0x61** - No operation. + /// + /// ```no_run + /// div u8 r1 r2 r3 + /// ``` + DIV_U8 = 0x61, + + /// **0x62** - No operation. + /// + /// ```no_run + /// div u16 r1 r2 r3 + /// ``` + DIV_U16 = 0x62, + + /// **0x63** - No operation. + /// + /// ```no_run + /// div u32 r1 r2 r3 + /// ``` + DIV_U32 = 0x63, + + /// **0x64** - No operation. + /// + /// ```no_run + /// div u64 r1 r2 r3 + /// ``` + DIV_U64 = 0x64, + + /// **0x65** - No operation. + /// + /// ```no_run + /// div u128 r1 r2 r3 + /// ``` + DIV_U128 = 0x65, + + /// **0x66** - No operation. + /// + /// ```no_run + /// div i8 r1 r2 r3 + /// ``` + DIV_I8 = 0x66, + + /// **0x67** - No operation. + /// + /// ```no_run + /// div i16 r1 r2 r3 + /// ``` + DIV_I16 = 0x67, + + /// **0x68** - No operation. + /// + /// ```no_run + /// div i32 r1 r2 r3 + /// ``` + DIV_I32 = 0x68, + + /// **0x69** - No operation. + /// + /// ```no_run + /// div i64 r1 r2 r3 + /// ``` + DIV_I64 = 0x69, + + /// **0x6A** - No operation. + /// + /// ```no_run + /// div i128 r1 r2 r3 r4 r5 + /// ``` + DIV_I128 = 0x6A, + + /// **0x6B** - No operation. + /// + /// ```no_run + /// div f32 r1 r2 r3 + /// ``` + DIV_F32 = 0x6B, + + /// **0x6C** - No operation. + /// + /// ```no_run + /// div f64 r1 r2 r3 + /// ``` + DIV_F64 = 0x6C, + + /// **0x6D** - No operation. + /// + /// ```no_run + /// rem u8 r1 r2 r3 + /// ``` + REM_U8 = 0x6D, + + /// **0x6E** - No operation. + /// + /// ```no_run + /// rem u16 r1 r2 r3 + /// ``` + REM_U16 = 0x6E, + + /// **0x6F** - No operation. + /// + /// ```no_run + /// rem u32 r1 r2 r3 + /// ``` + REM_U32 = 0x6F, + + /// **0x70** - No operation. + /// + /// ```no_run + /// rem u64 r1 r2 r3 + /// ``` + REM_U64 = 0x70, + + /// **0x71** - No operation. + /// + /// ```no_run + /// rem u128 r1 r2 r3 + /// ``` + REM_U128 = 0x71, + + /// **0x72** - No operation. + /// + /// ```no_run + /// rem i8 r1 r2 r3 + /// ``` + REM_I8 = 0x72, + + /// **0x73** - No operation. + /// + /// ```no_run + /// rem i16 r1 r2 r3 + /// ``` + REM_I16 = 0x73, + + /// **0x74** - No operation. + /// + /// ```no_run + /// rem i32 r1 r2 r3 + /// ``` + REM_I32 = 0x74, + + /// **0x75** - No operation. + /// + /// ```no_run + /// rem i64 r1 r2 r3 + /// ``` + REM_I64 = 0x75, + + /// **0x76** - No operation. + /// + /// ```no_run + /// rem i128 r1 r2 r3 r4 r5 + /// ``` + REM_I128 = 0x76, + + /// **0x77** - No operation. + /// + /// ```no_run + /// rem f32 r1 r2 r3 + /// ``` + REM_F32 = 0x77, + + /// **0x78** - No operation. + /// + /// ```no_run + /// rem f64 r1 r2 r3 + /// ``` + REM_F64 = 0x78, + + /// **0x79** - No operation. + /// + /// ```no_run + /// and r1 r2 r3 + /// ``` + AND = 0x79, + + /// **0x7A** - No operation. + /// + /// ```no_run + /// or r1 r2 r3 + /// ``` + OR = 0x7A, + + /// **0x7B** - No operation. + /// + /// ```no_run + /// xor r1 r2 r3 + /// ``` + XOR = 0x7B, + + /// **0x7C** - No operation. + /// + /// ```no_run + /// not r1 r2 + /// ``` + NOT = 0x7C, + + /// **0x7D** - No operation. + /// + /// ```no_run + /// nand r1 r2 r3 + /// ``` + NAND = 0x7D, + + /// **0x7E** - No operation. + /// + /// ```no_run + /// nor r1 r2 r3 + /// ``` + NOR = 0x7E, + + /// **0x7F** - No operation. + /// + /// ```no_run + /// xnor r1 r2 r3 + /// ``` + XNOR = 0x7F, + + /// **0x80** - No operation. + /// + /// ```no_run + /// shl r1 r2 + /// ``` + SHL = 0x80, + + /// **0x81** - No operation. + /// + /// ```no_run + /// shr r1 r2 + /// ``` + SHR = 0x81, + + /// **0x82** - No operation. + /// + /// ```no_run + /// cmp r1 r2 + /// ``` + CMP = 0x82, + + /// **0x83** - No operation. + /// + /// ```no_run + /// eq r1 r2 r3 + /// ``` + EQ = 0x83, + + /// **0x84** - No operation. + /// + /// ```no_run + /// ne r1 r2 r3 + /// ``` + NE = 0x84, + + /// **0x85** - No operation. + /// + /// ```no_run + /// lt r1 r2 r3 + /// ``` + LT = 0x85, + + /// **0x86** - No operation. + /// + /// ```no_run + /// le r1 r2 r3 + /// ``` + LE = 0x86, + + /// **0x87** - No operation. + /// + /// ```no_run + /// gt r1 r2 r3 + /// ``` + GT = 0x87, + + /// **0x88** - No operation. + /// + /// ```no_run + /// ge r1 r2 r3 + /// ``` + GE = 0x88, + + /// **0xFF** - No operation. + /// + /// ```no_run + /// hlt + /// ``` + HLT = 0xFF, +} diff --git a/Source/Stack.rs b/Source/Stack.rs index f847e37..3d12e23 100644 --- a/Source/Stack.rs +++ b/Source/Stack.rs @@ -1,33 +1,150 @@ -use crate::Frame; +use crate::Types::*; +use std::mem; pub struct Stack { - frames: Vec, + inner: Vec, lenght: usize, } impl Stack { pub fn New(size: usize) -> Self { Self { - frames: Vec::with_capacity(size), + inner: Vec::with_capacity(size), lenght: size, } } pub fn IsEmpty(&self) -> bool { - self.frames.is_empty() + self.inner.is_empty() } pub fn Flush(&mut self) { - self.frames.clear(); + self.inner.clear(); } - pub fn Push(&mut self, frame: Frame) { - if self.frames.len() + frame.GetSize() < self.lenght { - self.frames.push(frame); + pub fn PushByte(&mut self, value: Byte) { + if self.inner.len() + 1 < self.lenght { + self.inner.push(value); } } - pub fn Pop(&mut self) -> Frame { - self.frames.pop().unwrap_or(Frame::Null()) + pub fn PeekByte(&self) -> Byte { + *self.inner.last().unwrap() + } + + pub fn PopByte(&mut self) -> Byte { + self.inner.pop().unwrap() + } + + pub fn PushHalf(&mut self, value: Half) { + if self.inner.len() + 1 < self.lenght { + self.inner.extend(value); + } + } + + pub fn PeekHalf(&self) -> Half { + const BYTES: usize = mem::size_of::(); + let mut buffer = [0; BYTES]; + + for i in 0..BYTES { + buffer[i] = *self.inner.last().unwrap_or(&0); + } + + buffer + } + + pub fn PopHalf(&mut self) -> Half { + const BYTES: usize = mem::size_of::(); + let mut buffer = [0; BYTES]; + + for i in 0..BYTES { + buffer[i] = self.inner.pop().unwrap_or(0); + } + + buffer + } + + pub fn PushWord(&mut self, value: Word) { + if self.inner.len() + 1 < self.lenght { + self.inner.extend(value); + } + } + + pub fn PeekWord(&self) -> Word { + const BYTES: usize = mem::size_of::(); + let mut buffer = [0; BYTES]; + + for i in 0..BYTES { + buffer[i] = *self.inner.last().unwrap_or(&0); + } + + buffer + } + + pub fn PopWord(&mut self) -> Word { + const BYTES: usize = mem::size_of::(); + let mut buffer = [0; BYTES]; + + for i in 0..BYTES { + buffer[i] = self.inner.pop().unwrap_or(0); + } + + buffer + } + + pub fn PushDWord(&mut self, value: DWord) { + if self.inner.len() + 1 < self.lenght { + self.inner.extend(value); + } + } + + pub fn PeekDWord(&self) -> DWord { + const BYTES: usize = mem::size_of::(); + let mut buffer = [0; BYTES]; + + for i in 0..BYTES { + buffer[i] = *self.inner.last().unwrap_or(&0); + } + + buffer + } + + pub fn PopDWord(&mut self) -> DWord { + const BYTES: usize = mem::size_of::(); + let mut buffer = [0; BYTES]; + + for i in 0..BYTES { + buffer[i] = self.inner.pop().unwrap_or(0); + } + + buffer + } + + pub fn PushQWord(&mut self, value: QWord) { + if self.inner.len() + 1 < self.lenght { + self.inner.extend(value); + } + } + + pub fn PeekQWord(&self) -> QWord { + const BYTES: usize = mem::size_of::(); + let mut buffer = [0; BYTES]; + + for i in 0..BYTES { + buffer[i] = *self.inner.last().unwrap_or(&0); + } + + buffer + } + + pub fn PopQWord(&mut self) -> QWord { + const BYTES: usize = mem::size_of::(); + let mut buffer = [0; BYTES]; + + for i in 0..BYTES { + buffer[i] = self.inner.pop().unwrap_or(0); + } + + buffer } } diff --git a/Source/Types.rs b/Source/Types.rs index fada5a4..97cbb40 100644 --- a/Source/Types.rs +++ b/Source/Types.rs @@ -3,3 +3,22 @@ pub type Half = [Byte; 2]; pub type Word = [Byte; 4]; pub type DWord = [Byte; 8]; pub type QWord = [Byte; 16]; + +pub enum PrimitiveType { + Byte, + Bool, + Char, + Int8, + Int16, + Int32, + Int64, + Int128, + UInt8, + UInt16, + UInt32, + UInt64, + UInt128, + Float32, + Float64, + String, +} diff --git a/Source/lib.rs b/Source/lib.rs index dc29f7f..d1b7606 100644 --- a/Source/lib.rs +++ b/Source/lib.rs @@ -3,10 +3,15 @@ mod Instructions; +pub mod Mnemonics; pub mod Operations; pub mod Payload; pub mod Types; +#[path = "Assembly.rs"] +mod _Assembly; +pub use self::_Assembly::*; + #[path = "Frame.rs"] mod _Frame; pub use self::_Frame::*; @@ -30,3 +35,11 @@ pub use self::_Registry::*; #[path = "Stack.rs"] mod _Stack; pub use self::_Stack::*; + +#[path = "Instruction.rs"] +mod _Instruction; +pub use self::_Instruction::*; + +#[path = "InstructionTable.rs"] +mod _InstructionTable; +pub use self::_InstructionTable::*;