summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAmlal <amlal@nekernel.org>2025-04-25 13:14:01 +0200
committerAmlal <amlal@nekernel.org>2025-04-25 13:14:01 +0200
commit20042235d1f53ae428aa154e64afdbae5d8d91ad (patch)
tree6ea42d1b30505a57301f8ff2916c78ce94ff6eaf
parent0561a8d0a6ae7588309a6e3513bbfeeef5f0aa15 (diff)
meta: update .clang-format, format codebase.
Signed-off-by: Amlal <amlal@nekernel.org>
-rw-r--r--.clang-format43
-rw-r--r--dev/LibC++/base_alloc.h74
-rw-r--r--dev/LibC++/base_exception.h32
-rw-r--r--dev/LibC++/base_math.h80
-rw-r--r--dev/LibC++/base_process.h16
-rw-r--r--dev/LibC++/defines.h57
-rw-r--r--dev/LibC++/filesystem.h17
-rw-r--r--dev/LibC++/lc_runtime+unreachable.cc10
-rw-r--r--dev/LibC++/lc_runtime.h4
-rw-r--r--dev/LibC++/utility.h45
-rw-r--r--dev/LibCompiler/AE.h199
-rw-r--r--dev/LibCompiler/AssemblyInterface.h354
-rw-r--r--dev/LibCompiler/Backend/32x0.h68
-rw-r--r--dev/LibCompiler/Backend/64x0.h85
-rw-r--r--dev/LibCompiler/Backend/amd64.h48
-rw-r--r--dev/LibCompiler/Backend/arm64.h39
-rw-r--r--dev/LibCompiler/Backend/power64.h3404
-rw-r--r--dev/LibCompiler/Defines.h134
-rw-r--r--dev/LibCompiler/ErrorID.h16
-rw-r--r--dev/LibCompiler/ErrorOr.h78
-rw-r--r--dev/LibCompiler/Macros.h28
-rw-r--r--dev/LibCompiler/PEF.h191
-rw-r--r--dev/LibCompiler/Parser.h303
-rw-r--r--dev/LibCompiler/Ref.h150
-rw-r--r--dev/LibCompiler/StringView.h139
-rw-r--r--dev/LibCompiler/UUID.h1582
-rw-r--r--dev/LibCompiler/Version.h6
-rw-r--r--dev/LibCompiler/XCOFF.h48
-rw-r--r--dev/LibCompiler/src/Assembler32x0.cc17
-rw-r--r--dev/LibCompiler/src/Assembler64x0.cc1724
-rw-r--r--dev/LibCompiler/src/AssemblerAMD64.cc2337
-rw-r--r--dev/LibCompiler/src/AssemblerARM64.cc1011
-rw-r--r--dev/LibCompiler/src/AssemblerPower.cc1724
-rw-r--r--dev/LibCompiler/src/AssemblyFactory.cc62
-rw-r--r--dev/LibCompiler/src/CCompiler64x0.cc2547
-rw-r--r--dev/LibCompiler/src/CCompilerARM64.cc2549
-rw-r--r--dev/LibCompiler/src/CCompilerPower64.cc2596
-rw-r--r--dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc1854
-rw-r--r--dev/LibCompiler/src/CPlusPlusCompilerPreProcessor.cc1744
-rw-r--r--dev/LibCompiler/src/Detail/AsmUtils.h176
-rw-r--r--dev/LibCompiler/src/Detail/ClUtils.h2
-rw-r--r--dev/LibCompiler/src/DynamicLinkerPEF.cc1315
-rw-r--r--dev/LibCompiler/src/StringView.cc413
-rw-r--r--dev/LibDebugger/DebuggerContract.h77
-rw-r--r--dev/LibDebugger/NeKernelContract.h86
-rw-r--r--dev/LibDebugger/POSIXMachContract.h203
-rw-r--r--dev/LibDebugger/src/POSIXMachContract.cc168
-rw-r--r--dev/Vendor/Dialogs.h3287
-rw-r--r--tests/example.cc19
-rw-r--r--tools/asm.cc155
-rw-r--r--tools/cppdrv.cc19
-rw-r--r--tools/cxxdrv.cc100
-rw-r--r--tools/dbg.cc7
-rw-r--r--tools/kdbg.cc7
-rw-r--r--tools/ld64.cc14
55 files changed, 14079 insertions, 17384 deletions
diff --git a/.clang-format b/.clang-format
index fb3cacb..3943f55 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1,16 +1,29 @@
----
-BasedOnStyle: Microsoft
-AccessModifierOffset: '-4'
-AlignAfterOpenBracket: Align
-AlignConsecutiveMacros: 'true'
-AlignConsecutiveAssignments: 'true'
-AlignConsecutiveDeclarations: 'true'
-BinPackParameters: 'false'
-ColumnLimit: '0'
-Language: Cpp
-NamespaceIndentation: All
+BasedOnStyle: Google
+IndentWidth: 2
+TabWidth: 2
+UseTab: Never
+ColumnLimit: 100
+DerivePointerAlignment: false
PointerAlignment: Left
-ReflowComments: 'true'
-SortIncludes: 'false'
-UseTab: Always
-...
+AllowShortFunctionsOnASingleLine: Inline
+AllowShortIfStatementsOnASingleLine: true
+AllowShortLoopsOnASingleLine: true
+SortIncludes: true
+IncludeBlocks: Preserve
+SpaceAfterCStyleCast: true
+SpaceBeforeParens: ControlStatements
+SpacesInAngles: false
+SpacesInContainerLiterals: true
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+BreakBeforeBraces: Attach
+ConstructorInitializerAllOnOneLineOrOnePerLine: true
+Cpp11BracedListStyle: true
+NamespaceIndentation: Inner
+ReflowComments: true
+AlignConsecutiveAssignments: true
+AlignConsecutiveDeclarations: true
+AlignTrailingComments: true
+FixNamespaceComments: true
+IncludeIsMainRegex: '(Test)?$'
+SortUsingDeclarations: true
diff --git a/dev/LibC++/base_alloc.h b/dev/LibC++/base_alloc.h
index b12fd0a..af5693b 100644
--- a/dev/LibC++/base_alloc.h
+++ b/dev/LibC++/base_alloc.h
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved.
+ Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved.
------------------------------------------- */
@@ -8,42 +8,36 @@
#include <LibC++/defines.h>
-namespace std::base_alloc
-{
- /// @brief allocate a new class.
- /// @tparam KindClass the class type to allocate.
- template <typename KindClass, typename... Args>
- inline KindClass* allocate(Args&&... args)
- {
- return new KindClass(forward(args)...);
- }
-
- /// @brief allocate a new class.
- /// @note aborts on error.
- /// @tparam KindClass the class type to allocate.
- template <typename KindClass, typename... Args>
- inline KindClass* allocate_nothrow(Args&&... args) noexcept
- {
- return allocate(forward(args)...);
- }
-
- /// @brief free a class.
- /// @tparam KindClass the class type to allocate.
- template <typename KindClass>
- inline void release(KindClass ptr)
- {
- if (!ptr)
- return;
-
- delete ptr;
- }
-
- /// @brief destroy and free a class.
- /// @note aborts on error.
- /// @tparam KindClass the class type to allocate.
- template <typename KindClass>
- inline void release_nothrow(KindClass ptr) noexcept
- {
- release(ptr);
- }
-} // namespace std::base_alloc
+namespace std::base_alloc {
+/// @brief allocate a new class.
+/// @tparam KindClass the class type to allocate.
+template <typename KindClass, typename... Args>
+inline KindClass* allocate(Args&&... args) {
+ return new KindClass(forward(args)...);
+}
+
+/// @brief allocate a new class.
+/// @note aborts on error.
+/// @tparam KindClass the class type to allocate.
+template <typename KindClass, typename... Args>
+inline KindClass* allocate_nothrow(Args&&... args) noexcept {
+ return allocate(forward(args)...);
+}
+
+/// @brief free a class.
+/// @tparam KindClass the class type to allocate.
+template <typename KindClass>
+inline void release(KindClass ptr) {
+ if (!ptr) return;
+
+ delete ptr;
+}
+
+/// @brief destroy and free a class.
+/// @note aborts on error.
+/// @tparam KindClass the class type to allocate.
+template <typename KindClass>
+inline void release_nothrow(KindClass ptr) noexcept {
+ release(ptr);
+}
+} // namespace std::base_alloc
diff --git a/dev/LibC++/base_exception.h b/dev/LibC++/base_exception.h
index 30ec466..314ac12 100644
--- a/dev/LibC++/base_exception.h
+++ b/dev/LibC++/base_exception.h
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved.
+ Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved.
------------------------------------------- */
@@ -9,22 +9,18 @@
#include <LibC++/defines.h>
#include <LibC++/process_base.h>
-namespace std::base_exception
-{
- inline void __throw_general(void)
- {
- exit(33);
- }
+namespace std::base_exception {
+inline void __throw_general(void) {
+ exit(33);
+}
- inline void __throw_domain_error(const char* error)
- {
- __throw_general();
- __builtin_unreachable(); // prevent from continuing.
- }
+inline void __throw_domain_error(const char* error) {
+ __throw_general();
+ __builtin_unreachable(); // prevent from continuing.
+}
- inline void __throw_bad_array_new_length(void)
- {
- __throw_general();
- __builtin_unreachable(); // prevent from continuing.
- }
-} // namespace std::base_exception
+inline void __throw_bad_array_new_length(void) {
+ __throw_general();
+ __builtin_unreachable(); // prevent from continuing.
+}
+} // namespace std::base_exception
diff --git a/dev/LibC++/base_math.h b/dev/LibC++/base_math.h
index ed1728e..ca6aace 100644
--- a/dev/LibC++/base_math.h
+++ b/dev/LibC++/base_math.h
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved.
+ Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved.
------------------------------------------- */
@@ -17,46 +17,38 @@ typedef double real_type;
typedef float real_type;
#endif
-namespace std::base_math
-{
- /// @brief Power function, with Repeat argument.
- template <size_t Exponent>
- inline real_type pow(real_type in)
- {
- if (Exponent == 0)
- return 1; // Any number to the power of 0 is 1.
-
- if (Exponent == 1)
- return in; // Any number to the power of 1 is itself.
-
- size_t cnt = Exponent;
-
- real_type result = 1;
-
- for (auto i = 0; i < cnt; ++i)
- result *= in;
-
- return result;
- }
-
- /// @brief Square of function, with Base template argument.
- /// @param of Base argument to find sqquare of
- template <size_t Base>
- inline real_type sqr(real_type in)
- {
- if (in == 0)
- return 0;
-
- return pow<1 / Base>(in);
- }
-
- /// @brief Linear interpolation equation solver.
- /// @param from where?
- /// @param to to?
- /// @param Updated diff value according to difference.
- inline real_type lerp(real_type to, real_type from, real_type stat)
- {
- real_type diff = (to - from);
- return from + (diff * stat);
- }
-} // namespace std::base_math
+namespace std::base_math {
+/// @brief Power function, with Repeat argument.
+template <size_t Exponent>
+inline real_type pow(real_type in) {
+ if (Exponent == 0) return 1; // Any number to the power of 0 is 1.
+
+ if (Exponent == 1) return in; // Any number to the power of 1 is itself.
+
+ size_t cnt = Exponent;
+
+ real_type result = 1;
+
+ for (auto i = 0; i < cnt; ++i) result *= in;
+
+ return result;
+}
+
+/// @brief Square of function, with Base template argument.
+/// @param of Base argument to find sqquare of
+template <size_t Base>
+inline real_type sqr(real_type in) {
+ if (in == 0) return 0;
+
+ return pow<1 / Base>(in);
+}
+
+/// @brief Linear interpolation equation solver.
+/// @param from where?
+/// @param to to?
+/// @param Updated diff value according to difference.
+inline real_type lerp(real_type to, real_type from, real_type stat) {
+ real_type diff = (to - from);
+ return from + (diff * stat);
+}
+} // namespace std::base_math
diff --git a/dev/LibC++/base_process.h b/dev/LibC++/base_process.h
index 7008b86..757e592 100644
--- a/dev/LibC++/base_process.h
+++ b/dev/LibC++/base_process.h
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved.
+ Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved.
------------------------------------------- */
@@ -12,11 +12,9 @@
extern "C" int exit(int code);
/// @brief Standard C++ namespace
-namespace std::base_process
-{
- inline int exit(int code)
- {
- exit(code);
- return -1;
- }
-} // namespace std::base_process
+namespace std::base_process {
+inline int exit(int code) {
+ exit(code);
+ return -1;
+}
+} // namespace std::base_process
diff --git a/dev/LibC++/defines.h b/dev/LibC++/defines.h
index 43cefb9..c0459ac 100644
--- a/dev/LibC++/defines.h
+++ b/dev/LibC++/defines.h
@@ -1,16 +1,15 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved.
+ Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved.
------------------------------------------- */
#ifndef __LIBCOMPILER_DEFINES_H__
#define __LIBCOMPILER_DEFINES_H__
-extern "C"
-{
-#include <stdint.h>
+extern "C" {
#include <stddef.h>
+#include <stdint.h>
}
#ifndef __GNUC__
@@ -21,9 +20,9 @@ typedef __SIZE_TYPE__ size_t;
typedef long int ssize_t;
#else
typedef int ssize_t;
-#endif // __LP64__
+#endif // __LP64__
-typedef void* ptr_type;
+typedef void* ptr_type;
typedef __SIZE_TYPE__ size_type;
typedef size_t ptrdiff_t;
@@ -33,8 +32,8 @@ typedef void* any_t;
typedef char* caddr_t;
#ifndef NULL
-#define NULL ((voidptr_t)0)
-#endif // !null
+#define NULL ((voidptr_t) 0)
+#endif // !null
#ifdef __GNUC__
#include <LibC++/alloca.h>
@@ -45,12 +44,10 @@ typedef char* caddr_t;
#define __deref(ptr) (*(ptr))
#ifdef __cplusplus
-#define __init_decl() \
- extern "C" \
- {
+#define __init_decl() extern "C" {
#define __fini_decl() \
- } \
- ;
+ } \
+ ;
#else
#define __init_decl()
#define __fini_decl()
@@ -66,31 +63,29 @@ typedef char* caddr_t;
#warning ! alloca not detected !
#endif
-typedef long long off_t;
+typedef long long off_t;
typedef unsigned long long uoff_t;
typedef union float_cast {
- struct
- {
- unsigned int mantissa : 23;
- unsigned int exponent : 8;
- unsigned int sign : 1;
- };
-
- float f;
+ struct {
+ unsigned int mantissa : 23;
+ unsigned int exponent : 8;
+ unsigned int sign : 1;
+ };
+
+ float f;
} __attribute__((packed)) float_cast_t;
typedef union double_cast {
- struct
- {
- unsigned long long int mantissa : 52;
- unsigned int exponent : 11;
- unsigned int sign : 1;
- };
-
- double f;
+ struct {
+ unsigned long long int mantissa : 52;
+ unsigned int exponent : 11;
+ unsigned int sign : 1;
+ };
+
+ double f;
} __attribute__((packed)) double_cast_t;
-#endif // ifndef __GNUC__
+#endif // ifndef __GNUC__
#endif /* __LIBCOMPILER_DEFINES_H__ */
diff --git a/dev/LibC++/filesystem.h b/dev/LibC++/filesystem.h
index b97bb1f..254bfab 100644
--- a/dev/LibC++/filesystem.h
+++ b/dev/LibC++/filesystem.h
@@ -1,18 +1,17 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved.
+ Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved.
------------------------------------------- */
#ifndef __LIBCOMPILER_FS_H__
#define __LIBCOMPILER_FS_H__
-namespace std
-{
- class path;
- class filesystem_error;
- class directory_entry;
- class directory_iterator;
-} // namespace std
+namespace std {
+class path;
+class filesystem_error;
+class directory_entry;
+class directory_iterator;
+} // namespace std
-#endif // __LIBCOMPILER_FS_H__ \ No newline at end of file
+#endif // __LIBCOMPILER_FS_H__ \ No newline at end of file
diff --git a/dev/LibC++/lc_runtime+unreachable.cc b/dev/LibC++/lc_runtime+unreachable.cc
index 125584e..2aaa3c1 100644
--- a/dev/LibC++/lc_runtime+unreachable.cc
+++ b/dev/LibC++/lc_runtime+unreachable.cc
@@ -1,13 +1,11 @@
/* -------------------------------------------
- \
+ \
Copyright (C) 2025 Amlal El Mahrouss, all rights reserved. \
- \
+ \
------------------------------------------- */
#include <LibC++/lc_runtime.h>
-extern "C" void __libcompiler_unreachable(void)
-{
- while (true)
- ;
+extern "C" void __libcompiler_unreachable(void) {
+ while (true);
} \ No newline at end of file
diff --git a/dev/LibC++/lc_runtime.h b/dev/LibC++/lc_runtime.h
index 0b58a58..d3d331f 100644
--- a/dev/LibC++/lc_runtime.h
+++ b/dev/LibC++/lc_runtime.h
@@ -1,7 +1,7 @@
/* -------------------------------------------
- \
+ \
Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved. \
- \
+ \
------------------------------------------- */
#pragma once
diff --git a/dev/LibC++/utility.h b/dev/LibC++/utility.h
index 1b1b932..4f1d2d7 100644
--- a/dev/LibC++/utility.h
+++ b/dev/LibC++/utility.h
@@ -1,33 +1,30 @@
/* -------------------------------------------
- \
+ \
Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved. \
- \
+ \
------------------------------------------- */
#ifndef LIBCXX_UTILITY_H
#define LIBCXX_UTILITY_H
-namespace std
-{
- /// @brief Forward object.
- /// @tparam Args the object type.
- /// @param arg the object.
- /// @return object's rvalue
- template <typename Args>
- inline Args&& forward(Args& arg)
- {
- return static_cast<Args&&>(arg);
- }
+namespace std {
+/// @brief Forward object.
+/// @tparam Args the object type.
+/// @param arg the object.
+/// @return object's rvalue
+template <typename Args>
+inline Args&& forward(Args& arg) {
+ return static_cast<Args&&>(arg);
+}
- /// @brief Move object.
- /// @tparam Args the object type.
- /// @param arg the object.
- /// @return object's rvalue
- template <typename Args>
- inline Args&& move(Args&& arg)
- {
- return static_cast<Args&&>(arg);
- }
-} // namespace std
+/// @brief Move object.
+/// @tparam Args the object type.
+/// @param arg the object.
+/// @return object's rvalue
+template <typename Args>
+inline Args&& move(Args&& arg) {
+ return static_cast<Args&&>(arg);
+}
+} // namespace std
-#endif // LIBCXX_UTILITY_H
+#endif // LIBCXX_UTILITY_H
diff --git a/dev/LibCompiler/AE.h b/dev/LibCompiler/AE.h
index fdf42a5..6e5f97f 100644
--- a/dev/LibCompiler/AE.h
+++ b/dev/LibCompiler/AE.h
@@ -15,128 +15,113 @@
#define kAEMag1 'E'
#define kAESymbolLen (255)
-#define kAEPad (8)
-#define kAEMagLen (2)
-#define kAENullType (0x00)
+#define kAEPad (8)
+#define kAEMagLen (2)
+#define kAENullType (0x00)
// Advanced Executable File Format for ld64.
// Reloctable by offset is the default strategy.
// You can also relocate at runtime but that's up to the operating system loader.
-namespace LibCompiler
-{
- // @brief Advanced Executable Header
- // One thing to keep in mind.
- // This object format, is reloctable.
- typedef struct AEHeader final
- {
- CharType fMagic[kAEMagLen];
- CharType fArch;
- CharType fSubArch;
- SizeType fCount;
- CharType fSize;
- SizeType fStartCode;
- SizeType fCodeSize;
- CharType fPad[kAEPad];
- } PACKED AEHeader, *AEHeaderPtr;
-
- // @brief Advanced Executable Record.
- // Could be data, code or bss.
- // fKind must be filled with PEF fields.
-
- typedef struct AERecordHeader final
- {
- CharType fName[kAESymbolLen];
- SizeType fKind;
- SizeType fSize;
- SizeType fFlags;
- UIntPtr fOffset;
- CharType fPad[kAEPad];
- } PACKED AERecordHeader, *AERecordHeaderPtr;
-
- enum
- {
- kKindRelocationByOffset = 0x23f,
- kKindRelocationAtRuntime = 0x34f,
- };
-} // namespace LibCompiler
+namespace LibCompiler {
+// @brief Advanced Executable Header
+// One thing to keep in mind.
+// This object format, is reloctable.
+typedef struct AEHeader final {
+ CharType fMagic[kAEMagLen];
+ CharType fArch;
+ CharType fSubArch;
+ SizeType fCount;
+ CharType fSize;
+ SizeType fStartCode;
+ SizeType fCodeSize;
+ CharType fPad[kAEPad];
+} PACKED AEHeader, *AEHeaderPtr;
+
+// @brief Advanced Executable Record.
+// Could be data, code or bss.
+// fKind must be filled with PEF fields.
+
+typedef struct AERecordHeader final {
+ CharType fName[kAESymbolLen];
+ SizeType fKind;
+ SizeType fSize;
+ SizeType fFlags;
+ UIntPtr fOffset;
+ CharType fPad[kAEPad];
+} PACKED AERecordHeader, *AERecordHeaderPtr;
+
+enum {
+ kKindRelocationByOffset = 0x23f,
+ kKindRelocationAtRuntime = 0x34f,
+};
+} // namespace LibCompiler
// provide operator<< for AE
-inline std::ofstream& operator<<(std::ofstream& fp, LibCompiler::AEHeader& container)
-{
- fp.write((char*)&container, sizeof(LibCompiler::AEHeader));
+inline std::ofstream& operator<<(std::ofstream& fp, LibCompiler::AEHeader& container) {
+ fp.write((char*) &container, sizeof(LibCompiler::AEHeader));
- return fp;
+ return fp;
}
-inline std::ofstream& operator<<(std::ofstream& fp,
- LibCompiler::AERecordHeader& container)
-{
- fp.write((char*)&container, sizeof(LibCompiler::AERecordHeader));
+inline std::ofstream& operator<<(std::ofstream& fp, LibCompiler::AERecordHeader& container) {
+ fp.write((char*) &container, sizeof(LibCompiler::AERecordHeader));
- return fp;
+ return fp;
}
-inline std::ifstream& operator>>(std::ifstream& fp, LibCompiler::AEHeader& container)
-{
- fp.read((char*)&container, sizeof(LibCompiler::AEHeader));
- return fp;
+inline std::ifstream& operator>>(std::ifstream& fp, LibCompiler::AEHeader& container) {
+ fp.read((char*) &container, sizeof(LibCompiler::AEHeader));
+ return fp;
}
-inline std::ifstream& operator>>(std::ifstream& fp,
- LibCompiler::AERecordHeader& container)
-{
- fp.read((char*)&container, sizeof(LibCompiler::AERecordHeader));
- return fp;
+inline std::ifstream& operator>>(std::ifstream& fp, LibCompiler::AERecordHeader& container) {
+ fp.read((char*) &container, sizeof(LibCompiler::AERecordHeader));
+ return fp;
}
-namespace LibCompiler::Utils
-{
- /**
- * @brief AE Reader protocol
- *
- */
- class AEReadableProtocol final
- {
- public:
- std::ifstream FP;
-
- public:
- explicit AEReadableProtocol() = default;
- ~AEReadableProtocol() = default;
-
- LIBCOMPILER_COPY_DELETE(AEReadableProtocol);
-
- /**
- * @brief Read AE Record headers.
- *
- * @param raw the containing buffer
- * @param sz it's size (1 = one AERecordHeader, 2 two AERecordHeader(s))
- * @return AERecordHeaderPtr
- */
- AERecordHeaderPtr Read(char* raw, std::size_t sz)
- {
- if (!raw)
- return nullptr;
-
- return this->_Read<AERecordHeader>(raw, sz * sizeof(AERecordHeader));
- }
-
- private:
- /**
- * @brief Implementation of Read for raw classes.
- *
- * @tparam TypeClass The class to read.
- * @param raw the buffer
- * @param sz the size
- * @return TypeClass* the returning class.
- */
- template <typename TypeClass>
- TypeClass* _Read(char* raw, std::size_t sz)
- {
- FP.read(raw, std::streamsize(sz));
- return reinterpret_cast<TypeClass*>(raw);
- }
- };
-} // namespace LibCompiler::Utils
+namespace LibCompiler::Utils {
+/**
+ * @brief AE Reader protocol
+ *
+ */
+class AEReadableProtocol final {
+ public:
+ std::ifstream FP;
+
+ public:
+ explicit AEReadableProtocol() = default;
+ ~AEReadableProtocol() = default;
+
+ LIBCOMPILER_COPY_DELETE(AEReadableProtocol);
+
+ /**
+ * @brief Read AE Record headers.
+ *
+ * @param raw the containing buffer
+ * @param sz it's size (1 = one AERecordHeader, 2 two AERecordHeader(s))
+ * @return AERecordHeaderPtr
+ */
+ AERecordHeaderPtr Read(char* raw, std::size_t sz) {
+ if (!raw) return nullptr;
+
+ return this->_Read<AERecordHeader>(raw, sz * sizeof(AERecordHeader));
+ }
+
+ private:
+ /**
+ * @brief Implementation of Read for raw classes.
+ *
+ * @tparam TypeClass The class to read.
+ * @param raw the buffer
+ * @param sz the size
+ * @return TypeClass* the returning class.
+ */
+ template <typename TypeClass>
+ TypeClass* _Read(char* raw, std::size_t sz) {
+ FP.read(raw, std::streamsize(sz));
+ return reinterpret_cast<TypeClass*>(raw);
+ }
+};
+} // namespace LibCompiler::Utils
diff --git a/dev/LibCompiler/AssemblyInterface.h b/dev/LibCompiler/AssemblyInterface.h
index 622e2ff..aebd01f 100644
--- a/dev/LibCompiler/AssemblyInterface.h
+++ b/dev/LibCompiler/AssemblyInterface.h
@@ -1,242 +1,198 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
+ Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
------------------------------------------- */
#pragma once
-#include <LibCompiler/Macros.h>
#include <LibCompiler/Defines.h>
+#include <LibCompiler/Macros.h>
#include <LibCompiler/StringView.h>
#define ASSEMBLY_INTERFACE : public LibCompiler::AssemblyInterface
-namespace LibCompiler
-{
- /// @brief Assembly to binary generator class.
- /// @note This interface creates according to the CPU target of the child class.
- class AssemblyInterface
- {
- public:
- explicit AssemblyInterface() = default;
- virtual ~AssemblyInterface() = default;
-
- LIBCOMPILER_COPY_DEFAULT(AssemblyInterface);
-
- /// @brief compile to object file.
- /// @note Example C++ -> MASM -> AE object.
- virtual Int32 CompileToFormat(std::string& src, Int32 arch) = 0;
- };
-
- /// @brief Simple assembly factory
- class AssemblyFactory final
- {
- public:
- explicit AssemblyFactory() = default;
- ~AssemblyFactory() = default;
-
- LIBCOMPILER_COPY_DEFAULT(AssemblyFactory);
-
- public:
- enum
- {
- kArchAMD64,
- kArch32x0,
- kArch64x0,
- kArchRISCV,
- kArchPowerPC,
- kArchAARCH64,
- kArchUnknown,
- };
-
- Int32 Compile(std::string& sourceFile, const Int32& arch) noexcept;
-
- void Mount(AssemblyInterface* mountPtr) noexcept;
- AssemblyInterface* Unmount() noexcept;
-
- private:
- AssemblyInterface* fMounted{nullptr};
- };
-
- union NumberCastBase {
- NumberCastBase() = default;
- ~NumberCastBase() = default;
- };
-
- union NumberCast64 final {
- NumberCast64() = default;
- explicit NumberCast64(UInt64 raw)
- : raw(raw)
- {
- }
-
- ~NumberCast64()
- {
- raw = 0;
- }
-
- CharType number[8];
- UInt64 raw;
- };
-
- union NumberCast32 final {
- NumberCast32() = default;
- explicit NumberCast32(UInt32 raw)
- : raw(raw)
- {
- }
-
- ~NumberCast32()
- {
- raw = 0;
- }
-
- CharType number[4];
- UInt32 raw;
- };
-
- union NumberCast16 final {
- NumberCast16() = default;
- explicit NumberCast16(UInt16 raw)
- : raw(raw)
- {
- }
-
- ~NumberCast16()
- {
- raw = 0;
- }
-
- CharType number[2];
- UInt16 raw;
- };
-
- union NumberCast8 final {
- NumberCast8() = default;
- explicit NumberCast8(UInt8 raw)
- : raw(raw)
- {
- }
-
- ~NumberCast8()
- {
- raw = 0;
- }
-
- CharType number;
- UInt8 raw;
- };
-
- class EncoderInterface
- {
- public:
- explicit EncoderInterface() = default;
- virtual ~EncoderInterface() = default;
-
- LIBCOMPILER_COPY_DEFAULT(EncoderInterface);
-
- virtual std::string CheckLine(std::string& line, const std::string& file) = 0;
- virtual bool WriteLine(std::string& line, const std::string& file) = 0;
- virtual bool WriteNumber(const std::size_t& pos, std::string& from_what) = 0;
- };
+namespace LibCompiler {
+/// @brief Assembly to binary generator class.
+/// @note This interface creates according to the CPU target of the child class.
+class AssemblyInterface {
+ public:
+ explicit AssemblyInterface() = default;
+ virtual ~AssemblyInterface() = default;
+
+ LIBCOMPILER_COPY_DEFAULT(AssemblyInterface);
+
+ /// @brief compile to object file.
+ /// @note Example C++ -> MASM -> AE object.
+ virtual Int32 CompileToFormat(std::string& src, Int32 arch) = 0;
+};
+
+/// @brief Simple assembly factory
+class AssemblyFactory final {
+ public:
+ explicit AssemblyFactory() = default;
+ ~AssemblyFactory() = default;
+
+ LIBCOMPILER_COPY_DEFAULT(AssemblyFactory);
+
+ public:
+ enum {
+ kArchAMD64,
+ kArch32x0,
+ kArch64x0,
+ kArchRISCV,
+ kArchPowerPC,
+ kArchAARCH64,
+ kArchUnknown,
+ };
+
+ Int32 Compile(std::string& sourceFile, const Int32& arch) noexcept;
+
+ void Mount(AssemblyInterface* mountPtr) noexcept;
+ AssemblyInterface* Unmount() noexcept;
+
+ private:
+ AssemblyInterface* fMounted{nullptr};
+};
+
+union NumberCastBase {
+ NumberCastBase() = default;
+ ~NumberCastBase() = default;
+};
+
+union NumberCast64 final {
+ NumberCast64() = default;
+ explicit NumberCast64(UInt64 raw) : raw(raw) {}
+
+ ~NumberCast64() { raw = 0; }
+
+ CharType number[8];
+ UInt64 raw;
+};
+
+union NumberCast32 final {
+ NumberCast32() = default;
+ explicit NumberCast32(UInt32 raw) : raw(raw) {}
+
+ ~NumberCast32() { raw = 0; }
+
+ CharType number[4];
+ UInt32 raw;
+};
+
+union NumberCast16 final {
+ NumberCast16() = default;
+ explicit NumberCast16(UInt16 raw) : raw(raw) {}
+
+ ~NumberCast16() { raw = 0; }
+
+ CharType number[2];
+ UInt16 raw;
+};
+
+union NumberCast8 final {
+ NumberCast8() = default;
+ explicit NumberCast8(UInt8 raw) : raw(raw) {}
+
+ ~NumberCast8() { raw = 0; }
+
+ CharType number;
+ UInt8 raw;
+};
+
+class EncoderInterface {
+ public:
+ explicit EncoderInterface() = default;
+ virtual ~EncoderInterface() = default;
+
+ LIBCOMPILER_COPY_DEFAULT(EncoderInterface);
+
+ virtual std::string CheckLine(std::string& line, const std::string& file) = 0;
+ virtual bool WriteLine(std::string& line, const std::string& file) = 0;
+ virtual bool WriteNumber(const std::size_t& pos, std::string& from_what) = 0;
+};
#ifdef __ASM_NEED_AMD64__
- class EncoderAMD64 final : public EncoderInterface
- {
- public:
- explicit EncoderAMD64() = default;
- ~EncoderAMD64() override = default;
+class EncoderAMD64 final : public EncoderInterface {
+ public:
+ explicit EncoderAMD64() = default;
+ ~EncoderAMD64() override = default;
- LIBCOMPILER_COPY_DEFAULT(EncoderAMD64);
+ LIBCOMPILER_COPY_DEFAULT(EncoderAMD64);
- virtual std::string CheckLine(std::string& line,
- const std::string& file) override;
- virtual bool WriteLine(std::string& line, const std::string& file) override;
- virtual bool WriteNumber(const std::size_t& pos,
- std::string& from_what) override;
+ virtual std::string CheckLine(std::string& line, const std::string& file) override;
+ virtual bool WriteLine(std::string& line, const std::string& file) override;
+ virtual bool WriteNumber(const std::size_t& pos, std::string& from_what) override;
- virtual bool WriteNumber16(const std::size_t& pos, std::string& from_what);
- virtual bool WriteNumber32(const std::size_t& pos, std::string& from_what);
- virtual bool WriteNumber8(const std::size_t& pos, std::string& from_what);
- };
+ virtual bool WriteNumber16(const std::size_t& pos, std::string& from_what);
+ virtual bool WriteNumber32(const std::size_t& pos, std::string& from_what);
+ virtual bool WriteNumber8(const std::size_t& pos, std::string& from_what);
+};
-#endif // __ASM_NEED_AMD64__
+#endif // __ASM_NEED_AMD64__
#ifdef __ASM_NEED_ARM64__
- class EncoderARM64 final : public EncoderInterface
- {
- public:
- explicit EncoderARM64() = default;
- ~EncoderARM64() override = default;
+class EncoderARM64 final : public EncoderInterface {
+ public:
+ explicit EncoderARM64() = default;
+ ~EncoderARM64() override = default;
- LIBCOMPILER_COPY_DEFAULT(EncoderARM64);
+ LIBCOMPILER_COPY_DEFAULT(EncoderARM64);
- virtual std::string CheckLine(std::string& line,
- const std::string& file) override;
- virtual bool WriteLine(std::string& line, const std::string& file) override;
- virtual bool WriteNumber(const std::size_t& pos,
- std::string& from_what) override;
- };
+ virtual std::string CheckLine(std::string& line, const std::string& file) override;
+ virtual bool WriteLine(std::string& line, const std::string& file) override;
+ virtual bool WriteNumber(const std::size_t& pos, std::string& from_what) override;
+};
-#endif // __ASM_NEED_ARM64__
+#endif // __ASM_NEED_ARM64__
#ifdef __ASM_NEED_64x0__
- class Encoder64x0 final : public EncoderInterface
- {
- public:
- explicit Encoder64x0() = default;
- ~Encoder64x0() override = default;
+class Encoder64x0 final : public EncoderInterface {
+ public:
+ explicit Encoder64x0() = default;
+ ~Encoder64x0() override = default;
- LIBCOMPILER_COPY_DEFAULT(Encoder64x0);
+ LIBCOMPILER_COPY_DEFAULT(Encoder64x0);
- virtual std::string CheckLine(std::string& line,
- const std::string& file) override;
- virtual bool WriteLine(std::string& line, const std::string& file) override;
- virtual bool WriteNumber(const std::size_t& pos,
- std::string& from_what) override;
- };
+ virtual std::string CheckLine(std::string& line, const std::string& file) override;
+ virtual bool WriteLine(std::string& line, const std::string& file) override;
+ virtual bool WriteNumber(const std::size_t& pos, std::string& from_what) override;
+};
-#endif // __ASM_NEED_64x0__
+#endif // __ASM_NEED_64x0__
#ifdef __ASM_NEED_32x0__
- class Encoder32x0 final : public EncoderInterface
- {
- public:
- explicit Encoder32x0() = default;
- ~Encoder32x0() override = default;
+class Encoder32x0 final : public EncoderInterface {
+ public:
+ explicit Encoder32x0() = default;
+ ~Encoder32x0() override = default;
- LIBCOMPILER_COPY_DEFAULT(Encoder32x0);
+ LIBCOMPILER_COPY_DEFAULT(Encoder32x0);
- virtual std::string CheckLine(std::string& line,
- const std::string& file) override;
- virtual bool WriteLine(std::string& line, const std::string& file) override;
- virtual bool WriteNumber(const std::size_t& pos,
- std::string& from_what) override;
- };
+ virtual std::string CheckLine(std::string& line, const std::string& file) override;
+ virtual bool WriteLine(std::string& line, const std::string& file) override;
+ virtual bool WriteNumber(const std::size_t& pos, std::string& from_what) override;
+};
-#endif // __ASM_NEED_32x0__
+#endif // __ASM_NEED_32x0__
#ifdef __ASM_NEED_PPC__
- class EncoderPowerPC final : public EncoderInterface
- {
- public:
- explicit EncoderPowerPC() = default;
- ~EncoderPowerPC() override = default;
+class EncoderPowerPC final : public EncoderInterface {
+ public:
+ explicit EncoderPowerPC() = default;
+ ~EncoderPowerPC() override = default;
- LIBCOMPILER_COPY_DEFAULT(EncoderPowerPC);
+ LIBCOMPILER_COPY_DEFAULT(EncoderPowerPC);
- virtual std::string CheckLine(std::string& line,
- const std::string& file) override;
- virtual bool WriteLine(std::string& line, const std::string& file) override;
- virtual bool WriteNumber(const std::size_t& pos,
- std::string& from_what) override;
- };
+ virtual std::string CheckLine(std::string& line, const std::string& file) override;
+ virtual bool WriteLine(std::string& line, const std::string& file) override;
+ virtual bool WriteNumber(const std::size_t& pos, std::string& from_what) override;
+};
-#endif // __ASM_NEED_32x0__
-} // namespace LibCompiler
+#endif // __ASM_NEED_32x0__
+} // namespace LibCompiler
diff --git a/dev/LibCompiler/Backend/32x0.h b/dev/LibCompiler/Backend/32x0.h
index 32f31ff..bb0a5aa 100644
--- a/dev/LibCompiler/Backend/32x0.h
+++ b/dev/LibCompiler/Backend/32x0.h
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
+ Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
------------------------------------------- */
@@ -12,47 +12,43 @@
// @file Backend/32x0.hpp
#define kAsmOpcodeDecl(__NAME, __OPCODE, __FUNCT3, __FUNCT7) \
- {.fName = __NAME, \
- .fOpcode = __OPCODE, \
- .fFunct3 = __FUNCT3, \
- .fFunct7 = __FUNCT7},
+ {.fName = __NAME, .fOpcode = __OPCODE, .fFunct3 = __FUNCT3, .fFunct7 = __FUNCT7},
#define kAsmImmediate 0x01
-#define kAsmSyscall 0x02
-#define kAsmJump 0x03
-#define kAsmNoArgs 0x04
+#define kAsmSyscall 0x02
+#define kAsmJump 0x03
+#define kAsmNoArgs 0x04
-#define kAsmByte 0
+#define kAsmByte 0
#define kAsmHWord 1
-#define kAsmWord 2
-
-struct CpuCode32x0
-{
- const char fName[32];
- uint8_t fOpcode;
- uint8_t fSize;
- uint8_t fFunct3;
- uint8_t fFunct7;
+#define kAsmWord 2
+
+struct CpuCode32x0 {
+ const char fName[32];
+ uint8_t fOpcode;
+ uint8_t fSize;
+ uint8_t fFunct3;
+ uint8_t fFunct7;
};
#define kAsmDWordStr ".dword" /* 64 bit */
-#define kAsmWordStr ".word" /* 32-bit */
+#define kAsmWordStr ".word" /* 32-bit */
#define kAsmHWordStr ".half" /* 16-bit */
-#define kAsmByteStr ".byte" /* 8-bit */
+#define kAsmByteStr ".byte" /* 8-bit */
inline std::vector<CpuCode32x0> kOpcodes32x0 = {
- kAsmOpcodeDecl("nop", 0b0100011, 0b000, kAsmNoArgs) // nothing to do. (1C)
- kAsmOpcodeDecl("jmp", 0b1110011, 0b001, kAsmJump) // jump to branch (2C)
- kAsmOpcodeDecl("mov", 0b0100011, 0b101, kAsmImmediate) // move registers (3C)
- kAsmOpcodeDecl("psh", 0b0111011, 0b000, kAsmImmediate) // push to sp (2C)
- kAsmOpcodeDecl("pop", 0b0111011, 0b001, kAsmImmediate) // pop from sp. (1C)
- kAsmOpcodeDecl("lea", 0b0111011, 0b010,
- kAsmImmediate) // setup stack and call, store address to CR (1C).
- kAsmOpcodeDecl("ret", 0b0111011, 0b110,
- kAsmImmediate) // return from procedure (2C).
- kAsmOpcodeDecl("uc", 0b0111111, 0b000, kAsmSyscall) // user call (1C)
- kAsmOpcodeDecl("kc", 0b0111111, 0b001, kAsmSyscall) // kernel call (1C)
- kAsmOpcodeDecl("int", 0b0111111, 0b010, kAsmSyscall) // raise interrupt (1C)
+ kAsmOpcodeDecl("nop", 0b0100011, 0b000, kAsmNoArgs) // nothing to do. (1C)
+ kAsmOpcodeDecl("jmp", 0b1110011, 0b001, kAsmJump) // jump to branch (2C)
+ kAsmOpcodeDecl("mov", 0b0100011, 0b101, kAsmImmediate) // move registers (3C)
+ kAsmOpcodeDecl("psh", 0b0111011, 0b000, kAsmImmediate) // push to sp (2C)
+ kAsmOpcodeDecl("pop", 0b0111011, 0b001, kAsmImmediate) // pop from sp. (1C)
+ kAsmOpcodeDecl("lea", 0b0111011, 0b010,
+ kAsmImmediate) // setup stack and call, store address to CR (1C).
+ kAsmOpcodeDecl("ret", 0b0111011, 0b110,
+ kAsmImmediate) // return from procedure (2C).
+ kAsmOpcodeDecl("uc", 0b0111111, 0b000, kAsmSyscall) // user call (1C)
+ kAsmOpcodeDecl("kc", 0b0111111, 0b001, kAsmSyscall) // kernel call (1C)
+ kAsmOpcodeDecl("int", 0b0111111, 0b010, kAsmSyscall) // raise interrupt (1C)
};
// \brief 64x0 register prefix
@@ -61,10 +57,10 @@ inline std::vector<CpuCode32x0> kOpcodes32x0 = {
// r0 -> hw zero
#define kAsmRegisterPrefix "r"
-#define kAsmRegisterLimit 16
-#define kAsmPcRegister 17
-#define kAsmCrRegister 18
-#define kAsmSpRegister 5
+#define kAsmRegisterLimit 16
+#define kAsmPcRegister 17
+#define kAsmCrRegister 18
+#define kAsmSpRegister 5
/* return address register */
#define kAsmRetRegister 19
diff --git a/dev/LibCompiler/Backend/64x0.h b/dev/LibCompiler/Backend/64x0.h
index a0084b1..745dff0 100644
--- a/dev/LibCompiler/Backend/64x0.h
+++ b/dev/LibCompiler/Backend/64x0.h
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
+ Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
------------------------------------------- */
@@ -13,53 +13,48 @@
// @file Backend/64x0.hpp
#define kAsmOpcodeDecl(__NAME, __OPCODE, __FUNCT3, __FUNCT7) \
- {.fName = __NAME, \
- .fOpcode = __OPCODE, \
- .fFunct3 = __FUNCT3, \
- .fFunct7 = __FUNCT7},
+ {.fName = __NAME, .fOpcode = __OPCODE, .fFunct3 = __FUNCT3, .fFunct7 = __FUNCT7},
#define kAsmImmediate 0x01
-#define kAsmRegToReg 0x02
-#define kAsmSyscall 0x03
-#define kAsmJump 0x04
-#define kAsmNoArgs 0x00
+#define kAsmRegToReg 0x02
+#define kAsmSyscall 0x03
+#define kAsmJump 0x04
+#define kAsmNoArgs 0x00
-typedef char e64k_character_t;
+typedef char e64k_character_t;
typedef uint8_t e64k_num_t;
-struct CpuOpcode64x0
-{
- const e64k_character_t fName[32];
- e64k_num_t fOpcode;
- e64k_num_t fFunct3;
- e64k_num_t fFunct7;
+struct CpuOpcode64x0 {
+ const e64k_character_t fName[32];
+ e64k_num_t fOpcode;
+ e64k_num_t fFunct3;
+ e64k_num_t fFunct7;
};
inline std::vector<CpuOpcode64x0> kOpcodes64x0 = {
- kAsmOpcodeDecl("nop", 0b0000000, 0b0000000, kAsmNoArgs) // no-operation.
- kAsmOpcodeDecl("np", 0b0000000, 0b0000000, kAsmNoArgs) // no-operation.
- kAsmOpcodeDecl("jlr", 0b1110011, 0b0000111,
- kAsmJump) // jump to linked return register
- kAsmOpcodeDecl("jrl", 0b1110011, 0b0001111,
- kAsmJump) // jump from return register.
- kAsmOpcodeDecl("mv", 0b0100011, 0b101, kAsmRegToReg)
- kAsmOpcodeDecl("bg", 0b1100111, 0b111, kAsmRegToReg)
- kAsmOpcodeDecl("bl", 0b1100111, 0b011, kAsmRegToReg)
- kAsmOpcodeDecl("beq", 0b1100111, 0b000, kAsmRegToReg)
- kAsmOpcodeDecl("bne", 0b1100111, 0b001, kAsmRegToReg)
- kAsmOpcodeDecl("bge", 0b1100111, 0b101, kAsmRegToReg)
- kAsmOpcodeDecl("ble", 0b1100111, 0b100, kAsmRegToReg)
- kAsmOpcodeDecl("stw", 0b0001111, 0b100, kAsmImmediate)
- kAsmOpcodeDecl("ldw", 0b0001111, 0b100, kAsmImmediate)
- kAsmOpcodeDecl("lda", 0b0001111, 0b101, kAsmImmediate)
- kAsmOpcodeDecl("sta", 0b0001111, 0b001, kAsmImmediate)
- // add/sub without carry flag
- kAsmOpcodeDecl("add", 0b0101011, 0b100, kAsmImmediate)
- kAsmOpcodeDecl("sub", 0b0101011, 0b101, kAsmImmediate)
- // add/sub with carry flag
- kAsmOpcodeDecl("addc", 0b0101011, 0b110, kAsmImmediate)
- kAsmOpcodeDecl("subc", 0b0101011, 0b111, kAsmImmediate)
- kAsmOpcodeDecl("sc", 0b1110011, 0b00, kAsmSyscall)};
+ kAsmOpcodeDecl("nop", 0b0000000, 0b0000000, kAsmNoArgs) // no-operation.
+ kAsmOpcodeDecl("np", 0b0000000, 0b0000000, kAsmNoArgs) // no-operation.
+ kAsmOpcodeDecl("jlr", 0b1110011, 0b0000111,
+ kAsmJump) // jump to linked return register
+ kAsmOpcodeDecl("jrl", 0b1110011, 0b0001111,
+ kAsmJump) // jump from return register.
+ kAsmOpcodeDecl("mv", 0b0100011, 0b101, kAsmRegToReg) kAsmOpcodeDecl(
+ "bg", 0b1100111, 0b111, kAsmRegToReg) kAsmOpcodeDecl("bl", 0b1100111, 0b011, kAsmRegToReg)
+ kAsmOpcodeDecl("beq", 0b1100111, 0b000, kAsmRegToReg)
+ kAsmOpcodeDecl("bne", 0b1100111, 0b001, kAsmRegToReg)
+ kAsmOpcodeDecl("bge", 0b1100111, 0b101, kAsmRegToReg)
+ kAsmOpcodeDecl("ble", 0b1100111, 0b100, kAsmRegToReg)
+ kAsmOpcodeDecl("stw", 0b0001111, 0b100, kAsmImmediate)
+ kAsmOpcodeDecl("ldw", 0b0001111, 0b100, kAsmImmediate)
+ kAsmOpcodeDecl("lda", 0b0001111, 0b101, kAsmImmediate)
+ kAsmOpcodeDecl("sta", 0b0001111, 0b001, kAsmImmediate)
+ // add/sub without carry flag
+ kAsmOpcodeDecl("add", 0b0101011, 0b100, kAsmImmediate)
+ kAsmOpcodeDecl("sub", 0b0101011, 0b101, kAsmImmediate)
+ // add/sub with carry flag
+ kAsmOpcodeDecl("addc", 0b0101011, 0b110, kAsmImmediate)
+ kAsmOpcodeDecl("subc", 0b0101011, 0b111, kAsmImmediate)
+ kAsmOpcodeDecl("sc", 0b1110011, 0b00, kAsmSyscall)};
// \brief 64x0 register prefix
// example: r32, r0
@@ -67,13 +62,13 @@ inline std::vector<CpuOpcode64x0> kOpcodes64x0 = {
// r0 -> hw zero
#define kAsmFloatZeroRegister 0
-#define kAsmZeroRegister 0
+#define kAsmZeroRegister 0
#define kAsmRegisterPrefix "r"
-#define kAsmRegisterLimit 30
-#define kAsmPcRegister 17
-#define kAsmCrRegister 18
-#define kAsmSpRegister 5
+#define kAsmRegisterLimit 30
+#define kAsmPcRegister 17
+#define kAsmCrRegister 18
+#define kAsmSpRegister 5
/* return address register */
#define kAsmRetRegister 19
diff --git a/dev/LibCompiler/Backend/amd64.h b/dev/LibCompiler/Backend/amd64.h
index 8486b01..f42b131 100644
--- a/dev/LibCompiler/Backend/amd64.h
+++ b/dev/LibCompiler/Backend/amd64.h
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
+ Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
------------------------------------------- */
@@ -13,46 +13,36 @@
#define kAsmOpcodeDecl(__NAME, __OPCODE) {.fName = __NAME, .fOpcode = __OPCODE},
-typedef char i64_character_t;
-typedef uint8_t i64_byte_t;
+typedef char i64_character_t;
+typedef uint8_t i64_byte_t;
typedef uint16_t i64_hword_t;
typedef uint32_t i64_word_t;
#define kAsmRegisterPrefix "r"
-struct CpuOpcodeAMD64
-{
- std::string fName;
- i64_byte_t fPrefixBytes[4];
- i64_hword_t fOpcode;
- i64_hword_t fModReg;
- i64_word_t fDisplacment;
- i64_word_t fImmediate;
+struct CpuOpcodeAMD64 {
+ std::string fName;
+ i64_byte_t fPrefixBytes[4];
+ i64_hword_t fOpcode;
+ i64_hword_t fModReg;
+ i64_word_t fDisplacment;
+ i64_word_t fImmediate;
};
/// these two are edge cases
-#define kAsmIntOpcode 0xCC
+#define kAsmIntOpcode 0xCC
#define kasmIntOpcodeAlt 0xCD
-#define kAsmJumpOpcode 0x0F80
-#define kJumpLimit 30
-#define kJumpLimitStandard 0xE3
+#define kAsmJumpOpcode 0x0F80
+#define kJumpLimit 30
+#define kJumpLimitStandard 0xE3
#define kJumpLimitStandardLimit 0xEB
inline std::vector<CpuOpcodeAMD64> kOpcodesAMD64 = {
- kAsmOpcodeDecl("int", 0xCD)
- kAsmOpcodeDecl("into", 0xCE)
- kAsmOpcodeDecl("intd", 0xF1)
- kAsmOpcodeDecl("int3", 0xC3)
- kAsmOpcodeDecl("iret", 0xCF)
- kAsmOpcodeDecl("retf", 0xCB)
- kAsmOpcodeDecl("retn", 0xC3)
- kAsmOpcodeDecl("ret", 0xC3)
- kAsmOpcodeDecl("sti", 0xfb)
- kAsmOpcodeDecl("cli", 0xfa)
- kAsmOpcodeDecl("hlt", 0xf4)
- kAsmOpcodeDecl("nop", 0x90)
- kAsmOpcodeDecl("mov", 0x48)
- kAsmOpcodeDecl("call", 0xFF)};
+ kAsmOpcodeDecl("int", 0xCD) kAsmOpcodeDecl("into", 0xCE) kAsmOpcodeDecl("intd", 0xF1)
+ kAsmOpcodeDecl("int3", 0xC3) kAsmOpcodeDecl("iret", 0xCF) kAsmOpcodeDecl("retf", 0xCB)
+ kAsmOpcodeDecl("retn", 0xC3) kAsmOpcodeDecl("ret", 0xC3) kAsmOpcodeDecl("sti", 0xfb)
+ kAsmOpcodeDecl("cli", 0xfa) kAsmOpcodeDecl("hlt", 0xf4) kAsmOpcodeDecl("nop", 0x90)
+ kAsmOpcodeDecl("mov", 0x48) kAsmOpcodeDecl("call", 0xFF)};
#define kAsmRegisterLimit 16
diff --git a/dev/LibCompiler/Backend/arm64.h b/dev/LibCompiler/Backend/arm64.h
index 08096ee..fb91a1c 100644
--- a/dev/LibCompiler/Backend/arm64.h
+++ b/dev/LibCompiler/Backend/arm64.h
@@ -6,8 +6,8 @@ Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
#pragma once
-#include <stdint.h>
#include <LibCompiler/Defines.h>
+#include <stdint.h>
/// @brief ARM64 encoding support.
/// @file Backend/arm64.hpp
@@ -15,30 +15,27 @@ Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
struct CpuOpcodeArm64;
/// @brief ARM64 opcode header.
-struct PACKED CpuOpcodeArm64_Data final
-{
- uint32_t fOpcode : 10; // Bits 31–22: Opcode for operation
- uint32_t fRm : 5; // Bits 21–16: Source register Rm
- uint32_t fShamt : 6; // Bits 15–10: Shift amount
- uint32_t fRn : 5; // Bits 9–5: Source register Rn
- uint32_t fRd : 5; // Bits 4–0: Destination register Rd
+struct PACKED CpuOpcodeArm64_Data final {
+ uint32_t fOpcode : 10; // Bits 31–22: Opcode for operation
+ uint32_t fRm : 5; // Bits 21–16: Source register Rm
+ uint32_t fShamt : 6; // Bits 15–10: Shift amount
+ uint32_t fRn : 5; // Bits 9–5: Source register Rn
+ uint32_t fRd : 5; // Bits 4–0: Destination register Rd
};
-typedef struct
-{
- uint32_t opcode : 6; // Bits 31–26: Branch opcode
- int32_t offset : 26; // Bits 25–0: Signed offset (branch target)
+typedef struct {
+ uint32_t opcode : 6; // Bits 31–26: Branch opcode
+ int32_t offset : 26; // Bits 25–0: Signed offset (branch target)
} PACKED CpuOpcodeArm64_Branch;
-typedef struct
-{
- uint32_t size : 2; // Bits 31–30: Size of the data
- uint32_t opcode : 7; // Bits 29–23: Opcode for load/store
- uint32_t offset : 12; // Bits 22–10: Offset
- uint32_t rn : 5; // Bits 9–5: Base address register Rn
- uint32_t rt : 5; // Bits 4–0: Target/source register Rt
+typedef struct {
+ uint32_t size : 2; // Bits 31–30: Size of the data
+ uint32_t opcode : 7; // Bits 29–23: Opcode for load/store
+ uint32_t offset : 12; // Bits 22–10: Offset
+ uint32_t rn : 5; // Bits 9–5: Base address register Rn
+ uint32_t rt : 5; // Bits 4–0: Target/source register Rt
} PACKED CpuOpcodeArm64_LoadStore;
-#define kAsmRegisterLimit (30)
+#define kAsmRegisterLimit (30)
#define kAsmRegisterPrefix "x"
-#define kOpcodeARM64Count (1000)
+#define kOpcodeARM64Count (1000)
diff --git a/dev/LibCompiler/Backend/power64.h b/dev/LibCompiler/Backend/power64.h
index 0f797a5..03aea49 100644
--- a/dev/LibCompiler/Backend/power64.h
+++ b/dev/LibCompiler/Backend/power64.h
@@ -1,10 +1,10 @@
/* -------------------------------------------
- Some modifications are copyrighted under:
- Amlal El Mahrouss
+ Some modifications are copyrighted under:
+ Amlal El Mahrouss
- Original author:
- Apple Inc
+ Original author:
+ Apple Inc
------------------------------------------- */
@@ -22,1908 +22,1536 @@
* is zero it can execute on all cpus. The defines are or'ed together. This
* information is used to set the cpusubtype in the resulting object file.
*/
-#define CPU601 0x1
-#define IMPL64 0x2
-#define OPTIONAL 0x4
-#define VMX 0x8
-#define CPU970 0x10 /* added to OPTIONAL insts that the 970 has */
+#define CPU601 0x1
+#define IMPL64 0x2
+#define OPTIONAL 0x4
+#define VMX 0x8
+#define CPU970 0x10 /* added to OPTIONAL insts that the 970 has */
#define CPUMAHROUSS 0x12 /* optional mahrouss insts. */
-enum OpcodeType
-{
- NONE, /* no operand */
- JBSR, /* jbsr pseudo op */
- PCREL, /* PC relative (branch offset) */
- BADDR, /* Branch address (sign extended absolute address) */
- D, /* 16 bit displacement */
- DS, /* 14 bit displacement (double word) */
- SI, /* signed 16 bit immediate */
- UI, /* unsigned 16 bit immediate */
- HI, /* high 16 bit immediate (with truncation) */
- GREG, /* general register */
- G0REG, /* general register r1-r31 or 0 */
- FREG, /* float register */
- VREG, /* vector register */
- SGREG, /* segment register */
- SPREG, /* special register (or 10 bit number, 5 bit halves reversed) */
- BCND, /* branch condition opcode */
- CRF, /* condition register field */
- CRFONLY, /* condition register field only no expression allowed */
- sh, /* 6 bit number (0 - 63) (sh field, split and reversed) */
- mb, /* 6 bit number (0 - 63) (mb field, mb5 || mb0:4 reversed) */
- NUM, /* number */
- SNUM, /* signed number */
- NUM0, /* number (where 1<<width is the same as 0) */
- MBE, /* mask defined by MB and ME fields */
- FXM, /* 8-bit mask with only one bit set */
- ZERO /* the number zero */
+enum OpcodeType {
+ NONE, /* no operand */
+ JBSR, /* jbsr pseudo op */
+ PCREL, /* PC relative (branch offset) */
+ BADDR, /* Branch address (sign extended absolute address) */
+ D, /* 16 bit displacement */
+ DS, /* 14 bit displacement (double word) */
+ SI, /* signed 16 bit immediate */
+ UI, /* unsigned 16 bit immediate */
+ HI, /* high 16 bit immediate (with truncation) */
+ GREG, /* general register */
+ G0REG, /* general register r1-r31 or 0 */
+ FREG, /* float register */
+ VREG, /* vector register */
+ SGREG, /* segment register */
+ SPREG, /* special register (or 10 bit number, 5 bit halves reversed) */
+ BCND, /* branch condition opcode */
+ CRF, /* condition register field */
+ CRFONLY, /* condition register field only no expression allowed */
+ sh, /* 6 bit number (0 - 63) (sh field, split and reversed) */
+ mb, /* 6 bit number (0 - 63) (mb field, mb5 || mb0:4 reversed) */
+ NUM, /* number */
+ SNUM, /* signed number */
+ NUM0, /* number (where 1<<width is the same as 0) */
+ MBE, /* mask defined by MB and ME fields */
+ FXM, /* 8-bit mask with only one bit set */
+ ZERO /* the number zero */
};
-struct CpuOpcodePPC
-{
- struct OpcodeType final
- {
- uint32_t offset : 5;
- uint32_t width : 5;
- uint32_t type : 6;
- };
-
- uint32_t opcode;
- const char* name; // c++ wants the string to be const, it makes sense here.
- OpcodeType ops[5];
- uint32_t cpus;
+struct CpuOpcodePPC {
+ struct OpcodeType final {
+ uint32_t offset : 5;
+ uint32_t width : 5;
+ uint32_t type : 6;
+ };
+
+ uint32_t opcode;
+ const char* name; // c++ wants the string to be const, it makes sense here.
+ OpcodeType ops[5];
+ uint32_t cpus;
};
inline CpuOpcodePPC kOpcodesPowerPC[] = {
- {0x38000000, "addi", {{21, 5, GREG}, {16, 5, G0REG}, {0, 16, SI}}},
- {0x38000000, "li", {{21, 5, GREG}, {0, 16, SI}}},
- {0x3c000000, "addis", {{21, 5, GREG}, {16, 5, G0REG}, {0, 16, HI}}},
- {0x3c000000, "lis", {{21, 5, GREG}, {0, 16, HI}}},
- {0x30000000, "addic", {{21, 5, GREG}, {16, 5, GREG}, {0, 16, SI}}},
- {0x34000000, "addic.", {{21, 5, GREG}, {16, 5, GREG}, {0, 16, SI}}},
- {0x7c000214, "add", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000215, "add.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000614, "addo", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000615, "addo.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
-
- {0x7c000014, "addc", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000015, "addc.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000414, "addco", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000415, "addco.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
-
- {0x7c000114, "adde", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000115, "adde.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000514, "addeo", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000515, "addeo.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
-
- {0x7c0001d4, "addme", {{21, 5, GREG}, {16, 5, GREG}}},
- {0x7c0001d5, "addme.", {{21, 5, GREG}, {16, 5, GREG}}},
- {0x7c0005d4, "addmeo", {{21, 5, GREG}, {16, 5, GREG}}},
- {0x7c0005d5, "addmeo.", {{21, 5, GREG}, {16, 5, GREG}}},
-
- {0x7c000194, "addze", {{21, 5, GREG}, {16, 5, GREG}}},
- {0x7c000195, "addze.", {{21, 5, GREG}, {16, 5, GREG}}},
- {0x7c000594, "addzeo", {{21, 5, GREG}, {16, 5, GREG}}},
- {0x7c000595, "addzeo.", {{21, 5, GREG}, {16, 5, GREG}}},
-
- {0x70000000, "andi.", {{16, 5, GREG}, {21, 5, GREG}, {0, 16, UI}}},
- {0x74000000, "andis.", {{16, 5, GREG}, {21, 5, GREG}, {0, 16, UI}}},
- {0x7c000038, "and", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
- {0x7c000039, "and.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
-
- {0x7c000078, "andc", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
- {0x7c000079, "andc.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
-
- {0x48000000, "b", {{2, 24, PCREL}}},
- {0x48000002, "ba", {{2, 24, BADDR}}},
- {0x48000001, "bl", {{2, 24, PCREL}}},
- {0x48000003, "bla", {{2, 24, BADDR}}},
-
- {0x48000001, "jbsr", {{0, 0, JBSR}, {2, 24, PCREL}}},
- {0x48000000, "jmp", {{0, 0, JBSR}, {2, 24, PCREL}}},
-
- {0x40000000, "bc", {{21, 5, NUM}, {16, 5, NUM}, {2, 14, PCREL}}},
- {0x40000002, "bca", {{21, 5, NUM}, {16, 5, NUM}, {2, 14, BADDR}}},
- {0x40000001, "bcl", {{21, 5, NUM}, {16, 5, NUM}, {2, 14, PCREL}}},
- {0x40000003, "bcla", {{21, 5, NUM}, {16, 5, NUM}, {2, 14, BADDR}}},
-
- {0x4c000420, "bcctr", {{21, 5, NUM}, {16, 5, NUM}}},
- {0x4c000420, "bcctr", {{21, 5, NUM}, {16, 5, NUM}, {11, 2, NUM}}},
- {0x4c000421, "bcctrl", {{21, 5, NUM}, {16, 5, NUM}}},
- {0x4c000421, "bcctrl", {{21, 5, NUM}, {16, 5, NUM}, {11, 2, NUM}}},
- {0x4c000020, "bclr", {{21, 5, NUM}, {16, 5, NUM}}},
- {0x4c000020, "bclr", {{21, 5, NUM}, {16, 5, NUM}, {11, 2, NUM}}},
- {0x4c000021, "bclrl", {{21, 5, NUM}, {16, 5, NUM}}},
- {0x4c000021, "bclrl", {{21, 5, NUM}, {16, 5, NUM}, {11, 2, NUM}}},
-
- /* Basic branch mnemonics (assember extended mnemonics) */
- /* { 0x42800000, "b", {{2,14,PCREL}} }, overlaps */
- /* { 0x42800001, "bl", {{2,14,PCREL}} }, overlaps */
- {0x41800000, "bt", {{16, 5, BCND}, {2, 14, PCREL}}},
- {0x41800001, "btl", {{16, 5, BCND}, {2, 14, PCREL}}},
- {0x40800000, "bf", {{16, 5, BCND}, {2, 14, PCREL}}},
- {0x40800001, "bfl", {{16, 5, BCND}, {2, 14, PCREL}}},
- {0x42000000, "bdnz", {{2, 14, PCREL}}},
- {0x42000001, "bdnzl", {{2, 14, PCREL}}},
- {0x41000000, "bdnzt", {{16, 5, BCND}, {2, 14, PCREL}}},
- {0x41000001, "bdnztl", {{16, 5, BCND}, {2, 14, PCREL}}},
- {0x40000000, "bdnzf", {{16, 5, BCND}, {2, 14, PCREL}}},
- {0x40000001, "bdnzfl", {{16, 5, BCND}, {2, 14, PCREL}}},
- {0x42400000, "bdz", {{2, 14, PCREL}}},
- {0x42400001, "bdzl", {{2, 14, PCREL}}},
- {0x41400000, "bdzt", {{16, 5, BCND}, {2, 14, PCREL}}},
- {0x41400001, "bdztl", {{16, 5, BCND}, {2, 14, PCREL}}},
- {0x40400000, "bdzf", {{16, 5, BCND}, {2, 14, PCREL}}},
- {0x40400001, "bdzfl", {{16, 5, BCND}, {2, 14, PCREL}}},
-
- /* { 0x42800002, "ba", {{2,14,BADDR}} }, overlaps */
- /* { 0x42800003, "bla", {{2,14,BADDR}} }, overlaps */
- {0x41800002, "bta", {{16, 5, BCND}, {2, 14, BADDR}}},
- {0x41800003, "btla", {{16, 5, BCND}, {2, 14, BADDR}}},
- {0x40800002, "bfa", {{16, 5, BCND}, {2, 14, BADDR}}},
- {0x40800003, "bfla", {{16, 5, BCND}, {2, 14, BADDR}}},
- {0x42000002, "bdnza", {{2, 14, BADDR}}},
- {0x42000003, "bdnzla", {{2, 14, BADDR}}},
- {0x41000002, "bdnzta", {{16, 5, BCND}, {2, 14, BADDR}}},
- {0x41000003, "bdnztla", {{16, 5, BCND}, {2, 14, BADDR}}},
- {0x40000002, "bdnzfa", {{16, 5, BCND}, {2, 14, BADDR}}},
- {0x40000003, "bdnzfla", {{16, 5, BCND}, {2, 14, BADDR}}},
- {0x42400002, "bdza", {{2, 14, BADDR}}},
- {0x42400003, "bdzla", {{2, 14, BADDR}}},
- {0x41400002, "bdzta", {{16, 5, BCND}, {2, 14, BADDR}}},
- {0x41400003, "bdztla", {{16, 5, BCND}, {2, 14, BADDR}}},
- {0x40400002, "bdzfa", {{16, 5, BCND}, {2, 14, BADDR}}},
- {0x40400003, "bdzfla", {{16, 5, BCND}, {2, 14, BADDR}}},
-
- {
- 0x4e800020,
- "blr",
- },
- {0x4e800020, "blr", {{11, 2, NUM}}},
- {
- 0x4e800021,
- "blrl",
- },
- {0x4e800021, "blrl", {{11, 2, NUM}}},
- {0x4d800020, "btlr", {{16, 5, BCND}}},
- {0x4d800020, "btlr", {{16, 5, BCND}, {11, 2, NUM}}},
- {0x4d800021, "btlrl", {{16, 5, BCND}}},
- {0x4d800021, "btlrl", {{16, 5, BCND}, {11, 2, NUM}}},
- {0x4c800020, "bflr", {{16, 5, BCND}}},
- {0x4c800020, "bflr", {{16, 5, BCND}, {11, 2, NUM}}},
- {0x4c800021, "bflrl", {{16, 5, BCND}}},
- {0x4c800021, "bflrl", {{16, 5, BCND}, {11, 2, NUM}}},
- {
- 0x4e000020,
- "bdnzlr",
- },
- {0x4e000020, "bdnzlr", {{11, 2, NUM}}},
- {
- 0x4e000021,
- "bdnzlrl",
- },
- {0x4e000021, "bdnzlrl", {{11, 2, NUM}}},
- {0x4d000020, "bdnztlr", {{16, 5, BCND}}},
- {0x4d000020, "bdnztlr", {{16, 5, BCND}, {11, 2, NUM}}},
- {0x4d000021, "bdnztlrl", {{16, 5, BCND}}},
- {0x4d000021, "bdnztlrl", {{16, 5, BCND}, {11, 2, NUM}}},
- {0x4c000020, "bdnzflr", {{16, 5, BCND}}},
- {0x4c000020, "bdnzflr", {{16, 5, BCND}, {11, 2, NUM}}},
- {0x4c000021, "bdnzflrl", {{16, 5, BCND}}},
- {0x4c000021, "bdnzflrl", {{16, 5, BCND}, {11, 2, NUM}}},
- {
- 0x4e400020,
- "bdzlr",
- },
- {0x4e400020, "bdzlr", {{11, 2, NUM}}},
- {
- 0x4e400021,
- "bdzlrl",
- },
- {0x4e400021, "bdzlrl", {{11, 2, NUM}}},
- {0x4d400020, "bdztlr", {{16, 5, BCND}}},
- {0x4d400020, "bdztlr", {{16, 5, BCND}, {11, 2, NUM}}},
- {0x4d400021, "bdztlrl", {{16, 5, BCND}}},
- {0x4d400021, "bdztlrl", {{16, 5, BCND}, {11, 2, NUM}}},
- {0x4c400020, "bdzflr", {{16, 5, BCND}}},
- {0x4c400020, "bdzflr", {{16, 5, BCND}, {11, 2, NUM}}},
- {0x4c400021, "bdzflrl", {{16, 5, BCND}}},
- {0x4c400021, "bdzflrl", {{16, 5, BCND}, {11, 2, NUM}}},
-
- {0x4c000420, "bctr", {{21, 5, NUM}, {16, 5, NUM}}},
- {
- 0x4e800420,
- "bctr",
- },
- {0x4e800420, "bctr", {{11, 2, NUM}}},
- {0x4c000421, "bctrl", {{21, 5, NUM}, {16, 5, NUM}}},
- {
- 0x4e800421,
- "bctrl",
- },
- {0x4e800421, "bctrl", {{11, 2, NUM}}},
- {0x4d800420, "btctr", {{16, 5, BCND}}},
- {0x4d800420, "btctr", {{16, 5, BCND}, {11, 2, NUM}}},
- {0x4d800421, "btctrl", {{16, 5, BCND}}},
- {0x4d800421, "btctrl", {{16, 5, BCND}, {11, 2, NUM}}},
- {0x4c800420, "bfctr", {{16, 5, BCND}}},
- {0x4c800420, "bfctr", {{16, 5, BCND}, {11, 2, NUM}}},
- {0x4c800421, "bfctrl", {{16, 5, BCND}}},
- {0x4c800421, "bfctrl", {{16, 5, BCND}, {11, 2, NUM}}},
-
- /* branch mnemonics incorporating conditions (assember extended mnemonics)
- */
- {0x41800000, "blt", {{16, 5, CRF}, {2, 14, PCREL}}},
- {0x41800000, "blt", {{2, 14, PCREL}}},
- {0x41800001, "bltl", {{16, 5, CRF}, {2, 14, PCREL}}},
- {0x41800001, "bltl", {{2, 14, PCREL}}},
- {0x40810000, "ble", {{16, 5, CRF}, {2, 14, PCREL}}},
- {0x40810000, "ble", {{2, 14, PCREL}}},
- {0x40810001, "blel", {{16, 5, CRF}, {2, 14, PCREL}}},
- {0x40810001, "blel", {{2, 14, PCREL}}},
- {0x41820000, "beq", {{16, 5, CRF}, {2, 14, PCREL}}},
- {0x41820000, "beq", {{2, 14, PCREL}}},
- {0x41820001, "beql", {{16, 5, CRF}, {2, 14, PCREL}}},
- {0x41820001, "beql", {{2, 14, PCREL}}},
- {0x40800000, "bge", {{16, 5, CRF}, {2, 14, PCREL}}},
- {0x40800000, "bge", {{2, 14, PCREL}}},
- {0x40800001, "bgel", {{16, 5, CRF}, {2, 14, PCREL}}},
- {0x40800001, "bgel", {{2, 14, PCREL}}},
- {0x41810000, "bgt", {{16, 5, CRF}, {2, 14, PCREL}}},
- {0x41810000, "bgt", {{2, 14, PCREL}}},
- {0x41810001, "bgtl", {{16, 5, CRF}, {2, 14, PCREL}}},
- {0x41810001, "bgtl", {{2, 14, PCREL}}},
- {0x40800000, "bnl", {{16, 5, CRF}, {2, 14, PCREL}}},
- {0x40800000, "bnl", {{2, 14, PCREL}}},
- {0x40800001, "bnll", {{16, 5, CRF}, {2, 14, PCREL}}},
- {0x40800001, "bnll", {{2, 14, PCREL}}},
- {0x40820000, "bne", {{16, 5, CRF}, {2, 14, PCREL}}},
- {0x40820000, "bne", {{2, 14, PCREL}}},
- {0x40820001, "bnel", {{16, 5, CRF}, {2, 14, PCREL}}},
- {0x40820001, "bnel", {{2, 14, PCREL}}},
- {0x40810000, "bng", {{16, 5, CRF}, {2, 14, PCREL}}},
- {0x40810000, "bng", {{2, 14, PCREL}}},
- {0x40810001, "bngl", {{16, 5, CRF}, {2, 14, PCREL}}},
- {0x40810001, "bngl", {{2, 14, PCREL}}},
- {0x41830000, "bso", {{16, 5, CRF}, {2, 14, PCREL}}},
- {0x41830000, "bso", {{2, 14, PCREL}}},
- {0x41830001, "bsol", {{16, 5, CRF}, {2, 14, PCREL}}},
- {0x41830001, "bsol", {{2, 14, PCREL}}},
- {0x40830000, "bns", {{16, 5, CRF}, {2, 14, PCREL}}},
- {0x40830000, "bns", {{2, 14, PCREL}}},
- {0x40830001, "bnsl", {{16, 5, CRF}, {2, 14, PCREL}}},
- {0x40830001, "bnsl", {{2, 14, PCREL}}},
- {0x41830000, "bun", {{16, 5, CRF}, {2, 14, PCREL}}},
- {0x41830000, "bun", {{2, 14, PCREL}}},
- {0x41830001, "bunl", {{16, 5, CRF}, {2, 14, PCREL}}},
- {0x41830001, "bunl", {{2, 14, PCREL}}},
- {0x40830000, "bnu", {{16, 5, CRF}, {2, 14, PCREL}}},
- {0x40830000, "bnu", {{2, 14, PCREL}}},
- {0x40830001, "bnul", {{16, 5, CRF}, {2, 14, PCREL}}},
- {0x40830001, "bnul", {{2, 14, PCREL}}},
-
- {0x41800002, "blta", {{16, 5, CRF}, {2, 14, BADDR}}},
- {0x41800002, "blta", {{2, 14, BADDR}}},
- {0x41800003, "bltla", {{16, 5, CRF}, {2, 14, BADDR}}},
- {0x41800003, "bltla", {{2, 14, BADDR}}},
- {0x40810002, "blea", {{16, 5, CRF}, {2, 14, BADDR}}},
- {0x40810002, "blea", {{2, 14, BADDR}}},
- {0x40810003, "blela", {{16, 5, CRF}, {2, 14, BADDR}}},
- {0x40810003, "blela", {{2, 14, BADDR}}},
- {0x41820002, "beqa", {{16, 5, CRF}, {2, 14, BADDR}}},
- {0x41820002, "beqa", {{2, 14, BADDR}}},
- {0x41820003, "beqla", {{16, 5, CRF}, {2, 14, BADDR}}},
- {0x41820003, "beqla", {{2, 14, BADDR}}},
- {0x40800002, "bgea", {{16, 5, CRF}, {2, 14, BADDR}}},
- {0x40800002, "bgea", {{2, 14, BADDR}}},
- {0x40800003, "bgela", {{16, 5, CRF}, {2, 14, BADDR}}},
- {0x40800003, "bgela", {{2, 14, BADDR}}},
- {0x41810002, "bgta", {{16, 5, CRF}, {2, 14, BADDR}}},
- {0x41810002, "bgta", {{2, 14, BADDR}}},
- {0x41810003, "bgtla", {{16, 5, CRF}, {2, 14, BADDR}}},
- {0x41810003, "bgtla", {{2, 14, BADDR}}},
- {0x40800002, "bnla", {{16, 5, CRF}, {2, 14, BADDR}}},
- {0x40800002, "bnla", {{2, 14, BADDR}}},
- {0x40800003, "bnlla", {{16, 5, CRF}, {2, 14, BADDR}}},
- {0x40800003, "bnlla", {{2, 14, BADDR}}},
- {0x40820002, "bnea", {{16, 5, CRF}, {2, 14, BADDR}}},
- {0x40820002, "bnea", {{2, 14, BADDR}}},
- {0x40820003, "bnela", {{16, 5, CRF}, {2, 14, BADDR}}},
- {0x40820003, "bnela", {{2, 14, BADDR}}},
- {0x40810002, "bnga", {{16, 5, CRF}, {2, 14, BADDR}}},
- {0x40810002, "bnga", {{2, 14, BADDR}}},
- {0x40810003, "bngla", {{16, 5, CRF}, {2, 14, BADDR}}},
- {0x40810003, "bngla", {{2, 14, BADDR}}},
- {0x41830002, "bsoa", {{16, 5, CRF}, {2, 14, BADDR}}},
- {0x41830002, "bsoa", {{2, 14, BADDR}}},
- {0x41830003, "bsola", {{16, 5, CRF}, {2, 14, BADDR}}},
- {0x41830003, "bsola", {{2, 14, BADDR}}},
- {0x40830002, "bnsa", {{16, 5, CRF}, {2, 14, BADDR}}},
- {0x40830002, "bnsa", {{2, 14, BADDR}}},
- {0x40830003, "bnsla", {{16, 5, CRF}, {2, 14, BADDR}}},
- {0x40830003, "bnsla", {{2, 14, BADDR}}},
- {0x41830002, "buna", {{16, 5, CRF}, {2, 14, BADDR}}},
- {0x41830002, "buna", {{2, 14, BADDR}}},
- {0x41830003, "bunla", {{16, 5, CRF}, {2, 14, BADDR}}},
- {0x41830003, "bunla", {{2, 14, BADDR}}},
- {0x40830002, "bnua", {{16, 5, CRF}, {2, 14, BADDR}}},
- {0x40830002, "bnua", {{2, 14, BADDR}}},
- {0x40830003, "bnula", {{16, 5, CRF}, {2, 14, BADDR}}},
- {0x40830003, "bnula", {{2, 14, BADDR}}},
-
- {0x4d800020, "bltlr", {{16, 5, CRF}}},
- {0x4d800020, "bltlr", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4d800020,
- "bltlr",
- },
- {0x4d800021, "bltlrl", {{16, 5, CRF}}},
- {0x4d800021, "bltlrl", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4d800021,
- "bltlrl",
- },
- {0x4c810020, "blelr", {{16, 5, CRF}}},
- {0x4c810020, "blelr", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4c810020,
- "blelr",
- },
- {0x4c810021, "blelrl", {{16, 5, CRF}}},
- {0x4c810021, "blelrl", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4c810021,
- "blelrl",
- },
- {0x4d820020, "beqlr", {{16, 5, CRF}}},
- {0x4d820020, "beqlr", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4d820020,
- "beqlr",
- },
- {0x4d820021, "beqlrl", {{16, 5, CRF}}},
- {0x4d820021, "beqlrl", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4d820021,
- "beqlrl",
- },
- {0x4c800020, "bgelr", {{16, 5, CRF}}},
- {0x4c800020, "bgelr", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4c800020,
- "bgelr",
- },
- {0x4c800021, "bgelrl", {{16, 5, CRF}}},
- {0x4c800021, "bgelrl", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4c800021,
- "bgelrl",
- },
- {0x4d810020, "bgtlr", {{16, 5, CRF}}},
- {0x4d810020, "bgtlr", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4d810020,
- "bgtlr",
- },
- {0x4d810021, "bgtlrl", {{16, 5, CRF}}},
- {0x4d810021, "bgtlrl", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4d810021,
- "bgtlrl",
- },
- {0x4c800020, "bnllr", {{16, 5, CRF}}},
- {0x4c800020, "bnllr", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4c800020,
- "bnllr",
- },
- {0x4c800021, "bnllrl", {{16, 5, CRF}}},
- {0x4c800021, "bnllrl", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4c800021,
- "bnllrl",
- },
- {0x4c820020, "bnelr", {{16, 5, CRF}}},
- {0x4c820020, "bnelr", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4c820020,
- "bnelr",
- },
- {0x4c820021, "bnelrl", {{16, 5, CRF}}},
- {0x4c820021, "bnelrl", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4c820021,
- "bnelrl",
- },
- {0x4c810020, "bnglr", {{16, 5, CRF}}},
- {0x4c810020, "bnglr", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4c810020,
- "bnglr",
- },
- {0x4c810021, "bnglrl", {{16, 5, CRF}}},
- {0x4c810021, "bnglrl", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4c810021,
- "bnglrl",
- },
- {0x4d830020, "bsolr", {{16, 5, CRF}}},
- {0x4d830020, "bsolr", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4d830020,
- "bsolr",
- },
- {0x4d830021, "bsolrl", {{16, 5, CRF}}},
- {0x4d830021, "bsolrl", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4d830021,
- "bsolrl",
- },
- {0x4c830020, "bnslr", {{16, 5, CRF}}},
- {0x4c830020, "bnslr", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4c830020,
- "bnslr",
- },
- {0x4c830021, "bnslrl", {{16, 5, CRF}}},
- {0x4c830021, "bnslrl", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4c830021,
- "bnslrl",
- },
- {0x4d830020, "bunlr", {{16, 5, CRF}}},
- {0x4d830020, "bunlr", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4d830020,
- "bunlr",
- },
- {0x4d830021, "bunlrl", {{16, 5, CRF}}},
- {0x4d830021, "bunlrl", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4d830021,
- "bunlrl",
- },
- {0x4c830020, "bnulr", {{16, 5, CRF}}},
- {0x4c830020, "bnulr", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4c830020,
- "bnulr",
- },
- {0x4c830021, "bnulrl", {{16, 5, CRF}}},
- {0x4c830021, "bnulrl", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4c830021,
- "bnulrl",
- },
-
- {0x4d800420, "bltctr", {{16, 5, CRF}}},
- {0x4d800420, "bltctr", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4d800420,
- "bltctr",
- },
- {0x4d800421, "bltctrl", {{16, 5, CRF}}},
- {0x4d800421, "bltctrl", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4d800421,
- "bltctrl",
- },
- {0x4c810420, "blectr", {{16, 5, CRF}}},
- {0x4c810420, "blectr", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4c810420,
- "blectr",
- },
- {0x4c810421, "blectrl", {{16, 5, CRF}}},
- {0x4c810421, "blectrl", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4c810421,
- "blectrl",
- },
- {0x4d820420, "beqctr", {{16, 5, CRF}}},
- {0x4d820420, "beqctr", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4d820420,
- "beqctr",
- },
- {0x4d820421, "beqctrl", {{16, 5, CRF}}},
- {0x4d820421, "beqctrl", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4d820421,
- "beqctrl",
- },
- {0x4c800420, "bgectr", {{16, 5, CRF}}},
- {0x4c800420, "bgectr", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4c800420,
- "bgectr",
- },
- {0x4c800421, "bgectrl", {{16, 5, CRF}}},
- {0x4c800421, "bgectrl", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4c800421,
- "bgectrl",
- },
- {0x4d810420, "bgtctr", {{16, 5, CRF}}},
- {0x4d810420, "bgtctr", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4d810420,
- "bgtctr",
- },
- {0x4d810421, "bgtctrl", {{16, 5, CRF}}},
- {0x4d810421, "bgtctrl", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4d810421,
- "bgtctrl",
- },
- {0x4c800420, "bnlctr", {{16, 5, CRF}}},
- {0x4c800420, "bnlctr", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4c800420,
- "bnlctr",
- },
- {0x4c800421, "bnlctrl", {{16, 5, CRF}}},
- {0x4c800421, "bnlctrl", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4c800421,
- "bnlctrl",
- },
- {0x4c820420, "bnectr", {{16, 5, CRF}}},
- {0x4c820420, "bnectr", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4c820420,
- "bnectr",
- },
- {0x4c820421, "bnectrl", {{16, 5, CRF}}},
- {0x4c820421, "bnectrl", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4c820421,
- "bnectrl",
- },
- {0x4c810420, "bngctr", {{16, 5, CRF}}},
- {0x4c810420, "bngctr", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4c810420,
- "bngctr",
- },
- {0x4c810421, "bngctrl", {{16, 5, CRF}}},
- {0x4c810421, "bngctrl", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4c810421,
- "bngctrl",
- },
- {0x4d830420, "bsoctr", {{16, 5, CRF}}},
- {0x4d830420, "bsoctr", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4d830420,
- "bsoctr",
- },
- {0x4d830421, "bsoctrl", {{16, 5, CRF}}},
- {0x4d830421, "bsoctrl", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4d830421,
- "bsoctrl",
- },
- {0x4c830420, "bnsctr", {{16, 5, CRF}}},
- {0x4c830420, "bnsctr", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4c830420,
- "bnsctr",
- },
- {0x4c830421, "bnsctrl", {{16, 5, CRF}}},
- {0x4c830421, "bnsctrl", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4c830421,
- "bnsctrl",
- },
- {0x4d830420, "bunctr", {{16, 5, CRF}}},
- {0x4d830420, "bunctr", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4d830420,
- "bunctr",
- },
- {0x4d830421, "bunctrl", {{16, 5, CRF}}},
- {0x4d830421, "bunctrl", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4d830421,
- "bunctrl",
- },
- {0x4c830420, "bnuctr", {{16, 5, CRF}}},
- {0x4c830420, "bnuctr", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4c830420,
- "bnuctr",
- },
- {0x4c830421, "bnuctrl", {{16, 5, CRF}}},
- {0x4c830421, "bnuctrl", {{16, 5, CRF}, {11, 2, NUM}}},
- {
- 0x4c830421,
- "bnuctrl",
- },
-
- {0x2c000000, "cmpi", {{21, 5, CRFONLY}, {16, 5, GREG}, {0, 16, SI}}},
- {0x2c000000,
- "cmpi",
- {{21, 5, CRFONLY}, {21, 1, NUM}, {16, 5, GREG}, {0, 16, SI}}},
- {0x2c000000, "cmpi", {{23, 3, NUM}, {16, 5, GREG}, {0, 16, SI}}},
- {0x2c000000,
- "cmpi",
- {{23, 3, NUM}, {21, 1, NUM}, {16, 5, GREG}, {0, 16, SI}}},
- {0x2c000000, "cmpwi", {{16, 5, GREG}, {0, 16, SI}}},
- {0x2c000000, "cmpwi", {{21, 5, CRFONLY}, {16, 5, GREG}, {0, 16, SI}}},
- {0x2c000000, "cmpwi", {{23, 3, NUM}, {16, 5, GREG}, {0, 16, SI}}},
- {0x2c200000, "cmpdi", {{16, 5, GREG}, {0, 16, SI}}},
- {0x2c200000, "cmpdi", {{21, 5, CRFONLY}, {16, 5, GREG}, {0, 16, SI}}},
- {0x2c200000, "cmpdi", {{23, 3, NUM}, {16, 5, GREG}, {0, 16, SI}}},
-
- {0x7c000000, "cmp", {{21, 5, CRFONLY}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000000,
- "cmp",
- {{21, 5, CRFONLY}, {21, 1, NUM}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000000, "cmp", {{23, 3, NUM}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000000,
- "cmp",
- {{23, 3, NUM}, {21, 1, NUM}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000000, "cmpw", {{16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000000, "cmpw", {{21, 5, CRFONLY}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000000, "cmpw", {{23, 3, NUM}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c200000, "cmpd", {{16, 5, GREG}, {11, 5, GREG}}},
- {0x7c200000, "cmpd", {{21, 5, CRFONLY}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c200000, "cmpd", {{23, 3, NUM}, {16, 5, GREG}, {11, 5, GREG}}},
-
- {0x28000000, "cmpli", {{21, 5, CRFONLY}, {16, 5, GREG}, {0, 16, UI}}},
- {0x28000000,
- "cmpli",
- {{21, 5, CRFONLY}, {21, 1, NUM}, {16, 5, GREG}, {0, 16, UI}}},
- {0x28000000, "cmpli", {{23, 3, NUM}, {16, 5, GREG}, {0, 16, UI}}},
- {0x28000000,
- "cmpli",
- {{23, 3, NUM}, {21, 1, NUM}, {16, 5, GREG}, {0, 16, UI}}},
- {0x28000000, "cmplwi", {{16, 5, GREG}, {0, 16, UI}}},
- {0x28000000, "cmplwi", {{21, 5, CRFONLY}, {16, 5, GREG}, {0, 16, UI}}},
- {0x28000000, "cmplwi", {{23, 3, NUM}, {16, 5, GREG}, {0, 16, UI}}},
- {0x28200000, "cmpldi", {{16, 5, GREG}, {0, 16, UI}}},
- {0x28200000, "cmpldi", {{21, 5, CRFONLY}, {16, 5, GREG}, {0, 16, UI}}},
- {0x28200000, "cmpldi", {{23, 3, NUM}, {16, 5, GREG}, {0, 16, UI}}},
-
- {0x7c000040, "cmpl", {{21, 5, CRFONLY}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000040,
- "cmpl",
- {{21, 5, CRFONLY}, {21, 1, NUM}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000040, "cmpl", {{23, 3, NUM}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000040,
- "cmpl",
- {{23, 3, NUM}, {21, 1, NUM}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000040, "cmplw", {{16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000040, "cmplw", {{21, 5, CRFONLY}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000040, "cmplw", {{23, 3, NUM}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c200040, "cmpld", {{16, 5, GREG}, {11, 5, GREG}}},
- {0x7c200040, "cmpld", {{21, 5, CRFONLY}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c200040, "cmpld", {{23, 3, NUM}, {16, 5, GREG}, {11, 5, GREG}}},
-
- {0x7c000034, "cntlzw", {{16, 5, GREG}, {21, 5, GREG}}},
- {0x7c000035, "cntlzw.", {{16, 5, GREG}, {21, 5, GREG}}},
- {0x7c000074, "cntlzd", {{16, 5, GREG}, {21, 5, GREG}}, IMPL64},
- {0x7c000075, "cntlzd.", {{16, 5, GREG}, {21, 5, GREG}}, IMPL64},
-
- {0x4c000202, "crand", {{21, 5, NUM}, {16, 5, NUM}, {11, 5, NUM}}},
- {0x4c000102, "crandc", {{21, 5, NUM}, {16, 5, NUM}, {11, 5, NUM}}},
- {0x4c000242, "creqv", {{21, 5, NUM}, {16, 5, NUM}, {11, 5, NUM}}},
- {0x4c0001c2, "crnand", {{21, 5, NUM}, {16, 5, NUM}, {11, 5, NUM}}},
- {0x4c000042, "crnor", {{21, 5, NUM}, {16, 5, NUM}, {11, 5, NUM}}},
- {0x4c000382, "cror", {{21, 5, NUM}, {16, 5, NUM}, {11, 5, NUM}}},
- {0x4c000342, "crorc", {{21, 5, NUM}, {16, 5, NUM}, {11, 5, NUM}}},
- {0x4c000182, "crxor", {{21, 5, NUM}, {16, 5, NUM}, {11, 5, NUM}}},
-
- {0x7c0003d2, "divd", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, IMPL64},
- {0x7c0003d3,
- "divd.",
- {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}},
- IMPL64},
- {0x7c0007d2,
- "divdo",
- {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}},
- IMPL64},
- {0x7c0007d3,
- "divdo.",
- {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}},
- IMPL64},
-
- {0x7c000392,
- "divdu",
- {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}},
- IMPL64},
- {0x7c000393,
- "divdu.",
- {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}},
- IMPL64},
- {0x7c000792,
- "divduo",
- {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}},
- IMPL64},
- {0x7c000793,
- "divduo.",
- {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}},
- IMPL64},
-
- {0x7c0003d6, "divw", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c0003d7, "divw.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c0007d6, "divwo", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c0007d7, "divwo.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
-
- {0x7c000396, "divwu", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000397, "divwu.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000796, "divwuo", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000797, "divwuo.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
-
- {0x7c000238, "eqv", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
- {0x7c000239, "eqv.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
-
- {0x7c000774, "extsb", {{16, 5, GREG}, {21, 5, GREG}}},
- {0x7c000775, "extsb.", {{16, 5, GREG}, {21, 5, GREG}}},
- {0x7c000734, "extsh", {{16, 5, GREG}, {21, 5, GREG}}},
- {0x7c000735, "extsh.", {{16, 5, GREG}, {21, 5, GREG}}},
- {0x7c0007b4, "extsw", {{16, 5, GREG}, {21, 5, GREG}}, IMPL64},
- {0x7c0007b5, "extsw.", {{16, 5, GREG}, {21, 5, GREG}}, IMPL64},
-
- {0xfc00002a, "fadd", {{21, 5, FREG}, {16, 5, FREG}, {11, 5, FREG}}},
- {0xfc00002b, "fadd.", {{21, 5, FREG}, {16, 5, FREG}, {11, 5, FREG}}},
- {0xec00002a, "fadds", {{21, 5, FREG}, {16, 5, FREG}, {11, 5, FREG}}},
- {0xec00002b, "fadds.", {{21, 5, FREG}, {16, 5, FREG}, {11, 5, FREG}}},
- {0xfc000028, "fsub", {{21, 5, FREG}, {16, 5, FREG}, {11, 5, FREG}}},
- {0xfc000029, "fsub.", {{21, 5, FREG}, {16, 5, FREG}, {11, 5, FREG}}},
- {0xec000028, "fsubs", {{21, 5, FREG}, {16, 5, FREG}, {11, 5, FREG}}},
- {0xec000029, "fsubs.", {{21, 5, FREG}, {16, 5, FREG}, {11, 5, FREG}}},
- {0xfc000032, "fmul", {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}}},
- {0xfc000033, "fmul.", {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}}},
- {0xec000032, "fmuls", {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}}},
- {0xec000033, "fmuls.", {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}}},
- {0xfc000024, "fdiv", {{21, 5, FREG}, {16, 5, FREG}, {11, 5, FREG}}},
- {0xfc000025, "fdiv.", {{21, 5, FREG}, {16, 5, FREG}, {11, 5, FREG}}},
- {0xec000024, "fdivs", {{21, 5, FREG}, {16, 5, FREG}, {11, 5, FREG}}},
- {0xec000025, "fdivs.", {{21, 5, FREG}, {16, 5, FREG}, {11, 5, FREG}}},
-
- {0xfc00003a,
- "fmadd",
- {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
- {0xfc00003b,
- "fmadd.",
- {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
- {0xec00003a,
- "fmadds",
- {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
- {0xec00003b,
- "fmadds.",
- {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
- {0xfc000038,
- "fmsub",
- {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
- {0xfc000039,
- "fmsub.",
- {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
- {0xec000038,
- "fmsubs",
- {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
- {0xec000039,
- "fmsubs.",
- {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
- {0xfc00003e,
- "fnmadd",
- {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
- {0xfc00003f,
- "fnmadd.",
- {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
- {0xec00003e,
- "fnmadds",
- {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
- {0xec00003f,
- "fnmadds.",
- {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
- {0xfc00003c,
- "fnmsub",
- {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
- {0xfc00003d,
- "fnmsub.",
- {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
- {0xec00003c,
- "fnmsubs",
- {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
- {0xec00003d,
- "fnmsubs.",
- {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
-
- {0xfc000090, "fmr", {{21, 5, FREG}, {11, 5, FREG}}},
- {0xfc000091, "fmr.", {{21, 5, FREG}, {11, 5, FREG}}},
- {0xfc000210, "fabs", {{21, 5, FREG}, {11, 5, FREG}}},
- {0xfc000211, "fabs.", {{21, 5, FREG}, {11, 5, FREG}}},
- {0xfc000050, "fneg", {{21, 5, FREG}, {11, 5, FREG}}},
- {0xfc000051, "fneg.", {{21, 5, FREG}, {11, 5, FREG}}},
- {0xfc000110, "fnabs", {{21, 5, FREG}, {11, 5, FREG}}},
- {0xfc000111, "fnabs.", {{21, 5, FREG}, {11, 5, FREG}}},
- {0xec000030, "fres", {{21, 5, FREG}, {11, 5, FREG}}},
- {0xec000031, "fres.", {{21, 5, FREG}, {11, 5, FREG}}},
- {0xfc000018, "frsp", {{21, 5, FREG}, {11, 5, FREG}}},
- {0xfc000019, "frsp.", {{21, 5, FREG}, {11, 5, FREG}}},
- {0xfc000034, "frsqrte", {{21, 5, FREG}, {11, 5, FREG}}},
- {0xfc000035, "frsqrte.", {{21, 5, FREG}, {11, 5, FREG}}},
- {0xfc00002e,
- "fsel",
- {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
- {0xfc00002f,
- "fsel.",
- {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
- {0xfc00002c, "fsqrt", {{21, 5, FREG}, {11, 5, FREG}}, OPTIONAL | CPU970},
- {0xfc00002d, "fsqrt.", {{21, 5, FREG}, {11, 5, FREG}}, OPTIONAL | CPU970},
- {0xec00002c, "fsqrts", {{21, 5, FREG}, {11, 5, FREG}}, OPTIONAL | CPU970},
- {0xec00002d, "fsqrts.", {{21, 5, FREG}, {11, 5, FREG}}, OPTIONAL | CPU970},
- {0xfc00065c, "fctid", {{21, 5, FREG}, {11, 5, FREG}}, IMPL64},
- {0xfc00065d, "fctid.", {{21, 5, FREG}, {11, 5, FREG}}, IMPL64},
- {0xfc00065e, "fctidz", {{21, 5, FREG}, {11, 5, FREG}}, IMPL64},
- {0xfc00065f, "fctidz.", {{21, 5, FREG}, {11, 5, FREG}}, IMPL64},
- {0xfc00001c, "fctiw", {{21, 5, FREG}, {11, 5, FREG}}},
- {0xfc00001d, "fctiw.", {{21, 5, FREG}, {11, 5, FREG}}},
- {0xfc00001e, "fctiwz", {{21, 5, FREG}, {11, 5, FREG}}},
- {0xfc00001f, "fctiwz.", {{21, 5, FREG}, {11, 5, FREG}}},
- {0xfc00069c, "fcfid", {{21, 5, FREG}, {11, 5, FREG}}, IMPL64},
- {0xfc00069d, "fcfid.", {{21, 5, FREG}, {11, 5, FREG}}, IMPL64},
-
- {0xfc000000, "fcmpu", {{21, 5, CRFONLY}, {16, 5, FREG}, {11, 5, FREG}}},
- {0xfc000000, "fcmpu", {{23, 3, NUM}, {16, 5, FREG}, {11, 5, FREG}}},
- {0xfc000040, "fcmpo", {{21, 5, CRFONLY}, {16, 5, FREG}, {11, 5, FREG}}},
- {0xfc000040, "fcmpo", {{23, 3, NUM}, {16, 5, FREG}, {11, 5, FREG}}},
- {0xfc00048e, "mffs", {{21, 5, FREG}}},
- {0xfc00048f, "mffs.", {{21, 5, FREG}}},
- {0xfc000080, "mcrfs", {{21, 5, CRFONLY}, {18, 5, NUM}}},
- {0xfc000080, "mcrfs", {{23, 3, NUM}, {18, 5, NUM}}},
- {0xfc00010c, "mtfsfi", {{23, 3, NUM}, {12, 4, NUM}}},
- {0xfc00010d, "mtfsfi.", {{23, 3, NUM}, {12, 4, NUM}}},
- {0xfc00058e, "mtfsf", {{17, 8, NUM}, {11, 5, FREG}}},
- {0xfc00058f, "mtfsf.", {{17, 8, NUM}, {11, 5, FREG}}},
- {0xfc00008c, "mtfsb0", {{21, 5, NUM}}},
- {0xfc00008d, "mtfsb0.", {{21, 5, NUM}}},
- {0xfc00004c, "mtfsb1", {{21, 5, NUM}}},
- {0xfc00004d, "mtfsb1.", {{21, 5, NUM}}},
-
- {0x88000000, "lbz", {{21, 5, GREG}, {0, 16, D}, {16, 5, G0REG}}},
- {0x7c0000ae, "lbzx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
- {0x8c000000, "lbzu", {{21, 5, GREG}, {0, 16, D}, {16, 5, G0REG}}},
- {0x7c0000ee, "lbzux", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0xa0000000, "lhz", {{21, 5, GREG}, {0, 16, D}, {16, 5, G0REG}}},
- {0x7c00022e, "lhzx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
- {0xa4000000, "lhzu", {{21, 5, GREG}, {0, 16, D}, {16, 5, G0REG}}},
- {0x7c00026e, "lhzux", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0xa8000000, "lha", {{21, 5, GREG}, {0, 16, D}, {16, 5, G0REG}}},
- {0x7c0002ae, "lhax", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
- {0xac000000, "lhau", {{21, 5, GREG}, {0, 16, D}, {16, 5, GREG}}},
- {0x7c0002ee, "lhaux", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x80000000, "lwz", {{21, 5, GREG}, {0, 16, D}, {16, 5, G0REG}}},
- {0x7c00002e, "lwzx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
- {0x84000000, "lwzu", {{21, 5, GREG}, {0, 16, D}, {16, 5, GREG}}},
- {0x7c00006e, "lwzux", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0xe8000002, "lwa", {{21, 5, GREG}, {2, 14, DS}, {16, 5, G0REG}}, IMPL64},
- {0x7c0002aa,
- "lwax",
- {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}},
- IMPL64},
- {0x7c0002ea,
- "lwaux",
- {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}},
- IMPL64},
- {0xe8000000, "ld", {{21, 5, GREG}, {2, 14, DS}, {16, 5, G0REG}}, IMPL64},
- {0x7c00002a, "ldx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}, IMPL64},
- {0xe8000001, "ldu", {{21, 5, GREG}, {2, 14, DS}, {16, 5, GREG}}, IMPL64},
- {0x7c00006a, "ldux", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, IMPL64},
-
- {0xb8000000, "lmw", {{21, 5, GREG}, {0, 16, D}, {16, 5, G0REG}}},
- {0xbc000000, "stmw", {{21, 5, GREG}, {0, 16, D}, {16, 5, G0REG}}},
-
- {0x7c00062c, "lhbrx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
- {0x7c00042c, "lwbrx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
- {0x7c00042a, "lswx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
- {0x7c000028, "lwarx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
- {0x7c0000a8,
- "ldarx",
- {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}},
- IMPL64},
-
- {0x7c00022a,
- "lscbx",
- {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}},
- CPU601},
- {0x7c00022b,
- "lscbx.",
- {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}},
- CPU601},
-
- {0x7c0004aa, "lswi", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, NUM0}}},
-
- {0xc0000000, "lfs", {{21, 5, FREG}, {0, 16, D}, {16, 5, G0REG}}},
- {0xc4000000, "lfsu", {{21, 5, FREG}, {0, 16, D}, {16, 5, GREG}}},
- {0x7c00042e, "lfsx", {{21, 5, FREG}, {16, 5, G0REG}, {11, 5, GREG}}},
- {0x7c00046e, "lfsux", {{21, 5, FREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0xc8000000, "lfd", {{21, 5, FREG}, {0, 16, D}, {16, 5, G0REG}}},
- {0xcc000000, "lfdu", {{21, 5, FREG}, {0, 16, D}, {16, 5, GREG}}},
- {0x7c0004ae, "lfdx", {{21, 5, FREG}, {16, 5, G0REG}, {11, 5, GREG}}},
- {0x7c0004ee, "lfdux", {{21, 5, FREG}, {16, 5, GREG}, {11, 5, GREG}}},
-
- {0x38000000, "la", {{21, 5, GREG}, {0, 16, D}, {16, 5, G0REG}}},
-
- {0x4c000000, "mcrf", {{21, 5, CRFONLY}, {16, 5, CRFONLY}}},
- {0x4c000000, "mcrf", {{23, 3, NUM}, {18, 3, NUM}}},
-
- {0x7c0002a6, "mfspr", {{21, 5, GREG}, {11, 10, SPREG}}},
- {0x7c0003a6, "mtspr", {{11, 10, SPREG}, {21, 5, GREG}}},
- {0x7c000120, "mtcrf", {{12, 8, FXM}, {21, 5, GREG}}},
- {0x7c000120, "mtocrf", {{12, 8, FXM}, {21, 5, GREG}}},
- {0x7c000400, "mcrxr", {{21, 5, CRFONLY}}},
- {0x7c000400, "mcrxr", {{23, 3, NUM}}},
- {0x7c000026, "mfcr", {{21, 5, GREG}}},
- {0x7c100026, "mfcr", {{21, 5, GREG}, {12, 8, FXM}}},
- {0x7c100026, "mfocrf", {{21, 5, GREG}, {12, 8, FXM}}},
-
- /* Move to/from spr mnemonics (assember extended mnemonics) */
- {0x7c0102a6, "mfxer", {{21, 5, GREG}}},
- {0x7c0802a6, "mflr", {{21, 5, GREG}}},
- {0x7c0902a6, "mfctr", {{21, 5, GREG}}},
- {0x7c0103a6, "mtxer", {{21, 5, GREG}}},
- {0x7c0803a6, "mtlr", {{21, 5, GREG}}},
- {0x7c0903a6, "mtctr", {{21, 5, GREG}}},
- {0x7c0002a6, "mfmq", {{21, 5, GREG}}},
- {0x7c0502a6, "mfrtcl", {{21, 5, GREG}}},
- {0x7c0402a6, "mfrtcu", {{21, 5, GREG}}},
- {0x7c0003a6, "mtmq", {{21, 5, GREG}}},
- {0x7c1503a6, "mtrtcl", {{21, 5, GREG}}},
- {0x7c1403a6, "mtrtcu", {{21, 5, GREG}}},
+ {0x38000000, "addi", {{21, 5, GREG}, {16, 5, G0REG}, {0, 16, SI}}},
+ {0x38000000, "li", {{21, 5, GREG}, {0, 16, SI}}},
+ {0x3c000000, "addis", {{21, 5, GREG}, {16, 5, G0REG}, {0, 16, HI}}},
+ {0x3c000000, "lis", {{21, 5, GREG}, {0, 16, HI}}},
+ {0x30000000, "addic", {{21, 5, GREG}, {16, 5, GREG}, {0, 16, SI}}},
+ {0x34000000, "addic.", {{21, 5, GREG}, {16, 5, GREG}, {0, 16, SI}}},
+ {0x7c000214, "add", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000215, "add.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000614, "addo", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000615, "addo.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+
+ {0x7c000014, "addc", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000015, "addc.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000414, "addco", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000415, "addco.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+
+ {0x7c000114, "adde", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000115, "adde.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000514, "addeo", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000515, "addeo.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+
+ {0x7c0001d4, "addme", {{21, 5, GREG}, {16, 5, GREG}}},
+ {0x7c0001d5, "addme.", {{21, 5, GREG}, {16, 5, GREG}}},
+ {0x7c0005d4, "addmeo", {{21, 5, GREG}, {16, 5, GREG}}},
+ {0x7c0005d5, "addmeo.", {{21, 5, GREG}, {16, 5, GREG}}},
+
+ {0x7c000194, "addze", {{21, 5, GREG}, {16, 5, GREG}}},
+ {0x7c000195, "addze.", {{21, 5, GREG}, {16, 5, GREG}}},
+ {0x7c000594, "addzeo", {{21, 5, GREG}, {16, 5, GREG}}},
+ {0x7c000595, "addzeo.", {{21, 5, GREG}, {16, 5, GREG}}},
+
+ {0x70000000, "andi.", {{16, 5, GREG}, {21, 5, GREG}, {0, 16, UI}}},
+ {0x74000000, "andis.", {{16, 5, GREG}, {21, 5, GREG}, {0, 16, UI}}},
+ {0x7c000038, "and", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000039, "and.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
+
+ {0x7c000078, "andc", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000079, "andc.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
+
+ {0x48000000, "b", {{2, 24, PCREL}}},
+ {0x48000002, "ba", {{2, 24, BADDR}}},
+ {0x48000001, "bl", {{2, 24, PCREL}}},
+ {0x48000003, "bla", {{2, 24, BADDR}}},
+
+ {0x48000001, "jbsr", {{0, 0, JBSR}, {2, 24, PCREL}}},
+ {0x48000000, "jmp", {{0, 0, JBSR}, {2, 24, PCREL}}},
+
+ {0x40000000, "bc", {{21, 5, NUM}, {16, 5, NUM}, {2, 14, PCREL}}},
+ {0x40000002, "bca", {{21, 5, NUM}, {16, 5, NUM}, {2, 14, BADDR}}},
+ {0x40000001, "bcl", {{21, 5, NUM}, {16, 5, NUM}, {2, 14, PCREL}}},
+ {0x40000003, "bcla", {{21, 5, NUM}, {16, 5, NUM}, {2, 14, BADDR}}},
+
+ {0x4c000420, "bcctr", {{21, 5, NUM}, {16, 5, NUM}}},
+ {0x4c000420, "bcctr", {{21, 5, NUM}, {16, 5, NUM}, {11, 2, NUM}}},
+ {0x4c000421, "bcctrl", {{21, 5, NUM}, {16, 5, NUM}}},
+ {0x4c000421, "bcctrl", {{21, 5, NUM}, {16, 5, NUM}, {11, 2, NUM}}},
+ {0x4c000020, "bclr", {{21, 5, NUM}, {16, 5, NUM}}},
+ {0x4c000020, "bclr", {{21, 5, NUM}, {16, 5, NUM}, {11, 2, NUM}}},
+ {0x4c000021, "bclrl", {{21, 5, NUM}, {16, 5, NUM}}},
+ {0x4c000021, "bclrl", {{21, 5, NUM}, {16, 5, NUM}, {11, 2, NUM}}},
+
+ /* Basic branch mnemonics (assember extended mnemonics) */
+ /* { 0x42800000, "b", {{2,14,PCREL}} }, overlaps */
+ /* { 0x42800001, "bl", {{2,14,PCREL}} }, overlaps */
+ {0x41800000, "bt", {{16, 5, BCND}, {2, 14, PCREL}}},
+ {0x41800001, "btl", {{16, 5, BCND}, {2, 14, PCREL}}},
+ {0x40800000, "bf", {{16, 5, BCND}, {2, 14, PCREL}}},
+ {0x40800001, "bfl", {{16, 5, BCND}, {2, 14, PCREL}}},
+ {0x42000000, "bdnz", {{2, 14, PCREL}}},
+ {0x42000001, "bdnzl", {{2, 14, PCREL}}},
+ {0x41000000, "bdnzt", {{16, 5, BCND}, {2, 14, PCREL}}},
+ {0x41000001, "bdnztl", {{16, 5, BCND}, {2, 14, PCREL}}},
+ {0x40000000, "bdnzf", {{16, 5, BCND}, {2, 14, PCREL}}},
+ {0x40000001, "bdnzfl", {{16, 5, BCND}, {2, 14, PCREL}}},
+ {0x42400000, "bdz", {{2, 14, PCREL}}},
+ {0x42400001, "bdzl", {{2, 14, PCREL}}},
+ {0x41400000, "bdzt", {{16, 5, BCND}, {2, 14, PCREL}}},
+ {0x41400001, "bdztl", {{16, 5, BCND}, {2, 14, PCREL}}},
+ {0x40400000, "bdzf", {{16, 5, BCND}, {2, 14, PCREL}}},
+ {0x40400001, "bdzfl", {{16, 5, BCND}, {2, 14, PCREL}}},
+
+ /* { 0x42800002, "ba", {{2,14,BADDR}} }, overlaps */
+ /* { 0x42800003, "bla", {{2,14,BADDR}} }, overlaps */
+ {0x41800002, "bta", {{16, 5, BCND}, {2, 14, BADDR}}},
+ {0x41800003, "btla", {{16, 5, BCND}, {2, 14, BADDR}}},
+ {0x40800002, "bfa", {{16, 5, BCND}, {2, 14, BADDR}}},
+ {0x40800003, "bfla", {{16, 5, BCND}, {2, 14, BADDR}}},
+ {0x42000002, "bdnza", {{2, 14, BADDR}}},
+ {0x42000003, "bdnzla", {{2, 14, BADDR}}},
+ {0x41000002, "bdnzta", {{16, 5, BCND}, {2, 14, BADDR}}},
+ {0x41000003, "bdnztla", {{16, 5, BCND}, {2, 14, BADDR}}},
+ {0x40000002, "bdnzfa", {{16, 5, BCND}, {2, 14, BADDR}}},
+ {0x40000003, "bdnzfla", {{16, 5, BCND}, {2, 14, BADDR}}},
+ {0x42400002, "bdza", {{2, 14, BADDR}}},
+ {0x42400003, "bdzla", {{2, 14, BADDR}}},
+ {0x41400002, "bdzta", {{16, 5, BCND}, {2, 14, BADDR}}},
+ {0x41400003, "bdztla", {{16, 5, BCND}, {2, 14, BADDR}}},
+ {0x40400002, "bdzfa", {{16, 5, BCND}, {2, 14, BADDR}}},
+ {0x40400003, "bdzfla", {{16, 5, BCND}, {2, 14, BADDR}}},
+
+ {
+ 0x4e800020,
+ "blr",
+ },
+ {0x4e800020, "blr", {{11, 2, NUM}}},
+ {
+ 0x4e800021,
+ "blrl",
+ },
+ {0x4e800021, "blrl", {{11, 2, NUM}}},
+ {0x4d800020, "btlr", {{16, 5, BCND}}},
+ {0x4d800020, "btlr", {{16, 5, BCND}, {11, 2, NUM}}},
+ {0x4d800021, "btlrl", {{16, 5, BCND}}},
+ {0x4d800021, "btlrl", {{16, 5, BCND}, {11, 2, NUM}}},
+ {0x4c800020, "bflr", {{16, 5, BCND}}},
+ {0x4c800020, "bflr", {{16, 5, BCND}, {11, 2, NUM}}},
+ {0x4c800021, "bflrl", {{16, 5, BCND}}},
+ {0x4c800021, "bflrl", {{16, 5, BCND}, {11, 2, NUM}}},
+ {
+ 0x4e000020,
+ "bdnzlr",
+ },
+ {0x4e000020, "bdnzlr", {{11, 2, NUM}}},
+ {
+ 0x4e000021,
+ "bdnzlrl",
+ },
+ {0x4e000021, "bdnzlrl", {{11, 2, NUM}}},
+ {0x4d000020, "bdnztlr", {{16, 5, BCND}}},
+ {0x4d000020, "bdnztlr", {{16, 5, BCND}, {11, 2, NUM}}},
+ {0x4d000021, "bdnztlrl", {{16, 5, BCND}}},
+ {0x4d000021, "bdnztlrl", {{16, 5, BCND}, {11, 2, NUM}}},
+ {0x4c000020, "bdnzflr", {{16, 5, BCND}}},
+ {0x4c000020, "bdnzflr", {{16, 5, BCND}, {11, 2, NUM}}},
+ {0x4c000021, "bdnzflrl", {{16, 5, BCND}}},
+ {0x4c000021, "bdnzflrl", {{16, 5, BCND}, {11, 2, NUM}}},
+ {
+ 0x4e400020,
+ "bdzlr",
+ },
+ {0x4e400020, "bdzlr", {{11, 2, NUM}}},
+ {
+ 0x4e400021,
+ "bdzlrl",
+ },
+ {0x4e400021, "bdzlrl", {{11, 2, NUM}}},
+ {0x4d400020, "bdztlr", {{16, 5, BCND}}},
+ {0x4d400020, "bdztlr", {{16, 5, BCND}, {11, 2, NUM}}},
+ {0x4d400021, "bdztlrl", {{16, 5, BCND}}},
+ {0x4d400021, "bdztlrl", {{16, 5, BCND}, {11, 2, NUM}}},
+ {0x4c400020, "bdzflr", {{16, 5, BCND}}},
+ {0x4c400020, "bdzflr", {{16, 5, BCND}, {11, 2, NUM}}},
+ {0x4c400021, "bdzflrl", {{16, 5, BCND}}},
+ {0x4c400021, "bdzflrl", {{16, 5, BCND}, {11, 2, NUM}}},
+
+ {0x4c000420, "bctr", {{21, 5, NUM}, {16, 5, NUM}}},
+ {
+ 0x4e800420,
+ "bctr",
+ },
+ {0x4e800420, "bctr", {{11, 2, NUM}}},
+ {0x4c000421, "bctrl", {{21, 5, NUM}, {16, 5, NUM}}},
+ {
+ 0x4e800421,
+ "bctrl",
+ },
+ {0x4e800421, "bctrl", {{11, 2, NUM}}},
+ {0x4d800420, "btctr", {{16, 5, BCND}}},
+ {0x4d800420, "btctr", {{16, 5, BCND}, {11, 2, NUM}}},
+ {0x4d800421, "btctrl", {{16, 5, BCND}}},
+ {0x4d800421, "btctrl", {{16, 5, BCND}, {11, 2, NUM}}},
+ {0x4c800420, "bfctr", {{16, 5, BCND}}},
+ {0x4c800420, "bfctr", {{16, 5, BCND}, {11, 2, NUM}}},
+ {0x4c800421, "bfctrl", {{16, 5, BCND}}},
+ {0x4c800421, "bfctrl", {{16, 5, BCND}, {11, 2, NUM}}},
+
+ /* branch mnemonics incorporating conditions (assember extended mnemonics)
+ */
+ {0x41800000, "blt", {{16, 5, CRF}, {2, 14, PCREL}}},
+ {0x41800000, "blt", {{2, 14, PCREL}}},
+ {0x41800001, "bltl", {{16, 5, CRF}, {2, 14, PCREL}}},
+ {0x41800001, "bltl", {{2, 14, PCREL}}},
+ {0x40810000, "ble", {{16, 5, CRF}, {2, 14, PCREL}}},
+ {0x40810000, "ble", {{2, 14, PCREL}}},
+ {0x40810001, "blel", {{16, 5, CRF}, {2, 14, PCREL}}},
+ {0x40810001, "blel", {{2, 14, PCREL}}},
+ {0x41820000, "beq", {{16, 5, CRF}, {2, 14, PCREL}}},
+ {0x41820000, "beq", {{2, 14, PCREL}}},
+ {0x41820001, "beql", {{16, 5, CRF}, {2, 14, PCREL}}},
+ {0x41820001, "beql", {{2, 14, PCREL}}},
+ {0x40800000, "bge", {{16, 5, CRF}, {2, 14, PCREL}}},
+ {0x40800000, "bge", {{2, 14, PCREL}}},
+ {0x40800001, "bgel", {{16, 5, CRF}, {2, 14, PCREL}}},
+ {0x40800001, "bgel", {{2, 14, PCREL}}},
+ {0x41810000, "bgt", {{16, 5, CRF}, {2, 14, PCREL}}},
+ {0x41810000, "bgt", {{2, 14, PCREL}}},
+ {0x41810001, "bgtl", {{16, 5, CRF}, {2, 14, PCREL}}},
+ {0x41810001, "bgtl", {{2, 14, PCREL}}},
+ {0x40800000, "bnl", {{16, 5, CRF}, {2, 14, PCREL}}},
+ {0x40800000, "bnl", {{2, 14, PCREL}}},
+ {0x40800001, "bnll", {{16, 5, CRF}, {2, 14, PCREL}}},
+ {0x40800001, "bnll", {{2, 14, PCREL}}},
+ {0x40820000, "bne", {{16, 5, CRF}, {2, 14, PCREL}}},
+ {0x40820000, "bne", {{2, 14, PCREL}}},
+ {0x40820001, "bnel", {{16, 5, CRF}, {2, 14, PCREL}}},
+ {0x40820001, "bnel", {{2, 14, PCREL}}},
+ {0x40810000, "bng", {{16, 5, CRF}, {2, 14, PCREL}}},
+ {0x40810000, "bng", {{2, 14, PCREL}}},
+ {0x40810001, "bngl", {{16, 5, CRF}, {2, 14, PCREL}}},
+ {0x40810001, "bngl", {{2, 14, PCREL}}},
+ {0x41830000, "bso", {{16, 5, CRF}, {2, 14, PCREL}}},
+ {0x41830000, "bso", {{2, 14, PCREL}}},
+ {0x41830001, "bsol", {{16, 5, CRF}, {2, 14, PCREL}}},
+ {0x41830001, "bsol", {{2, 14, PCREL}}},
+ {0x40830000, "bns", {{16, 5, CRF}, {2, 14, PCREL}}},
+ {0x40830000, "bns", {{2, 14, PCREL}}},
+ {0x40830001, "bnsl", {{16, 5, CRF}, {2, 14, PCREL}}},
+ {0x40830001, "bnsl", {{2, 14, PCREL}}},
+ {0x41830000, "bun", {{16, 5, CRF}, {2, 14, PCREL}}},
+ {0x41830000, "bun", {{2, 14, PCREL}}},
+ {0x41830001, "bunl", {{16, 5, CRF}, {2, 14, PCREL}}},
+ {0x41830001, "bunl", {{2, 14, PCREL}}},
+ {0x40830000, "bnu", {{16, 5, CRF}, {2, 14, PCREL}}},
+ {0x40830000, "bnu", {{2, 14, PCREL}}},
+ {0x40830001, "bnul", {{16, 5, CRF}, {2, 14, PCREL}}},
+ {0x40830001, "bnul", {{2, 14, PCREL}}},
+
+ {0x41800002, "blta", {{16, 5, CRF}, {2, 14, BADDR}}},
+ {0x41800002, "blta", {{2, 14, BADDR}}},
+ {0x41800003, "bltla", {{16, 5, CRF}, {2, 14, BADDR}}},
+ {0x41800003, "bltla", {{2, 14, BADDR}}},
+ {0x40810002, "blea", {{16, 5, CRF}, {2, 14, BADDR}}},
+ {0x40810002, "blea", {{2, 14, BADDR}}},
+ {0x40810003, "blela", {{16, 5, CRF}, {2, 14, BADDR}}},
+ {0x40810003, "blela", {{2, 14, BADDR}}},
+ {0x41820002, "beqa", {{16, 5, CRF}, {2, 14, BADDR}}},
+ {0x41820002, "beqa", {{2, 14, BADDR}}},
+ {0x41820003, "beqla", {{16, 5, CRF}, {2, 14, BADDR}}},
+ {0x41820003, "beqla", {{2, 14, BADDR}}},
+ {0x40800002, "bgea", {{16, 5, CRF}, {2, 14, BADDR}}},
+ {0x40800002, "bgea", {{2, 14, BADDR}}},
+ {0x40800003, "bgela", {{16, 5, CRF}, {2, 14, BADDR}}},
+ {0x40800003, "bgela", {{2, 14, BADDR}}},
+ {0x41810002, "bgta", {{16, 5, CRF}, {2, 14, BADDR}}},
+ {0x41810002, "bgta", {{2, 14, BADDR}}},
+ {0x41810003, "bgtla", {{16, 5, CRF}, {2, 14, BADDR}}},
+ {0x41810003, "bgtla", {{2, 14, BADDR}}},
+ {0x40800002, "bnla", {{16, 5, CRF}, {2, 14, BADDR}}},
+ {0x40800002, "bnla", {{2, 14, BADDR}}},
+ {0x40800003, "bnlla", {{16, 5, CRF}, {2, 14, BADDR}}},
+ {0x40800003, "bnlla", {{2, 14, BADDR}}},
+ {0x40820002, "bnea", {{16, 5, CRF}, {2, 14, BADDR}}},
+ {0x40820002, "bnea", {{2, 14, BADDR}}},
+ {0x40820003, "bnela", {{16, 5, CRF}, {2, 14, BADDR}}},
+ {0x40820003, "bnela", {{2, 14, BADDR}}},
+ {0x40810002, "bnga", {{16, 5, CRF}, {2, 14, BADDR}}},
+ {0x40810002, "bnga", {{2, 14, BADDR}}},
+ {0x40810003, "bngla", {{16, 5, CRF}, {2, 14, BADDR}}},
+ {0x40810003, "bngla", {{2, 14, BADDR}}},
+ {0x41830002, "bsoa", {{16, 5, CRF}, {2, 14, BADDR}}},
+ {0x41830002, "bsoa", {{2, 14, BADDR}}},
+ {0x41830003, "bsola", {{16, 5, CRF}, {2, 14, BADDR}}},
+ {0x41830003, "bsola", {{2, 14, BADDR}}},
+ {0x40830002, "bnsa", {{16, 5, CRF}, {2, 14, BADDR}}},
+ {0x40830002, "bnsa", {{2, 14, BADDR}}},
+ {0x40830003, "bnsla", {{16, 5, CRF}, {2, 14, BADDR}}},
+ {0x40830003, "bnsla", {{2, 14, BADDR}}},
+ {0x41830002, "buna", {{16, 5, CRF}, {2, 14, BADDR}}},
+ {0x41830002, "buna", {{2, 14, BADDR}}},
+ {0x41830003, "bunla", {{16, 5, CRF}, {2, 14, BADDR}}},
+ {0x41830003, "bunla", {{2, 14, BADDR}}},
+ {0x40830002, "bnua", {{16, 5, CRF}, {2, 14, BADDR}}},
+ {0x40830002, "bnua", {{2, 14, BADDR}}},
+ {0x40830003, "bnula", {{16, 5, CRF}, {2, 14, BADDR}}},
+ {0x40830003, "bnula", {{2, 14, BADDR}}},
+
+ {0x4d800020, "bltlr", {{16, 5, CRF}}},
+ {0x4d800020, "bltlr", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4d800020,
+ "bltlr",
+ },
+ {0x4d800021, "bltlrl", {{16, 5, CRF}}},
+ {0x4d800021, "bltlrl", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4d800021,
+ "bltlrl",
+ },
+ {0x4c810020, "blelr", {{16, 5, CRF}}},
+ {0x4c810020, "blelr", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4c810020,
+ "blelr",
+ },
+ {0x4c810021, "blelrl", {{16, 5, CRF}}},
+ {0x4c810021, "blelrl", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4c810021,
+ "blelrl",
+ },
+ {0x4d820020, "beqlr", {{16, 5, CRF}}},
+ {0x4d820020, "beqlr", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4d820020,
+ "beqlr",
+ },
+ {0x4d820021, "beqlrl", {{16, 5, CRF}}},
+ {0x4d820021, "beqlrl", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4d820021,
+ "beqlrl",
+ },
+ {0x4c800020, "bgelr", {{16, 5, CRF}}},
+ {0x4c800020, "bgelr", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4c800020,
+ "bgelr",
+ },
+ {0x4c800021, "bgelrl", {{16, 5, CRF}}},
+ {0x4c800021, "bgelrl", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4c800021,
+ "bgelrl",
+ },
+ {0x4d810020, "bgtlr", {{16, 5, CRF}}},
+ {0x4d810020, "bgtlr", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4d810020,
+ "bgtlr",
+ },
+ {0x4d810021, "bgtlrl", {{16, 5, CRF}}},
+ {0x4d810021, "bgtlrl", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4d810021,
+ "bgtlrl",
+ },
+ {0x4c800020, "bnllr", {{16, 5, CRF}}},
+ {0x4c800020, "bnllr", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4c800020,
+ "bnllr",
+ },
+ {0x4c800021, "bnllrl", {{16, 5, CRF}}},
+ {0x4c800021, "bnllrl", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4c800021,
+ "bnllrl",
+ },
+ {0x4c820020, "bnelr", {{16, 5, CRF}}},
+ {0x4c820020, "bnelr", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4c820020,
+ "bnelr",
+ },
+ {0x4c820021, "bnelrl", {{16, 5, CRF}}},
+ {0x4c820021, "bnelrl", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4c820021,
+ "bnelrl",
+ },
+ {0x4c810020, "bnglr", {{16, 5, CRF}}},
+ {0x4c810020, "bnglr", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4c810020,
+ "bnglr",
+ },
+ {0x4c810021, "bnglrl", {{16, 5, CRF}}},
+ {0x4c810021, "bnglrl", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4c810021,
+ "bnglrl",
+ },
+ {0x4d830020, "bsolr", {{16, 5, CRF}}},
+ {0x4d830020, "bsolr", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4d830020,
+ "bsolr",
+ },
+ {0x4d830021, "bsolrl", {{16, 5, CRF}}},
+ {0x4d830021, "bsolrl", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4d830021,
+ "bsolrl",
+ },
+ {0x4c830020, "bnslr", {{16, 5, CRF}}},
+ {0x4c830020, "bnslr", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4c830020,
+ "bnslr",
+ },
+ {0x4c830021, "bnslrl", {{16, 5, CRF}}},
+ {0x4c830021, "bnslrl", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4c830021,
+ "bnslrl",
+ },
+ {0x4d830020, "bunlr", {{16, 5, CRF}}},
+ {0x4d830020, "bunlr", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4d830020,
+ "bunlr",
+ },
+ {0x4d830021, "bunlrl", {{16, 5, CRF}}},
+ {0x4d830021, "bunlrl", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4d830021,
+ "bunlrl",
+ },
+ {0x4c830020, "bnulr", {{16, 5, CRF}}},
+ {0x4c830020, "bnulr", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4c830020,
+ "bnulr",
+ },
+ {0x4c830021, "bnulrl", {{16, 5, CRF}}},
+ {0x4c830021, "bnulrl", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4c830021,
+ "bnulrl",
+ },
+
+ {0x4d800420, "bltctr", {{16, 5, CRF}}},
+ {0x4d800420, "bltctr", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4d800420,
+ "bltctr",
+ },
+ {0x4d800421, "bltctrl", {{16, 5, CRF}}},
+ {0x4d800421, "bltctrl", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4d800421,
+ "bltctrl",
+ },
+ {0x4c810420, "blectr", {{16, 5, CRF}}},
+ {0x4c810420, "blectr", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4c810420,
+ "blectr",
+ },
+ {0x4c810421, "blectrl", {{16, 5, CRF}}},
+ {0x4c810421, "blectrl", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4c810421,
+ "blectrl",
+ },
+ {0x4d820420, "beqctr", {{16, 5, CRF}}},
+ {0x4d820420, "beqctr", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4d820420,
+ "beqctr",
+ },
+ {0x4d820421, "beqctrl", {{16, 5, CRF}}},
+ {0x4d820421, "beqctrl", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4d820421,
+ "beqctrl",
+ },
+ {0x4c800420, "bgectr", {{16, 5, CRF}}},
+ {0x4c800420, "bgectr", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4c800420,
+ "bgectr",
+ },
+ {0x4c800421, "bgectrl", {{16, 5, CRF}}},
+ {0x4c800421, "bgectrl", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4c800421,
+ "bgectrl",
+ },
+ {0x4d810420, "bgtctr", {{16, 5, CRF}}},
+ {0x4d810420, "bgtctr", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4d810420,
+ "bgtctr",
+ },
+ {0x4d810421, "bgtctrl", {{16, 5, CRF}}},
+ {0x4d810421, "bgtctrl", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4d810421,
+ "bgtctrl",
+ },
+ {0x4c800420, "bnlctr", {{16, 5, CRF}}},
+ {0x4c800420, "bnlctr", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4c800420,
+ "bnlctr",
+ },
+ {0x4c800421, "bnlctrl", {{16, 5, CRF}}},
+ {0x4c800421, "bnlctrl", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4c800421,
+ "bnlctrl",
+ },
+ {0x4c820420, "bnectr", {{16, 5, CRF}}},
+ {0x4c820420, "bnectr", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4c820420,
+ "bnectr",
+ },
+ {0x4c820421, "bnectrl", {{16, 5, CRF}}},
+ {0x4c820421, "bnectrl", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4c820421,
+ "bnectrl",
+ },
+ {0x4c810420, "bngctr", {{16, 5, CRF}}},
+ {0x4c810420, "bngctr", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4c810420,
+ "bngctr",
+ },
+ {0x4c810421, "bngctrl", {{16, 5, CRF}}},
+ {0x4c810421, "bngctrl", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4c810421,
+ "bngctrl",
+ },
+ {0x4d830420, "bsoctr", {{16, 5, CRF}}},
+ {0x4d830420, "bsoctr", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4d830420,
+ "bsoctr",
+ },
+ {0x4d830421, "bsoctrl", {{16, 5, CRF}}},
+ {0x4d830421, "bsoctrl", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4d830421,
+ "bsoctrl",
+ },
+ {0x4c830420, "bnsctr", {{16, 5, CRF}}},
+ {0x4c830420, "bnsctr", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4c830420,
+ "bnsctr",
+ },
+ {0x4c830421, "bnsctrl", {{16, 5, CRF}}},
+ {0x4c830421, "bnsctrl", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4c830421,
+ "bnsctrl",
+ },
+ {0x4d830420, "bunctr", {{16, 5, CRF}}},
+ {0x4d830420, "bunctr", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4d830420,
+ "bunctr",
+ },
+ {0x4d830421, "bunctrl", {{16, 5, CRF}}},
+ {0x4d830421, "bunctrl", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4d830421,
+ "bunctrl",
+ },
+ {0x4c830420, "bnuctr", {{16, 5, CRF}}},
+ {0x4c830420, "bnuctr", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4c830420,
+ "bnuctr",
+ },
+ {0x4c830421, "bnuctrl", {{16, 5, CRF}}},
+ {0x4c830421, "bnuctrl", {{16, 5, CRF}, {11, 2, NUM}}},
+ {
+ 0x4c830421,
+ "bnuctrl",
+ },
+
+ {0x2c000000, "cmpi", {{21, 5, CRFONLY}, {16, 5, GREG}, {0, 16, SI}}},
+ {0x2c000000, "cmpi", {{21, 5, CRFONLY}, {21, 1, NUM}, {16, 5, GREG}, {0, 16, SI}}},
+ {0x2c000000, "cmpi", {{23, 3, NUM}, {16, 5, GREG}, {0, 16, SI}}},
+ {0x2c000000, "cmpi", {{23, 3, NUM}, {21, 1, NUM}, {16, 5, GREG}, {0, 16, SI}}},
+ {0x2c000000, "cmpwi", {{16, 5, GREG}, {0, 16, SI}}},
+ {0x2c000000, "cmpwi", {{21, 5, CRFONLY}, {16, 5, GREG}, {0, 16, SI}}},
+ {0x2c000000, "cmpwi", {{23, 3, NUM}, {16, 5, GREG}, {0, 16, SI}}},
+ {0x2c200000, "cmpdi", {{16, 5, GREG}, {0, 16, SI}}},
+ {0x2c200000, "cmpdi", {{21, 5, CRFONLY}, {16, 5, GREG}, {0, 16, SI}}},
+ {0x2c200000, "cmpdi", {{23, 3, NUM}, {16, 5, GREG}, {0, 16, SI}}},
+
+ {0x7c000000, "cmp", {{21, 5, CRFONLY}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000000, "cmp", {{21, 5, CRFONLY}, {21, 1, NUM}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000000, "cmp", {{23, 3, NUM}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000000, "cmp", {{23, 3, NUM}, {21, 1, NUM}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000000, "cmpw", {{16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000000, "cmpw", {{21, 5, CRFONLY}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000000, "cmpw", {{23, 3, NUM}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c200000, "cmpd", {{16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c200000, "cmpd", {{21, 5, CRFONLY}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c200000, "cmpd", {{23, 3, NUM}, {16, 5, GREG}, {11, 5, GREG}}},
+
+ {0x28000000, "cmpli", {{21, 5, CRFONLY}, {16, 5, GREG}, {0, 16, UI}}},
+ {0x28000000, "cmpli", {{21, 5, CRFONLY}, {21, 1, NUM}, {16, 5, GREG}, {0, 16, UI}}},
+ {0x28000000, "cmpli", {{23, 3, NUM}, {16, 5, GREG}, {0, 16, UI}}},
+ {0x28000000, "cmpli", {{23, 3, NUM}, {21, 1, NUM}, {16, 5, GREG}, {0, 16, UI}}},
+ {0x28000000, "cmplwi", {{16, 5, GREG}, {0, 16, UI}}},
+ {0x28000000, "cmplwi", {{21, 5, CRFONLY}, {16, 5, GREG}, {0, 16, UI}}},
+ {0x28000000, "cmplwi", {{23, 3, NUM}, {16, 5, GREG}, {0, 16, UI}}},
+ {0x28200000, "cmpldi", {{16, 5, GREG}, {0, 16, UI}}},
+ {0x28200000, "cmpldi", {{21, 5, CRFONLY}, {16, 5, GREG}, {0, 16, UI}}},
+ {0x28200000, "cmpldi", {{23, 3, NUM}, {16, 5, GREG}, {0, 16, UI}}},
+
+ {0x7c000040, "cmpl", {{21, 5, CRFONLY}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000040, "cmpl", {{21, 5, CRFONLY}, {21, 1, NUM}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000040, "cmpl", {{23, 3, NUM}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000040, "cmpl", {{23, 3, NUM}, {21, 1, NUM}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000040, "cmplw", {{16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000040, "cmplw", {{21, 5, CRFONLY}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000040, "cmplw", {{23, 3, NUM}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c200040, "cmpld", {{16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c200040, "cmpld", {{21, 5, CRFONLY}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c200040, "cmpld", {{23, 3, NUM}, {16, 5, GREG}, {11, 5, GREG}}},
+
+ {0x7c000034, "cntlzw", {{16, 5, GREG}, {21, 5, GREG}}},
+ {0x7c000035, "cntlzw.", {{16, 5, GREG}, {21, 5, GREG}}},
+ {0x7c000074, "cntlzd", {{16, 5, GREG}, {21, 5, GREG}}, IMPL64},
+ {0x7c000075, "cntlzd.", {{16, 5, GREG}, {21, 5, GREG}}, IMPL64},
+
+ {0x4c000202, "crand", {{21, 5, NUM}, {16, 5, NUM}, {11, 5, NUM}}},
+ {0x4c000102, "crandc", {{21, 5, NUM}, {16, 5, NUM}, {11, 5, NUM}}},
+ {0x4c000242, "creqv", {{21, 5, NUM}, {16, 5, NUM}, {11, 5, NUM}}},
+ {0x4c0001c2, "crnand", {{21, 5, NUM}, {16, 5, NUM}, {11, 5, NUM}}},
+ {0x4c000042, "crnor", {{21, 5, NUM}, {16, 5, NUM}, {11, 5, NUM}}},
+ {0x4c000382, "cror", {{21, 5, NUM}, {16, 5, NUM}, {11, 5, NUM}}},
+ {0x4c000342, "crorc", {{21, 5, NUM}, {16, 5, NUM}, {11, 5, NUM}}},
+ {0x4c000182, "crxor", {{21, 5, NUM}, {16, 5, NUM}, {11, 5, NUM}}},
+
+ {0x7c0003d2, "divd", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+ {0x7c0003d3, "divd.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+ {0x7c0007d2, "divdo", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+ {0x7c0007d3, "divdo.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+
+ {0x7c000392, "divdu", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+ {0x7c000393, "divdu.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+ {0x7c000792, "divduo", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+ {0x7c000793, "divduo.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+
+ {0x7c0003d6, "divw", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c0003d7, "divw.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c0007d6, "divwo", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c0007d7, "divwo.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+
+ {0x7c000396, "divwu", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000397, "divwu.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000796, "divwuo", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000797, "divwuo.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+
+ {0x7c000238, "eqv", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000239, "eqv.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
+
+ {0x7c000774, "extsb", {{16, 5, GREG}, {21, 5, GREG}}},
+ {0x7c000775, "extsb.", {{16, 5, GREG}, {21, 5, GREG}}},
+ {0x7c000734, "extsh", {{16, 5, GREG}, {21, 5, GREG}}},
+ {0x7c000735, "extsh.", {{16, 5, GREG}, {21, 5, GREG}}},
+ {0x7c0007b4, "extsw", {{16, 5, GREG}, {21, 5, GREG}}, IMPL64},
+ {0x7c0007b5, "extsw.", {{16, 5, GREG}, {21, 5, GREG}}, IMPL64},
+
+ {0xfc00002a, "fadd", {{21, 5, FREG}, {16, 5, FREG}, {11, 5, FREG}}},
+ {0xfc00002b, "fadd.", {{21, 5, FREG}, {16, 5, FREG}, {11, 5, FREG}}},
+ {0xec00002a, "fadds", {{21, 5, FREG}, {16, 5, FREG}, {11, 5, FREG}}},
+ {0xec00002b, "fadds.", {{21, 5, FREG}, {16, 5, FREG}, {11, 5, FREG}}},
+ {0xfc000028, "fsub", {{21, 5, FREG}, {16, 5, FREG}, {11, 5, FREG}}},
+ {0xfc000029, "fsub.", {{21, 5, FREG}, {16, 5, FREG}, {11, 5, FREG}}},
+ {0xec000028, "fsubs", {{21, 5, FREG}, {16, 5, FREG}, {11, 5, FREG}}},
+ {0xec000029, "fsubs.", {{21, 5, FREG}, {16, 5, FREG}, {11, 5, FREG}}},
+ {0xfc000032, "fmul", {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}}},
+ {0xfc000033, "fmul.", {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}}},
+ {0xec000032, "fmuls", {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}}},
+ {0xec000033, "fmuls.", {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}}},
+ {0xfc000024, "fdiv", {{21, 5, FREG}, {16, 5, FREG}, {11, 5, FREG}}},
+ {0xfc000025, "fdiv.", {{21, 5, FREG}, {16, 5, FREG}, {11, 5, FREG}}},
+ {0xec000024, "fdivs", {{21, 5, FREG}, {16, 5, FREG}, {11, 5, FREG}}},
+ {0xec000025, "fdivs.", {{21, 5, FREG}, {16, 5, FREG}, {11, 5, FREG}}},
+
+ {0xfc00003a, "fmadd", {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
+ {0xfc00003b, "fmadd.", {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
+ {0xec00003a, "fmadds", {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
+ {0xec00003b, "fmadds.", {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
+ {0xfc000038, "fmsub", {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
+ {0xfc000039, "fmsub.", {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
+ {0xec000038, "fmsubs", {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
+ {0xec000039, "fmsubs.", {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
+ {0xfc00003e, "fnmadd", {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
+ {0xfc00003f, "fnmadd.", {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
+ {0xec00003e, "fnmadds", {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
+ {0xec00003f, "fnmadds.", {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
+ {0xfc00003c, "fnmsub", {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
+ {0xfc00003d, "fnmsub.", {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
+ {0xec00003c, "fnmsubs", {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
+ {0xec00003d, "fnmsubs.", {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
+
+ {0xfc000090, "fmr", {{21, 5, FREG}, {11, 5, FREG}}},
+ {0xfc000091, "fmr.", {{21, 5, FREG}, {11, 5, FREG}}},
+ {0xfc000210, "fabs", {{21, 5, FREG}, {11, 5, FREG}}},
+ {0xfc000211, "fabs.", {{21, 5, FREG}, {11, 5, FREG}}},
+ {0xfc000050, "fneg", {{21, 5, FREG}, {11, 5, FREG}}},
+ {0xfc000051, "fneg.", {{21, 5, FREG}, {11, 5, FREG}}},
+ {0xfc000110, "fnabs", {{21, 5, FREG}, {11, 5, FREG}}},
+ {0xfc000111, "fnabs.", {{21, 5, FREG}, {11, 5, FREG}}},
+ {0xec000030, "fres", {{21, 5, FREG}, {11, 5, FREG}}},
+ {0xec000031, "fres.", {{21, 5, FREG}, {11, 5, FREG}}},
+ {0xfc000018, "frsp", {{21, 5, FREG}, {11, 5, FREG}}},
+ {0xfc000019, "frsp.", {{21, 5, FREG}, {11, 5, FREG}}},
+ {0xfc000034, "frsqrte", {{21, 5, FREG}, {11, 5, FREG}}},
+ {0xfc000035, "frsqrte.", {{21, 5, FREG}, {11, 5, FREG}}},
+ {0xfc00002e, "fsel", {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
+ {0xfc00002f, "fsel.", {{21, 5, FREG}, {16, 5, FREG}, {6, 5, FREG}, {11, 5, FREG}}},
+ {0xfc00002c, "fsqrt", {{21, 5, FREG}, {11, 5, FREG}}, OPTIONAL | CPU970},
+ {0xfc00002d, "fsqrt.", {{21, 5, FREG}, {11, 5, FREG}}, OPTIONAL | CPU970},
+ {0xec00002c, "fsqrts", {{21, 5, FREG}, {11, 5, FREG}}, OPTIONAL | CPU970},
+ {0xec00002d, "fsqrts.", {{21, 5, FREG}, {11, 5, FREG}}, OPTIONAL | CPU970},
+ {0xfc00065c, "fctid", {{21, 5, FREG}, {11, 5, FREG}}, IMPL64},
+ {0xfc00065d, "fctid.", {{21, 5, FREG}, {11, 5, FREG}}, IMPL64},
+ {0xfc00065e, "fctidz", {{21, 5, FREG}, {11, 5, FREG}}, IMPL64},
+ {0xfc00065f, "fctidz.", {{21, 5, FREG}, {11, 5, FREG}}, IMPL64},
+ {0xfc00001c, "fctiw", {{21, 5, FREG}, {11, 5, FREG}}},
+ {0xfc00001d, "fctiw.", {{21, 5, FREG}, {11, 5, FREG}}},
+ {0xfc00001e, "fctiwz", {{21, 5, FREG}, {11, 5, FREG}}},
+ {0xfc00001f, "fctiwz.", {{21, 5, FREG}, {11, 5, FREG}}},
+ {0xfc00069c, "fcfid", {{21, 5, FREG}, {11, 5, FREG}}, IMPL64},
+ {0xfc00069d, "fcfid.", {{21, 5, FREG}, {11, 5, FREG}}, IMPL64},
+
+ {0xfc000000, "fcmpu", {{21, 5, CRFONLY}, {16, 5, FREG}, {11, 5, FREG}}},
+ {0xfc000000, "fcmpu", {{23, 3, NUM}, {16, 5, FREG}, {11, 5, FREG}}},
+ {0xfc000040, "fcmpo", {{21, 5, CRFONLY}, {16, 5, FREG}, {11, 5, FREG}}},
+ {0xfc000040, "fcmpo", {{23, 3, NUM}, {16, 5, FREG}, {11, 5, FREG}}},
+ {0xfc00048e, "mffs", {{21, 5, FREG}}},
+ {0xfc00048f, "mffs.", {{21, 5, FREG}}},
+ {0xfc000080, "mcrfs", {{21, 5, CRFONLY}, {18, 5, NUM}}},
+ {0xfc000080, "mcrfs", {{23, 3, NUM}, {18, 5, NUM}}},
+ {0xfc00010c, "mtfsfi", {{23, 3, NUM}, {12, 4, NUM}}},
+ {0xfc00010d, "mtfsfi.", {{23, 3, NUM}, {12, 4, NUM}}},
+ {0xfc00058e, "mtfsf", {{17, 8, NUM}, {11, 5, FREG}}},
+ {0xfc00058f, "mtfsf.", {{17, 8, NUM}, {11, 5, FREG}}},
+ {0xfc00008c, "mtfsb0", {{21, 5, NUM}}},
+ {0xfc00008d, "mtfsb0.", {{21, 5, NUM}}},
+ {0xfc00004c, "mtfsb1", {{21, 5, NUM}}},
+ {0xfc00004d, "mtfsb1.", {{21, 5, NUM}}},
+
+ {0x88000000, "lbz", {{21, 5, GREG}, {0, 16, D}, {16, 5, G0REG}}},
+ {0x7c0000ae, "lbzx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
+ {0x8c000000, "lbzu", {{21, 5, GREG}, {0, 16, D}, {16, 5, G0REG}}},
+ {0x7c0000ee, "lbzux", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0xa0000000, "lhz", {{21, 5, GREG}, {0, 16, D}, {16, 5, G0REG}}},
+ {0x7c00022e, "lhzx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
+ {0xa4000000, "lhzu", {{21, 5, GREG}, {0, 16, D}, {16, 5, G0REG}}},
+ {0x7c00026e, "lhzux", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0xa8000000, "lha", {{21, 5, GREG}, {0, 16, D}, {16, 5, G0REG}}},
+ {0x7c0002ae, "lhax", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
+ {0xac000000, "lhau", {{21, 5, GREG}, {0, 16, D}, {16, 5, GREG}}},
+ {0x7c0002ee, "lhaux", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x80000000, "lwz", {{21, 5, GREG}, {0, 16, D}, {16, 5, G0REG}}},
+ {0x7c00002e, "lwzx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
+ {0x84000000, "lwzu", {{21, 5, GREG}, {0, 16, D}, {16, 5, GREG}}},
+ {0x7c00006e, "lwzux", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0xe8000002, "lwa", {{21, 5, GREG}, {2, 14, DS}, {16, 5, G0REG}}, IMPL64},
+ {0x7c0002aa, "lwax", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}, IMPL64},
+ {0x7c0002ea, "lwaux", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+ {0xe8000000, "ld", {{21, 5, GREG}, {2, 14, DS}, {16, 5, G0REG}}, IMPL64},
+ {0x7c00002a, "ldx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}, IMPL64},
+ {0xe8000001, "ldu", {{21, 5, GREG}, {2, 14, DS}, {16, 5, GREG}}, IMPL64},
+ {0x7c00006a, "ldux", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+
+ {0xb8000000, "lmw", {{21, 5, GREG}, {0, 16, D}, {16, 5, G0REG}}},
+ {0xbc000000, "stmw", {{21, 5, GREG}, {0, 16, D}, {16, 5, G0REG}}},
+
+ {0x7c00062c, "lhbrx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
+ {0x7c00042c, "lwbrx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
+ {0x7c00042a, "lswx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
+ {0x7c000028, "lwarx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
+ {0x7c0000a8, "ldarx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}, IMPL64},
+
+ {0x7c00022a, "lscbx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}, CPU601},
+ {0x7c00022b, "lscbx.", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}, CPU601},
+
+ {0x7c0004aa, "lswi", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, NUM0}}},
+
+ {0xc0000000, "lfs", {{21, 5, FREG}, {0, 16, D}, {16, 5, G0REG}}},
+ {0xc4000000, "lfsu", {{21, 5, FREG}, {0, 16, D}, {16, 5, GREG}}},
+ {0x7c00042e, "lfsx", {{21, 5, FREG}, {16, 5, G0REG}, {11, 5, GREG}}},
+ {0x7c00046e, "lfsux", {{21, 5, FREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0xc8000000, "lfd", {{21, 5, FREG}, {0, 16, D}, {16, 5, G0REG}}},
+ {0xcc000000, "lfdu", {{21, 5, FREG}, {0, 16, D}, {16, 5, GREG}}},
+ {0x7c0004ae, "lfdx", {{21, 5, FREG}, {16, 5, G0REG}, {11, 5, GREG}}},
+ {0x7c0004ee, "lfdux", {{21, 5, FREG}, {16, 5, GREG}, {11, 5, GREG}}},
+
+ {0x38000000, "la", {{21, 5, GREG}, {0, 16, D}, {16, 5, G0REG}}},
+
+ {0x4c000000, "mcrf", {{21, 5, CRFONLY}, {16, 5, CRFONLY}}},
+ {0x4c000000, "mcrf", {{23, 3, NUM}, {18, 3, NUM}}},
+
+ {0x7c0002a6, "mfspr", {{21, 5, GREG}, {11, 10, SPREG}}},
+ {0x7c0003a6, "mtspr", {{11, 10, SPREG}, {21, 5, GREG}}},
+ {0x7c000120, "mtcrf", {{12, 8, FXM}, {21, 5, GREG}}},
+ {0x7c000120, "mtocrf", {{12, 8, FXM}, {21, 5, GREG}}},
+ {0x7c000400, "mcrxr", {{21, 5, CRFONLY}}},
+ {0x7c000400, "mcrxr", {{23, 3, NUM}}},
+ {0x7c000026, "mfcr", {{21, 5, GREG}}},
+ {0x7c100026, "mfcr", {{21, 5, GREG}, {12, 8, FXM}}},
+ {0x7c100026, "mfocrf", {{21, 5, GREG}, {12, 8, FXM}}},
+
+ /* Move to/from spr mnemonics (assember extended mnemonics) */
+ {0x7c0102a6, "mfxer", {{21, 5, GREG}}},
+ {0x7c0802a6, "mflr", {{21, 5, GREG}}},
+ {0x7c0902a6, "mfctr", {{21, 5, GREG}}},
+ {0x7c0103a6, "mtxer", {{21, 5, GREG}}},
+ {0x7c0803a6, "mtlr", {{21, 5, GREG}}},
+ {0x7c0903a6, "mtctr", {{21, 5, GREG}}},
+ {0x7c0002a6, "mfmq", {{21, 5, GREG}}},
+ {0x7c0502a6, "mfrtcl", {{21, 5, GREG}}},
+ {0x7c0402a6, "mfrtcu", {{21, 5, GREG}}},
+ {0x7c0003a6, "mtmq", {{21, 5, GREG}}},
+ {0x7c1503a6, "mtrtcl", {{21, 5, GREG}}},
+ {0x7c1403a6, "mtrtcu", {{21, 5, GREG}}},
#ifdef NRW_COMPILER
- {0x7c0001d6, "mull", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c0001d7, "mull.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c0005d6, "mullo", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c0005d7, "mullo.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c0001d6, "mull", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c0001d7, "mull.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c0005d6, "mullo", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c0005d7, "mullo.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
#endif /* NRW_COMPILER */
- {0x7c0001d6, "mullw", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c0001d7, "mullw.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c0005d6, "mullwo", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c0005d7, "mullwo.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
-
- {0x7c000092,
- "mulhd",
- {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}},
- IMPL64},
- {0x7c000093,
- "mulhd.",
- {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}},
- IMPL64},
+ {0x7c0001d6, "mullw", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c0001d7, "mullw.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c0005d6, "mullwo", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c0005d7, "mullwo.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+
+ {0x7c000092, "mulhd", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+ {0x7c000093, "mulhd.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, IMPL64},
#ifdef NRW_COMPILER
- {0x7c000096, "mulwd", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000097, "mulwd.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000096, "mulwd", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000097, "mulwd.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
#endif /* NRW_COMPILER */
- {0x7c000096, "mulhw", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000097, "mulhw.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
-
- {0x7c000012,
- "mulhdu",
- {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}},
- IMPL64},
- {0x7c000013,
- "mulhdu.",
- {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}},
- IMPL64},
-
- {0x7c000016, "mulhwu", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000017, "mulhwu.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
-
- {0x7c0001d2,
- "mulld",
- {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}},
- IMPL64},
- {0x7c0001d3,
- "mulld.",
- {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}},
- IMPL64},
- {0x7c0005d2,
- "mulldo",
- {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}},
- IMPL64},
- {0x7c0005d3,
- "mulldo.",
- {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}},
- IMPL64},
-
- {0x7c0003b8, "nand", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
- {0x7c0003b9, "nand.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
-
- {0x7c0000d0, "neg", {{21, 5, GREG}, {16, 5, GREG}}},
- {0x7c0000d1, "neg.", {{21, 5, GREG}, {16, 5, GREG}}},
- {0x7c0004d0, "nego", {{21, 5, GREG}, {16, 5, GREG}}},
- {0x7c0004d1, "nego.", {{21, 5, GREG}, {16, 5, GREG}}},
-
- {0x7c0000f8, "nor", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
- {0x7c0000f9, "nor.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
-
- /* Miscellaneous mnemonics (assember extended mnemonics) */
- {
- 0x60000000,
- "nop",
- },
-
- {0x60000000, "ori", {{16, 5, GREG}, {21, 5, GREG}, {0, 16, UI}}},
- {0x60000000, "ori", {{16, 5, ZERO}, {21, 5, ZERO}, {0, 16, ZERO}}},
- {0x64000000, "oris", {{16, 5, GREG}, {21, 5, GREG}, {0, 16, UI}}},
- {0x7c000378, "or", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
- {0x7c000379, "or.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
-
- /// @brief Move register
- {0x7c000378, "mr", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
-
- {0x7c000338, "orc", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
- {0x7c000339, "orc.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
-
- {0x78000000,
- "rldicl",
- {{16, 5, GREG}, {21, 5, GREG}, {0, 0, sh}, {0, 0, mb}},
- IMPL64},
- {0x78000001,
- "rldicl.",
- {{16, 5, GREG}, {21, 5, GREG}, {0, 0, sh}, {0, 0, mb}},
- IMPL64},
- {0x78000004,
- "rldicr",
- {{16, 5, GREG}, {21, 5, GREG}, {0, 0, sh}, {0, 0, mb}},
- IMPL64},
- {0x78000005,
- "rldicr.",
- {{16, 5, GREG}, {21, 5, GREG}, {0, 0, sh}, {0, 0, mb}},
- IMPL64},
- {0x78000008,
- "rldic",
- {{16, 5, GREG}, {21, 5, GREG}, {0, 0, sh}, {0, 0, mb}},
- IMPL64},
- {0x78000009,
- "rldic.",
- {{16, 5, GREG}, {21, 5, GREG}, {0, 0, sh}, {0, 0, mb}},
- IMPL64},
- {0x7800000c,
- "rldimi",
- {{16, 5, GREG}, {21, 5, GREG}, {0, 0, sh}, {0, 0, mb}},
- IMPL64},
- {0x7800000d,
- "rldimi.",
- {{16, 5, GREG}, {21, 5, GREG}, {0, 0, sh}, {0, 0, mb}},
- IMPL64},
- {0x78000010,
- "rldcl",
- {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}, {0, 0, mb}},
- IMPL64},
- {0x78000011,
- "rldcl.",
- {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}, {0, 0, mb}},
- IMPL64},
- {0x78000012,
- "rldcr",
- {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}, {0, 0, mb}},
- IMPL64},
- {0x78000013,
- "rldcr.",
- {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}, {0, 0, mb}},
- IMPL64},
-
- {0x54000000,
- "rlwinm",
- {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM0}, {6, 5, MBE}, {1, 5, MBE}}},
- {0x54000001,
- "rlwinm.",
- {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM0}, {6, 5, MBE}, {1, 5, MBE}}},
- {0x5c000000,
- "rlwnm",
- {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}, {6, 5, MBE}, {1, 5, MBE}}},
- {0x5c000001,
- "rlwnm.",
- {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}, {6, 5, MBE}, {1, 5, MBE}}},
- {0x50000000,
- "rlwimi",
- {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM0}, {6, 5, MBE}, {1, 5, MBE}}},
- {0x50000001,
- "rlwimi.",
- {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM0}, {6, 5, MBE}, {1, 5, MBE}}},
-
- {
- 0x44000002,
- "sc",
- },
- {0x4c000024, "rfid", {{0}}, IMPL64 | OPTIONAL},
-
- {0x7c000030, "slw", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
- {0x7c000031, "slw.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
- {0x7c000036, "sld", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, IMPL64},
- {0x7c000037, "sld.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, IMPL64},
-
- {0x7c000430, "srw", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
- {0x7c000431, "srw.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
- {0x7c000436, "srd", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, IMPL64},
- {0x7c000437, "srd.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, IMPL64},
-
- {0x7c000670, "srawi", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM}}},
- {0x7c000671, "srawi.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM}}},
- {0x7c000674, "sradi", {{16, 5, GREG}, {21, 5, GREG}, {0, 0, sh}}, IMPL64},
- {0x7c000675, "sradi.", {{16, 5, GREG}, {21, 5, GREG}, {0, 0, sh}}, IMPL64},
-
- {0x7c000630, "sraw", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
- {0x7c000631, "sraw.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
- {0x7c000634, "srad", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, IMPL64},
- {0x7c000635,
- "srad.",
- {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}},
- IMPL64},
-
- {0x98000000, "stb", {{21, 5, GREG}, {0, 16, D}, {16, 5, G0REG}}},
- {0x9c000000, "stbu", {{21, 5, GREG}, {0, 16, D}, {16, 5, GREG}}},
- {0x7c0001ae, "stbx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
- {0x7c0001ee, "stbux", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0xb0000000, "sth", {{21, 5, GREG}, {0, 16, D}, {16, 5, G0REG}}},
- {0xb4000000, "sthu", {{21, 5, GREG}, {0, 16, D}, {16, 5, GREG}}},
- {0x7c00032e, "sthx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
- {0x7c00036e, "sthux", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x90000000, "stw", {{21, 5, GREG}, {0, 16, D}, {16, 5, G0REG}}},
- {0x94000000, "stwu", {{21, 5, GREG}, {0, 16, D}, {16, 5, GREG}}},
- {0x7c00012e, "stwx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
- {0x7c00016e, "stwux", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0xf8000000, "std", {{21, 5, GREG}, {2, 14, DS}, {16, 5, G0REG}}, IMPL64},
- {0xf8000001, "stdu", {{21, 5, GREG}, {2, 14, DS}, {16, 5, GREG}}, IMPL64},
- {0x7c00012a,
- "stdx",
- {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}},
- IMPL64},
- {0x7c00016a,
- "stdux",
- {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}},
- IMPL64},
-
- {0x7c00072c, "sthbrx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
- {0x7c00052c, "stwbrx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
- {0x7c00052a, "stswx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
- {0x7c00012d, "stwcx.", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
- {0x7c0001ad,
- "stdcx.",
- {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}},
- IMPL64},
-
- {0x7c0005aa, "stswi", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, NUM0}}},
-
- {
- 0x7c0007ae,
- "stfiwx",
- {{21, 5, FREG}, {16, 5, G0REG}, {11, 5, GREG}},
- },
-
- {0xd0000000, "stfs", {{21, 5, FREG}, {0, 16, D}, {16, 5, G0REG}}},
- {0xd4000000, "stfsu", {{21, 5, FREG}, {0, 16, D}, {16, 5, GREG}}},
- {0x7c00052e, "stfsx", {{21, 5, FREG}, {16, 5, G0REG}, {11, 5, GREG}}},
- {0x7c00056e, "stfsux", {{21, 5, FREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0xd8000000, "stfd", {{21, 5, FREG}, {0, 16, D}, {16, 5, G0REG}}},
- {0xdc000000, "stfdu", {{21, 5, FREG}, {0, 16, D}, {16, 5, GREG}}},
- {0x7c0005ae, "stfdx", {{21, 5, FREG}, {16, 5, G0REG}, {11, 5, GREG}}},
- {0x7c0005ee, "stfdux", {{21, 5, FREG}, {16, 5, GREG}, {11, 5, GREG}}},
-
- {0x20000000, "subfic", {{21, 5, GREG}, {16, 5, GREG}, {0, 16, SI}}},
- {0x7c000050, "sub", {{21, 5, GREG}, {11, 5, GREG}, {16, 5, GREG}}},
- {0x7c000051, "sub.", {{21, 5, GREG}, {11, 5, GREG}, {16, 5, GREG}}},
- {0x7c000450, "subo", {{21, 5, GREG}, {11, 5, GREG}, {16, 5, GREG}}},
- {0x7c000451, "subo.", {{21, 5, GREG}, {11, 5, GREG}, {16, 5, GREG}}},
- {0x7c000050, "subf", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000051, "subf.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000450, "subfo", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000451, "subfo.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
-
- {0x7c000010, "subc", {{21, 5, GREG}, {11, 5, GREG}, {16, 5, GREG}}},
- {0x7c000011, "subc.", {{21, 5, GREG}, {11, 5, GREG}, {16, 5, GREG}}},
- {0x7c000410, "subco", {{21, 5, GREG}, {11, 5, GREG}, {16, 5, GREG}}},
- {0x7c000411, "subco.", {{21, 5, GREG}, {11, 5, GREG}, {16, 5, GREG}}},
- {0x7c000010, "subfc", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000011, "subfc.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000410, "subfco", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000411, "subfco.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
-
- {0x7c000110, "subfe", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000111, "subfe.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000510, "subfeo", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000511, "subfeo.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
-
- {0x7c0001d0, "subfme", {{21, 5, GREG}, {16, 5, GREG}}},
- {0x7c0001d1, "subfme.", {{21, 5, GREG}, {16, 5, GREG}}},
- {0x7c0005d0, "subfmeo", {{21, 5, GREG}, {16, 5, GREG}}},
- {0x7c0005d1, "subfmeo.", {{21, 5, GREG}, {16, 5, GREG}}},
-
- {0x7c000190, "subfze", {{21, 5, GREG}, {16, 5, GREG}}},
- {0x7c000191, "subfze.", {{21, 5, GREG}, {16, 5, GREG}}},
- {0x7c000590, "subfzeo", {{21, 5, GREG}, {16, 5, GREG}}},
- {0x7c000591, "subfzeo.", {{21, 5, GREG}, {16, 5, GREG}}},
-
- {
- 0x7c0004ac,
- "sync",
- },
- {0x7c0004ac, "sync", {{21, 2, NUM}}},
- {
- 0x7c2004ac,
- "lwsync",
- },
- {
- 0x7c4004ac,
- "ptesync",
- },
-
- {0x08000000, "tdi", {{21, 5, NUM}, {16, 5, GREG}, {0, 16, SI}}, IMPL64},
- {0x0a000000, "tdlti", {{16, 5, GREG}, {0, 16, SI}}, IMPL64},
- {0x0a800000, "tdlei", {{16, 5, GREG}, {0, 16, SI}}, IMPL64},
- {0x08800000, "tdeqi", {{16, 5, GREG}, {0, 16, SI}}, IMPL64},
- {0x09800000, "tdgei", {{16, 5, GREG}, {0, 16, SI}}, IMPL64},
- {0x09000000, "tdgti", {{16, 5, GREG}, {0, 16, SI}}, IMPL64},
- {0x09800000, "tdnli", {{16, 5, GREG}, {0, 16, SI}}, IMPL64},
- {0x0b000000, "tdnei", {{16, 5, GREG}, {0, 16, SI}}, IMPL64},
- {0x0a800000, "tdngi", {{16, 5, GREG}, {0, 16, SI}}, IMPL64},
- {0x08400000, "tdllti", {{16, 5, GREG}, {0, 16, SI}}, IMPL64},
- {0x08c00000, "tdllei", {{16, 5, GREG}, {0, 16, SI}}, IMPL64},
- {0x08a00000, "tdlgei", {{16, 5, GREG}, {0, 16, SI}}, IMPL64},
- {0x08200000, "tdlgti", {{16, 5, GREG}, {0, 16, SI}}, IMPL64},
- {0x08a00000, "tdlnli", {{16, 5, GREG}, {0, 16, SI}}, IMPL64},
- {0x08c00000, "tdlngi", {{16, 5, GREG}, {0, 16, SI}}, IMPL64},
-
- {0x7c000088, "td", {{21, 5, NUM}, {16, 5, GREG}, {11, 5, GREG}}, IMPL64},
- {0x7e000088, "tdlt", {{16, 5, GREG}, {11, 5, GREG}}, IMPL64},
- {0x7e800088, "tdle", {{16, 5, GREG}, {11, 5, GREG}}, IMPL64},
- {0x7c800088, "tdeq", {{16, 5, GREG}, {11, 5, GREG}}, IMPL64},
- {0x7d800088, "tdge", {{16, 5, GREG}, {11, 5, GREG}}, IMPL64},
- {0x7d000088, "tdgt", {{16, 5, GREG}, {11, 5, GREG}}, IMPL64},
- {0x7d800088, "tdnl", {{16, 5, GREG}, {11, 5, GREG}}, IMPL64},
- {0x7f000088, "tdne", {{16, 5, GREG}, {11, 5, GREG}}, IMPL64},
- {0x7e800088, "tdng", {{16, 5, GREG}, {11, 5, GREG}}, IMPL64},
- {0x7c400088, "tdllt", {{16, 5, GREG}, {11, 5, GREG}}, IMPL64},
- {0x7cc00088, "tdlle", {{16, 5, GREG}, {11, 5, GREG}}, IMPL64},
- {0x7ca00088, "tdlge", {{16, 5, GREG}, {11, 5, GREG}}, IMPL64},
- {0x7c200088, "tdlgt", {{16, 5, GREG}, {11, 5, GREG}}, IMPL64},
- {0x7ca00088, "tdlnl", {{16, 5, GREG}, {11, 5, GREG}}, IMPL64},
- {0x7cc00088, "tdlng", {{16, 5, GREG}, {11, 5, GREG}}, IMPL64},
-
- {0x0c000000, "twi", {{21, 5, NUM}, {16, 5, GREG}, {0, 16, SI}}},
- {0x0e000000, "twlti", {{16, 5, GREG}, {0, 16, SI}}},
- {0x0e800000, "twlei", {{16, 5, GREG}, {0, 16, SI}}},
- {0x0c800000, "tweqi", {{16, 5, GREG}, {0, 16, SI}}},
- {0x0d800000, "twgei", {{16, 5, GREG}, {0, 16, SI}}},
- {0x0d000000, "twgti", {{16, 5, GREG}, {0, 16, SI}}},
- {0x0d800000, "twnli", {{16, 5, GREG}, {0, 16, SI}}},
- {0x0f000000, "twnei", {{16, 5, GREG}, {0, 16, SI}}},
- {0x0e800000, "twngi", {{16, 5, GREG}, {0, 16, SI}}},
- {0x0c400000, "twllti", {{16, 5, GREG}, {0, 16, SI}}},
- {0x0cc00000, "twllei", {{16, 5, GREG}, {0, 16, SI}}},
- {0x0ca00000, "twlgei", {{16, 5, GREG}, {0, 16, SI}}},
- {0x0c200000, "twlgti", {{16, 5, GREG}, {0, 16, SI}}},
- {0x0ca00000, "twlnli", {{16, 5, GREG}, {0, 16, SI}}},
- {0x0cc00000, "twlngi", {{16, 5, GREG}, {0, 16, SI}}},
-
- {0x7c000008, "tw", {{21, 5, NUM}, {16, 5, GREG}, {11, 5, GREG}}},
- {0x7c000008, "tw", {{21, 5, NUM}, {16, 5, ZERO}, {11, 5, ZERO}}},
- {0x7e000008, "twlt", {{16, 5, GREG}, {11, 5, GREG}}},
- {0x7e800008, "twle", {{16, 5, GREG}, {11, 5, GREG}}},
- {0x7c800008, "tweq", {{16, 5, GREG}, {11, 5, GREG}}},
- {0x7d800008, "twge", {{16, 5, GREG}, {11, 5, GREG}}},
- {0x7d000008, "twgt", {{16, 5, GREG}, {11, 5, GREG}}},
- {0x7d800008, "twnl", {{16, 5, GREG}, {11, 5, GREG}}},
- {0x7f000008, "twne", {{16, 5, GREG}, {11, 5, GREG}}},
- {0x7e800008, "twng", {{16, 5, GREG}, {11, 5, GREG}}},
- {0x7c400008, "twllt", {{16, 5, GREG}, {11, 5, GREG}}},
- {0x7cc00008, "twlle", {{16, 5, GREG}, {11, 5, GREG}}},
- {0x7ca00008, "twlge", {{16, 5, GREG}, {11, 5, GREG}}},
- {0x7c200008, "twlgt", {{16, 5, GREG}, {11, 5, GREG}}},
- {0x7ca00008, "twlnl", {{16, 5, GREG}, {11, 5, GREG}}},
- {0x7cc00008, "twlng", {{16, 5, GREG}, {11, 5, GREG}}},
- {
- 0x7fe00008,
- "trap",
- },
-
- {0x68000000, "xori", {{16, 5, GREG}, {21, 5, GREG}, {0, 16, UI}}},
- {0x6c000000, "xoris", {{16, 5, GREG}, {21, 5, GREG}, {0, 16, UI}}},
- {0x7c000278, "xor", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
- {0x7c000279, "xor.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
-
- /* Cache Management Instructions (from book II) */
- {0x7c0007ac, "icbi", {{16, 5, G0REG}, {11, 5, GREG}}},
- {
- 0x4c00012c,
- "isync",
- },
- {0x7c00022c, "dcbt", {{16, 5, G0REG}, {11, 5, GREG}}},
- {
- 0x7c00022c,
- "dcbt",
- {{16, 5, G0REG}, {11, 5, GREG}, {21, 4, NUM}},
- },
- {0x7c0001ec, "dcbtst", {{16, 5, G0REG}, {11, 5, GREG}}},
- {0x7c00022c,
- "dcbt128",
- {{16, 5, G0REG}, {11, 5, GREG}, {21, 4, NUM}},
- IMPL64 | OPTIONAL},
- {0x7c0007ec, "dcbz", {{16, 5, G0REG}, {11, 5, GREG}}},
- {0x7c2007ec, "dcbzl", {{16, 5, G0REG}, {11, 5, GREG}}},
- {0x7c2007ec, "dcbz128", {{16, 5, G0REG}, {11, 5, GREG}}, IMPL64 | OPTIONAL},
- {0x7c00006c, "dcbst", {{16, 5, G0REG}, {11, 5, GREG}}},
- {0x7c0000ac, "dcbf", {{16, 5, G0REG}, {11, 5, GREG}}},
- {0x7c00026c,
- "eciwx",
- {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}},
- OPTIONAL | CPU970},
- {0x7c00036c,
- "ecowx",
- {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}},
- OPTIONAL | CPU970},
- {
- 0x7c0006ac,
- "eieio",
- },
- /* Instructions (from book III) */
- {
- 0x4c000064,
- "rfi",
- },
- {0x7c000124, "mtmsr", {{21, 5, GREG}}},
- {0x7c000164, "mtmsrd", {{21, 5, GREG}}, IMPL64 | OPTIONAL},
- {0x7c000164, "mtmsrd", {{21, 5, GREG}, {16, 1, NUM}}, IMPL64 | OPTIONAL},
- {0x7c0000a6, "mfmsr", {{21, 5, GREG}}},
- {0x7c0005ec, "dcba", {{16, 5, G0REG}, {11, 5, GREG}}, OPTIONAL},
- {0x7c0003ac, "dcbi", {{16, 5, G0REG}, {11, 5, GREG}}},
- {0x7c0001a4, "mtsr", {{16, 4, SGREG}, {21, 5, GREG}}},
- {0x7c0004a6, "mfsr", {{21, 5, GREG}, {16, 4, SGREG}}},
- {0x7c0001e4, "mtsrin", {{21, 5, GREG}, {11, 5, GREG}}},
- {0x7c000526, "mfsrin", {{21, 5, GREG}, {11, 5, GREG}}},
- {0x7c000364, "slbie", {{11, 5, GREG}}, IMPL64 | OPTIONAL},
- {0x7c0003e4, "slbia", {{0}}, IMPL64 | OPTIONAL},
- {0x7c000324, "slbmte", {{21, 5, GREG}, {11, 5, GREG}}, IMPL64 | OPTIONAL},
- {0x7c0006a6, "slbmfev", {{21, 5, GREG}, {11, 5, GREG}}, IMPL64 | OPTIONAL},
- {0x7c000726, "slbmfee", {{21, 5, GREG}, {11, 5, GREG}}, IMPL64 | OPTIONAL},
- {0x7c000264, "tlbie", {{11, 5, GREG}}, OPTIONAL | CPU970},
- {0x7c000264,
- "tlbie",
- {{11, 5, GREG}, {21, 1, NUM}},
- IMPL64 | OPTIONAL | CPU970},
- {0x7c000224, "tlbiel", {{11, 5, GREG}}, IMPL64 | OPTIONAL},
- {0x7c0002e4, "tlbia", {{0}}, OPTIONAL | CPU970},
- {0x7c00046c, "tlbsync", {{0}}, OPTIONAL | CPU970},
- {0x7c1c43a6, "mttbl", {{21, 5, GREG}}},
- {0x7c1d43a6, "mttbu", {{21, 5, GREG}}},
- {0x7c0002e6, "mftb", {{21, 5, GREG}, {11, 10, SPREG}}},
- {0x7c0c42e6, "mftb", {{21, 5, GREG}}},
- {0x7c0d42e6, "mftbu", {{21, 5, GREG}}},
- {0x00000200, "attn", {{11, 15, NUM}}, OPTIONAL | CPU970},
-
- /* Instructions (from book IV) */
- {0x24000000, "dozi", {{21, 5, GREG}, {16, 5, GREG}, {0, 16, SI}}, CPU601},
- {0x7c000210, "doz", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, CPU601},
- {0x7c000211, "doz.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, CPU601},
- {0x7c000610, "dozo", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, CPU601},
- {0x7c000611,
- "dozo.",
- {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}},
- CPU601},
-
- {0x7c0002d0, "abs", {{21, 5, GREG}, {16, 5, GREG}}, CPU601},
- {0x7c0002d1, "abs.", {{21, 5, GREG}, {16, 5, GREG}}, CPU601},
- {0x7c0006d0, "abso", {{21, 5, GREG}, {16, 5, GREG}}, CPU601},
- {0x7c0006d1, "abso.", {{21, 5, GREG}, {16, 5, GREG}}, CPU601},
-
- {0x7c0003d0, "nabs", {{21, 5, GREG}, {16, 5, GREG}}, CPU601},
- {0x7c0003d1, "nabs.", {{21, 5, GREG}, {16, 5, GREG}}, CPU601},
- {0x7c0007d0, "nabso", {{21, 5, GREG}, {16, 5, GREG}}, CPU601},
- {0x7c0007d1, "nabso.", {{21, 5, GREG}, {16, 5, GREG}}, CPU601},
-
- {0x1c000000, "mulli", {{21, 5, GREG}, {16, 5, GREG}, {0, 16, SI}}},
-
- {0x7c0000d6, "mul", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, CPU601},
- {0x7c0000d7, "mul.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, CPU601},
- {0x7c0004d6, "mulo", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, CPU601},
- {0x7c0004d7,
- "mulo.",
- {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}},
- CPU601},
-
- {0x7c000296, "div", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, CPU601},
- {0x7c000297, "div.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, CPU601},
- {0x7c000696, "divo", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, CPU601},
- {0x7c000697,
- "divo.",
- {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}},
- CPU601},
-
- {0x7c0002d6, "divs", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, CPU601},
- {0x7c0002d7,
- "divs.",
- {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}},
- CPU601},
- {0x7c0006d6,
- "divso",
- {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}},
- CPU601},
- {0x7c0006d7,
- "divso.",
- {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}},
- CPU601},
-
- {0x58000000,
- "rlmi",
- {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}, {6, 5, MBE}, {1, 5, MBE}},
- CPU601},
- {0x58000001,
- "rlmi.",
- {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}, {6, 5, MBE}, {1, 5, MBE}},
- CPU601},
-
- {0x7c000432, "rrib", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
- {0x7c000433,
- "rrib.",
- {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}},
- CPU601},
-
- {0x7c00003a,
- "maskg",
- {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}},
- CPU601},
- {0x7c00003b,
- "maskg.",
- {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}},
- CPU601},
-
- {0x7c00043a,
- "maskir",
- {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}},
- CPU601},
- {0x7c00043b,
- "maskir.",
- {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}},
- CPU601},
-
- {0x7c000130, "slq", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
- {0x7c000131, "slq.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
-
- {0x7c000530, "srq", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
- {0x7c000531, "srq.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
-
- {0x7c000170, "sliq", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM}}, CPU601},
- {0x7c000171, "sliq.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM}}, CPU601},
-
- {0x7c000570, "sriq", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM}}, CPU601},
- {0x7c000571, "sriq.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM}}, CPU601},
-
- {0x7c0001f0, "slliq", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM}}, CPU601},
- {0x7c0001f1,
- "slliq.",
- {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM}},
- CPU601},
-
- {0x7c0005f0, "srliq", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM}}, CPU601},
- {0x7c0005f1,
- "srliq.",
- {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM}},
- CPU601},
-
- {0x7c0001b0, "sllq", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
- {0x7c0001b1,
- "sllq.",
- {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}},
- CPU601},
-
- {0x7c0005b0, "srlq", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
- {0x7c0005b1,
- "srlq.",
- {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}},
- CPU601},
-
- {0x7c000132, "sle", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
- {0x7c000133, "sle.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
-
- {0x7c000532, "sre", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
- {0x7c000533, "sre.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
-
- {0x7c0001b2, "sleq", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
- {0x7c0001b3,
- "sleq.",
- {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}},
- CPU601},
-
- {0x7c0005b2, "sreq", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
- {0x7c0005b3,
- "sreq.",
- {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}},
- CPU601},
-
- {0x7c000770, "sraiq", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM}}, CPU601},
- {0x7c000771,
- "sraiq.",
- {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM}},
- CPU601},
-
- {0x7c000730, "sraq", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
- {0x7c000731,
- "sraq.",
- {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}},
- CPU601},
-
- {0x7c000732, "srea", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
- {0x7c000733,
- "srea.",
- {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}},
- CPU601},
-
- /* Added from the POWER 601 book */
- {0x7c000426, "clcs", {{21, 5, GREG}, {16, 5, GREG}}, CPU601},
-
- /* Added from the POWER 603 book.
- * These are really 603 specific instructions but we mark them as OPTIONAL
- * so that the -force_cpusubtype_ALL flag as to be used. This makes it so
- * only 601 instructions will cause the cputype to be set to other an ALL.
- */
- {0x7c0007a4, "tlbld", {{11, 5, GREG}}, OPTIONAL},
- {0x7c0007e4, "tlbli", {{11, 5, GREG}}, OPTIONAL},
-
- /* VMX Instructions */
- {0x7c00000e, "lvebx", {{21, 5, VREG}, {16, 5, G0REG}, {11, 5, GREG}}, VMX},
- {0x7c00004e, "lvehx", {{21, 5, VREG}, {16, 5, G0REG}, {11, 5, GREG}}, VMX},
- {0x7c00008e, "lvewx", {{21, 5, VREG}, {16, 5, G0REG}, {11, 5, GREG}}, VMX},
- {0x7c0000ce, "lvx", {{21, 5, VREG}, {16, 5, G0REG}, {11, 5, GREG}}, VMX},
- {0x7c0002ce, "lvxl", {{21, 5, VREG}, {16, 5, G0REG}, {11, 5, GREG}}, VMX},
-
- {0x7c00010e, "stvebx", {{21, 5, VREG}, {16, 5, G0REG}, {11, 5, GREG}}, VMX},
- {0x7c00014e, "stvehx", {{21, 5, VREG}, {16, 5, G0REG}, {11, 5, GREG}}, VMX},
- {0x7c00018e, "stvewx", {{21, 5, VREG}, {16, 5, G0REG}, {11, 5, GREG}}, VMX},
- {0x7c0001ce, "stvx", {{21, 5, VREG}, {16, 5, G0REG}, {11, 5, GREG}}, VMX},
- {0x7c0003ce, "stvxl", {{21, 5, VREG}, {16, 5, G0REG}, {11, 5, GREG}}, VMX},
-
- {0x7c00000c, "lvsl", {{21, 5, VREG}, {16, 5, G0REG}, {11, 5, GREG}}, VMX},
- {0x7c00004c, "lvsr", {{21, 5, VREG}, {16, 5, G0REG}, {11, 5, GREG}}, VMX},
-
- {0x10000644, "mtvscr", {{11, 5, VREG}}, VMX},
- {0x10000604, "mfvscr", {{21, 5, VREG}}, VMX},
-
- {0x7c0002ac, "dst", {{16, 5, GREG}, {11, 5, GREG}, {21, 2, NUM}}, VMX},
- {0x7e0002ac, "dstt", {{16, 5, GREG}, {11, 5, GREG}, {21, 2, NUM}}, VMX},
- {0x7c0002ec, "dstst", {{16, 5, GREG}, {11, 5, GREG}, {21, 2, NUM}}, VMX},
- {0x7e0002ec, "dststt", {{16, 5, GREG}, {11, 5, GREG}, {21, 2, NUM}}, VMX},
- {0x7c00066c, "dss", {{21, 2, NUM}}, VMX},
- {0x7e00066c, "dssall", {{0}}, VMX},
-
- {0x10000000, "vaddubm", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000200, "vaddubs", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000300, "vaddsbs", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000040, "vadduhm", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000240, "vadduhs", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000340, "vaddshs", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000080, "vadduwm", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000280, "vadduws", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000380, "vaddsws", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x1000000a, "vaddfp", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
-
- {0x10000180, "vaddcuw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
-
- {0x10000400, "vsububm", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000600, "vsububs", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000700, "vsubsbs", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000440, "vsubuhm", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000640, "vsubuhs", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000740, "vsubshs", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000480, "vsubuwm", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000680, "vsubuws", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000780, "vsubsws", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x1000004a, "vsubfp", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
-
- {0x10000580, "vsubcuw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
-
- {0x10000008, "vmuloub", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000108, "vmulosb", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000048, "vmulouh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000148, "vmulosh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
-
- {0x10000208, "vmuleub", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000308, "vmulesb", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000248, "vmuleuh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000348, "vmulesh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
-
- {0x10000020,
- "vmhaddshs",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}, {6, 5, VREG}},
- VMX},
- {0x10000021,
- "vmhraddshs",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}, {6, 5, VREG}},
- VMX},
- {0x10000022,
- "vmladduhm",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}, {6, 5, VREG}},
- VMX},
- {0x1000002e,
- "vmaddfp",
- {{21, 5, VREG}, {16, 5, VREG}, {6, 5, VREG}, {11, 5, VREG}},
- VMX},
-
- {0x10000024,
- "vmsumubm",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}, {6, 5, VREG}},
- VMX},
- {0x10000025,
- "vmsummbm",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}, {6, 5, VREG}},
- VMX},
- {0x10000026,
- "vmsumuhm",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}, {6, 5, VREG}},
- VMX},
- {0x10000027,
- "vmsumuhs",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}, {6, 5, VREG}},
- VMX},
- {0x10000028,
- "vmsumshm",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}, {6, 5, VREG}},
- VMX},
- {0x10000029,
- "vmsumshs",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}, {6, 5, VREG}},
- VMX},
-
- {0x10000788, "vsumsws", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
-
- {0x10000688,
- "vsum2sws",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}},
- VMX},
-
- {0x10000608,
- "vsum4ubs",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}},
- VMX},
- {0x10000708,
- "vsum4sbs",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}},
- VMX},
- {0x10000648,
- "vsum4shs",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}},
- VMX},
-
- {0x10000402, "vavgub", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000442, "vavguh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000482, "vavguw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000502, "vavgsb", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000542, "vavgsh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000582, "vavgsw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
-
- {0x10000404, "vand", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000484, "vor", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x100004c4, "vxor", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000444, "vandc", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000504, "vnor", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
-
- {0x10000004, "vrlb", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000044, "vrlh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000084, "vrlw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
-
- {0x10000104, "vslb", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000144, "vslh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000184, "vslw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x100001c4, "vsl", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
-
- {0x10000204, "vsrb", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000304, "vsrab", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000244, "vsrh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000344, "vsrah", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000284, "vsrw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000384, "vsraw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x100002c4, "vsr", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
-
- {0x10000206,
- "vcmpgtub",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}},
- VMX},
- {0x10000606,
- "vcmpgtub.",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}},
- VMX},
- {0x10000306,
- "vcmpgtsb",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}},
- VMX},
- {0x10000706,
- "vcmpgtsb.",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}},
- VMX},
- {0x10000246,
- "vcmpgtuh",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}},
- VMX},
- {0x10000646,
- "vcmpgtuh.",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}},
- VMX},
- {0x10000346,
- "vcmpgtsh",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}},
- VMX},
- {0x10000746,
- "vcmpgtsh.",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}},
- VMX},
- {0x10000286,
- "vcmpgtuw",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}},
- VMX},
- {0x10000686,
- "vcmpgtuw.",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}},
- VMX},
- {0x10000386,
- "vcmpgtsw",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}},
- VMX},
- {0x10000786,
- "vcmpgtsw.",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}},
- VMX},
- {0x100002c6,
- "vcmpgtfp",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}},
- VMX},
- {0x100006c6,
- "vcmpgtfp.",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}},
- VMX},
-
- {0x10000006,
- "vcmpequb",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}},
- VMX},
- {0x10000406,
- "vcmpequb.",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}},
- VMX},
- {0x10000046,
- "vcmpequh",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}},
- VMX},
- {0x10000446,
- "vcmpequh.",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}},
- VMX},
- {0x10000086,
- "vcmpequw",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}},
- VMX},
- {0x10000486,
- "vcmpequw.",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}},
- VMX},
- {0x100000c6,
- "vcmpeqfp",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}},
- VMX},
- {0x100004c6,
- "vcmpeqfp.",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}},
- VMX},
-
- {0x100001c6,
- "vcmpgefp",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}},
- VMX},
- {0x100005c6,
- "vcmpgefp.",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}},
- VMX},
-
- {0x100003c6, "vcmpbfp", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x100007c6,
- "vcmpbfp.",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}},
- VMX},
-
- {0x1000002a,
- "vsel",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}, {6, 5, VREG}},
- VMX},
-
- {0x1000000e, "vpkuhum", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x1000008e, "vpkuhus", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x1000010e, "vpkshus", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x1000018e, "vpkshss", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x1000004e, "vpkuwum", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x100000ce, "vpkuwus", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x1000014e, "vpkswus", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x100001ce, "vpkswss", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x1000030e, "vpkpx", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
-
- {0x1000020e, "vupkhsb", {{21, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x1000024e, "vupkhsh", {{21, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x1000034e, "vupkhpx", {{21, 5, VREG}, {11, 5, VREG}}, VMX},
-
- {0x1000028e, "vupklsb", {{21, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x100002ce, "vupklsh", {{21, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x100003ce, "vupklpx", {{21, 5, VREG}, {11, 5, VREG}}, VMX},
-
- {0x1000000c, "vmrghb", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x1000004c, "vmrghh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x1000008c, "vmrghw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
-
- {0x1000010c, "vmrglb", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x1000014c, "vmrglh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x1000018c, "vmrglw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
-
- {0x1000020c, "vspltb", {{21, 5, VREG}, {11, 5, VREG}, {16, 5, NUM}}, VMX},
- {0x1000024c, "vsplth", {{21, 5, VREG}, {11, 5, VREG}, {16, 5, NUM}}, VMX},
- {0x1000028c, "vspltw", {{21, 5, VREG}, {11, 5, VREG}, {16, 5, NUM}}, VMX},
-
- {0x1000030c, "vspltisb", {{21, 5, VREG}, {16, 5, SNUM}}, VMX},
- {0x1000034c, "vspltish", {{21, 5, VREG}, {16, 5, SNUM}}, VMX},
- {0x1000038c, "vspltisw", {{21, 5, VREG}, {16, 5, SNUM}}, VMX},
-
- {0x1000002b,
- "vperm",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}, {6, 5, VREG}},
- VMX},
-
- {0x1000002c,
- "vsldoi",
- {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}, {6, 4, NUM}},
- VMX},
-
- {0x1000040c, "vslo", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x1000044c, "vsro", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
-
- {0x10000002, "vmaxub", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000102, "vmaxsb", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000042, "vmaxuh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000142, "vmaxsh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000082, "vmaxuw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000182, "vmaxsw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x1000040a, "vmaxfp", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
-
- {0x10000202, "vminub", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000302, "vminsb", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000242, "vminuh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000342, "vminsh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000282, "vminuw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x10000382, "vminsw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x1000044a, "vminfp", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
-
- {0x1000010a, "vrefp", {{21, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x1000014a, "vrsqrtefp", {{21, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x100001ca, "vlogefp", {{21, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x1000018a, "vexptefp", {{21, 5, VREG}, {11, 5, VREG}}, VMX},
-
- {0x1000002f,
- "vnmsubfp",
- {{21, 5, VREG}, {16, 5, VREG}, {6, 5, VREG}, {11, 5, VREG}},
- VMX},
-
- {0x1000020a, "vrfin", {{21, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x1000024a, "vrfiz", {{21, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x1000028a, "vrfip", {{21, 5, VREG}, {11, 5, VREG}}, VMX},
- {0x100002ca, "vrfim", {{21, 5, VREG}, {11, 5, VREG}}, VMX},
-
- {0x1000038a, "vctuxs", {{21, 5, VREG}, {11, 5, VREG}, {16, 5, NUM}}, VMX},
- {0x100003ca, "vctsxs", {{21, 5, VREG}, {11, 5, VREG}, {16, 5, NUM}}, VMX},
-
- {0x1000030a, "vcfux", {{21, 5, VREG}, {11, 5, VREG}, {16, 5, NUM}}, VMX},
- {0x1000034a, "vcfsx", {{21, 5, VREG}, {11, 5, VREG}, {16, 5, NUM}}, VMX},
-
- {0, ""} /* end of table marker */
+ {0x7c000096, "mulhw", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000097, "mulhw.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+
+ {0x7c000012, "mulhdu", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+ {0x7c000013, "mulhdu.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+
+ {0x7c000016, "mulhwu", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000017, "mulhwu.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+
+ {0x7c0001d2, "mulld", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+ {0x7c0001d3, "mulld.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+ {0x7c0005d2, "mulldo", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+ {0x7c0005d3, "mulldo.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+
+ {0x7c0003b8, "nand", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
+ {0x7c0003b9, "nand.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
+
+ {0x7c0000d0, "neg", {{21, 5, GREG}, {16, 5, GREG}}},
+ {0x7c0000d1, "neg.", {{21, 5, GREG}, {16, 5, GREG}}},
+ {0x7c0004d0, "nego", {{21, 5, GREG}, {16, 5, GREG}}},
+ {0x7c0004d1, "nego.", {{21, 5, GREG}, {16, 5, GREG}}},
+
+ {0x7c0000f8, "nor", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
+ {0x7c0000f9, "nor.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
+
+ /* Miscellaneous mnemonics (assember extended mnemonics) */
+ {
+ 0x60000000,
+ "nop",
+ },
+
+ {0x60000000, "ori", {{16, 5, GREG}, {21, 5, GREG}, {0, 16, UI}}},
+ {0x60000000, "ori", {{16, 5, ZERO}, {21, 5, ZERO}, {0, 16, ZERO}}},
+ {0x64000000, "oris", {{16, 5, GREG}, {21, 5, GREG}, {0, 16, UI}}},
+ {0x7c000378, "or", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000379, "or.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
+
+ /// @brief Move register
+ {0x7c000378, "mr", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
+
+ {0x7c000338, "orc", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000339, "orc.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
+
+ {0x78000000, "rldicl", {{16, 5, GREG}, {21, 5, GREG}, {0, 0, sh}, {0, 0, mb}}, IMPL64},
+ {0x78000001, "rldicl.", {{16, 5, GREG}, {21, 5, GREG}, {0, 0, sh}, {0, 0, mb}}, IMPL64},
+ {0x78000004, "rldicr", {{16, 5, GREG}, {21, 5, GREG}, {0, 0, sh}, {0, 0, mb}}, IMPL64},
+ {0x78000005, "rldicr.", {{16, 5, GREG}, {21, 5, GREG}, {0, 0, sh}, {0, 0, mb}}, IMPL64},
+ {0x78000008, "rldic", {{16, 5, GREG}, {21, 5, GREG}, {0, 0, sh}, {0, 0, mb}}, IMPL64},
+ {0x78000009, "rldic.", {{16, 5, GREG}, {21, 5, GREG}, {0, 0, sh}, {0, 0, mb}}, IMPL64},
+ {0x7800000c, "rldimi", {{16, 5, GREG}, {21, 5, GREG}, {0, 0, sh}, {0, 0, mb}}, IMPL64},
+ {0x7800000d, "rldimi.", {{16, 5, GREG}, {21, 5, GREG}, {0, 0, sh}, {0, 0, mb}}, IMPL64},
+ {0x78000010, "rldcl", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}, {0, 0, mb}}, IMPL64},
+ {0x78000011, "rldcl.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}, {0, 0, mb}}, IMPL64},
+ {0x78000012, "rldcr", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}, {0, 0, mb}}, IMPL64},
+ {0x78000013, "rldcr.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}, {0, 0, mb}}, IMPL64},
+
+ {0x54000000, "rlwinm", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM0}, {6, 5, MBE}, {1, 5, MBE}}},
+ {0x54000001,
+ "rlwinm.",
+ {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM0}, {6, 5, MBE}, {1, 5, MBE}}},
+ {0x5c000000, "rlwnm", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}, {6, 5, MBE}, {1, 5, MBE}}},
+ {0x5c000001, "rlwnm.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}, {6, 5, MBE}, {1, 5, MBE}}},
+ {0x50000000, "rlwimi", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM0}, {6, 5, MBE}, {1, 5, MBE}}},
+ {0x50000001,
+ "rlwimi.",
+ {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM0}, {6, 5, MBE}, {1, 5, MBE}}},
+
+ {
+ 0x44000002,
+ "sc",
+ },
+ {0x4c000024, "rfid", {{0}}, IMPL64 | OPTIONAL},
+
+ {0x7c000030, "slw", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000031, "slw.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000036, "sld", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, IMPL64},
+ {0x7c000037, "sld.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, IMPL64},
+
+ {0x7c000430, "srw", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000431, "srw.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000436, "srd", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, IMPL64},
+ {0x7c000437, "srd.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, IMPL64},
+
+ {0x7c000670, "srawi", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM}}},
+ {0x7c000671, "srawi.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM}}},
+ {0x7c000674, "sradi", {{16, 5, GREG}, {21, 5, GREG}, {0, 0, sh}}, IMPL64},
+ {0x7c000675, "sradi.", {{16, 5, GREG}, {21, 5, GREG}, {0, 0, sh}}, IMPL64},
+
+ {0x7c000630, "sraw", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000631, "sraw.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000634, "srad", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, IMPL64},
+ {0x7c000635, "srad.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, IMPL64},
+
+ {0x98000000, "stb", {{21, 5, GREG}, {0, 16, D}, {16, 5, G0REG}}},
+ {0x9c000000, "stbu", {{21, 5, GREG}, {0, 16, D}, {16, 5, GREG}}},
+ {0x7c0001ae, "stbx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
+ {0x7c0001ee, "stbux", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0xb0000000, "sth", {{21, 5, GREG}, {0, 16, D}, {16, 5, G0REG}}},
+ {0xb4000000, "sthu", {{21, 5, GREG}, {0, 16, D}, {16, 5, GREG}}},
+ {0x7c00032e, "sthx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
+ {0x7c00036e, "sthux", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x90000000, "stw", {{21, 5, GREG}, {0, 16, D}, {16, 5, G0REG}}},
+ {0x94000000, "stwu", {{21, 5, GREG}, {0, 16, D}, {16, 5, GREG}}},
+ {0x7c00012e, "stwx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
+ {0x7c00016e, "stwux", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0xf8000000, "std", {{21, 5, GREG}, {2, 14, DS}, {16, 5, G0REG}}, IMPL64},
+ {0xf8000001, "stdu", {{21, 5, GREG}, {2, 14, DS}, {16, 5, GREG}}, IMPL64},
+ {0x7c00012a, "stdx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}, IMPL64},
+ {0x7c00016a, "stdux", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+
+ {0x7c00072c, "sthbrx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
+ {0x7c00052c, "stwbrx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
+ {0x7c00052a, "stswx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
+ {0x7c00012d, "stwcx.", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}},
+ {0x7c0001ad, "stdcx.", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}, IMPL64},
+
+ {0x7c0005aa, "stswi", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, NUM0}}},
+
+ {
+ 0x7c0007ae,
+ "stfiwx",
+ {{21, 5, FREG}, {16, 5, G0REG}, {11, 5, GREG}},
+ },
+
+ {0xd0000000, "stfs", {{21, 5, FREG}, {0, 16, D}, {16, 5, G0REG}}},
+ {0xd4000000, "stfsu", {{21, 5, FREG}, {0, 16, D}, {16, 5, GREG}}},
+ {0x7c00052e, "stfsx", {{21, 5, FREG}, {16, 5, G0REG}, {11, 5, GREG}}},
+ {0x7c00056e, "stfsux", {{21, 5, FREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0xd8000000, "stfd", {{21, 5, FREG}, {0, 16, D}, {16, 5, G0REG}}},
+ {0xdc000000, "stfdu", {{21, 5, FREG}, {0, 16, D}, {16, 5, GREG}}},
+ {0x7c0005ae, "stfdx", {{21, 5, FREG}, {16, 5, G0REG}, {11, 5, GREG}}},
+ {0x7c0005ee, "stfdux", {{21, 5, FREG}, {16, 5, GREG}, {11, 5, GREG}}},
+
+ {0x20000000, "subfic", {{21, 5, GREG}, {16, 5, GREG}, {0, 16, SI}}},
+ {0x7c000050, "sub", {{21, 5, GREG}, {11, 5, GREG}, {16, 5, GREG}}},
+ {0x7c000051, "sub.", {{21, 5, GREG}, {11, 5, GREG}, {16, 5, GREG}}},
+ {0x7c000450, "subo", {{21, 5, GREG}, {11, 5, GREG}, {16, 5, GREG}}},
+ {0x7c000451, "subo.", {{21, 5, GREG}, {11, 5, GREG}, {16, 5, GREG}}},
+ {0x7c000050, "subf", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000051, "subf.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000450, "subfo", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000451, "subfo.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+
+ {0x7c000010, "subc", {{21, 5, GREG}, {11, 5, GREG}, {16, 5, GREG}}},
+ {0x7c000011, "subc.", {{21, 5, GREG}, {11, 5, GREG}, {16, 5, GREG}}},
+ {0x7c000410, "subco", {{21, 5, GREG}, {11, 5, GREG}, {16, 5, GREG}}},
+ {0x7c000411, "subco.", {{21, 5, GREG}, {11, 5, GREG}, {16, 5, GREG}}},
+ {0x7c000010, "subfc", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000011, "subfc.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000410, "subfco", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000411, "subfco.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+
+ {0x7c000110, "subfe", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000111, "subfe.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000510, "subfeo", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000511, "subfeo.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}},
+
+ {0x7c0001d0, "subfme", {{21, 5, GREG}, {16, 5, GREG}}},
+ {0x7c0001d1, "subfme.", {{21, 5, GREG}, {16, 5, GREG}}},
+ {0x7c0005d0, "subfmeo", {{21, 5, GREG}, {16, 5, GREG}}},
+ {0x7c0005d1, "subfmeo.", {{21, 5, GREG}, {16, 5, GREG}}},
+
+ {0x7c000190, "subfze", {{21, 5, GREG}, {16, 5, GREG}}},
+ {0x7c000191, "subfze.", {{21, 5, GREG}, {16, 5, GREG}}},
+ {0x7c000590, "subfzeo", {{21, 5, GREG}, {16, 5, GREG}}},
+ {0x7c000591, "subfzeo.", {{21, 5, GREG}, {16, 5, GREG}}},
+
+ {
+ 0x7c0004ac,
+ "sync",
+ },
+ {0x7c0004ac, "sync", {{21, 2, NUM}}},
+ {
+ 0x7c2004ac,
+ "lwsync",
+ },
+ {
+ 0x7c4004ac,
+ "ptesync",
+ },
+
+ {0x08000000, "tdi", {{21, 5, NUM}, {16, 5, GREG}, {0, 16, SI}}, IMPL64},
+ {0x0a000000, "tdlti", {{16, 5, GREG}, {0, 16, SI}}, IMPL64},
+ {0x0a800000, "tdlei", {{16, 5, GREG}, {0, 16, SI}}, IMPL64},
+ {0x08800000, "tdeqi", {{16, 5, GREG}, {0, 16, SI}}, IMPL64},
+ {0x09800000, "tdgei", {{16, 5, GREG}, {0, 16, SI}}, IMPL64},
+ {0x09000000, "tdgti", {{16, 5, GREG}, {0, 16, SI}}, IMPL64},
+ {0x09800000, "tdnli", {{16, 5, GREG}, {0, 16, SI}}, IMPL64},
+ {0x0b000000, "tdnei", {{16, 5, GREG}, {0, 16, SI}}, IMPL64},
+ {0x0a800000, "tdngi", {{16, 5, GREG}, {0, 16, SI}}, IMPL64},
+ {0x08400000, "tdllti", {{16, 5, GREG}, {0, 16, SI}}, IMPL64},
+ {0x08c00000, "tdllei", {{16, 5, GREG}, {0, 16, SI}}, IMPL64},
+ {0x08a00000, "tdlgei", {{16, 5, GREG}, {0, 16, SI}}, IMPL64},
+ {0x08200000, "tdlgti", {{16, 5, GREG}, {0, 16, SI}}, IMPL64},
+ {0x08a00000, "tdlnli", {{16, 5, GREG}, {0, 16, SI}}, IMPL64},
+ {0x08c00000, "tdlngi", {{16, 5, GREG}, {0, 16, SI}}, IMPL64},
+
+ {0x7c000088, "td", {{21, 5, NUM}, {16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+ {0x7e000088, "tdlt", {{16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+ {0x7e800088, "tdle", {{16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+ {0x7c800088, "tdeq", {{16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+ {0x7d800088, "tdge", {{16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+ {0x7d000088, "tdgt", {{16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+ {0x7d800088, "tdnl", {{16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+ {0x7f000088, "tdne", {{16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+ {0x7e800088, "tdng", {{16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+ {0x7c400088, "tdllt", {{16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+ {0x7cc00088, "tdlle", {{16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+ {0x7ca00088, "tdlge", {{16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+ {0x7c200088, "tdlgt", {{16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+ {0x7ca00088, "tdlnl", {{16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+ {0x7cc00088, "tdlng", {{16, 5, GREG}, {11, 5, GREG}}, IMPL64},
+
+ {0x0c000000, "twi", {{21, 5, NUM}, {16, 5, GREG}, {0, 16, SI}}},
+ {0x0e000000, "twlti", {{16, 5, GREG}, {0, 16, SI}}},
+ {0x0e800000, "twlei", {{16, 5, GREG}, {0, 16, SI}}},
+ {0x0c800000, "tweqi", {{16, 5, GREG}, {0, 16, SI}}},
+ {0x0d800000, "twgei", {{16, 5, GREG}, {0, 16, SI}}},
+ {0x0d000000, "twgti", {{16, 5, GREG}, {0, 16, SI}}},
+ {0x0d800000, "twnli", {{16, 5, GREG}, {0, 16, SI}}},
+ {0x0f000000, "twnei", {{16, 5, GREG}, {0, 16, SI}}},
+ {0x0e800000, "twngi", {{16, 5, GREG}, {0, 16, SI}}},
+ {0x0c400000, "twllti", {{16, 5, GREG}, {0, 16, SI}}},
+ {0x0cc00000, "twllei", {{16, 5, GREG}, {0, 16, SI}}},
+ {0x0ca00000, "twlgei", {{16, 5, GREG}, {0, 16, SI}}},
+ {0x0c200000, "twlgti", {{16, 5, GREG}, {0, 16, SI}}},
+ {0x0ca00000, "twlnli", {{16, 5, GREG}, {0, 16, SI}}},
+ {0x0cc00000, "twlngi", {{16, 5, GREG}, {0, 16, SI}}},
+
+ {0x7c000008, "tw", {{21, 5, NUM}, {16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000008, "tw", {{21, 5, NUM}, {16, 5, ZERO}, {11, 5, ZERO}}},
+ {0x7e000008, "twlt", {{16, 5, GREG}, {11, 5, GREG}}},
+ {0x7e800008, "twle", {{16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c800008, "tweq", {{16, 5, GREG}, {11, 5, GREG}}},
+ {0x7d800008, "twge", {{16, 5, GREG}, {11, 5, GREG}}},
+ {0x7d000008, "twgt", {{16, 5, GREG}, {11, 5, GREG}}},
+ {0x7d800008, "twnl", {{16, 5, GREG}, {11, 5, GREG}}},
+ {0x7f000008, "twne", {{16, 5, GREG}, {11, 5, GREG}}},
+ {0x7e800008, "twng", {{16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c400008, "twllt", {{16, 5, GREG}, {11, 5, GREG}}},
+ {0x7cc00008, "twlle", {{16, 5, GREG}, {11, 5, GREG}}},
+ {0x7ca00008, "twlge", {{16, 5, GREG}, {11, 5, GREG}}},
+ {0x7c200008, "twlgt", {{16, 5, GREG}, {11, 5, GREG}}},
+ {0x7ca00008, "twlnl", {{16, 5, GREG}, {11, 5, GREG}}},
+ {0x7cc00008, "twlng", {{16, 5, GREG}, {11, 5, GREG}}},
+ {
+ 0x7fe00008,
+ "trap",
+ },
+
+ {0x68000000, "xori", {{16, 5, GREG}, {21, 5, GREG}, {0, 16, UI}}},
+ {0x6c000000, "xoris", {{16, 5, GREG}, {21, 5, GREG}, {0, 16, UI}}},
+ {0x7c000278, "xor", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000279, "xor.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}},
+
+ /* Cache Management Instructions (from book II) */
+ {0x7c0007ac, "icbi", {{16, 5, G0REG}, {11, 5, GREG}}},
+ {
+ 0x4c00012c,
+ "isync",
+ },
+ {0x7c00022c, "dcbt", {{16, 5, G0REG}, {11, 5, GREG}}},
+ {
+ 0x7c00022c,
+ "dcbt",
+ {{16, 5, G0REG}, {11, 5, GREG}, {21, 4, NUM}},
+ },
+ {0x7c0001ec, "dcbtst", {{16, 5, G0REG}, {11, 5, GREG}}},
+ {0x7c00022c, "dcbt128", {{16, 5, G0REG}, {11, 5, GREG}, {21, 4, NUM}}, IMPL64 | OPTIONAL},
+ {0x7c0007ec, "dcbz", {{16, 5, G0REG}, {11, 5, GREG}}},
+ {0x7c2007ec, "dcbzl", {{16, 5, G0REG}, {11, 5, GREG}}},
+ {0x7c2007ec, "dcbz128", {{16, 5, G0REG}, {11, 5, GREG}}, IMPL64 | OPTIONAL},
+ {0x7c00006c, "dcbst", {{16, 5, G0REG}, {11, 5, GREG}}},
+ {0x7c0000ac, "dcbf", {{16, 5, G0REG}, {11, 5, GREG}}},
+ {0x7c00026c, "eciwx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}, OPTIONAL | CPU970},
+ {0x7c00036c, "ecowx", {{21, 5, GREG}, {16, 5, G0REG}, {11, 5, GREG}}, OPTIONAL | CPU970},
+ {
+ 0x7c0006ac,
+ "eieio",
+ },
+ /* Instructions (from book III) */
+ {
+ 0x4c000064,
+ "rfi",
+ },
+ {0x7c000124, "mtmsr", {{21, 5, GREG}}},
+ {0x7c000164, "mtmsrd", {{21, 5, GREG}}, IMPL64 | OPTIONAL},
+ {0x7c000164, "mtmsrd", {{21, 5, GREG}, {16, 1, NUM}}, IMPL64 | OPTIONAL},
+ {0x7c0000a6, "mfmsr", {{21, 5, GREG}}},
+ {0x7c0005ec, "dcba", {{16, 5, G0REG}, {11, 5, GREG}}, OPTIONAL},
+ {0x7c0003ac, "dcbi", {{16, 5, G0REG}, {11, 5, GREG}}},
+ {0x7c0001a4, "mtsr", {{16, 4, SGREG}, {21, 5, GREG}}},
+ {0x7c0004a6, "mfsr", {{21, 5, GREG}, {16, 4, SGREG}}},
+ {0x7c0001e4, "mtsrin", {{21, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000526, "mfsrin", {{21, 5, GREG}, {11, 5, GREG}}},
+ {0x7c000364, "slbie", {{11, 5, GREG}}, IMPL64 | OPTIONAL},
+ {0x7c0003e4, "slbia", {{0}}, IMPL64 | OPTIONAL},
+ {0x7c000324, "slbmte", {{21, 5, GREG}, {11, 5, GREG}}, IMPL64 | OPTIONAL},
+ {0x7c0006a6, "slbmfev", {{21, 5, GREG}, {11, 5, GREG}}, IMPL64 | OPTIONAL},
+ {0x7c000726, "slbmfee", {{21, 5, GREG}, {11, 5, GREG}}, IMPL64 | OPTIONAL},
+ {0x7c000264, "tlbie", {{11, 5, GREG}}, OPTIONAL | CPU970},
+ {0x7c000264, "tlbie", {{11, 5, GREG}, {21, 1, NUM}}, IMPL64 | OPTIONAL | CPU970},
+ {0x7c000224, "tlbiel", {{11, 5, GREG}}, IMPL64 | OPTIONAL},
+ {0x7c0002e4, "tlbia", {{0}}, OPTIONAL | CPU970},
+ {0x7c00046c, "tlbsync", {{0}}, OPTIONAL | CPU970},
+ {0x7c1c43a6, "mttbl", {{21, 5, GREG}}},
+ {0x7c1d43a6, "mttbu", {{21, 5, GREG}}},
+ {0x7c0002e6, "mftb", {{21, 5, GREG}, {11, 10, SPREG}}},
+ {0x7c0c42e6, "mftb", {{21, 5, GREG}}},
+ {0x7c0d42e6, "mftbu", {{21, 5, GREG}}},
+ {0x00000200, "attn", {{11, 15, NUM}}, OPTIONAL | CPU970},
+
+ /* Instructions (from book IV) */
+ {0x24000000, "dozi", {{21, 5, GREG}, {16, 5, GREG}, {0, 16, SI}}, CPU601},
+ {0x7c000210, "doz", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, CPU601},
+ {0x7c000211, "doz.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, CPU601},
+ {0x7c000610, "dozo", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, CPU601},
+ {0x7c000611, "dozo.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, CPU601},
+
+ {0x7c0002d0, "abs", {{21, 5, GREG}, {16, 5, GREG}}, CPU601},
+ {0x7c0002d1, "abs.", {{21, 5, GREG}, {16, 5, GREG}}, CPU601},
+ {0x7c0006d0, "abso", {{21, 5, GREG}, {16, 5, GREG}}, CPU601},
+ {0x7c0006d1, "abso.", {{21, 5, GREG}, {16, 5, GREG}}, CPU601},
+
+ {0x7c0003d0, "nabs", {{21, 5, GREG}, {16, 5, GREG}}, CPU601},
+ {0x7c0003d1, "nabs.", {{21, 5, GREG}, {16, 5, GREG}}, CPU601},
+ {0x7c0007d0, "nabso", {{21, 5, GREG}, {16, 5, GREG}}, CPU601},
+ {0x7c0007d1, "nabso.", {{21, 5, GREG}, {16, 5, GREG}}, CPU601},
+
+ {0x1c000000, "mulli", {{21, 5, GREG}, {16, 5, GREG}, {0, 16, SI}}},
+
+ {0x7c0000d6, "mul", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, CPU601},
+ {0x7c0000d7, "mul.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, CPU601},
+ {0x7c0004d6, "mulo", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, CPU601},
+ {0x7c0004d7, "mulo.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, CPU601},
+
+ {0x7c000296, "div", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, CPU601},
+ {0x7c000297, "div.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, CPU601},
+ {0x7c000696, "divo", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, CPU601},
+ {0x7c000697, "divo.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, CPU601},
+
+ {0x7c0002d6, "divs", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, CPU601},
+ {0x7c0002d7, "divs.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, CPU601},
+ {0x7c0006d6, "divso", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, CPU601},
+ {0x7c0006d7, "divso.", {{21, 5, GREG}, {16, 5, GREG}, {11, 5, GREG}}, CPU601},
+
+ {0x58000000,
+ "rlmi",
+ {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}, {6, 5, MBE}, {1, 5, MBE}},
+ CPU601},
+ {0x58000001,
+ "rlmi.",
+ {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}, {6, 5, MBE}, {1, 5, MBE}},
+ CPU601},
+
+ {0x7c000432, "rrib", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
+ {0x7c000433, "rrib.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
+
+ {0x7c00003a, "maskg", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
+ {0x7c00003b, "maskg.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
+
+ {0x7c00043a, "maskir", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
+ {0x7c00043b, "maskir.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
+
+ {0x7c000130, "slq", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
+ {0x7c000131, "slq.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
+
+ {0x7c000530, "srq", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
+ {0x7c000531, "srq.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
+
+ {0x7c000170, "sliq", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM}}, CPU601},
+ {0x7c000171, "sliq.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM}}, CPU601},
+
+ {0x7c000570, "sriq", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM}}, CPU601},
+ {0x7c000571, "sriq.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM}}, CPU601},
+
+ {0x7c0001f0, "slliq", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM}}, CPU601},
+ {0x7c0001f1, "slliq.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM}}, CPU601},
+
+ {0x7c0005f0, "srliq", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM}}, CPU601},
+ {0x7c0005f1, "srliq.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM}}, CPU601},
+
+ {0x7c0001b0, "sllq", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
+ {0x7c0001b1, "sllq.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
+
+ {0x7c0005b0, "srlq", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
+ {0x7c0005b1, "srlq.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
+
+ {0x7c000132, "sle", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
+ {0x7c000133, "sle.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
+
+ {0x7c000532, "sre", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
+ {0x7c000533, "sre.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
+
+ {0x7c0001b2, "sleq", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
+ {0x7c0001b3, "sleq.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
+
+ {0x7c0005b2, "sreq", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
+ {0x7c0005b3, "sreq.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
+
+ {0x7c000770, "sraiq", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM}}, CPU601},
+ {0x7c000771, "sraiq.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, NUM}}, CPU601},
+
+ {0x7c000730, "sraq", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
+ {0x7c000731, "sraq.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
+
+ {0x7c000732, "srea", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
+ {0x7c000733, "srea.", {{16, 5, GREG}, {21, 5, GREG}, {11, 5, GREG}}, CPU601},
+
+ /* Added from the POWER 601 book */
+ {0x7c000426, "clcs", {{21, 5, GREG}, {16, 5, GREG}}, CPU601},
+
+ /* Added from the POWER 603 book.
+ * These are really 603 specific instructions but we mark them as OPTIONAL
+ * so that the -force_cpusubtype_ALL flag as to be used. This makes it so
+ * only 601 instructions will cause the cputype to be set to other an ALL.
+ */
+ {0x7c0007a4, "tlbld", {{11, 5, GREG}}, OPTIONAL},
+ {0x7c0007e4, "tlbli", {{11, 5, GREG}}, OPTIONAL},
+
+ /* VMX Instructions */
+ {0x7c00000e, "lvebx", {{21, 5, VREG}, {16, 5, G0REG}, {11, 5, GREG}}, VMX},
+ {0x7c00004e, "lvehx", {{21, 5, VREG}, {16, 5, G0REG}, {11, 5, GREG}}, VMX},
+ {0x7c00008e, "lvewx", {{21, 5, VREG}, {16, 5, G0REG}, {11, 5, GREG}}, VMX},
+ {0x7c0000ce, "lvx", {{21, 5, VREG}, {16, 5, G0REG}, {11, 5, GREG}}, VMX},
+ {0x7c0002ce, "lvxl", {{21, 5, VREG}, {16, 5, G0REG}, {11, 5, GREG}}, VMX},
+
+ {0x7c00010e, "stvebx", {{21, 5, VREG}, {16, 5, G0REG}, {11, 5, GREG}}, VMX},
+ {0x7c00014e, "stvehx", {{21, 5, VREG}, {16, 5, G0REG}, {11, 5, GREG}}, VMX},
+ {0x7c00018e, "stvewx", {{21, 5, VREG}, {16, 5, G0REG}, {11, 5, GREG}}, VMX},
+ {0x7c0001ce, "stvx", {{21, 5, VREG}, {16, 5, G0REG}, {11, 5, GREG}}, VMX},
+ {0x7c0003ce, "stvxl", {{21, 5, VREG}, {16, 5, G0REG}, {11, 5, GREG}}, VMX},
+
+ {0x7c00000c, "lvsl", {{21, 5, VREG}, {16, 5, G0REG}, {11, 5, GREG}}, VMX},
+ {0x7c00004c, "lvsr", {{21, 5, VREG}, {16, 5, G0REG}, {11, 5, GREG}}, VMX},
+
+ {0x10000644, "mtvscr", {{11, 5, VREG}}, VMX},
+ {0x10000604, "mfvscr", {{21, 5, VREG}}, VMX},
+
+ {0x7c0002ac, "dst", {{16, 5, GREG}, {11, 5, GREG}, {21, 2, NUM}}, VMX},
+ {0x7e0002ac, "dstt", {{16, 5, GREG}, {11, 5, GREG}, {21, 2, NUM}}, VMX},
+ {0x7c0002ec, "dstst", {{16, 5, GREG}, {11, 5, GREG}, {21, 2, NUM}}, VMX},
+ {0x7e0002ec, "dststt", {{16, 5, GREG}, {11, 5, GREG}, {21, 2, NUM}}, VMX},
+ {0x7c00066c, "dss", {{21, 2, NUM}}, VMX},
+ {0x7e00066c, "dssall", {{0}}, VMX},
+
+ {0x10000000, "vaddubm", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000200, "vaddubs", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000300, "vaddsbs", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000040, "vadduhm", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000240, "vadduhs", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000340, "vaddshs", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000080, "vadduwm", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000280, "vadduws", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000380, "vaddsws", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x1000000a, "vaddfp", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x10000180, "vaddcuw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x10000400, "vsububm", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000600, "vsububs", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000700, "vsubsbs", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000440, "vsubuhm", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000640, "vsubuhs", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000740, "vsubshs", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000480, "vsubuwm", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000680, "vsubuws", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000780, "vsubsws", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x1000004a, "vsubfp", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x10000580, "vsubcuw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x10000008, "vmuloub", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000108, "vmulosb", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000048, "vmulouh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000148, "vmulosh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x10000208, "vmuleub", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000308, "vmulesb", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000248, "vmuleuh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000348, "vmulesh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x10000020, "vmhaddshs", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}, {6, 5, VREG}}, VMX},
+ {0x10000021, "vmhraddshs", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}, {6, 5, VREG}}, VMX},
+ {0x10000022, "vmladduhm", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}, {6, 5, VREG}}, VMX},
+ {0x1000002e, "vmaddfp", {{21, 5, VREG}, {16, 5, VREG}, {6, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x10000024, "vmsumubm", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}, {6, 5, VREG}}, VMX},
+ {0x10000025, "vmsummbm", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}, {6, 5, VREG}}, VMX},
+ {0x10000026, "vmsumuhm", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}, {6, 5, VREG}}, VMX},
+ {0x10000027, "vmsumuhs", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}, {6, 5, VREG}}, VMX},
+ {0x10000028, "vmsumshm", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}, {6, 5, VREG}}, VMX},
+ {0x10000029, "vmsumshs", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}, {6, 5, VREG}}, VMX},
+
+ {0x10000788, "vsumsws", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x10000688, "vsum2sws", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x10000608, "vsum4ubs", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000708, "vsum4sbs", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000648, "vsum4shs", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x10000402, "vavgub", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000442, "vavguh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000482, "vavguw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000502, "vavgsb", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000542, "vavgsh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000582, "vavgsw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x10000404, "vand", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000484, "vor", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x100004c4, "vxor", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000444, "vandc", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000504, "vnor", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x10000004, "vrlb", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000044, "vrlh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000084, "vrlw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x10000104, "vslb", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000144, "vslh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000184, "vslw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x100001c4, "vsl", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x10000204, "vsrb", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000304, "vsrab", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000244, "vsrh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000344, "vsrah", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000284, "vsrw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000384, "vsraw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x100002c4, "vsr", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x10000206, "vcmpgtub", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000606, "vcmpgtub.", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000306, "vcmpgtsb", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000706, "vcmpgtsb.", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000246, "vcmpgtuh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000646, "vcmpgtuh.", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000346, "vcmpgtsh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000746, "vcmpgtsh.", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000286, "vcmpgtuw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000686, "vcmpgtuw.", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000386, "vcmpgtsw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000786, "vcmpgtsw.", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x100002c6, "vcmpgtfp", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x100006c6, "vcmpgtfp.", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x10000006, "vcmpequb", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000406, "vcmpequb.", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000046, "vcmpequh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000446, "vcmpequh.", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000086, "vcmpequw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000486, "vcmpequw.", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x100000c6, "vcmpeqfp", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x100004c6, "vcmpeqfp.", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x100001c6, "vcmpgefp", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x100005c6, "vcmpgefp.", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x100003c6, "vcmpbfp", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x100007c6, "vcmpbfp.", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x1000002a, "vsel", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}, {6, 5, VREG}}, VMX},
+
+ {0x1000000e, "vpkuhum", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x1000008e, "vpkuhus", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x1000010e, "vpkshus", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x1000018e, "vpkshss", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x1000004e, "vpkuwum", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x100000ce, "vpkuwus", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x1000014e, "vpkswus", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x100001ce, "vpkswss", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x1000030e, "vpkpx", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x1000020e, "vupkhsb", {{21, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x1000024e, "vupkhsh", {{21, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x1000034e, "vupkhpx", {{21, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x1000028e, "vupklsb", {{21, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x100002ce, "vupklsh", {{21, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x100003ce, "vupklpx", {{21, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x1000000c, "vmrghb", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x1000004c, "vmrghh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x1000008c, "vmrghw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x1000010c, "vmrglb", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x1000014c, "vmrglh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x1000018c, "vmrglw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x1000020c, "vspltb", {{21, 5, VREG}, {11, 5, VREG}, {16, 5, NUM}}, VMX},
+ {0x1000024c, "vsplth", {{21, 5, VREG}, {11, 5, VREG}, {16, 5, NUM}}, VMX},
+ {0x1000028c, "vspltw", {{21, 5, VREG}, {11, 5, VREG}, {16, 5, NUM}}, VMX},
+
+ {0x1000030c, "vspltisb", {{21, 5, VREG}, {16, 5, SNUM}}, VMX},
+ {0x1000034c, "vspltish", {{21, 5, VREG}, {16, 5, SNUM}}, VMX},
+ {0x1000038c, "vspltisw", {{21, 5, VREG}, {16, 5, SNUM}}, VMX},
+
+ {0x1000002b, "vperm", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}, {6, 5, VREG}}, VMX},
+
+ {0x1000002c, "vsldoi", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}, {6, 4, NUM}}, VMX},
+
+ {0x1000040c, "vslo", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x1000044c, "vsro", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x10000002, "vmaxub", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000102, "vmaxsb", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000042, "vmaxuh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000142, "vmaxsh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000082, "vmaxuw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000182, "vmaxsw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x1000040a, "vmaxfp", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x10000202, "vminub", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000302, "vminsb", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000242, "vminuh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000342, "vminsh", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000282, "vminuw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x10000382, "vminsw", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x1000044a, "vminfp", {{21, 5, VREG}, {16, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x1000010a, "vrefp", {{21, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x1000014a, "vrsqrtefp", {{21, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x100001ca, "vlogefp", {{21, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x1000018a, "vexptefp", {{21, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x1000002f, "vnmsubfp", {{21, 5, VREG}, {16, 5, VREG}, {6, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x1000020a, "vrfin", {{21, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x1000024a, "vrfiz", {{21, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x1000028a, "vrfip", {{21, 5, VREG}, {11, 5, VREG}}, VMX},
+ {0x100002ca, "vrfim", {{21, 5, VREG}, {11, 5, VREG}}, VMX},
+
+ {0x1000038a, "vctuxs", {{21, 5, VREG}, {11, 5, VREG}, {16, 5, NUM}}, VMX},
+ {0x100003ca, "vctsxs", {{21, 5, VREG}, {11, 5, VREG}, {16, 5, NUM}}, VMX},
+
+ {0x1000030a, "vcfux", {{21, 5, VREG}, {11, 5, VREG}, {16, 5, NUM}}, VMX},
+ {0x1000034a, "vcfsx", {{21, 5, VREG}, {11, 5, VREG}, {16, 5, NUM}}, VMX},
+
+ {0, ""} /* end of table marker */
};
#define kAsmFloatZeroRegister 0
-#define kAsmZeroRegister 0
+#define kAsmZeroRegister 0
#define kAsmRegisterPrefix "r"
-#define kAsmRegisterLimit 31
-#define kAsmPcRegister 17
-#define kAsmCrRegister 18
-#define kAsmSpRegister 5
+#define kAsmRegisterLimit 31
+#define kAsmPcRegister 17
+#define kAsmCrRegister 18
+#define kAsmSpRegister 5
/* return address register */
#define kAsmRetRegister 19
diff --git a/dev/LibCompiler/Defines.h b/dev/LibCompiler/Defines.h
index 07f3b33..eacf9c0 100644
--- a/dev/LibCompiler/Defines.h
+++ b/dev/LibCompiler/Defines.h
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
+ Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
------------------------------------------- */
@@ -9,23 +9,23 @@
#ifndef Yes
#define Yes true
-#endif // ifndef Yes
+#endif // ifndef Yes
#ifndef No
#define No false
-#endif // ifndef No
+#endif // ifndef No
#ifndef YES
#define YES true
-#endif // ifndef YES
+#endif // ifndef YES
#ifndef NO
#define NO false
-#endif // ifndef NO
+#endif // ifndef NO
#ifndef BOOL
#define BOOL bool
-#endif // ifndef BOOL
+#endif // ifndef BOOL
#define SizeType size_t
@@ -34,37 +34,36 @@
#define UIntPtr uintptr_t
-#define Int64 int64_t
+#define Int64 int64_t
#define UInt64 uint64_t
-#define Int32 int
+#define Int32 int
#define UInt32 unsigned
#define Bool bool
-#define Int16 int16_t
+#define Int16 int16_t
#define UInt16 uint16_t
-#define Int8 int8_t
+#define Int8 int8_t
#define UInt8 uint8_t
#define CharType char
-#define Boolean bool
+#define Boolean bool
-#include <filesystem>
-#include <cstdint>
#include <cassert>
-#include <cstring>
-#include <iostream>
-#include <utility>
#include <cctype>
+#include <cstdint>
#include <cstdio>
+#include <cstring>
+#include <filesystem>
#include <fstream>
+#include <iostream>
#include <memory>
+#include <new>
#include <string>
+#include <utility>
#include <vector>
-#include <vector>
-#include <new>
#define nullPtr std::nullptr_t
@@ -82,76 +81,71 @@
#define rt_copy_memory(dst, src, len) memcpy(dst, src, len)
#endif
-#define LIBCOMPILER_COPY_DELETE(KLASS) \
- KLASS& operator=(const KLASS&) = delete; \
- KLASS(const KLASS&) = delete;
+#define LIBCOMPILER_COPY_DELETE(KLASS) \
+ KLASS& operator=(const KLASS&) = delete; \
+ KLASS(const KLASS&) = delete;
-#define LIBCOMPILER_COPY_DEFAULT(KLASS) \
- KLASS& operator=(const KLASS&) = default; \
- KLASS(const KLASS&) = default;
+#define LIBCOMPILER_COPY_DEFAULT(KLASS) \
+ KLASS& operator=(const KLASS&) = default; \
+ KLASS(const KLASS&) = default;
-#define LIBCOMPILER_MOVE_DELETE(KLASS) \
- KLASS& operator=(KLASS&&) = delete; \
- KLASS(KLASS&&) = delete;
+#define LIBCOMPILER_MOVE_DELETE(KLASS) \
+ KLASS& operator=(KLASS&&) = delete; \
+ KLASS(KLASS&&) = delete;
-#define LIBCOMPILER_MOVE_DEFAULT(KLASS) \
- KLASS& operator=(KLASS&&) = default; \
- KLASS(KLASS&&) = default;
+#define LIBCOMPILER_MOVE_DEFAULT(KLASS) \
+ KLASS& operator=(KLASS&&) = default; \
+ KLASS(KLASS&&) = default;
#define LC_IMPORT_C extern "C"
-#define LC_IMPORT extern
+#define LC_IMPORT extern
#include <ctime>
#include <fstream>
#include <string>
#include <vector>
-namespace LibCompiler
-{
- inline constexpr int kBaseYear = 1900;
+namespace LibCompiler {
+inline constexpr int kBaseYear = 1900;
- typedef std::string String;
+typedef std::string String;
- inline String current_date() noexcept
- {
- auto time_data = time(nullptr);
- auto time_struct = gmtime(&time_data);
+inline String current_date() noexcept {
+ auto time_data = time(nullptr);
+ auto time_struct = gmtime(&time_data);
- String fmt = std::to_string(kBaseYear + time_struct->tm_year);
+ String fmt = std::to_string(kBaseYear + time_struct->tm_year);
- fmt += "-";
- fmt += std::to_string(time_struct->tm_mon + 1);
- fmt += "-";
- fmt += std::to_string(time_struct->tm_mday);
+ fmt += "-";
+ fmt += std::to_string(time_struct->tm_mon + 1);
+ fmt += "-";
+ fmt += std::to_string(time_struct->tm_mday);
- return fmt;
- }
+ return fmt;
+}
- inline bool to_str(CharType* str, Int32 limit, Int32 base) noexcept
- {
- if (limit == 0)
- return false;
+inline bool to_str(CharType* str, Int32 limit, Int32 base) noexcept {
+ if (limit == 0) return false;
- Int32 copy_limit = limit;
- Int32 cnt = 0;
- Int32 ret = base;
+ Int32 copy_limit = limit;
+ Int32 cnt = 0;
+ Int32 ret = base;
- while (limit != 1)
- {
- ret = ret % 10;
- str[cnt] = ret;
+ while (limit != 1) {
+ ret = ret % 10;
+ str[cnt] = ret;
- ++cnt;
- --limit;
- --ret;
- }
+ ++cnt;
+ --limit;
+ --ret;
+ }
- str[copy_limit] = '\0';
- return true;
- }
+ str[copy_limit] = '\0';
+ return true;
+}
- using String = std::basic_string<CharType>;
-} // namespace LibCompiler
+using String = std::basic_string<CharType>;
+} // namespace LibCompiler
#define PACKED __attribute__((packed))
@@ -160,10 +154,8 @@ typedef char char_type;
#define kObjectFileExt ".obj"
#define kBinaryFileExt ".bin"
-#define kAsmFileExts \
- { \
- ".64x", ".32x", ".masm", ".s", ".S", ".asm", ".x64" \
- }
+#define kAsmFileExts \
+ { ".64x", ".32x", ".masm", ".s", ".S", ".asm", ".x64" }
#define kAsmFileExtsMax 7
@@ -171,6 +163,6 @@ typedef char char_type;
#ifdef MSVC
#pragma scalar_storage_order big - endian
-#endif // ifdef MSVC
+#endif // ifdef MSVC
#endif /* ifndef __LIBCOMPILER_DEFINES_H__ */
diff --git a/dev/LibCompiler/ErrorID.h b/dev/LibCompiler/ErrorID.h
index b105f9b..1f58313 100644
--- a/dev/LibCompiler/ErrorID.h
+++ b/dev/LibCompiler/ErrorID.h
@@ -12,12 +12,12 @@
#include <LibCompiler/Defines.h>
#include <LibCompiler/ErrorOr.h>
-#define LIBCOMPILER_SUCCESSS 0
-#define LIBCOMPILER_EXEC_ERROR -30
+#define LIBCOMPILER_SUCCESSS 0
+#define LIBCOMPILER_EXEC_ERROR -30
#define LIBCOMPILER_FILE_NOT_FOUND -31
-#define LIBCOMPILER_DIR_NOT_FOUND -32
-#define LIBCOMPILER_FILE_EXISTS -33
-#define LIBCOMPILER_TOO_LONG -34
-#define LIBCOMPILER_INVALID_DATA -35
-#define LIBCOMPILER_UNIMPLEMENTED -36
-#define LIBCOMPILER_FAT_ERROR -37
+#define LIBCOMPILER_DIR_NOT_FOUND -32
+#define LIBCOMPILER_FILE_EXISTS -33
+#define LIBCOMPILER_TOO_LONG -34
+#define LIBCOMPILER_INVALID_DATA -35
+#define LIBCOMPILER_UNIMPLEMENTED -36
+#define LIBCOMPILER_FAT_ERROR -37
diff --git a/dev/LibCompiler/ErrorOr.h b/dev/LibCompiler/ErrorOr.h
index 2a6d590..ca93dd2 100644
--- a/dev/LibCompiler/ErrorOr.h
+++ b/dev/LibCompiler/ErrorOr.h
@@ -12,50 +12,34 @@
#include <LibCompiler/Defines.h>
#include <LibCompiler/Ref.h>
-namespace LibCompiler
-{
- using ErrorT = UInt32;
-
- template <typename T>
- class ErrorOr final
- {
- public:
- ErrorOr() = default;
- ~ErrorOr() = default;
-
- public:
- explicit ErrorOr(Int32 err)
- : mId(err)
- {
- }
-
- explicit ErrorOr(nullPtr Null)
- {
- }
-
- explicit ErrorOr(T Class)
- : mRef(Class)
- {
- }
-
- ErrorOr& operator=(const ErrorOr&) = default;
- ErrorOr(const ErrorOr&) = default;
-
- Ref<T> Leak()
- {
- return mRef;
- }
-
- operator bool()
- {
- return mRef;
- }
-
- private:
- Ref<T> mRef;
- Int32 mId{0};
- };
-
- using ErrorOrAny = ErrorOr<voidPtr>;
-
-} // namespace LibCompiler
+namespace LibCompiler {
+using ErrorT = UInt32;
+
+template <typename T>
+class ErrorOr final {
+ public:
+ ErrorOr() = default;
+ ~ErrorOr() = default;
+
+ public:
+ explicit ErrorOr(Int32 err) : mId(err) {}
+
+ explicit ErrorOr(nullPtr Null) {}
+
+ explicit ErrorOr(T Class) : mRef(Class) {}
+
+ ErrorOr& operator=(const ErrorOr&) = default;
+ ErrorOr(const ErrorOr&) = default;
+
+ Ref<T> Leak() { return mRef; }
+
+ operator bool() { return mRef; }
+
+ private:
+ Ref<T> mRef;
+ Int32 mId{0};
+};
+
+using ErrorOrAny = ErrorOr<voidPtr>;
+
+} // namespace LibCompiler
diff --git a/dev/LibCompiler/Macros.h b/dev/LibCompiler/Macros.h
index f2f5f6b..cce89d6 100644
--- a/dev/LibCompiler/Macros.h
+++ b/dev/LibCompiler/Macros.h
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
+ Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
------------------------------------------- */
@@ -9,25 +9,25 @@
#ifndef _MACROS_H_
#define _MACROS_H_
-#define LIBCOMPILER_COPY_DELETE(KLASS) \
- KLASS& operator=(const KLASS&) = delete; \
- KLASS(const KLASS&) = delete;
+#define LIBCOMPILER_COPY_DELETE(KLASS) \
+ KLASS& operator=(const KLASS&) = delete; \
+ KLASS(const KLASS&) = delete;
-#define LIBCOMPILER_COPY_DEFAULT(KLASS) \
- KLASS& operator=(const KLASS&) = default; \
- KLASS(const KLASS&) = default;
+#define LIBCOMPILER_COPY_DEFAULT(KLASS) \
+ KLASS& operator=(const KLASS&) = default; \
+ KLASS(const KLASS&) = default;
-#define LIBCOMPILER_MOVE_DELETE(KLASS) \
- KLASS& operator=(KLASS&&) = delete; \
- KLASS(KLASS&&) = delete;
+#define LIBCOMPILER_MOVE_DELETE(KLASS) \
+ KLASS& operator=(KLASS&&) = delete; \
+ KLASS(KLASS&&) = delete;
-#define LIBCOMPILER_MOVE_DEFAULT(KLASS) \
- KLASS& operator=(KLASS&&) = default; \
- KLASS(KLASS&&) = default;
+#define LIBCOMPILER_MOVE_DEFAULT(KLASS) \
+ KLASS& operator=(KLASS&&) = default; \
+ KLASS(KLASS&&) = default;
/// @note xxxx is the error placeholder, in hexadecimal.
#define LIBCOMPILER_ERROR_PREFIX_CXX "CXXxxxx"
-#define LIBCOMPILER_ERROR_PREFIX_CL "CLxxxx"
+#define LIBCOMPILER_ERROR_PREFIX_CL "CLxxxx"
#define LIBCOMPILER_ERROR_PREFIX_ASM "ASMxxxx"
#endif /* ifndef _MACROS_H_ */
diff --git a/dev/LibCompiler/PEF.h b/dev/LibCompiler/PEF.h
index 1148dea..f32d830 100644
--- a/dev/LibCompiler/PEF.h
+++ b/dev/LibCompiler/PEF.h
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
+ Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
------------------------------------------- */
@@ -11,14 +11,14 @@
// @file PEF.hpp
// @brief Preferred Executable Format
-#define kPefMagic "Joy!"
+#define kPefMagic "Joy!"
#define kPefMagicFat "yoJ!"
-#define kPefExt ".exec"
-#define kPefDylibExt ".dylib"
-#define kPefLibExt ".lib"
+#define kPefExt ".exec"
+#define kPefDylibExt ".dylib"
+#define kPefLibExt ".lib"
#define kPefObjectExt ".obj"
-#define kPefDebugExt ".dbg"
+#define kPefDebugExt ".dbg"
#define kPefDriverExt ".sys"
#define kPefZero128 ".zero128"
@@ -38,107 +38,92 @@
#define kPefStart "__ImageStart"
-namespace LibCompiler
-{
- enum
- {
- kPefArchStart = 99,
- kPefArchIntel86S = 100,
- kPefArchAMD64,
- kPefArchRISCV,
- kPefArch64000, /* 64x0 RISC architecture. */
- kPefArch32000,
- kPefArchPowerPC, /* 64-bit POWER architecture. */
- kPefArchARM64,
- kPefArchCount = (kPefArchPowerPC - kPefArchIntel86S) + 1,
- kPefArchInvalid = 0xFF,
- };
-
- enum
- {
- kPefSubArchAMD,
- kPefSubArchIntel,
- kPefSubArchARM,
- kPefSubArchGeneric,
- kPefSubArchIBM,
- };
-
- enum
- {
- kPefKindExec = 1, /* .o */
- kPefKindDylib = 2, /* .dylib */
- kPefKindObject = 4, /* .obj */
- kPefKindDebug = 5, /* .dbg */
- kPefKindDriver = 6,
- kPefKindCount,
- };
-
- /* PEF container */
- typedef struct PEFContainer final
- {
- CharType Magic[kPefMagicLen];
- UInt32 Linker;
- UInt32 Version;
- UInt32 Kind;
- UInt32 Abi;
- UInt32 Cpu;
- UInt32 SubCpu; /* Cpu specific information */
- UIntPtr Start; /* Origin of code */
- SizeType HdrSz; /* Size of header */
- SizeType Count; /* container header count */
- } PACKED PEFContainer, *PEFContainerPtr;
-
- /* First PEFCommandHeader starts after PEFContainer */
- /* Last container is __exec_end */
-
- /* PEF executable section and commands. */
-
- typedef struct PEFCommandHeader final
- {
- CharType Name[kPefNameLen]; /* container name */
- UInt32 Cpu; /* container cpu */
- UInt32 SubCpu; /* container sub-cpu */
- UInt32 Flags; /* container flags */
- UInt16 Kind; /* container kind */
- UIntPtr Offset; /* file offset */
- SizeType Size; /* file size */
- } PACKED PEFCommandHeader, *PEFCommandHeaderPtr;
-
- enum
- {
- kPefCode = 0xC,
- kPefData = 0xD,
- kPefZero = 0xE,
- kPefLinkerID = 0x1,
- kPefCount = 4,
- kPefInvalid = 0xFF,
- };
-} // namespace LibCompiler
-
-inline std::ofstream& operator<<(std::ofstream& fp,
- LibCompiler::PEFContainer& container)
-{
- fp.write((char*)&container, sizeof(LibCompiler::PEFContainer));
- return fp;
+namespace LibCompiler {
+enum {
+ kPefArchStart = 99,
+ kPefArchIntel86S = 100,
+ kPefArchAMD64,
+ kPefArchRISCV,
+ kPefArch64000, /* 64x0 RISC architecture. */
+ kPefArch32000,
+ kPefArchPowerPC, /* 64-bit POWER architecture. */
+ kPefArchARM64,
+ kPefArchCount = (kPefArchPowerPC - kPefArchIntel86S) + 1,
+ kPefArchInvalid = 0xFF,
+};
+
+enum {
+ kPefSubArchAMD,
+ kPefSubArchIntel,
+ kPefSubArchARM,
+ kPefSubArchGeneric,
+ kPefSubArchIBM,
+};
+
+enum {
+ kPefKindExec = 1, /* .o */
+ kPefKindDylib = 2, /* .dylib */
+ kPefKindObject = 4, /* .obj */
+ kPefKindDebug = 5, /* .dbg */
+ kPefKindDriver = 6,
+ kPefKindCount,
+};
+
+/* PEF container */
+typedef struct PEFContainer final {
+ CharType Magic[kPefMagicLen];
+ UInt32 Linker;
+ UInt32 Version;
+ UInt32 Kind;
+ UInt32 Abi;
+ UInt32 Cpu;
+ UInt32 SubCpu; /* Cpu specific information */
+ UIntPtr Start; /* Origin of code */
+ SizeType HdrSz; /* Size of header */
+ SizeType Count; /* container header count */
+} PACKED PEFContainer, *PEFContainerPtr;
+
+/* First PEFCommandHeader starts after PEFContainer */
+/* Last container is __exec_end */
+
+/* PEF executable section and commands. */
+
+typedef struct PEFCommandHeader final {
+ CharType Name[kPefNameLen]; /* container name */
+ UInt32 Cpu; /* container cpu */
+ UInt32 SubCpu; /* container sub-cpu */
+ UInt32 Flags; /* container flags */
+ UInt16 Kind; /* container kind */
+ UIntPtr Offset; /* file offset */
+ SizeType Size; /* file size */
+} PACKED PEFCommandHeader, *PEFCommandHeaderPtr;
+
+enum {
+ kPefCode = 0xC,
+ kPefData = 0xD,
+ kPefZero = 0xE,
+ kPefLinkerID = 0x1,
+ kPefCount = 4,
+ kPefInvalid = 0xFF,
+};
+} // namespace LibCompiler
+
+inline std::ofstream& operator<<(std::ofstream& fp, LibCompiler::PEFContainer& container) {
+ fp.write((char*) &container, sizeof(LibCompiler::PEFContainer));
+ return fp;
}
-inline std::ofstream& operator<<(std::ofstream& fp,
- LibCompiler::PEFCommandHeader& container)
-{
- fp.write((char*)&container, sizeof(LibCompiler::PEFCommandHeader));
- return fp;
+inline std::ofstream& operator<<(std::ofstream& fp, LibCompiler::PEFCommandHeader& container) {
+ fp.write((char*) &container, sizeof(LibCompiler::PEFCommandHeader));
+ return fp;
}
-inline std::ifstream& operator>>(std::ifstream& fp,
- LibCompiler::PEFContainer& container)
-{
- fp.read((char*)&container, sizeof(LibCompiler::PEFContainer));
- return fp;
+inline std::ifstream& operator>>(std::ifstream& fp, LibCompiler::PEFContainer& container) {
+ fp.read((char*) &container, sizeof(LibCompiler::PEFContainer));
+ return fp;
}
-inline std::ifstream& operator>>(std::ifstream& fp,
- LibCompiler::PEFCommandHeader& container)
-{
- fp.read((char*)&container, sizeof(LibCompiler::PEFCommandHeader));
- return fp;
+inline std::ifstream& operator>>(std::ifstream& fp, LibCompiler::PEFCommandHeader& container) {
+ fp.read((char*) &container, sizeof(LibCompiler::PEFCommandHeader));
+ return fp;
}
diff --git a/dev/LibCompiler/Parser.h b/dev/LibCompiler/Parser.h
index cb0e470..04a7fab 100644
--- a/dev/LibCompiler/Parser.h
+++ b/dev/LibCompiler/Parser.h
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
+ Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
------------------------------------------- */
@@ -8,172 +8,143 @@
#include <LibCompiler/AssemblyInterface.h>
-namespace LibCompiler
-{
- inline auto kInvalidFrontend = "NA";
-
- /// @brief Compiler backend, implements a frontend, such as C, C++...
- /// See Toolchain, for some examples.
- class ICompilerFrontend
- {
- public:
- explicit ICompilerFrontend() = default;
- virtual ~ICompilerFrontend() = default;
-
- LIBCOMPILER_COPY_DEFAULT(ICompilerFrontend);
-
- // NOTE: cast this to your user defined ast.
- typedef void* AstType;
-
- //! @brief Compile a syntax tree ouf of the text.
- //! Also takes the source file name for metadata.
-
- virtual bool Compile(std::string text, const std::string file) = 0;
-
- //! @brief What language are we dealing with?
- virtual const char* Language()
- {
- return kInvalidFrontend;
- }
-
- virtual bool IsValid()
- {
- return strcmp(this->Language(), kInvalidFrontend) > 0;
- }
- };
-
- struct SyntaxLeafList;
- struct SyntaxLeafList;
- struct CompilerKeyword;
-
- /// we want to do that because to separate keywords.
- enum KeywordKind
- {
- kKeywordKindNamespace,
- kKeywordKindFunctionStart,
- kKeywordKindFunctionEnd,
- kKeywordKindVariable,
- kKeywordKindVariablePtr,
- kKeywordKindType,
- kKeywordKindTypePtr,
- kKeywordKindExpressionBegin,
- kKeywordKindExpressionEnd,
- kKeywordKindArgSeparator,
- kKeywordKindBodyStart,
- kKeywordKindBodyEnd,
- kKeywordKindClass,
- kKeywordKindPtrAccess,
- kKeywordKindAccess,
- kKeywordKindIf,
- kKeywordKindElse,
- kKeywordKindElseIf,
- kKeywordKindVariableAssign,
- kKeywordKindVariableDec,
- kKeywordKindVariableInc,
- kKeywordKindConstant,
- kKeywordKindTypedef,
- kKeywordKindEndInstr,
- kKeywordKindSpecifier,
- kKeywordKindInvalid,
- kKeywordKindReturn,
- kKeywordKindCommentInline,
- kKeywordKindCommentMultiLineStart,
- kKeywordKindCommentMultiLineEnd,
- kKeywordKindEq,
- kKeywordKindNotEq,
- kKeywordKindGreaterEq,
- kKeywordKindLessEq,
- kKeywordKindPtr,
- };
-
- /// \brief Compiler keyword information struct.
- struct CompilerKeyword
- {
- std::string keyword_name;
- KeywordKind keyword_kind = kKeywordKindInvalid;
- };
- struct SyntaxLeafList final
- {
- struct SyntaxLeaf final
- {
- Int32 fUserType;
+namespace LibCompiler {
+inline auto kInvalidFrontend = "NA";
+
+/// @brief Compiler backend, implements a frontend, such as C, C++...
+/// See Toolchain, for some examples.
+class ICompilerFrontend {
+ public:
+ explicit ICompilerFrontend() = default;
+ virtual ~ICompilerFrontend() = default;
+
+ LIBCOMPILER_COPY_DEFAULT(ICompilerFrontend);
+
+ // NOTE: cast this to your user defined ast.
+ typedef void* AstType;
+
+ //! @brief Compile a syntax tree ouf of the text.
+ //! Also takes the source file name for metadata.
+
+ virtual bool Compile(std::string text, const std::string file) = 0;
+
+ //! @brief What language are we dealing with?
+ virtual const char* Language() { return kInvalidFrontend; }
+
+ virtual bool IsValid() { return strcmp(this->Language(), kInvalidFrontend) > 0; }
+};
+
+struct SyntaxLeafList;
+struct SyntaxLeafList;
+struct CompilerKeyword;
+
+/// we want to do that because to separate keywords.
+enum KeywordKind {
+ kKeywordKindNamespace,
+ kKeywordKindFunctionStart,
+ kKeywordKindFunctionEnd,
+ kKeywordKindVariable,
+ kKeywordKindVariablePtr,
+ kKeywordKindType,
+ kKeywordKindTypePtr,
+ kKeywordKindExpressionBegin,
+ kKeywordKindExpressionEnd,
+ kKeywordKindArgSeparator,
+ kKeywordKindBodyStart,
+ kKeywordKindBodyEnd,
+ kKeywordKindClass,
+ kKeywordKindPtrAccess,
+ kKeywordKindAccess,
+ kKeywordKindIf,
+ kKeywordKindElse,
+ kKeywordKindElseIf,
+ kKeywordKindVariableAssign,
+ kKeywordKindVariableDec,
+ kKeywordKindVariableInc,
+ kKeywordKindConstant,
+ kKeywordKindTypedef,
+ kKeywordKindEndInstr,
+ kKeywordKindSpecifier,
+ kKeywordKindInvalid,
+ kKeywordKindReturn,
+ kKeywordKindCommentInline,
+ kKeywordKindCommentMultiLineStart,
+ kKeywordKindCommentMultiLineEnd,
+ kKeywordKindEq,
+ kKeywordKindNotEq,
+ kKeywordKindGreaterEq,
+ kKeywordKindLessEq,
+ kKeywordKindPtr,
+};
+
+/// \brief Compiler keyword information struct.
+struct CompilerKeyword {
+ std::string keyword_name;
+ KeywordKind keyword_kind = kKeywordKindInvalid;
+};
+struct SyntaxLeafList final {
+ struct SyntaxLeaf final {
+ Int32 fUserType;
#ifdef LC_USE_STRUCTS
- CompilerKeyword fUserData;
+ CompilerKeyword fUserData;
#else
- std::string fUserData;
+ std::string fUserData;
#endif
- SyntaxLeaf() = default;
-
- std::string fUserValue;
- struct SyntaxLeaf* fNext;
- };
-
- std::vector<SyntaxLeaf> fLeafList;
- SizeType fNumLeafs;
-
- size_t SizeOf()
- {
- return fNumLeafs;
- }
- std::vector<SyntaxLeaf>& Get()
- {
- return fLeafList;
- }
- SyntaxLeaf& At(size_t index)
- {
- return fLeafList[index];
- }
- };
-
- /// find the perfect matching word in a haystack.
- /// \param haystack base string
- /// \param needle the string we search for.
- /// \return if we found it or not.
- inline bool find_word(const std::string& haystack,
- const std::string& needle) noexcept
- {
- auto index = haystack.find(needle);
-
- // check for needle validity.
- if (index == std::string::npos)
- return false;
-
- // declare lambda
- auto not_part_of_word = [&](int index) {
- if (std::isspace(haystack[index]) || std::ispunct(haystack[index]))
- return true;
-
- if (index <= 0 || index >= haystack.size())
- return true;
-
- return false;
- };
-
- return not_part_of_word(index - 1) && not_part_of_word(index + needle.size());
- }
-
- /// find a word within strict conditions and returns a range of it.
- /// \param haystack
- /// \param needle
- /// \return position of needle.
- inline std::size_t find_word_range(const std::string& haystack,
- const std::string& needle) noexcept
- {
- auto index = haystack.find(needle);
-
- // check for needle validity.
- if (index == std::string::npos)
- return false;
-
- if (!isalnum((haystack[index + needle.size() + 1])) &&
- !isdigit(haystack[index + needle.size() + 1]) &&
- !isalnum((haystack[index - needle.size() - 1])) &&
- !isdigit(haystack[index - needle.size() - 1]))
- {
- return index;
- }
-
- return false;
- }
-} // namespace LibCompiler
+ SyntaxLeaf() = default;
+
+ std::string fUserValue;
+ struct SyntaxLeaf* fNext;
+ };
+
+ std::vector<SyntaxLeaf> fLeafList;
+ SizeType fNumLeafs;
+
+ size_t SizeOf() { return fNumLeafs; }
+ std::vector<SyntaxLeaf>& Get() { return fLeafList; }
+ SyntaxLeaf& At(size_t index) { return fLeafList[index]; }
+};
+
+/// find the perfect matching word in a haystack.
+/// \param haystack base string
+/// \param needle the string we search for.
+/// \return if we found it or not.
+inline bool find_word(const std::string& haystack, const std::string& needle) noexcept {
+ auto index = haystack.find(needle);
+
+ // check for needle validity.
+ if (index == std::string::npos) return false;
+
+ // declare lambda
+ auto not_part_of_word = [&](int index) {
+ if (std::isspace(haystack[index]) || std::ispunct(haystack[index])) return true;
+
+ if (index <= 0 || index >= haystack.size()) return true;
+
+ return false;
+ };
+
+ return not_part_of_word(index - 1) && not_part_of_word(index + needle.size());
+}
+
+/// find a word within strict conditions and returns a range of it.
+/// \param haystack
+/// \param needle
+/// \return position of needle.
+inline std::size_t find_word_range(const std::string& haystack,
+ const std::string& needle) noexcept {
+ auto index = haystack.find(needle);
+
+ // check for needle validity.
+ if (index == std::string::npos) return false;
+
+ if (!isalnum((haystack[index + needle.size() + 1])) &&
+ !isdigit(haystack[index + needle.size() + 1]) &&
+ !isalnum((haystack[index - needle.size() - 1])) &&
+ !isdigit(haystack[index - needle.size() - 1])) {
+ return index;
+ }
+
+ return false;
+}
+} // namespace LibCompiler
diff --git a/dev/LibCompiler/Ref.h b/dev/LibCompiler/Ref.h
index 117083c..c5188b5 100644
--- a/dev/LibCompiler/Ref.h
+++ b/dev/LibCompiler/Ref.h
@@ -12,92 +12,64 @@
#include <LibCompiler/Defines.h>
-namespace LibCompiler
-{
- // @author EL Mahrouss Amlal
- // @brief Reference holder class, refers to a pointer of data in static memory.
- template <typename T>
- class Ref final
- {
- public:
- explicit Ref() = default;
-
- ~Ref()
- {
- if (m_Strong)
- {
- (*m_Class).~T();
- }
- }
-
- LIBCOMPILER_COPY_DEFAULT(Ref);
-
- public:
- explicit Ref(T cls, const Bool& strong = false)
- : m_Class(&cls), m_Strong(strong)
- {
- }
-
- Ref& operator=(T ref)
- {
- *m_Class = ref;
- return *this;
- }
-
- public:
- T* operator->() const
- {
- return m_Class;
- }
-
- T& Leak()
- {
- return *m_Class;
- }
-
- T operator*()
- {
- return *m_Class;
- }
-
- Bool IsStrong() const
- {
- return m_Strong;
- }
-
- operator bool()
- {
- return *m_Class;
- }
-
- private:
- T* m_Class{nullptr};
- Bool m_Strong{false};
- };
-
- // @author EL Mahrouss Amlal
- // @brief Non null Reference holder class, refers to a pointer of data in static memory.
- template <typename T>
- class NonNullRef final
- {
- public:
- explicit NonNullRef() = delete;
-
- explicit NonNullRef(T* ref)
- : m_Ref(ref, true)
- {
- }
-
- Ref<T>& operator->()
- {
- MUST_PASS(m_Ref);
- return m_Ref;
- }
-
- NonNullRef& operator=(const NonNullRef<T>& ref) = delete;
- NonNullRef(const NonNullRef<T>& ref) = default;
-
- private:
- Ref<T> m_Ref{nullptr};
- };
-} // namespace LibCompiler
+namespace LibCompiler {
+// @author EL Mahrouss Amlal
+// @brief Reference holder class, refers to a pointer of data in static memory.
+template <typename T>
+class Ref final {
+ public:
+ explicit Ref() = default;
+
+ ~Ref() {
+ if (m_Strong) {
+ (*m_Class).~T();
+ }
+ }
+
+ LIBCOMPILER_COPY_DEFAULT(Ref);
+
+ public:
+ explicit Ref(T cls, const Bool& strong = false) : m_Class(&cls), m_Strong(strong) {}
+
+ Ref& operator=(T ref) {
+ *m_Class = ref;
+ return *this;
+ }
+
+ public:
+ T* operator->() const { return m_Class; }
+
+ T& Leak() { return *m_Class; }
+
+ T operator*() { return *m_Class; }
+
+ Bool IsStrong() const { return m_Strong; }
+
+ operator bool() { return *m_Class; }
+
+ private:
+ T* m_Class{nullptr};
+ Bool m_Strong{false};
+};
+
+// @author EL Mahrouss Amlal
+// @brief Non null Reference holder class, refers to a pointer of data in static memory.
+template <typename T>
+class NonNullRef final {
+ public:
+ explicit NonNullRef() = delete;
+
+ explicit NonNullRef(T* ref) : m_Ref(ref, true) {}
+
+ Ref<T>& operator->() {
+ MUST_PASS(m_Ref);
+ return m_Ref;
+ }
+
+ NonNullRef& operator=(const NonNullRef<T>& ref) = delete;
+ NonNullRef(const NonNullRef<T>& ref) = default;
+
+ private:
+ Ref<T> m_Ref{nullptr};
+};
+} // namespace LibCompiler
diff --git a/dev/LibCompiler/StringView.h b/dev/LibCompiler/StringView.h
index b65121e..18003a3 100644
--- a/dev/LibCompiler/StringView.h
+++ b/dev/LibCompiler/StringView.h
@@ -12,79 +12,66 @@
#include <LibCompiler/Defines.h>
#include <LibCompiler/ErrorOr.h>
-namespace LibCompiler
-{
- /**
- * @brief StringView class, contains a C string and manages it.
- * @note No need to manage it it's getting deleted by default.
- */
-
- class StringView final
- {
- public:
- explicit StringView() = delete;
-
- explicit StringView(SizeType Sz) noexcept
- : m_Sz(Sz)
- {
- m_Data = new CharType[Sz];
- assert(m_Data);
- }
-
- ~StringView() noexcept
- {
- if (m_Data)
- {
- memset(m_Data, 0, m_Sz);
- delete[] m_Data;
-
- m_Data = nullptr;
- }
- }
-
- LIBCOMPILER_COPY_DEFAULT(StringView);
-
- CharType* Data();
- const CharType* CData() const;
- SizeType Length() const;
-
- bool operator==(const CharType* rhs) const;
- bool operator!=(const CharType* rhs) const;
-
- bool operator==(const StringView& rhs) const;
- bool operator!=(const StringView& rhs) const;
-
- StringView& operator+=(const CharType* rhs);
- StringView& operator+=(const StringView& rhs);
-
- operator bool()
- {
- return m_Data && m_Data[0] != 0;
- }
-
- bool operator!()
- {
- return !m_Data || m_Data[0] == 0;
- }
-
- private:
- CharType* m_Data{nullptr};
- SizeType m_Sz{0};
- SizeType m_Cur{0};
-
- friend class StringBuilder;
- };
-
- /**
- * @brief StringBuilder class
- * @note These results shall call delete[] after they're used.
- */
- struct StringBuilder final
- {
- static StringView Construct(const CharType* data);
- static const char* FromInt(const char* fmt, int n);
- static const char* FromBool(const char* fmt, bool n);
- static const char* Format(const char* fmt, const char* from);
- static bool Equals(const char* lhs, const char* rhs);
- };
-} // namespace LibCompiler
+namespace LibCompiler {
+/**
+ * @brief StringView class, contains a C string and manages it.
+ * @note No need to manage it it's getting deleted by default.
+ */
+
+class StringView final {
+ public:
+ explicit StringView() = delete;
+
+ explicit StringView(SizeType Sz) noexcept : m_Sz(Sz) {
+ m_Data = new CharType[Sz];
+ assert(m_Data);
+ }
+
+ ~StringView() noexcept {
+ if (m_Data) {
+ memset(m_Data, 0, m_Sz);
+ delete[] m_Data;
+
+ m_Data = nullptr;
+ }
+ }
+
+ LIBCOMPILER_COPY_DEFAULT(StringView);
+
+ CharType* Data();
+ const CharType* CData() const;
+ SizeType Length() const;
+
+ bool operator==(const CharType* rhs) const;
+ bool operator!=(const CharType* rhs) const;
+
+ bool operator==(const StringView& rhs) const;
+ bool operator!=(const StringView& rhs) const;
+
+ StringView& operator+=(const CharType* rhs);
+ StringView& operator+=(const StringView& rhs);
+
+ operator bool() { return m_Data && m_Data[0] != 0; }
+
+ bool operator!() { return !m_Data || m_Data[0] == 0; }
+
+ private:
+ CharType* m_Data{nullptr};
+ SizeType m_Sz{0};
+ SizeType m_Cur{0};
+
+ friend class StringBuilder;
+};
+
+/**
+ * @brief StringBuilder class
+ * @note These results shall call delete[] after they're used.
+ */
+struct StringBuilder final {
+ static StringView Construct(const CharType* data);
+ static const char* FromInt(const char* fmt, int n);
+ static const char* FromBool(const char* fmt, bool n);
+ static const char* Format(const char* fmt, const char* from);
+ static bool Equals(const char* lhs, const char* rhs);
+};
+} // namespace LibCompiler
diff --git a/dev/LibCompiler/UUID.h b/dev/LibCompiler/UUID.h
index 84ffd43..d54eec7 100644
--- a/dev/LibCompiler/UUID.h
+++ b/dev/LibCompiler/UUID.h
@@ -63,921 +63,773 @@
#endif
-namespace uuids
-{
+namespace uuids {
#ifdef __cpp_lib_span
- template <class ElementType, std::size_t Extent>
- using span = std::span<ElementType, Extent>;
+template <class ElementType, std::size_t Extent>
+using span = std::span<ElementType, Extent>;
#else
- template <class ElementType, std::ptrdiff_t Extent>
- using span = gsl::span<ElementType, Extent>;
+template <class ElementType, std::ptrdiff_t Extent>
+using span = gsl::span<ElementType, Extent>;
#endif
- namespace Detail
- {
- template <typename TChar>
- [[nodiscard]] constexpr inline unsigned char hex2char(TChar const ch) noexcept
- {
- if (ch >= static_cast<TChar>('0') && ch <= static_cast<TChar>('9'))
- return static_cast<unsigned char>(ch - static_cast<TChar>('0'));
- if (ch >= static_cast<TChar>('a') && ch <= static_cast<TChar>('f'))
- return static_cast<unsigned char>(10 + ch - static_cast<TChar>('a'));
- if (ch >= static_cast<TChar>('A') && ch <= static_cast<TChar>('F'))
- return static_cast<unsigned char>(10 + ch - static_cast<TChar>('A'));
- return 0;
- }
-
- template <typename TChar>
- [[nodiscard]] constexpr inline bool is_hex(TChar const ch) noexcept
- {
- return (ch >= static_cast<TChar>('0') && ch <= static_cast<TChar>('9')) ||
- (ch >= static_cast<TChar>('a') && ch <= static_cast<TChar>('f')) ||
- (ch >= static_cast<TChar>('A') && ch <= static_cast<TChar>('F'));
- }
-
- template <typename TChar>
- [[nodiscard]] constexpr std::basic_string_view<TChar> to_string_view(
- TChar const* str) noexcept
- {
- if (str)
- return str;
- return {};
- }
-
- template <typename StringType>
- [[nodiscard]] constexpr std::basic_string_view<typename StringType::value_type,
- typename StringType::traits_type>
- to_string_view(StringType const& str) noexcept
- {
- return str;
- }
-
- class sha1
- {
- public:
- using digest32_t = uint32_t[5];
- using digest8_t = uint8_t[20];
-
- static constexpr unsigned int block_bytes = 64;
-
- [[nodiscard]] inline static uint32_t left_rotate(
- uint32_t value, size_t const count) noexcept
- {
- return (value << count) ^ (value >> (32 - count));
- }
-
- sha1()
- {
- reset();
- }
-
- void reset() noexcept
- {
- m_digest[0] = 0x67452301;
- m_digest[1] = 0xEFCDAB89;
- m_digest[2] = 0x98BADCFE;
- m_digest[3] = 0x10325476;
- m_digest[4] = 0xC3D2E1F0;
- m_blockByteIndex = 0;
- m_byteCount = 0;
- }
-
- void process_byte(uint8_t octet)
- {
- this->m_block[this->m_blockByteIndex++] = octet;
- ++this->m_byteCount;
- if (m_blockByteIndex == block_bytes)
- {
- this->m_blockByteIndex = 0;
- process_block();
- }
- }
-
- void process_block(void const* const start, void const* const end)
- {
- const uint8_t* begin = static_cast<const uint8_t*>(start);
- const uint8_t* finish = static_cast<const uint8_t*>(end);
- while (begin != finish)
- {
- process_byte(*begin);
- begin++;
- }
- }
-
- void process_bytes(void const* const data, size_t const len)
- {
- const uint8_t* block = static_cast<const uint8_t*>(data);
- process_block(block, block + len);
- }
-
- uint32_t const* get_digest(digest32_t digest)
- {
- size_t const bitCount = this->m_byteCount * 8;
- process_byte(0x80);
- if (this->m_blockByteIndex > 56)
- {
- while (m_blockByteIndex != 0)
- {
- process_byte(0);
- }
- while (m_blockByteIndex < 56)
- {
- process_byte(0);
- }
- }
- else
- {
- while (m_blockByteIndex < 56)
- {
- process_byte(0);
- }
- }
- process_byte(0);
- process_byte(0);
- process_byte(0);
- process_byte(0);
- process_byte(static_cast<unsigned char>((bitCount >> 24) & 0xFF));
- process_byte(static_cast<unsigned char>((bitCount >> 16) & 0xFF));
- process_byte(static_cast<unsigned char>((bitCount >> 8) & 0xFF));
- process_byte(static_cast<unsigned char>((bitCount)&0xFF));
-
- memcpy(digest, m_digest, 5 * sizeof(uint32_t));
- return digest;
- }
-
- uint8_t const* get_digest_bytes(digest8_t digest)
- {
- digest32_t d32;
- get_digest(d32);
- size_t di = 0;
- digest[di++] = static_cast<uint8_t>(d32[0] >> 24);
- digest[di++] = static_cast<uint8_t>(d32[0] >> 16);
- digest[di++] = static_cast<uint8_t>(d32[0] >> 8);
- digest[di++] = static_cast<uint8_t>(d32[0] >> 0);
-
- digest[di++] = static_cast<uint8_t>(d32[1] >> 24);
- digest[di++] = static_cast<uint8_t>(d32[1] >> 16);
- digest[di++] = static_cast<uint8_t>(d32[1] >> 8);
- digest[di++] = static_cast<uint8_t>(d32[1] >> 0);
-
- digest[di++] = static_cast<uint8_t>(d32[2] >> 24);
- digest[di++] = static_cast<uint8_t>(d32[2] >> 16);
- digest[di++] = static_cast<uint8_t>(d32[2] >> 8);
- digest[di++] = static_cast<uint8_t>(d32[2] >> 0);
-
- digest[di++] = static_cast<uint8_t>(d32[3] >> 24);
- digest[di++] = static_cast<uint8_t>(d32[3] >> 16);
- digest[di++] = static_cast<uint8_t>(d32[3] >> 8);
- digest[di++] = static_cast<uint8_t>(d32[3] >> 0);
-
- digest[di++] = static_cast<uint8_t>(d32[4] >> 24);
- digest[di++] = static_cast<uint8_t>(d32[4] >> 16);
- digest[di++] = static_cast<uint8_t>(d32[4] >> 8);
- digest[di++] = static_cast<uint8_t>(d32[4] >> 0);
-
- return digest;
- }
-
- private:
- void process_block()
- {
- uint32_t w[80];
- for (size_t i = 0; i < 16; i++)
- {
- w[i] = static_cast<uint32_t>(m_block[i * 4 + 0] << 24);
- w[i] |= static_cast<uint32_t>(m_block[i * 4 + 1] << 16);
- w[i] |= static_cast<uint32_t>(m_block[i * 4 + 2] << 8);
- w[i] |= static_cast<uint32_t>(m_block[i * 4 + 3]);
- }
- for (size_t i = 16; i < 80; i++)
- {
- w[i] = left_rotate((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]), 1);
- }
-
- uint32_t a = m_digest[0];
- uint32_t b = m_digest[1];
- uint32_t c = m_digest[2];
- uint32_t d = m_digest[3];
- uint32_t e = m_digest[4];
-
- for (std::size_t i = 0; i < 80; ++i)
- {
- uint32_t f = 0;
- uint32_t k = 0;
-
- if (i < 20)
- {
- f = (b & c) | (~b & d);
- k = 0x5A827999;
- }
- else if (i < 40)
- {
- f = b ^ c ^ d;
- k = 0x6ED9EBA1;
- }
- else if (i < 60)
- {
- f = (b & c) | (b & d) | (c & d);
- k = 0x8F1BBCDC;
- }
- else
- {
- f = b ^ c ^ d;
- k = 0xCA62C1D6;
- }
- uint32_t temp = left_rotate(a, 5) + f + e + k + w[i];
- e = d;
- d = c;
- c = left_rotate(b, 30);
- b = a;
- a = temp;
- }
-
- m_digest[0] += a;
- m_digest[1] += b;
- m_digest[2] += c;
- m_digest[3] += d;
- m_digest[4] += e;
- }
-
- private:
- digest32_t m_digest;
- uint8_t m_block[64];
- size_t m_blockByteIndex;
- size_t m_byteCount;
- };
-
- template <typename CharT>
- inline constexpr CharT empty_guid[37] = "00000000-0000-0000-0000-000000000000";
-
- template <>
- inline constexpr wchar_t empty_guid<wchar_t>[37] =
- L"00000000-0000-0000-0000-000000000000";
-
- template <typename CharT>
- inline constexpr CharT guid_encoder[17] = "0123456789abcdef";
-
- template <>
- inline constexpr wchar_t guid_encoder<wchar_t>[17] = L"0123456789abcdef";
- } // namespace Detail
-
- // --------------------------------------------------------------------------------------------------------------------------
- // UUID format https://tools.ietf.org/html/rfc4122
- // --------------------------------------------------------------------------------------------------------------------------
-
- // --------------------------------------------------------------------------------------------------------------------------
- // Field NDR Data Type Octet # Note
- // --------------------------------------------------------------------------------------------------------------------------
- // time_low unsigned long 0 - 3 The low field
- // of the timestamp. time_mid unsigned short 4 - 5
- // The middle field of the timestamp. time_hi_and_version unsigned
- // short 6 - 7 The high field of the timestamp multiplexed
- // with the version number. clock_seq_hi_and_reserved unsigned small 8
- // The high field of the clock sequence multiplexed with the variant.
- // clock_seq_low unsigned small 9 The low
- // field of the clock sequence. node character 10
- // - 15 The spatially unique node identifier.
- // --------------------------------------------------------------------------------------------------------------------------
- // 0 1 2 3
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | time_low |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | time_mid | time_hi_and_version |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // |clk_seq_hi_res | clk_seq_low | node (0-1) |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | node (2-5) |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
- // --------------------------------------------------------------------------------------------------------------------------
- // enumerations
- // --------------------------------------------------------------------------------------------------------------------------
-
- // indicated by a bit pattern in octet 8, marked with N in
- // xxxxxxxx-xxxx-xxxx-Nxxx-xxxxxxxxxxxx
- enum class uuid_variant
- {
- // NCS backward compatibility (with the obsolete Apollo Network Computing
- // System 1.5 UUID format) N bit pattern: 0xxx > the first 6 octets of the
- // UUID are a 48-bit timestamp (the number of 4 microsecond units of time
- // since 1 Jan 1980 UTC); > the next 2 octets are reserved; > the next octet
- // is the "address family"; > the final 7 octets are a 56-bit host ID in the
- // form specified by the address family
- ncs,
-
- // RFC 4122/DCE 1.1
- // N bit pattern: 10xx
- // > big-endian byte order
- rfc,
-
- // Microsoft Corporation backward compatibility
- // N bit pattern: 110x
- // > little endian byte order
- // > formely used in the Component Object Model (COM) library
- microsoft,
-
- // reserved for possible future definition
- // N bit pattern: 111x
- reserved
- };
-
- // indicated by a bit pattern in octet 6, marked with M in
- // xxxxxxxx-xxxx-Mxxx-xxxx-xxxxxxxxxxxx
- enum class uuid_version
- {
- none = 0, // only possible for nil or invalid uuids
- time_based = 1, // The time-based version specified in RFC 4122
- dce_security = 2, // DCE Security version, with embedded POSIX UIDs.
- name_based_md5 =
- 3, // The name-based version specified in RFS 4122 with MD5 hashing
- random_number_based = 4, // The randomly or pseudo-randomly generated version
- // specified in RFS 4122
- name_based_sha1 =
- 5 // The name-based version specified in RFS 4122 with SHA1 hashing
- };
-
- // Forward declare uuid & to_string so that we can declare to_string as a friend
- // later.
- class uuid;
- template <class CharT = char, class Traits = std::char_traits<CharT>, class Allocator = std::allocator<CharT>>
- std::basic_string<CharT, Traits, Allocator> to_string(uuid const& id);
-
- // --------------------------------------------------------------------------------------------------------------------------
- // uuid class
- // --------------------------------------------------------------------------------------------------------------------------
- class uuid
- {
- public:
- using value_type = uint8_t;
-
- constexpr uuid() noexcept = default;
-
- uuid(value_type (&arr)[16]) noexcept
- {
- std::copy(std::cbegin(arr), std::cend(arr), std::begin(data));
- }
-
- constexpr uuid(std::array<value_type, 16> const& arr) noexcept
- : data{arr}
- {
- }
-
- explicit uuid(span<value_type, 16> bytes)
- {
- std::copy(std::cbegin(bytes), std::cend(bytes), std::begin(data));
- }
-
- template <typename ForwardIterator>
- explicit uuid(ForwardIterator first, ForwardIterator last)
- {
- if (std::distance(first, last) == 16)
- std::copy(first, last, std::begin(data));
- }
-
- [[nodiscard]] constexpr uuid_variant variant() const noexcept
- {
- if ((data[8] & 0x80) == 0x00)
- return uuid_variant::ncs;
- else if ((data[8] & 0xC0) == 0x80)
- return uuid_variant::rfc;
- else if ((data[8] & 0xE0) == 0xC0)
- return uuid_variant::microsoft;
- else
- return uuid_variant::reserved;
- }
-
- [[nodiscard]] constexpr uuid_version version() const noexcept
- {
- if ((data[6] & 0xF0) == 0x10)
- return uuid_version::time_based;
- else if ((data[6] & 0xF0) == 0x20)
- return uuid_version::dce_security;
- else if ((data[6] & 0xF0) == 0x30)
- return uuid_version::name_based_md5;
- else if ((data[6] & 0xF0) == 0x40)
- return uuid_version::random_number_based;
- else if ((data[6] & 0xF0) == 0x50)
- return uuid_version::name_based_sha1;
- else
- return uuid_version::none;
- }
-
- [[nodiscard]] constexpr bool is_nil() const noexcept
- {
- for (size_t i = 0; i < data.size(); ++i)
- if (data[i] != 0)
- return false;
- return true;
- }
-
- void swap(uuid& other) noexcept
- {
- data.swap(other.data);
- }
-
- [[nodiscard]] inline span<std::byte const, 16> as_bytes() const
- {
- return span<std::byte const, 16>(
- reinterpret_cast<std::byte const*>(data.data()), 16);
- }
-
- template <typename StringType>
- [[nodiscard]] constexpr static bool is_valid_uuid(
- StringType const& in_str) noexcept
- {
- auto str = Detail::to_string_view(in_str);
- bool firstDigit = true;
- size_t hasBraces = 0;
- size_t index = 0;
-
- if (str.empty())
- return false;
-
- if (str.front() == '{')
- hasBraces = 1;
- if (hasBraces && str.back() != '}')
- return false;
-
- for (size_t i = hasBraces; i < str.size() - hasBraces; ++i)
- {
- if (str[i] == '-')
- continue;
-
- if (index >= 16 || !Detail::is_hex(str[i]))
- {
- return false;
- }
-
- if (firstDigit)
- {
- firstDigit = false;
- }
- else
- {
- index++;
- firstDigit = true;
- }
- }
-
- if (index < 16)
- {
- return false;
- }
-
- return true;
- }
-
- template <typename StringType>
- [[nodiscard]] constexpr static std::optional<uuid> from_string(
- StringType const& in_str) noexcept
- {
- auto str = Detail::to_string_view(in_str);
- bool firstDigit = true;
- size_t hasBraces = 0;
- size_t index = 0;
-
- std::array<uint8_t, 16> data{{0}};
-
- if (str.empty())
- return {};
-
- if (str.front() == '{')
- hasBraces = 1;
- if (hasBraces && str.back() != '}')
- return {};
-
- for (size_t i = hasBraces; i < str.size() - hasBraces; ++i)
- {
- if (str[i] == '-')
- continue;
-
- if (index >= 16 || !Detail::is_hex(str[i]))
- {
- return {};
- }
-
- if (firstDigit)
- {
- data[index] = static_cast<uint8_t>(Detail::hex2char(str[i]) << 4);
- firstDigit = false;
- }
- else
- {
- data[index] =
- static_cast<uint8_t>(data[index] | Detail::hex2char(str[i]));
- index++;
- firstDigit = true;
- }
- }
-
- if (index < 16)
- {
- return {};
- }
-
- return uuid{data};
- }
-
- private:
- std::array<value_type, 16> data{{0}};
-
- friend bool operator==(uuid const& lhs, uuid const& rhs) noexcept;
- friend bool operator<(uuid const& lhs, uuid const& rhs) noexcept;
-
- template <class Elem, class Traits>
- friend std::basic_ostream<Elem, Traits>& operator<<(
- std::basic_ostream<Elem, Traits>& s, uuid const& id);
-
- template <class CharT, class Traits, class Allocator>
- friend std::basic_string<CharT, Traits, Allocator> to_string(uuid const& id);
-
- friend std::hash<uuid>;
- };
-
- // --------------------------------------------------------------------------------------------------------------------------
- // operators and non-member functions
- // --------------------------------------------------------------------------------------------------------------------------
-
- [[nodiscard]] inline bool operator==(uuid const& lhs,
- uuid const& rhs) noexcept
- {
- return lhs.data == rhs.data;
- }
-
- [[nodiscard]] inline bool operator!=(uuid const& lhs,
- uuid const& rhs) noexcept
- {
- return !(lhs == rhs);
- }
-
- [[nodiscard]] inline bool operator<(uuid const& lhs, uuid const& rhs) noexcept
- {
- return lhs.data < rhs.data;
- }
-
- template <class CharT, class Traits, class Allocator>
- [[nodiscard]] inline std::basic_string<CharT, Traits, Allocator> to_string(
- uuid const& id)
- {
- std::basic_string<CharT, Traits, Allocator> uustr{Detail::empty_guid<CharT>};
-
- for (size_t i = 0, index = 0; i < 36; ++i)
- {
- if (i == 8 || i == 13 || i == 18 || i == 23)
- {
- continue;
- }
- uustr[i] = Detail::guid_encoder<CharT>[id.data[index] >> 4 & 0x0f];
- uustr[++i] = Detail::guid_encoder<CharT>[id.data[index] & 0x0f];
- index++;
- }
-
- return uustr;
- }
-
- template <class Elem, class Traits>
- std::basic_ostream<Elem, Traits>& operator<<(
- std::basic_ostream<Elem, Traits>& s, uuid const& id)
- {
- s << to_string(id);
- return s;
- }
-
- inline void swap(uuids::uuid& lhs, uuids::uuid& rhs) noexcept
- {
- lhs.swap(rhs);
- }
-
- // --------------------------------------------------------------------------------------------------------------------------
- // namespace IDs that could be used for generating name-based uuids
- // --------------------------------------------------------------------------------------------------------------------------
-
- // Name string is a fully-qualified domain name
- static uuid uuid_namespace_dns{{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1,
- 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30,
- 0xc8}};
-
- // Name string is a URL
- static uuid uuid_namespace_url{{0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1,
- 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30,
- 0xc8}};
-
- // Name string is an ISO OID (See https://oidref.com/,
- // https://en.wikipedia.org/wiki/Object_identifier)
- static uuid uuid_namespace_oid{{0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1,
- 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30,
- 0xc8}};
-
- // Name string is an X.500 DN, in DER or a text output format (See
- // https://en.wikipedia.org/wiki/X.500,
- // https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One)
- static uuid uuid_namespace_x500{{0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1,
- 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30,
- 0xc8}};
-
- // --------------------------------------------------------------------------------------------------------------------------
- // uuid generators
- // --------------------------------------------------------------------------------------------------------------------------
+namespace Detail {
+ template <typename TChar>
+ [[nodiscard]] constexpr inline unsigned char hex2char(TChar const ch) noexcept {
+ if (ch >= static_cast<TChar>('0') && ch <= static_cast<TChar>('9'))
+ return static_cast<unsigned char>(ch - static_cast<TChar>('0'));
+ if (ch >= static_cast<TChar>('a') && ch <= static_cast<TChar>('f'))
+ return static_cast<unsigned char>(10 + ch - static_cast<TChar>('a'));
+ if (ch >= static_cast<TChar>('A') && ch <= static_cast<TChar>('F'))
+ return static_cast<unsigned char>(10 + ch - static_cast<TChar>('A'));
+ return 0;
+ }
+
+ template <typename TChar>
+ [[nodiscard]] constexpr inline bool is_hex(TChar const ch) noexcept {
+ return (ch >= static_cast<TChar>('0') && ch <= static_cast<TChar>('9')) ||
+ (ch >= static_cast<TChar>('a') && ch <= static_cast<TChar>('f')) ||
+ (ch >= static_cast<TChar>('A') && ch <= static_cast<TChar>('F'));
+ }
+
+ template <typename TChar>
+ [[nodiscard]] constexpr std::basic_string_view<TChar> to_string_view(TChar const* str) noexcept {
+ if (str) return str;
+ return {};
+ }
+
+ template <typename StringType>
+ [[nodiscard]] constexpr std::basic_string_view<typename StringType::value_type,
+ typename StringType::traits_type>
+ to_string_view(StringType const& str) noexcept {
+ return str;
+ }
+
+ class sha1 {
+ public:
+ using digest32_t = uint32_t[5];
+ using digest8_t = uint8_t[20];
+
+ static constexpr unsigned int block_bytes = 64;
+
+ [[nodiscard]] inline static uint32_t left_rotate(uint32_t value, size_t const count) noexcept {
+ return (value << count) ^ (value >> (32 - count));
+ }
+
+ sha1() { reset(); }
+
+ void reset() noexcept {
+ m_digest[0] = 0x67452301;
+ m_digest[1] = 0xEFCDAB89;
+ m_digest[2] = 0x98BADCFE;
+ m_digest[3] = 0x10325476;
+ m_digest[4] = 0xC3D2E1F0;
+ m_blockByteIndex = 0;
+ m_byteCount = 0;
+ }
+
+ void process_byte(uint8_t octet) {
+ this->m_block[this->m_blockByteIndex++] = octet;
+ ++this->m_byteCount;
+ if (m_blockByteIndex == block_bytes) {
+ this->m_blockByteIndex = 0;
+ process_block();
+ }
+ }
+
+ void process_block(void const* const start, void const* const end) {
+ const uint8_t* begin = static_cast<const uint8_t*>(start);
+ const uint8_t* finish = static_cast<const uint8_t*>(end);
+ while (begin != finish) {
+ process_byte(*begin);
+ begin++;
+ }
+ }
+
+ void process_bytes(void const* const data, size_t const len) {
+ const uint8_t* block = static_cast<const uint8_t*>(data);
+ process_block(block, block + len);
+ }
+
+ uint32_t const* get_digest(digest32_t digest) {
+ size_t const bitCount = this->m_byteCount * 8;
+ process_byte(0x80);
+ if (this->m_blockByteIndex > 56) {
+ while (m_blockByteIndex != 0) {
+ process_byte(0);
+ }
+ while (m_blockByteIndex < 56) {
+ process_byte(0);
+ }
+ } else {
+ while (m_blockByteIndex < 56) {
+ process_byte(0);
+ }
+ }
+ process_byte(0);
+ process_byte(0);
+ process_byte(0);
+ process_byte(0);
+ process_byte(static_cast<unsigned char>((bitCount >> 24) & 0xFF));
+ process_byte(static_cast<unsigned char>((bitCount >> 16) & 0xFF));
+ process_byte(static_cast<unsigned char>((bitCount >> 8) & 0xFF));
+ process_byte(static_cast<unsigned char>((bitCount) & 0xFF));
+
+ memcpy(digest, m_digest, 5 * sizeof(uint32_t));
+ return digest;
+ }
+
+ uint8_t const* get_digest_bytes(digest8_t digest) {
+ digest32_t d32;
+ get_digest(d32);
+ size_t di = 0;
+ digest[di++] = static_cast<uint8_t>(d32[0] >> 24);
+ digest[di++] = static_cast<uint8_t>(d32[0] >> 16);
+ digest[di++] = static_cast<uint8_t>(d32[0] >> 8);
+ digest[di++] = static_cast<uint8_t>(d32[0] >> 0);
+
+ digest[di++] = static_cast<uint8_t>(d32[1] >> 24);
+ digest[di++] = static_cast<uint8_t>(d32[1] >> 16);
+ digest[di++] = static_cast<uint8_t>(d32[1] >> 8);
+ digest[di++] = static_cast<uint8_t>(d32[1] >> 0);
+
+ digest[di++] = static_cast<uint8_t>(d32[2] >> 24);
+ digest[di++] = static_cast<uint8_t>(d32[2] >> 16);
+ digest[di++] = static_cast<uint8_t>(d32[2] >> 8);
+ digest[di++] = static_cast<uint8_t>(d32[2] >> 0);
+
+ digest[di++] = static_cast<uint8_t>(d32[3] >> 24);
+ digest[di++] = static_cast<uint8_t>(d32[3] >> 16);
+ digest[di++] = static_cast<uint8_t>(d32[3] >> 8);
+ digest[di++] = static_cast<uint8_t>(d32[3] >> 0);
+
+ digest[di++] = static_cast<uint8_t>(d32[4] >> 24);
+ digest[di++] = static_cast<uint8_t>(d32[4] >> 16);
+ digest[di++] = static_cast<uint8_t>(d32[4] >> 8);
+ digest[di++] = static_cast<uint8_t>(d32[4] >> 0);
+
+ return digest;
+ }
+
+ private:
+ void process_block() {
+ uint32_t w[80];
+ for (size_t i = 0; i < 16; i++) {
+ w[i] = static_cast<uint32_t>(m_block[i * 4 + 0] << 24);
+ w[i] |= static_cast<uint32_t>(m_block[i * 4 + 1] << 16);
+ w[i] |= static_cast<uint32_t>(m_block[i * 4 + 2] << 8);
+ w[i] |= static_cast<uint32_t>(m_block[i * 4 + 3]);
+ }
+ for (size_t i = 16; i < 80; i++) {
+ w[i] = left_rotate((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]), 1);
+ }
+
+ uint32_t a = m_digest[0];
+ uint32_t b = m_digest[1];
+ uint32_t c = m_digest[2];
+ uint32_t d = m_digest[3];
+ uint32_t e = m_digest[4];
+
+ for (std::size_t i = 0; i < 80; ++i) {
+ uint32_t f = 0;
+ uint32_t k = 0;
+
+ if (i < 20) {
+ f = (b & c) | (~b & d);
+ k = 0x5A827999;
+ } else if (i < 40) {
+ f = b ^ c ^ d;
+ k = 0x6ED9EBA1;
+ } else if (i < 60) {
+ f = (b & c) | (b & d) | (c & d);
+ k = 0x8F1BBCDC;
+ } else {
+ f = b ^ c ^ d;
+ k = 0xCA62C1D6;
+ }
+ uint32_t temp = left_rotate(a, 5) + f + e + k + w[i];
+ e = d;
+ d = c;
+ c = left_rotate(b, 30);
+ b = a;
+ a = temp;
+ }
+
+ m_digest[0] += a;
+ m_digest[1] += b;
+ m_digest[2] += c;
+ m_digest[3] += d;
+ m_digest[4] += e;
+ }
+
+ private:
+ digest32_t m_digest;
+ uint8_t m_block[64];
+ size_t m_blockByteIndex;
+ size_t m_byteCount;
+ };
+
+ template <typename CharT>
+ inline constexpr CharT empty_guid[37] = "00000000-0000-0000-0000-000000000000";
+
+ template <>
+ inline constexpr wchar_t empty_guid<wchar_t>[37] = L"00000000-0000-0000-0000-000000000000";
+
+ template <typename CharT>
+ inline constexpr CharT guid_encoder[17] = "0123456789abcdef";
+
+ template <>
+ inline constexpr wchar_t guid_encoder<wchar_t>[17] = L"0123456789abcdef";
+} // namespace Detail
+
+// --------------------------------------------------------------------------------------------------------------------------
+// UUID format https://tools.ietf.org/html/rfc4122
+// --------------------------------------------------------------------------------------------------------------------------
+
+// --------------------------------------------------------------------------------------------------------------------------
+// Field NDR Data Type Octet # Note
+// --------------------------------------------------------------------------------------------------------------------------
+// time_low unsigned long 0 - 3 The low field
+// of the timestamp. time_mid unsigned short 4 - 5
+// The middle field of the timestamp. time_hi_and_version unsigned
+// short 6 - 7 The high field of the timestamp multiplexed
+// with the version number. clock_seq_hi_and_reserved unsigned small 8
+// The high field of the clock sequence multiplexed with the variant.
+// clock_seq_low unsigned small 9 The low
+// field of the clock sequence. node character 10
+// - 15 The spatially unique node identifier.
+// --------------------------------------------------------------------------------------------------------------------------
+// 0 1 2 3
+// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | time_low |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | time_mid | time_hi_and_version |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// |clk_seq_hi_res | clk_seq_low | node (0-1) |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | node (2-5) |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+// --------------------------------------------------------------------------------------------------------------------------
+// enumerations
+// --------------------------------------------------------------------------------------------------------------------------
+
+// indicated by a bit pattern in octet 8, marked with N in
+// xxxxxxxx-xxxx-xxxx-Nxxx-xxxxxxxxxxxx
+enum class uuid_variant {
+ // NCS backward compatibility (with the obsolete Apollo Network Computing
+ // System 1.5 UUID format) N bit pattern: 0xxx > the first 6 octets of the
+ // UUID are a 48-bit timestamp (the number of 4 microsecond units of time
+ // since 1 Jan 1980 UTC); > the next 2 octets are reserved; > the next octet
+ // is the "address family"; > the final 7 octets are a 56-bit host ID in the
+ // form specified by the address family
+ ncs,
+
+ // RFC 4122/DCE 1.1
+ // N bit pattern: 10xx
+ // > big-endian byte order
+ rfc,
+
+ // Microsoft Corporation backward compatibility
+ // N bit pattern: 110x
+ // > little endian byte order
+ // > formely used in the Component Object Model (COM) library
+ microsoft,
+
+ // reserved for possible future definition
+ // N bit pattern: 111x
+ reserved
+};
+
+// indicated by a bit pattern in octet 6, marked with M in
+// xxxxxxxx-xxxx-Mxxx-xxxx-xxxxxxxxxxxx
+enum class uuid_version {
+ none = 0, // only possible for nil or invalid uuids
+ time_based = 1, // The time-based version specified in RFC 4122
+ dce_security = 2, // DCE Security version, with embedded POSIX UIDs.
+ name_based_md5 = 3, // The name-based version specified in RFS 4122 with MD5 hashing
+ random_number_based = 4, // The randomly or pseudo-randomly generated version
+ // specified in RFS 4122
+ name_based_sha1 = 5 // The name-based version specified in RFS 4122 with SHA1 hashing
+};
+
+// Forward declare uuid & to_string so that we can declare to_string as a friend
+// later.
+class uuid;
+template <class CharT = char, class Traits = std::char_traits<CharT>,
+ class Allocator = std::allocator<CharT>>
+std::basic_string<CharT, Traits, Allocator> to_string(uuid const& id);
+
+// --------------------------------------------------------------------------------------------------------------------------
+// uuid class
+// --------------------------------------------------------------------------------------------------------------------------
+class uuid {
+ public:
+ using value_type = uint8_t;
+
+ constexpr uuid() noexcept = default;
+
+ uuid(value_type (&arr)[16]) noexcept {
+ std::copy(std::cbegin(arr), std::cend(arr), std::begin(data));
+ }
+
+ constexpr uuid(std::array<value_type, 16> const& arr) noexcept : data{arr} {}
+
+ explicit uuid(span<value_type, 16> bytes) {
+ std::copy(std::cbegin(bytes), std::cend(bytes), std::begin(data));
+ }
+
+ template <typename ForwardIterator>
+ explicit uuid(ForwardIterator first, ForwardIterator last) {
+ if (std::distance(first, last) == 16) std::copy(first, last, std::begin(data));
+ }
+
+ [[nodiscard]] constexpr uuid_variant variant() const noexcept {
+ if ((data[8] & 0x80) == 0x00)
+ return uuid_variant::ncs;
+ else if ((data[8] & 0xC0) == 0x80)
+ return uuid_variant::rfc;
+ else if ((data[8] & 0xE0) == 0xC0)
+ return uuid_variant::microsoft;
+ else
+ return uuid_variant::reserved;
+ }
+
+ [[nodiscard]] constexpr uuid_version version() const noexcept {
+ if ((data[6] & 0xF0) == 0x10)
+ return uuid_version::time_based;
+ else if ((data[6] & 0xF0) == 0x20)
+ return uuid_version::dce_security;
+ else if ((data[6] & 0xF0) == 0x30)
+ return uuid_version::name_based_md5;
+ else if ((data[6] & 0xF0) == 0x40)
+ return uuid_version::random_number_based;
+ else if ((data[6] & 0xF0) == 0x50)
+ return uuid_version::name_based_sha1;
+ else
+ return uuid_version::none;
+ }
+
+ [[nodiscard]] constexpr bool is_nil() const noexcept {
+ for (size_t i = 0; i < data.size(); ++i)
+ if (data[i] != 0) return false;
+ return true;
+ }
+
+ void swap(uuid& other) noexcept { data.swap(other.data); }
+
+ [[nodiscard]] inline span<std::byte const, 16> as_bytes() const {
+ return span<std::byte const, 16>(reinterpret_cast<std::byte const*>(data.data()), 16);
+ }
+
+ template <typename StringType>
+ [[nodiscard]] constexpr static bool is_valid_uuid(StringType const& in_str) noexcept {
+ auto str = Detail::to_string_view(in_str);
+ bool firstDigit = true;
+ size_t hasBraces = 0;
+ size_t index = 0;
+
+ if (str.empty()) return false;
+
+ if (str.front() == '{') hasBraces = 1;
+ if (hasBraces && str.back() != '}') return false;
+
+ for (size_t i = hasBraces; i < str.size() - hasBraces; ++i) {
+ if (str[i] == '-') continue;
+
+ if (index >= 16 || !Detail::is_hex(str[i])) {
+ return false;
+ }
+
+ if (firstDigit) {
+ firstDigit = false;
+ } else {
+ index++;
+ firstDigit = true;
+ }
+ }
+
+ if (index < 16) {
+ return false;
+ }
+
+ return true;
+ }
+
+ template <typename StringType>
+ [[nodiscard]] constexpr static std::optional<uuid> from_string(
+ StringType const& in_str) noexcept {
+ auto str = Detail::to_string_view(in_str);
+ bool firstDigit = true;
+ size_t hasBraces = 0;
+ size_t index = 0;
+
+ std::array<uint8_t, 16> data{{0}};
+
+ if (str.empty()) return {};
+
+ if (str.front() == '{') hasBraces = 1;
+ if (hasBraces && str.back() != '}') return {};
+
+ for (size_t i = hasBraces; i < str.size() - hasBraces; ++i) {
+ if (str[i] == '-') continue;
+
+ if (index >= 16 || !Detail::is_hex(str[i])) {
+ return {};
+ }
+
+ if (firstDigit) {
+ data[index] = static_cast<uint8_t>(Detail::hex2char(str[i]) << 4);
+ firstDigit = false;
+ } else {
+ data[index] = static_cast<uint8_t>(data[index] | Detail::hex2char(str[i]));
+ index++;
+ firstDigit = true;
+ }
+ }
+
+ if (index < 16) {
+ return {};
+ }
+
+ return uuid{data};
+ }
+
+ private:
+ std::array<value_type, 16> data{{0}};
+
+ friend bool operator==(uuid const& lhs, uuid const& rhs) noexcept;
+ friend bool operator<(uuid const& lhs, uuid const& rhs) noexcept;
+
+ template <class Elem, class Traits>
+ friend std::basic_ostream<Elem, Traits>& operator<<(std::basic_ostream<Elem, Traits>& s,
+ uuid const& id);
+
+ template <class CharT, class Traits, class Allocator>
+ friend std::basic_string<CharT, Traits, Allocator> to_string(uuid const& id);
+
+ friend std::hash<uuid>;
+};
+
+// --------------------------------------------------------------------------------------------------------------------------
+// operators and non-member functions
+// --------------------------------------------------------------------------------------------------------------------------
+
+[[nodiscard]] inline bool operator==(uuid const& lhs, uuid const& rhs) noexcept {
+ return lhs.data == rhs.data;
+}
+
+[[nodiscard]] inline bool operator!=(uuid const& lhs, uuid const& rhs) noexcept {
+ return !(lhs == rhs);
+}
+
+[[nodiscard]] inline bool operator<(uuid const& lhs, uuid const& rhs) noexcept {
+ return lhs.data < rhs.data;
+}
+
+template <class CharT, class Traits, class Allocator>
+[[nodiscard]] inline std::basic_string<CharT, Traits, Allocator> to_string(uuid const& id) {
+ std::basic_string<CharT, Traits, Allocator> uustr{Detail::empty_guid<CharT>};
+
+ for (size_t i = 0, index = 0; i < 36; ++i) {
+ if (i == 8 || i == 13 || i == 18 || i == 23) {
+ continue;
+ }
+ uustr[i] = Detail::guid_encoder<CharT>[id.data[index] >> 4 & 0x0f];
+ uustr[++i] = Detail::guid_encoder<CharT>[id.data[index] & 0x0f];
+ index++;
+ }
+
+ return uustr;
+}
+
+template <class Elem, class Traits>
+std::basic_ostream<Elem, Traits>& operator<<(std::basic_ostream<Elem, Traits>& s, uuid const& id) {
+ s << to_string(id);
+ return s;
+}
+
+inline void swap(uuids::uuid& lhs, uuids::uuid& rhs) noexcept {
+ lhs.swap(rhs);
+}
+
+// --------------------------------------------------------------------------------------------------------------------------
+// namespace IDs that could be used for generating name-based uuids
+// --------------------------------------------------------------------------------------------------------------------------
+
+// Name string is a fully-qualified domain name
+static uuid uuid_namespace_dns{{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00,
+ 0xc0, 0x4f, 0xd4, 0x30, 0xc8}};
+
+// Name string is a URL
+static uuid uuid_namespace_url{{0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00,
+ 0xc0, 0x4f, 0xd4, 0x30, 0xc8}};
+
+// Name string is an ISO OID (See https://oidref.com/,
+// https://en.wikipedia.org/wiki/Object_identifier)
+static uuid uuid_namespace_oid{{0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00,
+ 0xc0, 0x4f, 0xd4, 0x30, 0xc8}};
+
+// Name string is an X.500 DN, in DER or a text output format (See
+// https://en.wikipedia.org/wiki/X.500,
+// https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One)
+static uuid uuid_namespace_x500{{0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00,
+ 0xc0, 0x4f, 0xd4, 0x30, 0xc8}};
+
+// --------------------------------------------------------------------------------------------------------------------------
+// uuid generators
+// --------------------------------------------------------------------------------------------------------------------------
#ifdef UUID_SYSTEM_GENERATOR
- class uuid_system_generator
- {
- public:
- using result_type = uuid;
+class uuid_system_generator {
+ public:
+ using result_type = uuid;
- uuid operator()()
- {
+ uuid operator()() {
#ifdef _WIN32
- GUID newId;
- HRESULT hr = ::CoCreateGuid(&newId);
+ GUID newId;
+ HRESULT hr = ::CoCreateGuid(&newId);
- if (FAILED(hr))
- {
- throw std::system_error(hr, std::system_category(),
- "CoCreateGuid failed");
- }
+ if (FAILED(hr)) {
+ throw std::system_error(hr, std::system_category(), "CoCreateGuid failed");
+ }
- std::array<uint8_t, 16> bytes = {
- {static_cast<unsigned char>((newId.Data1 >> 24) & 0xFF),
- static_cast<unsigned char>((newId.Data1 >> 16) & 0xFF),
- static_cast<unsigned char>((newId.Data1 >> 8) & 0xFF),
- static_cast<unsigned char>((newId.Data1) & 0xFF),
+ std::array<uint8_t, 16> bytes = {
+ {static_cast<unsigned char>((newId.Data1 >> 24) & 0xFF),
+ static_cast<unsigned char>((newId.Data1 >> 16) & 0xFF),
+ static_cast<unsigned char>((newId.Data1 >> 8) & 0xFF),
+ static_cast<unsigned char>((newId.Data1) & 0xFF),
- (unsigned char)((newId.Data2 >> 8) & 0xFF),
- (unsigned char)((newId.Data2) & 0xFF),
+ (unsigned char) ((newId.Data2 >> 8) & 0xFF), (unsigned char) ((newId.Data2) & 0xFF),
- (unsigned char)((newId.Data3 >> 8) & 0xFF),
- (unsigned char)((newId.Data3) & 0xFF),
+ (unsigned char) ((newId.Data3 >> 8) & 0xFF), (unsigned char) ((newId.Data3) & 0xFF),
- newId.Data4[0], newId.Data4[1], newId.Data4[2], newId.Data4[3],
- newId.Data4[4], newId.Data4[5], newId.Data4[6], newId.Data4[7]}};
+ newId.Data4[0], newId.Data4[1], newId.Data4[2], newId.Data4[3], newId.Data4[4],
+ newId.Data4[5], newId.Data4[6], newId.Data4[7]}};
- return uuid{std::begin(bytes), std::end(bytes)};
+ return uuid{std::begin(bytes), std::end(bytes)};
#elif defined(__linux__) || defined(__unix__)
- uuid_t id;
- uuid_generate(id);
+ uuid_t id;
+ uuid_generate(id);
- std::array<uint8_t, 16> bytes = {{id[0], id[1], id[2], id[3], id[4], id[5],
- id[6], id[7], id[8], id[9], id[10],
- id[11], id[12], id[13], id[14], id[15]}};
+ std::array<uint8_t, 16> bytes = {{id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7], id[8],
+ id[9], id[10], id[11], id[12], id[13], id[14], id[15]}};
- return uuid{std::begin(bytes), std::end(bytes)};
+ return uuid{std::begin(bytes), std::end(bytes)};
#elif defined(__APPLE__)
- auto newId = CFUUIDCreate(NULL);
- auto bytes = CFUUIDGetUUIDBytes(newId);
- CFRelease(newId);
-
- std::array<uint8_t, 16> arrbytes = {
- {bytes.byte0, bytes.byte1, bytes.byte2, bytes.byte3, bytes.byte4,
- bytes.byte5, bytes.byte6, bytes.byte7, bytes.byte8, bytes.byte9,
- bytes.byte10, bytes.byte11, bytes.byte12, bytes.byte13, bytes.byte14,
- bytes.byte15}};
- return uuid{std::begin(arrbytes), std::end(arrbytes)};
+ auto newId = CFUUIDCreate(NULL);
+ auto bytes = CFUUIDGetUUIDBytes(newId);
+ CFRelease(newId);
+
+ std::array<uint8_t, 16> arrbytes = {{bytes.byte0, bytes.byte1, bytes.byte2, bytes.byte3,
+ bytes.byte4, bytes.byte5, bytes.byte6, bytes.byte7,
+ bytes.byte8, bytes.byte9, bytes.byte10, bytes.byte11,
+ bytes.byte12, bytes.byte13, bytes.byte14, bytes.byte15}};
+ return uuid{std::begin(arrbytes), std::end(arrbytes)};
#else
- return uuid{};
+ return uuid{};
#endif
- }
- };
+ }
+};
#endif
- template <typename UniformRandomNumberGenerator>
- class basic_uuid_random_generator
- {
- public:
- using engine_type = UniformRandomNumberGenerator;
-
- explicit basic_uuid_random_generator(engine_type& gen)
- : generator(&gen, [](auto) {})
- {
- }
- explicit basic_uuid_random_generator(engine_type* gen)
- : generator(gen, [](auto) {})
- {
- }
-
- [[nodiscard]] uuid operator()()
- {
- alignas(uint32_t) uint8_t bytes[16];
- for (int i = 0; i < 16; i += 4)
- *reinterpret_cast<uint32_t*>(bytes + i) = distribution(*generator);
-
- // variant must be 10xxxxxx
- bytes[8] &= 0xBF;
- bytes[8] |= 0x80;
-
- // version must be 0100xxxx
- bytes[6] &= 0x4F;
- bytes[6] |= 0x40;
-
- return uuid{std::begin(bytes), std::end(bytes)};
- }
-
- private:
- std::uniform_int_distribution<uint32_t> distribution;
- std::shared_ptr<UniformRandomNumberGenerator> generator;
- };
-
- using uuid_random_generator = basic_uuid_random_generator<std::mt19937>;
-
- class uuid_name_generator
- {
- public:
- explicit uuid_name_generator(uuid const& namespace_uuid) noexcept
- : nsuuid(namespace_uuid)
- {
- }
-
- template <typename StringType>
- [[nodiscard]] uuid operator()(StringType const& name)
- {
- reset();
- process_characters(Detail::to_string_view(name));
- return make_uuid();
- }
-
- private:
- void reset()
- {
- hasher.reset();
- std::byte bytes[16];
- auto nsbytes = nsuuid.as_bytes();
- std::copy(std::cbegin(nsbytes), std::cend(nsbytes), bytes);
- hasher.process_bytes(bytes, 16);
- }
-
- template <typename CharT, typename Traits>
- void process_characters(std::basic_string_view<CharT, Traits> const str)
- {
- for (uint32_t c : str)
- {
- hasher.process_byte(static_cast<uint8_t>(c & 0xFF));
- if constexpr (!std::is_same_v<CharT, char>)
- {
- hasher.process_byte(static_cast<uint8_t>((c >> 8) & 0xFF));
- hasher.process_byte(static_cast<uint8_t>((c >> 16) & 0xFF));
- hasher.process_byte(static_cast<uint8_t>((c >> 24) & 0xFF));
- }
- }
- }
-
- [[nodiscard]] uuid make_uuid()
- {
- Detail::sha1::digest8_t digest;
- hasher.get_digest_bytes(digest);
-
- // variant must be 0b10xxxxxx
- digest[8] &= 0xBF;
- digest[8] |= 0x80;
-
- // version must be 0b0101xxxx
- digest[6] &= 0x5F;
- digest[6] |= 0x50;
-
- return uuid{digest, digest + 16};
- }
-
- private:
- uuid nsuuid;
- Detail::sha1 hasher;
- };
+template <typename UniformRandomNumberGenerator>
+class basic_uuid_random_generator {
+ public:
+ using engine_type = UniformRandomNumberGenerator;
+
+ explicit basic_uuid_random_generator(engine_type& gen) : generator(&gen, [](auto) {}) {}
+ explicit basic_uuid_random_generator(engine_type* gen) : generator(gen, [](auto) {}) {}
+
+ [[nodiscard]] uuid operator()() {
+ alignas(uint32_t) uint8_t bytes[16];
+ for (int i = 0; i < 16; i += 4)
+ *reinterpret_cast<uint32_t*>(bytes + i) = distribution(*generator);
+
+ // variant must be 10xxxxxx
+ bytes[8] &= 0xBF;
+ bytes[8] |= 0x80;
+
+ // version must be 0100xxxx
+ bytes[6] &= 0x4F;
+ bytes[6] |= 0x40;
+
+ return uuid{std::begin(bytes), std::end(bytes)};
+ }
+
+ private:
+ std::uniform_int_distribution<uint32_t> distribution;
+ std::shared_ptr<UniformRandomNumberGenerator> generator;
+};
+
+using uuid_random_generator = basic_uuid_random_generator<std::mt19937>;
+
+class uuid_name_generator {
+ public:
+ explicit uuid_name_generator(uuid const& namespace_uuid) noexcept : nsuuid(namespace_uuid) {}
+
+ template <typename StringType>
+ [[nodiscard]] uuid operator()(StringType const& name) {
+ reset();
+ process_characters(Detail::to_string_view(name));
+ return make_uuid();
+ }
+
+ private:
+ void reset() {
+ hasher.reset();
+ std::byte bytes[16];
+ auto nsbytes = nsuuid.as_bytes();
+ std::copy(std::cbegin(nsbytes), std::cend(nsbytes), bytes);
+ hasher.process_bytes(bytes, 16);
+ }
+
+ template <typename CharT, typename Traits>
+ void process_characters(std::basic_string_view<CharT, Traits> const str) {
+ for (uint32_t c : str) {
+ hasher.process_byte(static_cast<uint8_t>(c & 0xFF));
+ if constexpr (!std::is_same_v<CharT, char>) {
+ hasher.process_byte(static_cast<uint8_t>((c >> 8) & 0xFF));
+ hasher.process_byte(static_cast<uint8_t>((c >> 16) & 0xFF));
+ hasher.process_byte(static_cast<uint8_t>((c >> 24) & 0xFF));
+ }
+ }
+ }
+
+ [[nodiscard]] uuid make_uuid() {
+ Detail::sha1::digest8_t digest;
+ hasher.get_digest_bytes(digest);
+
+ // variant must be 0b10xxxxxx
+ digest[8] &= 0xBF;
+ digest[8] |= 0x80;
+
+ // version must be 0b0101xxxx
+ digest[6] &= 0x5F;
+ digest[6] |= 0x50;
+
+ return uuid{digest, digest + 16};
+ }
+
+ private:
+ uuid nsuuid;
+ Detail::sha1 hasher;
+};
#ifdef UUID_TIME_GENERATOR
- // !!! DO NOT USE THIS IN PRODUCTION
- // this implementation is unreliable for good uuids
- class uuid_time_generator
- {
- using mac_address = std::array<unsigned char, 6>;
+// !!! DO NOT USE THIS IN PRODUCTION
+// this implementation is unreliable for good uuids
+class uuid_time_generator {
+ using mac_address = std::array<unsigned char, 6>;
- std::optional<mac_address> device_address;
+ std::optional<mac_address> device_address;
- [[nodiscard]] bool get_mac_address()
- {
- if (device_address.has_value())
- {
- return true;
- }
+ [[nodiscard]] bool get_mac_address() {
+ if (device_address.has_value()) {
+ return true;
+ }
#ifdef _WIN32
- DWORD len = 0;
- auto ret = GetAdaptersInfo(nullptr, &len);
- if (ret != ERROR_BUFFER_OVERFLOW)
- return false;
- std::vector<unsigned char> buf(len);
- auto pips = reinterpret_cast<PIP_ADAPTER_INFO>(&buf.front());
- ret = GetAdaptersInfo(pips, &len);
- if (ret != ERROR_SUCCESS)
- return false;
- mac_address addr;
- std::copy(pips->Address, pips->Address + 6, std::begin(addr));
- device_address = addr;
+ DWORD len = 0;
+ auto ret = GetAdaptersInfo(nullptr, &len);
+ if (ret != ERROR_BUFFER_OVERFLOW) return false;
+ std::vector<unsigned char> buf(len);
+ auto pips = reinterpret_cast<PIP_ADAPTER_INFO>(&buf.front());
+ ret = GetAdaptersInfo(pips, &len);
+ if (ret != ERROR_SUCCESS) return false;
+ mac_address addr;
+ std::copy(pips->Address, pips->Address + 6, std::begin(addr));
+ device_address = addr;
#endif
- return device_address.has_value();
- }
+ return device_address.has_value();
+ }
- [[nodiscard]] long long get_time_intervals()
- {
- auto start = std::chrono::system_clock::from_time_t(time_t(-12219292800));
- auto diff = std::chrono::system_clock::now() - start;
- auto ns =
- std::chrono::duration_cast<std::chrono::nanoseconds>(diff).count();
- return ns / 100;
- }
+ [[nodiscard]] long long get_time_intervals() {
+ auto start = std::chrono::system_clock::from_time_t(time_t(-12219292800));
+ auto diff = std::chrono::system_clock::now() - start;
+ auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(diff).count();
+ return ns / 100;
+ }
- [[nodiscard]] static unsigned short get_clock_sequence()
- {
- static std::mt19937 clock_gen(std::random_device{}());
- static std::uniform_int_distribution<unsigned short> clock_dis;
- static std::atomic_ushort clock_sequence = clock_dis(clock_gen);
- return clock_sequence++;
- }
+ [[nodiscard]] static unsigned short get_clock_sequence() {
+ static std::mt19937 clock_gen(std::random_device{}());
+ static std::uniform_int_distribution<unsigned short> clock_dis;
+ static std::atomic_ushort clock_sequence = clock_dis(clock_gen);
+ return clock_sequence++;
+ }
- public:
- [[nodiscard]] uuid operator()()
- {
- if (get_mac_address())
- {
- std::array<uuids::uuid::value_type, 16> data;
+ public:
+ [[nodiscard]] uuid operator()() {
+ if (get_mac_address()) {
+ std::array<uuids::uuid::value_type, 16> data;
- auto tm = get_time_intervals();
+ auto tm = get_time_intervals();
- auto clock_seq = get_clock_sequence();
+ auto clock_seq = get_clock_sequence();
- auto ptm = reinterpret_cast<uuids::uuid::value_type*>(&tm);
+ auto ptm = reinterpret_cast<uuids::uuid::value_type*>(&tm);
- memcpy(&data[0], ptm + 4, 4);
- memcpy(&data[4], ptm + 2, 2);
- memcpy(&data[6], ptm, 2);
+ memcpy(&data[0], ptm + 4, 4);
+ memcpy(&data[4], ptm + 2, 2);
+ memcpy(&data[6], ptm, 2);
- memcpy(&data[8], &clock_seq, 2);
+ memcpy(&data[8], &clock_seq, 2);
- // variant must be 0b10xxxxxx
- data[8] &= 0xBF;
- data[8] |= 0x80;
+ // variant must be 0b10xxxxxx
+ data[8] &= 0xBF;
+ data[8] |= 0x80;
- // version must be 0b0001xxxx
- data[6] &= 0x1F;
- data[6] |= 0x10;
+ // version must be 0b0001xxxx
+ data[6] &= 0x1F;
+ data[6] |= 0x10;
- memcpy(&data[10], &device_address.value()[0], 6);
+ memcpy(&data[10], &device_address.value()[0], 6);
- return uuids::uuid{std::cbegin(data), std::cend(data)};
- }
+ return uuids::uuid{std::cbegin(data), std::cend(data)};
+ }
- return {};
- }
- };
+ return {};
+ }
+};
#endif
-} // namespace uuids
-
-namespace std
-{
- template <>
- struct hash<uuids::uuid>
- {
- using argument_type = uuids::uuid;
- using result_type = std::size_t;
-
- [[nodiscard]] result_type operator()(argument_type const& uuid) const
- {
+} // namespace uuids
+
+namespace std {
+template <>
+struct hash<uuids::uuid> {
+ using argument_type = uuids::uuid;
+ using result_type = std::size_t;
+
+ [[nodiscard]] result_type operator()(argument_type const& uuid) const {
#ifdef UUID_HASH_STRING_BASED
- std::hash<std::string> hasher;
- return static_cast<result_type>(hasher(uuids::to_string(uuid)));
+ std::hash<std::string> hasher;
+ return static_cast<result_type>(hasher(uuids::to_string(uuid)));
#else
- uint64_t l = static_cast<uint64_t>(uuid.data[0]) << 56 |
- static_cast<uint64_t>(uuid.data[1]) << 48 |
- static_cast<uint64_t>(uuid.data[2]) << 40 |
- static_cast<uint64_t>(uuid.data[3]) << 32 |
- static_cast<uint64_t>(uuid.data[4]) << 24 |
- static_cast<uint64_t>(uuid.data[5]) << 16 |
- static_cast<uint64_t>(uuid.data[6]) << 8 |
- static_cast<uint64_t>(uuid.data[7]);
- uint64_t h = static_cast<uint64_t>(uuid.data[8]) << 56 |
- static_cast<uint64_t>(uuid.data[9]) << 48 |
- static_cast<uint64_t>(uuid.data[10]) << 40 |
- static_cast<uint64_t>(uuid.data[11]) << 32 |
- static_cast<uint64_t>(uuid.data[12]) << 24 |
- static_cast<uint64_t>(uuid.data[13]) << 16 |
- static_cast<uint64_t>(uuid.data[14]) << 8 |
- static_cast<uint64_t>(uuid.data[15]);
-
- if constexpr (sizeof(result_type) > 4)
- {
- return result_type(l ^ h);
- }
- else
- {
- uint64_t hash64 = l ^ h;
- return result_type(uint32_t(hash64 >> 32) ^ uint32_t(hash64));
- }
+ uint64_t l =
+ static_cast<uint64_t>(uuid.data[0]) << 56 | static_cast<uint64_t>(uuid.data[1]) << 48 |
+ static_cast<uint64_t>(uuid.data[2]) << 40 | static_cast<uint64_t>(uuid.data[3]) << 32 |
+ static_cast<uint64_t>(uuid.data[4]) << 24 | static_cast<uint64_t>(uuid.data[5]) << 16 |
+ static_cast<uint64_t>(uuid.data[6]) << 8 | static_cast<uint64_t>(uuid.data[7]);
+ uint64_t h =
+ static_cast<uint64_t>(uuid.data[8]) << 56 | static_cast<uint64_t>(uuid.data[9]) << 48 |
+ static_cast<uint64_t>(uuid.data[10]) << 40 | static_cast<uint64_t>(uuid.data[11]) << 32 |
+ static_cast<uint64_t>(uuid.data[12]) << 24 | static_cast<uint64_t>(uuid.data[13]) << 16 |
+ static_cast<uint64_t>(uuid.data[14]) << 8 | static_cast<uint64_t>(uuid.data[15]);
+
+ if constexpr (sizeof(result_type) > 4) {
+ return result_type(l ^ h);
+ } else {
+ uint64_t hash64 = l ^ h;
+ return result_type(uint32_t(hash64 >> 32) ^ uint32_t(hash64));
+ }
#endif
- }
- };
-} // namespace std
+ }
+};
+} // namespace std
#endif /* STDUUID_H */ \ No newline at end of file
diff --git a/dev/LibCompiler/Version.h b/dev/LibCompiler/Version.h
index c10a16e..a623312 100644
--- a/dev/LibCompiler/Version.h
+++ b/dev/LibCompiler/Version.h
@@ -1,15 +1,15 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
+ Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
------------------------------------------- */
#pragma once
-#define kDistVersion "v1.1.0"
+#define kDistVersion "v1.1.0"
#define kDistVersionBCD 0x0110
-#define ToString(X) Stringify(X)
+#define ToString(X) Stringify(X)
#define Stringify(X) #X
#define kDistRelease ToString(kDistReleaseBranch)
diff --git a/dev/LibCompiler/XCOFF.h b/dev/LibCompiler/XCOFF.h
index 862c363..047a20f 100644
--- a/dev/LibCompiler/XCOFF.h
+++ b/dev/LibCompiler/XCOFF.h
@@ -1,13 +1,13 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
+ Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
- File: XCOFF.hpp
- Purpose: XCOFF for NeKernel.
+ File: XCOFF.hpp
+ Purpose: XCOFF for NeKernel.
- Revision History:
+ Revision History:
- 04/07/24: Added file (amlel)
+ 04/07/24: Added file (amlel)
------------------------------------------- */
@@ -18,24 +18,22 @@
#define kXCOFF64Magic 0x01F7
-#define kXCOFFRelFlg 0x0001
+#define kXCOFFRelFlg 0x0001
#define kXCOFFExecutable 0x0002
-#define kXCOFFLnno 0x0004
-#define kXCOFFLSyms 0x0008
-
-namespace LibCompiler
-{
- /// @brief XCoff identification header.
- typedef struct XCoffFileHeader
- {
- UInt16 fMagic;
- UInt16 fTarget;
- UInt16 fNumSecs;
- UInt32 fTimeDat;
- UIntPtr fSymPtr;
- UInt32 fNumSyms;
- UInt16 fOptHdr; // ?: Number of bytes in optional header
- } XCoffFileHeader;
-} // namespace LibCompiler
-
-#endif // ifndef __XCOFF__
+#define kXCOFFLnno 0x0004
+#define kXCOFFLSyms 0x0008
+
+namespace LibCompiler {
+/// @brief XCoff identification header.
+typedef struct XCoffFileHeader {
+ UInt16 fMagic;
+ UInt16 fTarget;
+ UInt16 fNumSecs;
+ UInt32 fTimeDat;
+ UIntPtr fSymPtr;
+ UInt32 fNumSyms;
+ UInt16 fOptHdr; // ?: Number of bytes in optional header
+} XCoffFileHeader;
+} // namespace LibCompiler
+
+#endif // ifndef __XCOFF__
diff --git a/dev/LibCompiler/src/Assembler32x0.cc b/dev/LibCompiler/src/Assembler32x0.cc
index 1790b8b..ac24946 100644
--- a/dev/LibCompiler/src/Assembler32x0.cc
+++ b/dev/LibCompiler/src/Assembler32x0.cc
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
+ Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
------------------------------------------- */
@@ -19,10 +19,10 @@
#define __ASM_NEED_32x0__ 1
-#include <LibCompiler/Backend/32x0.h>
-#include <LibCompiler/Parser.h>
#include <LibCompiler/AE.h>
+#include <LibCompiler/Backend/32x0.h>
#include <LibCompiler/PEF.h>
+#include <LibCompiler/Parser.h>
/////////////////////
@@ -30,9 +30,9 @@
/////////////////////
-#define kBlank "\e[0;30m"
-#define kRed "\e[0;31m"
-#define kWhite "\e[0;97m"
+#define kBlank "\e[0;30m"
+#define kRed "\e[0;31m"
+#define kWhite "\e[0;97m"
#define kYellow "\e[0;33m"
#define kStdOut (std::cout << kWhite)
@@ -44,7 +44,6 @@
/////////////////////////////////////////////////////////////////////////////////////////
-LIBCOMPILER_MODULE(NEAssemblerMain32000)
-{
- return 0;
+LIBCOMPILER_MODULE(NEAssemblerMain32000) {
+ return 0;
}
diff --git a/dev/LibCompiler/src/Assembler64x0.cc b/dev/LibCompiler/src/Assembler64x0.cc
index 7630adf..7701982 100644
--- a/dev/LibCompiler/src/Assembler64x0.cc
+++ b/dev/LibCompiler/src/Assembler64x0.cc
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
+ Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
------------------------------------------- */
@@ -19,10 +19,10 @@
#define __ASM_NEED_64x0__ 1
-#include <LibCompiler/Backend/64x0.h>
-#include <LibCompiler/Parser.h>
#include <LibCompiler/AE.h>
+#include <LibCompiler/Backend/64x0.h>
#include <LibCompiler/PEF.h>
+#include <LibCompiler/Parser.h>
#include <algorithm>
#include <filesystem>
#include <fstream>
@@ -35,25 +35,25 @@
/////////////////////
-#define kBlank "\e[0;30m"
-#define kRed "\e[0;31m"
-#define kWhite "\e[0;97m"
+#define kBlank "\e[0;30m"
+#define kRed "\e[0;31m"
+#define kWhite "\e[0;97m"
#define kYellow "\e[0;33m"
#define kStdOut (std::cout << kWhite)
#define kStdErr (std::cout << kRed)
-static char kOutputArch = LibCompiler::kPefArch64000;
+static char kOutputArch = LibCompiler::kPefArch64000;
static Boolean kOutputAsBinary = false;
-static UInt32 kErrorLimit = 10;
+static UInt32 kErrorLimit = 10;
static UInt32 kAcceptableErrors = 0;
constexpr auto c64x0IPAlignment = 0x4U;
static std::size_t kCounter = 1UL;
-static std::uintptr_t kOrigin = kPefBaseOrigin;
+static std::uintptr_t kOrigin = kPefBaseOrigin;
static std::vector<std::pair<std::string, std::uintptr_t>> kOriginLabel;
static bool kVerbose = false;
@@ -61,49 +61,42 @@ static bool kVerbose = false;
static std::vector<e64k_num_t> kBytes;
static LibCompiler::AERecordHeader kCurrentRecord{
- .fName = "", .fKind = LibCompiler::kPefCode, .fSize = 0, .fOffset = 0};
+ .fName = "", .fKind = LibCompiler::kPefCode, .fSize = 0, .fOffset = 0};
static std::vector<LibCompiler::AERecordHeader> kRecords;
-static std::vector<std::string> kUndefinedSymbols;
+static std::vector<std::string> kUndefinedSymbols;
static const std::string kUndefinedSymbol = ":UndefinedSymbol:";
-static const std::string kRelocSymbol = ":RuntimeSymbol:";
+static const std::string kRelocSymbol = ":RuntimeSymbol:";
// \brief forward decl.
static bool asm_read_attributes(std::string& line);
-namespace Detail
-{
- void print_error(std::string reason, std::string file) noexcept
- {
- if (reason[0] == '\n')
- reason.erase(0, 1);
+namespace Detail {
+void print_error(std::string reason, std::string file) noexcept {
+ if (reason[0] == '\n') reason.erase(0, 1);
- kStdErr << kRed << "[ asm ] " << kWhite
- << ((file == "LibCompiler") ? "InternalErrorException: "
- : ("FileException{ " + file + " }: "))
- << kBlank << std::endl;
- kStdErr << kRed << "[ asm ] " << kWhite << reason << kBlank << std::endl;
+ kStdErr << kRed << "[ asm ] " << kWhite
+ << ((file == "LibCompiler") ? "InternalErrorException: "
+ : ("FileException{ " + file + " }: "))
+ << kBlank << std::endl;
+ kStdErr << kRed << "[ asm ] " << kWhite << reason << kBlank << std::endl;
- if (kAcceptableErrors > kErrorLimit)
- std::exit(3);
+ if (kAcceptableErrors > kErrorLimit) std::exit(3);
- ++kAcceptableErrors;
- }
+ ++kAcceptableErrors;
+}
- void print_warning(std::string reason, std::string file) noexcept
- {
- if (reason[0] == '\n')
- reason.erase(0, 1);
+void print_warning(std::string reason, std::string file) noexcept {
+ if (reason[0] == '\n') reason.erase(0, 1);
- if (!file.empty())
- {
- kStdOut << kYellow << "[ asm ] " << kWhite << file << kBlank << std::endl;
- }
+ if (!file.empty()) {
+ kStdOut << kYellow << "[ asm ] " << kWhite << file << kBlank << std::endl;
+ }
- kStdOut << kYellow << "[ asm ] " << kWhite << reason << kBlank << std::endl;
- }
-} // namespace Detail
+ kStdOut << kYellow << "[ asm ] " << kWhite << reason << kBlank << std::endl;
+}
+} // namespace Detail
/////////////////////////////////////////////////////////////////////////////////////////
@@ -111,225 +104,191 @@ namespace Detail
/////////////////////////////////////////////////////////////////////////////////////////
-LIBCOMPILER_MODULE(AssemblerMain64x0)
-{
- for (size_t i = 1; i < argc; ++i)
- {
- if (argv[i][0] == '-')
- {
- if (strcmp(argv[i], "--ver") == 0 || strcmp(argv[i], "--v") == 0)
- {
- kStdOut << "Assembler64x0: 64x0 Assembler.\nAssembler64x0: v1.10\nAssembler64x0: Copyright (c) "
- "Amlal El Mahrouss\n";
- return 0;
- }
- else if (strcmp(argv[i], "--h") == 0)
- {
- kStdOut << "Assembler64x0: 64x0 Assembler.\nAssembler64x0: Copyright (c) 2024 Mahrouss "
- "Logic.\n";
- kStdOut << "--version: Print program version.\n";
- kStdOut << "--verbose: Print verbose output.\n";
- kStdOut << "--binary: Output as flat binary.\n";
- kStdOut << "--64xxx: Compile for a subset of the X64000.\n";
-
- return 0;
- }
- else if (strcmp(argv[i], "--binary") == 0)
- {
- kOutputAsBinary = true;
- continue;
- }
- else if (strcmp(argv[i], "--verbose") == 0)
- {
- kVerbose = true;
- continue;
- }
-
- kStdOut << "Assembler64x0: ignore " << argv[i] << "\n";
- continue;
- }
-
- if (!std::filesystem::exists(argv[i]))
- {
- kStdOut << "Assembler64x0: can't open: " << argv[i] << std::endl;
- goto asm_fail_exit;
- }
-
- std::string object_output(argv[i]);
-
- for (auto& ext : kAsmFileExts)
- {
- if (object_output.find(ext) != std::string::npos)
- {
- object_output.erase(object_output.find(ext), std::strlen(ext));
- }
- }
-
- object_output += kOutputAsBinary ? kBinaryFileExt : kObjectFileExt;
-
- std::ifstream file_ptr(argv[i]);
- std::ofstream file_ptr_out(object_output, std::ofstream::binary);
-
- if (file_ptr_out.bad())
- {
- if (kVerbose)
- {
- kStdOut << "Assembler64x0: error: " << strerror(errno) << "\n";
- }
- }
-
- std::string line;
-
- LibCompiler::AEHeader hdr{0};
-
- memset(hdr.fPad, kAENullType, kAEPad);
-
- hdr.fMagic[0] = kAEMag0;
- hdr.fMagic[1] = kAEMag1;
- hdr.fSize = sizeof(LibCompiler::AEHeader);
- hdr.fArch = kOutputArch;
-
- /////////////////////////////////////////////////////////////////////////////////////////
-
- // COMPILATION LOOP
-
- /////////////////////////////////////////////////////////////////////////////////////////
-
- LibCompiler::Encoder64x0 asm64;
-
- while (std::getline(file_ptr, line))
- {
- if (auto ln = asm64.CheckLine(line, argv[i]); !ln.empty())
- {
- Detail::print_error(ln, argv[i]);
- continue;
- }
-
- try
- {
- asm_read_attributes(line);
- asm64.WriteLine(line, argv[i]);
- }
- catch (const std::exception& e)
- {
- if (kVerbose)
- {
- std::string what = e.what();
- Detail::print_warning("exit because of: " + what, "LibCompiler");
- }
-
- std::filesystem::remove(object_output);
- goto asm_fail_exit;
- }
- }
-
- if (!kOutputAsBinary)
- {
- if (kVerbose)
- {
- kStdOut << "Assembler64x0: Writing object file...\n";
- }
+LIBCOMPILER_MODULE(AssemblerMain64x0) {
+ for (size_t i = 1; i < argc; ++i) {
+ if (argv[i][0] == '-') {
+ if (strcmp(argv[i], "--ver") == 0 || strcmp(argv[i], "--v") == 0) {
+ kStdOut
+ << "Assembler64x0: 64x0 Assembler.\nAssembler64x0: v1.10\nAssembler64x0: Copyright (c) "
+ "Amlal El Mahrouss\n";
+ return 0;
+ } else if (strcmp(argv[i], "--h") == 0) {
+ kStdOut << "Assembler64x0: 64x0 Assembler.\nAssembler64x0: Copyright (c) 2024 Mahrouss "
+ "Logic.\n";
+ kStdOut << "--version: Print program version.\n";
+ kStdOut << "--verbose: Print verbose output.\n";
+ kStdOut << "--binary: Output as flat binary.\n";
+ kStdOut << "--64xxx: Compile for a subset of the X64000.\n";
+
+ return 0;
+ } else if (strcmp(argv[i], "--binary") == 0) {
+ kOutputAsBinary = true;
+ continue;
+ } else if (strcmp(argv[i], "--verbose") == 0) {
+ kVerbose = true;
+ continue;
+ }
+
+ kStdOut << "Assembler64x0: ignore " << argv[i] << "\n";
+ continue;
+ }
+
+ if (!std::filesystem::exists(argv[i])) {
+ kStdOut << "Assembler64x0: can't open: " << argv[i] << std::endl;
+ goto asm_fail_exit;
+ }
+
+ std::string object_output(argv[i]);
+
+ for (auto& ext : kAsmFileExts) {
+ if (object_output.find(ext) != std::string::npos) {
+ object_output.erase(object_output.find(ext), std::strlen(ext));
+ }
+ }
+
+ object_output += kOutputAsBinary ? kBinaryFileExt : kObjectFileExt;
+
+ std::ifstream file_ptr(argv[i]);
+ std::ofstream file_ptr_out(object_output, std::ofstream::binary);
+
+ if (file_ptr_out.bad()) {
+ if (kVerbose) {
+ kStdOut << "Assembler64x0: error: " << strerror(errno) << "\n";
+ }
+ }
- // this is the final step, write everything to the file.
+ std::string line;
- auto pos = file_ptr_out.tellp();
+ LibCompiler::AEHeader hdr{0};
- hdr.fCount = kRecords.size() + kUndefinedSymbols.size();
+ memset(hdr.fPad, kAENullType, kAEPad);
- file_ptr_out << hdr;
+ hdr.fMagic[0] = kAEMag0;
+ hdr.fMagic[1] = kAEMag1;
+ hdr.fSize = sizeof(LibCompiler::AEHeader);
+ hdr.fArch = kOutputArch;
- if (kRecords.empty())
- {
- kStdErr << "Assembler64x0: At least one record is needed to write an object "
- "file.\nAssembler64x0: Make one using `public_segment .code64 foo_bar`.\n";
+ /////////////////////////////////////////////////////////////////////////////////////////
- std::filesystem::remove(object_output);
- return 1;
- }
+ // COMPILATION LOOP
- kRecords[kRecords.size() - 1].fSize = kBytes.size();
+ /////////////////////////////////////////////////////////////////////////////////////////
- std::size_t record_count = 0UL;
+ LibCompiler::Encoder64x0 asm64;
- for (auto& rec : kRecords)
- {
- if (kVerbose)
- kStdOut << "Assembler64x0: Wrote record " << rec.fName << " to file...\n";
+ while (std::getline(file_ptr, line)) {
+ if (auto ln = asm64.CheckLine(line, argv[i]); !ln.empty()) {
+ Detail::print_error(ln, argv[i]);
+ continue;
+ }
- rec.fFlags |= LibCompiler::kKindRelocationAtRuntime;
- rec.fOffset = record_count;
- ++record_count;
+ try {
+ asm_read_attributes(line);
+ asm64.WriteLine(line, argv[i]);
+ } catch (const std::exception& e) {
+ if (kVerbose) {
+ std::string what = e.what();
+ Detail::print_warning("exit because of: " + what, "LibCompiler");
+ }
- file_ptr_out << rec;
- }
+ std::filesystem::remove(object_output);
+ goto asm_fail_exit;
+ }
+ }
- // increment once again, so that we won't lie about the kUndefinedSymbols.
- ++record_count;
+ if (!kOutputAsBinary) {
+ if (kVerbose) {
+ kStdOut << "Assembler64x0: Writing object file...\n";
+ }
- for (auto& sym : kUndefinedSymbols)
- {
- LibCompiler::AERecordHeader _record_hdr{0};
+ // this is the final step, write everything to the file.
- if (kVerbose)
- kStdOut << "Assembler64x0: Wrote symbol " << sym << " to file...\n";
+ auto pos = file_ptr_out.tellp();
- _record_hdr.fKind = kAENullType;
- _record_hdr.fSize = sym.size();
- _record_hdr.fOffset = record_count;
+ hdr.fCount = kRecords.size() + kUndefinedSymbols.size();
- ++record_count;
+ file_ptr_out << hdr;
- memset(_record_hdr.fPad, kAENullType, kAEPad);
- memcpy(_record_hdr.fName, sym.c_str(), sym.size());
+ if (kRecords.empty()) {
+ kStdErr << "Assembler64x0: At least one record is needed to write an object "
+ "file.\nAssembler64x0: Make one using `public_segment .code64 foo_bar`.\n";
- file_ptr_out << _record_hdr;
+ std::filesystem::remove(object_output);
+ return 1;
+ }
- ++kCounter;
- }
+ kRecords[kRecords.size() - 1].fSize = kBytes.size();
- auto pos_end = file_ptr_out.tellp();
+ std::size_t record_count = 0UL;
- file_ptr_out.seekp(pos);
+ for (auto& rec : kRecords) {
+ if (kVerbose) kStdOut << "Assembler64x0: Wrote record " << rec.fName << " to file...\n";
- hdr.fStartCode = pos_end;
- hdr.fCodeSize = kBytes.size();
+ rec.fFlags |= LibCompiler::kKindRelocationAtRuntime;
+ rec.fOffset = record_count;
+ ++record_count;
- file_ptr_out << hdr;
+ file_ptr_out << rec;
+ }
- file_ptr_out.seekp(pos_end);
- }
- else
- {
- if (kVerbose)
- {
- kStdOut << "Assembler64x0: Write raw binary...\n";
- }
- }
+ // increment once again, so that we won't lie about the kUndefinedSymbols.
+ ++record_count;
- // byte from byte, we write this.
- for (auto& byte : kBytes)
- {
- file_ptr_out.write(reinterpret_cast<const char*>(&byte), sizeof(byte));
- }
+ for (auto& sym : kUndefinedSymbols) {
+ LibCompiler::AERecordHeader _record_hdr{0};
- if (kVerbose)
- kStdOut << "Assembler64x0: Wrote file with program in it.\n";
+ if (kVerbose) kStdOut << "Assembler64x0: Wrote symbol " << sym << " to file...\n";
- file_ptr_out.flush();
- file_ptr_out.close();
+ _record_hdr.fKind = kAENullType;
+ _record_hdr.fSize = sym.size();
+ _record_hdr.fOffset = record_count;
- if (kVerbose)
- kStdOut << "Assembler64x0: Exit succeeded.\n";
+ ++record_count;
- return 0;
- }
+ memset(_record_hdr.fPad, kAENullType, kAEPad);
+ memcpy(_record_hdr.fName, sym.c_str(), sym.size());
+
+ file_ptr_out << _record_hdr;
+
+ ++kCounter;
+ }
+
+ auto pos_end = file_ptr_out.tellp();
+
+ file_ptr_out.seekp(pos);
+
+ hdr.fStartCode = pos_end;
+ hdr.fCodeSize = kBytes.size();
+
+ file_ptr_out << hdr;
+
+ file_ptr_out.seekp(pos_end);
+ } else {
+ if (kVerbose) {
+ kStdOut << "Assembler64x0: Write raw binary...\n";
+ }
+ }
+
+ // byte from byte, we write this.
+ for (auto& byte : kBytes) {
+ file_ptr_out.write(reinterpret_cast<const char*>(&byte), sizeof(byte));
+ }
+
+ if (kVerbose) kStdOut << "Assembler64x0: Wrote file with program in it.\n";
+
+ file_ptr_out.flush();
+ file_ptr_out.close();
+
+ if (kVerbose) kStdOut << "Assembler64x0: Exit succeeded.\n";
+
+ return 0;
+ }
asm_fail_exit:
- if (kVerbose)
- kStdOut << "Assembler64x0: Exit failed.\n";
+ if (kVerbose) kStdOut << "Assembler64x0: Exit failed.\n";
- return 1;
+ return 1;
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -339,176 +298,145 @@ asm_fail_exit:
/////////////////////////////////////////////////////////////////////////////////////////
-static bool asm_read_attributes(std::string& line)
-{
- // extern_segment is the opposite of public_segment, it signals to the ld
- // that we need this symbol.
- if (LibCompiler::find_word(line, "extern_segment"))
- {
- if (kOutputAsBinary)
- {
- Detail::print_error("Invalid extern_segment directive in flat binary mode.",
- "LibCompiler");
- throw std::runtime_error("invalid_extern_segment_bin");
- }
-
- auto name = line.substr(line.find("extern_segment") + strlen("extern_segment"));
-
- /// sanity check to avoid stupid linker errors.
- if (name.size() == 0)
- {
- Detail::print_error("Invalid extern_segment", "power-as");
- throw std::runtime_error("invalid_extern_segment");
- }
-
- std::string result = std::to_string(name.size());
- result += kUndefinedSymbol;
-
- // mangle this
- for (char& j : name)
- {
- if (j == ' ' || j == ',')
- j = '$';
- }
-
- result += name;
-
- if (name.find(".code64") != std::string::npos)
- {
- // data is treated as code.
- kCurrentRecord.fKind = LibCompiler::kPefCode;
- }
- else if (name.find(".data64") != std::string::npos)
- {
- // no code will be executed from here.
- kCurrentRecord.fKind = LibCompiler::kPefData;
- }
- else if (name.find(".zero64") != std::string::npos)
- {
- // this is a bss section.
- kCurrentRecord.fKind = LibCompiler::kPefZero;
- }
-
- // this is a special case for the start stub.
- // we want this so that ld can find it.
-
- if (name == kPefStart)
- {
- kCurrentRecord.fKind = LibCompiler::kPefCode;
- }
-
- // now we can tell the code size of the previous kCurrentRecord.
-
- if (!kRecords.empty())
- kRecords[kRecords.size() - 1].fSize = kBytes.size();
-
- memset(kCurrentRecord.fName, 0, kAESymbolLen);
- memcpy(kCurrentRecord.fName, result.c_str(), result.size());
-
- ++kCounter;
-
- memset(kCurrentRecord.fPad, kAENullType, kAEPad);
-
- kRecords.emplace_back(kCurrentRecord);
-
- return true;
- }
- // public_segment is a special keyword used by Assembler64x0 to tell the AE output stage to
- // mark this section as a header. it currently supports .code64, .data64.,
- // .zero64
- else if (LibCompiler::find_word(line, "public_segment"))
- {
- if (kOutputAsBinary)
- {
- Detail::print_error("Invalid public_segment directive in flat binary mode.",
- "LibCompiler");
- throw std::runtime_error("invalid_public_segment_bin");
- }
-
- auto name = line.substr(line.find("public_segment") + strlen("public_segment"));
-
- std::string name_copy = name;
-
- for (char& j : name)
- {
- if (j == ' ')
- j = '$';
- }
-
- if (name.find(".code64") != std::string::npos)
- {
- // data is treated as code.
-
- name_copy.erase(name_copy.find(".code64"), strlen(".code64"));
- kCurrentRecord.fKind = LibCompiler::kPefCode;
- }
- else if (name.find(".data64") != std::string::npos)
- {
- // no code will be executed from here.
-
- name_copy.erase(name_copy.find(".data64"), strlen(".data64"));
- kCurrentRecord.fKind = LibCompiler::kPefData;
- }
- else if (name.find(".zero64") != std::string::npos)
- {
- // this is a bss section.
-
- name_copy.erase(name_copy.find(".zero64"), strlen(".zero64"));
- kCurrentRecord.fKind = LibCompiler::kPefZero;
- }
-
- // this is a special case for the start stub.
- // we want this so that ld can find it.
+static bool asm_read_attributes(std::string& line) {
+ // extern_segment is the opposite of public_segment, it signals to the ld
+ // that we need this symbol.
+ if (LibCompiler::find_word(line, "extern_segment")) {
+ if (kOutputAsBinary) {
+ Detail::print_error("Invalid extern_segment directive in flat binary mode.", "LibCompiler");
+ throw std::runtime_error("invalid_extern_segment_bin");
+ }
+
+ auto name = line.substr(line.find("extern_segment") + strlen("extern_segment"));
- if (name == kPefStart)
- {
- kCurrentRecord.fKind = LibCompiler::kPefCode;
- }
-
- while (name_copy.find(" ") != std::string::npos)
- name_copy.erase(name_copy.find(" "), 1);
+ /// sanity check to avoid stupid linker errors.
+ if (name.size() == 0) {
+ Detail::print_error("Invalid extern_segment", "power-as");
+ throw std::runtime_error("invalid_extern_segment");
+ }
- kOriginLabel.push_back(std::make_pair(name_copy, kOrigin));
- ++kOrigin;
+ std::string result = std::to_string(name.size());
+ result += kUndefinedSymbol;
- // now we can tell the code size of the previous kCurrentRecord.
+ // mangle this
+ for (char& j : name) {
+ if (j == ' ' || j == ',') j = '$';
+ }
- if (!kRecords.empty())
- kRecords[kRecords.size() - 1].fSize = kBytes.size();
+ result += name;
- memset(kCurrentRecord.fName, 0, kAESymbolLen);
- memcpy(kCurrentRecord.fName, name.c_str(), name.size());
+ if (name.find(".code64") != std::string::npos) {
+ // data is treated as code.
+ kCurrentRecord.fKind = LibCompiler::kPefCode;
+ } else if (name.find(".data64") != std::string::npos) {
+ // no code will be executed from here.
+ kCurrentRecord.fKind = LibCompiler::kPefData;
+ } else if (name.find(".zero64") != std::string::npos) {
+ // this is a bss section.
+ kCurrentRecord.fKind = LibCompiler::kPefZero;
+ }
- ++kCounter;
+ // this is a special case for the start stub.
+ // we want this so that ld can find it.
- memset(kCurrentRecord.fPad, kAENullType, kAEPad);
+ if (name == kPefStart) {
+ kCurrentRecord.fKind = LibCompiler::kPefCode;
+ }
- kRecords.emplace_back(kCurrentRecord);
+ // now we can tell the code size of the previous kCurrentRecord.
- return true;
- }
+ if (!kRecords.empty()) kRecords[kRecords.size() - 1].fSize = kBytes.size();
- return false;
+ memset(kCurrentRecord.fName, 0, kAESymbolLen);
+ memcpy(kCurrentRecord.fName, result.c_str(), result.size());
+
+ ++kCounter;
+
+ memset(kCurrentRecord.fPad, kAENullType, kAEPad);
+
+ kRecords.emplace_back(kCurrentRecord);
+
+ return true;
+ }
+ // public_segment is a special keyword used by Assembler64x0 to tell the AE output stage to
+ // mark this section as a header. it currently supports .code64, .data64.,
+ // .zero64
+ else if (LibCompiler::find_word(line, "public_segment")) {
+ if (kOutputAsBinary) {
+ Detail::print_error("Invalid public_segment directive in flat binary mode.", "LibCompiler");
+ throw std::runtime_error("invalid_public_segment_bin");
+ }
+
+ auto name = line.substr(line.find("public_segment") + strlen("public_segment"));
+
+ std::string name_copy = name;
+
+ for (char& j : name) {
+ if (j == ' ') j = '$';
+ }
+
+ if (name.find(".code64") != std::string::npos) {
+ // data is treated as code.
+
+ name_copy.erase(name_copy.find(".code64"), strlen(".code64"));
+ kCurrentRecord.fKind = LibCompiler::kPefCode;
+ } else if (name.find(".data64") != std::string::npos) {
+ // no code will be executed from here.
+
+ name_copy.erase(name_copy.find(".data64"), strlen(".data64"));
+ kCurrentRecord.fKind = LibCompiler::kPefData;
+ } else if (name.find(".zero64") != std::string::npos) {
+ // this is a bss section.
+
+ name_copy.erase(name_copy.find(".zero64"), strlen(".zero64"));
+ kCurrentRecord.fKind = LibCompiler::kPefZero;
+ }
+
+ // this is a special case for the start stub.
+ // we want this so that ld can find it.
+
+ if (name == kPefStart) {
+ kCurrentRecord.fKind = LibCompiler::kPefCode;
+ }
+
+ while (name_copy.find(" ") != std::string::npos) name_copy.erase(name_copy.find(" "), 1);
+
+ kOriginLabel.push_back(std::make_pair(name_copy, kOrigin));
+ ++kOrigin;
+
+ // now we can tell the code size of the previous kCurrentRecord.
+
+ if (!kRecords.empty()) kRecords[kRecords.size() - 1].fSize = kBytes.size();
+
+ memset(kCurrentRecord.fName, 0, kAESymbolLen);
+ memcpy(kCurrentRecord.fName, name.c_str(), name.size());
+
+ ++kCounter;
+
+ memset(kCurrentRecord.fPad, kAENullType, kAEPad);
+
+ kRecords.emplace_back(kCurrentRecord);
+
+ return true;
+ }
+
+ return false;
}
// \brief algorithms and helpers.
-namespace Detail::algorithm
-{
- // \brief authorize a brief set of characters.
- static inline bool is_not_alnum_space(char c)
- {
- return !(isalpha(c) || isdigit(c) || (c == ' ') || (c == '\t') ||
- (c == ',') || (c == '(') || (c == ')') || (c == '"') ||
- (c == '\'') || (c == '[') || (c == ']') || (c == '+') ||
- (c == '_') || (c == ':') || (c == '@') || (c == '.'));
- }
-
- bool is_valid_64x0(const std::string& str)
- {
- return std::find_if(str.begin(), str.end(), is_not_alnum_space) == str.end();
- }
-} // namespace Detail::algorithm
+namespace Detail::algorithm {
+// \brief authorize a brief set of characters.
+static inline bool is_not_alnum_space(char c) {
+ return !(isalpha(c) || isdigit(c) || (c == ' ') || (c == '\t') || (c == ',') || (c == '(') ||
+ (c == ')') || (c == '"') || (c == '\'') || (c == '[') || (c == ']') || (c == '+') ||
+ (c == '_') || (c == ':') || (c == '@') || (c == '.'));
+}
+
+bool is_valid_64x0(const std::string& str) {
+ return std::find_if(str.begin(), str.end(), is_not_alnum_space) == str.end();
+}
+} // namespace Detail::algorithm
/////////////////////////////////////////////////////////////////////////////////////////
@@ -516,258 +444,199 @@ namespace Detail::algorithm
/////////////////////////////////////////////////////////////////////////////////////////
-std::string LibCompiler::Encoder64x0::CheckLine(std::string& line,
- const std::string& file)
-{
- std::string err_str;
-
- if (line.empty() || LibCompiler::find_word(line, "extern_segment") ||
- LibCompiler::find_word(line, "public_segment") ||
- line.find('#') != std::string::npos || LibCompiler::find_word(line, ";"))
- {
- if (line.find('#') != std::string::npos)
- {
- line.erase(line.find('#'));
- }
- else if (line.find(';') != std::string::npos)
- {
- line.erase(line.find(';'));
- }
- else
- {
- // now check the line for validity
- if (!Detail::algorithm::is_valid_64x0(line))
- {
- err_str = "Line contains non alphanumeric characters.\nhere -> ";
- err_str += line;
- }
- }
-
- return err_str;
- }
-
- if (!Detail::algorithm::is_valid_64x0(line))
- {
- err_str = "Line contains non alphanumeric characters.\nhere -> ";
- err_str += line;
-
- return err_str;
- }
-
- // check for a valid instruction format.
-
- if (line.find(',') != std::string::npos)
- {
- if (line.find(',') + 1 == line.size())
- {
- err_str += "\nInstruction lacks right register, here -> ";
- err_str += line.substr(line.find(','));
-
- return err_str;
- }
- else
- {
- bool nothing_on_right = true;
-
- if (line.find(',') + 1 > line.size())
- {
- err_str += "\nInstruction not complete, here -> ";
- err_str += line;
-
- return err_str;
- }
-
- auto substr = line.substr(line.find(',') + 1);
-
- for (auto& ch : substr)
- {
- if (ch != ' ' && ch != '\t')
- {
- nothing_on_right = false;
- }
- }
-
- // this means we found nothing after that ',' .
- if (nothing_on_right)
- {
- err_str += "\nInstruction not complete, here -> ";
- err_str += line;
-
- return err_str;
- }
- }
- }
-
- // these do take an argument.
- std::vector<std::string> operands_inst = {"stw", "ldw", "lda", "sta"};
-
- // these don't.
- std::vector<std::string> filter_inst = {"jlr", "jrl", "int"};
-
- for (auto& opcode64x0 : kOpcodes64x0)
- {
- if (line.find(opcode64x0.fName) != std::string::npos)
- {
- if (opcode64x0.fFunct7 == kAsmNoArgs)
- return err_str;
-
- for (auto& op : operands_inst)
- {
- // if only the instruction was found.
- if (line == op)
- {
- err_str += "\nMalformed ";
- err_str += op;
- err_str += " instruction, here -> ";
- err_str += line;
- }
- }
-
- // if it is like that -> addr1, 0x0
- if (auto it = std::find(filter_inst.begin(), filter_inst.end(),
- opcode64x0.fName);
- it == filter_inst.cend())
- {
- if (LibCompiler::find_word(line, opcode64x0.fName))
- {
- if (!isspace(line[line.find(opcode64x0.fName) +
- strlen(opcode64x0.fName)]))
- {
- err_str += "\nMissing space between ";
- err_str += opcode64x0.fName;
- err_str += " and operands.\nhere -> ";
- err_str += line;
- }
- }
- }
-
- return err_str;
- }
- }
-
- err_str += "Unrecognized instruction: " + line;
-
- return err_str;
+std::string LibCompiler::Encoder64x0::CheckLine(std::string& line, const std::string& file) {
+ std::string err_str;
+
+ if (line.empty() || LibCompiler::find_word(line, "extern_segment") ||
+ LibCompiler::find_word(line, "public_segment") || line.find('#') != std::string::npos ||
+ LibCompiler::find_word(line, ";")) {
+ if (line.find('#') != std::string::npos) {
+ line.erase(line.find('#'));
+ } else if (line.find(';') != std::string::npos) {
+ line.erase(line.find(';'));
+ } else {
+ // now check the line for validity
+ if (!Detail::algorithm::is_valid_64x0(line)) {
+ err_str = "Line contains non alphanumeric characters.\nhere -> ";
+ err_str += line;
+ }
+ }
+
+ return err_str;
+ }
+
+ if (!Detail::algorithm::is_valid_64x0(line)) {
+ err_str = "Line contains non alphanumeric characters.\nhere -> ";
+ err_str += line;
+
+ return err_str;
+ }
+
+ // check for a valid instruction format.
+
+ if (line.find(',') != std::string::npos) {
+ if (line.find(',') + 1 == line.size()) {
+ err_str += "\nInstruction lacks right register, here -> ";
+ err_str += line.substr(line.find(','));
+
+ return err_str;
+ } else {
+ bool nothing_on_right = true;
+
+ if (line.find(',') + 1 > line.size()) {
+ err_str += "\nInstruction not complete, here -> ";
+ err_str += line;
+
+ return err_str;
+ }
+
+ auto substr = line.substr(line.find(',') + 1);
+
+ for (auto& ch : substr) {
+ if (ch != ' ' && ch != '\t') {
+ nothing_on_right = false;
+ }
+ }
+
+ // this means we found nothing after that ',' .
+ if (nothing_on_right) {
+ err_str += "\nInstruction not complete, here -> ";
+ err_str += line;
+
+ return err_str;
+ }
+ }
+ }
+
+ // these do take an argument.
+ std::vector<std::string> operands_inst = {"stw", "ldw", "lda", "sta"};
+
+ // these don't.
+ std::vector<std::string> filter_inst = {"jlr", "jrl", "int"};
+
+ for (auto& opcode64x0 : kOpcodes64x0) {
+ if (line.find(opcode64x0.fName) != std::string::npos) {
+ if (opcode64x0.fFunct7 == kAsmNoArgs) return err_str;
+
+ for (auto& op : operands_inst) {
+ // if only the instruction was found.
+ if (line == op) {
+ err_str += "\nMalformed ";
+ err_str += op;
+ err_str += " instruction, here -> ";
+ err_str += line;
+ }
+ }
+
+ // if it is like that -> addr1, 0x0
+ if (auto it = std::find(filter_inst.begin(), filter_inst.end(), opcode64x0.fName);
+ it == filter_inst.cend()) {
+ if (LibCompiler::find_word(line, opcode64x0.fName)) {
+ if (!isspace(line[line.find(opcode64x0.fName) + strlen(opcode64x0.fName)])) {
+ err_str += "\nMissing space between ";
+ err_str += opcode64x0.fName;
+ err_str += " and operands.\nhere -> ";
+ err_str += line;
+ }
+ }
+ }
+
+ return err_str;
+ }
+ }
+
+ err_str += "Unrecognized instruction: " + line;
+
+ return err_str;
}
-bool LibCompiler::Encoder64x0::WriteNumber(const std::size_t& pos,
- std::string& jump_label)
-{
- if (!isdigit(jump_label[pos]))
- return false;
-
- switch (jump_label[pos + 1])
- {
- case 'x': {
- if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16);
- !res)
- {
- if (errno != 0)
- {
- Detail::print_error("invalid hex number: " + jump_label, "LibCompiler");
- throw std::runtime_error("invalid_hex_number");
- }
- }
-
- LibCompiler::NumberCast64 num(
- strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16));
-
- for (char& i : num.number)
- {
- kBytes.push_back(i);
- }
-
- if (kVerbose)
- {
- kStdOut << "Assembler64x0: found a base 16 number here: "
- << jump_label.substr(pos) << "\n";
- }
-
- return true;
- }
- case 'b': {
- if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2);
- !res)
- {
- if (errno != 0)
- {
- Detail::print_error("invalid binary number: " + jump_label, "LibCompiler");
- throw std::runtime_error("invalid_bin");
- }
- }
-
- LibCompiler::NumberCast64 num(
- strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2));
-
- if (kVerbose)
- {
- kStdOut << "Assembler64x0: found a base 2 number here: "
- << jump_label.substr(pos) << "\n";
- }
-
- for (char& i : num.number)
- {
- kBytes.push_back(i);
- }
-
- return true;
- }
- case 'o': {
- if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7);
- !res)
- {
- if (errno != 0)
- {
- Detail::print_error("invalid octal number: " + jump_label, "LibCompiler");
- throw std::runtime_error("invalid_octal");
- }
- }
-
- LibCompiler::NumberCast64 num(
- strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7));
-
- if (kVerbose)
- {
- kStdOut << "Assembler64x0: found a base 8 number here: "
- << jump_label.substr(pos) << "\n";
- }
-
- for (char& i : num.number)
- {
- kBytes.push_back(i);
- }
-
- return true;
- }
- default: {
- break;
- }
- }
-
- /* check for errno and stuff like that */
- if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res)
- {
- if (errno != 0)
- {
- return false;
- }
- }
-
- LibCompiler::NumberCast64 num(
- strtol(jump_label.substr(pos).c_str(), nullptr, 10));
-
- for (char& i : num.number)
- {
- kBytes.push_back(i);
- }
-
- if (kVerbose)
- {
- kStdOut << "Assembler64x0: found a base 10 number here: " << jump_label.substr(pos)
- << "\n";
- }
-
- return true;
+bool LibCompiler::Encoder64x0::WriteNumber(const std::size_t& pos, std::string& jump_label) {
+ if (!isdigit(jump_label[pos])) return false;
+
+ switch (jump_label[pos + 1]) {
+ case 'x': {
+ if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16); !res) {
+ if (errno != 0) {
+ Detail::print_error("invalid hex number: " + jump_label, "LibCompiler");
+ throw std::runtime_error("invalid_hex_number");
+ }
+ }
+
+ LibCompiler::NumberCast64 num(strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16));
+
+ for (char& i : num.number) {
+ kBytes.push_back(i);
+ }
+
+ if (kVerbose) {
+ kStdOut << "Assembler64x0: found a base 16 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ return true;
+ }
+ case 'b': {
+ if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2); !res) {
+ if (errno != 0) {
+ Detail::print_error("invalid binary number: " + jump_label, "LibCompiler");
+ throw std::runtime_error("invalid_bin");
+ }
+ }
+
+ LibCompiler::NumberCast64 num(strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2));
+
+ if (kVerbose) {
+ kStdOut << "Assembler64x0: found a base 2 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ for (char& i : num.number) {
+ kBytes.push_back(i);
+ }
+
+ return true;
+ }
+ case 'o': {
+ if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7); !res) {
+ if (errno != 0) {
+ Detail::print_error("invalid octal number: " + jump_label, "LibCompiler");
+ throw std::runtime_error("invalid_octal");
+ }
+ }
+
+ LibCompiler::NumberCast64 num(strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7));
+
+ if (kVerbose) {
+ kStdOut << "Assembler64x0: found a base 8 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ for (char& i : num.number) {
+ kBytes.push_back(i);
+ }
+
+ return true;
+ }
+ default: {
+ break;
+ }
+ }
+
+ /* check for errno and stuff like that */
+ if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res) {
+ if (errno != 0) {
+ return false;
+ }
+ }
+
+ LibCompiler::NumberCast64 num(strtol(jump_label.substr(pos).c_str(), nullptr, 10));
+
+ for (char& i : num.number) {
+ kBytes.push_back(i);
+ }
+
+ if (kVerbose) {
+ kStdOut << "Assembler64x0: found a base 10 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ return true;
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -776,342 +645,265 @@ bool LibCompiler::Encoder64x0::WriteNumber(const std::size_t& pos,
/////////////////////////////////////////////////////////////////////////////////////////
-bool LibCompiler::Encoder64x0::WriteLine(std::string& line,
- const std::string& file)
-{
- if (LibCompiler::find_word(line, "public_segment "))
- return true;
-
- for (auto& opcode64x0 : kOpcodes64x0)
- {
- // strict check here
- if (LibCompiler::find_word(line, opcode64x0.fName) &&
- Detail::algorithm::is_valid_64x0(line))
- {
- std::string name(opcode64x0.fName);
- std::string jump_label, cpy_jump_label;
-
- kBytes.emplace_back(opcode64x0.fOpcode);
- kBytes.emplace_back(opcode64x0.fFunct3);
- kBytes.emplace_back(opcode64x0.fFunct7);
-
- // check funct7 type.
- switch (opcode64x0.fFunct7)
- {
- // reg to reg means register to register transfer operation.
- case kAsmRegToReg:
- case kAsmImmediate: {
- // \brief how many registers we found.
- std::size_t found_some = 0UL;
-
- for (size_t line_index = 0UL; line_index < line.size();
- line_index++)
- {
- if (line[line_index] == kAsmRegisterPrefix[0] &&
- isdigit(line[line_index + 1]))
- {
- std::string register_syntax = kAsmRegisterPrefix;
- register_syntax += line[line_index + 1];
-
- if (isdigit(line[line_index + 2]))
- register_syntax += line[line_index + 2];
-
- std::string reg_str;
- reg_str += line[line_index + 1];
-
- if (isdigit(line[line_index + 2]))
- reg_str += line[line_index + 2];
-
- // it ranges from r0 to r19
- // something like r190 doesn't exist in the instruction set.
- if (kOutputArch == LibCompiler::kPefArch64000)
- {
- if (isdigit(line[line_index + 3]) &&
- isdigit(line[line_index + 2]))
- {
- reg_str += line[line_index + 3];
- Detail::print_error(
- "invalid register index, r" + reg_str +
- "\nnote: The 64x0 accepts registers from r0 to r20.",
- file);
- throw std::runtime_error("invalid_register_index");
- }
- }
-
- // finally cast to a size_t
- std::size_t reg_index = strtol(reg_str.c_str(), nullptr, 10);
-
- if (reg_index > kAsmRegisterLimit)
- {
- Detail::print_error("invalid register index, r" + reg_str,
- file);
- throw std::runtime_error("invalid_register_index");
- }
-
- kBytes.emplace_back(reg_index);
- ++found_some;
-
- if (kVerbose)
- {
- kStdOut << "Assembler64x0: Register found: " << register_syntax << "\n";
- kStdOut << "Assembler64x0: Register amount in instruction: "
- << found_some << "\n";
- }
- }
- }
-
- // we're not in immediate addressing, reg to reg.
- if (opcode64x0.fFunct7 != kAsmImmediate)
- {
- // remember! register to register!
- if (found_some == 1)
- {
- Detail::print_error(
- "Too few registers.\ntip: each Assembler64x0 register "
- "starts with 'r'.\nline: " +
- line,
- file);
- throw std::runtime_error("not_a_register");
- }
- }
-
- if (found_some < 1 && name != "ldw" && name != "lda" &&
- name != "stw")
- {
- Detail::print_error(
- "invalid combination of opcode and registers.\nline: " + line,
- file);
- throw std::runtime_error("invalid_comb_op_reg");
- }
- else if (found_some == 1 && name == "add")
- {
- Detail::print_error(
- "invalid combination of opcode and registers.\nline: " + line,
- file);
- throw std::runtime_error("invalid_comb_op_reg");
- }
- else if (found_some == 1 && name == "sub")
- {
- Detail::print_error(
- "invalid combination of opcode and registers.\nline: " + line,
- file);
- throw std::runtime_error("invalid_comb_op_reg");
- }
-
- if (found_some > 0 && name == "pop")
- {
- Detail::print_error(
- "invalid combination for opcode 'pop'.\ntip: it expects "
- "nothing.\nline: " +
- line,
- file);
- throw std::runtime_error("invalid_comb_op_pop");
- }
- }
- default:
- break;
- }
-
- // try to fetch a number from the name
- if (name == "stw" || name == "ldw" || name == "lda" || name == "sta")
- {
- auto where_string = name;
-
- // if we load something, we'd need it's symbol/literal
- if (name == "stw" || name == "sta" || name == "ldw" || name == "lda" ||
- name == "sta")
- where_string = ",";
-
- jump_label = line;
-
- auto found_sym = false;
-
- while (jump_label.find(where_string) != std::string::npos)
- {
- jump_label = jump_label.substr(jump_label.find(where_string) +
- where_string.size());
-
- while (jump_label.find(" ") != std::string::npos)
- {
- jump_label.erase(jump_label.find(" "), 1);
- }
-
- if (jump_label[0] != kAsmRegisterPrefix[0] &&
- !isdigit(jump_label[1]))
- {
- if (found_sym)
- {
- Detail::print_error(
- "invalid combination of opcode and operands.\nhere -> " +
- jump_label,
- file);
- throw std::runtime_error("invalid_comb_op_ops");
- }
- else
- {
- // death trap installed.
- found_sym = true;
- }
- }
- }
-
- cpy_jump_label = jump_label;
-
- // replace any spaces with $
- if (jump_label[0] == ' ')
- {
- while (jump_label.find(' ') != std::string::npos)
- {
- if (isalnum(jump_label[0]) || isdigit(jump_label[0]))
- break;
-
- jump_label.erase(jump_label.find(' '), 1);
- }
- }
-
- if (!this->WriteNumber(0, jump_label))
- {
- // sta expects this: sta 0x000000, r0
- if (name == "sta")
- {
- Detail::print_error(
- "invalid combination of opcode and operands.\nHere ->" + line,
- file);
- throw std::runtime_error("invalid_comb_op_ops");
- }
- }
- else
- {
- if (name == "sta" &&
- cpy_jump_label.find("extern_segment ") != std::string::npos)
- {
- Detail::print_error("invalid usage extern_segment on 'sta', here: " + line,
- file);
- throw std::runtime_error("invalid_sta_usage");
- }
- }
-
- goto asm_write_label;
- }
-
- // This is the case where we jump to a label, it is also used as a goto.
- if (name == "lda" || name == "sta")
- {
- asm_write_label:
- if (cpy_jump_label.find('\n') != std::string::npos)
- cpy_jump_label.erase(cpy_jump_label.find('\n'), 1);
-
- if (cpy_jump_label.find("extern_segment") != std::string::npos)
- {
- cpy_jump_label.erase(cpy_jump_label.find("extern_segment"), strlen("extern_segment"));
-
- if (name == "sta")
- {
- Detail::print_error("extern_segment is not allowed on a sta operation.",
- file);
- throw std::runtime_error("extern_segment_sta_op");
- }
- else
- {
- goto asm_end_label_cpy;
- }
- }
-
- if (name == "lda" || name == "sta")
- {
- for (auto& label : kOriginLabel)
- {
- if (cpy_jump_label == label.first)
- {
- if (kVerbose)
- {
- kStdOut << "Assembler64x0: Replace label " << cpy_jump_label
- << " to address: " << label.second << std::endl;
- }
-
- LibCompiler::NumberCast64 num(label.second);
-
- for (auto& num : num.number)
- {
- kBytes.push_back(num);
- }
-
- goto asm_end_label_cpy;
- }
- }
-
- if (cpy_jump_label[0] == '0')
- {
- switch (cpy_jump_label[1])
- {
- case 'x':
- case 'o':
- case 'b':
- if (this->WriteNumber(0, cpy_jump_label))
- goto asm_end_label_cpy;
-
- break;
- default:
- break;
- }
-
- if (isdigit(cpy_jump_label[0]))
- {
- if (this->WriteNumber(0, cpy_jump_label))
- goto asm_end_label_cpy;
-
- break;
- }
- }
- }
-
- if (cpy_jump_label.size() < 1)
- {
- Detail::print_error("label is empty, can't jump on it.", file);
- throw std::runtime_error("label_empty");
- }
-
- /// don't go any further if:
- /// load word (ldw) or store word. (stw)
-
- if (name == "ldw" || name == "stw")
- break;
-
- auto mld_reloc_str = std::to_string(cpy_jump_label.size());
- mld_reloc_str += kUndefinedSymbol;
- mld_reloc_str += cpy_jump_label;
-
- bool ignore_back_slash = false;
-
- for (auto& reloc_chr : mld_reloc_str)
- {
- if (reloc_chr == '\\')
- {
- ignore_back_slash = true;
- continue;
- }
-
- if (ignore_back_slash)
- {
- ignore_back_slash = false;
- continue;
- }
-
- kBytes.push_back(reloc_chr);
- }
-
- kBytes.push_back('\0');
- goto asm_end_label_cpy;
- }
-
- asm_end_label_cpy:
- kOrigin += c64x0IPAlignment;
-
- break;
- }
- }
-
- return true;
+bool LibCompiler::Encoder64x0::WriteLine(std::string& line, const std::string& file) {
+ if (LibCompiler::find_word(line, "public_segment ")) return true;
+
+ for (auto& opcode64x0 : kOpcodes64x0) {
+ // strict check here
+ if (LibCompiler::find_word(line, opcode64x0.fName) && Detail::algorithm::is_valid_64x0(line)) {
+ std::string name(opcode64x0.fName);
+ std::string jump_label, cpy_jump_label;
+
+ kBytes.emplace_back(opcode64x0.fOpcode);
+ kBytes.emplace_back(opcode64x0.fFunct3);
+ kBytes.emplace_back(opcode64x0.fFunct7);
+
+ // check funct7 type.
+ switch (opcode64x0.fFunct7) {
+ // reg to reg means register to register transfer operation.
+ case kAsmRegToReg:
+ case kAsmImmediate: {
+ // \brief how many registers we found.
+ std::size_t found_some = 0UL;
+
+ for (size_t line_index = 0UL; line_index < line.size(); line_index++) {
+ if (line[line_index] == kAsmRegisterPrefix[0] && isdigit(line[line_index + 1])) {
+ std::string register_syntax = kAsmRegisterPrefix;
+ register_syntax += line[line_index + 1];
+
+ if (isdigit(line[line_index + 2])) register_syntax += line[line_index + 2];
+
+ std::string reg_str;
+ reg_str += line[line_index + 1];
+
+ if (isdigit(line[line_index + 2])) reg_str += line[line_index + 2];
+
+ // it ranges from r0 to r19
+ // something like r190 doesn't exist in the instruction set.
+ if (kOutputArch == LibCompiler::kPefArch64000) {
+ if (isdigit(line[line_index + 3]) && isdigit(line[line_index + 2])) {
+ reg_str += line[line_index + 3];
+ Detail::print_error("invalid register index, r" + reg_str +
+ "\nnote: The 64x0 accepts registers from r0 to r20.",
+ file);
+ throw std::runtime_error("invalid_register_index");
+ }
+ }
+
+ // finally cast to a size_t
+ std::size_t reg_index = strtol(reg_str.c_str(), nullptr, 10);
+
+ if (reg_index > kAsmRegisterLimit) {
+ Detail::print_error("invalid register index, r" + reg_str, file);
+ throw std::runtime_error("invalid_register_index");
+ }
+
+ kBytes.emplace_back(reg_index);
+ ++found_some;
+
+ if (kVerbose) {
+ kStdOut << "Assembler64x0: Register found: " << register_syntax << "\n";
+ kStdOut << "Assembler64x0: Register amount in instruction: " << found_some << "\n";
+ }
+ }
+ }
+
+ // we're not in immediate addressing, reg to reg.
+ if (opcode64x0.fFunct7 != kAsmImmediate) {
+ // remember! register to register!
+ if (found_some == 1) {
+ Detail::print_error(
+ "Too few registers.\ntip: each Assembler64x0 register "
+ "starts with 'r'.\nline: " +
+ line,
+ file);
+ throw std::runtime_error("not_a_register");
+ }
+ }
+
+ if (found_some < 1 && name != "ldw" && name != "lda" && name != "stw") {
+ Detail::print_error("invalid combination of opcode and registers.\nline: " + line,
+ file);
+ throw std::runtime_error("invalid_comb_op_reg");
+ } else if (found_some == 1 && name == "add") {
+ Detail::print_error("invalid combination of opcode and registers.\nline: " + line,
+ file);
+ throw std::runtime_error("invalid_comb_op_reg");
+ } else if (found_some == 1 && name == "sub") {
+ Detail::print_error("invalid combination of opcode and registers.\nline: " + line,
+ file);
+ throw std::runtime_error("invalid_comb_op_reg");
+ }
+
+ if (found_some > 0 && name == "pop") {
+ Detail::print_error(
+ "invalid combination for opcode 'pop'.\ntip: it expects "
+ "nothing.\nline: " +
+ line,
+ file);
+ throw std::runtime_error("invalid_comb_op_pop");
+ }
+ }
+ default:
+ break;
+ }
+
+ // try to fetch a number from the name
+ if (name == "stw" || name == "ldw" || name == "lda" || name == "sta") {
+ auto where_string = name;
+
+ // if we load something, we'd need it's symbol/literal
+ if (name == "stw" || name == "sta" || name == "ldw" || name == "lda" || name == "sta")
+ where_string = ",";
+
+ jump_label = line;
+
+ auto found_sym = false;
+
+ while (jump_label.find(where_string) != std::string::npos) {
+ jump_label = jump_label.substr(jump_label.find(where_string) + where_string.size());
+
+ while (jump_label.find(" ") != std::string::npos) {
+ jump_label.erase(jump_label.find(" "), 1);
+ }
+
+ if (jump_label[0] != kAsmRegisterPrefix[0] && !isdigit(jump_label[1])) {
+ if (found_sym) {
+ Detail::print_error(
+ "invalid combination of opcode and operands.\nhere -> " + jump_label, file);
+ throw std::runtime_error("invalid_comb_op_ops");
+ } else {
+ // death trap installed.
+ found_sym = true;
+ }
+ }
+ }
+
+ cpy_jump_label = jump_label;
+
+ // replace any spaces with $
+ if (jump_label[0] == ' ') {
+ while (jump_label.find(' ') != std::string::npos) {
+ if (isalnum(jump_label[0]) || isdigit(jump_label[0])) break;
+
+ jump_label.erase(jump_label.find(' '), 1);
+ }
+ }
+
+ if (!this->WriteNumber(0, jump_label)) {
+ // sta expects this: sta 0x000000, r0
+ if (name == "sta") {
+ Detail::print_error("invalid combination of opcode and operands.\nHere ->" + line,
+ file);
+ throw std::runtime_error("invalid_comb_op_ops");
+ }
+ } else {
+ if (name == "sta" && cpy_jump_label.find("extern_segment ") != std::string::npos) {
+ Detail::print_error("invalid usage extern_segment on 'sta', here: " + line, file);
+ throw std::runtime_error("invalid_sta_usage");
+ }
+ }
+
+ goto asm_write_label;
+ }
+
+ // This is the case where we jump to a label, it is also used as a goto.
+ if (name == "lda" || name == "sta") {
+ asm_write_label:
+ if (cpy_jump_label.find('\n') != std::string::npos)
+ cpy_jump_label.erase(cpy_jump_label.find('\n'), 1);
+
+ if (cpy_jump_label.find("extern_segment") != std::string::npos) {
+ cpy_jump_label.erase(cpy_jump_label.find("extern_segment"), strlen("extern_segment"));
+
+ if (name == "sta") {
+ Detail::print_error("extern_segment is not allowed on a sta operation.", file);
+ throw std::runtime_error("extern_segment_sta_op");
+ } else {
+ goto asm_end_label_cpy;
+ }
+ }
+
+ if (name == "lda" || name == "sta") {
+ for (auto& label : kOriginLabel) {
+ if (cpy_jump_label == label.first) {
+ if (kVerbose) {
+ kStdOut << "Assembler64x0: Replace label " << cpy_jump_label
+ << " to address: " << label.second << std::endl;
+ }
+
+ LibCompiler::NumberCast64 num(label.second);
+
+ for (auto& num : num.number) {
+ kBytes.push_back(num);
+ }
+
+ goto asm_end_label_cpy;
+ }
+ }
+
+ if (cpy_jump_label[0] == '0') {
+ switch (cpy_jump_label[1]) {
+ case 'x':
+ case 'o':
+ case 'b':
+ if (this->WriteNumber(0, cpy_jump_label)) goto asm_end_label_cpy;
+
+ break;
+ default:
+ break;
+ }
+
+ if (isdigit(cpy_jump_label[0])) {
+ if (this->WriteNumber(0, cpy_jump_label)) goto asm_end_label_cpy;
+
+ break;
+ }
+ }
+ }
+
+ if (cpy_jump_label.size() < 1) {
+ Detail::print_error("label is empty, can't jump on it.", file);
+ throw std::runtime_error("label_empty");
+ }
+
+ /// don't go any further if:
+ /// load word (ldw) or store word. (stw)
+
+ if (name == "ldw" || name == "stw") break;
+
+ auto mld_reloc_str = std::to_string(cpy_jump_label.size());
+ mld_reloc_str += kUndefinedSymbol;
+ mld_reloc_str += cpy_jump_label;
+
+ bool ignore_back_slash = false;
+
+ for (auto& reloc_chr : mld_reloc_str) {
+ if (reloc_chr == '\\') {
+ ignore_back_slash = true;
+ continue;
+ }
+
+ if (ignore_back_slash) {
+ ignore_back_slash = false;
+ continue;
+ }
+
+ kBytes.push_back(reloc_chr);
+ }
+
+ kBytes.push_back('\0');
+ goto asm_end_label_cpy;
+ }
+
+ asm_end_label_cpy:
+ kOrigin += c64x0IPAlignment;
+
+ break;
+ }
+ }
+
+ return true;
}
// Last rev 13-1-24
diff --git a/dev/LibCompiler/src/AssemblerAMD64.cc b/dev/LibCompiler/src/AssemblerAMD64.cc
index be77ce9..a5a7ee5 100644
--- a/dev/LibCompiler/src/AssemblerAMD64.cc
+++ b/dev/LibCompiler/src/AssemblerAMD64.cc
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
+ Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
------------------------------------------- */
@@ -24,12 +24,12 @@
#define __ASM_NEED_AMD64__ 1
#define kAssemblerPragmaSymStr "#"
-#define kAssemblerPragmaSym '#'
+#define kAssemblerPragmaSym '#'
-#include <LibCompiler/Backend/amd64.h>
-#include <LibCompiler/Parser.h>
#include <LibCompiler/AE.h>
+#include <LibCompiler/Backend/amd64.h>
#include <LibCompiler/PEF.h>
+#include <LibCompiler/Parser.h>
#include <algorithm>
#include <cstdlib>
#include <filesystem>
@@ -43,25 +43,25 @@
/////////////////////
-#define kBlank "\e[0;30m"
-#define kRed "\e[0;31m"
-#define kWhite "\e[0;97m"
+#define kBlank "\e[0;30m"
+#define kRed "\e[0;31m"
+#define kWhite "\e[0;97m"
#define kYellow "\e[0;33m"
#define kStdOut (std::cout << kWhite)
#define kStdErr (std::cout << kRed)
-static char kOutputArch = LibCompiler::kPefArchAMD64;
+static char kOutputArch = LibCompiler::kPefArchAMD64;
static Boolean kOutputAsBinary = false;
-static UInt32 kErrorLimit = 10;
+static UInt32 kErrorLimit = 10;
static UInt32 kAcceptableErrors = 0;
constexpr auto kIPAlignement = 0x4U;
static std::size_t kCounter = 1UL;
-static std::uintptr_t kOrigin = kPefBaseOrigin;
+static std::uintptr_t kOrigin = kPefBaseOrigin;
static std::vector<std::pair<std::string, std::uintptr_t>> kOriginLabel;
/// @brief keep it simple by default.
@@ -72,11 +72,11 @@ static bool kVerbose = false;
static std::vector<i64_byte_t> kAppBytes;
static LibCompiler::AERecordHeader kCurrentRecord{
- .fName = "", .fKind = LibCompiler::kPefCode, .fSize = 0, .fOffset = 0};
+ .fName = "", .fKind = LibCompiler::kPefCode, .fSize = 0, .fOffset = 0};
static std::vector<LibCompiler::AERecordHeader> kRecords;
-static std::vector<std::string> kDefinedSymbols;
-static std::vector<std::string> kUndefinedSymbols;
+static std::vector<std::string> kDefinedSymbols;
+static std::vector<std::string> kUndefinedSymbols;
static const std::string kUndefinedSymbol = ":UndefinedSymbol:";
@@ -91,289 +91,246 @@ static bool asm_read_attributes(std::string& line);
/////////////////////////////////////////////////////////////////////////////////////////
-LIBCOMPILER_MODULE(AssemblerMainAMD64)
-{
- //////////////// CPU OPCODES BEGIN ////////////////
-
- std::string opcodes_jump[kJumpLimit] = {
- "ja", "jae", "jb", "jbe", "jc", "je", "jg", "jge", "jl", "jle",
- "jna", "jnae", "jnb", "jnbe", "jnc", "jne", "jng", "jnge", "jnl", "jnle",
- "jno", "jnp", "jns", "jnz", "jo", "jp", "jpe", "jpo", "js", "jz"};
-
- for (i64_hword_t i = 0; i < kJumpLimit; i++)
- {
- CpuOpcodeAMD64 code{
- .fName = opcodes_jump[i],
- .fOpcode = static_cast<i64_hword_t>(kAsmJumpOpcode + i)};
- kOpcodesAMD64.push_back(code);
- }
-
- CpuOpcodeAMD64 code{.fName = "jcxz", .fOpcode = 0xE3};
- kOpcodesAMD64.push_back(code);
-
- for (i64_hword_t i = kJumpLimitStandard; i < kJumpLimitStandardLimit; i++)
- {
- CpuOpcodeAMD64 code{.fName = "jmp", .fOpcode = i};
- kOpcodesAMD64.push_back(code);
- }
-
- CpuOpcodeAMD64 lahf{.fName = "lahf", .fOpcode = 0x9F};
- kOpcodesAMD64.push_back(lahf);
-
- CpuOpcodeAMD64 lds{.fName = "lds", .fOpcode = 0xC5};
- kOpcodesAMD64.push_back(lds);
-
- CpuOpcodeAMD64 lea{.fName = "lea", .fOpcode = 0x8D};
- kOpcodesAMD64.push_back(lea);
-
- CpuOpcodeAMD64 nop{.fName = "nop", .fOpcode = 0x90};
- kOpcodesAMD64.push_back(nop);
-
- //////////////// CPU OPCODES END ////////////////
-
- for (size_t i = 1; i < argc; ++i)
- {
- if (argv[i][0] == '-')
- {
- if (strcmp(argv[i], "--amd64:ver") == 0 || strcmp(argv[i], "--amd64:v") == 0)
- {
- kStdOut << "AssemblerAMD64: AMD64 Assembler Driver.\nAssemblerAMD64: v1.10\nAssemblerAMD64: Copyright "
- "(c) Amlal El Mahrouss\n";
- return 0;
- }
- else if (strcmp(argv[i], "--amd64:h") == 0)
- {
- kStdOut << "AssemblerAMD64: AMD64 Assembler Driver.\nAssemblerAMD64: Copyright (c) 2024 "
- "Amlal El Mahrouss\n";
- kStdOut << "--version: Print program version.\n";
- kStdOut << "--verbose: Print verbose output.\n";
- kStdOut << "--binary: Output as flat binary.\n";
-
- return 0;
- }
- else if (strcmp(argv[i], "--amd64:binary") == 0)
- {
- kOutputAsBinary = true;
- continue;
- }
- else if (strcmp(argv[i], "--amd64:verbose") == 0)
- {
- kVerbose = true;
- continue;
- }
-
- kStdOut << "AssemblerAMD64: ignore " << argv[i] << "\n";
- continue;
- }
-
- if (!std::filesystem::exists(argv[i]))
- {
- kStdOut << "AssemblerAMD64: can't open: " << argv[i] << std::endl;
- goto asm_fail_exit;
- }
-
- std::string object_output(argv[i]);
- std::string asm_input(argv[i]);
-
- for (auto& ext : kAsmFileExts)
- {
- if (object_output.ends_with(ext))
- {
- object_output.erase(object_output.find(ext), std::strlen(ext));
- break;
- }
- }
-
- object_output += kOutputAsBinary ? kBinaryFileExt : kObjectFileExt;
-
- std::ifstream file_ptr(argv[i]);
- std::ofstream file_ptr_out(object_output, std::ofstream::binary);
-
- kStdOut << "AssemblerAMD64: Assembling: " << argv[i] << "\n";
-
- if (file_ptr_out.bad())
- {
- if (kVerbose)
- {
- kStdOut << "AssemblerAMD64: error: " << strerror(errno) << "\n";
- }
-
- return 1;
- }
-
- std::string line;
-
- LibCompiler::AEHeader hdr{0};
-
- memset(hdr.fPad, kAENullType, kAEPad);
-
- hdr.fMagic[0] = kAEMag0;
- hdr.fMagic[1] = kAEMag1;
- hdr.fSize = sizeof(LibCompiler::AEHeader);
- hdr.fArch = kOutputArch;
-
- /////////////////////////////////////////////////////////////////////////////////////////
-
- // COMPILATION LOOP
-
- /////////////////////////////////////////////////////////////////////////////////////////
-
- LibCompiler::EncoderAMD64 asm64;
-
- if (kVerbose)
- {
- kStdOut << "Compiling: " + asm_input << "\n";
- kStdOut << "From: " + line << "\n";
- }
-
- while (std::getline(file_ptr, line))
- {
- if (auto ln = asm64.CheckLine(line, argv[i]); !ln.empty())
- {
- Detail::print_error(ln, argv[i]);
- continue;
- }
-
- try
- {
- asm_read_attributes(line);
- asm64.WriteLine(line, argv[i]);
- }
- catch (const std::exception& e)
- {
- if (kVerbose)
- {
- std::string what = e.what();
- Detail::print_warning("exit because of: " + what, "LibCompiler");
- }
-
- try
- {
- std::filesystem::remove(object_output);
- }
- catch (...)
- {
- }
+LIBCOMPILER_MODULE(AssemblerMainAMD64) {
+ //////////////// CPU OPCODES BEGIN ////////////////
+
+ std::string opcodes_jump[kJumpLimit] = {"ja", "jae", "jb", "jbe", "jc", "je", "jg", "jge",
+ "jl", "jle", "jna", "jnae", "jnb", "jnbe", "jnc", "jne",
+ "jng", "jnge", "jnl", "jnle", "jno", "jnp", "jns", "jnz",
+ "jo", "jp", "jpe", "jpo", "js", "jz"};
+
+ for (i64_hword_t i = 0; i < kJumpLimit; i++) {
+ CpuOpcodeAMD64 code{.fName = opcodes_jump[i],
+ .fOpcode = static_cast<i64_hword_t>(kAsmJumpOpcode + i)};
+ kOpcodesAMD64.push_back(code);
+ }
+
+ CpuOpcodeAMD64 code{.fName = "jcxz", .fOpcode = 0xE3};
+ kOpcodesAMD64.push_back(code);
+
+ for (i64_hword_t i = kJumpLimitStandard; i < kJumpLimitStandardLimit; i++) {
+ CpuOpcodeAMD64 code{.fName = "jmp", .fOpcode = i};
+ kOpcodesAMD64.push_back(code);
+ }
+
+ CpuOpcodeAMD64 lahf{.fName = "lahf", .fOpcode = 0x9F};
+ kOpcodesAMD64.push_back(lahf);
+
+ CpuOpcodeAMD64 lds{.fName = "lds", .fOpcode = 0xC5};
+ kOpcodesAMD64.push_back(lds);
+
+ CpuOpcodeAMD64 lea{.fName = "lea", .fOpcode = 0x8D};
+ kOpcodesAMD64.push_back(lea);
+
+ CpuOpcodeAMD64 nop{.fName = "nop", .fOpcode = 0x90};
+ kOpcodesAMD64.push_back(nop);
+
+ //////////////// CPU OPCODES END ////////////////
+
+ for (size_t i = 1; i < argc; ++i) {
+ if (argv[i][0] == '-') {
+ if (strcmp(argv[i], "--amd64:ver") == 0 || strcmp(argv[i], "--amd64:v") == 0) {
+ kStdOut << "AssemblerAMD64: AMD64 Assembler Driver.\nAssemblerAMD64: "
+ "v1.10\nAssemblerAMD64: Copyright "
+ "(c) Amlal El Mahrouss\n";
+ return 0;
+ } else if (strcmp(argv[i], "--amd64:h") == 0) {
+ kStdOut << "AssemblerAMD64: AMD64 Assembler Driver.\nAssemblerAMD64: Copyright (c) 2024 "
+ "Amlal El Mahrouss\n";
+ kStdOut << "--version: Print program version.\n";
+ kStdOut << "--verbose: Print verbose output.\n";
+ kStdOut << "--binary: Output as flat binary.\n";
+
+ return 0;
+ } else if (strcmp(argv[i], "--amd64:binary") == 0) {
+ kOutputAsBinary = true;
+ continue;
+ } else if (strcmp(argv[i], "--amd64:verbose") == 0) {
+ kVerbose = true;
+ continue;
+ }
+
+ kStdOut << "AssemblerAMD64: ignore " << argv[i] << "\n";
+ continue;
+ }
+
+ if (!std::filesystem::exists(argv[i])) {
+ kStdOut << "AssemblerAMD64: can't open: " << argv[i] << std::endl;
+ goto asm_fail_exit;
+ }
+
+ std::string object_output(argv[i]);
+ std::string asm_input(argv[i]);
+
+ for (auto& ext : kAsmFileExts) {
+ if (object_output.ends_with(ext)) {
+ object_output.erase(object_output.find(ext), std::strlen(ext));
+ break;
+ }
+ }
+
+ object_output += kOutputAsBinary ? kBinaryFileExt : kObjectFileExt;
+
+ std::ifstream file_ptr(argv[i]);
+ std::ofstream file_ptr_out(object_output, std::ofstream::binary);
+
+ kStdOut << "AssemblerAMD64: Assembling: " << argv[i] << "\n";
+
+ if (file_ptr_out.bad()) {
+ if (kVerbose) {
+ kStdOut << "AssemblerAMD64: error: " << strerror(errno) << "\n";
+ }
+
+ return 1;
+ }
+
+ std::string line;
- goto asm_fail_exit;
- }
- }
+ LibCompiler::AEHeader hdr{0};
- if (!kOutputAsBinary)
- {
- if (kVerbose)
- {
- kStdOut << "AssemblerAMD64: Writing object file...\n";
- }
+ memset(hdr.fPad, kAENullType, kAEPad);
- // this is the final step, write everything to the file.
+ hdr.fMagic[0] = kAEMag0;
+ hdr.fMagic[1] = kAEMag1;
+ hdr.fSize = sizeof(LibCompiler::AEHeader);
+ hdr.fArch = kOutputArch;
- auto pos = file_ptr_out.tellp();
+ /////////////////////////////////////////////////////////////////////////////////////////
- hdr.fCount = kRecords.size() + kUndefinedSymbols.size();
+ // COMPILATION LOOP
- file_ptr_out << hdr;
+ /////////////////////////////////////////////////////////////////////////////////////////
- if (kRecords.empty())
- {
- kStdErr << "AssemblerAMD64: At least one record is needed to write an object "
- "file.\nAssemblerAMD64: Make one using `public_segment .code64 foo_bar`.\n";
+ LibCompiler::EncoderAMD64 asm64;
- std::filesystem::remove(object_output);
- return 1;
- }
+ if (kVerbose) {
+ kStdOut << "Compiling: " + asm_input << "\n";
+ kStdOut << "From: " + line << "\n";
+ }
- kRecords[kRecords.size() - 1].fSize = kAppBytes.size();
+ while (std::getline(file_ptr, line)) {
+ if (auto ln = asm64.CheckLine(line, argv[i]); !ln.empty()) {
+ Detail::print_error(ln, argv[i]);
+ continue;
+ }
- std::size_t record_count = 0UL;
+ try {
+ asm_read_attributes(line);
+ asm64.WriteLine(line, argv[i]);
+ } catch (const std::exception& e) {
+ if (kVerbose) {
+ std::string what = e.what();
+ Detail::print_warning("exit because of: " + what, "LibCompiler");
+ }
- for (auto& rec : kRecords)
- {
- if (kVerbose)
- kStdOut << "AssemblerAMD64: Wrote record " << rec.fName << " to file...\n";
+ try {
+ std::filesystem::remove(object_output);
+ } catch (...) {
+ }
- rec.fFlags |= LibCompiler::kKindRelocationAtRuntime;
- rec.fOffset = record_count;
- ++record_count;
+ goto asm_fail_exit;
+ }
+ }
- file_ptr_out << rec;
- }
+ if (!kOutputAsBinary) {
+ if (kVerbose) {
+ kStdOut << "AssemblerAMD64: Writing object file...\n";
+ }
- // increment once again, so that we won't lie about the kUndefinedSymbols.
- ++record_count;
+ // this is the final step, write everything to the file.
- for (auto& sym : kUndefinedSymbols)
- {
- LibCompiler::AERecordHeader _record_hdr{0};
+ auto pos = file_ptr_out.tellp();
- if (kVerbose)
- kStdOut << "AssemblerAMD64: Wrote symbol " << sym << " to file...\n";
+ hdr.fCount = kRecords.size() + kUndefinedSymbols.size();
- _record_hdr.fKind = kAENullType;
- _record_hdr.fSize = sym.size();
- _record_hdr.fOffset = record_count;
+ file_ptr_out << hdr;
- ++record_count;
+ if (kRecords.empty()) {
+ kStdErr << "AssemblerAMD64: At least one record is needed to write an object "
+ "file.\nAssemblerAMD64: Make one using `public_segment .code64 foo_bar`.\n";
- memset(_record_hdr.fPad, kAENullType, kAEPad);
- memcpy(_record_hdr.fName, sym.c_str(), sym.size());
+ std::filesystem::remove(object_output);
+ return 1;
+ }
- file_ptr_out << _record_hdr;
+ kRecords[kRecords.size() - 1].fSize = kAppBytes.size();
- ++kCounter;
- }
+ std::size_t record_count = 0UL;
- auto pos_end = file_ptr_out.tellp();
+ for (auto& rec : kRecords) {
+ if (kVerbose) kStdOut << "AssemblerAMD64: Wrote record " << rec.fName << " to file...\n";
- file_ptr_out.seekp(pos);
+ rec.fFlags |= LibCompiler::kKindRelocationAtRuntime;
+ rec.fOffset = record_count;
+ ++record_count;
- hdr.fStartCode = pos_end;
- hdr.fCodeSize = kAppBytes.size();
+ file_ptr_out << rec;
+ }
- file_ptr_out << hdr;
+ // increment once again, so that we won't lie about the kUndefinedSymbols.
+ ++record_count;
- file_ptr_out.seekp(pos_end);
- }
- else
- {
- if (kVerbose)
- {
- kStdOut << "AssemblerAMD64: Write raw binary...\n";
- }
- }
+ for (auto& sym : kUndefinedSymbols) {
+ LibCompiler::AERecordHeader _record_hdr{0};
- // byte from byte, we write this.
- for (auto& byte : kAppBytes)
- {
- if (byte == 0)
- continue;
+ if (kVerbose) kStdOut << "AssemblerAMD64: Wrote symbol " << sym << " to file...\n";
- if (byte == 0xFF)
- {
- byte = 0;
- }
+ _record_hdr.fKind = kAENullType;
+ _record_hdr.fSize = sym.size();
+ _record_hdr.fOffset = record_count;
- file_ptr_out << reinterpret_cast<const char*>(&byte)[0];
- }
+ ++record_count;
- if (kVerbose)
- kStdOut << "AssemblerAMD64: Wrote file with program in it.\n";
+ memset(_record_hdr.fPad, kAENullType, kAEPad);
+ memcpy(_record_hdr.fName, sym.c_str(), sym.size());
- file_ptr_out.flush();
- file_ptr_out.close();
+ file_ptr_out << _record_hdr;
- if (kVerbose)
- kStdOut << "AssemblerAMD64: Exit succeeded.\n";
+ ++kCounter;
+ }
- return 0;
- }
+ auto pos_end = file_ptr_out.tellp();
+
+ file_ptr_out.seekp(pos);
+
+ hdr.fStartCode = pos_end;
+ hdr.fCodeSize = kAppBytes.size();
+
+ file_ptr_out << hdr;
+
+ file_ptr_out.seekp(pos_end);
+ } else {
+ if (kVerbose) {
+ kStdOut << "AssemblerAMD64: Write raw binary...\n";
+ }
+ }
+
+ // byte from byte, we write this.
+ for (auto& byte : kAppBytes) {
+ if (byte == 0) continue;
+
+ if (byte == 0xFF) {
+ byte = 0;
+ }
+
+ file_ptr_out << reinterpret_cast<const char*>(&byte)[0];
+ }
+
+ if (kVerbose) kStdOut << "AssemblerAMD64: Wrote file with program in it.\n";
+
+ file_ptr_out.flush();
+ file_ptr_out.close();
+
+ if (kVerbose) kStdOut << "AssemblerAMD64: Exit succeeded.\n";
+
+ return 0;
+ }
asm_fail_exit:
- if (kVerbose)
- kStdOut << "AssemblerAMD64: Exit failed.\n";
+ if (kVerbose) kStdOut << "AssemblerAMD64: Exit failed.\n";
- return 1;
+ return 1;
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -383,185 +340,155 @@ asm_fail_exit:
/////////////////////////////////////////////////////////////////////////////////////////
-static bool asm_read_attributes(std::string& line)
-{
- // extern_segment is the opposite of public_segment, it signals to the ld
- // that we need this symbol.
- if (LibCompiler::find_word(line, "extern_segment"))
- {
- if (kOutputAsBinary)
- {
- Detail::print_error("Invalid directive in flat binary mode.", "LibCompiler");
- throw std::runtime_error("invalid_extern_segment_bin");
- }
-
- auto name = line.substr(line.find("extern_segment") + strlen("extern_segment") + 1);
-
- if (name.size() == 0)
- {
- Detail::print_error("Invalid extern_segment", "power-as");
- throw std::runtime_error("invalid_extern_segment");
- }
-
- std::string result = std::to_string(name.size());
- result += kUndefinedSymbol;
-
- // mangle this
- for (char& j : name)
- {
- if (j == ' ' || j == ',')
- j = '$';
- }
-
- result += name;
-
- if (name.find(kPefCode64) != std::string::npos)
- {
- // data is treated as code.
- kCurrentRecord.fKind = LibCompiler::kPefCode;
- }
- else if (name.find(kPefData64) != std::string::npos)
- {
- // no code will be executed from here.
- kCurrentRecord.fKind = LibCompiler::kPefData;
- }
- else if (name.find(kPefZero64) != std::string::npos)
- {
- // this is a bss section.
- kCurrentRecord.fKind = LibCompiler::kPefZero;
- }
-
- // this is a special case for the start stub.
- // we want this so that ld can find it.
-
- if (name == kPefStart)
- {
- kCurrentRecord.fKind = LibCompiler::kPefCode;
- }
-
- // now we can tell the code size of the previous kCurrentRecord.
-
- if (!kRecords.empty())
- kRecords[kRecords.size() - 1].fSize = kAppBytes.size();
-
- memset(kCurrentRecord.fName, 0, kAESymbolLen);
- memcpy(kCurrentRecord.fName, result.c_str(), result.size());
-
- ++kCounter;
-
- memset(kCurrentRecord.fPad, kAENullType, kAEPad);
-
- kRecords.emplace_back(kCurrentRecord);
-
- return true;
- }
- // public_segment is a special keyword used by AssemblerAMD64 to tell the AE output stage to
- // mark this section as a header. it currently supports .code64, .data64 and
- // .zero64.
- else if (LibCompiler::find_word(line, "public_segment"))
- {
- if (kOutputAsBinary)
- {
- Detail::print_error("Invalid directive in flat binary mode.", "LibCompiler");
- throw std::runtime_error("invalid_public_segment_bin");
- }
-
- auto name = line.substr(line.find("public_segment") + strlen("public_segment") + 1);
-
- std::string name_copy = name;
-
- for (char& j : name)
- {
- if (j == ' ')
- j = '$';
- }
-
- if (std::find(kDefinedSymbols.begin(), kDefinedSymbols.end(), name) !=
- kDefinedSymbols.end())
- {
- Detail::print_error("Symbol already defined.", "LibCompiler");
- throw std::runtime_error("invalid_public_segment_bin");
- }
-
- kDefinedSymbols.push_back(name);
-
- if (name.find(".code64") != std::string::npos)
- {
- // data is treated as code.
-
- name_copy.erase(name_copy.find(".code64"), strlen(".code64"));
- kCurrentRecord.fKind = LibCompiler::kPefCode;
- }
- else if (name.find(".data64") != std::string::npos)
- {
- // no code will be executed from here.
-
- name_copy.erase(name_copy.find(".data64"), strlen(".data64"));
- kCurrentRecord.fKind = LibCompiler::kPefData;
- }
- else if (name.find(".zero64") != std::string::npos)
- {
- // this is a bss section.
+static bool asm_read_attributes(std::string& line) {
+ // extern_segment is the opposite of public_segment, it signals to the ld
+ // that we need this symbol.
+ if (LibCompiler::find_word(line, "extern_segment")) {
+ if (kOutputAsBinary) {
+ Detail::print_error("Invalid directive in flat binary mode.", "LibCompiler");
+ throw std::runtime_error("invalid_extern_segment_bin");
+ }
+
+ auto name = line.substr(line.find("extern_segment") + strlen("extern_segment") + 1);
+
+ if (name.size() == 0) {
+ Detail::print_error("Invalid extern_segment", "power-as");
+ throw std::runtime_error("invalid_extern_segment");
+ }
+
+ std::string result = std::to_string(name.size());
+ result += kUndefinedSymbol;
+
+ // mangle this
+ for (char& j : name) {
+ if (j == ' ' || j == ',') j = '$';
+ }
+
+ result += name;
+
+ if (name.find(kPefCode64) != std::string::npos) {
+ // data is treated as code.
+ kCurrentRecord.fKind = LibCompiler::kPefCode;
+ } else if (name.find(kPefData64) != std::string::npos) {
+ // no code will be executed from here.
+ kCurrentRecord.fKind = LibCompiler::kPefData;
+ } else if (name.find(kPefZero64) != std::string::npos) {
+ // this is a bss section.
+ kCurrentRecord.fKind = LibCompiler::kPefZero;
+ }
+
+ // this is a special case for the start stub.
+ // we want this so that ld can find it.
+
+ if (name == kPefStart) {
+ kCurrentRecord.fKind = LibCompiler::kPefCode;
+ }
+
+ // now we can tell the code size of the previous kCurrentRecord.
+
+ if (!kRecords.empty()) kRecords[kRecords.size() - 1].fSize = kAppBytes.size();
+
+ memset(kCurrentRecord.fName, 0, kAESymbolLen);
+ memcpy(kCurrentRecord.fName, result.c_str(), result.size());
- name_copy.erase(name_copy.find(".zero64"), strlen(".zero64"));
- kCurrentRecord.fKind = LibCompiler::kPefZero;
- }
-
- // this is a special case for the start stub.
- // we want this so that ld can find it.
+ ++kCounter;
- if (name == kPefStart)
- {
- kCurrentRecord.fKind = LibCompiler::kPefCode;
- }
+ memset(kCurrentRecord.fPad, kAENullType, kAEPad);
- while (name_copy.find(" ") != std::string::npos)
- name_copy.erase(name_copy.find(" "), 1);
+ kRecords.emplace_back(kCurrentRecord);
- kOriginLabel.push_back(std::make_pair(name_copy, kOrigin));
- ++kOrigin;
+ return true;
+ }
+ // public_segment is a special keyword used by AssemblerAMD64 to tell the AE output stage to
+ // mark this section as a header. it currently supports .code64, .data64 and
+ // .zero64.
+ else if (LibCompiler::find_word(line, "public_segment")) {
+ if (kOutputAsBinary) {
+ Detail::print_error("Invalid directive in flat binary mode.", "LibCompiler");
+ throw std::runtime_error("invalid_public_segment_bin");
+ }
- // now we can tell the code size of the previous kCurrentRecord.
+ auto name = line.substr(line.find("public_segment") + strlen("public_segment") + 1);
- if (!kRecords.empty())
- kRecords[kRecords.size() - 1].fSize = kAppBytes.size();
+ std::string name_copy = name;
- memset(kCurrentRecord.fName, 0, kAESymbolLen);
- memcpy(kCurrentRecord.fName, name.c_str(), name.size());
+ for (char& j : name) {
+ if (j == ' ') j = '$';
+ }
- ++kCounter;
+ if (std::find(kDefinedSymbols.begin(), kDefinedSymbols.end(), name) != kDefinedSymbols.end()) {
+ Detail::print_error("Symbol already defined.", "LibCompiler");
+ throw std::runtime_error("invalid_public_segment_bin");
+ }
- memset(kCurrentRecord.fPad, kAENullType, kAEPad);
+ kDefinedSymbols.push_back(name);
- kRecords.emplace_back(kCurrentRecord);
+ if (name.find(".code64") != std::string::npos) {
+ // data is treated as code.
- return true;
- }
+ name_copy.erase(name_copy.find(".code64"), strlen(".code64"));
+ kCurrentRecord.fKind = LibCompiler::kPefCode;
+ } else if (name.find(".data64") != std::string::npos) {
+ // no code will be executed from here.
- return false;
+ name_copy.erase(name_copy.find(".data64"), strlen(".data64"));
+ kCurrentRecord.fKind = LibCompiler::kPefData;
+ } else if (name.find(".zero64") != std::string::npos) {
+ // this is a bss section.
+
+ name_copy.erase(name_copy.find(".zero64"), strlen(".zero64"));
+ kCurrentRecord.fKind = LibCompiler::kPefZero;
+ }
+
+ // this is a special case for the start stub.
+ // we want this so that ld can find it.
+
+ if (name == kPefStart) {
+ kCurrentRecord.fKind = LibCompiler::kPefCode;
+ }
+
+ while (name_copy.find(" ") != std::string::npos) name_copy.erase(name_copy.find(" "), 1);
+
+ kOriginLabel.push_back(std::make_pair(name_copy, kOrigin));
+ ++kOrigin;
+
+ // now we can tell the code size of the previous kCurrentRecord.
+
+ if (!kRecords.empty()) kRecords[kRecords.size() - 1].fSize = kAppBytes.size();
+
+ memset(kCurrentRecord.fName, 0, kAESymbolLen);
+ memcpy(kCurrentRecord.fName, name.c_str(), name.size());
+
+ ++kCounter;
+
+ memset(kCurrentRecord.fPad, kAENullType, kAEPad);
+
+ kRecords.emplace_back(kCurrentRecord);
+
+ return true;
+ }
+
+ return false;
}
// \brief algorithms and helpers.
-namespace Detail::algorithm
-{
- // \brief authorize a brief set of characters.
- static inline bool is_not_valid(char c)
- {
- if ((isalpha(c) || isdigit(c)) || ((c == ' ') || (c == '\t') ||
- (c == ',') || (c == '(') || (c == ')') || (c == '"') || (c == '*') ||
- (c == '\'') || (c == '[') || (c == ']') || (c == '+') ||
- (c == '_') || (c == ':') || (c == '@') || (c == '.') || (c == '#') || (c == ';')))
- return false;
-
- return true;
- }
-
- bool is_valid_amd64(const std::string& str)
- {
- return std::find_if(str.begin(), str.end(), is_not_valid) == str.end();
- }
-} // namespace Detail::algorithm
+namespace Detail::algorithm {
+// \brief authorize a brief set of characters.
+static inline bool is_not_valid(char c) {
+ if ((isalpha(c) || isdigit(c)) ||
+ ((c == ' ') || (c == '\t') || (c == ',') || (c == '(') || (c == ')') || (c == '"') ||
+ (c == '*') || (c == '\'') || (c == '[') || (c == ']') || (c == '+') || (c == '_') ||
+ (c == ':') || (c == '@') || (c == '.') || (c == '#') || (c == ';')))
+ return false;
+
+ return true;
+}
+
+bool is_valid_amd64(const std::string& str) {
+ return std::find_if(str.begin(), str.end(), is_not_valid) == str.end();
+}
+} // namespace Detail::algorithm
/////////////////////////////////////////////////////////////////////////////////////////
@@ -569,580 +496,458 @@ namespace Detail::algorithm
/////////////////////////////////////////////////////////////////////////////////////////
-std::string LibCompiler::EncoderAMD64::CheckLine(std::string& line,
- const std::string& file)
-{
- std::string err_str;
-
- if (line.empty() || LibCompiler::find_word(line, "extern_segment") ||
- LibCompiler::find_word(line, "public_segment") ||
- LibCompiler::find_word(line, kAssemblerPragmaSymStr) ||
- LibCompiler::find_word(line, ";") || line[0] == kAssemblerPragmaSym)
- {
- if (line.find(';') != std::string::npos)
- {
- line.erase(line.find(';'));
- }
- else
- {
- // now check the line for validity
- if (!Detail::algorithm::is_valid_amd64(line))
- {
- err_str = "Line contains non valid characters.\nhere -> ";
- err_str += line;
- }
- }
-
- return err_str;
- }
-
- // check for a valid instruction format.
-
- if (line.find(',') != std::string::npos)
- {
- if (line.find(',') + 1 == line.size())
- {
- err_str += "\nInstruction lacks right register, here -> ";
- err_str += line.substr(line.find(','));
-
- return err_str;
- }
- else
- {
- bool nothing_on_right = true;
-
- if (line.find(',') + 1 > line.size())
- {
- err_str += "\nInstruction not complete, here -> ";
- err_str += line;
-
- return err_str;
- }
-
- auto substr = line.substr(line.find(',') + 1);
-
- for (auto& ch : substr)
- {
- if (ch != ' ' && ch != '\t')
- {
- nothing_on_right = false;
- }
- }
-
- // this means we found nothing after that ',' .
- if (nothing_on_right)
- {
- err_str += "\nInstruction not complete, here -> ";
- err_str += line;
-
- return err_str;
- }
- }
- }
- for (auto& opcodeAMD64 : kOpcodesAMD64)
- {
- if (LibCompiler::find_word(line, opcodeAMD64.fName))
- {
- return err_str;
- }
- }
-
- err_str += "\nUnrecognized instruction -> " + line;
-
- return err_str;
+std::string LibCompiler::EncoderAMD64::CheckLine(std::string& line, const std::string& file) {
+ std::string err_str;
+
+ if (line.empty() || LibCompiler::find_word(line, "extern_segment") ||
+ LibCompiler::find_word(line, "public_segment") ||
+ LibCompiler::find_word(line, kAssemblerPragmaSymStr) || LibCompiler::find_word(line, ";") ||
+ line[0] == kAssemblerPragmaSym) {
+ if (line.find(';') != std::string::npos) {
+ line.erase(line.find(';'));
+ } else {
+ // now check the line for validity
+ if (!Detail::algorithm::is_valid_amd64(line)) {
+ err_str = "Line contains non valid characters.\nhere -> ";
+ err_str += line;
+ }
+ }
+
+ return err_str;
+ }
+
+ // check for a valid instruction format.
+
+ if (line.find(',') != std::string::npos) {
+ if (line.find(',') + 1 == line.size()) {
+ err_str += "\nInstruction lacks right register, here -> ";
+ err_str += line.substr(line.find(','));
+
+ return err_str;
+ } else {
+ bool nothing_on_right = true;
+
+ if (line.find(',') + 1 > line.size()) {
+ err_str += "\nInstruction not complete, here -> ";
+ err_str += line;
+
+ return err_str;
+ }
+
+ auto substr = line.substr(line.find(',') + 1);
+
+ for (auto& ch : substr) {
+ if (ch != ' ' && ch != '\t') {
+ nothing_on_right = false;
+ }
+ }
+
+ // this means we found nothing after that ',' .
+ if (nothing_on_right) {
+ err_str += "\nInstruction not complete, here -> ";
+ err_str += line;
+
+ return err_str;
+ }
+ }
+ }
+ for (auto& opcodeAMD64 : kOpcodesAMD64) {
+ if (LibCompiler::find_word(line, opcodeAMD64.fName)) {
+ return err_str;
+ }
+ }
+
+ err_str += "\nUnrecognized instruction -> " + line;
+
+ return err_str;
}
-bool LibCompiler::EncoderAMD64::WriteNumber(const std::size_t& pos,
- std::string& jump_label)
-{
- if (!isdigit(jump_label[pos]))
- return false;
-
- switch (jump_label[pos + 1])
- {
- case 'x': {
- if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16);
- !res)
- {
- if (errno != 0)
- {
- Detail::print_error("invalid hex number: " + jump_label, "LibCompiler");
- throw std::runtime_error("invalid_hex");
- }
- }
-
- LibCompiler::NumberCast64 num = LibCompiler::NumberCast64(
- strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16));
-
- for (char& i : num.number)
- {
- if (i == 0)
- i = 0xFF;
-
- kAppBytes.push_back(i);
- }
-
- if (kVerbose)
- {
- kStdOut << "AssemblerAMD64: Found a base 16 number here: "
- << jump_label.substr(pos) << "\n";
- }
-
- return true;
- }
- case 'b': {
- if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2);
- !res)
- {
- if (errno != 0)
- {
- Detail::print_error("invalid binary number: " + jump_label, "LibCompiler");
- throw std::runtime_error("invalid_bin");
- }
- }
-
- LibCompiler::NumberCast64 num = LibCompiler::NumberCast64(
- strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2));
-
- if (kVerbose)
- {
- kStdOut << "AssemblerAMD64: Found a base 2 number here: "
- << jump_label.substr(pos) << "\n";
- }
-
- for (char& i : num.number)
- {
- if (i == 0)
- i = 0xFF;
-
- kAppBytes.push_back(i);
- }
-
- return true;
- }
- case 'o': {
- if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7);
- !res)
- {
- if (errno != 0)
- {
- Detail::print_error("invalid octal number: " + jump_label, "LibCompiler");
- throw std::runtime_error("invalid_octal");
- }
- }
-
- LibCompiler::NumberCast64 num = LibCompiler::NumberCast64(
- strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7));
-
- if (kVerbose)
- {
- kStdOut << "AssemblerAMD64: Found a base 8 number here: "
- << jump_label.substr(pos) << "\n";
- }
-
- for (char& i : num.number)
- {
- if (i == 0)
- i = 0xFF;
-
- kAppBytes.push_back(i);
- }
-
- return true;
- }
- default: {
- break;
- }
- }
-
- /* check for errno and stuff like that */
- if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res)
- {
- if (errno != 0)
- {
- return false;
- }
- }
-
- LibCompiler::NumberCast64 num = LibCompiler::NumberCast64(
- strtol(jump_label.substr(pos).c_str(), nullptr, 10));
-
- for (char& i : num.number)
- {
- if (i == 0)
- i = 0xFF;
-
- kAppBytes.push_back(i);
- }
-
- if (kVerbose)
- {
- kStdOut << "AssemblerAMD64: Found a base 10 number here: " << jump_label.substr(pos)
- << "\n";
- }
-
- return true;
+bool LibCompiler::EncoderAMD64::WriteNumber(const std::size_t& pos, std::string& jump_label) {
+ if (!isdigit(jump_label[pos])) return false;
+
+ switch (jump_label[pos + 1]) {
+ case 'x': {
+ if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16); !res) {
+ if (errno != 0) {
+ Detail::print_error("invalid hex number: " + jump_label, "LibCompiler");
+ throw std::runtime_error("invalid_hex");
+ }
+ }
+
+ LibCompiler::NumberCast64 num =
+ LibCompiler::NumberCast64(strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16));
+
+ for (char& i : num.number) {
+ if (i == 0) i = 0xFF;
+
+ kAppBytes.push_back(i);
+ }
+
+ if (kVerbose) {
+ kStdOut << "AssemblerAMD64: Found a base 16 number here: " << jump_label.substr(pos)
+ << "\n";
+ }
+
+ return true;
+ }
+ case 'b': {
+ if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2); !res) {
+ if (errno != 0) {
+ Detail::print_error("invalid binary number: " + jump_label, "LibCompiler");
+ throw std::runtime_error("invalid_bin");
+ }
+ }
+
+ LibCompiler::NumberCast64 num =
+ LibCompiler::NumberCast64(strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2));
+
+ if (kVerbose) {
+ kStdOut << "AssemblerAMD64: Found a base 2 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ for (char& i : num.number) {
+ if (i == 0) i = 0xFF;
+
+ kAppBytes.push_back(i);
+ }
+
+ return true;
+ }
+ case 'o': {
+ if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7); !res) {
+ if (errno != 0) {
+ Detail::print_error("invalid octal number: " + jump_label, "LibCompiler");
+ throw std::runtime_error("invalid_octal");
+ }
+ }
+
+ LibCompiler::NumberCast64 num =
+ LibCompiler::NumberCast64(strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7));
+
+ if (kVerbose) {
+ kStdOut << "AssemblerAMD64: Found a base 8 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ for (char& i : num.number) {
+ if (i == 0) i = 0xFF;
+
+ kAppBytes.push_back(i);
+ }
+
+ return true;
+ }
+ default: {
+ break;
+ }
+ }
+
+ /* check for errno and stuff like that */
+ if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res) {
+ if (errno != 0) {
+ return false;
+ }
+ }
+
+ LibCompiler::NumberCast64 num =
+ LibCompiler::NumberCast64(strtol(jump_label.substr(pos).c_str(), nullptr, 10));
+
+ for (char& i : num.number) {
+ if (i == 0) i = 0xFF;
+
+ kAppBytes.push_back(i);
+ }
+
+ if (kVerbose) {
+ kStdOut << "AssemblerAMD64: Found a base 10 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ return true;
}
-bool LibCompiler::EncoderAMD64::WriteNumber32(const std::size_t& pos,
- std::string& jump_label)
-{
- if (!isdigit(jump_label[pos]))
- return false;
-
- switch (jump_label[pos + 1])
- {
- case 'x': {
- auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16);
- res += kOrigin;
-
- if (errno != 0)
- {
- return false;
- }
-
- LibCompiler::NumberCast32 num = LibCompiler::NumberCast32(res);
-
- for (char& i : num.number)
- {
- if (i == 0)
- i = 0xFF;
-
- kAppBytes.push_back(i);
- }
-
- if (kVerbose)
- {
- kStdOut << "AssemblerAMD64: Found a base 16 number here: "
- << jump_label.substr(pos) << "\n";
- }
-
- return true;
- }
- case 'b': {
- auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2);
- res += kOrigin;
-
- if (errno != 0)
- {
- return false;
- }
-
- LibCompiler::NumberCast32 num = LibCompiler::NumberCast32(res);
-
- if (kVerbose)
- {
- kStdOut << "AssemblerAMD64: Found a base 2 number here: "
- << jump_label.substr(pos) << "\n";
- }
-
- for (char& i : num.number)
- {
- if (i == 0)
- i = 0xFF;
-
- kAppBytes.push_back(i);
- }
-
- return true;
- }
- case 'o': {
- auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7);
- res += kOrigin;
-
- if (errno != 0)
- {
- return false;
- }
-
- LibCompiler::NumberCast32 num = LibCompiler::NumberCast32(res);
-
- if (kVerbose)
- {
- kStdOut << "AssemblerAMD64: Found a base 8 number here: "
- << jump_label.substr(pos) << "\n";
- }
-
- for (char& i : num.number)
- {
- if (i == 0)
- i = 0xFF;
-
- kAppBytes.push_back(i);
- }
-
- return true;
- }
- default: {
- break;
- }
- }
-
- auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 10);
- res += kOrigin;
-
- if (errno != 0)
- {
- return false;
- }
-
- LibCompiler::NumberCast32 num = LibCompiler::NumberCast32(res);
-
- for (char& i : num.number)
- {
- if (i == 0)
- i = 0xFF;
-
- kAppBytes.push_back(i);
- }
-
- if (kVerbose)
- {
- kStdOut << "AssemblerAMD64: Found a base 10 number here: " << jump_label.substr(pos)
- << "\n";
- }
-
- return true;
+bool LibCompiler::EncoderAMD64::WriteNumber32(const std::size_t& pos, std::string& jump_label) {
+ if (!isdigit(jump_label[pos])) return false;
+
+ switch (jump_label[pos + 1]) {
+ case 'x': {
+ auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16);
+ res += kOrigin;
+
+ if (errno != 0) {
+ return false;
+ }
+
+ LibCompiler::NumberCast32 num = LibCompiler::NumberCast32(res);
+
+ for (char& i : num.number) {
+ if (i == 0) i = 0xFF;
+
+ kAppBytes.push_back(i);
+ }
+
+ if (kVerbose) {
+ kStdOut << "AssemblerAMD64: Found a base 16 number here: " << jump_label.substr(pos)
+ << "\n";
+ }
+
+ return true;
+ }
+ case 'b': {
+ auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2);
+ res += kOrigin;
+
+ if (errno != 0) {
+ return false;
+ }
+
+ LibCompiler::NumberCast32 num = LibCompiler::NumberCast32(res);
+
+ if (kVerbose) {
+ kStdOut << "AssemblerAMD64: Found a base 2 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ for (char& i : num.number) {
+ if (i == 0) i = 0xFF;
+
+ kAppBytes.push_back(i);
+ }
+
+ return true;
+ }
+ case 'o': {
+ auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7);
+ res += kOrigin;
+
+ if (errno != 0) {
+ return false;
+ }
+
+ LibCompiler::NumberCast32 num = LibCompiler::NumberCast32(res);
+
+ if (kVerbose) {
+ kStdOut << "AssemblerAMD64: Found a base 8 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ for (char& i : num.number) {
+ if (i == 0) i = 0xFF;
+
+ kAppBytes.push_back(i);
+ }
+
+ return true;
+ }
+ default: {
+ break;
+ }
+ }
+
+ auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 10);
+ res += kOrigin;
+
+ if (errno != 0) {
+ return false;
+ }
+
+ LibCompiler::NumberCast32 num = LibCompiler::NumberCast32(res);
+
+ for (char& i : num.number) {
+ if (i == 0) i = 0xFF;
+
+ kAppBytes.push_back(i);
+ }
+
+ if (kVerbose) {
+ kStdOut << "AssemblerAMD64: Found a base 10 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ return true;
}
-bool LibCompiler::EncoderAMD64::WriteNumber16(const std::size_t& pos,
- std::string& jump_label)
-{
- if (!isdigit(jump_label[pos]))
- return false;
-
- switch (jump_label[pos + 1])
- {
- case 'x': {
- if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16);
- !res)
- {
- if (errno != 0)
- {
- Detail::print_error("invalid hex number: " + jump_label, "LibCompiler");
- throw std::runtime_error("invalid_hex");
- }
- }
-
- LibCompiler::NumberCast16 num = LibCompiler::NumberCast16(
- strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16));
-
- for (char& i : num.number)
- {
- if (i == 0)
- i = 0xFF;
-
- kAppBytes.push_back(i);
- }
-
- if (kVerbose)
- {
- kStdOut << "AssemblerAMD64: Found a base 16 number here: "
- << jump_label.substr(pos) << "\n";
- }
-
- return true;
- }
- case 'b': {
- if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2);
- !res)
- {
- if (errno != 0)
- {
- Detail::print_error("invalid binary number: " + jump_label, "LibCompiler");
- throw std::runtime_error("invalid_bin");
- }
- }
-
- LibCompiler::NumberCast16 num = LibCompiler::NumberCast16(
- strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2));
-
- if (kVerbose)
- {
- kStdOut << "AssemblerAMD64: Found a base 2 number here: "
- << jump_label.substr(pos) << "\n";
- }
-
- for (char& i : num.number)
- {
- if (i == 0)
- i = 0xFF;
-
- kAppBytes.push_back(i);
- }
-
- return true;
- }
- case 'o': {
- if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7);
- !res)
- {
- if (errno != 0)
- {
- Detail::print_error("invalid octal number: " + jump_label, "LibCompiler");
- throw std::runtime_error("invalid_octal");
- }
- }
-
- LibCompiler::NumberCast16 num = LibCompiler::NumberCast16(
- strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7));
-
- if (kVerbose)
- {
- kStdOut << "AssemblerAMD64: Found a base 8 number here: "
- << jump_label.substr(pos) << "\n";
- }
-
- for (char& i : num.number)
- {
- if (i == 0)
- i = 0xFF;
-
- kAppBytes.push_back(i);
- }
-
- return true;
- }
- default: {
- break;
- }
- }
-
- /* check for errno and stuff like that */
- if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res)
- {
- if (errno != 0)
- {
- return false;
- }
- }
-
- LibCompiler::NumberCast16 num = LibCompiler::NumberCast16(
- strtol(jump_label.substr(pos).c_str(), nullptr, 10));
-
- for (char& i : num.number)
- {
- if (i == 0)
- i = 0xFF;
-
- kAppBytes.push_back(i);
- }
-
- if (kVerbose)
- {
- kStdOut << "AssemblerAMD64: Found a base 10 number here: " << jump_label.substr(pos)
- << "\n";
- }
-
- return true;
+bool LibCompiler::EncoderAMD64::WriteNumber16(const std::size_t& pos, std::string& jump_label) {
+ if (!isdigit(jump_label[pos])) return false;
+
+ switch (jump_label[pos + 1]) {
+ case 'x': {
+ if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16); !res) {
+ if (errno != 0) {
+ Detail::print_error("invalid hex number: " + jump_label, "LibCompiler");
+ throw std::runtime_error("invalid_hex");
+ }
+ }
+
+ LibCompiler::NumberCast16 num =
+ LibCompiler::NumberCast16(strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16));
+
+ for (char& i : num.number) {
+ if (i == 0) i = 0xFF;
+
+ kAppBytes.push_back(i);
+ }
+
+ if (kVerbose) {
+ kStdOut << "AssemblerAMD64: Found a base 16 number here: " << jump_label.substr(pos)
+ << "\n";
+ }
+
+ return true;
+ }
+ case 'b': {
+ if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2); !res) {
+ if (errno != 0) {
+ Detail::print_error("invalid binary number: " + jump_label, "LibCompiler");
+ throw std::runtime_error("invalid_bin");
+ }
+ }
+
+ LibCompiler::NumberCast16 num =
+ LibCompiler::NumberCast16(strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2));
+
+ if (kVerbose) {
+ kStdOut << "AssemblerAMD64: Found a base 2 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ for (char& i : num.number) {
+ if (i == 0) i = 0xFF;
+
+ kAppBytes.push_back(i);
+ }
+
+ return true;
+ }
+ case 'o': {
+ if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7); !res) {
+ if (errno != 0) {
+ Detail::print_error("invalid octal number: " + jump_label, "LibCompiler");
+ throw std::runtime_error("invalid_octal");
+ }
+ }
+
+ LibCompiler::NumberCast16 num =
+ LibCompiler::NumberCast16(strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7));
+
+ if (kVerbose) {
+ kStdOut << "AssemblerAMD64: Found a base 8 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ for (char& i : num.number) {
+ if (i == 0) i = 0xFF;
+
+ kAppBytes.push_back(i);
+ }
+
+ return true;
+ }
+ default: {
+ break;
+ }
+ }
+
+ /* check for errno and stuff like that */
+ if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res) {
+ if (errno != 0) {
+ return false;
+ }
+ }
+
+ LibCompiler::NumberCast16 num =
+ LibCompiler::NumberCast16(strtol(jump_label.substr(pos).c_str(), nullptr, 10));
+
+ for (char& i : num.number) {
+ if (i == 0) i = 0xFF;
+
+ kAppBytes.push_back(i);
+ }
+
+ if (kVerbose) {
+ kStdOut << "AssemblerAMD64: Found a base 10 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ return true;
}
-bool LibCompiler::EncoderAMD64::WriteNumber8(const std::size_t& pos,
- std::string& jump_label)
-{
- if (!isdigit(jump_label[pos]))
- return false;
-
- switch (jump_label[pos + 1])
- {
- case 'x': {
- if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16);
- !res)
- {
- if (errno != 0)
- {
- Detail::print_error("invalid hex number: " + jump_label, "LibCompiler");
- throw std::runtime_error("invalid_hex");
- }
- }
-
- LibCompiler::NumberCast8 num = LibCompiler::NumberCast8(
- strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16));
-
- kAppBytes.push_back(num.number);
-
- if (kVerbose)
- {
- kStdOut << "AssemblerAMD64: Found a base 16 number here: "
- << jump_label.substr(pos) << "\n";
- }
-
- return true;
- }
- case 'b': {
- if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2);
- !res)
- {
- if (errno != 0)
- {
- Detail::print_error("invalid binary number: " + jump_label, "LibCompiler");
- throw std::runtime_error("invalid_bin");
- }
- }
-
- LibCompiler::NumberCast8 num = LibCompiler::NumberCast8(
- strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2));
-
- if (kVerbose)
- {
- kStdOut << "AssemblerAMD64: Found a base 2 number here: "
- << jump_label.substr(pos) << "\n";
- }
-
- kAppBytes.push_back(num.number);
-
- return true;
- }
- case 'o': {
- if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7);
- !res)
- {
- if (errno != 0)
- {
- Detail::print_error("invalid octal number: " + jump_label, "LibCompiler");
- throw std::runtime_error("invalid_octal");
- }
- }
-
- LibCompiler::NumberCast8 num = LibCompiler::NumberCast8(
- strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7));
-
- if (kVerbose)
- {
- kStdOut << "AssemblerAMD64: Found a base 8 number here: "
- << jump_label.substr(pos) << "\n";
- }
-
- kAppBytes.push_back(num.number);
-
- return true;
- }
- default: {
- break;
- }
- }
-
- /* check for errno and stuff like that */
- if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res)
- {
- if (errno != 0)
- {
- return false;
- }
- }
-
- LibCompiler::NumberCast8 num = LibCompiler::NumberCast8(
- strtol(jump_label.substr(pos).c_str(), nullptr, 10));
-
- kAppBytes.push_back(num.number);
-
- if (kVerbose)
- {
- kStdOut << "AssemblerAMD64: Found a base 10 number here: " << jump_label.substr(pos)
- << "\n";
- }
-
- return true;
+bool LibCompiler::EncoderAMD64::WriteNumber8(const std::size_t& pos, std::string& jump_label) {
+ if (!isdigit(jump_label[pos])) return false;
+
+ switch (jump_label[pos + 1]) {
+ case 'x': {
+ if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16); !res) {
+ if (errno != 0) {
+ Detail::print_error("invalid hex number: " + jump_label, "LibCompiler");
+ throw std::runtime_error("invalid_hex");
+ }
+ }
+
+ LibCompiler::NumberCast8 num =
+ LibCompiler::NumberCast8(strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16));
+
+ kAppBytes.push_back(num.number);
+
+ if (kVerbose) {
+ kStdOut << "AssemblerAMD64: Found a base 16 number here: " << jump_label.substr(pos)
+ << "\n";
+ }
+
+ return true;
+ }
+ case 'b': {
+ if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2); !res) {
+ if (errno != 0) {
+ Detail::print_error("invalid binary number: " + jump_label, "LibCompiler");
+ throw std::runtime_error("invalid_bin");
+ }
+ }
+
+ LibCompiler::NumberCast8 num =
+ LibCompiler::NumberCast8(strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2));
+
+ if (kVerbose) {
+ kStdOut << "AssemblerAMD64: Found a base 2 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ kAppBytes.push_back(num.number);
+
+ return true;
+ }
+ case 'o': {
+ if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7); !res) {
+ if (errno != 0) {
+ Detail::print_error("invalid octal number: " + jump_label, "LibCompiler");
+ throw std::runtime_error("invalid_octal");
+ }
+ }
+
+ LibCompiler::NumberCast8 num =
+ LibCompiler::NumberCast8(strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7));
+
+ if (kVerbose) {
+ kStdOut << "AssemblerAMD64: Found a base 8 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ kAppBytes.push_back(num.number);
+
+ return true;
+ }
+ default: {
+ break;
+ }
+ }
+
+ /* check for errno and stuff like that */
+ if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res) {
+ if (errno != 0) {
+ return false;
+ }
+ }
+
+ LibCompiler::NumberCast8 num =
+ LibCompiler::NumberCast8(strtol(jump_label.substr(pos).c_str(), nullptr, 10));
+
+ kAppBytes.push_back(num.number);
+
+ if (kVerbose) {
+ kStdOut << "AssemblerAMD64: Found a base 10 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ return true;
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -1151,331 +956,237 @@ bool LibCompiler::EncoderAMD64::WriteNumber8(const std::size_t& pos,
/////////////////////////////////////////////////////////////////////////////////////////
-bool LibCompiler::EncoderAMD64::WriteLine(std::string& line,
- const std::string& file)
-{
- if (LibCompiler::find_word(line, "public_segment "))
- return true;
-
- struct RegMapAMD64
- {
- std::string fName;
- i64_byte_t fModRM;
- };
-
- std::vector<RegMapAMD64> kRegisterList{
- {.fName = "ax", .fModRM = 0x0},
- {.fName = "cx", .fModRM = 1},
- {.fName = "dx", .fModRM = 0x2},
- {.fName = "bx", .fModRM = 3},
- {.fName = "sp", .fModRM = 0x4},
- {.fName = "bp", .fModRM = 5},
- {.fName = "si", .fModRM = 0x6},
- {.fName = "di", .fModRM = 7},
- {.fName = "r8", .fModRM = 8},
- {.fName = "r13", .fModRM = 9},
- {.fName = "r9", .fModRM = 10},
- {.fName = "r14", .fModRM = 11},
- {.fName = "r10", .fModRM = 12},
- {.fName = "r15", .fModRM = 13},
- {.fName = "r11", .fModRM = 14},
- };
-
- bool foundInstruction = false;
-
- for (auto& opcodeAMD64 : kOpcodesAMD64)
- {
- // strict check here
- if (LibCompiler::find_word(line, opcodeAMD64.fName) &&
- Detail::algorithm::is_valid_amd64(line))
- {
- foundInstruction = true;
- std::string name(opcodeAMD64.fName);
-
- /// Move instruction handler.
- if (line.find(name) != std::string::npos &&
- name == "mov")
- {
- std::string substr = line.substr(line.find(name) + name.size());
-
- uint64_t bits = kRegisterBitWidth;
-
- if (substr.find(",") == std::string::npos)
- {
- Detail::print_error("Syntax error: missing right operand.", "LibCompiler");
- throw std::runtime_error("syntax_err");
- }
-
- bool onlyOneReg = true;
-
- std::vector<RegMapAMD64> currentRegList;
-
- for (auto& reg : kRegisterList)
- {
- std::vector<char> regExt = {'e', 'r'};
-
- for (auto& ext : regExt)
- {
- std::string registerName;
-
- if (bits > 16)
- registerName.push_back(ext);
-
- registerName += reg.fName;
-
- while (line.find(registerName) != std::string::npos)
- {
- line.erase(line.find(registerName), registerName.size());
-
- if (bits == 16)
- {
- if (registerName[0] == 'r')
- {
- Detail::print_error(
- "invalid size for register, current bit width is: " +
- std::to_string(kRegisterBitWidth),
- file);
- throw std::runtime_error("invalid_reg_size");
- }
- }
-
- currentRegList.push_back(
- {.fName = registerName, .fModRM = reg.fModRM});
- }
- }
- }
-
- if (currentRegList.size() > 1)
- onlyOneReg = false;
-
- bool hasRBasedRegs = false;
-
- if (!onlyOneReg)
- {
- /// very tricky to understand.
- /// but this checks for a r8 through r15 register.
- if (currentRegList[0].fName[0] == 'r' ||
- currentRegList[1].fName[0] == 'r')
- {
- if (isdigit(currentRegList[0].fName[1]) &&
- isdigit(currentRegList[1].fName[1]))
- {
- kAppBytes.emplace_back(0x4d);
- hasRBasedRegs = true;
- }
- else if (isdigit(currentRegList[0].fName[1]) ||
- isdigit(currentRegList[1].fName[1]))
- {
- kAppBytes.emplace_back(0x4c);
- hasRBasedRegs = true;
- }
- }
- }
-
- if (bits == 64 || bits == 32)
- {
- if (!hasRBasedRegs && bits >= 32)
- {
- kAppBytes.emplace_back(opcodeAMD64.fOpcode);
- }
-
- if (!onlyOneReg)
- kAppBytes.emplace_back(0x89);
- }
- else if (bits == 16)
- {
- if (hasRBasedRegs)
- {
- Detail::print_error(
- "Invalid combination of operands and registers.", "LibCompiler");
- throw std::runtime_error("comb_op_reg");
- }
- else
- {
- kAppBytes.emplace_back(0x66);
- kAppBytes.emplace_back(0x89);
- }
- }
-
- if (onlyOneReg)
- {
- auto num = GetNumber32(line, ",");
-
- for (auto& num_idx : num.number)
- {
- if (num_idx == 0)
- num_idx = 0xFF;
- }
-
- auto modrm = (0x3 << 6 |
- currentRegList[0].fModRM);
-
- kAppBytes.emplace_back(0xC7); // prefixed before placing the modrm and then the number.
- kAppBytes.emplace_back(modrm);
- kAppBytes.emplace_back(num.number[0]);
- kAppBytes.emplace_back(num.number[1]);
- kAppBytes.emplace_back(num.number[2]);
- kAppBytes.emplace_back(num.number[3]);
-
- break;
- }
-
- if (currentRegList[1].fName[0] == 'r' &&
- currentRegList[0].fName[0] == 'e')
- {
- Detail::print_error("Invalid combination of operands and registers.",
- "LibCompiler");
- throw std::runtime_error("comb_op_reg");
- }
-
- if (currentRegList[0].fName[0] == 'r' &&
- currentRegList[1].fName[0] == 'e')
- {
- Detail::print_error("Invalid combination of operands and registers.",
- "LibCompiler");
- throw std::runtime_error("comb_op_reg");
- }
-
- if (bits == 16)
- {
- if (currentRegList[0].fName[0] == 'r' ||
- currentRegList[0].fName[0] == 'e')
- {
- Detail::print_error("Invalid combination of operands and registers.",
- "LibCompiler");
- throw std::runtime_error("comb_op_reg");
- }
-
- if (currentRegList[1].fName[0] == 'r' ||
- currentRegList[1].fName[0] == 'e')
- {
- Detail::print_error("Invalid combination of operands and registers.",
- "LibCompiler");
- throw std::runtime_error("comb_op_reg");
- }
- }
- else
- {
- if (currentRegList[0].fName[0] != 'r' ||
- currentRegList[0].fName[0] == 'e')
- {
- Detail::print_error("Invalid combination of operands and registers.",
- "LibCompiler");
- throw std::runtime_error("comb_op_reg");
- }
-
- if (currentRegList[1].fName[0] != 'r' ||
- currentRegList[1].fName[0] == 'e')
- {
- Detail::print_error("Invalid combination of operands and registers.",
- "LibCompiler");
- throw std::runtime_error("comb_op_reg");
- }
- }
-
- /// encode register using the modrm encoding.
-
- auto modrm = (0x3 << 6 | currentRegList[1].fModRM << 3 |
- currentRegList[0].fModRM);
-
- kAppBytes.emplace_back(modrm);
-
- break;
- }
- else if (name == "int" || name == "into" || name == "intd")
- {
- kAppBytes.emplace_back(opcodeAMD64.fOpcode);
- this->WriteNumber8(line.find(name) + name.size() + 1, line);
-
- break;
- }
- else if (name == "jmp" || name == "call")
- {
- kAppBytes.emplace_back(opcodeAMD64.fOpcode);
-
- if (!this->WriteNumber32(line.find(name) + name.size() + 1, line))
- {
- throw std::runtime_error("BUG: WriteNumber32");
- }
-
- break;
- }
- else
- {
- kAppBytes.emplace_back(opcodeAMD64.fOpcode);
-
- break;
- }
- }
- }
-
- if (line[0] == kAssemblerPragmaSym)
- {
- if (foundInstruction)
- {
- Detail::print_error("Syntax error: " + line, "LibCompiler");
- throw std::runtime_error("syntax_err");
- }
-
- if (line.find("bits 64") != std::string::npos)
- {
- kRegisterBitWidth = 64U;
- }
- else if (line.find("bits 32") != std::string::npos)
- {
- kRegisterBitWidth = 32U;
- }
- else if (line.find("bits 16") != std::string::npos)
- {
- kRegisterBitWidth = 16U;
- }
- else if (line.find("org") != std::string::npos)
- {
- size_t base[] = {10, 16, 2, 7};
-
- for (size_t i = 0; i < 4; i++)
- {
- if (kOrigin = strtol(
- (line.substr(line.find("org") + strlen("org") + 1)).c_str(),
- nullptr, base[i]);
- kOrigin)
- {
- if (errno != 0)
- {
- continue;
- }
- else
- {
- if (kVerbose)
- {
- kStdOut << "AssemblerAMD64: origin set: " << kOrigin << std::endl;
- }
-
- break;
- }
- }
- }
- }
- }
- /// write a dword
- else if (line.find(".dword") != std::string::npos)
- {
- this->WriteNumber32(line.find(".dword") + strlen(".dword") + 1, line);
- }
- /// write a long
- else if (line.find(".long") != std::string::npos)
- {
- this->WriteNumber(line.find(".long") + strlen(".long") + 1, line);
- }
- /// write a 16-bit number
- else if (line.find(".word") != std::string::npos)
- {
- this->WriteNumber16(line.find(".word") + strlen(".word") + 1, line);
- }
-
- kOrigin += kIPAlignement;
-
- return true;
+bool LibCompiler::EncoderAMD64::WriteLine(std::string& line, const std::string& file) {
+ if (LibCompiler::find_word(line, "public_segment ")) return true;
+
+ struct RegMapAMD64 {
+ std::string fName;
+ i64_byte_t fModRM;
+ };
+
+ std::vector<RegMapAMD64> kRegisterList{
+ {.fName = "ax", .fModRM = 0x0}, {.fName = "cx", .fModRM = 1},
+ {.fName = "dx", .fModRM = 0x2}, {.fName = "bx", .fModRM = 3},
+ {.fName = "sp", .fModRM = 0x4}, {.fName = "bp", .fModRM = 5},
+ {.fName = "si", .fModRM = 0x6}, {.fName = "di", .fModRM = 7},
+ {.fName = "r8", .fModRM = 8}, {.fName = "r13", .fModRM = 9},
+ {.fName = "r9", .fModRM = 10}, {.fName = "r14", .fModRM = 11},
+ {.fName = "r10", .fModRM = 12}, {.fName = "r15", .fModRM = 13},
+ {.fName = "r11", .fModRM = 14},
+ };
+
+ bool foundInstruction = false;
+
+ for (auto& opcodeAMD64 : kOpcodesAMD64) {
+ // strict check here
+ if (LibCompiler::find_word(line, opcodeAMD64.fName) &&
+ Detail::algorithm::is_valid_amd64(line)) {
+ foundInstruction = true;
+ std::string name(opcodeAMD64.fName);
+
+ /// Move instruction handler.
+ if (line.find(name) != std::string::npos && name == "mov") {
+ std::string substr = line.substr(line.find(name) + name.size());
+
+ uint64_t bits = kRegisterBitWidth;
+
+ if (substr.find(",") == std::string::npos) {
+ Detail::print_error("Syntax error: missing right operand.", "LibCompiler");
+ throw std::runtime_error("syntax_err");
+ }
+
+ bool onlyOneReg = true;
+
+ std::vector<RegMapAMD64> currentRegList;
+
+ for (auto& reg : kRegisterList) {
+ std::vector<char> regExt = {'e', 'r'};
+
+ for (auto& ext : regExt) {
+ std::string registerName;
+
+ if (bits > 16) registerName.push_back(ext);
+
+ registerName += reg.fName;
+
+ while (line.find(registerName) != std::string::npos) {
+ line.erase(line.find(registerName), registerName.size());
+
+ if (bits == 16) {
+ if (registerName[0] == 'r') {
+ Detail::print_error("invalid size for register, current bit width is: " +
+ std::to_string(kRegisterBitWidth),
+ file);
+ throw std::runtime_error("invalid_reg_size");
+ }
+ }
+
+ currentRegList.push_back({.fName = registerName, .fModRM = reg.fModRM});
+ }
+ }
+ }
+
+ if (currentRegList.size() > 1) onlyOneReg = false;
+
+ bool hasRBasedRegs = false;
+
+ if (!onlyOneReg) {
+ /// very tricky to understand.
+ /// but this checks for a r8 through r15 register.
+ if (currentRegList[0].fName[0] == 'r' || currentRegList[1].fName[0] == 'r') {
+ if (isdigit(currentRegList[0].fName[1]) && isdigit(currentRegList[1].fName[1])) {
+ kAppBytes.emplace_back(0x4d);
+ hasRBasedRegs = true;
+ } else if (isdigit(currentRegList[0].fName[1]) || isdigit(currentRegList[1].fName[1])) {
+ kAppBytes.emplace_back(0x4c);
+ hasRBasedRegs = true;
+ }
+ }
+ }
+
+ if (bits == 64 || bits == 32) {
+ if (!hasRBasedRegs && bits >= 32) {
+ kAppBytes.emplace_back(opcodeAMD64.fOpcode);
+ }
+
+ if (!onlyOneReg) kAppBytes.emplace_back(0x89);
+ } else if (bits == 16) {
+ if (hasRBasedRegs) {
+ Detail::print_error("Invalid combination of operands and registers.", "LibCompiler");
+ throw std::runtime_error("comb_op_reg");
+ } else {
+ kAppBytes.emplace_back(0x66);
+ kAppBytes.emplace_back(0x89);
+ }
+ }
+
+ if (onlyOneReg) {
+ auto num = GetNumber32(line, ",");
+
+ for (auto& num_idx : num.number) {
+ if (num_idx == 0) num_idx = 0xFF;
+ }
+
+ auto modrm = (0x3 << 6 | currentRegList[0].fModRM);
+
+ kAppBytes.emplace_back(0xC7); // prefixed before placing the modrm and then the number.
+ kAppBytes.emplace_back(modrm);
+ kAppBytes.emplace_back(num.number[0]);
+ kAppBytes.emplace_back(num.number[1]);
+ kAppBytes.emplace_back(num.number[2]);
+ kAppBytes.emplace_back(num.number[3]);
+
+ break;
+ }
+
+ if (currentRegList[1].fName[0] == 'r' && currentRegList[0].fName[0] == 'e') {
+ Detail::print_error("Invalid combination of operands and registers.", "LibCompiler");
+ throw std::runtime_error("comb_op_reg");
+ }
+
+ if (currentRegList[0].fName[0] == 'r' && currentRegList[1].fName[0] == 'e') {
+ Detail::print_error("Invalid combination of operands and registers.", "LibCompiler");
+ throw std::runtime_error("comb_op_reg");
+ }
+
+ if (bits == 16) {
+ if (currentRegList[0].fName[0] == 'r' || currentRegList[0].fName[0] == 'e') {
+ Detail::print_error("Invalid combination of operands and registers.", "LibCompiler");
+ throw std::runtime_error("comb_op_reg");
+ }
+
+ if (currentRegList[1].fName[0] == 'r' || currentRegList[1].fName[0] == 'e') {
+ Detail::print_error("Invalid combination of operands and registers.", "LibCompiler");
+ throw std::runtime_error("comb_op_reg");
+ }
+ } else {
+ if (currentRegList[0].fName[0] != 'r' || currentRegList[0].fName[0] == 'e') {
+ Detail::print_error("Invalid combination of operands and registers.", "LibCompiler");
+ throw std::runtime_error("comb_op_reg");
+ }
+
+ if (currentRegList[1].fName[0] != 'r' || currentRegList[1].fName[0] == 'e') {
+ Detail::print_error("Invalid combination of operands and registers.", "LibCompiler");
+ throw std::runtime_error("comb_op_reg");
+ }
+ }
+
+ /// encode register using the modrm encoding.
+
+ auto modrm = (0x3 << 6 | currentRegList[1].fModRM << 3 | currentRegList[0].fModRM);
+
+ kAppBytes.emplace_back(modrm);
+
+ break;
+ } else if (name == "int" || name == "into" || name == "intd") {
+ kAppBytes.emplace_back(opcodeAMD64.fOpcode);
+ this->WriteNumber8(line.find(name) + name.size() + 1, line);
+
+ break;
+ } else if (name == "jmp" || name == "call") {
+ kAppBytes.emplace_back(opcodeAMD64.fOpcode);
+
+ if (!this->WriteNumber32(line.find(name) + name.size() + 1, line)) {
+ throw std::runtime_error("BUG: WriteNumber32");
+ }
+
+ break;
+ } else {
+ kAppBytes.emplace_back(opcodeAMD64.fOpcode);
+
+ break;
+ }
+ }
+ }
+
+ if (line[0] == kAssemblerPragmaSym) {
+ if (foundInstruction) {
+ Detail::print_error("Syntax error: " + line, "LibCompiler");
+ throw std::runtime_error("syntax_err");
+ }
+
+ if (line.find("bits 64") != std::string::npos) {
+ kRegisterBitWidth = 64U;
+ } else if (line.find("bits 32") != std::string::npos) {
+ kRegisterBitWidth = 32U;
+ } else if (line.find("bits 16") != std::string::npos) {
+ kRegisterBitWidth = 16U;
+ } else if (line.find("org") != std::string::npos) {
+ size_t base[] = {10, 16, 2, 7};
+
+ for (size_t i = 0; i < 4; i++) {
+ if (kOrigin = strtol((line.substr(line.find("org") + strlen("org") + 1)).c_str(), nullptr,
+ base[i]);
+ kOrigin) {
+ if (errno != 0) {
+ continue;
+ } else {
+ if (kVerbose) {
+ kStdOut << "AssemblerAMD64: origin set: " << kOrigin << std::endl;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+ }
+ /// write a dword
+ else if (line.find(".dword") != std::string::npos) {
+ this->WriteNumber32(line.find(".dword") + strlen(".dword") + 1, line);
+ }
+ /// write a long
+ else if (line.find(".long") != std::string::npos) {
+ this->WriteNumber(line.find(".long") + strlen(".long") + 1, line);
+ }
+ /// write a 16-bit number
+ else if (line.find(".word") != std::string::npos) {
+ this->WriteNumber16(line.find(".word") + strlen(".word") + 1, line);
+ }
+
+ kOrigin += kIPAlignement;
+
+ return true;
}
// Last rev 13-1-24
diff --git a/dev/LibCompiler/src/AssemblerARM64.cc b/dev/LibCompiler/src/AssemblerARM64.cc
index 52b78d6..d984845 100644
--- a/dev/LibCompiler/src/AssemblerARM64.cc
+++ b/dev/LibCompiler/src/AssemblerARM64.cc
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
+ Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
------------------------------------------- */
@@ -17,16 +17,16 @@
#define __ASM_NEED_ARM64__ 1
-#include <LibCompiler/ErrorID.h>
+#include <LibCompiler/AE.h>
#include <LibCompiler/Backend/arm64.h>
+#include <LibCompiler/ErrorID.h>
#include <LibCompiler/PEF.h>
#include <LibCompiler/Parser.h>
-#include <LibCompiler/AE.h>
#include <LibCompiler/Version.h>
-#include <filesystem>
#include <algorithm>
-#include <iostream>
+#include <filesystem>
#include <fstream>
+#include <iostream>
#include <vector>
/////////////////////
@@ -35,9 +35,9 @@
/////////////////////
-#define kBlank "\e[0;30m"
-#define kRed "\e[0;31m"
-#define kWhite "\e[0;97m"
+#define kBlank "\e[0;30m"
+#define kRed "\e[0;31m"
+#define kWhite "\e[0;97m"
#define kYellow "\e[0;33m"
#define kStdOut (std::cout << kWhite)
@@ -45,15 +45,15 @@
constexpr auto cPowerIPAlignment = 0x4U;
-static CharType kOutputArch = LibCompiler::kPefArchARM64;
-static Boolean kOutputAsBinary = false;
+static CharType kOutputArch = LibCompiler::kPefArchARM64;
+static Boolean kOutputAsBinary = false;
-static UInt32 kErrorLimit = 10;
+static UInt32 kErrorLimit = 10;
static UInt32 kAcceptableErrors = 0;
static std::size_t kCounter = 1UL;
-static std::uintptr_t kOrigin = kPefBaseOrigin;
+static std::uintptr_t kOrigin = kPefBaseOrigin;
static std::vector<std::pair<std::string, std::uintptr_t>> kOriginLabel;
static bool kVerbose = false;
@@ -61,13 +61,13 @@ static bool kVerbose = false;
static std::vector<uint8_t> kBytes;
static LibCompiler::AERecordHeader kCurrentRecord{
- .fName = "", .fKind = LibCompiler::kPefCode, .fSize = 0, .fOffset = 0};
+ .fName = "", .fKind = LibCompiler::kPefCode, .fSize = 0, .fOffset = 0};
static std::vector<LibCompiler::AERecordHeader> kRecords;
-static std::vector<std::string> kUndefinedSymbols;
+static std::vector<std::string> kUndefinedSymbols;
static const std::string kUndefinedSymbol = ":UndefinedSymbol:";
-static const std::string kRelocSymbol = ":RuntimeSymbol:";
+static const std::string kRelocSymbol = ":RuntimeSymbol:";
// \brief forward decl.
static bool asm_read_attributes(std::string& line);
@@ -81,225 +81,191 @@ static bool asm_read_attributes(std::string& line);
/////////////////////////////////////////////////////////////////////////////////////////
-LIBCOMPILER_MODULE(AssemblerMainARM64)
-{
- for (size_t i = 1; i < argc; ++i)
- {
- if (argv[i][0] == '-')
- {
- if (strcmp(argv[i], "--ver") == 0 || strcmp(argv[i], "--v") == 0)
- {
- kStdOut << "AssemblerPower: AARCH64 Assembler Driver.\nAssemblerPower: " << kDistVersion << "\nAssemblerPower: "
- "Copyright (c) "
- "Amlal El Mahrouss\n";
- return 0;
- }
- else if (strcmp(argv[i], "--h") == 0)
- {
- kStdOut << "AssemblerPower: AARCH64 Assembler Driver.\nAssemblerPower: Copyright (c) 2024 "
- "Amlal El Mahrouss\n";
- kStdOut << "--version,/v: print program version.\n";
- kStdOut << "--verbose: print verbose output.\n";
- kStdOut << "--binary: output as flat binary.\n";
-
- return 0;
- }
- else if (strcmp(argv[i], "--binary") == 0)
- {
- kOutputAsBinary = true;
- continue;
- }
- else if (strcmp(argv[i], "--verbose") == 0)
- {
- kVerbose = true;
- continue;
- }
-
- kStdOut << "AssemblerPower: ignore " << argv[i] << "\n";
- continue;
- }
-
- if (!std::filesystem::exists(argv[i]))
- {
- kStdOut << "AssemblerPower: can't open: " << argv[i] << std::endl;
- goto asm_fail_exit;
- }
-
- std::string object_output(argv[i]);
-
- for (auto& ext : kAsmFileExts)
- {
- if (object_output.find(ext) != std::string::npos)
- {
- object_output.erase(object_output.find(ext), std::strlen(ext));
- }
- }
-
- object_output += kOutputAsBinary ? kBinaryFileExt : kObjectFileExt;
-
- std::ifstream file_ptr(argv[i]);
- std::ofstream file_ptr_out(object_output, std::ofstream::binary);
-
- if (file_ptr_out.bad())
- {
- if (kVerbose)
- {
- kStdOut << "AssemblerPower: error: " << strerror(errno) << "\n";
- }
- }
-
- std::string line;
-
- LibCompiler::AEHeader hdr{0};
-
- memset(hdr.fPad, kAENullType, kAEPad);
-
- hdr.fMagic[0] = kAEMag0;
- hdr.fMagic[1] = kAEMag1;
- hdr.fSize = sizeof(LibCompiler::AEHeader);
- hdr.fArch = kOutputArch;
-
- /////////////////////////////////////////////////////////////////////////////////////////
-
- // COMPILATION LOOP
-
- /////////////////////////////////////////////////////////////////////////////////////////
-
- LibCompiler::EncoderARM64 asm64;
-
- while (std::getline(file_ptr, line))
- {
- if (auto ln = asm64.CheckLine(line, argv[i]); !ln.empty())
- {
- Detail::print_error(ln, argv[i]);
- continue;
- }
-
- try
- {
- asm_read_attributes(line);
- asm64.WriteLine(line, argv[i]);
- }
- catch (const std::exception& e)
- {
- if (kVerbose)
- {
- std::string what = e.what();
- Detail::print_warning("exit because of: " + what, "LibCompiler");
- }
-
- std::filesystem::remove(object_output);
- goto asm_fail_exit;
- }
- }
-
- if (!kOutputAsBinary)
- {
- if (kVerbose)
- {
- kStdOut << "AssemblerARM64: Writing object file...\n";
- }
+LIBCOMPILER_MODULE(AssemblerMainARM64) {
+ for (size_t i = 1; i < argc; ++i) {
+ if (argv[i][0] == '-') {
+ if (strcmp(argv[i], "--ver") == 0 || strcmp(argv[i], "--v") == 0) {
+ kStdOut << "AssemblerPower: AARCH64 Assembler Driver.\nAssemblerPower: " << kDistVersion
+ << "\nAssemblerPower: "
+ "Copyright (c) "
+ "Amlal El Mahrouss\n";
+ return 0;
+ } else if (strcmp(argv[i], "--h") == 0) {
+ kStdOut << "AssemblerPower: AARCH64 Assembler Driver.\nAssemblerPower: Copyright (c) 2024 "
+ "Amlal El Mahrouss\n";
+ kStdOut << "--version,/v: print program version.\n";
+ kStdOut << "--verbose: print verbose output.\n";
+ kStdOut << "--binary: output as flat binary.\n";
+
+ return 0;
+ } else if (strcmp(argv[i], "--binary") == 0) {
+ kOutputAsBinary = true;
+ continue;
+ } else if (strcmp(argv[i], "--verbose") == 0) {
+ kVerbose = true;
+ continue;
+ }
+
+ kStdOut << "AssemblerPower: ignore " << argv[i] << "\n";
+ continue;
+ }
+
+ if (!std::filesystem::exists(argv[i])) {
+ kStdOut << "AssemblerPower: can't open: " << argv[i] << std::endl;
+ goto asm_fail_exit;
+ }
+
+ std::string object_output(argv[i]);
+
+ for (auto& ext : kAsmFileExts) {
+ if (object_output.find(ext) != std::string::npos) {
+ object_output.erase(object_output.find(ext), std::strlen(ext));
+ }
+ }
+
+ object_output += kOutputAsBinary ? kBinaryFileExt : kObjectFileExt;
+
+ std::ifstream file_ptr(argv[i]);
+ std::ofstream file_ptr_out(object_output, std::ofstream::binary);
+
+ if (file_ptr_out.bad()) {
+ if (kVerbose) {
+ kStdOut << "AssemblerPower: error: " << strerror(errno) << "\n";
+ }
+ }
+
+ std::string line;
+
+ LibCompiler::AEHeader hdr{0};
+
+ memset(hdr.fPad, kAENullType, kAEPad);
+
+ hdr.fMagic[0] = kAEMag0;
+ hdr.fMagic[1] = kAEMag1;
+ hdr.fSize = sizeof(LibCompiler::AEHeader);
+ hdr.fArch = kOutputArch;
+
+ /////////////////////////////////////////////////////////////////////////////////////////
+
+ // COMPILATION LOOP
+
+ /////////////////////////////////////////////////////////////////////////////////////////
+
+ LibCompiler::EncoderARM64 asm64;
+
+ while (std::getline(file_ptr, line)) {
+ if (auto ln = asm64.CheckLine(line, argv[i]); !ln.empty()) {
+ Detail::print_error(ln, argv[i]);
+ continue;
+ }
+
+ try {
+ asm_read_attributes(line);
+ asm64.WriteLine(line, argv[i]);
+ } catch (const std::exception& e) {
+ if (kVerbose) {
+ std::string what = e.what();
+ Detail::print_warning("exit because of: " + what, "LibCompiler");
+ }
+
+ std::filesystem::remove(object_output);
+ goto asm_fail_exit;
+ }
+ }
- // this is the final step, write everything to the file.
+ if (!kOutputAsBinary) {
+ if (kVerbose) {
+ kStdOut << "AssemblerARM64: Writing object file...\n";
+ }
- auto pos = file_ptr_out.tellp();
+ // this is the final step, write everything to the file.
- hdr.fCount = kRecords.size() + kUndefinedSymbols.size();
+ auto pos = file_ptr_out.tellp();
- file_ptr_out << hdr;
+ hdr.fCount = kRecords.size() + kUndefinedSymbols.size();
- if (kRecords.empty())
- {
- kStdErr << "AssemblerARM64: At least one record is needed to write an object "
- "file.\nAssemblerARM64: Make one using `public_segment .code64 foo_bar`.\n";
+ file_ptr_out << hdr;
- std::filesystem::remove(object_output);
- return 1;
- }
+ if (kRecords.empty()) {
+ kStdErr << "AssemblerARM64: At least one record is needed to write an object "
+ "file.\nAssemblerARM64: Make one using `public_segment .code64 foo_bar`.\n";
- kRecords[kRecords.size() - 1].fSize = kBytes.size();
+ std::filesystem::remove(object_output);
+ return 1;
+ }
- std::size_t record_count = 0UL;
+ kRecords[kRecords.size() - 1].fSize = kBytes.size();
- for (auto& record_hdr : kRecords)
- {
- record_hdr.fFlags |= LibCompiler::kKindRelocationAtRuntime;
- record_hdr.fOffset = record_count;
- ++record_count;
+ std::size_t record_count = 0UL;
- file_ptr_out << record_hdr;
+ for (auto& record_hdr : kRecords) {
+ record_hdr.fFlags |= LibCompiler::kKindRelocationAtRuntime;
+ record_hdr.fOffset = record_count;
+ ++record_count;
- if (kVerbose)
- kStdOut << "AssemblerARM64: Wrote record " << record_hdr.fName << "...\n";
- }
+ file_ptr_out << record_hdr;
- // increment once again, so that we won't lie about the kUndefinedSymbols.
- ++record_count;
+ if (kVerbose) kStdOut << "AssemblerARM64: Wrote record " << record_hdr.fName << "...\n";
+ }
- for (auto& sym : kUndefinedSymbols)
- {
- LibCompiler::AERecordHeader undefined_sym{0};
+ // increment once again, so that we won't lie about the kUndefinedSymbols.
+ ++record_count;
- if (kVerbose)
- kStdOut << "AssemblerARM64: Wrote symbol " << sym << " to file...\n";
+ for (auto& sym : kUndefinedSymbols) {
+ LibCompiler::AERecordHeader undefined_sym{0};
- undefined_sym.fKind = kAENullType;
- undefined_sym.fSize = sym.size();
- undefined_sym.fOffset = record_count;
+ if (kVerbose) kStdOut << "AssemblerARM64: Wrote symbol " << sym << " to file...\n";
- ++record_count;
+ undefined_sym.fKind = kAENullType;
+ undefined_sym.fSize = sym.size();
+ undefined_sym.fOffset = record_count;
- memset(undefined_sym.fPad, kAENullType, kAEPad);
- memcpy(undefined_sym.fName, sym.c_str(), sym.size());
+ ++record_count;
- file_ptr_out << undefined_sym;
+ memset(undefined_sym.fPad, kAENullType, kAEPad);
+ memcpy(undefined_sym.fName, sym.c_str(), sym.size());
- ++kCounter;
- }
+ file_ptr_out << undefined_sym;
- auto pos_end = file_ptr_out.tellp();
+ ++kCounter;
+ }
- file_ptr_out.seekp(pos);
+ auto pos_end = file_ptr_out.tellp();
- hdr.fStartCode = pos_end;
- hdr.fCodeSize = kBytes.size();
+ file_ptr_out.seekp(pos);
- file_ptr_out << hdr;
+ hdr.fStartCode = pos_end;
+ hdr.fCodeSize = kBytes.size();
- file_ptr_out.seekp(pos_end);
- }
- else
- {
- if (kVerbose)
- {
- kStdOut << "AssemblerARM64: Write raw binary...\n";
- }
- }
+ file_ptr_out << hdr;
- // byte from byte, we write this.
- for (auto& byte : kBytes)
- {
- file_ptr_out.write(reinterpret_cast<const char*>(&byte), sizeof(byte));
- }
+ file_ptr_out.seekp(pos_end);
+ } else {
+ if (kVerbose) {
+ kStdOut << "AssemblerARM64: Write raw binary...\n";
+ }
+ }
- if (kVerbose)
- kStdOut << "AssemblerARM64: Wrote file with program in it.\n";
+ // byte from byte, we write this.
+ for (auto& byte : kBytes) {
+ file_ptr_out.write(reinterpret_cast<const char*>(&byte), sizeof(byte));
+ }
- file_ptr_out.flush();
- file_ptr_out.close();
+ if (kVerbose) kStdOut << "AssemblerARM64: Wrote file with program in it.\n";
- if (kVerbose)
- kStdOut << "AssemblerARM64: Exit succeeded.\n";
+ file_ptr_out.flush();
+ file_ptr_out.close();
- return 0;
- }
+ if (kVerbose) kStdOut << "AssemblerARM64: Exit succeeded.\n";
+
+ return 0;
+ }
asm_fail_exit:
- if (kVerbose)
- kStdOut << "AssemblerARM64: Exit failed.\n";
+ if (kVerbose) kStdOut << "AssemblerARM64: Exit failed.\n";
- return LIBCOMPILER_EXEC_ERROR;
+ return LIBCOMPILER_EXEC_ERROR;
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -309,175 +275,144 @@ asm_fail_exit:
/////////////////////////////////////////////////////////////////////////////////////////
-static bool asm_read_attributes(std::string& line)
-{
- // extern_segment is the opposite of public_segment, it signals to the li
- // that we need this symbol.
- if (LibCompiler::find_word(line, "extern_segment"))
- {
- if (kOutputAsBinary)
- {
- Detail::print_error("Invalid extern_segment directive in flat binary mode.",
- "LibCompiler");
- throw std::runtime_error("invalid_extern_segment_bin");
- }
-
- auto name = line.substr(line.find("extern_segment") + strlen("extern_segment") + 1);
-
- if (name.size() == 0)
- {
- Detail::print_error("Invalid extern_segment", "LibCompiler");
- throw std::runtime_error("invalid_extern_segment");
- }
-
- std::string result = std::to_string(name.size());
- result += kUndefinedSymbol;
-
- // mangle this
- for (char& j : name)
- {
- if (j == ' ' || j == ',')
- j = '$';
- }
-
- result += name;
-
- if (name.find(".code64") != std::string::npos)
- {
- // data is treated as code.
- kCurrentRecord.fKind = LibCompiler::kPefCode;
- }
- else if (name.find(".data64") != std::string::npos)
- {
- // no code will be executed from here.
- kCurrentRecord.fKind = LibCompiler::kPefData;
- }
- else if (name.find(".zero64") != std::string::npos)
- {
- // this is a bss section.
- kCurrentRecord.fKind = LibCompiler::kPefZero;
- }
-
- // this is a special case for the start stub.
- // we want this so that li can find it.
-
- if (name == kPefStart)
- {
- kCurrentRecord.fKind = LibCompiler::kPefCode;
- }
-
- // now we can tell the code size of the previous kCurrentRecord.
-
- if (!kRecords.empty())
- kRecords[kRecords.size() - 1].fSize = kBytes.size();
-
- memset(kCurrentRecord.fName, 0, kAESymbolLen);
- memcpy(kCurrentRecord.fName, result.c_str(), result.size());
-
- ++kCounter;
-
- memset(kCurrentRecord.fPad, kAENullType, kAEPad);
-
- kRecords.emplace_back(kCurrentRecord);
-
- return true;
- }
- // public_segment is a special keyword used by Assembler to tell the AE output stage to
- // mark this section as a header. it currently supports .code64, .data64.,
- // .zero64
- else if (LibCompiler::find_word(line, "public_segment"))
- {
- if (kOutputAsBinary)
- {
- Detail::print_error("Invalid public_segment directive in flat binary mode.",
- "LibCompiler");
- throw std::runtime_error("invalid_public_segment_bin");
- }
-
- auto name = line.substr(line.find("public_segment") + strlen("public_segment"));
-
- std::string name_copy = name;
-
- for (char& j : name)
- {
- if (j == ' ')
- j = '$';
- }
-
- if (name.find(".code64") != std::string::npos)
- {
- // data is treated as code.
-
- name_copy.erase(name_copy.find(".code64"), strlen(".code64"));
- kCurrentRecord.fKind = LibCompiler::kPefCode;
- }
- else if (name.find(".data64") != std::string::npos)
- {
- // no code will be executed from here.
-
- name_copy.erase(name_copy.find(".data64"), strlen(".data64"));
- kCurrentRecord.fKind = LibCompiler::kPefData;
- }
- else if (name.find(".zero64") != std::string::npos)
- {
- // this is a bss section.
+static bool asm_read_attributes(std::string& line) {
+ // extern_segment is the opposite of public_segment, it signals to the li
+ // that we need this symbol.
+ if (LibCompiler::find_word(line, "extern_segment")) {
+ if (kOutputAsBinary) {
+ Detail::print_error("Invalid extern_segment directive in flat binary mode.", "LibCompiler");
+ throw std::runtime_error("invalid_extern_segment_bin");
+ }
+
+ auto name = line.substr(line.find("extern_segment") + strlen("extern_segment") + 1);
+
+ if (name.size() == 0) {
+ Detail::print_error("Invalid extern_segment", "LibCompiler");
+ throw std::runtime_error("invalid_extern_segment");
+ }
+
+ std::string result = std::to_string(name.size());
+ result += kUndefinedSymbol;
+
+ // mangle this
+ for (char& j : name) {
+ if (j == ' ' || j == ',') j = '$';
+ }
+
+ result += name;
+
+ if (name.find(".code64") != std::string::npos) {
+ // data is treated as code.
+ kCurrentRecord.fKind = LibCompiler::kPefCode;
+ } else if (name.find(".data64") != std::string::npos) {
+ // no code will be executed from here.
+ kCurrentRecord.fKind = LibCompiler::kPefData;
+ } else if (name.find(".zero64") != std::string::npos) {
+ // this is a bss section.
+ kCurrentRecord.fKind = LibCompiler::kPefZero;
+ }
+
+ // this is a special case for the start stub.
+ // we want this so that li can find it.
+
+ if (name == kPefStart) {
+ kCurrentRecord.fKind = LibCompiler::kPefCode;
+ }
+
+ // now we can tell the code size of the previous kCurrentRecord.
+
+ if (!kRecords.empty()) kRecords[kRecords.size() - 1].fSize = kBytes.size();
+
+ memset(kCurrentRecord.fName, 0, kAESymbolLen);
+ memcpy(kCurrentRecord.fName, result.c_str(), result.size());
+
+ ++kCounter;
+
+ memset(kCurrentRecord.fPad, kAENullType, kAEPad);
- name_copy.erase(name_copy.find(".zero64"), strlen(".zero64"));
- kCurrentRecord.fKind = LibCompiler::kPefZero;
- }
-
- // this is a special case for the start stub.
- // we want this so that li can find it.
+ kRecords.emplace_back(kCurrentRecord);
- if (name == kPefStart)
- {
- kCurrentRecord.fKind = LibCompiler::kPefCode;
- }
-
- while (name_copy.find(" ") != std::string::npos)
- name_copy.erase(name_copy.find(" "), 1);
+ return true;
+ }
+ // public_segment is a special keyword used by Assembler to tell the AE output stage to
+ // mark this section as a header. it currently supports .code64, .data64.,
+ // .zero64
+ else if (LibCompiler::find_word(line, "public_segment")) {
+ if (kOutputAsBinary) {
+ Detail::print_error("Invalid public_segment directive in flat binary mode.", "LibCompiler");
+ throw std::runtime_error("invalid_public_segment_bin");
+ }
- kOriginLabel.push_back(std::make_pair(name_copy, kOrigin));
- ++kOrigin;
+ auto name = line.substr(line.find("public_segment") + strlen("public_segment"));
- // now we can tell the code size of the previous kCurrentRecord.
+ std::string name_copy = name;
- if (!kRecords.empty())
- kRecords[kRecords.size() - 1].fSize = kBytes.size();
+ for (char& j : name) {
+ if (j == ' ') j = '$';
+ }
- memset(kCurrentRecord.fName, 0, kAESymbolLen);
- memcpy(kCurrentRecord.fName, name.c_str(), name.size());
+ if (name.find(".code64") != std::string::npos) {
+ // data is treated as code.
- ++kCounter;
+ name_copy.erase(name_copy.find(".code64"), strlen(".code64"));
+ kCurrentRecord.fKind = LibCompiler::kPefCode;
+ } else if (name.find(".data64") != std::string::npos) {
+ // no code will be executed from here.
- memset(kCurrentRecord.fPad, kAENullType, kAEPad);
+ name_copy.erase(name_copy.find(".data64"), strlen(".data64"));
+ kCurrentRecord.fKind = LibCompiler::kPefData;
+ } else if (name.find(".zero64") != std::string::npos) {
+ // this is a bss section.
- kRecords.emplace_back(kCurrentRecord);
+ name_copy.erase(name_copy.find(".zero64"), strlen(".zero64"));
+ kCurrentRecord.fKind = LibCompiler::kPefZero;
+ }
- return true;
- }
+ // this is a special case for the start stub.
+ // we want this so that li can find it.
- return false;
+ if (name == kPefStart) {
+ kCurrentRecord.fKind = LibCompiler::kPefCode;
+ }
+
+ while (name_copy.find(" ") != std::string::npos) name_copy.erase(name_copy.find(" "), 1);
+
+ kOriginLabel.push_back(std::make_pair(name_copy, kOrigin));
+ ++kOrigin;
+
+ // now we can tell the code size of the previous kCurrentRecord.
+
+ if (!kRecords.empty()) kRecords[kRecords.size() - 1].fSize = kBytes.size();
+
+ memset(kCurrentRecord.fName, 0, kAESymbolLen);
+ memcpy(kCurrentRecord.fName, name.c_str(), name.size());
+
+ ++kCounter;
+
+ memset(kCurrentRecord.fPad, kAENullType, kAEPad);
+
+ kRecords.emplace_back(kCurrentRecord);
+
+ return true;
+ }
+
+ return false;
}
// \brief algorithms and helpers.
-namespace Detail::algorithm
-{
- // \brief authorize a brief set of characters.
- static inline bool is_not_alnum_space(char c)
- {
- return !(isalpha(c) || isdigit(c) || (c == ' ') || (c == '\t') ||
- (c == ',') || (c == '(') || (c == ')') || (c == '"') ||
- (c == '\'') || (c == '[') || (c == ']') || (c == '+') ||
- (c == '_') || (c == ':') || (c == '@') || (c == '.'));
- }
-
- bool is_valid_arm64(const std::string& str)
- {
- return std::find_if(str.begin(), str.end(), is_not_alnum_space) == str.end();
- }
-} // namespace Detail::algorithm
+namespace Detail::algorithm {
+// \brief authorize a brief set of characters.
+static inline bool is_not_alnum_space(char c) {
+ return !(isalpha(c) || isdigit(c) || (c == ' ') || (c == '\t') || (c == ',') || (c == '(') ||
+ (c == ')') || (c == '"') || (c == '\'') || (c == '[') || (c == ']') || (c == '+') ||
+ (c == '_') || (c == ':') || (c == '@') || (c == '.'));
+}
+
+bool is_valid_arm64(const std::string& str) {
+ return std::find_if(str.begin(), str.end(), is_not_alnum_space) == str.end();
+}
+} // namespace Detail::algorithm
/////////////////////////////////////////////////////////////////////////////////////////
@@ -485,209 +420,161 @@ namespace Detail::algorithm
/////////////////////////////////////////////////////////////////////////////////////////
-std::string LibCompiler::EncoderARM64::CheckLine(std::string& line,
- const std::string& file)
-{
- std::string err_str;
-
- if (line.empty() || LibCompiler::find_word(line, "extern_segment") ||
- LibCompiler::find_word(line, "public_segment") ||
- line.find('#') != std::string::npos || LibCompiler::find_word(line, ";"))
- {
- if (line.find('#') != std::string::npos)
- {
- line.erase(line.find('#'));
- }
- else if (line.find(';') != std::string::npos)
- {
- line.erase(line.find(';'));
- }
- else
- {
- /// does the line contains valid input?
- if (!Detail::algorithm::is_valid_arm64(line))
- {
- err_str = "Line contains non alphanumeric characters.\nhere -> ";
- err_str += line;
- }
- }
-
- return err_str;
- }
-
- if (!Detail::algorithm::is_valid_arm64(line))
- {
- err_str = "Line contains non alphanumeric characters.\nhere -> ";
- err_str += line;
-
- return err_str;
- }
-
- // check for a valid instruction format.
-
- if (line.find(',') != std::string::npos)
- {
- if (line.find(',') + 1 == line.size())
- {
- err_str += "\nInstruction lacks right register, here -> ";
- err_str += line.substr(line.find(','));
-
- return err_str;
- }
- else
- {
- bool nothing_on_right = true;
-
- if (line.find(',') + 1 > line.size())
- {
- err_str += "\nInstruction not complete, here -> ";
- err_str += line;
-
- return err_str;
- }
-
- auto substr = line.substr(line.find(',') + 1);
-
- for (auto& ch : substr)
- {
- if (ch != ' ' && ch != '\t')
- {
- nothing_on_right = false;
- }
- }
-
- // this means we found nothing after that ',' .
- if (nothing_on_right)
- {
- err_str += "\nInstruction not complete, here -> ";
- err_str += line;
-
- return err_str;
- }
- }
- }
-
- return err_str;
+std::string LibCompiler::EncoderARM64::CheckLine(std::string& line, const std::string& file) {
+ std::string err_str;
+
+ if (line.empty() || LibCompiler::find_word(line, "extern_segment") ||
+ LibCompiler::find_word(line, "public_segment") || line.find('#') != std::string::npos ||
+ LibCompiler::find_word(line, ";")) {
+ if (line.find('#') != std::string::npos) {
+ line.erase(line.find('#'));
+ } else if (line.find(';') != std::string::npos) {
+ line.erase(line.find(';'));
+ } else {
+ /// does the line contains valid input?
+ if (!Detail::algorithm::is_valid_arm64(line)) {
+ err_str = "Line contains non alphanumeric characters.\nhere -> ";
+ err_str += line;
+ }
+ }
+
+ return err_str;
+ }
+
+ if (!Detail::algorithm::is_valid_arm64(line)) {
+ err_str = "Line contains non alphanumeric characters.\nhere -> ";
+ err_str += line;
+
+ return err_str;
+ }
+
+ // check for a valid instruction format.
+
+ if (line.find(',') != std::string::npos) {
+ if (line.find(',') + 1 == line.size()) {
+ err_str += "\nInstruction lacks right register, here -> ";
+ err_str += line.substr(line.find(','));
+
+ return err_str;
+ } else {
+ bool nothing_on_right = true;
+
+ if (line.find(',') + 1 > line.size()) {
+ err_str += "\nInstruction not complete, here -> ";
+ err_str += line;
+
+ return err_str;
+ }
+
+ auto substr = line.substr(line.find(',') + 1);
+
+ for (auto& ch : substr) {
+ if (ch != ' ' && ch != '\t') {
+ nothing_on_right = false;
+ }
+ }
+
+ // this means we found nothing after that ',' .
+ if (nothing_on_right) {
+ err_str += "\nInstruction not complete, here -> ";
+ err_str += line;
+
+ return err_str;
+ }
+ }
+ }
+
+ return err_str;
}
-bool LibCompiler::EncoderARM64::WriteNumber(const std::size_t& pos,
- std::string& jump_label)
-{
- if (!isdigit(jump_label[pos]))
- return false;
-
- switch (jump_label[pos + 1])
- {
- case 'x': {
- if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16);
- !res)
- {
- if (errno != 0)
- {
- Detail::print_error("invalid hex number: " + jump_label, "LibCompiler");
- throw std::runtime_error("invalid_hex");
- }
- }
-
- LibCompiler::NumberCast64 num(
- strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16));
-
- for (char& i : num.number)
- {
- kBytes.push_back(i);
- }
-
- if (kVerbose)
- {
- kStdOut << "AssemblerARM64: found a base 16 number here: "
- << jump_label.substr(pos) << "\n";
- }
-
- return true;
- }
- case 'b': {
- if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2);
- !res)
- {
- if (errno != 0)
- {
- Detail::print_error("invalid binary number: " + jump_label, "LibCompiler");
- throw std::runtime_error("invalid_bin");
- }
- }
-
- LibCompiler::NumberCast64 num(
- strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2));
-
- if (kVerbose)
- {
- kStdOut << "AssemblerARM64: found a base 2 number here: "
- << jump_label.substr(pos) << "\n";
- }
-
- for (char& i : num.number)
- {
- kBytes.push_back(i);
- }
-
- return true;
- }
- case 'o': {
- if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7);
- !res)
- {
- if (errno != 0)
- {
- Detail::print_error("invalid octal number: " + jump_label, "LibCompiler");
- throw std::runtime_error("invalid_octal");
- }
- }
-
- LibCompiler::NumberCast64 num(
- strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7));
-
- if (kVerbose)
- {
- kStdOut << "AssemblerARM64: found a base 8 number here: "
- << jump_label.substr(pos) << "\n";
- }
-
- for (char& i : num.number)
- {
- kBytes.push_back(i);
- }
-
- return true;
- }
- default: {
- break;
- }
- }
-
- /* check for errno and stuff like that */
- if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res)
- {
- if (errno != 0)
- {
- return false;
- }
- }
-
- LibCompiler::NumberCast64 num(
- strtol(jump_label.substr(pos).c_str(), nullptr, 10));
-
- for (char& i : num.number)
- {
- kBytes.push_back(i);
- }
-
- if (kVerbose)
- {
- kStdOut << "AssemblerARM64: found a base 10 number here: " << jump_label.substr(pos)
- << "\n";
- }
-
- return true;
+bool LibCompiler::EncoderARM64::WriteNumber(const std::size_t& pos, std::string& jump_label) {
+ if (!isdigit(jump_label[pos])) return false;
+
+ switch (jump_label[pos + 1]) {
+ case 'x': {
+ if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16); !res) {
+ if (errno != 0) {
+ Detail::print_error("invalid hex number: " + jump_label, "LibCompiler");
+ throw std::runtime_error("invalid_hex");
+ }
+ }
+
+ LibCompiler::NumberCast64 num(strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16));
+
+ for (char& i : num.number) {
+ kBytes.push_back(i);
+ }
+
+ if (kVerbose) {
+ kStdOut << "AssemblerARM64: found a base 16 number here: " << jump_label.substr(pos)
+ << "\n";
+ }
+
+ return true;
+ }
+ case 'b': {
+ if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2); !res) {
+ if (errno != 0) {
+ Detail::print_error("invalid binary number: " + jump_label, "LibCompiler");
+ throw std::runtime_error("invalid_bin");
+ }
+ }
+
+ LibCompiler::NumberCast64 num(strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2));
+
+ if (kVerbose) {
+ kStdOut << "AssemblerARM64: found a base 2 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ for (char& i : num.number) {
+ kBytes.push_back(i);
+ }
+
+ return true;
+ }
+ case 'o': {
+ if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7); !res) {
+ if (errno != 0) {
+ Detail::print_error("invalid octal number: " + jump_label, "LibCompiler");
+ throw std::runtime_error("invalid_octal");
+ }
+ }
+
+ LibCompiler::NumberCast64 num(strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7));
+
+ if (kVerbose) {
+ kStdOut << "AssemblerARM64: found a base 8 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ for (char& i : num.number) {
+ kBytes.push_back(i);
+ }
+
+ return true;
+ }
+ default: {
+ break;
+ }
+ }
+
+ /* check for errno and stuff like that */
+ if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res) {
+ if (errno != 0) {
+ return false;
+ }
+ }
+
+ LibCompiler::NumberCast64 num(strtol(jump_label.substr(pos).c_str(), nullptr, 10));
+
+ for (char& i : num.number) {
+ kBytes.push_back(i);
+ }
+
+ if (kVerbose) {
+ kStdOut << "AssemblerARM64: found a base 10 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ return true;
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -696,16 +583,12 @@ bool LibCompiler::EncoderARM64::WriteNumber(const std::size_t& pos,
/////////////////////////////////////////////////////////////////////////////////////////
-bool LibCompiler::EncoderARM64::WriteLine(std::string& line,
- const std::string& file)
-{
- if (LibCompiler::find_word(line, "public_segment"))
- return false;
+bool LibCompiler::EncoderARM64::WriteLine(std::string& line, const std::string& file) {
+ if (LibCompiler::find_word(line, "public_segment")) return false;
- if (!Detail::algorithm::is_valid_arm64(line))
- return false;
+ if (!Detail::algorithm::is_valid_arm64(line)) return false;
- return true;
+ return true;
}
// Last rev 13-1-24
diff --git a/dev/LibCompiler/src/AssemblerPower.cc b/dev/LibCompiler/src/AssemblerPower.cc
index 59f7ed6..30b6d68 100644
--- a/dev/LibCompiler/src/AssemblerPower.cc
+++ b/dev/LibCompiler/src/AssemblerPower.cc
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
+ Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
------------------------------------------- */
@@ -17,16 +17,16 @@
#define __ASM_NEED_PPC__ 1
-#include <LibCompiler/ErrorID.h>
+#include <LibCompiler/AE.h>
#include <LibCompiler/Backend/power64.h>
+#include <LibCompiler/ErrorID.h>
#include <LibCompiler/PEF.h>
#include <LibCompiler/Parser.h>
-#include <LibCompiler/AE.h>
#include <LibCompiler/Version.h>
-#include <filesystem>
#include <algorithm>
-#include <iostream>
+#include <filesystem>
#include <fstream>
+#include <iostream>
#include <vector>
/////////////////////
@@ -35,9 +35,9 @@
/////////////////////
-#define kBlank "\e[0;30m"
-#define kRed "\e[0;31m"
-#define kWhite "\e[0;97m"
+#define kBlank "\e[0;30m"
+#define kRed "\e[0;31m"
+#define kWhite "\e[0;97m"
#define kYellow "\e[0;33m"
#define kStdOut (std::cout << kWhite)
@@ -45,15 +45,15 @@
constexpr auto cPowerIPAlignment = 0x4U;
-static CharType kOutputArch = LibCompiler::kPefArchPowerPC;
-static Boolean kOutputAsBinary = false;
+static CharType kOutputArch = LibCompiler::kPefArchPowerPC;
+static Boolean kOutputAsBinary = false;
-static UInt32 kErrorLimit = 10;
+static UInt32 kErrorLimit = 10;
static UInt32 kAcceptableErrors = 0;
static std::size_t kCounter = 1UL;
-static std::uintptr_t kOrigin = kPefBaseOrigin;
+static std::uintptr_t kOrigin = kPefBaseOrigin;
static std::vector<std::pair<std::string, std::uintptr_t>> kOriginLabel;
static bool kVerbose = false;
@@ -61,13 +61,13 @@ static bool kVerbose = false;
static std::vector<uint8_t> kBytes;
static LibCompiler::AERecordHeader kCurrentRecord{
- .fName = "", .fKind = LibCompiler::kPefCode, .fSize = 0, .fOffset = 0};
+ .fName = "", .fKind = LibCompiler::kPefCode, .fSize = 0, .fOffset = 0};
static std::vector<LibCompiler::AERecordHeader> kRecords;
-static std::vector<std::string> kUndefinedSymbols;
+static std::vector<std::string> kUndefinedSymbols;
static const std::string kUndefinedSymbol = ":UndefinedSymbol:";
-static const std::string kRelocSymbol = ":RuntimeSymbol:";
+static const std::string kRelocSymbol = ":RuntimeSymbol:";
// \brief forward decl.
static bool asm_read_attributes(std::string& line);
@@ -81,225 +81,191 @@ static bool asm_read_attributes(std::string& line);
/////////////////////////////////////////////////////////////////////////////////////////
-LIBCOMPILER_MODULE(AssemblerMainPower64)
-{
- for (size_t i = 1; i < argc; ++i)
- {
- if (argv[i][0] == '-')
- {
- if (strcmp(argv[i], "--ver") == 0 || strcmp(argv[i], "--v") == 0)
- {
- kStdOut << "AssemblerPower: POWER64 Assembler Driver.\nAssemblerPower: " << kDistVersion << "\nAssemblerPower: "
- "Copyright (c) "
- "Amlal El Mahrouss\n";
- return 0;
- }
- else if (strcmp(argv[i], "--h") == 0)
- {
- kStdOut << "AssemblerPower: POWER64 Assembler Driver.\nAssemblerPower: Copyright (c) 2024 "
- "Amlal El Mahrouss\n";
- kStdOut << "--version,/v: print program version.\n";
- kStdOut << "--verbose: print verbose output.\n";
- kStdOut << "--binary: output as flat binary.\n";
-
- return 0;
- }
- else if (strcmp(argv[i], "--binary") == 0)
- {
- kOutputAsBinary = true;
- continue;
- }
- else if (strcmp(argv[i], "--verbose") == 0)
- {
- kVerbose = true;
- continue;
- }
-
- kStdOut << "AssemblerPower: ignore " << argv[i] << "\n";
- continue;
- }
-
- if (!std::filesystem::exists(argv[i]))
- {
- kStdOut << "AssemblerPower: can't open: " << argv[i] << std::endl;
- goto asm_fail_exit;
- }
-
- std::string object_output(argv[i]);
-
- for (auto& ext : kAsmFileExts)
- {
- if (object_output.find(ext) != std::string::npos)
- {
- object_output.erase(object_output.find(ext), std::strlen(ext));
- }
- }
-
- object_output += kOutputAsBinary ? kBinaryFileExt : kObjectFileExt;
-
- std::ifstream file_ptr(argv[i]);
- std::ofstream file_ptr_out(object_output, std::ofstream::binary);
-
- if (file_ptr_out.bad())
- {
- if (kVerbose)
- {
- kStdOut << "AssemblerPower: error: " << strerror(errno) << "\n";
- }
- }
-
- std::string line;
-
- LibCompiler::AEHeader hdr{0};
-
- memset(hdr.fPad, kAENullType, kAEPad);
-
- hdr.fMagic[0] = kAEMag0;
- hdr.fMagic[1] = kAEMag1;
- hdr.fSize = sizeof(LibCompiler::AEHeader);
- hdr.fArch = kOutputArch;
-
- /////////////////////////////////////////////////////////////////////////////////////////
-
- // COMPILATION LOOP
-
- /////////////////////////////////////////////////////////////////////////////////////////
-
- LibCompiler::EncoderPowerPC asm64;
-
- while (std::getline(file_ptr, line))
- {
- if (auto ln = asm64.CheckLine(line, argv[i]); !ln.empty())
- {
- Detail::print_error(ln, argv[i]);
- continue;
- }
-
- try
- {
- asm_read_attributes(line);
- asm64.WriteLine(line, argv[i]);
- }
- catch (const std::exception& e)
- {
- if (kVerbose)
- {
- std::string what = e.what();
- Detail::print_warning("exit because of: " + what, "LibCompiler");
- }
-
- std::filesystem::remove(object_output);
- goto asm_fail_exit;
- }
- }
-
- if (!kOutputAsBinary)
- {
- if (kVerbose)
- {
- kStdOut << "AssemblerPower: Writing object file...\n";
- }
+LIBCOMPILER_MODULE(AssemblerMainPower64) {
+ for (size_t i = 1; i < argc; ++i) {
+ if (argv[i][0] == '-') {
+ if (strcmp(argv[i], "--ver") == 0 || strcmp(argv[i], "--v") == 0) {
+ kStdOut << "AssemblerPower: POWER64 Assembler Driver.\nAssemblerPower: " << kDistVersion
+ << "\nAssemblerPower: "
+ "Copyright (c) "
+ "Amlal El Mahrouss\n";
+ return 0;
+ } else if (strcmp(argv[i], "--h") == 0) {
+ kStdOut << "AssemblerPower: POWER64 Assembler Driver.\nAssemblerPower: Copyright (c) 2024 "
+ "Amlal El Mahrouss\n";
+ kStdOut << "--version,/v: print program version.\n";
+ kStdOut << "--verbose: print verbose output.\n";
+ kStdOut << "--binary: output as flat binary.\n";
+
+ return 0;
+ } else if (strcmp(argv[i], "--binary") == 0) {
+ kOutputAsBinary = true;
+ continue;
+ } else if (strcmp(argv[i], "--verbose") == 0) {
+ kVerbose = true;
+ continue;
+ }
+
+ kStdOut << "AssemblerPower: ignore " << argv[i] << "\n";
+ continue;
+ }
+
+ if (!std::filesystem::exists(argv[i])) {
+ kStdOut << "AssemblerPower: can't open: " << argv[i] << std::endl;
+ goto asm_fail_exit;
+ }
+
+ std::string object_output(argv[i]);
+
+ for (auto& ext : kAsmFileExts) {
+ if (object_output.find(ext) != std::string::npos) {
+ object_output.erase(object_output.find(ext), std::strlen(ext));
+ }
+ }
+
+ object_output += kOutputAsBinary ? kBinaryFileExt : kObjectFileExt;
+
+ std::ifstream file_ptr(argv[i]);
+ std::ofstream file_ptr_out(object_output, std::ofstream::binary);
+
+ if (file_ptr_out.bad()) {
+ if (kVerbose) {
+ kStdOut << "AssemblerPower: error: " << strerror(errno) << "\n";
+ }
+ }
+
+ std::string line;
+
+ LibCompiler::AEHeader hdr{0};
+
+ memset(hdr.fPad, kAENullType, kAEPad);
+
+ hdr.fMagic[0] = kAEMag0;
+ hdr.fMagic[1] = kAEMag1;
+ hdr.fSize = sizeof(LibCompiler::AEHeader);
+ hdr.fArch = kOutputArch;
+
+ /////////////////////////////////////////////////////////////////////////////////////////
+
+ // COMPILATION LOOP
+
+ /////////////////////////////////////////////////////////////////////////////////////////
+
+ LibCompiler::EncoderPowerPC asm64;
+
+ while (std::getline(file_ptr, line)) {
+ if (auto ln = asm64.CheckLine(line, argv[i]); !ln.empty()) {
+ Detail::print_error(ln, argv[i]);
+ continue;
+ }
+
+ try {
+ asm_read_attributes(line);
+ asm64.WriteLine(line, argv[i]);
+ } catch (const std::exception& e) {
+ if (kVerbose) {
+ std::string what = e.what();
+ Detail::print_warning("exit because of: " + what, "LibCompiler");
+ }
+
+ std::filesystem::remove(object_output);
+ goto asm_fail_exit;
+ }
+ }
- // this is the final step, write everything to the file.
+ if (!kOutputAsBinary) {
+ if (kVerbose) {
+ kStdOut << "AssemblerPower: Writing object file...\n";
+ }
- auto pos = file_ptr_out.tellp();
+ // this is the final step, write everything to the file.
- hdr.fCount = kRecords.size() + kUndefinedSymbols.size();
+ auto pos = file_ptr_out.tellp();
- file_ptr_out << hdr;
+ hdr.fCount = kRecords.size() + kUndefinedSymbols.size();
- if (kRecords.empty())
- {
- kStdErr << "AssemblerPower: At least one record is needed to write an object "
- "file.\nAssemblerPower: Make one using `public_segment .code64 foo_bar`.\n";
+ file_ptr_out << hdr;
- std::filesystem::remove(object_output);
- return 1;
- }
+ if (kRecords.empty()) {
+ kStdErr << "AssemblerPower: At least one record is needed to write an object "
+ "file.\nAssemblerPower: Make one using `public_segment .code64 foo_bar`.\n";
- kRecords[kRecords.size() - 1].fSize = kBytes.size();
+ std::filesystem::remove(object_output);
+ return 1;
+ }
- std::size_t record_count = 0UL;
+ kRecords[kRecords.size() - 1].fSize = kBytes.size();
- for (auto& record_hdr : kRecords)
- {
- record_hdr.fFlags |= LibCompiler::kKindRelocationAtRuntime;
- record_hdr.fOffset = record_count;
- ++record_count;
+ std::size_t record_count = 0UL;
- file_ptr_out << record_hdr;
+ for (auto& record_hdr : kRecords) {
+ record_hdr.fFlags |= LibCompiler::kKindRelocationAtRuntime;
+ record_hdr.fOffset = record_count;
+ ++record_count;
- if (kVerbose)
- kStdOut << "AssemblerPower: Wrote record " << record_hdr.fName << "...\n";
- }
+ file_ptr_out << record_hdr;
- // increment once again, so that we won't lie about the kUndefinedSymbols.
- ++record_count;
+ if (kVerbose) kStdOut << "AssemblerPower: Wrote record " << record_hdr.fName << "...\n";
+ }
- for (auto& sym : kUndefinedSymbols)
- {
- LibCompiler::AERecordHeader undefined_sym{0};
+ // increment once again, so that we won't lie about the kUndefinedSymbols.
+ ++record_count;
- if (kVerbose)
- kStdOut << "AssemblerPower: Wrote symbol " << sym << " to file...\n";
+ for (auto& sym : kUndefinedSymbols) {
+ LibCompiler::AERecordHeader undefined_sym{0};
- undefined_sym.fKind = kAENullType;
- undefined_sym.fSize = sym.size();
- undefined_sym.fOffset = record_count;
+ if (kVerbose) kStdOut << "AssemblerPower: Wrote symbol " << sym << " to file...\n";
- ++record_count;
+ undefined_sym.fKind = kAENullType;
+ undefined_sym.fSize = sym.size();
+ undefined_sym.fOffset = record_count;
- memset(undefined_sym.fPad, kAENullType, kAEPad);
- memcpy(undefined_sym.fName, sym.c_str(), sym.size());
+ ++record_count;
- file_ptr_out << undefined_sym;
+ memset(undefined_sym.fPad, kAENullType, kAEPad);
+ memcpy(undefined_sym.fName, sym.c_str(), sym.size());
- ++kCounter;
- }
+ file_ptr_out << undefined_sym;
- auto pos_end = file_ptr_out.tellp();
+ ++kCounter;
+ }
- file_ptr_out.seekp(pos);
+ auto pos_end = file_ptr_out.tellp();
- hdr.fStartCode = pos_end;
- hdr.fCodeSize = kBytes.size();
+ file_ptr_out.seekp(pos);
- file_ptr_out << hdr;
+ hdr.fStartCode = pos_end;
+ hdr.fCodeSize = kBytes.size();
- file_ptr_out.seekp(pos_end);
- }
- else
- {
- if (kVerbose)
- {
- kStdOut << "AssemblerPower: Write raw binary...\n";
- }
- }
+ file_ptr_out << hdr;
- // byte from byte, we write this.
- for (auto& byte : kBytes)
- {
- file_ptr_out.write(reinterpret_cast<const char*>(&byte), sizeof(byte));
- }
+ file_ptr_out.seekp(pos_end);
+ } else {
+ if (kVerbose) {
+ kStdOut << "AssemblerPower: Write raw binary...\n";
+ }
+ }
- if (kVerbose)
- kStdOut << "AssemblerPower: Wrote file with program in it.\n";
+ // byte from byte, we write this.
+ for (auto& byte : kBytes) {
+ file_ptr_out.write(reinterpret_cast<const char*>(&byte), sizeof(byte));
+ }
- file_ptr_out.flush();
- file_ptr_out.close();
+ if (kVerbose) kStdOut << "AssemblerPower: Wrote file with program in it.\n";
- if (kVerbose)
- kStdOut << "AssemblerPower: Exit succeeded.\n";
+ file_ptr_out.flush();
+ file_ptr_out.close();
- return 0;
- }
+ if (kVerbose) kStdOut << "AssemblerPower: Exit succeeded.\n";
+
+ return 0;
+ }
asm_fail_exit:
- if (kVerbose)
- kStdOut << "AssemblerPower: Exit failed.\n";
+ if (kVerbose) kStdOut << "AssemblerPower: Exit failed.\n";
- return LIBCOMPILER_EXEC_ERROR;
+ return LIBCOMPILER_EXEC_ERROR;
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -309,175 +275,144 @@ asm_fail_exit:
/////////////////////////////////////////////////////////////////////////////////////////
-static bool asm_read_attributes(std::string& line)
-{
- // extern_segment is the opposite of public_segment, it signals to the li
- // that we need this symbol.
- if (LibCompiler::find_word(line, "extern_segment"))
- {
- if (kOutputAsBinary)
- {
- Detail::print_error("Invalid extern_segment directive in flat binary mode.",
- "LibCompiler");
- throw std::runtime_error("invalid_extern_segment_bin");
- }
-
- auto name = line.substr(line.find("extern_segment") + strlen("extern_segment") + 1);
-
- if (name.size() == 0)
- {
- Detail::print_error("Invalid extern_segment", "LibCompiler");
- throw std::runtime_error("invalid_extern_segment");
- }
-
- std::string result = std::to_string(name.size());
- result += kUndefinedSymbol;
-
- // mangle this
- for (char& j : name)
- {
- if (j == ' ' || j == ',')
- j = '$';
- }
-
- result += name;
-
- if (name.find(".code64") != std::string::npos)
- {
- // data is treated as code.
- kCurrentRecord.fKind = LibCompiler::kPefCode;
- }
- else if (name.find(".data64") != std::string::npos)
- {
- // no code will be executed from here.
- kCurrentRecord.fKind = LibCompiler::kPefData;
- }
- else if (name.find(".zero64") != std::string::npos)
- {
- // this is a bss section.
- kCurrentRecord.fKind = LibCompiler::kPefZero;
- }
-
- // this is a special case for the start stub.
- // we want this so that li can find it.
-
- if (name == kPefStart)
- {
- kCurrentRecord.fKind = LibCompiler::kPefCode;
- }
-
- // now we can tell the code size of the previous kCurrentRecord.
-
- if (!kRecords.empty())
- kRecords[kRecords.size() - 1].fSize = kBytes.size();
-
- memset(kCurrentRecord.fName, 0, kAESymbolLen);
- memcpy(kCurrentRecord.fName, result.c_str(), result.size());
-
- ++kCounter;
-
- memset(kCurrentRecord.fPad, kAENullType, kAEPad);
-
- kRecords.emplace_back(kCurrentRecord);
-
- return true;
- }
- // public_segment is a special keyword used by AssemblerPower to tell the AE output stage to
- // mark this section as a header. it currently supports .code64, .data64.,
- // .zero64
- else if (LibCompiler::find_word(line, "public_segment"))
- {
- if (kOutputAsBinary)
- {
- Detail::print_error("Invalid public_segment directive in flat binary mode.",
- "LibCompiler");
- throw std::runtime_error("invalid_public_segment_bin");
- }
-
- auto name = line.substr(line.find("public_segment") + strlen("public_segment"));
-
- std::string name_copy = name;
-
- for (char& j : name)
- {
- if (j == ' ')
- j = '$';
- }
-
- if (name.find(".code64") != std::string::npos)
- {
- // data is treated as code.
-
- name_copy.erase(name_copy.find(".code64"), strlen(".code64"));
- kCurrentRecord.fKind = LibCompiler::kPefCode;
- }
- else if (name.find(".data64") != std::string::npos)
- {
- // no code will be executed from here.
-
- name_copy.erase(name_copy.find(".data64"), strlen(".data64"));
- kCurrentRecord.fKind = LibCompiler::kPefData;
- }
- else if (name.find(".zero64") != std::string::npos)
- {
- // this is a bss section.
+static bool asm_read_attributes(std::string& line) {
+ // extern_segment is the opposite of public_segment, it signals to the li
+ // that we need this symbol.
+ if (LibCompiler::find_word(line, "extern_segment")) {
+ if (kOutputAsBinary) {
+ Detail::print_error("Invalid extern_segment directive in flat binary mode.", "LibCompiler");
+ throw std::runtime_error("invalid_extern_segment_bin");
+ }
+
+ auto name = line.substr(line.find("extern_segment") + strlen("extern_segment") + 1);
+
+ if (name.size() == 0) {
+ Detail::print_error("Invalid extern_segment", "LibCompiler");
+ throw std::runtime_error("invalid_extern_segment");
+ }
+
+ std::string result = std::to_string(name.size());
+ result += kUndefinedSymbol;
+
+ // mangle this
+ for (char& j : name) {
+ if (j == ' ' || j == ',') j = '$';
+ }
+
+ result += name;
+
+ if (name.find(".code64") != std::string::npos) {
+ // data is treated as code.
+ kCurrentRecord.fKind = LibCompiler::kPefCode;
+ } else if (name.find(".data64") != std::string::npos) {
+ // no code will be executed from here.
+ kCurrentRecord.fKind = LibCompiler::kPefData;
+ } else if (name.find(".zero64") != std::string::npos) {
+ // this is a bss section.
+ kCurrentRecord.fKind = LibCompiler::kPefZero;
+ }
+
+ // this is a special case for the start stub.
+ // we want this so that li can find it.
+
+ if (name == kPefStart) {
+ kCurrentRecord.fKind = LibCompiler::kPefCode;
+ }
+
+ // now we can tell the code size of the previous kCurrentRecord.
+
+ if (!kRecords.empty()) kRecords[kRecords.size() - 1].fSize = kBytes.size();
+
+ memset(kCurrentRecord.fName, 0, kAESymbolLen);
+ memcpy(kCurrentRecord.fName, result.c_str(), result.size());
+
+ ++kCounter;
+
+ memset(kCurrentRecord.fPad, kAENullType, kAEPad);
- name_copy.erase(name_copy.find(".zero64"), strlen(".zero64"));
- kCurrentRecord.fKind = LibCompiler::kPefZero;
- }
-
- // this is a special case for the start stub.
- // we want this so that li can find it.
+ kRecords.emplace_back(kCurrentRecord);
- if (name == kPefStart)
- {
- kCurrentRecord.fKind = LibCompiler::kPefCode;
- }
-
- while (name_copy.find(" ") != std::string::npos)
- name_copy.erase(name_copy.find(" "), 1);
+ return true;
+ }
+ // public_segment is a special keyword used by AssemblerPower to tell the AE output stage to
+ // mark this section as a header. it currently supports .code64, .data64.,
+ // .zero64
+ else if (LibCompiler::find_word(line, "public_segment")) {
+ if (kOutputAsBinary) {
+ Detail::print_error("Invalid public_segment directive in flat binary mode.", "LibCompiler");
+ throw std::runtime_error("invalid_public_segment_bin");
+ }
- kOriginLabel.push_back(std::make_pair(name_copy, kOrigin));
- ++kOrigin;
+ auto name = line.substr(line.find("public_segment") + strlen("public_segment"));
- // now we can tell the code size of the previous kCurrentRecord.
+ std::string name_copy = name;
- if (!kRecords.empty())
- kRecords[kRecords.size() - 1].fSize = kBytes.size();
+ for (char& j : name) {
+ if (j == ' ') j = '$';
+ }
- memset(kCurrentRecord.fName, 0, kAESymbolLen);
- memcpy(kCurrentRecord.fName, name.c_str(), name.size());
+ if (name.find(".code64") != std::string::npos) {
+ // data is treated as code.
- ++kCounter;
+ name_copy.erase(name_copy.find(".code64"), strlen(".code64"));
+ kCurrentRecord.fKind = LibCompiler::kPefCode;
+ } else if (name.find(".data64") != std::string::npos) {
+ // no code will be executed from here.
- memset(kCurrentRecord.fPad, kAENullType, kAEPad);
+ name_copy.erase(name_copy.find(".data64"), strlen(".data64"));
+ kCurrentRecord.fKind = LibCompiler::kPefData;
+ } else if (name.find(".zero64") != std::string::npos) {
+ // this is a bss section.
- kRecords.emplace_back(kCurrentRecord);
+ name_copy.erase(name_copy.find(".zero64"), strlen(".zero64"));
+ kCurrentRecord.fKind = LibCompiler::kPefZero;
+ }
- return true;
- }
+ // this is a special case for the start stub.
+ // we want this so that li can find it.
- return false;
+ if (name == kPefStart) {
+ kCurrentRecord.fKind = LibCompiler::kPefCode;
+ }
+
+ while (name_copy.find(" ") != std::string::npos) name_copy.erase(name_copy.find(" "), 1);
+
+ kOriginLabel.push_back(std::make_pair(name_copy, kOrigin));
+ ++kOrigin;
+
+ // now we can tell the code size of the previous kCurrentRecord.
+
+ if (!kRecords.empty()) kRecords[kRecords.size() - 1].fSize = kBytes.size();
+
+ memset(kCurrentRecord.fName, 0, kAESymbolLen);
+ memcpy(kCurrentRecord.fName, name.c_str(), name.size());
+
+ ++kCounter;
+
+ memset(kCurrentRecord.fPad, kAENullType, kAEPad);
+
+ kRecords.emplace_back(kCurrentRecord);
+
+ return true;
+ }
+
+ return false;
}
// \brief algorithms and helpers.
-namespace Detail::algorithm
-{
- // \brief authorize a brief set of characters.
- static inline bool is_not_alnum_space(char c)
- {
- return !(isalpha(c) || isdigit(c) || (c == ' ') || (c == '\t') ||
- (c == ',') || (c == '(') || (c == ')') || (c == '"') ||
- (c == '\'') || (c == '[') || (c == ']') || (c == '+') ||
- (c == '_') || (c == ':') || (c == '@') || (c == '.'));
- }
-
- bool is_valid_power64(const std::string& str)
- {
- return std::find_if(str.begin(), str.end(), is_not_alnum_space) == str.end();
- }
-} // namespace Detail::algorithm
+namespace Detail::algorithm {
+// \brief authorize a brief set of characters.
+static inline bool is_not_alnum_space(char c) {
+ return !(isalpha(c) || isdigit(c) || (c == ' ') || (c == '\t') || (c == ',') || (c == '(') ||
+ (c == ')') || (c == '"') || (c == '\'') || (c == '[') || (c == ']') || (c == '+') ||
+ (c == '_') || (c == ':') || (c == '@') || (c == '.'));
+}
+
+bool is_valid_power64(const std::string& str) {
+ return std::find_if(str.begin(), str.end(), is_not_alnum_space) == str.end();
+}
+} // namespace Detail::algorithm
/////////////////////////////////////////////////////////////////////////////////////////
@@ -485,255 +420,198 @@ namespace Detail::algorithm
/////////////////////////////////////////////////////////////////////////////////////////
-std::string LibCompiler::EncoderPowerPC::CheckLine(std::string& line,
- const std::string& file)
-{
- std::string err_str;
-
- if (line.empty() || LibCompiler::find_word(line, "extern_segment") ||
- LibCompiler::find_word(line, "public_segment") ||
- line.find('#') != std::string::npos || LibCompiler::find_word(line, ";"))
- {
- if (line.find('#') != std::string::npos)
- {
- line.erase(line.find('#'));
- }
- else if (line.find(';') != std::string::npos)
- {
- line.erase(line.find(';'));
- }
- else
- {
- /// does the line contains valid input?
- if (!Detail::algorithm::is_valid_power64(line))
- {
- err_str = "Line contains non alphanumeric characters.\nhere -> ";
- err_str += line;
- }
- }
-
- return err_str;
- }
-
- if (!Detail::algorithm::is_valid_power64(line))
- {
- err_str = "Line contains non alphanumeric characters.\nhere -> ";
- err_str += line;
-
- return err_str;
- }
-
- // check for a valid instruction format.
-
- if (line.find(',') != std::string::npos)
- {
- if (line.find(',') + 1 == line.size())
- {
- err_str += "\nInstruction lacks right register, here -> ";
- err_str += line.substr(line.find(','));
-
- return err_str;
- }
- else
- {
- bool nothing_on_right = true;
-
- if (line.find(',') + 1 > line.size())
- {
- err_str += "\nInstruction not complete, here -> ";
- err_str += line;
-
- return err_str;
- }
-
- auto substr = line.substr(line.find(',') + 1);
-
- for (auto& ch : substr)
- {
- if (ch != ' ' && ch != '\t')
- {
- nothing_on_right = false;
- }
- }
-
- // this means we found nothing after that ',' .
- if (nothing_on_right)
- {
- err_str += "\nInstruction not complete, here -> ";
- err_str += line;
-
- return err_str;
- }
- }
- }
-
- // these do take an argument.
- std::vector<std::string> operands_inst = {"stw", "li"};
-
- // these don't.
- std::vector<std::string> filter_inst = {"blr", "bl", "sc"};
-
- for (auto& opcode_risc : kOpcodesPowerPC)
- {
- if (LibCompiler::find_word(line, opcode_risc.name))
- {
- for (auto& op : operands_inst)
- {
- // if only the instruction was found.
- if (line == op)
- {
- err_str += "\nMalformed ";
- err_str += op;
- err_str += " instruction, here -> ";
- err_str += line;
- }
- }
-
- // if it is like that -> addr1, 0x0
- if (auto it =
- std::find(filter_inst.begin(), filter_inst.end(), opcode_risc.name);
- it == filter_inst.cend())
- {
- if (LibCompiler::find_word(line, opcode_risc.name))
- {
- if (!isspace(
- line[line.find(opcode_risc.name) + strlen(opcode_risc.name)]))
- {
- err_str += "\nMissing space between ";
- err_str += opcode_risc.name;
- err_str += " and operands.\nhere -> ";
- err_str += line;
- }
- }
- }
-
- return err_str;
- }
- }
-
- err_str += "Unrecognized instruction: " + line;
-
- return err_str;
+std::string LibCompiler::EncoderPowerPC::CheckLine(std::string& line, const std::string& file) {
+ std::string err_str;
+
+ if (line.empty() || LibCompiler::find_word(line, "extern_segment") ||
+ LibCompiler::find_word(line, "public_segment") || line.find('#') != std::string::npos ||
+ LibCompiler::find_word(line, ";")) {
+ if (line.find('#') != std::string::npos) {
+ line.erase(line.find('#'));
+ } else if (line.find(';') != std::string::npos) {
+ line.erase(line.find(';'));
+ } else {
+ /// does the line contains valid input?
+ if (!Detail::algorithm::is_valid_power64(line)) {
+ err_str = "Line contains non alphanumeric characters.\nhere -> ";
+ err_str += line;
+ }
+ }
+
+ return err_str;
+ }
+
+ if (!Detail::algorithm::is_valid_power64(line)) {
+ err_str = "Line contains non alphanumeric characters.\nhere -> ";
+ err_str += line;
+
+ return err_str;
+ }
+
+ // check for a valid instruction format.
+
+ if (line.find(',') != std::string::npos) {
+ if (line.find(',') + 1 == line.size()) {
+ err_str += "\nInstruction lacks right register, here -> ";
+ err_str += line.substr(line.find(','));
+
+ return err_str;
+ } else {
+ bool nothing_on_right = true;
+
+ if (line.find(',') + 1 > line.size()) {
+ err_str += "\nInstruction not complete, here -> ";
+ err_str += line;
+
+ return err_str;
+ }
+
+ auto substr = line.substr(line.find(',') + 1);
+
+ for (auto& ch : substr) {
+ if (ch != ' ' && ch != '\t') {
+ nothing_on_right = false;
+ }
+ }
+
+ // this means we found nothing after that ',' .
+ if (nothing_on_right) {
+ err_str += "\nInstruction not complete, here -> ";
+ err_str += line;
+
+ return err_str;
+ }
+ }
+ }
+
+ // these do take an argument.
+ std::vector<std::string> operands_inst = {"stw", "li"};
+
+ // these don't.
+ std::vector<std::string> filter_inst = {"blr", "bl", "sc"};
+
+ for (auto& opcode_risc : kOpcodesPowerPC) {
+ if (LibCompiler::find_word(line, opcode_risc.name)) {
+ for (auto& op : operands_inst) {
+ // if only the instruction was found.
+ if (line == op) {
+ err_str += "\nMalformed ";
+ err_str += op;
+ err_str += " instruction, here -> ";
+ err_str += line;
+ }
+ }
+
+ // if it is like that -> addr1, 0x0
+ if (auto it = std::find(filter_inst.begin(), filter_inst.end(), opcode_risc.name);
+ it == filter_inst.cend()) {
+ if (LibCompiler::find_word(line, opcode_risc.name)) {
+ if (!isspace(line[line.find(opcode_risc.name) + strlen(opcode_risc.name)])) {
+ err_str += "\nMissing space between ";
+ err_str += opcode_risc.name;
+ err_str += " and operands.\nhere -> ";
+ err_str += line;
+ }
+ }
+ }
+
+ return err_str;
+ }
+ }
+
+ err_str += "Unrecognized instruction: " + line;
+
+ return err_str;
}
-bool LibCompiler::EncoderPowerPC::WriteNumber(const std::size_t& pos,
- std::string& jump_label)
-{
- if (!isdigit(jump_label[pos]))
- return false;
-
- switch (jump_label[pos + 1])
- {
- case 'x': {
- if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16);
- !res)
- {
- if (errno != 0)
- {
- Detail::print_error("invalid hex number: " + jump_label, "LibCompiler");
- throw std::runtime_error("invalid_hex");
- }
- }
-
- LibCompiler::NumberCast64 num(
- strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16));
-
- for (char& i : num.number)
- {
- kBytes.push_back(i);
- }
-
- if (kVerbose)
- {
- kStdOut << "AssemblerPower: found a base 16 number here: "
- << jump_label.substr(pos) << "\n";
- }
-
- return true;
- }
- case 'b': {
- if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2);
- !res)
- {
- if (errno != 0)
- {
- Detail::print_error("invalid binary number: " + jump_label, "LibCompiler");
- throw std::runtime_error("invalid_bin");
- }
- }
-
- LibCompiler::NumberCast64 num(
- strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2));
-
- if (kVerbose)
- {
- kStdOut << "AssemblerPower: found a base 2 number here: "
- << jump_label.substr(pos) << "\n";
- }
-
- for (char& i : num.number)
- {
- kBytes.push_back(i);
- }
-
- return true;
- }
- case 'o': {
- if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7);
- !res)
- {
- if (errno != 0)
- {
- Detail::print_error("invalid octal number: " + jump_label, "LibCompiler");
- throw std::runtime_error("invalid_octal");
- }
- }
-
- LibCompiler::NumberCast64 num(
- strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7));
-
- if (kVerbose)
- {
- kStdOut << "AssemblerPower: found a base 8 number here: "
- << jump_label.substr(pos) << "\n";
- }
-
- for (char& i : num.number)
- {
- kBytes.push_back(i);
- }
-
- return true;
- }
- default: {
- break;
- }
- }
-
- /* check for errno and stuff like that */
- if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res)
- {
- if (errno != 0)
- {
- return false;
- }
- }
-
- LibCompiler::NumberCast64 num(
- strtol(jump_label.substr(pos).c_str(), nullptr, 10));
-
- for (char& i : num.number)
- {
- kBytes.push_back(i);
- }
-
- if (kVerbose)
- {
- kStdOut << "AssemblerPower: found a base 10 number here: " << jump_label.substr(pos)
- << "\n";
- }
-
- return true;
+bool LibCompiler::EncoderPowerPC::WriteNumber(const std::size_t& pos, std::string& jump_label) {
+ if (!isdigit(jump_label[pos])) return false;
+
+ switch (jump_label[pos + 1]) {
+ case 'x': {
+ if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16); !res) {
+ if (errno != 0) {
+ Detail::print_error("invalid hex number: " + jump_label, "LibCompiler");
+ throw std::runtime_error("invalid_hex");
+ }
+ }
+
+ LibCompiler::NumberCast64 num(strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16));
+
+ for (char& i : num.number) {
+ kBytes.push_back(i);
+ }
+
+ if (kVerbose) {
+ kStdOut << "AssemblerPower: found a base 16 number here: " << jump_label.substr(pos)
+ << "\n";
+ }
+
+ return true;
+ }
+ case 'b': {
+ if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2); !res) {
+ if (errno != 0) {
+ Detail::print_error("invalid binary number: " + jump_label, "LibCompiler");
+ throw std::runtime_error("invalid_bin");
+ }
+ }
+
+ LibCompiler::NumberCast64 num(strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2));
+
+ if (kVerbose) {
+ kStdOut << "AssemblerPower: found a base 2 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ for (char& i : num.number) {
+ kBytes.push_back(i);
+ }
+
+ return true;
+ }
+ case 'o': {
+ if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7); !res) {
+ if (errno != 0) {
+ Detail::print_error("invalid octal number: " + jump_label, "LibCompiler");
+ throw std::runtime_error("invalid_octal");
+ }
+ }
+
+ LibCompiler::NumberCast64 num(strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7));
+
+ if (kVerbose) {
+ kStdOut << "AssemblerPower: found a base 8 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ for (char& i : num.number) {
+ kBytes.push_back(i);
+ }
+
+ return true;
+ }
+ default: {
+ break;
+ }
+ }
+
+ /* check for errno and stuff like that */
+ if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res) {
+ if (errno != 0) {
+ return false;
+ }
+ }
+
+ LibCompiler::NumberCast64 num(strtol(jump_label.substr(pos).c_str(), nullptr, 10));
+
+ for (char& i : num.number) {
+ kBytes.push_back(i);
+ }
+
+ if (kVerbose) {
+ kStdOut << "AssemblerPower: found a base 10 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ return true;
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -742,355 +620,299 @@ bool LibCompiler::EncoderPowerPC::WriteNumber(const std::size_t& pos,
/////////////////////////////////////////////////////////////////////////////////////////
-bool LibCompiler::EncoderPowerPC::WriteLine(std::string& line,
- const std::string& file)
-{
- if (LibCompiler::find_word(line, "public_segment"))
- return false;
- if (!Detail::algorithm::is_valid_power64(line))
- return false;
-
- for (auto& opcode_risc : kOpcodesPowerPC)
- {
- // strict check here
- if (LibCompiler::find_word(line, opcode_risc.name))
- {
- std::string name(opcode_risc.name);
- std::string jump_label, cpy_jump_label;
- std::vector<size_t> found_registers_index;
-
- // check funct7 type.
- switch (opcode_risc.ops->type)
- {
- default: {
- NumberCast32 num(opcode_risc.opcode);
-
- for (auto ch : num.number)
- {
- kBytes.emplace_back(ch);
- }
- break;
- }
- case BADDR:
- case PCREL: {
- auto num = GetNumber32(line, name);
-
- kBytes.emplace_back(num.number[0]);
- kBytes.emplace_back(num.number[1]);
- kBytes.emplace_back(num.number[2]);
- kBytes.emplace_back(0x48);
-
- break;
- }
- /// General purpose, float, vector operations. Everything that involve
- /// registers.
- case G0REG:
- case FREG:
- case VREG:
- case GREG: {
- // \brief how many registers we found.
- std::size_t found_some_count = 0UL;
- std::size_t register_count = 0UL;
- std::string opcodeName = opcode_risc.name;
- std::size_t register_sum = 0;
-
- NumberCast64 num(opcode_risc.opcode);
-
- for (size_t line_index = 0UL; line_index < line.size();
- line_index++)
- {
- if (line[line_index] == kAsmRegisterPrefix[0] &&
- isdigit(line[line_index + 1]))
- {
- std::string register_syntax = kAsmRegisterPrefix;
- register_syntax += line[line_index + 1];
-
- if (isdigit(line[line_index + 2]))
- register_syntax += line[line_index + 2];
-
- std::string reg_str;
- reg_str += line[line_index + 1];
-
- if (isdigit(line[line_index + 2]))
- reg_str += line[line_index + 2];
-
- // it ranges from r0 to r19
- // something like r190 doesn't exist in the instruction set.
- if (isdigit(line[line_index + 3]) &&
- isdigit(line[line_index + 2]))
- {
- reg_str += line[line_index + 3];
- Detail::print_error(
- "invalid register index, r" + reg_str +
- "\nnote: The POWER accepts registers from r0 to r32.",
- file);
- throw std::runtime_error("invalid_register_index");
- }
-
- // finally cast to a size_t
- std::size_t reg_index = strtol(reg_str.c_str(), nullptr, 10);
-
- if (reg_index > kAsmRegisterLimit)
- {
- Detail::print_error("invalid register index, r" + reg_str,
- file);
- throw std::runtime_error("invalid_register_index");
- }
-
- if (opcodeName == "li")
- {
- char numIndex = 0;
-
- for (size_t i = 0; i != reg_index; i++)
- {
- numIndex += 0x20;
- }
-
- auto num = GetNumber32(line, reg_str);
-
- kBytes.push_back(num.number[0]);
- kBytes.push_back(num.number[1]);
- kBytes.push_back(numIndex);
- kBytes.push_back(0x38);
-
- // check if bigger than two.
- for (size_t i = 2; i < 4; i++)
- {
- if (num.number[i] > 0)
- {
- Detail::print_warning("number overflow on li operation.",
- file);
- break;
- }
- }
-
- break;
- }
-
- if ((opcodeName[0] == 's' && opcodeName[1] == 't'))
- {
- if (register_sum == 0)
- {
- for (size_t indexReg = 0UL; indexReg < reg_index;
- ++indexReg)
- {
- register_sum += 0x20;
- }
- }
- else
- {
- register_sum += reg_index;
- }
- }
-
- if (opcodeName == "mr")
- {
- switch (register_count)
- {
- case 0: {
- kBytes.push_back(0x78);
-
- char numIndex = 0x3;
-
- for (size_t i = 0; i != reg_index; i++)
- {
- numIndex += 0x8;
- }
-
- kBytes.push_back(numIndex);
-
- break;
- }
- case 1: {
- char numIndex = 0x1;
-
- for (size_t i = 0; i != reg_index; i++)
- {
- numIndex += 0x20;
- }
-
- for (size_t i = 0; i != reg_index; i++)
- {
- kBytes[kBytes.size() - 1] += 0x8;
- }
-
- kBytes[kBytes.size() - 1] -= 0x8;
-
- kBytes.push_back(numIndex);
-
- if (reg_index >= 10 && reg_index < 20)
- kBytes.push_back(0x7d);
- else if (reg_index >= 20 && reg_index < 30)
- kBytes.push_back(0x7e);
- else if (reg_index >= 30)
- kBytes.push_back(0x7f);
- else
- kBytes.push_back(0x7c);
-
- break;
- }
- default:
- break;
- }
-
- ++register_count;
- ++found_some_count;
- }
-
- if (opcodeName == "addi")
- {
- if (found_some_count == 2 || found_some_count == 0)
- kBytes.emplace_back(reg_index);
- else if (found_some_count == 1)
- kBytes.emplace_back(0x00);
-
- ++found_some_count;
-
- if (found_some_count > 3)
- {
- Detail::print_error("Too much registers. -> " + line, file);
- throw std::runtime_error("too_much_regs");
- }
- }
-
- if (opcodeName.find("cmp") != std::string::npos)
- {
- ++found_some_count;
-
- if (found_some_count > 3)
- {
- Detail::print_error("Too much registers. -> " + line, file);
- throw std::runtime_error("too_much_regs");
- }
- }
-
- if (opcodeName.find("mf") != std::string::npos ||
- opcodeName.find("mt") != std::string::npos)
- {
- char numIndex = 0;
-
- for (size_t i = 0; i != reg_index; i++)
- {
- numIndex += 0x20;
- }
-
- num.number[2] += numIndex;
-
- ++found_some_count;
-
- if (found_some_count > 1)
- {
- Detail::print_error("Too much registers. -> " + line, file);
- throw std::runtime_error("too_much_regs");
- }
-
- if (kVerbose)
- {
- kStdOut << "AssemblerPower: Found register: " << register_syntax
- << "\n";
- kStdOut << "AssemblerPower: Amount of registers in instruction: "
- << found_some_count << "\n";
- }
-
- if (reg_index >= 10 && reg_index < 20)
- num.number[3] = 0x7d;
- else if (reg_index >= 20 && reg_index < 30)
- num.number[3] = 0x7e;
- else if (reg_index >= 30)
- num.number[3] = 0x7f;
- else
- num.number[3] = 0x7c;
-
- for (auto ch : num.number)
- {
- kBytes.emplace_back(ch);
- }
- }
-
- found_registers_index.push_back(reg_index);
- }
- }
-
- if (opcodeName == "addi")
- {
- kBytes.emplace_back(0x38);
- }
-
- if (opcodeName.find("cmp") != std::string::npos)
- {
- char rightReg = 0x0;
-
- for (size_t i = 0; i != found_registers_index[1]; i++)
- {
- rightReg += 0x08;
- }
-
- kBytes.emplace_back(0x00);
- kBytes.emplace_back(rightReg);
- kBytes.emplace_back(found_registers_index[0]);
- kBytes.emplace_back(0x7c);
- }
-
- if ((opcodeName[0] == 's' && opcodeName[1] == 't'))
- {
- size_t offset = 0UL;
-
- if (line.find('+') != std::string::npos)
- {
- auto number = GetNumber32(line.substr(line.find("+")), "+");
- offset = number.raw;
- }
-
- kBytes.push_back(offset);
- kBytes.push_back(0x00);
- kBytes.push_back(register_sum);
-
- kBytes.emplace_back(0x90);
- }
-
- if (opcodeName == "mr")
- {
- if (register_count == 1)
- {
- Detail::print_error("Too few registers. -> " + line, file);
- throw std::runtime_error("too_few_registers");
- }
- }
-
- // we're not in immediate addressing, reg to reg.
- if (opcode_risc.ops->type != GREG)
- {
- // remember! register to register!
- if (found_some_count == 1)
- {
- Detail::print_error(
- "Unrecognized register found.\ntip: each AssemblerPower register "
- "starts with 'r'.\nline: " +
- line,
- file);
-
- throw std::runtime_error("not_a_register");
- }
- }
-
- if (found_some_count < 1 && name[0] != 'l' && name[0] != 's')
- {
- Detail::print_error(
- "invalid combination of opcode and registers.\nline: " + line,
- file);
- throw std::runtime_error("invalid_comb_op_reg");
- }
-
- break;
- }
- }
-
- kOrigin += cPowerIPAlignment;
- break;
- }
- }
-
- return true;
+bool LibCompiler::EncoderPowerPC::WriteLine(std::string& line, const std::string& file) {
+ if (LibCompiler::find_word(line, "public_segment")) return false;
+ if (!Detail::algorithm::is_valid_power64(line)) return false;
+
+ for (auto& opcode_risc : kOpcodesPowerPC) {
+ // strict check here
+ if (LibCompiler::find_word(line, opcode_risc.name)) {
+ std::string name(opcode_risc.name);
+ std::string jump_label, cpy_jump_label;
+ std::vector<size_t> found_registers_index;
+
+ // check funct7 type.
+ switch (opcode_risc.ops->type) {
+ default: {
+ NumberCast32 num(opcode_risc.opcode);
+
+ for (auto ch : num.number) {
+ kBytes.emplace_back(ch);
+ }
+ break;
+ }
+ case BADDR:
+ case PCREL: {
+ auto num = GetNumber32(line, name);
+
+ kBytes.emplace_back(num.number[0]);
+ kBytes.emplace_back(num.number[1]);
+ kBytes.emplace_back(num.number[2]);
+ kBytes.emplace_back(0x48);
+
+ break;
+ }
+ /// General purpose, float, vector operations. Everything that involve
+ /// registers.
+ case G0REG:
+ case FREG:
+ case VREG:
+ case GREG: {
+ // \brief how many registers we found.
+ std::size_t found_some_count = 0UL;
+ std::size_t register_count = 0UL;
+ std::string opcodeName = opcode_risc.name;
+ std::size_t register_sum = 0;
+
+ NumberCast64 num(opcode_risc.opcode);
+
+ for (size_t line_index = 0UL; line_index < line.size(); line_index++) {
+ if (line[line_index] == kAsmRegisterPrefix[0] && isdigit(line[line_index + 1])) {
+ std::string register_syntax = kAsmRegisterPrefix;
+ register_syntax += line[line_index + 1];
+
+ if (isdigit(line[line_index + 2])) register_syntax += line[line_index + 2];
+
+ std::string reg_str;
+ reg_str += line[line_index + 1];
+
+ if (isdigit(line[line_index + 2])) reg_str += line[line_index + 2];
+
+ // it ranges from r0 to r19
+ // something like r190 doesn't exist in the instruction set.
+ if (isdigit(line[line_index + 3]) && isdigit(line[line_index + 2])) {
+ reg_str += line[line_index + 3];
+ Detail::print_error("invalid register index, r" + reg_str +
+ "\nnote: The POWER accepts registers from r0 to r32.",
+ file);
+ throw std::runtime_error("invalid_register_index");
+ }
+
+ // finally cast to a size_t
+ std::size_t reg_index = strtol(reg_str.c_str(), nullptr, 10);
+
+ if (reg_index > kAsmRegisterLimit) {
+ Detail::print_error("invalid register index, r" + reg_str, file);
+ throw std::runtime_error("invalid_register_index");
+ }
+
+ if (opcodeName == "li") {
+ char numIndex = 0;
+
+ for (size_t i = 0; i != reg_index; i++) {
+ numIndex += 0x20;
+ }
+
+ auto num = GetNumber32(line, reg_str);
+
+ kBytes.push_back(num.number[0]);
+ kBytes.push_back(num.number[1]);
+ kBytes.push_back(numIndex);
+ kBytes.push_back(0x38);
+
+ // check if bigger than two.
+ for (size_t i = 2; i < 4; i++) {
+ if (num.number[i] > 0) {
+ Detail::print_warning("number overflow on li operation.", file);
+ break;
+ }
+ }
+
+ break;
+ }
+
+ if ((opcodeName[0] == 's' && opcodeName[1] == 't')) {
+ if (register_sum == 0) {
+ for (size_t indexReg = 0UL; indexReg < reg_index; ++indexReg) {
+ register_sum += 0x20;
+ }
+ } else {
+ register_sum += reg_index;
+ }
+ }
+
+ if (opcodeName == "mr") {
+ switch (register_count) {
+ case 0: {
+ kBytes.push_back(0x78);
+
+ char numIndex = 0x3;
+
+ for (size_t i = 0; i != reg_index; i++) {
+ numIndex += 0x8;
+ }
+
+ kBytes.push_back(numIndex);
+
+ break;
+ }
+ case 1: {
+ char numIndex = 0x1;
+
+ for (size_t i = 0; i != reg_index; i++) {
+ numIndex += 0x20;
+ }
+
+ for (size_t i = 0; i != reg_index; i++) {
+ kBytes[kBytes.size() - 1] += 0x8;
+ }
+
+ kBytes[kBytes.size() - 1] -= 0x8;
+
+ kBytes.push_back(numIndex);
+
+ if (reg_index >= 10 && reg_index < 20)
+ kBytes.push_back(0x7d);
+ else if (reg_index >= 20 && reg_index < 30)
+ kBytes.push_back(0x7e);
+ else if (reg_index >= 30)
+ kBytes.push_back(0x7f);
+ else
+ kBytes.push_back(0x7c);
+
+ break;
+ }
+ default:
+ break;
+ }
+
+ ++register_count;
+ ++found_some_count;
+ }
+
+ if (opcodeName == "addi") {
+ if (found_some_count == 2 || found_some_count == 0)
+ kBytes.emplace_back(reg_index);
+ else if (found_some_count == 1)
+ kBytes.emplace_back(0x00);
+
+ ++found_some_count;
+
+ if (found_some_count > 3) {
+ Detail::print_error("Too much registers. -> " + line, file);
+ throw std::runtime_error("too_much_regs");
+ }
+ }
+
+ if (opcodeName.find("cmp") != std::string::npos) {
+ ++found_some_count;
+
+ if (found_some_count > 3) {
+ Detail::print_error("Too much registers. -> " + line, file);
+ throw std::runtime_error("too_much_regs");
+ }
+ }
+
+ if (opcodeName.find("mf") != std::string::npos ||
+ opcodeName.find("mt") != std::string::npos) {
+ char numIndex = 0;
+
+ for (size_t i = 0; i != reg_index; i++) {
+ numIndex += 0x20;
+ }
+
+ num.number[2] += numIndex;
+
+ ++found_some_count;
+
+ if (found_some_count > 1) {
+ Detail::print_error("Too much registers. -> " + line, file);
+ throw std::runtime_error("too_much_regs");
+ }
+
+ if (kVerbose) {
+ kStdOut << "AssemblerPower: Found register: " << register_syntax << "\n";
+ kStdOut << "AssemblerPower: Amount of registers in instruction: "
+ << found_some_count << "\n";
+ }
+
+ if (reg_index >= 10 && reg_index < 20)
+ num.number[3] = 0x7d;
+ else if (reg_index >= 20 && reg_index < 30)
+ num.number[3] = 0x7e;
+ else if (reg_index >= 30)
+ num.number[3] = 0x7f;
+ else
+ num.number[3] = 0x7c;
+
+ for (auto ch : num.number) {
+ kBytes.emplace_back(ch);
+ }
+ }
+
+ found_registers_index.push_back(reg_index);
+ }
+ }
+
+ if (opcodeName == "addi") {
+ kBytes.emplace_back(0x38);
+ }
+
+ if (opcodeName.find("cmp") != std::string::npos) {
+ char rightReg = 0x0;
+
+ for (size_t i = 0; i != found_registers_index[1]; i++) {
+ rightReg += 0x08;
+ }
+
+ kBytes.emplace_back(0x00);
+ kBytes.emplace_back(rightReg);
+ kBytes.emplace_back(found_registers_index[0]);
+ kBytes.emplace_back(0x7c);
+ }
+
+ if ((opcodeName[0] == 's' && opcodeName[1] == 't')) {
+ size_t offset = 0UL;
+
+ if (line.find('+') != std::string::npos) {
+ auto number = GetNumber32(line.substr(line.find("+")), "+");
+ offset = number.raw;
+ }
+
+ kBytes.push_back(offset);
+ kBytes.push_back(0x00);
+ kBytes.push_back(register_sum);
+
+ kBytes.emplace_back(0x90);
+ }
+
+ if (opcodeName == "mr") {
+ if (register_count == 1) {
+ Detail::print_error("Too few registers. -> " + line, file);
+ throw std::runtime_error("too_few_registers");
+ }
+ }
+
+ // we're not in immediate addressing, reg to reg.
+ if (opcode_risc.ops->type != GREG) {
+ // remember! register to register!
+ if (found_some_count == 1) {
+ Detail::print_error(
+ "Unrecognized register found.\ntip: each AssemblerPower register "
+ "starts with 'r'.\nline: " +
+ line,
+ file);
+
+ throw std::runtime_error("not_a_register");
+ }
+ }
+
+ if (found_some_count < 1 && name[0] != 'l' && name[0] != 's') {
+ Detail::print_error("invalid combination of opcode and registers.\nline: " + line,
+ file);
+ throw std::runtime_error("invalid_comb_op_reg");
+ }
+
+ break;
+ }
+ }
+
+ kOrigin += cPowerIPAlignment;
+ break;
+ }
+ }
+
+ return true;
}
// Last rev 13-1-24
diff --git a/dev/LibCompiler/src/AssemblyFactory.cc b/dev/LibCompiler/src/AssemblyFactory.cc
index e70f279..4695c63 100644
--- a/dev/LibCompiler/src/AssemblyFactory.cc
+++ b/dev/LibCompiler/src/AssemblyFactory.cc
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
+ Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
------------------------------------------- */
@@ -23,37 +23,29 @@
//! @file Asm.cpp
//! @brief AssemblyKit source implementation.
-namespace LibCompiler
-{
- ///! @brief Compile for specific format (ELF, PEF, ZBIN)
- Int32 AssemblyFactory::Compile(std::string& sourceFile,
- const Int32& arch) noexcept
- {
- if (sourceFile.length() < 1 || !fMounted)
- return LIBCOMPILER_UNIMPLEMENTED;
-
- return fMounted->CompileToFormat(sourceFile, arch);
- }
-
- ///! @brief mount assembly backend.
- void AssemblyFactory::Mount(AssemblyInterface* mountPtr) noexcept
- {
- if (mountPtr)
- {
- fMounted = mountPtr;
- }
- }
-
- ///! @brief Unmount assembler.
- AssemblyInterface* AssemblyFactory::Unmount() noexcept
- {
- auto mount_prev = fMounted;
-
- if (mount_prev)
- {
- fMounted = nullptr;
- }
-
- return mount_prev;
- }
-} // namespace LibCompiler
+namespace LibCompiler {
+///! @brief Compile for specific format (ELF, PEF, ZBIN)
+Int32 AssemblyFactory::Compile(std::string& sourceFile, const Int32& arch) noexcept {
+ if (sourceFile.length() < 1 || !fMounted) return LIBCOMPILER_UNIMPLEMENTED;
+
+ return fMounted->CompileToFormat(sourceFile, arch);
+}
+
+///! @brief mount assembly backend.
+void AssemblyFactory::Mount(AssemblyInterface* mountPtr) noexcept {
+ if (mountPtr) {
+ fMounted = mountPtr;
+ }
+}
+
+///! @brief Unmount assembler.
+AssemblyInterface* AssemblyFactory::Unmount() noexcept {
+ auto mount_prev = fMounted;
+
+ if (mount_prev) {
+ fMounted = nullptr;
+ }
+
+ return mount_prev;
+}
+} // namespace LibCompiler
diff --git a/dev/LibCompiler/src/CCompiler64x0.cc b/dev/LibCompiler/src/CCompiler64x0.cc
index 89fc682..dea3ebd 100644
--- a/dev/LibCompiler/src/CCompiler64x0.cc
+++ b/dev/LibCompiler/src/CCompiler64x0.cc
@@ -41,7 +41,7 @@
#define kExitOK (0)
#define kBlank "\e[0;30m"
-#define kRed "\e[0;31m"
+#define kRed "\e[0;31m"
#define kWhite "\e[0;97m"
/////////////////////////////////////
@@ -50,63 +50,57 @@
/////////////////////////////////////
-namespace Detail
-{
- // \brief Register map structure, used to keep track of each variable's registers.
- struct CompilerRegisterMap final
- {
- std::string fName;
- std::string fReg;
- };
-
- // \brief Map for C structs
- // \author amlel
- struct CompilerStructMap final
- {
- // 'my_foo'
- std::string fName;
-
- // if instance: stores a valid register.
- std::string fReg;
-
- // offset count
- std::size_t fOffsetsCnt;
-
- // offset array.
- std::vector<std::pair<Int32, std::string>> fOffsets;
- };
-
- struct CompilerState final
- {
- std::vector<LibCompiler::SyntaxLeafList> fSyntaxTreeList;
- std::vector<CompilerRegisterMap> kStackFrame;
- std::vector<CompilerStructMap> kStructMap;
- LibCompiler::SyntaxLeafList* fSyntaxTree{nullptr};
- std::unique_ptr<std::ofstream> fOutputAssembly;
- std::string fLastFile;
- std::string fLastError;
- bool fVerbose;
- };
-} // namespace Detail
+namespace Detail {
+// \brief Register map structure, used to keep track of each variable's registers.
+struct CompilerRegisterMap final {
+ std::string fName;
+ std::string fReg;
+};
+
+// \brief Map for C structs
+// \author amlel
+struct CompilerStructMap final {
+ // 'my_foo'
+ std::string fName;
+
+ // if instance: stores a valid register.
+ std::string fReg;
+
+ // offset count
+ std::size_t fOffsetsCnt;
+
+ // offset array.
+ std::vector<std::pair<Int32, std::string>> fOffsets;
+};
+
+struct CompilerState final {
+ std::vector<LibCompiler::SyntaxLeafList> fSyntaxTreeList;
+ std::vector<CompilerRegisterMap> kStackFrame;
+ std::vector<CompilerStructMap> kStructMap;
+ LibCompiler::SyntaxLeafList* fSyntaxTree{nullptr};
+ std::unique_ptr<std::ofstream> fOutputAssembly;
+ std::string fLastFile;
+ std::string fLastError;
+ bool fVerbose;
+};
+} // namespace Detail
static Detail::CompilerState kState;
-static SizeType kErrorLimit = 100;
-static std::string kIfFunction = "";
-static Int32 kAcceptableErrors = 0;
-
-namespace Detail
-{
- /// @brief prints an error into stdout.
- /// @param reason the reason of the error.
- /// @param file where does it originate from?
- void print_error(std::string reason, std::string file) noexcept;
-
- struct CompilerType final
- {
- std::string fName;
- std::string fValue;
- };
-} // namespace Detail
+static SizeType kErrorLimit = 100;
+static std::string kIfFunction = "";
+static Int32 kAcceptableErrors = 0;
+
+namespace Detail {
+/// @brief prints an error into stdout.
+/// @param reason the reason of the error.
+/// @param file where does it originate from?
+void print_error(std::string reason, std::string file) noexcept;
+
+struct CompilerType final {
+ std::string fName;
+ std::string fValue;
+};
+} // namespace Detail
/////////////////////////////////////////////////////////////////////////////////////////
@@ -119,11 +113,11 @@ static int kMachine = 0;
/////////////////////////////////////////
-static size_t kRegisterCnt = kAsmRegisterLimit;
-static size_t kStartUsable = 2;
-static size_t kUsableLimit = 15;
-static size_t kRegisterCounter = kStartUsable;
-static std::string kRegisterPrefix = kAsmRegisterPrefix;
+static size_t kRegisterCnt = kAsmRegisterLimit;
+static size_t kStartUsable = 2;
+static size_t kUsableLimit = 15;
+static size_t kRegisterCounter = kStartUsable;
+static std::string kRegisterPrefix = kAsmRegisterPrefix;
/////////////////////////////////////////
@@ -131,67 +125,56 @@ static std::string kRegisterPrefix = kAsmRegisterPrefix;
/////////////////////////////////////////
-static std::vector<std::string> kFileList;
+static std::vector<std::string> kFileList;
static LibCompiler::AssemblyFactory kFactory;
-static bool kInStruct = false;
-static bool kOnWhileLoop = false;
-static bool kOnForLoop = false;
-static bool kInBraces = false;
-static bool kIfFound = false;
-static size_t kBracesCount = 0UL;
+static bool kInStruct = false;
+static bool kOnWhileLoop = false;
+static bool kOnForLoop = false;
+static bool kInBraces = false;
+static bool kIfFound = false;
+static size_t kBracesCount = 0UL;
/* @brief C compiler backend for C */
-class CompilerFrontend64x0 final : public LibCompiler::ICompilerFrontend
-{
-public:
- explicit CompilerFrontend64x0() = default;
- ~CompilerFrontend64x0() override = default;
+class CompilerFrontend64x0 final : public LibCompiler::ICompilerFrontend {
+ public:
+ explicit CompilerFrontend64x0() = default;
+ ~CompilerFrontend64x0() override = default;
- LIBCOMPILER_COPY_DEFAULT(CompilerFrontend64x0);
+ LIBCOMPILER_COPY_DEFAULT(CompilerFrontend64x0);
- std::string Check(const char* text, const char* file);
- bool Compile(std::string text, const std::string file) override;
+ std::string Check(const char* text, const char* file);
+ bool Compile(std::string text, const std::string file) override;
- const char* Language() override
- {
- return "64k C";
- }
+ const char* Language() override { return "64k C"; }
};
-static CompilerFrontend64x0* kCompilerFrontend = nullptr;
+static CompilerFrontend64x0* kCompilerFrontend = nullptr;
static std::vector<Detail::CompilerType> kCompilerVariables;
-static std::vector<std::string> kCompilerFunctions;
+static std::vector<std::string> kCompilerFunctions;
static std::vector<Detail::CompilerType> kCompilerTypes;
-namespace Detail
-{
- union number_cast final {
- public:
- number_cast(UInt64 _Raw)
- : _Raw(_Raw)
- {
- }
-
- public:
- char _Num[8];
- UInt64 _Raw;
- };
-
- union double_cast final {
- public:
- double_cast(float _Raw)
- : _Raw(_Raw)
- {
- }
-
- public:
- char _Sign;
- char _Lh[8];
- char _Rh[23];
-
- float _Raw;
- };
-} // namespace Detail
+namespace Detail {
+union number_cast final {
+ public:
+ number_cast(UInt64 _Raw) : _Raw(_Raw) {}
+
+ public:
+ char _Num[8];
+ UInt64 _Raw;
+};
+
+union double_cast final {
+ public:
+ double_cast(float _Raw) : _Raw(_Raw) {}
+
+ public:
+ char _Sign;
+ char _Lh[8];
+ char _Rh[23];
+
+ float _Raw;
+};
+} // namespace Detail
/////////////////////////////////////////////////////////////////////////////////////////
@@ -200,1090 +183,858 @@ namespace Detail
/////////////////////////////////////////////////////////////////////////////////////////
-bool CompilerFrontend64x0::Compile(std::string text_, const std::string file)
-{
- std::string text = text_;
-
- bool typeFound = false;
- bool fnFound = false;
-
- // setup generator.
- std::random_device rd;
-
- auto seed_data = std::array<int, std::mt19937::state_size>{};
- std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd));
- std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
- std::mt19937 generator(seq);
-
- // start parsing
- for (size_t text_index = 0; text_index < text.size(); ++text_index)
- {
- auto syntaxLeaf = LibCompiler::SyntaxLeafList::SyntaxLeaf();
-
- auto gen = uuids::uuid_random_generator{generator};
- uuids::uuid out = gen();
-
- Detail::number_cast time_off = (UInt64)out.as_bytes().data();
-
- if (!typeFound)
- {
- auto substr = text.substr(text_index);
- std::string match_type;
-
- for (size_t y = 0; y < substr.size(); ++y)
- {
- if (substr[y] == ' ')
- {
- while (match_type.find(' ') != std::string::npos)
- {
- match_type.erase(match_type.find(' '));
- }
-
- for (auto& clType : kCompilerTypes)
- {
- if (clType.fName == match_type)
- {
- match_type.clear();
-
- std::string buf;
-
- buf += clType.fValue;
- buf += ' ';
+bool CompilerFrontend64x0::Compile(std::string text_, const std::string file) {
+ std::string text = text_;
+
+ bool typeFound = false;
+ bool fnFound = false;
+
+ // setup generator.
+ std::random_device rd;
+
+ auto seed_data = std::array<int, std::mt19937::state_size>{};
+ std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd));
+ std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
+ std::mt19937 generator(seq);
+
+ // start parsing
+ for (size_t text_index = 0; text_index < text.size(); ++text_index) {
+ auto syntaxLeaf = LibCompiler::SyntaxLeafList::SyntaxLeaf();
+
+ auto gen = uuids::uuid_random_generator{generator};
+ uuids::uuid out = gen();
+
+ Detail::number_cast time_off = (UInt64) out.as_bytes().data();
+
+ if (!typeFound) {
+ auto substr = text.substr(text_index);
+ std::string match_type;
+
+ for (size_t y = 0; y < substr.size(); ++y) {
+ if (substr[y] == ' ') {
+ while (match_type.find(' ') != std::string::npos) {
+ match_type.erase(match_type.find(' '));
+ }
+
+ for (auto& clType : kCompilerTypes) {
+ if (clType.fName == match_type) {
+ match_type.clear();
+
+ std::string buf;
+
+ buf += clType.fValue;
+ buf += ' ';
+
+ if (substr.find('=') != std::string::npos) {
+ break;
+ }
+
+ if (text.find('(') != std::string::npos) {
+ syntaxLeaf.fUserValue = buf;
+
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+ }
+
+ typeFound = true;
+ break;
+ }
+ }
+
+ break;
+ }
+
+ match_type += substr[y];
+ }
+ }
+
+ if (text[text_index] == '{') {
+ if (kInStruct) {
+ continue;
+ }
+
+ kInBraces = true;
+ ++kBracesCount;
+
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+ }
+
+ // return keyword handler
+ if (text[text_index] == 'r') {
+ std::string return_keyword;
+ return_keyword += "return";
+
+ std::size_t index = 0UL;
+
+ std::string value;
+
+ for (size_t return_index = text_index; return_index < text.size(); ++return_index) {
+ if (text[return_index] != return_keyword[index]) {
+ for (size_t value_index = return_index; value_index < text.size(); ++value_index) {
+ if (text[value_index] == ';') break;
+
+ value += text[value_index];
+ }
+
+ break;
+ }
+
+ ++index;
+ }
+
+ if (index == return_keyword.size()) {
+ if (!value.empty()) {
+ if (value.find('(') != std::string::npos) {
+ value.erase(value.find('('));
+ }
+
+ if (!isdigit(value[value.find('(') + 2])) {
+ std::string tmp = value;
+ bool reg_to_reg = false;
+
+ value.clear();
+
+ value += " extern_segment";
+ value += tmp;
+ }
+
+ syntaxLeaf.fUserValue = "\tldw r19, ";
+
+ // make it pretty.
+ if (value.find('\t') != std::string::npos) value.erase(value.find('\t'), 1);
+
+ syntaxLeaf.fUserValue += value + "\n";
+ }
+
+ syntaxLeaf.fUserValue += "\tjlr";
+
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+
+ break;
+ }
+ }
+
+ if (text[text_index] == 'i' && text[text_index + 1] == 'f') {
+ auto expr = text.substr(text_index + 2);
+ text.erase(text_index, 2);
+
+ if (expr.find("{") != std::string::npos) {
+ expr.erase(expr.find("{"));
+ }
+
+ if (expr.find("(") != std::string::npos) expr.erase(expr.find("("));
+
+ if (expr.find(")") != std::string::npos) expr.erase(expr.find(")"));
+
+ kIfFunction = "__LIBCOMPILER_IF_PROC_";
+ kIfFunction += std::to_string(time_off._Raw);
+
+ syntaxLeaf.fUserValue = "\tlda r12, extern_segment ";
+ syntaxLeaf.fUserValue += kIfFunction +
+ "\n\t#r12 = Code to jump on, r11 right cond, r10 left cond.\n\tbeq "
+ "r10, r11, r12\ndword public_segment .code64 " +
+ kIfFunction + "\n";
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+
+ kIfFound = true;
+ }
+
+ // Parse expressions and instructions here.
+ // what does this mean?
+ // we encounter an assignment, or we reached the end of an expression.
+ if (text[text_index] == '=' || text[text_index] == ';') {
+ if (fnFound) continue;
+ if (kIfFound) continue;
+
+ if (text[text_index] == ';' && kInStruct) continue;
+
+ if (text.find("typedef ") != std::string::npos) continue;
+
+ if (text[text_index] == '=' && kInStruct) {
+ Detail::print_error("assignement of value in struct " + text, file);
+ continue;
+ }
+
+ if (text[text_index] == ';' && kInStruct) {
+ bool space_found_ = false;
+ std::string sym;
+
+ for (auto& ch : text) {
+ if (ch == ' ') {
+ space_found_ = true;
+ }
+
+ if (ch == ';') break;
+
+ if (space_found_) sym.push_back(ch);
+ }
+
+ kState.kStructMap[kState.kStructMap.size() - 1].fOffsets.push_back(
+ std::make_pair(kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4, sym));
+
+ kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt =
+ kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4;
+
+ continue;
+ }
+
+ if (text[text_index] == '=' && kInStruct) {
+ continue;
+ }
+
+ if (text[text_index + 1] == '=' || text[text_index - 1] == '!' ||
+ text[text_index - 1] == '<' || text[text_index - 1] == '>') {
+ continue;
+ }
+
+ std::string substr;
+
+ if (text.find('=') != std::string::npos && kInBraces && !kIfFound) {
+ if (text.find("*") != std::string::npos) {
+ if (text.find("=") > text.find("*"))
+ substr += "\tlda ";
+ else
+ substr += "\tldw ";
+ } else {
+ substr += "\tldw ";
+ }
+ } else if (text.find('=') != std::string::npos && !kInBraces) {
+ substr += "stw public_segment .data64 ";
+ }
+
+ int first_encountered = 0;
+
+ std::string str_name;
+
+ for (size_t text_index_2 = 0; text_index_2 < text.size(); ++text_index_2) {
+ if (text[text_index_2] == '\"') {
+ ++text_index_2;
+
+ // want to add this, so that the parser recognizes that this is a
+ // string.
+ substr += '"';
+
+ for (; text_index_2 < text.size(); ++text_index_2) {
+ if (text[text_index_2] == '\"') break;
+
+ substr += text[text_index_2];
+ }
+ }
+
+ if (text[text_index_2] == '{' || text[text_index_2] == '}') continue;
+
+ if (text[text_index_2] == ';') {
+ break;
+ }
+
+ if (text[text_index_2] == ' ' || text[text_index_2] == '\t') {
+ if (first_encountered != 2) {
+ if (text[text_index] != '=' &&
+ substr.find("public_segment .data64") == std::string::npos && !kInStruct)
+ substr += "public_segment .data64 ";
+ }
+
+ ++first_encountered;
+
+ continue;
+ }
- if (substr.find('=') != std::string::npos)
- {
- break;
- }
+ if (text[text_index_2] == '=') {
+ if (!kInBraces) {
+ substr.replace(substr.find("public_segment .data64"), strlen("public_segment .data64"),
+ "public_segment .zero64 ");
+ }
- if (text.find('(') != std::string::npos)
- {
- syntaxLeaf.fUserValue = buf;
+ substr += ",";
+ continue;
+ }
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
- }
+ substr += text[text_index_2];
+ }
- typeFound = true;
- break;
- }
- }
+ for (auto& clType : kCompilerTypes) {
+ if (substr.find(clType.fName) != std::string::npos) {
+ if (substr.find(clType.fName) > substr.find('"')) continue;
- break;
- }
+ substr.erase(substr.find(clType.fName), clType.fName.size());
+ } else if (substr.find(clType.fValue) != std::string::npos) {
+ if (substr.find(clType.fValue) > substr.find('"')) continue;
- match_type += substr[y];
- }
- }
+ if (clType.fName == "const") continue;
- if (text[text_index] == '{')
- {
- if (kInStruct)
- {
- continue;
- }
+ substr.erase(substr.find(clType.fValue), clType.fValue.size());
+ }
+ }
- kInBraces = true;
- ++kBracesCount;
+ if (substr.find("extern") != std::string::npos) {
+ substr.replace(substr.find("extern"), strlen("extern"), "extern_segment ");
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
- }
-
- // return keyword handler
- if (text[text_index] == 'r')
- {
- std::string return_keyword;
- return_keyword += "return";
-
- std::size_t index = 0UL;
-
- std::string value;
-
- for (size_t return_index = text_index; return_index < text.size();
- ++return_index)
- {
- if (text[return_index] != return_keyword[index])
- {
- for (size_t value_index = return_index;
- value_index < text.size(); ++value_index)
- {
- if (text[value_index] == ';')
- break;
-
- value += text[value_index];
- }
-
- break;
- }
-
- ++index;
- }
-
- if (index == return_keyword.size())
- {
- if (!value.empty())
- {
- if (value.find('(') != std::string::npos)
- {
- value.erase(value.find('('));
- }
-
- if (!isdigit(value[value.find('(') + 2]))
- {
- std::string tmp = value;
- bool reg_to_reg = false;
-
- value.clear();
-
- value += " extern_segment";
- value += tmp;
- }
-
- syntaxLeaf.fUserValue = "\tldw r19, ";
-
- // make it pretty.
- if (value.find('\t') != std::string::npos)
- value.erase(value.find('\t'), 1);
-
- syntaxLeaf.fUserValue += value + "\n";
- }
-
- syntaxLeaf.fUserValue += "\tjlr";
-
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
-
- break;
- }
- }
-
- if (text[text_index] == 'i' && text[text_index + 1] == 'f')
- {
- auto expr = text.substr(text_index + 2);
- text.erase(text_index, 2);
-
- if (expr.find("{") != std::string::npos)
- {
- expr.erase(expr.find("{"));
- }
-
- if (expr.find("(") != std::string::npos)
- expr.erase(expr.find("("));
-
- if (expr.find(")") != std::string::npos)
- expr.erase(expr.find(")"));
-
- kIfFunction = "__LIBCOMPILER_IF_PROC_";
- kIfFunction += std::to_string(time_off._Raw);
-
- syntaxLeaf.fUserValue = "\tlda r12, extern_segment ";
- syntaxLeaf.fUserValue +=
- kIfFunction +
- "\n\t#r12 = Code to jump on, r11 right cond, r10 left cond.\n\tbeq "
- "r10, r11, r12\ndword public_segment .code64 " +
- kIfFunction + "\n";
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
-
- kIfFound = true;
- }
-
- // Parse expressions and instructions here.
- // what does this mean?
- // we encounter an assignment, or we reached the end of an expression.
- if (text[text_index] == '=' || text[text_index] == ';')
- {
- if (fnFound)
- continue;
- if (kIfFound)
- continue;
-
- if (text[text_index] == ';' && kInStruct)
- continue;
-
- if (text.find("typedef ") != std::string::npos)
- continue;
-
- if (text[text_index] == '=' && kInStruct)
- {
- Detail::print_error("assignement of value in struct " + text,
- file);
- continue;
- }
-
- if (text[text_index] == ';' && kInStruct)
- {
- bool space_found_ = false;
- std::string sym;
-
- for (auto& ch : text)
- {
- if (ch == ' ')
- {
- space_found_ = true;
- }
-
- if (ch == ';')
- break;
-
- if (space_found_)
- sym.push_back(ch);
- }
-
- kState.kStructMap[kState.kStructMap.size() - 1].fOffsets.push_back(
- std::make_pair(
- kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4,
- sym));
-
- kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt =
- kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4;
-
- continue;
- }
-
- if (text[text_index] == '=' && kInStruct)
- {
- continue;
- }
-
- if (text[text_index + 1] == '=' ||
- text[text_index - 1] == '!' ||
- text[text_index - 1] == '<' ||
- text[text_index - 1] == '>')
- {
- continue;
- }
-
- std::string substr;
-
- if (text.find('=') != std::string::npos && kInBraces && !kIfFound)
- {
- if (text.find("*") != std::string::npos)
- {
- if (text.find("=") > text.find("*"))
- substr += "\tlda ";
- else
- substr += "\tldw ";
- }
- else
- {
- substr += "\tldw ";
- }
- }
- else if (text.find('=') != std::string::npos && !kInBraces)
- {
- substr += "stw public_segment .data64 ";
- }
-
- int first_encountered = 0;
-
- std::string str_name;
-
- for (size_t text_index_2 = 0; text_index_2 < text.size();
- ++text_index_2)
- {
- if (text[text_index_2] == '\"')
- {
- ++text_index_2;
-
- // want to add this, so that the parser recognizes that this is a
- // string.
- substr += '"';
-
- for (; text_index_2 < text.size(); ++text_index_2)
- {
- if (text[text_index_2] == '\"')
- break;
-
- substr += text[text_index_2];
- }
- }
-
- if (text[text_index_2] == '{' || text[text_index_2] == '}')
- continue;
-
- if (text[text_index_2] == ';')
- {
- break;
- }
-
- if (text[text_index_2] == ' ' ||
- text[text_index_2] == '\t')
- {
- if (first_encountered != 2)
- {
- if (text[text_index] != '=' &&
- substr.find("public_segment .data64") == std::string::npos &&
- !kInStruct)
- substr += "public_segment .data64 ";
- }
-
- ++first_encountered;
-
- continue;
- }
-
- if (text[text_index_2] == '=')
- {
- if (!kInBraces)
- {
- substr.replace(substr.find("public_segment .data64"),
- strlen("public_segment .data64"), "public_segment .zero64 ");
- }
-
- substr += ",";
- continue;
- }
-
- substr += text[text_index_2];
- }
-
- for (auto& clType : kCompilerTypes)
- {
- if (substr.find(clType.fName) != std::string::npos)
- {
- if (substr.find(clType.fName) > substr.find('"'))
- continue;
-
- substr.erase(substr.find(clType.fName), clType.fName.size());
- }
- else if (substr.find(clType.fValue) != std::string::npos)
- {
- if (substr.find(clType.fValue) > substr.find('"'))
- continue;
-
- if (clType.fName == "const")
- continue;
-
- substr.erase(substr.find(clType.fValue), clType.fValue.size());
- }
- }
-
- if (substr.find("extern") != std::string::npos)
- {
- substr.replace(substr.find("extern"), strlen("extern"), "extern_segment ");
-
- if (substr.find("public_segment .data64") != std::string::npos)
- substr.erase(substr.find("public_segment .data64"), strlen("public_segment .data64"));
- }
-
- auto var_to_find =
- std::find_if(kCompilerVariables.cbegin(), kCompilerVariables.cend(),
- [&](Detail::CompilerType type) {
- return type.fName.find(substr) != std::string::npos;
- });
-
- if (kRegisterCounter == 5 || kRegisterCounter == 6)
- ++kRegisterCounter;
-
- std::string reg = kAsmRegisterPrefix;
- reg += std::to_string(kRegisterCounter);
-
- if (var_to_find == kCompilerVariables.cend())
- {
- ++kRegisterCounter;
-
- kState.kStackFrame.push_back({.fName = substr, .fReg = reg});
- kCompilerVariables.push_back({.fName = substr});
- }
-
- syntaxLeaf.fUserValue += substr;
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
-
- if (text[text_index] == '=')
- break;
- }
-
- // function handler.
-
- if (text[text_index] == '(' && !fnFound && !kIfFound)
- {
- std::string substr;
- std::string args_buffer;
- std::string args;
-
- bool type_crossed = false;
-
- for (size_t idx = text.find('(') + 1; idx < text.size();
- ++idx)
- {
- if (text[idx] == ',')
- continue;
-
- if (text[idx] == ' ')
- continue;
-
- if (text[idx] == ')')
- break;
- }
-
- for (char substr_first_index : text)
- {
- if (substr_first_index != ',')
- args_buffer += substr_first_index;
- else
- args_buffer += '$';
-
- if (substr_first_index == ';')
- {
- args_buffer = args_buffer.erase(0, args_buffer.find('('));
- args_buffer = args_buffer.erase(args_buffer.find(';'), 1);
- args_buffer = args_buffer.erase(args_buffer.find(')'), 1);
- args_buffer = args_buffer.erase(args_buffer.find('('), 1);
+ if (substr.find("public_segment .data64") != std::string::npos)
+ substr.erase(substr.find("public_segment .data64"), strlen("public_segment .data64"));
+ }
- if (!args_buffer.empty())
- args += "\tldw r6, ";
+ auto var_to_find = std::find_if(
+ kCompilerVariables.cbegin(), kCompilerVariables.cend(),
+ [&](Detail::CompilerType type) { return type.fName.find(substr) != std::string::npos; });
- std::string register_type;
- std::size_t index = 7UL;
+ if (kRegisterCounter == 5 || kRegisterCounter == 6) ++kRegisterCounter;
- while (args_buffer.find("$") != std::string::npos)
- {
- register_type = kRegisterPrefix;
- register_type += std::to_string(index);
+ std::string reg = kAsmRegisterPrefix;
+ reg += std::to_string(kRegisterCounter);
- ++index;
+ if (var_to_find == kCompilerVariables.cend()) {
+ ++kRegisterCounter;
- args_buffer.replace(args_buffer.find('$'), 1,
- "\n\tldw " + register_type + ",");
- }
+ kState.kStackFrame.push_back({.fName = substr, .fReg = reg});
+ kCompilerVariables.push_back({.fName = substr});
+ }
- args += args_buffer;
- args += "\n\tlda r19, ";
- }
- }
+ syntaxLeaf.fUserValue += substr;
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
- for (char _text_i : text)
- {
- if (_text_i == '\t' || _text_i == ' ')
- {
- if (!type_crossed)
- {
- substr.clear();
- type_crossed = true;
- }
+ if (text[text_index] == '=') break;
+ }
- continue;
- }
+ // function handler.
- if (_text_i == '(')
- break;
+ if (text[text_index] == '(' && !fnFound && !kIfFound) {
+ std::string substr;
+ std::string args_buffer;
+ std::string args;
- substr += _text_i;
- }
+ bool type_crossed = false;
- if (kInBraces)
- {
- syntaxLeaf.fUserValue = args;
- syntaxLeaf.fUserValue += substr;
- syntaxLeaf.fUserValue += "\n\tjrl\n";
+ for (size_t idx = text.find('(') + 1; idx < text.size(); ++idx) {
+ if (text[idx] == ',') continue;
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+ if (text[idx] == ' ') continue;
- fnFound = true;
- }
- else
- {
- syntaxLeaf.fUserValue.clear();
+ if (text[idx] == ')') break;
+ }
- syntaxLeaf.fUserValue += "public_segment .code64 ";
+ for (char substr_first_index : text) {
+ if (substr_first_index != ',')
+ args_buffer += substr_first_index;
+ else
+ args_buffer += '$';
- syntaxLeaf.fUserValue += substr;
- syntaxLeaf.fUserValue += "\n";
+ if (substr_first_index == ';') {
+ args_buffer = args_buffer.erase(0, args_buffer.find('('));
+ args_buffer = args_buffer.erase(args_buffer.find(';'), 1);
+ args_buffer = args_buffer.erase(args_buffer.find(')'), 1);
+ args_buffer = args_buffer.erase(args_buffer.find('('), 1);
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+ if (!args_buffer.empty()) args += "\tldw r6, ";
- fnFound = true;
- }
+ std::string register_type;
+ std::size_t index = 7UL;
- kCompilerFunctions.push_back(text);
- }
+ while (args_buffer.find("$") != std::string::npos) {
+ register_type = kRegisterPrefix;
+ register_type += std::to_string(index);
- if (text[text_index] == '-' && text[text_index + 1] == '-')
- {
- text = text.replace(text.find("--"), strlen("--"), "");
+ ++index;
- for (int _text_i = 0; _text_i < text.size(); ++_text_i)
- {
- if (text[_text_i] == '\t' || text[_text_i] == ' ')
- text.erase(_text_i, 1);
- }
+ args_buffer.replace(args_buffer.find('$'), 1, "\n\tldw " + register_type + ",");
+ }
- syntaxLeaf.fUserValue += "sub ";
- syntaxLeaf.fUserValue += text;
+ args += args_buffer;
+ args += "\n\tlda r19, ";
+ }
+ }
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
- break;
- }
+ for (char _text_i : text) {
+ if (_text_i == '\t' || _text_i == ' ') {
+ if (!type_crossed) {
+ substr.clear();
+ type_crossed = true;
+ }
- if (text[text_index] == '}')
- {
- kRegisterCounter = kStartUsable;
+ continue;
+ }
- --kBracesCount;
+ if (_text_i == '(') break;
- if (kBracesCount < 1)
- {
- kInBraces = false;
- kBracesCount = 0;
- }
+ substr += _text_i;
+ }
- if (kIfFound)
- kIfFound = false;
+ if (kInBraces) {
+ syntaxLeaf.fUserValue = args;
+ syntaxLeaf.fUserValue += substr;
+ syntaxLeaf.fUserValue += "\n\tjrl\n";
- if (kInStruct)
- kInStruct = false;
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
- }
+ fnFound = true;
+ } else {
+ syntaxLeaf.fUserValue.clear();
- syntaxLeaf.fUserValue.clear();
- }
+ syntaxLeaf.fUserValue += "public_segment .code64 ";
- auto syntaxLeaf = LibCompiler::SyntaxLeafList::SyntaxLeaf();
- syntaxLeaf.fUserValue = "\n";
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+ syntaxLeaf.fUserValue += substr;
+ syntaxLeaf.fUserValue += "\n";
- return true;
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+
+ fnFound = true;
+ }
+
+ kCompilerFunctions.push_back(text);
+ }
+
+ if (text[text_index] == '-' && text[text_index + 1] == '-') {
+ text = text.replace(text.find("--"), strlen("--"), "");
+
+ for (int _text_i = 0; _text_i < text.size(); ++_text_i) {
+ if (text[_text_i] == '\t' || text[_text_i] == ' ') text.erase(_text_i, 1);
+ }
+
+ syntaxLeaf.fUserValue += "sub ";
+ syntaxLeaf.fUserValue += text;
+
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+ break;
+ }
+
+ if (text[text_index] == '}') {
+ kRegisterCounter = kStartUsable;
+
+ --kBracesCount;
+
+ if (kBracesCount < 1) {
+ kInBraces = false;
+ kBracesCount = 0;
+ }
+
+ if (kIfFound) kIfFound = false;
+
+ if (kInStruct) kInStruct = false;
+
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+ }
+
+ syntaxLeaf.fUserValue.clear();
+ }
+
+ auto syntaxLeaf = LibCompiler::SyntaxLeafList::SyntaxLeaf();
+ syntaxLeaf.fUserValue = "\n";
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+
+ return true;
}
-static bool kShouldHaveBraces = false;
+static bool kShouldHaveBraces = false;
static std::string kFnName;
-std::string CompilerFrontend64x0::Check(const char* text, const char* file)
-{
- std::string err_str;
- std::string ln = text;
-
- if (ln.empty())
- {
- return err_str;
- }
-
- bool non_ascii_found = false;
-
- for (int i = 0; i < ln.size(); ++i)
- {
- if (isalnum(ln[i]))
- {
- non_ascii_found = true;
- break;
- }
- }
-
- if (kShouldHaveBraces && ln.find('{') != std::string::npos)
- {
- kShouldHaveBraces = false;
- }
-
- if (!non_ascii_found)
- return err_str;
-
- size_t string_index = 1UL;
-
- if (ln.find('\'') != std::string::npos)
- {
- string_index = ln.find('\'') + 1;
-
- for (; string_index < ln.size(); ++string_index)
- {
- if (ln[string_index] == '\'')
- {
- if (ln[string_index + 1] != ';')
- {
- ln.erase(string_index, 1);
- }
-
- return err_str;
- }
- }
- }
- else if (ln.find('"') != std::string::npos)
- {
- string_index = ln.find('"') + 1;
-
- for (; string_index < ln.size(); ++string_index)
- {
- if (ln[string_index] == '"')
- {
- if (ln[string_index + 1] != ';')
- {
- ln.erase(string_index, 1);
- }
- else
- {
- break;
- }
- }
- }
- }
- else if (ln.find('"') == std::string::npos &&
- ln.find('\'') == std::string::npos)
- {
- std::vector<std::string> forbidden_words;
-
- forbidden_words.push_back("\\");
- forbidden_words.push_back("?");
- forbidden_words.push_back("@");
- forbidden_words.push_back("~");
- forbidden_words.push_back("::");
- forbidden_words.push_back("--*");
- forbidden_words.push_back("*/");
-
- // add them to avoid stupid mistakes.
- forbidden_words.push_back("namespace");
- forbidden_words.push_back("class");
- forbidden_words.push_back("extern \"C\"");
-
- for (auto& forbidden : forbidden_words)
- {
- if (ln.find(forbidden) != std::string::npos)
- {
- err_str += "\nForbidden character detected: ";
- err_str += forbidden;
-
- return err_str;
- }
- }
- }
-
- struct CompilerVariableRange final
- {
- std::string fBegin;
- std::string fEnd;
- };
-
- const std::vector<CompilerVariableRange> variables_list = {
- {.fBegin = "static ", .fEnd = "="},
- {.fBegin = "=", .fEnd = ";"},
- {.fBegin = "if(", .fEnd = "="},
- {.fBegin = "if (", .fEnd = "="},
- {.fBegin = "if(", .fEnd = "<"},
- {.fBegin = "if (", .fEnd = "<"},
- {.fBegin = "if(", .fEnd = ">"},
- {.fBegin = "if (", .fEnd = ">"},
- {.fBegin = "if(", .fEnd = ")"},
- {.fBegin = "if (", .fEnd = ")"},
-
- {.fBegin = "else(", .fEnd = "="},
- {.fBegin = "else (", .fEnd = "="},
- {.fBegin = "else(", .fEnd = "<"},
- {.fBegin = "else (", .fEnd = "<"},
- {.fBegin = "else(", .fEnd = ">"},
- {.fBegin = "else (", .fEnd = ">"},
- {.fBegin = "else(", .fEnd = ")"},
- {.fBegin = "else (", .fEnd = ")"},
- };
-
- for (auto& variable : variables_list)
- {
- if (ln.find(variable.fBegin) != std::string::npos)
- {
- string_index = ln.find(variable.fBegin) + variable.fBegin.size();
-
- while (ln[string_index] == ' ')
- ++string_index;
-
- std::string keyword;
-
- for (; string_index < ln.size(); ++string_index)
- {
- if (ln[string_index] == variable.fEnd[0])
- {
- std::string varname = "";
-
- for (size_t index_keyword = ln.find(' ');
- ln[index_keyword] != variable.fBegin[0]; ++index_keyword)
- {
- if (ln[index_keyword] == ' ')
- {
- continue;
- }
-
- if (isdigit(ln[index_keyword]))
- {
- goto cc_next_loop;
- }
-
- varname += ln[index_keyword];
- }
-
- if (varname.find(' ') != std::string::npos)
- {
- varname.erase(0, varname.find(' '));
-
- if (variable.fBegin == "extern")
- {
- varname.erase(0, varname.find(' '));
- }
- }
-
- if (kRegisterCounter == 5 || kRegisterCounter == 6)
- ++kRegisterCounter;
-
- std::string reg = kAsmRegisterPrefix;
- reg += std::to_string(kRegisterCounter);
-
- kCompilerVariables.push_back({.fValue = varname});
- goto cc_check_done;
- }
-
- keyword.push_back(ln[string_index]);
- }
-
- goto cc_next_loop;
-
- cc_check_done:
-
- // skip digit value.
- if (isdigit(keyword[0]) || keyword[0] == '"')
- {
- goto cc_next_loop;
- }
-
- while (keyword.find(' ') != std::string::npos)
- keyword.erase(keyword.find(' '), 1);
-
- for (auto& var : kCompilerVariables)
- {
- if (var.fValue.find(keyword) != std::string::npos)
- {
- err_str.clear();
- goto cc_next;
- }
- }
-
- for (auto& fn : kCompilerFunctions)
- {
- if (fn.find(keyword[0]) != std::string::npos)
- {
- auto where_begin = fn.find(keyword[0]);
- auto keyword_begin = 0UL;
- auto failed = false;
-
- for (; where_begin < keyword.size(); ++where_begin)
- {
- if (fn[where_begin] == '(' && keyword[keyword_begin] == '(')
- break;
-
- if (fn[where_begin] != keyword[keyword_begin])
- {
- failed = true;
- break;
- }
-
- ++keyword_begin;
- }
-
- if (!failed)
- {
- err_str.clear();
- goto cc_next;
- }
- else
- {
- continue;
- }
- }
- }
-
- cc_error_value:
- if (keyword.find("->") != std::string::npos)
- return err_str;
-
- if (keyword.find(".") != std::string::npos)
- return err_str;
-
- if (isalnum(keyword[0]))
- err_str += "\nUndefined value: " + keyword;
-
- return err_str;
- }
-
- cc_next_loop:
- continue;
- }
+std::string CompilerFrontend64x0::Check(const char* text, const char* file) {
+ std::string err_str;
+ std::string ln = text;
+
+ if (ln.empty()) {
+ return err_str;
+ }
+
+ bool non_ascii_found = false;
+
+ for (int i = 0; i < ln.size(); ++i) {
+ if (isalnum(ln[i])) {
+ non_ascii_found = true;
+ break;
+ }
+ }
+
+ if (kShouldHaveBraces && ln.find('{') != std::string::npos) {
+ kShouldHaveBraces = false;
+ }
+
+ if (!non_ascii_found) return err_str;
+
+ size_t string_index = 1UL;
+
+ if (ln.find('\'') != std::string::npos) {
+ string_index = ln.find('\'') + 1;
+
+ for (; string_index < ln.size(); ++string_index) {
+ if (ln[string_index] == '\'') {
+ if (ln[string_index + 1] != ';') {
+ ln.erase(string_index, 1);
+ }
+
+ return err_str;
+ }
+ }
+ } else if (ln.find('"') != std::string::npos) {
+ string_index = ln.find('"') + 1;
+
+ for (; string_index < ln.size(); ++string_index) {
+ if (ln[string_index] == '"') {
+ if (ln[string_index + 1] != ';') {
+ ln.erase(string_index, 1);
+ } else {
+ break;
+ }
+ }
+ }
+ } else if (ln.find('"') == std::string::npos && ln.find('\'') == std::string::npos) {
+ std::vector<std::string> forbidden_words;
+
+ forbidden_words.push_back("\\");
+ forbidden_words.push_back("?");
+ forbidden_words.push_back("@");
+ forbidden_words.push_back("~");
+ forbidden_words.push_back("::");
+ forbidden_words.push_back("--*");
+ forbidden_words.push_back("*/");
+
+ // add them to avoid stupid mistakes.
+ forbidden_words.push_back("namespace");
+ forbidden_words.push_back("class");
+ forbidden_words.push_back("extern \"C\"");
+
+ for (auto& forbidden : forbidden_words) {
+ if (ln.find(forbidden) != std::string::npos) {
+ err_str += "\nForbidden character detected: ";
+ err_str += forbidden;
+
+ return err_str;
+ }
+ }
+ }
+
+ struct CompilerVariableRange final {
+ std::string fBegin;
+ std::string fEnd;
+ };
+
+ const std::vector<CompilerVariableRange> variables_list = {
+ {.fBegin = "static ", .fEnd = "="}, {.fBegin = "=", .fEnd = ";"},
+ {.fBegin = "if(", .fEnd = "="}, {.fBegin = "if (", .fEnd = "="},
+ {.fBegin = "if(", .fEnd = "<"}, {.fBegin = "if (", .fEnd = "<"},
+ {.fBegin = "if(", .fEnd = ">"}, {.fBegin = "if (", .fEnd = ">"},
+ {.fBegin = "if(", .fEnd = ")"}, {.fBegin = "if (", .fEnd = ")"},
+
+ {.fBegin = "else(", .fEnd = "="}, {.fBegin = "else (", .fEnd = "="},
+ {.fBegin = "else(", .fEnd = "<"}, {.fBegin = "else (", .fEnd = "<"},
+ {.fBegin = "else(", .fEnd = ">"}, {.fBegin = "else (", .fEnd = ">"},
+ {.fBegin = "else(", .fEnd = ")"}, {.fBegin = "else (", .fEnd = ")"},
+ };
+
+ for (auto& variable : variables_list) {
+ if (ln.find(variable.fBegin) != std::string::npos) {
+ string_index = ln.find(variable.fBegin) + variable.fBegin.size();
+
+ while (ln[string_index] == ' ') ++string_index;
+
+ std::string keyword;
+
+ for (; string_index < ln.size(); ++string_index) {
+ if (ln[string_index] == variable.fEnd[0]) {
+ std::string varname = "";
+
+ for (size_t index_keyword = ln.find(' '); ln[index_keyword] != variable.fBegin[0];
+ ++index_keyword) {
+ if (ln[index_keyword] == ' ') {
+ continue;
+ }
+
+ if (isdigit(ln[index_keyword])) {
+ goto cc_next_loop;
+ }
+
+ varname += ln[index_keyword];
+ }
+
+ if (varname.find(' ') != std::string::npos) {
+ varname.erase(0, varname.find(' '));
+
+ if (variable.fBegin == "extern") {
+ varname.erase(0, varname.find(' '));
+ }
+ }
+
+ if (kRegisterCounter == 5 || kRegisterCounter == 6) ++kRegisterCounter;
+
+ std::string reg = kAsmRegisterPrefix;
+ reg += std::to_string(kRegisterCounter);
+
+ kCompilerVariables.push_back({.fValue = varname});
+ goto cc_check_done;
+ }
+
+ keyword.push_back(ln[string_index]);
+ }
+
+ goto cc_next_loop;
+
+ cc_check_done:
+
+ // skip digit value.
+ if (isdigit(keyword[0]) || keyword[0] == '"') {
+ goto cc_next_loop;
+ }
+
+ while (keyword.find(' ') != std::string::npos) keyword.erase(keyword.find(' '), 1);
+
+ for (auto& var : kCompilerVariables) {
+ if (var.fValue.find(keyword) != std::string::npos) {
+ err_str.clear();
+ goto cc_next;
+ }
+ }
+
+ for (auto& fn : kCompilerFunctions) {
+ if (fn.find(keyword[0]) != std::string::npos) {
+ auto where_begin = fn.find(keyword[0]);
+ auto keyword_begin = 0UL;
+ auto failed = false;
+
+ for (; where_begin < keyword.size(); ++where_begin) {
+ if (fn[where_begin] == '(' && keyword[keyword_begin] == '(') break;
+
+ if (fn[where_begin] != keyword[keyword_begin]) {
+ failed = true;
+ break;
+ }
+
+ ++keyword_begin;
+ }
+
+ if (!failed) {
+ err_str.clear();
+ goto cc_next;
+ } else {
+ continue;
+ }
+ }
+ }
+
+ cc_error_value:
+ if (keyword.find("->") != std::string::npos) return err_str;
+
+ if (keyword.find(".") != std::string::npos) return err_str;
+
+ if (isalnum(keyword[0])) err_str += "\nUndefined value: " + keyword;
+
+ return err_str;
+ }
+
+ cc_next_loop:
+ continue;
+ }
cc_next:
- // extern does not declare anything, it extern_segments a variable.
- // so that's why it's not declare upper.
- if (LibCompiler::find_word(ln, "extern"))
- {
- auto substr = ln.substr(ln.find("extern") + strlen("extern"));
- kCompilerVariables.push_back({.fValue = substr});
- }
-
- if (kShouldHaveBraces && ln.find('{') == std::string::npos)
- {
- err_str += "Missing '{' for function ";
- err_str += kFnName;
- err_str += "\n";
-
- kShouldHaveBraces = false;
- kFnName.clear();
- }
- else if (kShouldHaveBraces && ln.find('{') != std::string::npos)
- {
- kShouldHaveBraces = false;
- kFnName.clear();
- }
-
- bool type_not_found = true;
-
- if (ln.find('\'') != std::string::npos)
- {
- ln.replace(ln.find('\''), 3, "0");
- }
-
- auto first = ln.find('"');
- if (first != std::string::npos)
- {
- auto second = 0UL;
- bool found_second_quote = false;
-
- for (size_t i = first + 1; i < ln.size(); ++i)
- {
- if (ln[i] == '\"')
- {
- found_second_quote = true;
- second = i;
-
- break;
- }
- }
-
- if (!found_second_quote)
- {
- err_str += "Missing terminating \".";
- err_str += " here -> " + ln.substr(ln.find('"'), second);
- }
- }
-
- if (ln.find(')') != std::string::npos && ln.find(';') == std::string::npos)
- {
- if (ln.find('{') == std::string::npos)
- {
- kFnName = ln;
- kShouldHaveBraces = true;
-
- goto skip_braces_check;
- }
- else if (ln.find('{') != std::string::npos)
- {
- kShouldHaveBraces = false;
- }
- }
+ // extern does not declare anything, it extern_segments a variable.
+ // so that's why it's not declare upper.
+ if (LibCompiler::find_word(ln, "extern")) {
+ auto substr = ln.substr(ln.find("extern") + strlen("extern"));
+ kCompilerVariables.push_back({.fValue = substr});
+ }
+
+ if (kShouldHaveBraces && ln.find('{') == std::string::npos) {
+ err_str += "Missing '{' for function ";
+ err_str += kFnName;
+ err_str += "\n";
+
+ kShouldHaveBraces = false;
+ kFnName.clear();
+ } else if (kShouldHaveBraces && ln.find('{') != std::string::npos) {
+ kShouldHaveBraces = false;
+ kFnName.clear();
+ }
+
+ bool type_not_found = true;
+
+ if (ln.find('\'') != std::string::npos) {
+ ln.replace(ln.find('\''), 3, "0");
+ }
+
+ auto first = ln.find('"');
+ if (first != std::string::npos) {
+ auto second = 0UL;
+ bool found_second_quote = false;
+
+ for (size_t i = first + 1; i < ln.size(); ++i) {
+ if (ln[i] == '\"') {
+ found_second_quote = true;
+ second = i;
+
+ break;
+ }
+ }
+
+ if (!found_second_quote) {
+ err_str += "Missing terminating \".";
+ err_str += " here -> " + ln.substr(ln.find('"'), second);
+ }
+ }
+
+ if (ln.find(')') != std::string::npos && ln.find(';') == std::string::npos) {
+ if (ln.find('{') == std::string::npos) {
+ kFnName = ln;
+ kShouldHaveBraces = true;
+
+ goto skip_braces_check;
+ } else if (ln.find('{') != std::string::npos) {
+ kShouldHaveBraces = false;
+ }
+ }
skip_braces_check:
- for (auto& key : kCompilerTypes)
- {
- if (LibCompiler::find_word(ln, key.fName))
- {
- if (isdigit(ln[ln.find(key.fName) + key.fName.size() + 1]))
- {
- err_str += "\nNumber cannot be set for ";
- err_str += key.fName;
- err_str += "'s name. here -> ";
- err_str += ln;
- }
-
- if (ln.find(key.fName) == 0 || ln[ln.find(key.fName) - 1] == ' ' ||
- ln[ln.find(key.fName) - 1] == '\t')
- {
- type_not_found = false;
-
- if (ln[ln.find(key.fName) + key.fName.size()] != ' ')
- {
- type_not_found = true;
-
- if (ln[ln.find(key.fName) + key.fName.size()] == '\t')
- type_not_found = false;
-
- goto next;
- }
- else if (ln[ln.find(key.fName) + key.fName.size()] != '\t')
- {
- type_not_found = true;
-
- if (ln[ln.find(key.fName) + key.fName.size()] == ' ')
- type_not_found = false;
- }
- }
-
- next:
-
- if (ln.find(';') == std::string::npos)
- {
- if (ln.find('(') != std::string::npos)
- {
- if (ln.find('=') == std::string::npos)
- continue;
- }
-
- err_str += "\nMissing ';', here -> ";
- err_str += ln;
- }
- else
- {
- continue;
- }
-
- if (ln.find('=') != std::string::npos)
- {
- if (ln.find('(') != std::string::npos)
- {
- if (ln.find(')') == std::string::npos)
- {
- err_str += "\nMissing ')', after '(' here -> ";
- err_str += ln.substr(ln.find('('));
- }
- }
- }
- }
- }
-
- if (kInBraces && ln.find("struct") != std::string::npos &&
- ln.find("union") != std::string::npos &&
- ln.find("enum") != std::string::npos &&
- ln.find('=') != std::string::npos)
- {
- if (ln.find(';') == std::string::npos)
- {
- err_str += "\nMissing ';' after struct/union/enum declaration, here -> ";
- err_str += ln;
- }
- }
-
- if (ln.find(';') != std::string::npos &&
- ln.find("for") == std::string::npos)
- {
- if (ln.find(';') + 1 != ln.size())
- {
- for (int i = 0; i < ln.substr(ln.find(';') + 1).size(); ++i)
- {
- if ((ln.substr(ln.find(';') + 1)[i] != ' ') ||
- (ln.substr(ln.find(';') + 1)[i] != '\t'))
- {
- if (auto err = this->Check(ln.substr(ln.find(';') + 1).c_str(), file);
- !err.empty())
- {
- err_str += "\nUnexpected text after ';' -> ";
- err_str += ln.substr(ln.find(';'));
- err_str += err;
- }
- }
- }
- }
- }
-
- if (ln.find('(') != std::string::npos)
- {
- if (ln.find(';') == std::string::npos && !LibCompiler::find_word(ln, "|") &&
- !LibCompiler::find_word(ln, "||") && !LibCompiler::find_word(ln, "&") &&
- !LibCompiler::find_word(ln, "&&") && !LibCompiler::find_word(ln, "~"))
- {
- bool found_func = false;
- size_t i = ln.find('(');
- std::vector<char> opens;
- std::vector<char> closes;
-
- for (; i < ln.size(); ++i)
- {
- if (ln[i] == ')')
- {
- closes.push_back(1);
- }
-
- if (ln[i] == '(')
- {
- opens.push_back(1);
- }
- }
-
- if (closes.size() != opens.size())
- err_str += "Unterminated (), here -> " + ln;
-
- bool space_found = false;
-
- for (int i = 0; i < ln.size(); ++i)
- {
- if (ln[i] == ')' && !space_found)
- {
- space_found = true;
- continue;
- }
-
- if (space_found)
- {
- if (ln[i] == ' ' && isalnum(ln[i + 1]))
- {
- err_str += "\nBad function format here -> ";
- err_str += ln;
- }
- }
- }
- }
-
- if (ln.find('(') < 1)
- {
- err_str += "\nMissing identifier before '(' here -> ";
- err_str += ln;
- }
- else
- {
- if (type_not_found && ln.find(';') == std::string::npos &&
- ln.find("if") == std::string::npos &&
- ln.find("|") == std::string::npos &&
- ln.find("&") == std::string::npos &&
- ln.find("(") == std::string::npos &&
- ln.find(")") == std::string::npos)
- {
- err_str += "\n Missing ';' or type, here -> ";
- err_str += ln;
- }
- }
-
- if (ln.find(')') == std::string::npos)
- {
- err_str += "\nMissing ')', after '(' here -> ";
- err_str += ln.substr(ln.find('('));
- }
- }
- else
- {
- if (ln.find("for") != std::string::npos ||
- ln.find("while") != std::string::npos)
- {
- err_str += "\nMissing '(', after \"for\", here -> ";
- err_str += ln;
- }
- }
-
- if (ln.find('}') != std::string::npos && !kInBraces)
- {
- if (!kInStruct && ln.find(';') == std::string::npos)
- {
- err_str += "\nMismatched '}', here -> ";
- err_str += ln;
- }
- }
-
- if (!ln.empty())
- {
- if (ln.find(';') == std::string::npos &&
- ln.find('{') == std::string::npos &&
- ln.find('}') == std::string::npos &&
- ln.find(')') == std::string::npos &&
- ln.find('(') == std::string::npos &&
- ln.find(',') == std::string::npos)
- {
- if (ln.size() <= 2)
- return err_str;
-
- err_str += "\nMissing ';', here -> ";
- err_str += ln;
- }
- }
-
- return err_str;
+ for (auto& key : kCompilerTypes) {
+ if (LibCompiler::find_word(ln, key.fName)) {
+ if (isdigit(ln[ln.find(key.fName) + key.fName.size() + 1])) {
+ err_str += "\nNumber cannot be set for ";
+ err_str += key.fName;
+ err_str += "'s name. here -> ";
+ err_str += ln;
+ }
+
+ if (ln.find(key.fName) == 0 || ln[ln.find(key.fName) - 1] == ' ' ||
+ ln[ln.find(key.fName) - 1] == '\t') {
+ type_not_found = false;
+
+ if (ln[ln.find(key.fName) + key.fName.size()] != ' ') {
+ type_not_found = true;
+
+ if (ln[ln.find(key.fName) + key.fName.size()] == '\t') type_not_found = false;
+
+ goto next;
+ } else if (ln[ln.find(key.fName) + key.fName.size()] != '\t') {
+ type_not_found = true;
+
+ if (ln[ln.find(key.fName) + key.fName.size()] == ' ') type_not_found = false;
+ }
+ }
+
+ next:
+
+ if (ln.find(';') == std::string::npos) {
+ if (ln.find('(') != std::string::npos) {
+ if (ln.find('=') == std::string::npos) continue;
+ }
+
+ err_str += "\nMissing ';', here -> ";
+ err_str += ln;
+ } else {
+ continue;
+ }
+
+ if (ln.find('=') != std::string::npos) {
+ if (ln.find('(') != std::string::npos) {
+ if (ln.find(')') == std::string::npos) {
+ err_str += "\nMissing ')', after '(' here -> ";
+ err_str += ln.substr(ln.find('('));
+ }
+ }
+ }
+ }
+ }
+
+ if (kInBraces && ln.find("struct") != std::string::npos &&
+ ln.find("union") != std::string::npos && ln.find("enum") != std::string::npos &&
+ ln.find('=') != std::string::npos) {
+ if (ln.find(';') == std::string::npos) {
+ err_str += "\nMissing ';' after struct/union/enum declaration, here -> ";
+ err_str += ln;
+ }
+ }
+
+ if (ln.find(';') != std::string::npos && ln.find("for") == std::string::npos) {
+ if (ln.find(';') + 1 != ln.size()) {
+ for (int i = 0; i < ln.substr(ln.find(';') + 1).size(); ++i) {
+ if ((ln.substr(ln.find(';') + 1)[i] != ' ') || (ln.substr(ln.find(';') + 1)[i] != '\t')) {
+ if (auto err = this->Check(ln.substr(ln.find(';') + 1).c_str(), file); !err.empty()) {
+ err_str += "\nUnexpected text after ';' -> ";
+ err_str += ln.substr(ln.find(';'));
+ err_str += err;
+ }
+ }
+ }
+ }
+ }
+
+ if (ln.find('(') != std::string::npos) {
+ if (ln.find(';') == std::string::npos && !LibCompiler::find_word(ln, "|") &&
+ !LibCompiler::find_word(ln, "||") && !LibCompiler::find_word(ln, "&") &&
+ !LibCompiler::find_word(ln, "&&") && !LibCompiler::find_word(ln, "~")) {
+ bool found_func = false;
+ size_t i = ln.find('(');
+ std::vector<char> opens;
+ std::vector<char> closes;
+
+ for (; i < ln.size(); ++i) {
+ if (ln[i] == ')') {
+ closes.push_back(1);
+ }
+
+ if (ln[i] == '(') {
+ opens.push_back(1);
+ }
+ }
+
+ if (closes.size() != opens.size()) err_str += "Unterminated (), here -> " + ln;
+
+ bool space_found = false;
+
+ for (int i = 0; i < ln.size(); ++i) {
+ if (ln[i] == ')' && !space_found) {
+ space_found = true;
+ continue;
+ }
+
+ if (space_found) {
+ if (ln[i] == ' ' && isalnum(ln[i + 1])) {
+ err_str += "\nBad function format here -> ";
+ err_str += ln;
+ }
+ }
+ }
+ }
+
+ if (ln.find('(') < 1) {
+ err_str += "\nMissing identifier before '(' here -> ";
+ err_str += ln;
+ } else {
+ if (type_not_found && ln.find(';') == std::string::npos &&
+ ln.find("if") == std::string::npos && ln.find("|") == std::string::npos &&
+ ln.find("&") == std::string::npos && ln.find("(") == std::string::npos &&
+ ln.find(")") == std::string::npos) {
+ err_str += "\n Missing ';' or type, here -> ";
+ err_str += ln;
+ }
+ }
+
+ if (ln.find(')') == std::string::npos) {
+ err_str += "\nMissing ')', after '(' here -> ";
+ err_str += ln.substr(ln.find('('));
+ }
+ } else {
+ if (ln.find("for") != std::string::npos || ln.find("while") != std::string::npos) {
+ err_str += "\nMissing '(', after \"for\", here -> ";
+ err_str += ln;
+ }
+ }
+
+ if (ln.find('}') != std::string::npos && !kInBraces) {
+ if (!kInStruct && ln.find(';') == std::string::npos) {
+ err_str += "\nMismatched '}', here -> ";
+ err_str += ln;
+ }
+ }
+
+ if (!ln.empty()) {
+ if (ln.find(';') == std::string::npos && ln.find('{') == std::string::npos &&
+ ln.find('}') == std::string::npos && ln.find(')') == std::string::npos &&
+ ln.find('(') == std::string::npos && ln.find(',') == std::string::npos) {
+ if (ln.size() <= 2) return err_str;
+
+ err_str += "\nMissing ';', here -> ";
+ err_str += ln;
+ }
+ }
+
+ return err_str;
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -1294,186 +1045,144 @@ skip_braces_check:
/////////////////////////////////////////////////////////////////////////////////////////
-class AssemblyCCInterface final ASSEMBLY_INTERFACE
-{
-public:
- explicit AssemblyCCInterface() = default;
- ~AssemblyCCInterface() override = default;
-
- LIBCOMPILER_COPY_DEFAULT(AssemblyCCInterface);
-
- [[maybe_unused]] static Int32 Arch() noexcept
- {
- return LibCompiler::AssemblyFactory::kArch64x0;
- }
-
- Int32 CompileToFormat(std::string& src, Int32 arch) override
- {
- if (arch != AssemblyCCInterface::Arch())
- return 1;
-
- if (kCompilerFrontend == nullptr)
- return 1;
-
- /* @brief copy contents wihtout extension */
- std::string src_file = src.data();
- std::ifstream src_fp = std::ifstream(src_file, std::ios::in);
- std::string dest;
-
- for (auto& ch : src_file)
- {
- if (ch == '.')
- {
- break;
- }
-
- dest += ch;
- }
-
- /* According to PEF ABI. */
- std::vector<const char*> exts = kAsmFileExts;
- dest += exts[4];
-
- kState.fOutputAssembly = std::make_unique<std::ofstream>(dest);
-
- auto fmt = LibCompiler::current_date();
-
- (*kState.fOutputAssembly) << "# Path: " << src_file << "\n";
- (*kState.fOutputAssembly)
- << "# Language: 64x0 Assembly (Generated from ANSI C)\n";
- (*kState.fOutputAssembly) << "# Date: " << fmt << "\n\n";
-
- LibCompiler::SyntaxLeafList syntax;
-
- kState.fSyntaxTreeList.push_back(syntax);
- kState.fSyntaxTree =
- &kState.fSyntaxTreeList[kState.fSyntaxTreeList.size() - 1];
-
- std::string line_src;
-
- while (std::getline(src_fp, line_src))
- {
- if (auto err = kCompilerFrontend->Check(line_src.c_str(), src.data());
- err.empty())
- {
- kCompilerFrontend->Compile(line_src, src.data());
- }
- else
- {
- Detail::print_error(err, src.data());
- }
- }
-
- if (kAcceptableErrors > 0)
- return 1;
-
- std::vector<std::string> keywords = {"ldw", "stw", "lda", "sta",
- "add", "sub", "mv"};
-
- ///
- /// Replace, optimize, fix assembly output.
- ///
-
- for (auto& leaf : kState.fSyntaxTree->fLeafList)
- {
- std::vector<std::string> access_keywords = {"->", "."};
-
- for (auto& access_ident : access_keywords)
- {
- if (LibCompiler::find_word(leaf.fUserValue, access_ident))
- {
- for (auto& struc : kState.kStructMap)
- {
- /// TODO:
- }
- }
- }
-
- for (auto& keyword : keywords)
- {
- if (LibCompiler::find_word(leaf.fUserValue, keyword))
- {
- std::size_t cnt = 0UL;
-
- for (auto& reg : kState.kStackFrame)
- {
- std::string needle;
-
- for (size_t i = 0; i < reg.fName.size(); i++)
- {
- if (reg.fName[i] == ' ')
- {
- ++i;
-
- for (; i < reg.fName.size(); i++)
- {
- if (reg.fName[i] == ',')
- {
- break;
- }
-
- if (reg.fName[i] == ' ')
- continue;
-
- needle += reg.fName[i];
- }
-
- break;
- }
- }
-
- if (LibCompiler::find_word(leaf.fUserValue, needle))
- {
- if (leaf.fUserValue.find("extern_segment " + needle) !=
- std::string::npos)
- {
- std::string range = "extern_segment " + needle;
- leaf.fUserValue.replace(
- leaf.fUserValue.find("extern_segment " + needle), range.size(),
- needle);
- }
-
- if (leaf.fUserValue.find("ldw r6") != std::string::npos)
- {
- std::string::difference_type countComma = std::count(
- leaf.fUserValue.begin(), leaf.fUserValue.end(), ',');
-
- if (countComma == 1)
- {
- leaf.fUserValue.replace(leaf.fUserValue.find("ldw"),
- strlen("ldw"), "mv");
- }
- }
-
- leaf.fUserValue.replace(leaf.fUserValue.find(needle),
- needle.size(), reg.fReg);
-
- ++cnt;
- }
- }
-
- if (cnt > 1 && keyword != "mv" && keyword != "add" &&
- keyword != "sub")
- {
- leaf.fUserValue.replace(leaf.fUserValue.find(keyword),
- keyword.size(), "mv");
- }
- }
- }
- }
-
- for (auto& leaf : kState.fSyntaxTree->fLeafList)
- {
- (*kState.fOutputAssembly) << leaf.fUserValue;
- }
-
- kState.fSyntaxTree = nullptr;
-
- kState.fOutputAssembly->flush();
- kState.fOutputAssembly.reset();
-
- return kExitOK;
- }
+class AssemblyCCInterface final ASSEMBLY_INTERFACE {
+ public:
+ explicit AssemblyCCInterface() = default;
+ ~AssemblyCCInterface() override = default;
+
+ LIBCOMPILER_COPY_DEFAULT(AssemblyCCInterface);
+
+ [[maybe_unused]] static Int32 Arch() noexcept { return LibCompiler::AssemblyFactory::kArch64x0; }
+
+ Int32 CompileToFormat(std::string& src, Int32 arch) override {
+ if (arch != AssemblyCCInterface::Arch()) return 1;
+
+ if (kCompilerFrontend == nullptr) return 1;
+
+ /* @brief copy contents wihtout extension */
+ std::string src_file = src.data();
+ std::ifstream src_fp = std::ifstream(src_file, std::ios::in);
+ std::string dest;
+
+ for (auto& ch : src_file) {
+ if (ch == '.') {
+ break;
+ }
+
+ dest += ch;
+ }
+
+ /* According to PEF ABI. */
+ std::vector<const char*> exts = kAsmFileExts;
+ dest += exts[4];
+
+ kState.fOutputAssembly = std::make_unique<std::ofstream>(dest);
+
+ auto fmt = LibCompiler::current_date();
+
+ (*kState.fOutputAssembly) << "# Path: " << src_file << "\n";
+ (*kState.fOutputAssembly) << "# Language: 64x0 Assembly (Generated from ANSI C)\n";
+ (*kState.fOutputAssembly) << "# Date: " << fmt << "\n\n";
+
+ LibCompiler::SyntaxLeafList syntax;
+
+ kState.fSyntaxTreeList.push_back(syntax);
+ kState.fSyntaxTree = &kState.fSyntaxTreeList[kState.fSyntaxTreeList.size() - 1];
+
+ std::string line_src;
+
+ while (std::getline(src_fp, line_src)) {
+ if (auto err = kCompilerFrontend->Check(line_src.c_str(), src.data()); err.empty()) {
+ kCompilerFrontend->Compile(line_src, src.data());
+ } else {
+ Detail::print_error(err, src.data());
+ }
+ }
+
+ if (kAcceptableErrors > 0) return 1;
+
+ std::vector<std::string> keywords = {"ldw", "stw", "lda", "sta", "add", "sub", "mv"};
+
+ ///
+ /// Replace, optimize, fix assembly output.
+ ///
+
+ for (auto& leaf : kState.fSyntaxTree->fLeafList) {
+ std::vector<std::string> access_keywords = {"->", "."};
+
+ for (auto& access_ident : access_keywords) {
+ if (LibCompiler::find_word(leaf.fUserValue, access_ident)) {
+ for (auto& struc : kState.kStructMap) {
+ /// TODO:
+ }
+ }
+ }
+
+ for (auto& keyword : keywords) {
+ if (LibCompiler::find_word(leaf.fUserValue, keyword)) {
+ std::size_t cnt = 0UL;
+
+ for (auto& reg : kState.kStackFrame) {
+ std::string needle;
+
+ for (size_t i = 0; i < reg.fName.size(); i++) {
+ if (reg.fName[i] == ' ') {
+ ++i;
+
+ for (; i < reg.fName.size(); i++) {
+ if (reg.fName[i] == ',') {
+ break;
+ }
+
+ if (reg.fName[i] == ' ') continue;
+
+ needle += reg.fName[i];
+ }
+
+ break;
+ }
+ }
+
+ if (LibCompiler::find_word(leaf.fUserValue, needle)) {
+ if (leaf.fUserValue.find("extern_segment " + needle) != std::string::npos) {
+ std::string range = "extern_segment " + needle;
+ leaf.fUserValue.replace(leaf.fUserValue.find("extern_segment " + needle),
+ range.size(), needle);
+ }
+
+ if (leaf.fUserValue.find("ldw r6") != std::string::npos) {
+ std::string::difference_type countComma =
+ std::count(leaf.fUserValue.begin(), leaf.fUserValue.end(), ',');
+
+ if (countComma == 1) {
+ leaf.fUserValue.replace(leaf.fUserValue.find("ldw"), strlen("ldw"), "mv");
+ }
+ }
+
+ leaf.fUserValue.replace(leaf.fUserValue.find(needle), needle.size(), reg.fReg);
+
+ ++cnt;
+ }
+ }
+
+ if (cnt > 1 && keyword != "mv" && keyword != "add" && keyword != "sub") {
+ leaf.fUserValue.replace(leaf.fUserValue.find(keyword), keyword.size(), "mv");
+ }
+ }
+ }
+ }
+
+ for (auto& leaf : kState.fSyntaxTree->fLeafList) {
+ (*kState.fOutputAssembly) << leaf.fUserValue;
+ }
+
+ kState.fSyntaxTree = nullptr;
+
+ kState.fOutputAssembly->flush();
+ kState.fOutputAssembly.reset();
+
+ return kExitOK;
+ }
};
/////////////////////////////////////////////////////////////////////////////////////////
@@ -1481,116 +1190,98 @@ public:
#include <LibCompiler/Version.h>
#define kPrintF printf
-#define kSplashCxx() \
- kPrintF(kWhite "NE C Driver, %s, (c) Amlal El Mahrouss\n", kDistVersion)
+#define kSplashCxx() kPrintF(kWhite "NE C Driver, %s, (c) Amlal El Mahrouss\n", kDistVersion)
-static void cc_print_help()
-{
- kSplashCxx();
+static void cc_print_help() {
+ kSplashCxx();
}
/////////////////////////////////////////////////////////////////////////////////////////
#define kExt ".c"
-LIBCOMPILER_MODULE(NeOSCompilerCLang64x0)
-{
- kCompilerTypes.push_back({.fName = "void", .fValue = "void"});
- kCompilerTypes.push_back({.fName = "char", .fValue = "byte"});
- kCompilerTypes.push_back({.fName = "short", .fValue = "hword"});
- kCompilerTypes.push_back({.fName = "int", .fValue = "dword"});
- kCompilerTypes.push_back({.fName = "long", .fValue = "qword"});
- kCompilerTypes.push_back({.fName = "*", .fValue = "offset"});
-
- bool skip = false;
-
- kFactory.Mount(new AssemblyCCInterface());
- kMachine = LibCompiler::AssemblyFactory::kArch64x0;
- kCompilerFrontend = new CompilerFrontend64x0();
-
- for (auto index = 1UL; index < argc; ++index)
- {
- if (skip)
- {
- skip = false;
- continue;
- }
-
- if (argv[index][0] == '-')
- {
- if (strcmp(argv[index], "--v") == 0 ||
- strcmp(argv[index], "--version") == 0)
- {
- kSplashCxx();
- return kExitOK;
- }
-
- if (strcmp(argv[index], "--verbose") == 0)
- {
- kState.fVerbose = true;
-
- continue;
- }
-
- if (strcmp(argv[index], "--h") == 0 || strcmp(argv[index], "--help") == 0)
- {
- cc_print_help();
-
- return kExitOK;
- }
-
- if (strcmp(argv[index], "--dialect") == 0)
- {
- if (kCompilerFrontend)
- std::cout << kCompilerFrontend->Language() << "\n";
-
- return kExitOK;
- }
-
- if (strcmp(argv[index], "--fmax-exceptions") == 0)
- {
- try
- {
- kErrorLimit = std::strtol(argv[index + 1], nullptr, 10);
- }
- // catch anything here
- catch (...)
- {
- kErrorLimit = 0;
- }
-
- skip = true;
-
- continue;
- }
-
- std::string err = "Unknown command: ";
- err += argv[index];
-
- Detail::print_error(err, "cc");
-
- continue;
- }
-
- kFileList.emplace_back(argv[index]);
-
- std::string srcFile = argv[index];
-
- if (strstr(argv[index], kExt) == nullptr)
- {
- if (kState.fVerbose)
- {
- Detail::print_error(srcFile + " is not a valid C source.\n", "cc");
- }
-
- return 1;
- }
-
- if (kFactory.Compile(srcFile, kMachine) != kExitOK)
- return 1;
- }
-
- return kExitOK;
+LIBCOMPILER_MODULE(NeOSCompilerCLang64x0) {
+ kCompilerTypes.push_back({.fName = "void", .fValue = "void"});
+ kCompilerTypes.push_back({.fName = "char", .fValue = "byte"});
+ kCompilerTypes.push_back({.fName = "short", .fValue = "hword"});
+ kCompilerTypes.push_back({.fName = "int", .fValue = "dword"});
+ kCompilerTypes.push_back({.fName = "long", .fValue = "qword"});
+ kCompilerTypes.push_back({.fName = "*", .fValue = "offset"});
+
+ bool skip = false;
+
+ kFactory.Mount(new AssemblyCCInterface());
+ kMachine = LibCompiler::AssemblyFactory::kArch64x0;
+ kCompilerFrontend = new CompilerFrontend64x0();
+
+ for (auto index = 1UL; index < argc; ++index) {
+ if (skip) {
+ skip = false;
+ continue;
+ }
+
+ if (argv[index][0] == '-') {
+ if (strcmp(argv[index], "--v") == 0 || strcmp(argv[index], "--version") == 0) {
+ kSplashCxx();
+ return kExitOK;
+ }
+
+ if (strcmp(argv[index], "--verbose") == 0) {
+ kState.fVerbose = true;
+
+ continue;
+ }
+
+ if (strcmp(argv[index], "--h") == 0 || strcmp(argv[index], "--help") == 0) {
+ cc_print_help();
+
+ return kExitOK;
+ }
+
+ if (strcmp(argv[index], "--dialect") == 0) {
+ if (kCompilerFrontend) std::cout << kCompilerFrontend->Language() << "\n";
+
+ return kExitOK;
+ }
+
+ if (strcmp(argv[index], "--fmax-exceptions") == 0) {
+ try {
+ kErrorLimit = std::strtol(argv[index + 1], nullptr, 10);
+ }
+ // catch anything here
+ catch (...) {
+ kErrorLimit = 0;
+ }
+
+ skip = true;
+
+ continue;
+ }
+
+ std::string err = "Unknown command: ";
+ err += argv[index];
+
+ Detail::print_error(err, "cc");
+
+ continue;
+ }
+
+ kFileList.emplace_back(argv[index]);
+
+ std::string srcFile = argv[index];
+
+ if (strstr(argv[index], kExt) == nullptr) {
+ if (kState.fVerbose) {
+ Detail::print_error(srcFile + " is not a valid C source.\n", "cc");
+ }
+
+ return 1;
+ }
+
+ if (kFactory.Compile(srcFile, kMachine) != kExitOK) return 1;
+ }
+
+ return kExitOK;
}
// Last rev 8-1-24
diff --git a/dev/LibCompiler/src/CCompilerARM64.cc b/dev/LibCompiler/src/CCompilerARM64.cc
index 5d3e892..accd9f9 100644
--- a/dev/LibCompiler/src/CCompilerARM64.cc
+++ b/dev/LibCompiler/src/CCompilerARM64.cc
@@ -41,7 +41,7 @@
#define kExitOK (0)
#define kBlank "\e[0;30m"
-#define kRed "\e[0;31m"
+#define kRed "\e[0;31m"
#define kWhite "\e[0;97m"
/////////////////////////////////////
@@ -50,63 +50,57 @@
/////////////////////////////////////
-namespace Detail
-{
- // \brief Register map structure, used to keep track of each variable's registers.
- struct CompilerRegisterMap final
- {
- std::string fName;
- std::string fReg;
- };
-
- // \brief Map for C structs
- // \author amlel
- struct CompilerStructMap final
- {
- // 'my_foo'
- std::string fName;
-
- // if instance: stores a valid register.
- std::string fReg;
-
- // offset count
- std::size_t fOffsetsCnt;
-
- // offset array.
- std::vector<std::pair<Int32, std::string>> fOffsets;
- };
-
- struct CompilerState final
- {
- std::vector<LibCompiler::SyntaxLeafList> fSyntaxTreeList;
- std::vector<CompilerRegisterMap> kStackFrame;
- std::vector<CompilerStructMap> kStructMap;
- LibCompiler::SyntaxLeafList* fSyntaxTree{nullptr};
- std::unique_ptr<std::ofstream> fOutputAssembly;
- std::string fLastFile;
- std::string fLastError;
- bool fVerbose;
- };
-} // namespace Detail
+namespace Detail {
+// \brief Register map structure, used to keep track of each variable's registers.
+struct CompilerRegisterMap final {
+ std::string fName;
+ std::string fReg;
+};
+
+// \brief Map for C structs
+// \author amlel
+struct CompilerStructMap final {
+ // 'my_foo'
+ std::string fName;
+
+ // if instance: stores a valid register.
+ std::string fReg;
+
+ // offset count
+ std::size_t fOffsetsCnt;
+
+ // offset array.
+ std::vector<std::pair<Int32, std::string>> fOffsets;
+};
+
+struct CompilerState final {
+ std::vector<LibCompiler::SyntaxLeafList> fSyntaxTreeList;
+ std::vector<CompilerRegisterMap> kStackFrame;
+ std::vector<CompilerStructMap> kStructMap;
+ LibCompiler::SyntaxLeafList* fSyntaxTree{nullptr};
+ std::unique_ptr<std::ofstream> fOutputAssembly;
+ std::string fLastFile;
+ std::string fLastError;
+ bool fVerbose;
+};
+} // namespace Detail
static Detail::CompilerState kState;
-static SizeType kErrorLimit = 100;
-static std::string kIfFunction = "";
-static Int32 kAcceptableErrors = 0;
-
-namespace Detail
-{
- /// @brief prints an error into stdout.
- /// @param reason the reason of the error.
- /// @param file where does it originate from?
- void print_error(std::string reason, std::string file) noexcept;
-
- struct CompilerType final
- {
- std::string fName;
- std::string fValue;
- };
-} // namespace Detail
+static SizeType kErrorLimit = 100;
+static std::string kIfFunction = "";
+static Int32 kAcceptableErrors = 0;
+
+namespace Detail {
+/// @brief prints an error into stdout.
+/// @param reason the reason of the error.
+/// @param file where does it originate from?
+void print_error(std::string reason, std::string file) noexcept;
+
+struct CompilerType final {
+ std::string fName;
+ std::string fValue;
+};
+} // namespace Detail
/////////////////////////////////////////////////////////////////////////////////////////
@@ -119,11 +113,11 @@ static int kMachine = 0;
/////////////////////////////////////////
-static size_t kRegisterCnt = kAsmRegisterLimit;
-static size_t kStartUsable = 8;
-static size_t kUsableLimit = 15;
-static size_t kRegisterCounter = kStartUsable;
-static std::string kRegisterPrefix = kAsmRegisterPrefix;
+static size_t kRegisterCnt = kAsmRegisterLimit;
+static size_t kStartUsable = 8;
+static size_t kUsableLimit = 15;
+static size_t kRegisterCounter = kStartUsable;
+static std::string kRegisterPrefix = kAsmRegisterPrefix;
/////////////////////////////////////////
@@ -131,67 +125,56 @@ static std::string kRegisterPrefix = kAsmRegisterPrefix;
/////////////////////////////////////////
-static std::vector<std::string> kFileList;
+static std::vector<std::string> kFileList;
static LibCompiler::AssemblyFactory kFactory;
-static bool kInStruct = false;
-static bool kOnWhileLoop = false;
-static bool kOnForLoop = false;
-static bool kInBraces = false;
-static bool kIfFound = false;
-static size_t kBracesCount = 0UL;
+static bool kInStruct = false;
+static bool kOnWhileLoop = false;
+static bool kOnForLoop = false;
+static bool kInBraces = false;
+static bool kIfFound = false;
+static size_t kBracesCount = 0UL;
/* @brief C compiler backend for C */
-class CompilerFrontendARM64 final : public LibCompiler::ICompilerFrontend
-{
-public:
- explicit CompilerFrontendARM64() = default;
- ~CompilerFrontendARM64() override = default;
+class CompilerFrontendARM64 final : public LibCompiler::ICompilerFrontend {
+ public:
+ explicit CompilerFrontendARM64() = default;
+ ~CompilerFrontendARM64() override = default;
- LIBCOMPILER_COPY_DEFAULT(CompilerFrontendARM64);
+ LIBCOMPILER_COPY_DEFAULT(CompilerFrontendARM64);
- std::string Check(const char* text, const char* file);
- bool Compile(std::string text, const std::string file) override;
+ std::string Check(const char* text, const char* file);
+ bool Compile(std::string text, const std::string file) override;
- const char* Language() override
- {
- return "64k C";
- }
+ const char* Language() override { return "64k C"; }
};
-static CompilerFrontendARM64* kCompilerFrontend = nullptr;
+static CompilerFrontendARM64* kCompilerFrontend = nullptr;
static std::vector<Detail::CompilerType> kCompilerVariables;
-static std::vector<std::string> kCompilerFunctions;
+static std::vector<std::string> kCompilerFunctions;
static std::vector<Detail::CompilerType> kCompilerTypes;
-namespace Detail
-{
- union number_cast final {
- public:
- number_cast(UInt64 _Raw)
- : _Raw(_Raw)
- {
- }
-
- public:
- char _Num[8];
- UInt64 _Raw;
- };
-
- union double_cast final {
- public:
- double_cast(float _Raw)
- : _Raw(_Raw)
- {
- }
-
- public:
- char _Sign;
- char _Lh[8];
- char _Rh[23];
-
- float _Raw;
- };
-} // namespace Detail
+namespace Detail {
+union number_cast final {
+ public:
+ number_cast(UInt64 _Raw) : _Raw(_Raw) {}
+
+ public:
+ char _Num[8];
+ UInt64 _Raw;
+};
+
+union double_cast final {
+ public:
+ double_cast(float _Raw) : _Raw(_Raw) {}
+
+ public:
+ char _Sign;
+ char _Lh[8];
+ char _Rh[23];
+
+ float _Raw;
+};
+} // namespace Detail
/////////////////////////////////////////////////////////////////////////////////////////
@@ -200,1088 +183,856 @@ namespace Detail
/////////////////////////////////////////////////////////////////////////////////////////
-bool CompilerFrontendARM64::Compile(std::string text, const std::string file)
-{
- bool typeFound = false;
- bool fnFound = false;
-
- // setup generator.
- std::random_device rd;
-
- auto seed_data = std::array<int, std::mt19937::state_size>{};
- std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd));
- std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
- std::mt19937 generator(seq);
-
- // start parsing
- for (size_t text_index = 0; text_index < text.size(); ++text_index)
- {
- auto syntaxLeaf = LibCompiler::SyntaxLeafList::SyntaxLeaf();
-
- auto gen = uuids::uuid_random_generator{generator};
- uuids::uuid out = gen();
-
- Detail::number_cast time_off = (UInt64)out.as_bytes().data();
-
- if (!typeFound)
- {
- auto substr = text.substr(text_index);
- std::string match_type;
-
- for (size_t y = 0; y < substr.size(); ++y)
- {
- if (substr[y] == ' ')
- {
- while (match_type.find(' ') != std::string::npos)
- {
- match_type.erase(match_type.find(' '));
- }
-
- for (auto& clType : kCompilerTypes)
- {
- if (clType.fName == match_type)
- {
- match_type.clear();
-
- std::string buf;
-
- buf += clType.fValue;
- buf += ' ';
+bool CompilerFrontendARM64::Compile(std::string text, const std::string file) {
+ bool typeFound = false;
+ bool fnFound = false;
+
+ // setup generator.
+ std::random_device rd;
+
+ auto seed_data = std::array<int, std::mt19937::state_size>{};
+ std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd));
+ std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
+ std::mt19937 generator(seq);
+
+ // start parsing
+ for (size_t text_index = 0; text_index < text.size(); ++text_index) {
+ auto syntaxLeaf = LibCompiler::SyntaxLeafList::SyntaxLeaf();
+
+ auto gen = uuids::uuid_random_generator{generator};
+ uuids::uuid out = gen();
+
+ Detail::number_cast time_off = (UInt64) out.as_bytes().data();
+
+ if (!typeFound) {
+ auto substr = text.substr(text_index);
+ std::string match_type;
+
+ for (size_t y = 0; y < substr.size(); ++y) {
+ if (substr[y] == ' ') {
+ while (match_type.find(' ') != std::string::npos) {
+ match_type.erase(match_type.find(' '));
+ }
+
+ for (auto& clType : kCompilerTypes) {
+ if (clType.fName == match_type) {
+ match_type.clear();
+
+ std::string buf;
+
+ buf += clType.fValue;
+ buf += ' ';
+
+ if (substr.find('=') != std::string::npos) {
+ break;
+ }
+
+ if (text.find('(') != std::string::npos) {
+ syntaxLeaf.fUserValue = buf;
+
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+ }
+
+ typeFound = true;
+ break;
+ }
+ }
+
+ break;
+ }
+
+ match_type += substr[y];
+ }
+ }
+
+ if (text[text_index] == '{') {
+ if (kInStruct) {
+ continue;
+ }
+
+ kInBraces = true;
+ ++kBracesCount;
+
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+ }
+
+ // return keyword handler
+ if (text[text_index] == 'r') {
+ std::string return_keyword;
+ return_keyword += "return";
+
+ std::size_t index = 0UL;
+
+ std::string value;
+
+ for (size_t return_index = text_index; return_index < text.size(); ++return_index) {
+ if (text[return_index] != return_keyword[index]) {
+ for (size_t value_index = return_index; value_index < text.size(); ++value_index) {
+ if (text[value_index] == ';') break;
+
+ value += text[value_index];
+ }
+
+ break;
+ }
+
+ ++index;
+ }
+
+ if (index == return_keyword.size()) {
+ if (!value.empty()) {
+ if (value.find('(') != std::string::npos) {
+ value.erase(value.find('('));
+ }
+
+ if (!isdigit(value[value.find('(') + 2])) {
+ std::string tmp = value;
+ bool reg_to_reg = false;
+
+ value.clear();
+
+ value += " extern_segment";
+ value += tmp;
+ }
+
+ syntaxLeaf.fUserValue = "\tldw r19, ";
+
+ // make it pretty.
+ if (value.find('\t') != std::string::npos) value.erase(value.find('\t'), 1);
+
+ syntaxLeaf.fUserValue += value + "\n";
+ }
+
+ syntaxLeaf.fUserValue += "\tjlr";
+
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+
+ break;
+ }
+ }
+
+ if (text[text_index] == 'i' && text[text_index + 1] == 'f') {
+ auto expr = text.substr(text_index + 2);
+ text.erase(text_index, 2);
+
+ if (expr.find("{") != std::string::npos) {
+ expr.erase(expr.find("{"));
+ }
+
+ if (expr.find("(") != std::string::npos) expr.erase(expr.find("("));
+
+ if (expr.find(")") != std::string::npos) expr.erase(expr.find(")"));
+
+ kIfFunction = "__LIBCOMPILER_IF_PROC_";
+ kIfFunction += std::to_string(time_off._Raw);
+
+ syntaxLeaf.fUserValue = "\tlda r12, extern_segment ";
+ syntaxLeaf.fUserValue += kIfFunction +
+ "\n\t#r12 = Code to jump on, r11 right cond, r10 left cond.\n\tbeq "
+ "r10, r11, r12\ndword public_segment .code64 " +
+ kIfFunction + "\n";
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+
+ kIfFound = true;
+ }
+
+ // Parse expressions and instructions here.
+ // what does this mean?
+ // we encounter an assignment, or we reached the end of an expression.
+ if (text[text_index] == '=' || text[text_index] == ';') {
+ if (fnFound) continue;
+ if (kIfFound) continue;
+
+ if (text[text_index] == ';' && kInStruct) continue;
+
+ if (text.find("typedef ") != std::string::npos) continue;
+
+ if (text[text_index] == '=' && kInStruct) {
+ Detail::print_error("assignement of value in struct " + text, file);
+ continue;
+ }
+
+ if (text[text_index] == ';' && kInStruct) {
+ bool space_found_ = false;
+ std::string sym;
+
+ for (auto& ch : text) {
+ if (ch == ' ') {
+ space_found_ = true;
+ }
+
+ if (ch == ';') break;
+
+ if (space_found_) sym.push_back(ch);
+ }
+
+ kState.kStructMap[kState.kStructMap.size() - 1].fOffsets.push_back(
+ std::make_pair(kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4, sym));
+
+ kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt =
+ kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4;
+
+ continue;
+ }
+
+ if (text[text_index] == '=' && kInStruct) {
+ continue;
+ }
+
+ if (text[text_index + 1] == '=' || text[text_index - 1] == '!' ||
+ text[text_index - 1] == '<' || text[text_index - 1] == '>') {
+ continue;
+ }
+
+ std::string substr;
+
+ if (text.find('=') != std::string::npos && kInBraces && !kIfFound) {
+ if (text.find("*") != std::string::npos) {
+ if (text.find("=") > text.find("*"))
+ substr += "\tlda ";
+ else
+ substr += "\tldw ";
+ } else {
+ substr += "\tldw ";
+ }
+ } else if (text.find('=') != std::string::npos && !kInBraces) {
+ substr += "stw public_segment .data64 ";
+ }
+
+ int first_encountered = 0;
+
+ std::string str_name;
+
+ for (size_t text_index_2 = 0; text_index_2 < text.size(); ++text_index_2) {
+ if (text[text_index_2] == '\"') {
+ ++text_index_2;
+
+ // want to add this, so that the parser recognizes that this is a
+ // string.
+ substr += '"';
+
+ for (; text_index_2 < text.size(); ++text_index_2) {
+ if (text[text_index_2] == '\"') break;
+
+ substr += text[text_index_2];
+ }
+ }
+
+ if (text[text_index_2] == '{' || text[text_index_2] == '}') continue;
+
+ if (text[text_index_2] == ';') {
+ break;
+ }
+
+ if (text[text_index_2] == ' ' || text[text_index_2] == '\t') {
+ if (first_encountered != 2) {
+ if (text[text_index] != '=' &&
+ substr.find("public_segment .data64") == std::string::npos && !kInStruct)
+ substr += "public_segment .data64 ";
+ }
+
+ ++first_encountered;
+
+ continue;
+ }
+
+ if (text[text_index_2] == '=') {
+ if (!kInBraces) {
+ substr.replace(substr.find("public_segment .data64"), strlen("public_segment .data64"),
+ "public_segment .zero64 ");
+ }
- if (substr.find('=') != std::string::npos)
- {
- break;
- }
+ substr += ",";
+ continue;
+ }
- if (text.find('(') != std::string::npos)
- {
- syntaxLeaf.fUserValue = buf;
+ substr += text[text_index_2];
+ }
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
- }
-
- typeFound = true;
- break;
- }
- }
+ for (auto& clType : kCompilerTypes) {
+ if (substr.find(clType.fName) != std::string::npos) {
+ if (substr.find(clType.fName) > substr.find('"')) continue;
- break;
- }
+ substr.erase(substr.find(clType.fName), clType.fName.size());
+ } else if (substr.find(clType.fValue) != std::string::npos) {
+ if (substr.find(clType.fValue) > substr.find('"')) continue;
- match_type += substr[y];
- }
- }
+ if (clType.fName == "const") continue;
- if (text[text_index] == '{')
- {
- if (kInStruct)
- {
- continue;
- }
-
- kInBraces = true;
- ++kBracesCount;
+ substr.erase(substr.find(clType.fValue), clType.fValue.size());
+ }
+ }
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
- }
-
- // return keyword handler
- if (text[text_index] == 'r')
- {
- std::string return_keyword;
- return_keyword += "return";
-
- std::size_t index = 0UL;
-
- std::string value;
-
- for (size_t return_index = text_index; return_index < text.size();
- ++return_index)
- {
- if (text[return_index] != return_keyword[index])
- {
- for (size_t value_index = return_index;
- value_index < text.size(); ++value_index)
- {
- if (text[value_index] == ';')
- break;
-
- value += text[value_index];
- }
-
- break;
- }
-
- ++index;
- }
-
- if (index == return_keyword.size())
- {
- if (!value.empty())
- {
- if (value.find('(') != std::string::npos)
- {
- value.erase(value.find('('));
- }
-
- if (!isdigit(value[value.find('(') + 2]))
- {
- std::string tmp = value;
- bool reg_to_reg = false;
-
- value.clear();
-
- value += " extern_segment";
- value += tmp;
- }
-
- syntaxLeaf.fUserValue = "\tldw r19, ";
-
- // make it pretty.
- if (value.find('\t') != std::string::npos)
- value.erase(value.find('\t'), 1);
-
- syntaxLeaf.fUserValue += value + "\n";
- }
-
- syntaxLeaf.fUserValue += "\tjlr";
-
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
-
- break;
- }
- }
-
- if (text[text_index] == 'i' && text[text_index + 1] == 'f')
- {
- auto expr = text.substr(text_index + 2);
- text.erase(text_index, 2);
-
- if (expr.find("{") != std::string::npos)
- {
- expr.erase(expr.find("{"));
- }
-
- if (expr.find("(") != std::string::npos)
- expr.erase(expr.find("("));
-
- if (expr.find(")") != std::string::npos)
- expr.erase(expr.find(")"));
-
- kIfFunction = "__LIBCOMPILER_IF_PROC_";
- kIfFunction += std::to_string(time_off._Raw);
-
- syntaxLeaf.fUserValue = "\tlda r12, extern_segment ";
- syntaxLeaf.fUserValue +=
- kIfFunction +
- "\n\t#r12 = Code to jump on, r11 right cond, r10 left cond.\n\tbeq "
- "r10, r11, r12\ndword public_segment .code64 " +
- kIfFunction + "\n";
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
-
- kIfFound = true;
- }
-
- // Parse expressions and instructions here.
- // what does this mean?
- // we encounter an assignment, or we reached the end of an expression.
- if (text[text_index] == '=' || text[text_index] == ';')
- {
- if (fnFound)
- continue;
- if (kIfFound)
- continue;
-
- if (text[text_index] == ';' && kInStruct)
- continue;
-
- if (text.find("typedef ") != std::string::npos)
- continue;
-
- if (text[text_index] == '=' && kInStruct)
- {
- Detail::print_error("assignement of value in struct " + text,
- file);
- continue;
- }
-
- if (text[text_index] == ';' && kInStruct)
- {
- bool space_found_ = false;
- std::string sym;
-
- for (auto& ch : text)
- {
- if (ch == ' ')
- {
- space_found_ = true;
- }
-
- if (ch == ';')
- break;
-
- if (space_found_)
- sym.push_back(ch);
- }
-
- kState.kStructMap[kState.kStructMap.size() - 1].fOffsets.push_back(
- std::make_pair(
- kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4,
- sym));
-
- kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt =
- kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4;
-
- continue;
- }
-
- if (text[text_index] == '=' && kInStruct)
- {
- continue;
- }
-
- if (text[text_index + 1] == '=' ||
- text[text_index - 1] == '!' ||
- text[text_index - 1] == '<' ||
- text[text_index - 1] == '>')
- {
- continue;
- }
-
- std::string substr;
-
- if (text.find('=') != std::string::npos && kInBraces && !kIfFound)
- {
- if (text.find("*") != std::string::npos)
- {
- if (text.find("=") > text.find("*"))
- substr += "\tlda ";
- else
- substr += "\tldw ";
- }
- else
- {
- substr += "\tldw ";
- }
- }
- else if (text.find('=') != std::string::npos && !kInBraces)
- {
- substr += "stw public_segment .data64 ";
- }
-
- int first_encountered = 0;
-
- std::string str_name;
-
- for (size_t text_index_2 = 0; text_index_2 < text.size();
- ++text_index_2)
- {
- if (text[text_index_2] == '\"')
- {
- ++text_index_2;
-
- // want to add this, so that the parser recognizes that this is a
- // string.
- substr += '"';
-
- for (; text_index_2 < text.size(); ++text_index_2)
- {
- if (text[text_index_2] == '\"')
- break;
-
- substr += text[text_index_2];
- }
- }
-
- if (text[text_index_2] == '{' || text[text_index_2] == '}')
- continue;
-
- if (text[text_index_2] == ';')
- {
- break;
- }
-
- if (text[text_index_2] == ' ' ||
- text[text_index_2] == '\t')
- {
- if (first_encountered != 2)
- {
- if (text[text_index] != '=' &&
- substr.find("public_segment .data64") == std::string::npos &&
- !kInStruct)
- substr += "public_segment .data64 ";
- }
-
- ++first_encountered;
-
- continue;
- }
-
- if (text[text_index_2] == '=')
- {
- if (!kInBraces)
- {
- substr.replace(substr.find("public_segment .data64"),
- strlen("public_segment .data64"), "public_segment .zero64 ");
- }
-
- substr += ",";
- continue;
- }
-
- substr += text[text_index_2];
- }
-
- for (auto& clType : kCompilerTypes)
- {
- if (substr.find(clType.fName) != std::string::npos)
- {
- if (substr.find(clType.fName) > substr.find('"'))
- continue;
-
- substr.erase(substr.find(clType.fName), clType.fName.size());
- }
- else if (substr.find(clType.fValue) != std::string::npos)
- {
- if (substr.find(clType.fValue) > substr.find('"'))
- continue;
-
- if (clType.fName == "const")
- continue;
-
- substr.erase(substr.find(clType.fValue), clType.fValue.size());
- }
- }
-
- if (substr.find("extern") != std::string::npos)
- {
- substr.replace(substr.find("extern"), strlen("extern"), "extern_segment ");
-
- if (substr.find("public_segment .data64") != std::string::npos)
- substr.erase(substr.find("public_segment .data64"), strlen("public_segment .data64"));
- }
-
- auto var_to_find =
- std::find_if(kCompilerVariables.cbegin(), kCompilerVariables.cend(),
- [&](Detail::CompilerType type) {
- return type.fName.find(substr) != std::string::npos;
- });
-
- if (kRegisterCounter == 5 || kRegisterCounter == 6)
- ++kRegisterCounter;
-
- std::string reg = kAsmRegisterPrefix;
- reg += std::to_string(kRegisterCounter);
-
- if (var_to_find == kCompilerVariables.cend())
- {
- ++kRegisterCounter;
-
- kState.kStackFrame.push_back({.fName = substr, .fReg = reg});
- kCompilerVariables.push_back({.fName = substr});
- }
-
- syntaxLeaf.fUserValue += substr;
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
-
- if (text[text_index] == '=')
- break;
- }
-
- // function handler.
-
- if (text[text_index] == '(' && !fnFound && !kIfFound)
- {
- std::string substr;
- std::string args_buffer;
- std::string args;
-
- bool type_crossed = false;
-
- for (size_t idx = text.find('(') + 1; idx < text.size();
- ++idx)
- {
- if (text[idx] == ',')
- continue;
-
- if (text[idx] == ' ')
- continue;
-
- if (text[idx] == ')')
- break;
- }
-
- for (char substr_first_index : text)
- {
- if (substr_first_index != ',')
- args_buffer += substr_first_index;
- else
- args_buffer += '$';
-
- if (substr_first_index == ';')
- {
- args_buffer = args_buffer.erase(0, args_buffer.find('('));
- args_buffer = args_buffer.erase(args_buffer.find(';'), 1);
- args_buffer = args_buffer.erase(args_buffer.find(')'), 1);
- args_buffer = args_buffer.erase(args_buffer.find('('), 1);
+ if (substr.find("extern") != std::string::npos) {
+ substr.replace(substr.find("extern"), strlen("extern"), "extern_segment ");
- if (!args_buffer.empty())
- args += "\tldw r6, ";
+ if (substr.find("public_segment .data64") != std::string::npos)
+ substr.erase(substr.find("public_segment .data64"), strlen("public_segment .data64"));
+ }
- std::string register_type;
- std::size_t index = 7UL;
+ auto var_to_find = std::find_if(
+ kCompilerVariables.cbegin(), kCompilerVariables.cend(),
+ [&](Detail::CompilerType type) { return type.fName.find(substr) != std::string::npos; });
- while (args_buffer.find("$") != std::string::npos)
- {
- register_type = kRegisterPrefix;
- register_type += std::to_string(index);
+ if (kRegisterCounter == 5 || kRegisterCounter == 6) ++kRegisterCounter;
- ++index;
+ std::string reg = kAsmRegisterPrefix;
+ reg += std::to_string(kRegisterCounter);
- args_buffer.replace(args_buffer.find('$'), 1,
- "\n\tldw " + register_type + ",");
- }
+ if (var_to_find == kCompilerVariables.cend()) {
+ ++kRegisterCounter;
- args += args_buffer;
- args += "\n\tlda r19, ";
- }
- }
+ kState.kStackFrame.push_back({.fName = substr, .fReg = reg});
+ kCompilerVariables.push_back({.fName = substr});
+ }
- for (char _text_i : text)
- {
- if (_text_i == '\t' || _text_i == ' ')
- {
- if (!type_crossed)
- {
- substr.clear();
- type_crossed = true;
- }
+ syntaxLeaf.fUserValue += substr;
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
- continue;
- }
+ if (text[text_index] == '=') break;
+ }
- if (_text_i == '(')
- break;
+ // function handler.
- substr += _text_i;
- }
+ if (text[text_index] == '(' && !fnFound && !kIfFound) {
+ std::string substr;
+ std::string args_buffer;
+ std::string args;
- if (kInBraces)
- {
- syntaxLeaf.fUserValue = args;
- syntaxLeaf.fUserValue += substr;
- syntaxLeaf.fUserValue += "\n\tjrl\n";
+ bool type_crossed = false;
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+ for (size_t idx = text.find('(') + 1; idx < text.size(); ++idx) {
+ if (text[idx] == ',') continue;
- fnFound = true;
- }
- else
- {
- syntaxLeaf.fUserValue.clear();
+ if (text[idx] == ' ') continue;
- syntaxLeaf.fUserValue += "public_segment .code64 ";
+ if (text[idx] == ')') break;
+ }
- syntaxLeaf.fUserValue += substr;
- syntaxLeaf.fUserValue += "\n";
+ for (char substr_first_index : text) {
+ if (substr_first_index != ',')
+ args_buffer += substr_first_index;
+ else
+ args_buffer += '$';
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+ if (substr_first_index == ';') {
+ args_buffer = args_buffer.erase(0, args_buffer.find('('));
+ args_buffer = args_buffer.erase(args_buffer.find(';'), 1);
+ args_buffer = args_buffer.erase(args_buffer.find(')'), 1);
+ args_buffer = args_buffer.erase(args_buffer.find('('), 1);
- fnFound = true;
- }
+ if (!args_buffer.empty()) args += "\tldw r6, ";
- kCompilerFunctions.push_back(text);
- }
+ std::string register_type;
+ std::size_t index = 7UL;
- if (text[text_index] == '-' && text[text_index + 1] == '-')
- {
- text = text.replace(text.find("--"), strlen("--"), "");
+ while (args_buffer.find("$") != std::string::npos) {
+ register_type = kRegisterPrefix;
+ register_type += std::to_string(index);
- for (int _text_i = 0; _text_i < text.size(); ++_text_i)
- {
- if (text[_text_i] == '\t' || text[_text_i] == ' ')
- text.erase(_text_i, 1);
- }
+ ++index;
- syntaxLeaf.fUserValue += "sub ";
- syntaxLeaf.fUserValue += text;
+ args_buffer.replace(args_buffer.find('$'), 1, "\n\tldw " + register_type + ",");
+ }
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
- break;
- }
+ args += args_buffer;
+ args += "\n\tlda r19, ";
+ }
+ }
- if (text[text_index] == '}')
- {
- kRegisterCounter = kStartUsable;
+ for (char _text_i : text) {
+ if (_text_i == '\t' || _text_i == ' ') {
+ if (!type_crossed) {
+ substr.clear();
+ type_crossed = true;
+ }
- --kBracesCount;
+ continue;
+ }
- if (kBracesCount < 1)
- {
- kInBraces = false;
- kBracesCount = 0;
- }
+ if (_text_i == '(') break;
- if (kIfFound)
- kIfFound = false;
+ substr += _text_i;
+ }
- if (kInStruct)
- kInStruct = false;
+ if (kInBraces) {
+ syntaxLeaf.fUserValue = args;
+ syntaxLeaf.fUserValue += substr;
+ syntaxLeaf.fUserValue += "\n\tjrl\n";
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
- }
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
- syntaxLeaf.fUserValue.clear();
- }
+ fnFound = true;
+ } else {
+ syntaxLeaf.fUserValue.clear();
- auto syntaxLeaf = LibCompiler::SyntaxLeafList::SyntaxLeaf();
- syntaxLeaf.fUserValue = "\n";
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+ syntaxLeaf.fUserValue += "public_segment .code64 ";
- return true;
+ syntaxLeaf.fUserValue += substr;
+ syntaxLeaf.fUserValue += "\n";
+
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+
+ fnFound = true;
+ }
+
+ kCompilerFunctions.push_back(text);
+ }
+
+ if (text[text_index] == '-' && text[text_index + 1] == '-') {
+ text = text.replace(text.find("--"), strlen("--"), "");
+
+ for (int _text_i = 0; _text_i < text.size(); ++_text_i) {
+ if (text[_text_i] == '\t' || text[_text_i] == ' ') text.erase(_text_i, 1);
+ }
+
+ syntaxLeaf.fUserValue += "sub ";
+ syntaxLeaf.fUserValue += text;
+
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+ break;
+ }
+
+ if (text[text_index] == '}') {
+ kRegisterCounter = kStartUsable;
+
+ --kBracesCount;
+
+ if (kBracesCount < 1) {
+ kInBraces = false;
+ kBracesCount = 0;
+ }
+
+ if (kIfFound) kIfFound = false;
+
+ if (kInStruct) kInStruct = false;
+
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+ }
+
+ syntaxLeaf.fUserValue.clear();
+ }
+
+ auto syntaxLeaf = LibCompiler::SyntaxLeafList::SyntaxLeaf();
+ syntaxLeaf.fUserValue = "\n";
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+
+ return true;
}
-static bool kShouldHaveBraces = false;
+static bool kShouldHaveBraces = false;
static std::string kFnName;
-std::string CompilerFrontendARM64::Check(const char* text, const char* file)
-{
- std::string err_str;
- std::string ln = text;
-
- if (ln.empty())
- {
- return err_str;
- }
-
- bool non_ascii_found = false;
-
- for (int i = 0; i < ln.size(); ++i)
- {
- if (isalnum(ln[i]))
- {
- non_ascii_found = true;
- break;
- }
- }
-
- if (kShouldHaveBraces && ln.find('{') != std::string::npos)
- {
- kShouldHaveBraces = false;
- }
-
- if (!non_ascii_found)
- return err_str;
-
- size_t string_index = 1UL;
-
- if (ln.find('\'') != std::string::npos)
- {
- string_index = ln.find('\'') + 1;
-
- for (; string_index < ln.size(); ++string_index)
- {
- if (ln[string_index] == '\'')
- {
- if (ln[string_index + 1] != ';')
- {
- ln.erase(string_index, 1);
- }
-
- return err_str;
- }
- }
- }
- else if (ln.find('"') != std::string::npos)
- {
- string_index = ln.find('"') + 1;
-
- for (; string_index < ln.size(); ++string_index)
- {
- if (ln[string_index] == '"')
- {
- if (ln[string_index + 1] != ';')
- {
- ln.erase(string_index, 1);
- }
- else
- {
- break;
- }
- }
- }
- }
- else if (ln.find('"') == std::string::npos &&
- ln.find('\'') == std::string::npos)
- {
- std::vector<std::string> forbidden_words;
-
- forbidden_words.push_back("\\");
- forbidden_words.push_back("?");
- forbidden_words.push_back("@");
- forbidden_words.push_back("~");
- forbidden_words.push_back("::");
- forbidden_words.push_back("--*");
- forbidden_words.push_back("*/");
-
- // add them to avoid stupid mistakes.
- forbidden_words.push_back("namespace");
- forbidden_words.push_back("class");
- forbidden_words.push_back("extern \"C\"");
-
- for (auto& forbidden : forbidden_words)
- {
- if (ln.find(forbidden) != std::string::npos)
- {
- err_str += "\nForbidden character detected: ";
- err_str += forbidden;
-
- return err_str;
- }
- }
- }
-
- struct CompilerVariableRange final
- {
- std::string fBegin;
- std::string fEnd;
- };
-
- const std::vector<CompilerVariableRange> variables_list = {
- {.fBegin = "static ", .fEnd = "="},
- {.fBegin = "=", .fEnd = ";"},
- {.fBegin = "if(", .fEnd = "="},
- {.fBegin = "if (", .fEnd = "="},
- {.fBegin = "if(", .fEnd = "<"},
- {.fBegin = "if (", .fEnd = "<"},
- {.fBegin = "if(", .fEnd = ">"},
- {.fBegin = "if (", .fEnd = ">"},
- {.fBegin = "if(", .fEnd = ")"},
- {.fBegin = "if (", .fEnd = ")"},
-
- {.fBegin = "else(", .fEnd = "="},
- {.fBegin = "else (", .fEnd = "="},
- {.fBegin = "else(", .fEnd = "<"},
- {.fBegin = "else (", .fEnd = "<"},
- {.fBegin = "else(", .fEnd = ">"},
- {.fBegin = "else (", .fEnd = ">"},
- {.fBegin = "else(", .fEnd = ")"},
- {.fBegin = "else (", .fEnd = ")"},
- };
-
- for (auto& variable : variables_list)
- {
- if (ln.find(variable.fBegin) != std::string::npos)
- {
- string_index = ln.find(variable.fBegin) + variable.fBegin.size();
-
- while (ln[string_index] == ' ')
- ++string_index;
-
- std::string keyword;
-
- for (; string_index < ln.size(); ++string_index)
- {
- if (ln[string_index] == variable.fEnd[0])
- {
- std::string varname = "";
-
- for (size_t index_keyword = ln.find(' ');
- ln[index_keyword] != variable.fBegin[0]; ++index_keyword)
- {
- if (ln[index_keyword] == ' ')
- {
- continue;
- }
-
- if (isdigit(ln[index_keyword]))
- {
- goto cc_next_loop;
- }
-
- varname += ln[index_keyword];
- }
-
- if (varname.find(' ') != std::string::npos)
- {
- varname.erase(0, varname.find(' '));
-
- if (variable.fBegin == "extern")
- {
- varname.erase(0, varname.find(' '));
- }
- }
-
- if (kRegisterCounter == 5 || kRegisterCounter == 6)
- ++kRegisterCounter;
-
- std::string reg = kAsmRegisterPrefix;
- reg += std::to_string(kRegisterCounter);
-
- kCompilerVariables.push_back({.fValue = varname});
- goto cc_check_done;
- }
-
- keyword.push_back(ln[string_index]);
- }
-
- goto cc_next_loop;
-
- cc_check_done:
-
- // skip digit value.
- if (isdigit(keyword[0]) || keyword[0] == '"')
- {
- goto cc_next_loop;
- }
-
- while (keyword.find(' ') != std::string::npos)
- keyword.erase(keyword.find(' '), 1);
-
- for (auto& var : kCompilerVariables)
- {
- if (var.fValue.find(keyword) != std::string::npos)
- {
- err_str.clear();
- goto cc_next;
- }
- }
-
- for (auto& fn : kCompilerFunctions)
- {
- if (fn.find(keyword[0]) != std::string::npos)
- {
- auto where_begin = fn.find(keyword[0]);
- auto keyword_begin = 0UL;
- auto failed = false;
-
- for (; where_begin < keyword.size(); ++where_begin)
- {
- if (fn[where_begin] == '(' && keyword[keyword_begin] == '(')
- break;
-
- if (fn[where_begin] != keyword[keyword_begin])
- {
- failed = true;
- break;
- }
-
- ++keyword_begin;
- }
-
- if (!failed)
- {
- err_str.clear();
- goto cc_next;
- }
- else
- {
- continue;
- }
- }
- }
-
- cc_error_value:
- if (keyword.find("->") != std::string::npos)
- return err_str;
-
- if (keyword.find(".") != std::string::npos)
- return err_str;
-
- if (isalnum(keyword[0]))
- err_str += "\nUndefined value: " + keyword;
-
- return err_str;
- }
-
- cc_next_loop:
- continue;
- }
+std::string CompilerFrontendARM64::Check(const char* text, const char* file) {
+ std::string err_str;
+ std::string ln = text;
+
+ if (ln.empty()) {
+ return err_str;
+ }
+
+ bool non_ascii_found = false;
+
+ for (int i = 0; i < ln.size(); ++i) {
+ if (isalnum(ln[i])) {
+ non_ascii_found = true;
+ break;
+ }
+ }
+
+ if (kShouldHaveBraces && ln.find('{') != std::string::npos) {
+ kShouldHaveBraces = false;
+ }
+
+ if (!non_ascii_found) return err_str;
+
+ size_t string_index = 1UL;
+
+ if (ln.find('\'') != std::string::npos) {
+ string_index = ln.find('\'') + 1;
+
+ for (; string_index < ln.size(); ++string_index) {
+ if (ln[string_index] == '\'') {
+ if (ln[string_index + 1] != ';') {
+ ln.erase(string_index, 1);
+ }
+
+ return err_str;
+ }
+ }
+ } else if (ln.find('"') != std::string::npos) {
+ string_index = ln.find('"') + 1;
+
+ for (; string_index < ln.size(); ++string_index) {
+ if (ln[string_index] == '"') {
+ if (ln[string_index + 1] != ';') {
+ ln.erase(string_index, 1);
+ } else {
+ break;
+ }
+ }
+ }
+ } else if (ln.find('"') == std::string::npos && ln.find('\'') == std::string::npos) {
+ std::vector<std::string> forbidden_words;
+
+ forbidden_words.push_back("\\");
+ forbidden_words.push_back("?");
+ forbidden_words.push_back("@");
+ forbidden_words.push_back("~");
+ forbidden_words.push_back("::");
+ forbidden_words.push_back("--*");
+ forbidden_words.push_back("*/");
+
+ // add them to avoid stupid mistakes.
+ forbidden_words.push_back("namespace");
+ forbidden_words.push_back("class");
+ forbidden_words.push_back("extern \"C\"");
+
+ for (auto& forbidden : forbidden_words) {
+ if (ln.find(forbidden) != std::string::npos) {
+ err_str += "\nForbidden character detected: ";
+ err_str += forbidden;
+
+ return err_str;
+ }
+ }
+ }
+
+ struct CompilerVariableRange final {
+ std::string fBegin;
+ std::string fEnd;
+ };
+
+ const std::vector<CompilerVariableRange> variables_list = {
+ {.fBegin = "static ", .fEnd = "="}, {.fBegin = "=", .fEnd = ";"},
+ {.fBegin = "if(", .fEnd = "="}, {.fBegin = "if (", .fEnd = "="},
+ {.fBegin = "if(", .fEnd = "<"}, {.fBegin = "if (", .fEnd = "<"},
+ {.fBegin = "if(", .fEnd = ">"}, {.fBegin = "if (", .fEnd = ">"},
+ {.fBegin = "if(", .fEnd = ")"}, {.fBegin = "if (", .fEnd = ")"},
+
+ {.fBegin = "else(", .fEnd = "="}, {.fBegin = "else (", .fEnd = "="},
+ {.fBegin = "else(", .fEnd = "<"}, {.fBegin = "else (", .fEnd = "<"},
+ {.fBegin = "else(", .fEnd = ">"}, {.fBegin = "else (", .fEnd = ">"},
+ {.fBegin = "else(", .fEnd = ")"}, {.fBegin = "else (", .fEnd = ")"},
+ };
+
+ for (auto& variable : variables_list) {
+ if (ln.find(variable.fBegin) != std::string::npos) {
+ string_index = ln.find(variable.fBegin) + variable.fBegin.size();
+
+ while (ln[string_index] == ' ') ++string_index;
+
+ std::string keyword;
+
+ for (; string_index < ln.size(); ++string_index) {
+ if (ln[string_index] == variable.fEnd[0]) {
+ std::string varname = "";
+
+ for (size_t index_keyword = ln.find(' '); ln[index_keyword] != variable.fBegin[0];
+ ++index_keyword) {
+ if (ln[index_keyword] == ' ') {
+ continue;
+ }
+
+ if (isdigit(ln[index_keyword])) {
+ goto cc_next_loop;
+ }
+
+ varname += ln[index_keyword];
+ }
+
+ if (varname.find(' ') != std::string::npos) {
+ varname.erase(0, varname.find(' '));
+
+ if (variable.fBegin == "extern") {
+ varname.erase(0, varname.find(' '));
+ }
+ }
+
+ if (kRegisterCounter == 5 || kRegisterCounter == 6) ++kRegisterCounter;
+
+ std::string reg = kAsmRegisterPrefix;
+ reg += std::to_string(kRegisterCounter);
+
+ kCompilerVariables.push_back({.fValue = varname});
+ goto cc_check_done;
+ }
+
+ keyword.push_back(ln[string_index]);
+ }
+
+ goto cc_next_loop;
+
+ cc_check_done:
+
+ // skip digit value.
+ if (isdigit(keyword[0]) || keyword[0] == '"') {
+ goto cc_next_loop;
+ }
+
+ while (keyword.find(' ') != std::string::npos) keyword.erase(keyword.find(' '), 1);
+
+ for (auto& var : kCompilerVariables) {
+ if (var.fValue.find(keyword) != std::string::npos) {
+ err_str.clear();
+ goto cc_next;
+ }
+ }
+
+ for (auto& fn : kCompilerFunctions) {
+ if (fn.find(keyword[0]) != std::string::npos) {
+ auto where_begin = fn.find(keyword[0]);
+ auto keyword_begin = 0UL;
+ auto failed = false;
+
+ for (; where_begin < keyword.size(); ++where_begin) {
+ if (fn[where_begin] == '(' && keyword[keyword_begin] == '(') break;
+
+ if (fn[where_begin] != keyword[keyword_begin]) {
+ failed = true;
+ break;
+ }
+
+ ++keyword_begin;
+ }
+
+ if (!failed) {
+ err_str.clear();
+ goto cc_next;
+ } else {
+ continue;
+ }
+ }
+ }
+
+ cc_error_value:
+ if (keyword.find("->") != std::string::npos) return err_str;
+
+ if (keyword.find(".") != std::string::npos) return err_str;
+
+ if (isalnum(keyword[0])) err_str += "\nUndefined value: " + keyword;
+
+ return err_str;
+ }
+
+ cc_next_loop:
+ continue;
+ }
cc_next:
- // extern does not declare anything, it extern_segments a variable.
- // so that's why it's not declare upper.
- if (LibCompiler::find_word(ln, "extern"))
- {
- auto substr = ln.substr(ln.find("extern") + strlen("extern"));
- kCompilerVariables.push_back({.fValue = substr});
- }
-
- if (kShouldHaveBraces && ln.find('{') == std::string::npos)
- {
- err_str += "Missing '{' for function ";
- err_str += kFnName;
- err_str += "\n";
-
- kShouldHaveBraces = false;
- kFnName.clear();
- }
- else if (kShouldHaveBraces && ln.find('{') != std::string::npos)
- {
- kShouldHaveBraces = false;
- kFnName.clear();
- }
-
- bool type_not_found = true;
-
- if (ln.find('\'') != std::string::npos)
- {
- ln.replace(ln.find('\''), 3, "0");
- }
-
- auto first = ln.find('"');
- if (first != std::string::npos)
- {
- auto second = 0UL;
- bool found_second_quote = false;
-
- for (size_t i = first + 1; i < ln.size(); ++i)
- {
- if (ln[i] == '\"')
- {
- found_second_quote = true;
- second = i;
-
- break;
- }
- }
-
- if (!found_second_quote)
- {
- err_str += "Missing terminating \".";
- err_str += " here -> " + ln.substr(ln.find('"'), second);
- }
- }
-
- if (ln.find(')') != std::string::npos && ln.find(';') == std::string::npos)
- {
- if (ln.find('{') == std::string::npos)
- {
- kFnName = ln;
- kShouldHaveBraces = true;
-
- goto skip_braces_check;
- }
- else if (ln.find('{') != std::string::npos)
- {
- kShouldHaveBraces = false;
- }
- }
+ // extern does not declare anything, it extern_segments a variable.
+ // so that's why it's not declare upper.
+ if (LibCompiler::find_word(ln, "extern")) {
+ auto substr = ln.substr(ln.find("extern") + strlen("extern"));
+ kCompilerVariables.push_back({.fValue = substr});
+ }
+
+ if (kShouldHaveBraces && ln.find('{') == std::string::npos) {
+ err_str += "Missing '{' for function ";
+ err_str += kFnName;
+ err_str += "\n";
+
+ kShouldHaveBraces = false;
+ kFnName.clear();
+ } else if (kShouldHaveBraces && ln.find('{') != std::string::npos) {
+ kShouldHaveBraces = false;
+ kFnName.clear();
+ }
+
+ bool type_not_found = true;
+
+ if (ln.find('\'') != std::string::npos) {
+ ln.replace(ln.find('\''), 3, "0");
+ }
+
+ auto first = ln.find('"');
+ if (first != std::string::npos) {
+ auto second = 0UL;
+ bool found_second_quote = false;
+
+ for (size_t i = first + 1; i < ln.size(); ++i) {
+ if (ln[i] == '\"') {
+ found_second_quote = true;
+ second = i;
+
+ break;
+ }
+ }
+
+ if (!found_second_quote) {
+ err_str += "Missing terminating \".";
+ err_str += " here -> " + ln.substr(ln.find('"'), second);
+ }
+ }
+
+ if (ln.find(')') != std::string::npos && ln.find(';') == std::string::npos) {
+ if (ln.find('{') == std::string::npos) {
+ kFnName = ln;
+ kShouldHaveBraces = true;
+
+ goto skip_braces_check;
+ } else if (ln.find('{') != std::string::npos) {
+ kShouldHaveBraces = false;
+ }
+ }
skip_braces_check:
- for (auto& key : kCompilerTypes)
- {
- if (LibCompiler::find_word(ln, key.fName))
- {
- if (isdigit(ln[ln.find(key.fName) + key.fName.size() + 1]))
- {
- err_str += "\nNumber cannot be set for ";
- err_str += key.fName;
- err_str += "'s name. here -> ";
- err_str += ln;
- }
-
- if (ln.find(key.fName) == 0 || ln[ln.find(key.fName) - 1] == ' ' ||
- ln[ln.find(key.fName) - 1] == '\t')
- {
- type_not_found = false;
-
- if (ln[ln.find(key.fName) + key.fName.size()] != ' ')
- {
- type_not_found = true;
-
- if (ln[ln.find(key.fName) + key.fName.size()] == '\t')
- type_not_found = false;
-
- goto next;
- }
- else if (ln[ln.find(key.fName) + key.fName.size()] != '\t')
- {
- type_not_found = true;
-
- if (ln[ln.find(key.fName) + key.fName.size()] == ' ')
- type_not_found = false;
- }
- }
-
- next:
-
- if (ln.find(';') == std::string::npos)
- {
- if (ln.find('(') != std::string::npos)
- {
- if (ln.find('=') == std::string::npos)
- continue;
- }
-
- err_str += "\nMissing ';', here -> ";
- err_str += ln;
- }
- else
- {
- continue;
- }
-
- if (ln.find('=') != std::string::npos)
- {
- if (ln.find('(') != std::string::npos)
- {
- if (ln.find(')') == std::string::npos)
- {
- err_str += "\nMissing ')', after '(' here -> ";
- err_str += ln.substr(ln.find('('));
- }
- }
- }
- }
- }
-
- if (kInBraces && ln.find("struct") != std::string::npos &&
- ln.find("union") != std::string::npos &&
- ln.find("enum") != std::string::npos &&
- ln.find('=') != std::string::npos)
- {
- if (ln.find(';') == std::string::npos)
- {
- err_str += "\nMissing ';' after struct/union/enum declaration, here -> ";
- err_str += ln;
- }
- }
-
- if (ln.find(';') != std::string::npos &&
- ln.find("for") == std::string::npos)
- {
- if (ln.find(';') + 1 != ln.size())
- {
- for (int i = 0; i < ln.substr(ln.find(';') + 1).size(); ++i)
- {
- if ((ln.substr(ln.find(';') + 1)[i] != ' ') ||
- (ln.substr(ln.find(';') + 1)[i] != '\t'))
- {
- if (auto err = this->Check(ln.substr(ln.find(';') + 1).c_str(), file);
- !err.empty())
- {
- err_str += "\nUnexpected text after ';' -> ";
- err_str += ln.substr(ln.find(';'));
- err_str += err;
- }
- }
- }
- }
- }
-
- if (ln.find('(') != std::string::npos)
- {
- if (ln.find(';') == std::string::npos && !LibCompiler::find_word(ln, "|") &&
- !LibCompiler::find_word(ln, "||") && !LibCompiler::find_word(ln, "&") &&
- !LibCompiler::find_word(ln, "&&") && !LibCompiler::find_word(ln, "~"))
- {
- bool found_func = false;
- size_t i = ln.find('(');
- std::vector<char> opens;
- std::vector<char> closes;
-
- for (; i < ln.size(); ++i)
- {
- if (ln[i] == ')')
- {
- closes.push_back(1);
- }
-
- if (ln[i] == '(')
- {
- opens.push_back(1);
- }
- }
-
- if (closes.size() != opens.size())
- err_str += "Unterminated (), here -> " + ln;
-
- bool space_found = false;
-
- for (int i = 0; i < ln.size(); ++i)
- {
- if (ln[i] == ')' && !space_found)
- {
- space_found = true;
- continue;
- }
-
- if (space_found)
- {
- if (ln[i] == ' ' && isalnum(ln[i + 1]))
- {
- err_str += "\nBad function format here -> ";
- err_str += ln;
- }
- }
- }
- }
-
- if (ln.find('(') < 1)
- {
- err_str += "\nMissing identifier before '(' here -> ";
- err_str += ln;
- }
- else
- {
- if (type_not_found && ln.find(';') == std::string::npos &&
- ln.find("if") == std::string::npos &&
- ln.find("|") == std::string::npos &&
- ln.find("&") == std::string::npos &&
- ln.find("(") == std::string::npos &&
- ln.find(")") == std::string::npos)
- {
- err_str += "\n Missing ';' or type, here -> ";
- err_str += ln;
- }
- }
-
- if (ln.find(')') == std::string::npos)
- {
- err_str += "\nMissing ')', after '(' here -> ";
- err_str += ln.substr(ln.find('('));
- }
- }
- else
- {
- if (ln.find("for") != std::string::npos ||
- ln.find("while") != std::string::npos)
- {
- err_str += "\nMissing '(', after \"for\", here -> ";
- err_str += ln;
- }
- }
-
- if (ln.find('}') != std::string::npos && !kInBraces)
- {
- if (!kInStruct && ln.find(';') == std::string::npos)
- {
- err_str += "\nMismatched '}', here -> ";
- err_str += ln;
- }
- }
-
- if (!ln.empty())
- {
- if (ln.find(';') == std::string::npos &&
- ln.find('{') == std::string::npos &&
- ln.find('}') == std::string::npos &&
- ln.find(')') == std::string::npos &&
- ln.find('(') == std::string::npos &&
- ln.find(',') == std::string::npos)
- {
- if (ln.size() <= 2)
- return err_str;
-
- err_str += "\nMissing ';', here -> ";
- err_str += ln;
- }
- }
-
- return err_str;
+ for (auto& key : kCompilerTypes) {
+ if (LibCompiler::find_word(ln, key.fName)) {
+ if (isdigit(ln[ln.find(key.fName) + key.fName.size() + 1])) {
+ err_str += "\nNumber cannot be set for ";
+ err_str += key.fName;
+ err_str += "'s name. here -> ";
+ err_str += ln;
+ }
+
+ if (ln.find(key.fName) == 0 || ln[ln.find(key.fName) - 1] == ' ' ||
+ ln[ln.find(key.fName) - 1] == '\t') {
+ type_not_found = false;
+
+ if (ln[ln.find(key.fName) + key.fName.size()] != ' ') {
+ type_not_found = true;
+
+ if (ln[ln.find(key.fName) + key.fName.size()] == '\t') type_not_found = false;
+
+ goto next;
+ } else if (ln[ln.find(key.fName) + key.fName.size()] != '\t') {
+ type_not_found = true;
+
+ if (ln[ln.find(key.fName) + key.fName.size()] == ' ') type_not_found = false;
+ }
+ }
+
+ next:
+
+ if (ln.find(';') == std::string::npos) {
+ if (ln.find('(') != std::string::npos) {
+ if (ln.find('=') == std::string::npos) continue;
+ }
+
+ err_str += "\nMissing ';', here -> ";
+ err_str += ln;
+ } else {
+ continue;
+ }
+
+ if (ln.find('=') != std::string::npos) {
+ if (ln.find('(') != std::string::npos) {
+ if (ln.find(')') == std::string::npos) {
+ err_str += "\nMissing ')', after '(' here -> ";
+ err_str += ln.substr(ln.find('('));
+ }
+ }
+ }
+ }
+ }
+
+ if (kInBraces && ln.find("struct") != std::string::npos &&
+ ln.find("union") != std::string::npos && ln.find("enum") != std::string::npos &&
+ ln.find('=') != std::string::npos) {
+ if (ln.find(';') == std::string::npos) {
+ err_str += "\nMissing ';' after struct/union/enum declaration, here -> ";
+ err_str += ln;
+ }
+ }
+
+ if (ln.find(';') != std::string::npos && ln.find("for") == std::string::npos) {
+ if (ln.find(';') + 1 != ln.size()) {
+ for (int i = 0; i < ln.substr(ln.find(';') + 1).size(); ++i) {
+ if ((ln.substr(ln.find(';') + 1)[i] != ' ') || (ln.substr(ln.find(';') + 1)[i] != '\t')) {
+ if (auto err = this->Check(ln.substr(ln.find(';') + 1).c_str(), file); !err.empty()) {
+ err_str += "\nUnexpected text after ';' -> ";
+ err_str += ln.substr(ln.find(';'));
+ err_str += err;
+ }
+ }
+ }
+ }
+ }
+
+ if (ln.find('(') != std::string::npos) {
+ if (ln.find(';') == std::string::npos && !LibCompiler::find_word(ln, "|") &&
+ !LibCompiler::find_word(ln, "||") && !LibCompiler::find_word(ln, "&") &&
+ !LibCompiler::find_word(ln, "&&") && !LibCompiler::find_word(ln, "~")) {
+ bool found_func = false;
+ size_t i = ln.find('(');
+ std::vector<char> opens;
+ std::vector<char> closes;
+
+ for (; i < ln.size(); ++i) {
+ if (ln[i] == ')') {
+ closes.push_back(1);
+ }
+
+ if (ln[i] == '(') {
+ opens.push_back(1);
+ }
+ }
+
+ if (closes.size() != opens.size()) err_str += "Unterminated (), here -> " + ln;
+
+ bool space_found = false;
+
+ for (int i = 0; i < ln.size(); ++i) {
+ if (ln[i] == ')' && !space_found) {
+ space_found = true;
+ continue;
+ }
+
+ if (space_found) {
+ if (ln[i] == ' ' && isalnum(ln[i + 1])) {
+ err_str += "\nBad function format here -> ";
+ err_str += ln;
+ }
+ }
+ }
+ }
+
+ if (ln.find('(') < 1) {
+ err_str += "\nMissing identifier before '(' here -> ";
+ err_str += ln;
+ } else {
+ if (type_not_found && ln.find(';') == std::string::npos &&
+ ln.find("if") == std::string::npos && ln.find("|") == std::string::npos &&
+ ln.find("&") == std::string::npos && ln.find("(") == std::string::npos &&
+ ln.find(")") == std::string::npos) {
+ err_str += "\n Missing ';' or type, here -> ";
+ err_str += ln;
+ }
+ }
+
+ if (ln.find(')') == std::string::npos) {
+ err_str += "\nMissing ')', after '(' here -> ";
+ err_str += ln.substr(ln.find('('));
+ }
+ } else {
+ if (ln.find("for") != std::string::npos || ln.find("while") != std::string::npos) {
+ err_str += "\nMissing '(', after \"for\", here -> ";
+ err_str += ln;
+ }
+ }
+
+ if (ln.find('}') != std::string::npos && !kInBraces) {
+ if (!kInStruct && ln.find(';') == std::string::npos) {
+ err_str += "\nMismatched '}', here -> ";
+ err_str += ln;
+ }
+ }
+
+ if (!ln.empty()) {
+ if (ln.find(';') == std::string::npos && ln.find('{') == std::string::npos &&
+ ln.find('}') == std::string::npos && ln.find(')') == std::string::npos &&
+ ln.find('(') == std::string::npos && ln.find(',') == std::string::npos) {
+ if (ln.size() <= 2) return err_str;
+
+ err_str += "\nMissing ';', here -> ";
+ err_str += ln;
+ }
+ }
+
+ return err_str;
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -1292,186 +1043,146 @@ skip_braces_check:
/////////////////////////////////////////////////////////////////////////////////////////
-class AssemblyCCInterface final ASSEMBLY_INTERFACE
-{
-public:
- explicit AssemblyCCInterface() = default;
- ~AssemblyCCInterface() override = default;
-
- LIBCOMPILER_COPY_DEFAULT(AssemblyCCInterface);
-
- [[maybe_unused]] static Int32 Arch() noexcept
- {
- return LibCompiler::AssemblyFactory::kArchAARCH64;
- }
-
- Int32 CompileToFormat(std::string& src, Int32 arch) override
- {
- if (arch != AssemblyCCInterface::Arch())
- return 1;
-
- if (kCompilerFrontend == nullptr)
- return 1;
-
- /* @brief copy contents wihtout extension */
- std::string src_file = src.data();
- std::ifstream src_fp = std::ifstream(src_file, std::ios::in);
- std::string dest;
-
- for (auto& ch : src_file)
- {
- if (ch == '.')
- {
- break;
- }
-
- dest += ch;
- }
-
- /* According to PEF ABI. */
- std::vector<const char*> exts = kAsmFileExts;
- dest += exts[4];
-
- kState.fOutputAssembly = std::make_unique<std::ofstream>(dest);
-
- auto fmt = LibCompiler::current_date();
-
- (*kState.fOutputAssembly) << "# Path: " << src_file << "\n";
- (*kState.fOutputAssembly)
- << "# Language: ARM64 Assembly (Generated from ANSI C)\n";
- (*kState.fOutputAssembly) << "# Date: " << fmt << "\n\n";
-
- LibCompiler::SyntaxLeafList syntax;
-
- kState.fSyntaxTreeList.push_back(syntax);
- kState.fSyntaxTree =
- &kState.fSyntaxTreeList[kState.fSyntaxTreeList.size() - 1];
-
- std::string line_src;
-
- while (std::getline(src_fp, line_src))
- {
- if (auto err = kCompilerFrontend->Check(line_src.c_str(), src.data());
- err.empty())
- {
- kCompilerFrontend->Compile(line_src, src.data());
- }
- else
- {
- Detail::print_error(err, src.data());
- }
- }
-
- if (kAcceptableErrors > 0)
- return 1;
-
- std::vector<std::string> keywords = {"ldw", "stw", "lda", "sta",
- "add", "sub", "mv"};
-
- ///
- /// Replace, optimize, fix assembly output.
- ///
-
- for (auto& leaf : kState.fSyntaxTree->fLeafList)
- {
- std::vector<std::string> access_keywords = {"->", "."};
-
- for (auto& access_ident : access_keywords)
- {
- if (LibCompiler::find_word(leaf.fUserValue, access_ident))
- {
- for (auto& struc : kState.kStructMap)
- {
- /// TODO:
- }
- }
- }
-
- for (auto& keyword : keywords)
- {
- if (LibCompiler::find_word(leaf.fUserValue, keyword))
- {
- std::size_t cnt = 0UL;
-
- for (auto& reg : kState.kStackFrame)
- {
- std::string needle;
-
- for (size_t i = 0; i < reg.fName.size(); i++)
- {
- if (reg.fName[i] == ' ')
- {
- ++i;
-
- for (; i < reg.fName.size(); i++)
- {
- if (reg.fName[i] == ',')
- {
- break;
- }
-
- if (reg.fName[i] == ' ')
- continue;
-
- needle += reg.fName[i];
- }
-
- break;
- }
- }
-
- if (LibCompiler::find_word(leaf.fUserValue, needle))
- {
- if (leaf.fUserValue.find("extern_segment " + needle) !=
- std::string::npos)
- {
- std::string range = "extern_segment " + needle;
- leaf.fUserValue.replace(
- leaf.fUserValue.find("extern_segment " + needle), range.size(),
- needle);
- }
-
- if (leaf.fUserValue.find("ldw r6") != std::string::npos)
- {
- std::string::difference_type countComma = std::count(
- leaf.fUserValue.begin(), leaf.fUserValue.end(), ',');
-
- if (countComma == 1)
- {
- leaf.fUserValue.replace(leaf.fUserValue.find("ldw"),
- strlen("ldw"), "mv");
- }
- }
-
- leaf.fUserValue.replace(leaf.fUserValue.find(needle),
- needle.size(), reg.fReg);
-
- ++cnt;
- }
- }
-
- if (cnt > 1 && keyword != "mv" && keyword != "add" &&
- keyword != "sub")
- {
- leaf.fUserValue.replace(leaf.fUserValue.find(keyword),
- keyword.size(), "mv");
- }
- }
- }
- }
-
- for (auto& leaf : kState.fSyntaxTree->fLeafList)
- {
- (*kState.fOutputAssembly) << leaf.fUserValue;
- }
-
- kState.fSyntaxTree = nullptr;
-
- kState.fOutputAssembly->flush();
- kState.fOutputAssembly.reset();
-
- return kExitOK;
- }
+class AssemblyCCInterface final ASSEMBLY_INTERFACE {
+ public:
+ explicit AssemblyCCInterface() = default;
+ ~AssemblyCCInterface() override = default;
+
+ LIBCOMPILER_COPY_DEFAULT(AssemblyCCInterface);
+
+ [[maybe_unused]] static Int32 Arch() noexcept {
+ return LibCompiler::AssemblyFactory::kArchAARCH64;
+ }
+
+ Int32 CompileToFormat(std::string& src, Int32 arch) override {
+ if (arch != AssemblyCCInterface::Arch()) return 1;
+
+ if (kCompilerFrontend == nullptr) return 1;
+
+ /* @brief copy contents wihtout extension */
+ std::string src_file = src.data();
+ std::ifstream src_fp = std::ifstream(src_file, std::ios::in);
+ std::string dest;
+
+ for (auto& ch : src_file) {
+ if (ch == '.') {
+ break;
+ }
+
+ dest += ch;
+ }
+
+ /* According to PEF ABI. */
+ std::vector<const char*> exts = kAsmFileExts;
+ dest += exts[4];
+
+ kState.fOutputAssembly = std::make_unique<std::ofstream>(dest);
+
+ auto fmt = LibCompiler::current_date();
+
+ (*kState.fOutputAssembly) << "# Path: " << src_file << "\n";
+ (*kState.fOutputAssembly) << "# Language: ARM64 Assembly (Generated from ANSI C)\n";
+ (*kState.fOutputAssembly) << "# Date: " << fmt << "\n\n";
+
+ LibCompiler::SyntaxLeafList syntax;
+
+ kState.fSyntaxTreeList.push_back(syntax);
+ kState.fSyntaxTree = &kState.fSyntaxTreeList[kState.fSyntaxTreeList.size() - 1];
+
+ std::string line_src;
+
+ while (std::getline(src_fp, line_src)) {
+ if (auto err = kCompilerFrontend->Check(line_src.c_str(), src.data()); err.empty()) {
+ kCompilerFrontend->Compile(line_src, src.data());
+ } else {
+ Detail::print_error(err, src.data());
+ }
+ }
+
+ if (kAcceptableErrors > 0) return 1;
+
+ std::vector<std::string> keywords = {"ldw", "stw", "lda", "sta", "add", "sub", "mv"};
+
+ ///
+ /// Replace, optimize, fix assembly output.
+ ///
+
+ for (auto& leaf : kState.fSyntaxTree->fLeafList) {
+ std::vector<std::string> access_keywords = {"->", "."};
+
+ for (auto& access_ident : access_keywords) {
+ if (LibCompiler::find_word(leaf.fUserValue, access_ident)) {
+ for (auto& struc : kState.kStructMap) {
+ /// TODO:
+ }
+ }
+ }
+
+ for (auto& keyword : keywords) {
+ if (LibCompiler::find_word(leaf.fUserValue, keyword)) {
+ std::size_t cnt = 0UL;
+
+ for (auto& reg : kState.kStackFrame) {
+ std::string needle;
+
+ for (size_t i = 0; i < reg.fName.size(); i++) {
+ if (reg.fName[i] == ' ') {
+ ++i;
+
+ for (; i < reg.fName.size(); i++) {
+ if (reg.fName[i] == ',') {
+ break;
+ }
+
+ if (reg.fName[i] == ' ') continue;
+
+ needle += reg.fName[i];
+ }
+
+ break;
+ }
+ }
+
+ if (LibCompiler::find_word(leaf.fUserValue, needle)) {
+ if (leaf.fUserValue.find("extern_segment " + needle) != std::string::npos) {
+ std::string range = "extern_segment " + needle;
+ leaf.fUserValue.replace(leaf.fUserValue.find("extern_segment " + needle),
+ range.size(), needle);
+ }
+
+ if (leaf.fUserValue.find("ldw r6") != std::string::npos) {
+ std::string::difference_type countComma =
+ std::count(leaf.fUserValue.begin(), leaf.fUserValue.end(), ',');
+
+ if (countComma == 1) {
+ leaf.fUserValue.replace(leaf.fUserValue.find("ldw"), strlen("ldw"), "mv");
+ }
+ }
+
+ leaf.fUserValue.replace(leaf.fUserValue.find(needle), needle.size(), reg.fReg);
+
+ ++cnt;
+ }
+ }
+
+ if (cnt > 1 && keyword != "mv" && keyword != "add" && keyword != "sub") {
+ leaf.fUserValue.replace(leaf.fUserValue.find(keyword), keyword.size(), "mv");
+ }
+ }
+ }
+ }
+
+ for (auto& leaf : kState.fSyntaxTree->fLeafList) {
+ (*kState.fOutputAssembly) << leaf.fUserValue;
+ }
+
+ kState.fSyntaxTree = nullptr;
+
+ kState.fOutputAssembly->flush();
+ kState.fOutputAssembly.reset();
+
+ return kExitOK;
+ }
};
/////////////////////////////////////////////////////////////////////////////////////////
@@ -1479,116 +1190,98 @@ public:
#include <LibCompiler/Version.h>
#define kPrintF printf
-#define kSplashCxx() \
- kPrintF(kWhite "NE C Driver, %s, (c) Amlal El Mahrouss\n", kDistVersion)
+#define kSplashCxx() kPrintF(kWhite "NE C Driver, %s, (c) Amlal El Mahrouss\n", kDistVersion)
-static void cc_print_help()
-{
- kSplashCxx();
+static void cc_print_help() {
+ kSplashCxx();
}
/////////////////////////////////////////////////////////////////////////////////////////
#define kCExtension ".c"
-LIBCOMPILER_MODULE(NeOSCompilerCLangARM64)
-{
- kCompilerTypes.push_back({.fName = "void", .fValue = "void"});
- kCompilerTypes.push_back({.fName = "char", .fValue = "byte"});
- kCompilerTypes.push_back({.fName = "short", .fValue = "hword"});
- kCompilerTypes.push_back({.fName = "int", .fValue = "dword"});
- kCompilerTypes.push_back({.fName = "long", .fValue = "qword"});
- kCompilerTypes.push_back({.fName = "*", .fValue = "offset"});
-
- bool skip = false;
-
- kFactory.Mount(new AssemblyCCInterface());
- kMachine = LibCompiler::AssemblyFactory::kArchAARCH64;
- kCompilerFrontend = new CompilerFrontendARM64();
-
- for (auto index = 1UL; index < argc; ++index)
- {
- if (skip)
- {
- skip = false;
- continue;
- }
-
- if (argv[index][0] == '-')
- {
- if (strcmp(argv[index], "--v") == 0 ||
- strcmp(argv[index], "--version") == 0)
- {
- kSplashCxx();
- return kExitOK;
- }
-
- if (strcmp(argv[index], "--verbose") == 0)
- {
- kState.fVerbose = true;
-
- continue;
- }
-
- if (strcmp(argv[index], "--h") == 0 || strcmp(argv[index], "--help") == 0)
- {
- cc_print_help();
-
- return kExitOK;
- }
-
- if (strcmp(argv[index], "--dialect") == 0)
- {
- if (kCompilerFrontend)
- std::cout << kCompilerFrontend->Language() << "\n";
-
- return kExitOK;
- }
-
- if (strcmp(argv[index], "--fmax-exceptions") == 0)
- {
- try
- {
- kErrorLimit = std::strtol(argv[index + 1], nullptr, 10);
- }
- // catch anything here
- catch (...)
- {
- kErrorLimit = 0;
- }
-
- skip = true;
-
- continue;
- }
-
- std::string err = "Unknown command: ";
- err += argv[index];
-
- Detail::print_error(err, "cc");
-
- continue;
- }
-
- kFileList.emplace_back(argv[index]);
-
- std::string srcFile = argv[index];
-
- if (strstr(argv[index], kCExtension) == nullptr)
- {
- if (kState.fVerbose)
- {
- Detail::print_error(srcFile + " is not a valid C source.\n", "cc");
- }
-
- return 1;
- }
-
- if (kFactory.Compile(srcFile, kMachine) != kExitOK)
- return 1;
- }
-
- return kExitOK;
+LIBCOMPILER_MODULE(NeOSCompilerCLangARM64) {
+ kCompilerTypes.push_back({.fName = "void", .fValue = "void"});
+ kCompilerTypes.push_back({.fName = "char", .fValue = "byte"});
+ kCompilerTypes.push_back({.fName = "short", .fValue = "hword"});
+ kCompilerTypes.push_back({.fName = "int", .fValue = "dword"});
+ kCompilerTypes.push_back({.fName = "long", .fValue = "qword"});
+ kCompilerTypes.push_back({.fName = "*", .fValue = "offset"});
+
+ bool skip = false;
+
+ kFactory.Mount(new AssemblyCCInterface());
+ kMachine = LibCompiler::AssemblyFactory::kArchAARCH64;
+ kCompilerFrontend = new CompilerFrontendARM64();
+
+ for (auto index = 1UL; index < argc; ++index) {
+ if (skip) {
+ skip = false;
+ continue;
+ }
+
+ if (argv[index][0] == '-') {
+ if (strcmp(argv[index], "--v") == 0 || strcmp(argv[index], "--version") == 0) {
+ kSplashCxx();
+ return kExitOK;
+ }
+
+ if (strcmp(argv[index], "--verbose") == 0) {
+ kState.fVerbose = true;
+
+ continue;
+ }
+
+ if (strcmp(argv[index], "--h") == 0 || strcmp(argv[index], "--help") == 0) {
+ cc_print_help();
+
+ return kExitOK;
+ }
+
+ if (strcmp(argv[index], "--dialect") == 0) {
+ if (kCompilerFrontend) std::cout << kCompilerFrontend->Language() << "\n";
+
+ return kExitOK;
+ }
+
+ if (strcmp(argv[index], "--fmax-exceptions") == 0) {
+ try {
+ kErrorLimit = std::strtol(argv[index + 1], nullptr, 10);
+ }
+ // catch anything here
+ catch (...) {
+ kErrorLimit = 0;
+ }
+
+ skip = true;
+
+ continue;
+ }
+
+ std::string err = "Unknown command: ";
+ err += argv[index];
+
+ Detail::print_error(err, "cc");
+
+ continue;
+ }
+
+ kFileList.emplace_back(argv[index]);
+
+ std::string srcFile = argv[index];
+
+ if (strstr(argv[index], kCExtension) == nullptr) {
+ if (kState.fVerbose) {
+ Detail::print_error(srcFile + " is not a valid C source.\n", "cc");
+ }
+
+ return 1;
+ }
+
+ if (kFactory.Compile(srcFile, kMachine) != kExitOK) return 1;
+ }
+
+ return kExitOK;
}
// Last rev 8-1-24
diff --git a/dev/LibCompiler/src/CCompilerPower64.cc b/dev/LibCompiler/src/CCompilerPower64.cc
index ac35c4a..90031a0 100644
--- a/dev/LibCompiler/src/CCompilerPower64.cc
+++ b/dev/LibCompiler/src/CCompilerPower64.cc
@@ -10,6 +10,7 @@
#include <LibCompiler/Backend/power64.h>
#include <LibCompiler/Parser.h>
#include <LibCompiler/UUID.h>
+#include <cstdio>
#include <fstream>
#include <iostream>
#include <memory>
@@ -17,7 +18,6 @@
#include <string>
#include <utility>
#include <vector>
-#include <cstdio>
#define kExitOK 0
@@ -32,7 +32,7 @@
/////////////////////
#define kBlank "\e[0;30m"
-#define kRed "\e[0;31m"
+#define kRed "\e[0;31m"
#define kWhite "\e[0;97m"
/////////////////////////////////////
@@ -41,63 +41,57 @@
/////////////////////////////////////
-namespace Detail
-{
- // \brief name to register struct.
- struct CompilerRegisterMap final
- {
- std::string fName;
- std::string fReg;
- };
-
- // \brief Map for C structs
- // \author amlel
- struct CompilerStructMap final
- {
- /// 'struct::my_foo'
- std::string fName;
-
- /// if instance: stores a valid register.
- std::string fReg;
-
- /// offset count
- std::size_t fOffsetsCnt;
-
- /// offset array.
- std::vector<std::pair<Int32, std::string>> fOffsets;
- };
-
- struct CompilerState final
- {
- std::vector<LibCompiler::SyntaxLeafList> fSyntaxTreeList;
- std::vector<CompilerRegisterMap> kStackFrame;
- std::vector<CompilerStructMap> kStructMap;
- LibCompiler::SyntaxLeafList* fSyntaxTree{nullptr};
- std::unique_ptr<std::ofstream> fOutputAssembly;
- std::string fLastFile;
- std::string fLastError;
- bool fVerbose;
- };
-} // namespace Detail
+namespace Detail {
+// \brief name to register struct.
+struct CompilerRegisterMap final {
+ std::string fName;
+ std::string fReg;
+};
+
+// \brief Map for C structs
+// \author amlel
+struct CompilerStructMap final {
+ /// 'struct::my_foo'
+ std::string fName;
+
+ /// if instance: stores a valid register.
+ std::string fReg;
+
+ /// offset count
+ std::size_t fOffsetsCnt;
+
+ /// offset array.
+ std::vector<std::pair<Int32, std::string>> fOffsets;
+};
+
+struct CompilerState final {
+ std::vector<LibCompiler::SyntaxLeafList> fSyntaxTreeList;
+ std::vector<CompilerRegisterMap> kStackFrame;
+ std::vector<CompilerStructMap> kStructMap;
+ LibCompiler::SyntaxLeafList* fSyntaxTree{nullptr};
+ std::unique_ptr<std::ofstream> fOutputAssembly;
+ std::string fLastFile;
+ std::string fLastError;
+ bool fVerbose;
+};
+} // namespace Detail
static Detail::CompilerState kState;
-static SizeType kErrorLimit = 100;
-static std::string kIfFunction = "";
-static Int32 kAcceptableErrors = 0;
-
-namespace Detail
-{
- /// @brief prints an error into stdout.
- /// @param reason the reason of the error.
- /// @param file where does it originate from?
- void print_error(std::string reason, std::string file) noexcept;
-
- struct CompilerType final
- {
- std::string fName;
- std::string fValue;
- };
-} // namespace Detail
+static SizeType kErrorLimit = 100;
+static std::string kIfFunction = "";
+static Int32 kAcceptableErrors = 0;
+
+namespace Detail {
+/// @brief prints an error into stdout.
+/// @param reason the reason of the error.
+/// @param file where does it originate from?
+void print_error(std::string reason, std::string file) noexcept;
+
+struct CompilerType final {
+ std::string fName;
+ std::string fValue;
+};
+} // namespace Detail
/////////////////////////////////////////////////////////////////////////////////////////
@@ -110,11 +104,11 @@ static int kMachine = 0;
/////////////////////////////////////////
-static size_t kRegisterCnt = kAsmRegisterLimit;
-static size_t kStartUsable = 2;
-static size_t kUsableLimit = 15;
-static size_t kRegisterCounter = kStartUsable;
-static std::string kRegisterPrefix = kAsmRegisterPrefix;
+static size_t kRegisterCnt = kAsmRegisterLimit;
+static size_t kStartUsable = 2;
+static size_t kUsableLimit = 15;
+static size_t kRegisterCounter = kStartUsable;
+static std::string kRegisterPrefix = kAsmRegisterPrefix;
/////////////////////////////////////////
@@ -122,67 +116,56 @@ static std::string kRegisterPrefix = kAsmRegisterPrefix;
/////////////////////////////////////////
-static std::vector<std::string> kFileList;
+static std::vector<std::string> kFileList;
static LibCompiler::AssemblyFactory kFactory;
-static bool kInStruct = false;
-static bool kOnWhileLoop = false;
-static bool kOnForLoop = false;
-static bool kInBraces = false;
-static bool kIfFound = false;
-static size_t kBracesCount = 0UL;
+static bool kInStruct = false;
+static bool kOnWhileLoop = false;
+static bool kOnForLoop = false;
+static bool kInBraces = false;
+static bool kIfFound = false;
+static size_t kBracesCount = 0UL;
/* @brief C compiler backend for C */
-class CompilerFrontendPower64 final : public LibCompiler::ICompilerFrontend
-{
-public:
- explicit CompilerFrontendPower64() = default;
- ~CompilerFrontendPower64() override = default;
+class CompilerFrontendPower64 final : public LibCompiler::ICompilerFrontend {
+ public:
+ explicit CompilerFrontendPower64() = default;
+ ~CompilerFrontendPower64() override = default;
- LIBCOMPILER_COPY_DEFAULT(CompilerFrontendPower64);
+ LIBCOMPILER_COPY_DEFAULT(CompilerFrontendPower64);
- std::string Check(const char* text, const char* file);
- bool Compile(std::string text, const std::string file) override;
+ std::string Check(const char* text, const char* file);
+ bool Compile(std::string text, const std::string file) override;
- const char* Language() override
- {
- return "POWER C";
- }
+ const char* Language() override { return "POWER C"; }
};
-static CompilerFrontendPower64* kCompilerFrontend = nullptr;
+static CompilerFrontendPower64* kCompilerFrontend = nullptr;
static std::vector<Detail::CompilerType> kCompilerVariables;
-static std::vector<std::string> kCompilerFunctions;
+static std::vector<std::string> kCompilerFunctions;
static std::vector<Detail::CompilerType> kCompilerTypes;
-namespace Detail
-{
- union number_cast final {
- public:
- number_cast(UInt64 _Raw)
- : _Raw(_Raw)
- {
- }
-
- public:
- char _Num[8];
- UInt64 _Raw;
- };
-
- union double_cast final {
- public:
- double_cast(float _Raw)
- : _Raw(_Raw)
- {
- }
-
- public:
- char _Sign;
- char _Lh[8];
- char _Rh[23];
-
- float _Raw;
- };
-} // namespace Detail
+namespace Detail {
+union number_cast final {
+ public:
+ number_cast(UInt64 _Raw) : _Raw(_Raw) {}
+
+ public:
+ char _Num[8];
+ UInt64 _Raw;
+};
+
+union double_cast final {
+ public:
+ double_cast(float _Raw) : _Raw(_Raw) {}
+
+ public:
+ char _Sign;
+ char _Lh[8];
+ char _Rh[23];
+
+ float _Raw;
+};
+} // namespace Detail
/////////////////////////////////////////////////////////////////////////////////////////
@@ -191,1122 +174,885 @@ namespace Detail
/////////////////////////////////////////////////////////////////////////////////////////
-bool CompilerFrontendPower64::Compile(std::string text_, const std::string file)
-{
- std::string text = text_;
-
- bool typeFound = false;
- bool fnFound = false;
-
- // setup generator.
- std::random_device rd;
-
- auto seed_data = std::array<int, std::mt19937::state_size>{};
- std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd));
- std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
- std::mt19937 generator(seq);
-
- // start parsing
- for (size_t text_index = 0; text_index < text.size(); ++text_index)
- {
- auto syntax_leaf = LibCompiler::SyntaxLeafList::SyntaxLeaf();
-
- auto gen = uuids::uuid_random_generator{generator};
- uuids::uuid out = gen();
-
- Detail::number_cast time_off = (UInt64)out.as_bytes().data();
-
- if (!typeFound)
- {
- auto substr = text.substr(text_index);
- std::string match_type;
-
- for (size_t y = 0; y < substr.size(); ++y)
- {
- if (substr[y] == ' ')
- {
- while (match_type.find(' ') != std::string::npos)
- {
- match_type.erase(match_type.find(' '));
- }
-
- for (auto& clType : kCompilerTypes)
- {
- if (clType.fName == match_type)
- {
- match_type.clear();
-
- std::string buf;
-
- buf += clType.fValue;
- buf += ' ';
+bool CompilerFrontendPower64::Compile(std::string text_, const std::string file) {
+ std::string text = text_;
+
+ bool typeFound = false;
+ bool fnFound = false;
+
+ // setup generator.
+ std::random_device rd;
+
+ auto seed_data = std::array<int, std::mt19937::state_size>{};
+ std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd));
+ std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
+ std::mt19937 generator(seq);
+
+ // start parsing
+ for (size_t text_index = 0; text_index < text.size(); ++text_index) {
+ auto syntax_leaf = LibCompiler::SyntaxLeafList::SyntaxLeaf();
+
+ auto gen = uuids::uuid_random_generator{generator};
+ uuids::uuid out = gen();
+
+ Detail::number_cast time_off = (UInt64) out.as_bytes().data();
+
+ if (!typeFound) {
+ auto substr = text.substr(text_index);
+ std::string match_type;
+
+ for (size_t y = 0; y < substr.size(); ++y) {
+ if (substr[y] == ' ') {
+ while (match_type.find(' ') != std::string::npos) {
+ match_type.erase(match_type.find(' '));
+ }
+
+ for (auto& clType : kCompilerTypes) {
+ if (clType.fName == match_type) {
+ match_type.clear();
+
+ std::string buf;
+
+ buf += clType.fValue;
+ buf += ' ';
+
+ if (substr.find('=') != std::string::npos) {
+ break;
+ }
+
+ if (text.find('(') != std::string::npos) {
+ syntax_leaf.fUserValue = buf;
+
+ kState.fSyntaxTree->fLeafList.push_back(syntax_leaf);
+ }
+
+ typeFound = true;
+ break;
+ }
+ }
+
+ break;
+ }
+
+ match_type += substr[y];
+ }
+ }
+
+ if (text[text_index] == '{') {
+ if (kInStruct) {
+ continue;
+ }
+
+ kInBraces = true;
+ ++kBracesCount;
+
+ kState.fSyntaxTree->fLeafList.push_back(syntax_leaf);
+ }
+
+ // return keyword handler
+ if (text[text_index] == 'r') {
+ std::string return_keyword;
+ return_keyword += "return";
+
+ std::size_t index = 0UL;
+
+ std::string value;
+
+ for (size_t return_index = text_index; return_index < text.size(); ++return_index) {
+ if (text[return_index] != return_keyword[index]) {
+ for (size_t value_index = return_index; value_index < text.size(); ++value_index) {
+ if (text[value_index] == ';') break;
+
+ value += text[value_index];
+ }
+
+ break;
+ }
+
+ ++index;
+ }
+
+ if (index == return_keyword.size()) {
+ if (!value.empty()) {
+ if (value.find('(') != std::string::npos) {
+ value.erase(value.find('('));
+ }
+
+ if (!isdigit(value[value.find('(') + 2])) {
+ std::string tmp = value;
+ bool reg_to_reg = false;
+
+ value.clear();
+
+ value += " extern_segment";
+ value += tmp;
+ }
+
+ syntax_leaf.fUserValue = "\tmr r31, ";
+
+ // make it pretty.
+ while (value.find('\t') != std::string::npos) value.erase(value.find('\t'), 1);
+
+ while (value.find(' ') != std::string::npos) value.erase(value.find(' '), 1);
+
+ while (value.find("extern_segment") != std::string::npos)
+ value.erase(value.find("extern_segment"), strlen("extern_segment"));
+
+ bool found = false;
+
+ for (auto& reg : kState.kStackFrame) {
+ if (value.find(reg.fName) != std::string::npos) {
+ found = true;
+ syntax_leaf.fUserValue += reg.fReg;
+ break;
+ }
+ }
+
+ if (!found) syntax_leaf.fUserValue += "r0";
+ }
+
+ syntax_leaf.fUserValue += "\n\tblr";
+
+ kState.fSyntaxTree->fLeafList.push_back(syntax_leaf);
+
+ break;
+ }
+ }
+
+ if (text[text_index] == 'i' && text[text_index + 1] == 'f') {
+ auto expr = text.substr(text_index + 2);
+ text.erase(text_index, 2);
+
+ if (expr.find("{") != std::string::npos) {
+ expr.erase(expr.find("{"));
+ }
+
+ if (expr.find("(") != std::string::npos) expr.erase(expr.find("("));
+
+ if (expr.find(")") != std::string::npos) expr.erase(expr.find(")"));
+
+ kIfFunction = "__LIBCOMPILER_IF_PROC_";
+ kIfFunction += std::to_string(time_off._Raw);
+
+ syntax_leaf.fUserValue =
+ "\tcmpw "
+ "r10, r11";
+
+ syntax_leaf.fUserValue += "\n\tbeq extern_segment " + kIfFunction +
+ " \ndword public_segment .code64 " + kIfFunction + "\n";
+
+ kState.fSyntaxTree->fLeafList.push_back(syntax_leaf);
+
+ kIfFound = true;
+ }
+
+ // Parse expressions and instructions here.
+ // what does this mean?
+ // we encounter an assignment, or we reached the end of an expression.
+ if (text[text_index] == '=' || text[text_index] == ';') {
+ if (fnFound) continue;
+ if (kIfFound) continue;
+
+ if (text[text_index] == ';' && kInStruct) continue;
+
+ if (text.find("typedef ") != std::string::npos) continue;
+
+ if (text[text_index] == '=' && kInStruct) {
+ Detail::print_error("assignement of value inside a struct " + text, file);
+ continue;
+ }
+
+ if (text[text_index] == ';' && kInStruct) {
+ bool space_found_ = false;
+ std::string sym;
+
+ for (auto& ch : text) {
+ if (ch == ' ') {
+ space_found_ = true;
+ }
+
+ if (ch == ';') break;
+
+ if (space_found_) sym.push_back(ch);
+ }
+
+ kState.kStructMap[kState.kStructMap.size() - 1].fOffsets.push_back(
+ std::make_pair(kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4, sym));
+
+ kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt =
+ kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4;
+
+ continue;
+ }
+
+ if (text[text_index] == '=' && kInStruct) {
+ continue;
+ }
+
+ if (text[text_index + 1] == '=' || text[text_index - 1] == '!' ||
+ text[text_index - 1] == '<' || text[text_index - 1] == '>') {
+ continue;
+ }
+
+ std::string substr;
+
+ if (text.find('=') != std::string::npos && kInBraces && !kIfFound) {
+ if (text.find("*") != std::string::npos) {
+ if (text.find("=") > text.find("*"))
+ substr += "\tli ";
+ else
+ substr += "\tli ";
+ } else {
+ substr += "\tli ";
+ }
+ } else if (text.find('=') != std::string::npos && !kInBraces) {
+ substr += "stw public_segment .data64 ";
+ }
+
+ int first_encountered = 0;
+
+ std::string str_name;
+
+ for (size_t text_index_2 = 0; text_index_2 < text.size(); ++text_index_2) {
+ if (text[text_index_2] == '\"') {
+ ++text_index_2;
+
+ // want to add this, so that the parser recognizes that this is a
+ // string.
+ substr += '"';
+
+ for (; text_index_2 < text.size(); ++text_index_2) {
+ if (text[text_index_2] == '\"') break;
+
+ substr += text[text_index_2];
+ }
+ }
+
+ if (text[text_index_2] == '{' || text[text_index_2] == '}') continue;
- if (substr.find('=') != std::string::npos)
- {
- break;
- }
-
- if (text.find('(') != std::string::npos)
- {
- syntax_leaf.fUserValue = buf;
-
- kState.fSyntaxTree->fLeafList.push_back(syntax_leaf);
- }
-
- typeFound = true;
- break;
- }
- }
-
- break;
- }
+ if (text[text_index_2] == ';') {
+ break;
+ }
- match_type += substr[y];
- }
- }
+ if (text[text_index_2] == ' ' || text[text_index_2] == '\t') {
+ if (first_encountered != 2) {
+ if (text[text_index] != '=' &&
+ substr.find("public_segment .data64") == std::string::npos && !kInStruct)
+ substr += "public_segment .data64 ";
+ }
- if (text[text_index] == '{')
- {
- if (kInStruct)
- {
- continue;
- }
-
- kInBraces = true;
- ++kBracesCount;
-
- kState.fSyntaxTree->fLeafList.push_back(syntax_leaf);
- }
-
- // return keyword handler
- if (text[text_index] == 'r')
- {
- std::string return_keyword;
- return_keyword += "return";
+ ++first_encountered;
- std::size_t index = 0UL;
-
- std::string value;
+ continue;
+ }
- for (size_t return_index = text_index; return_index < text.size();
- ++return_index)
- {
- if (text[return_index] != return_keyword[index])
- {
- for (size_t value_index = return_index;
- value_index < text.size(); ++value_index)
- {
- if (text[value_index] == ';')
- break;
-
- value += text[value_index];
- }
-
- break;
- }
-
- ++index;
- }
-
- if (index == return_keyword.size())
- {
- if (!value.empty())
- {
- if (value.find('(') != std::string::npos)
- {
- value.erase(value.find('('));
- }
-
- if (!isdigit(value[value.find('(') + 2]))
- {
- std::string tmp = value;
- bool reg_to_reg = false;
-
- value.clear();
-
- value += " extern_segment";
- value += tmp;
- }
-
- syntax_leaf.fUserValue = "\tmr r31, ";
-
- // make it pretty.
- while (value.find('\t') != std::string::npos)
- value.erase(value.find('\t'), 1);
-
- while (value.find(' ') != std::string::npos)
- value.erase(value.find(' '), 1);
-
- while (value.find("extern_segment") != std::string::npos)
- value.erase(value.find("extern_segment"), strlen("extern_segment"));
-
- bool found = false;
-
- for (auto& reg : kState.kStackFrame)
- {
- if (value.find(reg.fName) != std::string::npos)
- {
- found = true;
- syntax_leaf.fUserValue += reg.fReg;
- break;
- }
- }
-
- if (!found)
- syntax_leaf.fUserValue += "r0";
- }
-
- syntax_leaf.fUserValue += "\n\tblr";
-
- kState.fSyntaxTree->fLeafList.push_back(syntax_leaf);
-
- break;
- }
- }
-
- if (text[text_index] == 'i' && text[text_index + 1] == 'f')
- {
- auto expr = text.substr(text_index + 2);
- text.erase(text_index, 2);
-
- if (expr.find("{") != std::string::npos)
- {
- expr.erase(expr.find("{"));
- }
-
- if (expr.find("(") != std::string::npos)
- expr.erase(expr.find("("));
-
- if (expr.find(")") != std::string::npos)
- expr.erase(expr.find(")"));
-
- kIfFunction = "__LIBCOMPILER_IF_PROC_";
- kIfFunction += std::to_string(time_off._Raw);
-
- syntax_leaf.fUserValue =
- "\tcmpw "
- "r10, r11";
-
- syntax_leaf.fUserValue += "\n\tbeq extern_segment " + kIfFunction +
- " \ndword public_segment .code64 " + kIfFunction + "\n";
-
- kState.fSyntaxTree->fLeafList.push_back(syntax_leaf);
-
- kIfFound = true;
- }
-
- // Parse expressions and instructions here.
- // what does this mean?
- // we encounter an assignment, or we reached the end of an expression.
- if (text[text_index] == '=' || text[text_index] == ';')
- {
- if (fnFound)
- continue;
- if (kIfFound)
- continue;
-
- if (text[text_index] == ';' && kInStruct)
- continue;
-
- if (text.find("typedef ") != std::string::npos)
- continue;
-
- if (text[text_index] == '=' && kInStruct)
- {
- Detail::print_error(
- "assignement of value inside a struct " + text, file);
- continue;
- }
-
- if (text[text_index] == ';' && kInStruct)
- {
- bool space_found_ = false;
- std::string sym;
-
- for (auto& ch : text)
- {
- if (ch == ' ')
- {
- space_found_ = true;
- }
-
- if (ch == ';')
- break;
-
- if (space_found_)
- sym.push_back(ch);
- }
-
- kState.kStructMap[kState.kStructMap.size() - 1].fOffsets.push_back(
- std::make_pair(
- kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4,
- sym));
-
- kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt =
- kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4;
-
- continue;
- }
-
- if (text[text_index] == '=' && kInStruct)
- {
- continue;
- }
-
- if (text[text_index + 1] == '=' ||
- text[text_index - 1] == '!' ||
- text[text_index - 1] == '<' ||
- text[text_index - 1] == '>')
- {
- continue;
- }
-
- std::string substr;
-
- if (text.find('=') != std::string::npos && kInBraces && !kIfFound)
- {
- if (text.find("*") != std::string::npos)
- {
- if (text.find("=") > text.find("*"))
- substr += "\tli ";
- else
- substr += "\tli ";
- }
- else
- {
- substr += "\tli ";
- }
- }
- else if (text.find('=') != std::string::npos && !kInBraces)
- {
- substr += "stw public_segment .data64 ";
- }
-
- int first_encountered = 0;
-
- std::string str_name;
-
- for (size_t text_index_2 = 0; text_index_2 < text.size();
- ++text_index_2)
- {
- if (text[text_index_2] == '\"')
- {
- ++text_index_2;
-
- // want to add this, so that the parser recognizes that this is a
- // string.
- substr += '"';
-
- for (; text_index_2 < text.size(); ++text_index_2)
- {
- if (text[text_index_2] == '\"')
- break;
-
- substr += text[text_index_2];
- }
- }
-
- if (text[text_index_2] == '{' || text[text_index_2] == '}')
- continue;
-
- if (text[text_index_2] == ';')
- {
- break;
- }
-
- if (text[text_index_2] == ' ' ||
- text[text_index_2] == '\t')
- {
- if (first_encountered != 2)
- {
- if (text[text_index] != '=' &&
- substr.find("public_segment .data64") == std::string::npos &&
- !kInStruct)
- substr += "public_segment .data64 ";
- }
-
- ++first_encountered;
-
- continue;
- }
-
- if (text[text_index_2] == '=')
- {
- if (!kInBraces)
- {
- substr.replace(substr.find("public_segment .data64"),
- strlen("public_segment .data64"), "public_segment .zero64 ");
- }
-
- substr += ",";
- continue;
- }
-
- substr += text[text_index_2];
- }
-
- for (auto& clType : kCompilerTypes)
- {
- if (substr.find(clType.fName) != std::string::npos)
- {
- if (substr.find(clType.fName) > substr.find('"'))
- continue;
-
- substr.erase(substr.find(clType.fName), clType.fName.size());
- }
- else if (substr.find(clType.fValue) != std::string::npos)
- {
- if (substr.find(clType.fValue) > substr.find('"'))
- continue;
-
- if (clType.fName == "const")
- continue;
-
- substr.erase(substr.find(clType.fValue), clType.fValue.size());
- }
- }
-
- if (substr.find("extern") != std::string::npos)
- {
- substr.replace(substr.find("extern"), strlen("extern"), "extern_segment ");
-
- if (substr.find("public_segment .data64") != std::string::npos)
- substr.erase(substr.find("public_segment .data64"), strlen("public_segment .data64"));
- }
-
- auto var_to_find =
- std::find_if(kCompilerVariables.cbegin(), kCompilerVariables.cend(),
- [&](Detail::CompilerType type) {
- return type.fName.find(substr) != std::string::npos;
- });
-
- kCompilerVariables.push_back({.fName = substr});
-
- if (text[text_index] == ';')
- break;
-
- std::string reg = kAsmRegisterPrefix;
-
- ++kRegisterCounter;
- reg += std::to_string(kRegisterCounter);
-
- auto newSubstr = substr.substr(substr.find(" "));
-
- std::string symbol;
-
- for (size_t start = 0; start < newSubstr.size(); ++start)
- {
- if (newSubstr[start] == ',')
- break;
-
- if (newSubstr[start] == ' ')
- continue;
-
- symbol += (newSubstr[start]);
- }
-
- kState.kStackFrame.push_back({.fName = symbol, .fReg = reg});
-
- syntax_leaf.fUserValue +=
- "\n\tli " + reg + substr.substr(substr.find(','));
- kState.fSyntaxTree->fLeafList.push_back(syntax_leaf);
- }
+ if (text[text_index_2] == '=') {
+ if (!kInBraces) {
+ substr.replace(substr.find("public_segment .data64"), strlen("public_segment .data64"),
+ "public_segment .zero64 ");
+ }
- // function handler.
+ substr += ",";
+ continue;
+ }
- if (text[text_index] == '(' && !fnFound && !kIfFound)
- {
- std::string substr;
- std::string args_buffer;
- std::string args;
+ substr += text[text_index_2];
+ }
- bool type_crossed = false;
+ for (auto& clType : kCompilerTypes) {
+ if (substr.find(clType.fName) != std::string::npos) {
+ if (substr.find(clType.fName) > substr.find('"')) continue;
- for (size_t idx = text.find('(') + 1; idx < text.size();
- ++idx)
- {
- if (text[idx] == ',')
- continue;
+ substr.erase(substr.find(clType.fName), clType.fName.size());
+ } else if (substr.find(clType.fValue) != std::string::npos) {
+ if (substr.find(clType.fValue) > substr.find('"')) continue;
- if (text[idx] == ' ')
- continue;
+ if (clType.fName == "const") continue;
- if (text[idx] == ')')
- break;
- }
+ substr.erase(substr.find(clType.fValue), clType.fValue.size());
+ }
+ }
- for (char substr_first_index : text)
- {
- if (substr_first_index != ',')
- args_buffer += substr_first_index;
- else
- args_buffer += '$';
+ if (substr.find("extern") != std::string::npos) {
+ substr.replace(substr.find("extern"), strlen("extern"), "extern_segment ");
- if (substr_first_index == ';')
- {
- args_buffer = args_buffer.erase(0, args_buffer.find('('));
- args_buffer = args_buffer.erase(args_buffer.find(';'), 1);
- args_buffer = args_buffer.erase(args_buffer.find(')'), 1);
- args_buffer = args_buffer.erase(args_buffer.find('('), 1);
+ if (substr.find("public_segment .data64") != std::string::npos)
+ substr.erase(substr.find("public_segment .data64"), strlen("public_segment .data64"));
+ }
- if (!args_buffer.empty())
- args += "\tldw r6, ";
+ auto var_to_find = std::find_if(
+ kCompilerVariables.cbegin(), kCompilerVariables.cend(),
+ [&](Detail::CompilerType type) { return type.fName.find(substr) != std::string::npos; });
- std::string register_type;
- std::size_t index = 7UL;
+ kCompilerVariables.push_back({.fName = substr});
- while (args_buffer.find("$") != std::string::npos)
- {
- register_type = kRegisterPrefix;
- register_type += std::to_string(index);
+ if (text[text_index] == ';') break;
- ++index;
+ std::string reg = kAsmRegisterPrefix;
- args_buffer.replace(args_buffer.find('$'), 1,
- "\n\tldw " + register_type + ",");
- }
+ ++kRegisterCounter;
+ reg += std::to_string(kRegisterCounter);
- args += args_buffer;
- args += "\n\tli r31, ";
- }
- }
+ auto newSubstr = substr.substr(substr.find(" "));
- for (char _text_i : text)
- {
- if (_text_i == '\t' || _text_i == ' ')
- {
- if (!type_crossed)
- {
- substr.clear();
- type_crossed = true;
- }
+ std::string symbol;
- continue;
- }
+ for (size_t start = 0; start < newSubstr.size(); ++start) {
+ if (newSubstr[start] == ',') break;
- if (_text_i == '(')
- break;
+ if (newSubstr[start] == ' ') continue;
- substr += _text_i;
- }
+ symbol += (newSubstr[start]);
+ }
- if (kInBraces)
- {
- syntax_leaf.fUserValue = args;
- syntax_leaf.fUserValue += substr;
+ kState.kStackFrame.push_back({.fName = symbol, .fReg = reg});
- syntax_leaf.fUserValue += "\n\tblr\n";
+ syntax_leaf.fUserValue += "\n\tli " + reg + substr.substr(substr.find(','));
+ kState.fSyntaxTree->fLeafList.push_back(syntax_leaf);
+ }
- kState.fSyntaxTree->fLeafList.push_back(syntax_leaf);
+ // function handler.
- fnFound = true;
- }
- else
- {
- syntax_leaf.fUserValue.clear();
+ if (text[text_index] == '(' && !fnFound && !kIfFound) {
+ std::string substr;
+ std::string args_buffer;
+ std::string args;
- syntax_leaf.fUserValue += "public_segment .code64 ";
+ bool type_crossed = false;
- syntax_leaf.fUserValue += substr;
- syntax_leaf.fUserValue += "\n";
+ for (size_t idx = text.find('(') + 1; idx < text.size(); ++idx) {
+ if (text[idx] == ',') continue;
- kState.fSyntaxTree->fLeafList.push_back(syntax_leaf);
+ if (text[idx] == ' ') continue;
- fnFound = true;
- }
+ if (text[idx] == ')') break;
+ }
- kCompilerFunctions.push_back(text);
- }
+ for (char substr_first_index : text) {
+ if (substr_first_index != ',')
+ args_buffer += substr_first_index;
+ else
+ args_buffer += '$';
- if (text[text_index] == '-' && text[text_index + 1] == '-')
- {
- text = text.replace(text.find("--"), strlen("--"), "");
+ if (substr_first_index == ';') {
+ args_buffer = args_buffer.erase(0, args_buffer.find('('));
+ args_buffer = args_buffer.erase(args_buffer.find(';'), 1);
+ args_buffer = args_buffer.erase(args_buffer.find(')'), 1);
+ args_buffer = args_buffer.erase(args_buffer.find('('), 1);
- for (int _text_i = 0; _text_i < text.size(); ++_text_i)
- {
- if (text[_text_i] == '\t' || text[_text_i] == ' ')
- text.erase(_text_i, 1);
- }
+ if (!args_buffer.empty()) args += "\tldw r6, ";
- syntax_leaf.fUserValue += "dec ";
- syntax_leaf.fUserValue += text;
+ std::string register_type;
+ std::size_t index = 7UL;
- kState.fSyntaxTree->fLeafList.push_back(syntax_leaf);
- break;
- }
+ while (args_buffer.find("$") != std::string::npos) {
+ register_type = kRegisterPrefix;
+ register_type += std::to_string(index);
- if (text[text_index] == '}')
- {
- kRegisterCounter = kStartUsable;
+ ++index;
- --kBracesCount;
+ args_buffer.replace(args_buffer.find('$'), 1, "\n\tldw " + register_type + ",");
+ }
- if (kBracesCount < 1)
- {
- kInBraces = false;
- kBracesCount = 0;
- }
+ args += args_buffer;
+ args += "\n\tli r31, ";
+ }
+ }
- if (kIfFound)
- kIfFound = false;
+ for (char _text_i : text) {
+ if (_text_i == '\t' || _text_i == ' ') {
+ if (!type_crossed) {
+ substr.clear();
+ type_crossed = true;
+ }
- if (kInStruct)
- kInStruct = false;
+ continue;
+ }
- kState.fSyntaxTree->fLeafList.push_back(syntax_leaf);
- }
+ if (_text_i == '(') break;
- syntax_leaf.fUserValue.clear();
- }
+ substr += _text_i;
+ }
- auto syntax_leaf = LibCompiler::SyntaxLeafList::SyntaxLeaf();
- syntax_leaf.fUserValue = "\n";
- kState.fSyntaxTree->fLeafList.push_back(syntax_leaf);
+ if (kInBraces) {
+ syntax_leaf.fUserValue = args;
+ syntax_leaf.fUserValue += substr;
- return true;
+ syntax_leaf.fUserValue += "\n\tblr\n";
+
+ kState.fSyntaxTree->fLeafList.push_back(syntax_leaf);
+
+ fnFound = true;
+ } else {
+ syntax_leaf.fUserValue.clear();
+
+ syntax_leaf.fUserValue += "public_segment .code64 ";
+
+ syntax_leaf.fUserValue += substr;
+ syntax_leaf.fUserValue += "\n";
+
+ kState.fSyntaxTree->fLeafList.push_back(syntax_leaf);
+
+ fnFound = true;
+ }
+
+ kCompilerFunctions.push_back(text);
+ }
+
+ if (text[text_index] == '-' && text[text_index + 1] == '-') {
+ text = text.replace(text.find("--"), strlen("--"), "");
+
+ for (int _text_i = 0; _text_i < text.size(); ++_text_i) {
+ if (text[_text_i] == '\t' || text[_text_i] == ' ') text.erase(_text_i, 1);
+ }
+
+ syntax_leaf.fUserValue += "dec ";
+ syntax_leaf.fUserValue += text;
+
+ kState.fSyntaxTree->fLeafList.push_back(syntax_leaf);
+ break;
+ }
+
+ if (text[text_index] == '}') {
+ kRegisterCounter = kStartUsable;
+
+ --kBracesCount;
+
+ if (kBracesCount < 1) {
+ kInBraces = false;
+ kBracesCount = 0;
+ }
+
+ if (kIfFound) kIfFound = false;
+
+ if (kInStruct) kInStruct = false;
+
+ kState.fSyntaxTree->fLeafList.push_back(syntax_leaf);
+ }
+
+ syntax_leaf.fUserValue.clear();
+ }
+
+ auto syntax_leaf = LibCompiler::SyntaxLeafList::SyntaxLeaf();
+ syntax_leaf.fUserValue = "\n";
+ kState.fSyntaxTree->fLeafList.push_back(syntax_leaf);
+
+ return true;
}
-static bool kShouldHaveBraces = false;
+static bool kShouldHaveBraces = false;
static std::string kFnName;
-std::string CompilerFrontendPower64::Check(const char* text, const char* file)
-{
- std::string err_str;
- std::string ln = text;
-
- if (ln.empty())
- {
- return err_str;
- }
-
- bool non_ascii_found = false;
-
- for (int i = 0; i < ln.size(); ++i)
- {
- if (isalnum(ln[i]))
- {
- non_ascii_found = true;
- break;
- }
- }
-
- if (kShouldHaveBraces && ln.find('{') != std::string::npos)
- {
- kShouldHaveBraces = false;
- }
-
- if (!non_ascii_found)
- return err_str;
-
- size_t string_index = 1UL;
-
- if (ln.find('\'') != std::string::npos)
- {
- string_index = ln.find('\'') + 1;
-
- for (; string_index < ln.size(); ++string_index)
- {
- if (ln[string_index] == '\'')
- {
- if (ln[string_index + 1] != ';')
- {
- ln.erase(string_index, 1);
- }
-
- return err_str;
- }
- }
- }
- else if (ln.find('"') != std::string::npos)
- {
- string_index = ln.find('"') + 1;
-
- for (; string_index < ln.size(); ++string_index)
- {
- if (ln[string_index] == '"')
- {
- if (ln[string_index + 1] != ';')
- {
- ln.erase(string_index, 1);
- }
- else
- {
- break;
- }
- }
- }
- }
- else if (ln.find('"') == std::string::npos &&
- ln.find('\'') == std::string::npos)
- {
- std::vector<std::string> forbidden_words;
-
- forbidden_words.push_back("\\");
- forbidden_words.push_back("?");
- forbidden_words.push_back("@");
- forbidden_words.push_back("~");
- forbidden_words.push_back("::");
- forbidden_words.push_back("--*");
- forbidden_words.push_back("*/");
-
- // add them to avoid stupid mistakes.
- forbidden_words.push_back("namespace");
- forbidden_words.push_back("class");
- forbidden_words.push_back("extern \"C\"");
-
- for (auto& forbidden : forbidden_words)
- {
- if (ln.find(forbidden) != std::string::npos)
- {
- err_str += "\nForbidden character detected: ";
- err_str += forbidden;
-
- return err_str;
- }
- }
- }
-
- struct CompilerVariableRange final
- {
- std::string fBegin;
- std::string fEnd;
- };
-
- const std::vector<CompilerVariableRange> variables_list = {
- {.fBegin = "static ", .fEnd = "="},
- {.fBegin = "=", .fEnd = ";"},
- {.fBegin = "if(", .fEnd = "="},
- {.fBegin = "if (", .fEnd = "="},
- {.fBegin = "if(", .fEnd = "<"},
- {.fBegin = "if (", .fEnd = "<"},
- {.fBegin = "if(", .fEnd = ">"},
- {.fBegin = "if (", .fEnd = ">"},
- {.fBegin = "if(", .fEnd = ")"},
- {.fBegin = "if (", .fEnd = ")"},
-
- {.fBegin = "else(", .fEnd = "="},
- {.fBegin = "else (", .fEnd = "="},
- {.fBegin = "else(", .fEnd = "<"},
- {.fBegin = "else (", .fEnd = "<"},
- {.fBegin = "else(", .fEnd = ">"},
- {.fBegin = "else (", .fEnd = ">"},
- {.fBegin = "else(", .fEnd = ")"},
- {.fBegin = "else (", .fEnd = ")"},
- };
-
- for (auto& variable : variables_list)
- {
- if (ln.find(variable.fBegin) != std::string::npos)
- {
- string_index = ln.find(variable.fBegin) + variable.fBegin.size();
-
- while (ln[string_index] == ' ')
- ++string_index;
-
- std::string keyword;
-
- for (; string_index < ln.size(); ++string_index)
- {
- if (ln[string_index] == variable.fEnd[0])
- {
- std::string varname = "";
-
- for (size_t index_keyword = ln.find(' ');
- ln[index_keyword] != variable.fBegin[0]; ++index_keyword)
- {
- if (ln[index_keyword] == ' ')
- {
- continue;
- }
-
- if (isdigit(ln[index_keyword]))
- {
- goto cc_next_loop;
- }
-
- varname += ln[index_keyword];
- }
-
- if (varname.find(' ') != std::string::npos)
- {
- varname.erase(0, varname.find(' '));
-
- if (variable.fBegin == "extern")
- {
- varname.erase(0, varname.find(' '));
- }
- }
-
- if (kRegisterCounter == 5 || kRegisterCounter == 6)
- ++kRegisterCounter;
-
- std::string reg = kAsmRegisterPrefix;
- reg += std::to_string(kRegisterCounter);
-
- kCompilerVariables.push_back({.fValue = varname});
- goto cc_check_done;
- }
-
- keyword.push_back(ln[string_index]);
- }
-
- goto cc_next_loop;
-
- cc_check_done:
-
- // skip digit value.
- if (isdigit(keyword[0]) || keyword[0] == '"')
- {
- goto cc_next_loop;
- }
-
- while (keyword.find(' ') != std::string::npos)
- keyword.erase(keyword.find(' '), 1);
-
- for (auto& var : kCompilerVariables)
- {
- if (var.fValue.find(keyword) != std::string::npos)
- {
- err_str.clear();
- goto cc_next;
- }
- }
-
- for (auto& fn : kCompilerFunctions)
- {
- if (fn.find(keyword[0]) != std::string::npos)
- {
- auto where_begin = fn.find(keyword[0]);
- auto keyword_begin = 0UL;
- auto failed = false;
-
- for (; where_begin < keyword.size(); ++where_begin)
- {
- if (fn[where_begin] == '(' && keyword[keyword_begin] == '(')
- break;
-
- if (fn[where_begin] != keyword[keyword_begin])
- {
- failed = true;
- break;
- }
-
- ++keyword_begin;
- }
-
- if (!failed)
- {
- err_str.clear();
- goto cc_next;
- }
- else
- {
- continue;
- }
- }
- }
-
- cc_error_value:
- if (keyword.find("->") != std::string::npos)
- return err_str;
-
- if (keyword.find(".") != std::string::npos)
- return err_str;
-
- if (isalnum(keyword[0]))
- err_str += "\nUndefined value: " + keyword;
-
- return err_str;
- }
-
- cc_next_loop:
- continue;
- }
+std::string CompilerFrontendPower64::Check(const char* text, const char* file) {
+ std::string err_str;
+ std::string ln = text;
+
+ if (ln.empty()) {
+ return err_str;
+ }
+
+ bool non_ascii_found = false;
+
+ for (int i = 0; i < ln.size(); ++i) {
+ if (isalnum(ln[i])) {
+ non_ascii_found = true;
+ break;
+ }
+ }
+
+ if (kShouldHaveBraces && ln.find('{') != std::string::npos) {
+ kShouldHaveBraces = false;
+ }
+
+ if (!non_ascii_found) return err_str;
+
+ size_t string_index = 1UL;
+
+ if (ln.find('\'') != std::string::npos) {
+ string_index = ln.find('\'') + 1;
+
+ for (; string_index < ln.size(); ++string_index) {
+ if (ln[string_index] == '\'') {
+ if (ln[string_index + 1] != ';') {
+ ln.erase(string_index, 1);
+ }
+
+ return err_str;
+ }
+ }
+ } else if (ln.find('"') != std::string::npos) {
+ string_index = ln.find('"') + 1;
+
+ for (; string_index < ln.size(); ++string_index) {
+ if (ln[string_index] == '"') {
+ if (ln[string_index + 1] != ';') {
+ ln.erase(string_index, 1);
+ } else {
+ break;
+ }
+ }
+ }
+ } else if (ln.find('"') == std::string::npos && ln.find('\'') == std::string::npos) {
+ std::vector<std::string> forbidden_words;
+
+ forbidden_words.push_back("\\");
+ forbidden_words.push_back("?");
+ forbidden_words.push_back("@");
+ forbidden_words.push_back("~");
+ forbidden_words.push_back("::");
+ forbidden_words.push_back("--*");
+ forbidden_words.push_back("*/");
+
+ // add them to avoid stupid mistakes.
+ forbidden_words.push_back("namespace");
+ forbidden_words.push_back("class");
+ forbidden_words.push_back("extern \"C\"");
+
+ for (auto& forbidden : forbidden_words) {
+ if (ln.find(forbidden) != std::string::npos) {
+ err_str += "\nForbidden character detected: ";
+ err_str += forbidden;
+
+ return err_str;
+ }
+ }
+ }
+
+ struct CompilerVariableRange final {
+ std::string fBegin;
+ std::string fEnd;
+ };
+
+ const std::vector<CompilerVariableRange> variables_list = {
+ {.fBegin = "static ", .fEnd = "="}, {.fBegin = "=", .fEnd = ";"},
+ {.fBegin = "if(", .fEnd = "="}, {.fBegin = "if (", .fEnd = "="},
+ {.fBegin = "if(", .fEnd = "<"}, {.fBegin = "if (", .fEnd = "<"},
+ {.fBegin = "if(", .fEnd = ">"}, {.fBegin = "if (", .fEnd = ">"},
+ {.fBegin = "if(", .fEnd = ")"}, {.fBegin = "if (", .fEnd = ")"},
+
+ {.fBegin = "else(", .fEnd = "="}, {.fBegin = "else (", .fEnd = "="},
+ {.fBegin = "else(", .fEnd = "<"}, {.fBegin = "else (", .fEnd = "<"},
+ {.fBegin = "else(", .fEnd = ">"}, {.fBegin = "else (", .fEnd = ">"},
+ {.fBegin = "else(", .fEnd = ")"}, {.fBegin = "else (", .fEnd = ")"},
+ };
+
+ for (auto& variable : variables_list) {
+ if (ln.find(variable.fBegin) != std::string::npos) {
+ string_index = ln.find(variable.fBegin) + variable.fBegin.size();
+
+ while (ln[string_index] == ' ') ++string_index;
+
+ std::string keyword;
+
+ for (; string_index < ln.size(); ++string_index) {
+ if (ln[string_index] == variable.fEnd[0]) {
+ std::string varname = "";
+
+ for (size_t index_keyword = ln.find(' '); ln[index_keyword] != variable.fBegin[0];
+ ++index_keyword) {
+ if (ln[index_keyword] == ' ') {
+ continue;
+ }
+
+ if (isdigit(ln[index_keyword])) {
+ goto cc_next_loop;
+ }
+
+ varname += ln[index_keyword];
+ }
+
+ if (varname.find(' ') != std::string::npos) {
+ varname.erase(0, varname.find(' '));
+
+ if (variable.fBegin == "extern") {
+ varname.erase(0, varname.find(' '));
+ }
+ }
+
+ if (kRegisterCounter == 5 || kRegisterCounter == 6) ++kRegisterCounter;
+
+ std::string reg = kAsmRegisterPrefix;
+ reg += std::to_string(kRegisterCounter);
+
+ kCompilerVariables.push_back({.fValue = varname});
+ goto cc_check_done;
+ }
+
+ keyword.push_back(ln[string_index]);
+ }
+
+ goto cc_next_loop;
+
+ cc_check_done:
+
+ // skip digit value.
+ if (isdigit(keyword[0]) || keyword[0] == '"') {
+ goto cc_next_loop;
+ }
+
+ while (keyword.find(' ') != std::string::npos) keyword.erase(keyword.find(' '), 1);
+
+ for (auto& var : kCompilerVariables) {
+ if (var.fValue.find(keyword) != std::string::npos) {
+ err_str.clear();
+ goto cc_next;
+ }
+ }
+
+ for (auto& fn : kCompilerFunctions) {
+ if (fn.find(keyword[0]) != std::string::npos) {
+ auto where_begin = fn.find(keyword[0]);
+ auto keyword_begin = 0UL;
+ auto failed = false;
+
+ for (; where_begin < keyword.size(); ++where_begin) {
+ if (fn[where_begin] == '(' && keyword[keyword_begin] == '(') break;
+
+ if (fn[where_begin] != keyword[keyword_begin]) {
+ failed = true;
+ break;
+ }
+
+ ++keyword_begin;
+ }
+
+ if (!failed) {
+ err_str.clear();
+ goto cc_next;
+ } else {
+ continue;
+ }
+ }
+ }
+
+ cc_error_value:
+ if (keyword.find("->") != std::string::npos) return err_str;
+
+ if (keyword.find(".") != std::string::npos) return err_str;
+
+ if (isalnum(keyword[0])) err_str += "\nUndefined value: " + keyword;
+
+ return err_str;
+ }
+
+ cc_next_loop:
+ continue;
+ }
cc_next:
- // extern does not declare anything, it extern_segments a variable.
- // so that's why it's not declare upper.
- if (LibCompiler::find_word(ln, "extern"))
- {
- auto substr = ln.substr(ln.find("extern") + strlen("extern"));
- kCompilerVariables.push_back({.fValue = substr});
- }
-
- if (kShouldHaveBraces && ln.find('{') == std::string::npos)
- {
- err_str += "Missing '{' for function ";
- err_str += kFnName;
- err_str += "\n";
-
- kShouldHaveBraces = false;
- kFnName.clear();
- }
- else if (kShouldHaveBraces && ln.find('{') != std::string::npos)
- {
- kShouldHaveBraces = false;
- kFnName.clear();
- }
-
- bool type_not_found = true;
-
- if (ln.find('\'') != std::string::npos)
- {
- ln.replace(ln.find('\''), 3, "0");
- }
-
- auto first = ln.find('"');
- if (first != std::string::npos)
- {
- auto second = 0UL;
- bool found_second_quote = false;
-
- for (size_t i = first + 1; i < ln.size(); ++i)
- {
- if (ln[i] == '\"')
- {
- found_second_quote = true;
- second = i;
-
- break;
- }
- }
-
- if (!found_second_quote)
- {
- err_str += "Missing terminating \".";
- err_str += " here -> " + ln.substr(ln.find('"'), second);
- }
- }
-
- if (ln.find(')') != std::string::npos && ln.find(';') == std::string::npos)
- {
- if (ln.find('{') == std::string::npos)
- {
- kFnName = ln;
- kShouldHaveBraces = true;
-
- goto skip_braces_check;
- }
- else if (ln.find('{') != std::string::npos)
- {
- kShouldHaveBraces = false;
- }
- }
+ // extern does not declare anything, it extern_segments a variable.
+ // so that's why it's not declare upper.
+ if (LibCompiler::find_word(ln, "extern")) {
+ auto substr = ln.substr(ln.find("extern") + strlen("extern"));
+ kCompilerVariables.push_back({.fValue = substr});
+ }
+
+ if (kShouldHaveBraces && ln.find('{') == std::string::npos) {
+ err_str += "Missing '{' for function ";
+ err_str += kFnName;
+ err_str += "\n";
+
+ kShouldHaveBraces = false;
+ kFnName.clear();
+ } else if (kShouldHaveBraces && ln.find('{') != std::string::npos) {
+ kShouldHaveBraces = false;
+ kFnName.clear();
+ }
+
+ bool type_not_found = true;
+
+ if (ln.find('\'') != std::string::npos) {
+ ln.replace(ln.find('\''), 3, "0");
+ }
+
+ auto first = ln.find('"');
+ if (first != std::string::npos) {
+ auto second = 0UL;
+ bool found_second_quote = false;
+
+ for (size_t i = first + 1; i < ln.size(); ++i) {
+ if (ln[i] == '\"') {
+ found_second_quote = true;
+ second = i;
+
+ break;
+ }
+ }
+
+ if (!found_second_quote) {
+ err_str += "Missing terminating \".";
+ err_str += " here -> " + ln.substr(ln.find('"'), second);
+ }
+ }
+
+ if (ln.find(')') != std::string::npos && ln.find(';') == std::string::npos) {
+ if (ln.find('{') == std::string::npos) {
+ kFnName = ln;
+ kShouldHaveBraces = true;
+
+ goto skip_braces_check;
+ } else if (ln.find('{') != std::string::npos) {
+ kShouldHaveBraces = false;
+ }
+ }
skip_braces_check:
- for (auto& key : kCompilerTypes)
- {
- if (LibCompiler::find_word(ln, key.fName))
- {
- if (isdigit(ln[ln.find(key.fName) + key.fName.size() + 1]))
- {
- err_str += "\nNumber cannot be set for ";
- err_str += key.fName;
- err_str += "'s name. here -> ";
- err_str += ln;
- }
-
- if (ln.find(key.fName) == 0 || ln[ln.find(key.fName) - 1] == ' ' ||
- ln[ln.find(key.fName) - 1] == '\t')
- {
- type_not_found = false;
-
- if (ln[ln.find(key.fName) + key.fName.size()] != ' ')
- {
- type_not_found = true;
-
- if (ln[ln.find(key.fName) + key.fName.size()] == '\t')
- type_not_found = false;
-
- goto next;
- }
- else if (ln[ln.find(key.fName) + key.fName.size()] != '\t')
- {
- type_not_found = true;
-
- if (ln[ln.find(key.fName) + key.fName.size()] == ' ')
- type_not_found = false;
- }
- }
-
- next:
-
- if (ln.find(';') == std::string::npos)
- {
- if (ln.find('(') != std::string::npos)
- {
- if (ln.find('=') == std::string::npos)
- continue;
- }
-
- err_str += "\nMissing ';', here -> ";
- err_str += ln;
- }
- else
- {
- continue;
- }
-
- if (ln.find('=') != std::string::npos)
- {
- if (ln.find('(') != std::string::npos)
- {
- if (ln.find(')') == std::string::npos)
- {
- err_str += "\nMissing ')', after '(' here -> ";
- err_str += ln.substr(ln.find('('));
- }
- }
- }
- }
- }
-
- if (kInBraces && ln.find("struct") != std::string::npos &&
- ln.find("union") != std::string::npos &&
- ln.find("enum") != std::string::npos &&
- ln.find('=') != std::string::npos)
- {
- if (ln.find(';') == std::string::npos)
- {
- err_str += "\nMissing ';' after struct/union/enum declaration, here -> ";
- err_str += ln;
- }
- }
-
- if (ln.find(';') != std::string::npos &&
- ln.find("for") == std::string::npos)
- {
- if (ln.find(';') + 1 != ln.size())
- {
- for (int i = 0; i < ln.substr(ln.find(';') + 1).size(); ++i)
- {
- if ((ln.substr(ln.find(';') + 1)[i] != ' ') ||
- (ln.substr(ln.find(';') + 1)[i] != '\t'))
- {
- if (auto err = this->Check(ln.substr(ln.find(';') + 1).c_str(), file);
- !err.empty())
- {
- err_str += "\nUnexpected text after ';' -> ";
- err_str += ln.substr(ln.find(';'));
- err_str += err;
- }
- }
- }
- }
- }
-
- if (ln.find('(') != std::string::npos)
- {
- if (ln.find(';') == std::string::npos && !LibCompiler::find_word(ln, "|") &&
- !LibCompiler::find_word(ln, "||") && !LibCompiler::find_word(ln, "&") &&
- !LibCompiler::find_word(ln, "&&") && !LibCompiler::find_word(ln, "~"))
- {
- bool found_func = false;
- size_t i = ln.find('(');
- std::vector<char> opens;
- std::vector<char> closes;
-
- for (; i < ln.size(); ++i)
- {
- if (ln[i] == ')')
- {
- closes.push_back(1);
- }
-
- if (ln[i] == '(')
- {
- opens.push_back(1);
- }
- }
-
- if (closes.size() != opens.size())
- err_str += "Unterminated (), here -> " + ln;
-
- bool space_found = false;
-
- for (int i = 0; i < ln.size(); ++i)
- {
- if (ln[i] == ')' && !space_found)
- {
- space_found = true;
- continue;
- }
-
- if (space_found)
- {
- if (ln[i] == ' ' && isalnum(ln[i + 1]))
- {
- err_str += "\nBad function format here -> ";
- err_str += ln;
- }
- }
- }
- }
-
- if (ln.find('(') < 1)
- {
- err_str += "\nMissing identifier before '(' here -> ";
- err_str += ln;
- }
- else
- {
- if (type_not_found && ln.find(';') == std::string::npos &&
- ln.find("if") == std::string::npos &&
- ln.find("|") == std::string::npos &&
- ln.find("&") == std::string::npos &&
- ln.find("(") == std::string::npos &&
- ln.find(")") == std::string::npos)
- {
- err_str += "\n Missing ';' or type, here -> ";
- err_str += ln;
- }
- }
-
- if (ln.find(')') == std::string::npos)
- {
- err_str += "\nMissing ')', after '(' here -> ";
- err_str += ln.substr(ln.find('('));
- }
- }
- else
- {
- if (ln.find("for") != std::string::npos ||
- ln.find("while") != std::string::npos)
- {
- err_str += "\nMissing '(', after \"for\", here -> ";
- err_str += ln;
- }
- }
-
- if (ln.find('}') != std::string::npos && !kInBraces)
- {
- if (!kInStruct && ln.find(';') == std::string::npos)
- {
- err_str += "\nMismatched '}', here -> ";
- err_str += ln;
- }
- }
-
- if (!ln.empty())
- {
- if (ln.find(';') == std::string::npos &&
- ln.find('{') == std::string::npos &&
- ln.find('}') == std::string::npos &&
- ln.find(')') == std::string::npos &&
- ln.find('(') == std::string::npos &&
- ln.find(',') == std::string::npos)
- {
- if (ln.size() <= 2)
- return err_str;
-
- err_str += "\nMissing ';', here -> ";
- err_str += ln;
- }
- }
-
- return err_str;
+ for (auto& key : kCompilerTypes) {
+ if (LibCompiler::find_word(ln, key.fName)) {
+ if (isdigit(ln[ln.find(key.fName) + key.fName.size() + 1])) {
+ err_str += "\nNumber cannot be set for ";
+ err_str += key.fName;
+ err_str += "'s name. here -> ";
+ err_str += ln;
+ }
+
+ if (ln.find(key.fName) == 0 || ln[ln.find(key.fName) - 1] == ' ' ||
+ ln[ln.find(key.fName) - 1] == '\t') {
+ type_not_found = false;
+
+ if (ln[ln.find(key.fName) + key.fName.size()] != ' ') {
+ type_not_found = true;
+
+ if (ln[ln.find(key.fName) + key.fName.size()] == '\t') type_not_found = false;
+
+ goto next;
+ } else if (ln[ln.find(key.fName) + key.fName.size()] != '\t') {
+ type_not_found = true;
+
+ if (ln[ln.find(key.fName) + key.fName.size()] == ' ') type_not_found = false;
+ }
+ }
+
+ next:
+
+ if (ln.find(';') == std::string::npos) {
+ if (ln.find('(') != std::string::npos) {
+ if (ln.find('=') == std::string::npos) continue;
+ }
+
+ err_str += "\nMissing ';', here -> ";
+ err_str += ln;
+ } else {
+ continue;
+ }
+
+ if (ln.find('=') != std::string::npos) {
+ if (ln.find('(') != std::string::npos) {
+ if (ln.find(')') == std::string::npos) {
+ err_str += "\nMissing ')', after '(' here -> ";
+ err_str += ln.substr(ln.find('('));
+ }
+ }
+ }
+ }
+ }
+
+ if (kInBraces && ln.find("struct") != std::string::npos &&
+ ln.find("union") != std::string::npos && ln.find("enum") != std::string::npos &&
+ ln.find('=') != std::string::npos) {
+ if (ln.find(';') == std::string::npos) {
+ err_str += "\nMissing ';' after struct/union/enum declaration, here -> ";
+ err_str += ln;
+ }
+ }
+
+ if (ln.find(';') != std::string::npos && ln.find("for") == std::string::npos) {
+ if (ln.find(';') + 1 != ln.size()) {
+ for (int i = 0; i < ln.substr(ln.find(';') + 1).size(); ++i) {
+ if ((ln.substr(ln.find(';') + 1)[i] != ' ') || (ln.substr(ln.find(';') + 1)[i] != '\t')) {
+ if (auto err = this->Check(ln.substr(ln.find(';') + 1).c_str(), file); !err.empty()) {
+ err_str += "\nUnexpected text after ';' -> ";
+ err_str += ln.substr(ln.find(';'));
+ err_str += err;
+ }
+ }
+ }
+ }
+ }
+
+ if (ln.find('(') != std::string::npos) {
+ if (ln.find(';') == std::string::npos && !LibCompiler::find_word(ln, "|") &&
+ !LibCompiler::find_word(ln, "||") && !LibCompiler::find_word(ln, "&") &&
+ !LibCompiler::find_word(ln, "&&") && !LibCompiler::find_word(ln, "~")) {
+ bool found_func = false;
+ size_t i = ln.find('(');
+ std::vector<char> opens;
+ std::vector<char> closes;
+
+ for (; i < ln.size(); ++i) {
+ if (ln[i] == ')') {
+ closes.push_back(1);
+ }
+
+ if (ln[i] == '(') {
+ opens.push_back(1);
+ }
+ }
+
+ if (closes.size() != opens.size()) err_str += "Unterminated (), here -> " + ln;
+
+ bool space_found = false;
+
+ for (int i = 0; i < ln.size(); ++i) {
+ if (ln[i] == ')' && !space_found) {
+ space_found = true;
+ continue;
+ }
+
+ if (space_found) {
+ if (ln[i] == ' ' && isalnum(ln[i + 1])) {
+ err_str += "\nBad function format here -> ";
+ err_str += ln;
+ }
+ }
+ }
+ }
+
+ if (ln.find('(') < 1) {
+ err_str += "\nMissing identifier before '(' here -> ";
+ err_str += ln;
+ } else {
+ if (type_not_found && ln.find(';') == std::string::npos &&
+ ln.find("if") == std::string::npos && ln.find("|") == std::string::npos &&
+ ln.find("&") == std::string::npos && ln.find("(") == std::string::npos &&
+ ln.find(")") == std::string::npos) {
+ err_str += "\n Missing ';' or type, here -> ";
+ err_str += ln;
+ }
+ }
+
+ if (ln.find(')') == std::string::npos) {
+ err_str += "\nMissing ')', after '(' here -> ";
+ err_str += ln.substr(ln.find('('));
+ }
+ } else {
+ if (ln.find("for") != std::string::npos || ln.find("while") != std::string::npos) {
+ err_str += "\nMissing '(', after \"for\", here -> ";
+ err_str += ln;
+ }
+ }
+
+ if (ln.find('}') != std::string::npos && !kInBraces) {
+ if (!kInStruct && ln.find(';') == std::string::npos) {
+ err_str += "\nMismatched '}', here -> ";
+ err_str += ln;
+ }
+ }
+
+ if (!ln.empty()) {
+ if (ln.find(';') == std::string::npos && ln.find('{') == std::string::npos &&
+ ln.find('}') == std::string::npos && ln.find(')') == std::string::npos &&
+ ln.find('(') == std::string::npos && ln.find(',') == std::string::npos) {
+ if (ln.size() <= 2) return err_str;
+
+ err_str += "\nMissing ';', here -> ";
+ err_str += ln;
+ }
+ }
+
+ return err_str;
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -1317,183 +1063,145 @@ skip_braces_check:
/////////////////////////////////////////////////////////////////////////////////////////
-class AssemblyMountpointCLang final ASSEMBLY_INTERFACE
-{
-public:
- explicit AssemblyMountpointCLang() = default;
- ~AssemblyMountpointCLang() override = default;
-
- LIBCOMPILER_COPY_DEFAULT(AssemblyMountpointCLang);
-
- [[maybe_unused]] static Int32 Arch() noexcept
- {
- return LibCompiler::AssemblyFactory::kArchPowerPC;
- }
-
- Int32 CompileToFormat(std::string& src, Int32 arch) override
- {
- if (arch != AssemblyMountpointCLang::Arch())
- return 1;
-
- if (kCompilerFrontend == nullptr)
- return 1;
-
- /* @brief copy contents wihtout extension */
- std::string src_file = src.data();
- std::ifstream src_fp = std::ifstream(src_file, std::ios::in);
- std::string dest;
-
- for (auto& ch : src_file)
- {
- if (ch == '.')
- {
- break;
- }
-
- dest += ch;
- }
-
- /* According to PEF ABI. */
- std::vector<const char*> exts = kAsmFileExts;
- dest += exts[4];
-
- kState.fOutputAssembly = std::make_unique<std::ofstream>(dest);
-
- auto fmt = LibCompiler::current_date();
-
- (*kState.fOutputAssembly) << "# Path: " << src_file << "\n";
- (*kState.fOutputAssembly)
- << "# Language: POWER Assembly (Generated from C)\n";
- (*kState.fOutputAssembly) << "# Date: " << fmt << "\n\n";
-
- LibCompiler::SyntaxLeafList syntax;
-
- kState.fSyntaxTreeList.push_back(syntax);
- kState.fSyntaxTree =
- &kState.fSyntaxTreeList[kState.fSyntaxTreeList.size() - 1];
-
- std::string line_src;
-
- while (std::getline(src_fp, line_src))
- {
- if (auto err = kCompilerFrontend->Check(line_src.c_str(), src.data());
- err.empty())
- {
- kCompilerFrontend->Compile(line_src, src.data());
- }
- else
- {
- Detail::print_error(err, src.data());
- }
- }
-
- if (kAcceptableErrors > 0)
- return 1;
-
- std::vector<std::string> keywords = {"ld", "stw", "add", "sub", "or"};
-
- ///
- /// Replace, optimize, fix assembly output.
- ///
-
- for (auto& leaf : kState.fSyntaxTree->fLeafList)
- {
- std::vector<std::string> access_keywords = {"->", "."};
-
- for (auto& access_ident : access_keywords)
- {
- if (LibCompiler::find_word(leaf.fUserValue, access_ident))
- {
- for (auto& struc : kState.kStructMap)
- {
- /// TODO:
- }
- }
- }
-
- for (auto& keyword : keywords)
- {
- if (LibCompiler::find_word(leaf.fUserValue, keyword))
- {
- std::size_t cnt = 0UL;
-
- for (auto& reg : kState.kStackFrame)
- {
- std::string needle;
-
- for (size_t i = 0; i < reg.fName.size(); i++)
- {
- if (reg.fName[i] == ' ')
- {
- ++i;
-
- for (; i < reg.fName.size(); i++)
- {
- if (reg.fName[i] == ',')
- {
- break;
- }
-
- if (reg.fName[i] == ' ')
- continue;
-
- needle += reg.fName[i];
- }
-
- break;
- }
- }
-
- if (LibCompiler::find_word(leaf.fUserValue, needle))
- {
- if (leaf.fUserValue.find("extern_segment ") != std::string::npos)
- {
- std::string range = "extern_segment ";
- leaf.fUserValue.replace(leaf.fUserValue.find(range),
- range.size(), "");
- }
-
- if (leaf.fUserValue.find("ldw r6") != std::string::npos)
- {
- std::string::difference_type countComma = std::count(
- leaf.fUserValue.begin(), leaf.fUserValue.end(), ',');
-
- if (countComma == 1)
- {
- leaf.fUserValue.replace(leaf.fUserValue.find("ldw"),
- strlen("ldw"), "mr");
- }
- }
-
- leaf.fUserValue.replace(leaf.fUserValue.find(needle),
- needle.size(), reg.fReg);
-
- ++cnt;
- }
- }
-
- if (cnt > 1 && keyword != "mr" && keyword != "add" &&
- keyword != "dec")
- {
- leaf.fUserValue.replace(leaf.fUserValue.find(keyword),
- keyword.size(), "mr");
- }
- }
- }
- }
-
- for (auto& leaf : kState.fSyntaxTree->fLeafList)
- {
- (*kState.fOutputAssembly) << leaf.fUserValue;
- }
-
- kState.fSyntaxTree = nullptr;
-
- kState.fOutputAssembly->flush();
- kState.fOutputAssembly.reset();
-
- return kExitOK;
- }
+class AssemblyMountpointCLang final ASSEMBLY_INTERFACE {
+ public:
+ explicit AssemblyMountpointCLang() = default;
+ ~AssemblyMountpointCLang() override = default;
+
+ LIBCOMPILER_COPY_DEFAULT(AssemblyMountpointCLang);
+
+ [[maybe_unused]] static Int32 Arch() noexcept {
+ return LibCompiler::AssemblyFactory::kArchPowerPC;
+ }
+
+ Int32 CompileToFormat(std::string& src, Int32 arch) override {
+ if (arch != AssemblyMountpointCLang::Arch()) return 1;
+
+ if (kCompilerFrontend == nullptr) return 1;
+
+ /* @brief copy contents wihtout extension */
+ std::string src_file = src.data();
+ std::ifstream src_fp = std::ifstream(src_file, std::ios::in);
+ std::string dest;
+
+ for (auto& ch : src_file) {
+ if (ch == '.') {
+ break;
+ }
+
+ dest += ch;
+ }
+
+ /* According to PEF ABI. */
+ std::vector<const char*> exts = kAsmFileExts;
+ dest += exts[4];
+
+ kState.fOutputAssembly = std::make_unique<std::ofstream>(dest);
+
+ auto fmt = LibCompiler::current_date();
+
+ (*kState.fOutputAssembly) << "# Path: " << src_file << "\n";
+ (*kState.fOutputAssembly) << "# Language: POWER Assembly (Generated from C)\n";
+ (*kState.fOutputAssembly) << "# Date: " << fmt << "\n\n";
+
+ LibCompiler::SyntaxLeafList syntax;
+
+ kState.fSyntaxTreeList.push_back(syntax);
+ kState.fSyntaxTree = &kState.fSyntaxTreeList[kState.fSyntaxTreeList.size() - 1];
+
+ std::string line_src;
+
+ while (std::getline(src_fp, line_src)) {
+ if (auto err = kCompilerFrontend->Check(line_src.c_str(), src.data()); err.empty()) {
+ kCompilerFrontend->Compile(line_src, src.data());
+ } else {
+ Detail::print_error(err, src.data());
+ }
+ }
+
+ if (kAcceptableErrors > 0) return 1;
+
+ std::vector<std::string> keywords = {"ld", "stw", "add", "sub", "or"};
+
+ ///
+ /// Replace, optimize, fix assembly output.
+ ///
+
+ for (auto& leaf : kState.fSyntaxTree->fLeafList) {
+ std::vector<std::string> access_keywords = {"->", "."};
+
+ for (auto& access_ident : access_keywords) {
+ if (LibCompiler::find_word(leaf.fUserValue, access_ident)) {
+ for (auto& struc : kState.kStructMap) {
+ /// TODO:
+ }
+ }
+ }
+
+ for (auto& keyword : keywords) {
+ if (LibCompiler::find_word(leaf.fUserValue, keyword)) {
+ std::size_t cnt = 0UL;
+
+ for (auto& reg : kState.kStackFrame) {
+ std::string needle;
+
+ for (size_t i = 0; i < reg.fName.size(); i++) {
+ if (reg.fName[i] == ' ') {
+ ++i;
+
+ for (; i < reg.fName.size(); i++) {
+ if (reg.fName[i] == ',') {
+ break;
+ }
+
+ if (reg.fName[i] == ' ') continue;
+
+ needle += reg.fName[i];
+ }
+
+ break;
+ }
+ }
+
+ if (LibCompiler::find_word(leaf.fUserValue, needle)) {
+ if (leaf.fUserValue.find("extern_segment ") != std::string::npos) {
+ std::string range = "extern_segment ";
+ leaf.fUserValue.replace(leaf.fUserValue.find(range), range.size(), "");
+ }
+
+ if (leaf.fUserValue.find("ldw r6") != std::string::npos) {
+ std::string::difference_type countComma =
+ std::count(leaf.fUserValue.begin(), leaf.fUserValue.end(), ',');
+
+ if (countComma == 1) {
+ leaf.fUserValue.replace(leaf.fUserValue.find("ldw"), strlen("ldw"), "mr");
+ }
+ }
+
+ leaf.fUserValue.replace(leaf.fUserValue.find(needle), needle.size(), reg.fReg);
+
+ ++cnt;
+ }
+ }
+
+ if (cnt > 1 && keyword != "mr" && keyword != "add" && keyword != "dec") {
+ leaf.fUserValue.replace(leaf.fUserValue.find(keyword), keyword.size(), "mr");
+ }
+ }
+ }
+ }
+
+ for (auto& leaf : kState.fSyntaxTree->fLeafList) {
+ (*kState.fOutputAssembly) << leaf.fUserValue;
+ }
+
+ kState.fSyntaxTree = nullptr;
+
+ kState.fOutputAssembly->flush();
+ kState.fOutputAssembly.reset();
+
+ return kExitOK;
+ }
};
/////////////////////////////////////////////////////////////////////////////////////////
@@ -1501,116 +1209,98 @@ public:
#include <LibCompiler/Version.h>
#define kPrintF printf
-#define kSplashCxx() \
- kPrintF(kWhite "cc, %s, (c) Amlal El Mahrouss\n", kDistVersion)
+#define kSplashCxx() kPrintF(kWhite "cc, %s, (c) Amlal El Mahrouss\n", kDistVersion)
-static void cc_print_help()
-{
- kSplashCxx();
+static void cc_print_help() {
+ kSplashCxx();
}
/////////////////////////////////////////////////////////////////////////////////////////
#define kExt ".c"
-LIBCOMPILER_MODULE(NeOSCompilerCLangPowerPC)
-{
- kCompilerTypes.push_back({.fName = "void", .fValue = "void"});
- kCompilerTypes.push_back({.fName = "char", .fValue = "byte"});
- kCompilerTypes.push_back({.fName = "short", .fValue = "hword"});
- kCompilerTypes.push_back({.fName = "int", .fValue = "dword"});
- kCompilerTypes.push_back({.fName = "long", .fValue = "qword"});
- kCompilerTypes.push_back({.fName = "*", .fValue = "offset"});
-
- bool skip = false;
-
- kFactory.Mount(new AssemblyMountpointCLang());
- kMachine = LibCompiler::AssemblyFactory::kArchPowerPC;
- kCompilerFrontend = new CompilerFrontendPower64();
-
- for (auto index = 1UL; index < argc; ++index)
- {
- if (skip)
- {
- skip = false;
- continue;
- }
-
- if (argv[index][0] == '-')
- {
- if (strcmp(argv[index], "-v") == 0 ||
- strcmp(argv[index], "-version") == 0)
- {
- kSplashCxx();
- return kExitOK;
- }
-
- if (strcmp(argv[index], "-verbose") == 0)
- {
- kState.fVerbose = true;
-
- continue;
- }
-
- if (strcmp(argv[index], "-h") == 0 || strcmp(argv[index], "-help") == 0)
- {
- cc_print_help();
-
- return kExitOK;
- }
-
- if (strcmp(argv[index], "-dialect") == 0)
- {
- if (kCompilerFrontend)
- std::cout << kCompilerFrontend->Language() << "\n";
-
- return kExitOK;
- }
-
- if (strcmp(argv[index], "-fmax-exceptions") == 0)
- {
- try
- {
- kErrorLimit = std::strtol(argv[index + 1], nullptr, 10);
- }
- // catch anything here
- catch (...)
- {
- kErrorLimit = 0;
- }
-
- skip = true;
-
- continue;
- }
-
- std::string err = "Unknown command: ";
- err += argv[index];
-
- Detail::print_error(err, "cc");
-
- continue;
- }
-
- kFileList.emplace_back(argv[index]);
-
- std::string srcFile = argv[index];
-
- if (strstr(argv[index], kExt) == nullptr)
- {
- if (kState.fVerbose)
- {
- Detail::print_error(srcFile + " is not a valid C source.\n", "cc");
- }
-
- return 1;
- }
-
- if (kFactory.Compile(srcFile, kMachine) != kExitOK)
- return 1;
- }
-
- return kExitOK;
+LIBCOMPILER_MODULE(NeOSCompilerCLangPowerPC) {
+ kCompilerTypes.push_back({.fName = "void", .fValue = "void"});
+ kCompilerTypes.push_back({.fName = "char", .fValue = "byte"});
+ kCompilerTypes.push_back({.fName = "short", .fValue = "hword"});
+ kCompilerTypes.push_back({.fName = "int", .fValue = "dword"});
+ kCompilerTypes.push_back({.fName = "long", .fValue = "qword"});
+ kCompilerTypes.push_back({.fName = "*", .fValue = "offset"});
+
+ bool skip = false;
+
+ kFactory.Mount(new AssemblyMountpointCLang());
+ kMachine = LibCompiler::AssemblyFactory::kArchPowerPC;
+ kCompilerFrontend = new CompilerFrontendPower64();
+
+ for (auto index = 1UL; index < argc; ++index) {
+ if (skip) {
+ skip = false;
+ continue;
+ }
+
+ if (argv[index][0] == '-') {
+ if (strcmp(argv[index], "-v") == 0 || strcmp(argv[index], "-version") == 0) {
+ kSplashCxx();
+ return kExitOK;
+ }
+
+ if (strcmp(argv[index], "-verbose") == 0) {
+ kState.fVerbose = true;
+
+ continue;
+ }
+
+ if (strcmp(argv[index], "-h") == 0 || strcmp(argv[index], "-help") == 0) {
+ cc_print_help();
+
+ return kExitOK;
+ }
+
+ if (strcmp(argv[index], "-dialect") == 0) {
+ if (kCompilerFrontend) std::cout << kCompilerFrontend->Language() << "\n";
+
+ return kExitOK;
+ }
+
+ if (strcmp(argv[index], "-fmax-exceptions") == 0) {
+ try {
+ kErrorLimit = std::strtol(argv[index + 1], nullptr, 10);
+ }
+ // catch anything here
+ catch (...) {
+ kErrorLimit = 0;
+ }
+
+ skip = true;
+
+ continue;
+ }
+
+ std::string err = "Unknown command: ";
+ err += argv[index];
+
+ Detail::print_error(err, "cc");
+
+ continue;
+ }
+
+ kFileList.emplace_back(argv[index]);
+
+ std::string srcFile = argv[index];
+
+ if (strstr(argv[index], kExt) == nullptr) {
+ if (kState.fVerbose) {
+ Detail::print_error(srcFile + " is not a valid C source.\n", "cc");
+ }
+
+ return 1;
+ }
+
+ if (kFactory.Compile(srcFile, kMachine) != kExitOK) return 1;
+ }
+
+ return kExitOK;
}
// Last rev 8-1-24
diff --git a/dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc b/dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc
index c053920..66cf859 100644
--- a/dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc
+++ b/dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc
@@ -14,8 +14,10 @@
#define kExitOK (EXIT_SUCCESS)
#define kExitNO (EXIT_FAILURE)
-#define kSplashCxx() \
- kPrintF(kWhite "%s\n", "NeKernel Optimized C++ Compiler Driver, (c) 2024-2025 Amlal El Mahrouss, All rights reserved.")
+#define kSplashCxx() \
+ kPrintF(kWhite "%s\n", \
+ "NeKernel Optimized C++ Compiler Driver, (c) 2024-2025 Amlal El Mahrouss, All rights " \
+ "reserved.")
// extern_segment, @autodelete { ... }, fn foo() -> auto { ... }
@@ -42,7 +44,7 @@
///////////////////////
#define kBlank "\e[0;30m"
-#define kRed "\e[0;31m"
+#define kRed "\e[0;31m"
#define kWhite "\e[0;97m"
/////////////////////////////////////
@@ -52,80 +54,68 @@
/////////////////////////////////////
/// @internal
-namespace Detail
-{
- std::filesystem::path expand_home(const std::filesystem::path& p)
- {
- if (!p.empty() && p.string()[0] == '~')
- {
- const char* home = std::getenv("HOME"); // For Unix-like systems
- if (!home)
- {
- home = std::getenv("USERPROFILE"); // For Windows
- }
- if (home)
- {
- return std::filesystem::path(home) / p.relative_path().string().substr(1);
- }
- else
- {
- throw std::runtime_error("Home directory not found in environment variables");
- }
- }
- return p;
- }
-
- struct CompilerRegisterMap final
- {
- std::string fName;
- std::string fReg;
- };
-
- // \brief Offset based struct/class
- struct CompilerStructMap final
- {
- std::string fName;
- std::string fReg;
-
- // offset counter
- std::size_t fOffsetsCnt;
-
- // offset array
- std::vector<std::pair<Int32, std::string>> fOffsets;
- };
-
- struct CompilerState final
- {
- std::vector<CompilerRegisterMap> fStackMapVector;
- std::vector<CompilerStructMap> fStructMapVector;
- LibCompiler::SyntaxLeafList* fSyntaxTree{nullptr};
- std::unique_ptr<std::ofstream> fOutputAssembly;
- std::string fLastFile;
- std::string fLastError;
- Boolean fVerbose;
- };
-} // namespace Detail
+namespace Detail {
+std::filesystem::path expand_home(const std::filesystem::path& p) {
+ if (!p.empty() && p.string()[0] == '~') {
+ const char* home = std::getenv("HOME"); // For Unix-like systems
+ if (!home) {
+ home = std::getenv("USERPROFILE"); // For Windows
+ }
+ if (home) {
+ return std::filesystem::path(home) / p.relative_path().string().substr(1);
+ } else {
+ throw std::runtime_error("Home directory not found in environment variables");
+ }
+ }
+ return p;
+}
+
+struct CompilerRegisterMap final {
+ std::string fName;
+ std::string fReg;
+};
+
+// \brief Offset based struct/class
+struct CompilerStructMap final {
+ std::string fName;
+ std::string fReg;
+
+ // offset counter
+ std::size_t fOffsetsCnt;
+
+ // offset array
+ std::vector<std::pair<Int32, std::string>> fOffsets;
+};
+
+struct CompilerState final {
+ std::vector<CompilerRegisterMap> fStackMapVector;
+ std::vector<CompilerStructMap> fStructMapVector;
+ LibCompiler::SyntaxLeafList* fSyntaxTree{nullptr};
+ std::unique_ptr<std::ofstream> fOutputAssembly;
+ std::string fLastFile;
+ std::string fLastError;
+ Boolean fVerbose;
+};
+} // namespace Detail
static Detail::CompilerState kState;
-static SizeType kErrorLimit = 100;
+static SizeType kErrorLimit = 100;
static Int32 kOnClassScope = 0;
static Int32 kAcceptableErrors = 0;
-namespace Detail
-{
- /// @brief prints an error into stdout.
- /// @param reason the reason of the error.
- /// @param file where does it originate from?
- void print_error(std::string reason, std::string file) noexcept;
+namespace Detail {
+/// @brief prints an error into stdout.
+/// @param reason the reason of the error.
+/// @param file where does it originate from?
+void print_error(std::string reason, std::string file) noexcept;
- struct CompilerType final
- {
- std::string fName;
- std::string fValue;
- };
-} // namespace Detail
+struct CompilerType final {
+ std::string fName;
+ std::string fValue;
+};
+} // namespace Detail
/////////////////////////////////////////////////////////////////////////////////////////
@@ -138,10 +128,10 @@ static int kMachine = LibCompiler::AssemblyFactory::kArchAMD64;
/////////////////////////////////////////
-static size_t kRegisterCnt = kAsmRegisterLimit;
-static size_t kStartUsable = 8;
-static size_t kUsableLimit = 15;
-static size_t kRegisterCounter = kStartUsable;
+static size_t kRegisterCnt = kAsmRegisterLimit;
+static size_t kStartUsable = 8;
+static size_t kUsableLimit = 15;
+static size_t kRegisterCounter = kStartUsable;
static std::vector<LibCompiler::CompilerKeyword> kKeywords;
/////////////////////////////////////////
@@ -150,26 +140,25 @@ static std::vector<LibCompiler::CompilerKeyword> kKeywords;
/////////////////////////////////////////
-static std::vector<std::string> kFileList;
+static std::vector<std::string> kFileList;
static LibCompiler::AssemblyFactory kFactory;
-static Boolean kInStruct = false;
-static Boolean kOnWhileLoop = false;
-static Boolean kOnForLoop = false;
-static Boolean kInBraces = false;
-static size_t kBracesCount = 0UL;
+static Boolean kInStruct = false;
+static Boolean kOnWhileLoop = false;
+static Boolean kOnForLoop = false;
+static Boolean kInBraces = false;
+static size_t kBracesCount = 0UL;
/* @brief C++ compiler backend for the NE C++ driver */
-class CompilerFrontendCPlusPlus final : public LibCompiler::ICompilerFrontend
-{
-public:
- explicit CompilerFrontendCPlusPlus() = default;
- ~CompilerFrontendCPlusPlus() override = default;
+class CompilerFrontendCPlusPlus final : public LibCompiler::ICompilerFrontend {
+ public:
+ explicit CompilerFrontendCPlusPlus() = default;
+ ~CompilerFrontendCPlusPlus() override = default;
- LIBCOMPILER_COPY_DEFAULT(CompilerFrontendCPlusPlus);
+ LIBCOMPILER_COPY_DEFAULT(CompilerFrontendCPlusPlus);
- Boolean Compile(const std::string text, const std::string file) override;
+ Boolean Compile(const std::string text, const std::string file) override;
- const char* Language() override;
+ const char* Language() override;
};
/// @internal compiler variables
@@ -179,40 +168,21 @@ static CompilerFrontendCPlusPlus* kCompilerFrontend = nullptr;
static std::vector<std::string> kRegisterMap;
static std::vector<std::string> kRegisterList = {
- "rbx",
- "rsi",
- "r10",
- "r11",
- "r12",
- "r13",
- "r14",
- "r15",
- "xmm12",
- "xmm13",
- "xmm14",
- "xmm15",
+ "rbx", "rsi", "r10", "r11", "r12", "r13", "r14", "r15", "xmm12", "xmm13", "xmm14", "xmm15",
};
/// @brief The PEF calling convention (caller must save rax, rbp)
/// @note callee must return via **rax**.
static std::vector<std::string> kRegisterConventionCallList = {
- "r8",
- "r9",
- "r10",
- "r11",
- "r12",
- "r13",
- "r14",
- "r15",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
};
static std::size_t kFunctionEmbedLevel = 0UL;
/// detail namespaces
-const char* CompilerFrontendCPlusPlus::Language()
-{
- return "NeKernel C++";
+const char* CompilerFrontendCPlusPlus::Language() {
+ return "NeKernel C++";
}
static std::uintptr_t kOrigin = 0x1000000;
@@ -226,645 +196,553 @@ std::vector<std::pair<std::string, std::uintptr_t>> kOriginMap;
/////////////////////////////////////////////////////////////////////////////////////////
-Boolean CompilerFrontendCPlusPlus::Compile(std::string text,
- const std::string file)
-{
- if (text.empty())
- return true;
-
- // Clean whitespace and tabs
- std::string cleanLine = text;
- cleanLine.erase(std::remove(cleanLine.begin(), cleanLine.end(), '\t'), cleanLine.end());
- cleanLine.erase(0, cleanLine.find_first_not_of(" \r\n"));
- cleanLine.erase(cleanLine.find_last_not_of(" \r\n") + 1);
-
- // Skip empty, doc, or block comment lines
- if (cleanLine.empty() || cleanLine.starts_with("///") || cleanLine.starts_with("//") || cleanLine.starts_with("/*"))
- return true;
-
- std::size_t index = 0UL;
- std::vector<std::pair<LibCompiler::CompilerKeyword, std::size_t>> keywords_list;
-
- Boolean found = false;
- static Boolean commentBlock = false;
-
- for (auto& keyword : kKeywords)
- {
- if (text.find(keyword.keyword_name) != std::string::npos)
- {
- switch (keyword.keyword_kind)
- {
- case LibCompiler::kKeywordKindCommentMultiLineStart: {
- commentBlock = true;
- return true;
- }
- case LibCompiler::kKeywordKindCommentMultiLineEnd: {
- commentBlock = false;
- break;
- }
- case LibCompiler::kKeywordKindCommentInline: {
- break;
- }
- default:
- break;
- }
-
- if (text[text.find(keyword.keyword_name) - 1] == '+' &&
- keyword.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableAssign)
- continue;
-
- if (text[text.find(keyword.keyword_name) - 1] == '-' &&
- keyword.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableAssign)
- continue;
-
- if (text[text.find(keyword.keyword_name) + 1] == '=' &&
- keyword.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableAssign)
- continue;
-
- keywords_list.emplace_back(std::make_pair(keyword, index));
- ++index;
-
- found = true;
- }
- }
-
- if (!found && !commentBlock)
- {
- for (size_t i = 0; i < text.size(); i++)
- {
- if (isalnum(text[i]))
- {
- Detail::print_error("syntax error: " + text, file);
- return false;
- }
- }
- }
-
- for (auto& keyword : keywords_list)
- {
- auto syntax_tree = LibCompiler::SyntaxLeafList::SyntaxLeaf();
-
- switch (keyword.first.keyword_kind)
- {
- case LibCompiler::KeywordKind::kKeywordKindClass: {
- ++kOnClassScope;
- break;
- }
- case LibCompiler::KeywordKind::kKeywordKindIf: {
- auto expr = text.substr(text.find(keyword.first.keyword_name) + keyword.first.keyword_name.size() + 1, text.find(")") - 1);
-
- if (expr.find(">=") != std::string::npos)
- {
- auto left = text.substr(text.find(keyword.first.keyword_name) + keyword.first.keyword_name.size() + 2, expr.find("<=") + strlen("<="));
- auto right = text.substr(expr.find(">=") + strlen(">="), text.find(")") - 1);
-
- size_t i = right.size() - 1;
-
- try
- {
- while (!std::isalnum(right[i]))
- {
- right.erase(i, 1);
- --i;
- }
-
- right.erase(0, i);
- }
- catch (...)
- {
- right.erase(0, i);
- }
-
- i = left.size() - 1;
- try
- {
- while (!std::isalnum(left[i]))
- {
- left.erase(i, 1);
- --i;
- }
-
- left.erase(0, i);
- }
- catch (...)
- {
- left.erase(0, i);
- }
-
- if (!isdigit(left[0]) ||
- !isdigit(right[0]))
- {
- auto indexRight = 0UL;
-
- auto& valueOfVar = !isdigit(left[0]) ? left : right;
-
- for (auto pairRight : kRegisterMap)
- {
- ++indexRight;
-
- if (pairRight != valueOfVar)
- {
-
- auto& valueOfVarOpposite = isdigit(left[0]) ? left : right;
-
- syntax_tree.fUserValue += "mov " + kRegisterList[indexRight + 1] + ", " + valueOfVarOpposite + "\n";
- syntax_tree.fUserValue += "cmp " + kRegisterList[kRegisterMap.size() - 1] + "," + kRegisterList[indexRight + 1] + "\n";
-
- goto done_iterarting_on_if;
- }
-
- auto& valueOfVarOpposite = isdigit(left[0]) ? left : right;
-
- syntax_tree.fUserValue += "mov " + kRegisterList[indexRight + 1] + ", " + valueOfVarOpposite + "\n";
- syntax_tree.fUserValue += "cmp " + kRegisterList[kRegisterMap.size() - 1] + ", " + kRegisterList[indexRight + 1] + "\n";
-
- break;
- }
- }
-
- done_iterarting_on_if:
-
- std::string fnName = text;
- fnName.erase(fnName.find(keyword.first.keyword_name));
-
- for (auto& ch : fnName)
- {
- if (ch == ' ')
- ch = '_';
- }
-
- syntax_tree.fUserValue += "jge __OFFSET_ON_TRUE_LC\nsegment .code64 __OFFSET_ON_TRUE_LC:\n";
- }
-
- break;
- }
- case LibCompiler::KeywordKind::kKeywordKindFunctionStart: {
- for (auto& ch : text)
- {
- if (isdigit(ch))
- {
- goto dont_accept;
- }
- }
-
- goto accept;
-
- dont_accept:
- return false;
-
- accept:
- std::string fnName = text;
- size_t indexFnName = 0;
-
- // this one is for the type.
- for (auto& ch : text)
- {
- ++indexFnName;
-
- if (ch == '\t')
- break;
-
- if (ch == ' ')
- break;
- }
-
- fnName = text.substr(indexFnName);
-
- if (text.find("return ") != std::string::npos)
- {
- text.erase(0, text.find("return "));
- break;
- }
-
- if (text.ends_with(";") && text.find("return") == std::string::npos)
- goto LC_write_assembly;
- else if (text.size() <= indexFnName)
- Detail::print_error("Invalid function name: " + fnName, file);
-
- indexFnName = 0;
-
- for (auto& ch : fnName)
- {
- if (ch == ' ' ||
- ch == '\t')
- {
- if (fnName[indexFnName - 1] != ')')
- Detail::print_error("Invalid function name: " + fnName, file);
-
- if ((indexFnName + 1) != fnName.size())
- Detail::print_error("Extra characters after function name: " + fnName, file);
- }
-
- ++indexFnName;
- }
-
- syntax_tree.fUserValue = "public_segment .code64 __LIBCOMPILER_" + fnName + "\n";
- ++kFunctionEmbedLevel;
-
- kOriginMap.push_back({"__LIBCOMPILER_" + fnName, kOrigin});
-
- break;
-
- LC_write_assembly:
- auto it = std::find_if(kOriginMap.begin(), kOriginMap.end(), [&fnName](std::pair<std::string, std::uintptr_t> pair) -> bool {
- return fnName == pair.first;
- });
-
- std::stringstream ss;
- ss << std::hex << it->second;
-
- if (it != kOriginMap.end())
- {
- syntax_tree.fUserValue = "jmp " + ss.str() + "\n";
- kOrigin += 1UL;
- }
- }
- case LibCompiler::KeywordKind::kKeywordKindFunctionEnd: {
- if (kOnClassScope)
- --kOnClassScope;
-
- if (text.ends_with(";"))
- break;
-
- --kFunctionEmbedLevel;
-
- if (kRegisterMap.size() > kRegisterList.size())
- {
- --kFunctionEmbedLevel;
- }
-
- if (kFunctionEmbedLevel < 1)
- kRegisterMap.clear();
-
- break;
- }
- case LibCompiler::KeywordKind::kKeywordKindEndInstr:
- case LibCompiler::KeywordKind::kKeywordKindVariableInc:
- case LibCompiler::KeywordKind::kKeywordKindVariableDec:
- case LibCompiler::KeywordKind::kKeywordKindVariableAssign: {
- std::string valueOfVar = "";
-
- if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableInc)
- {
- valueOfVar = text.substr(text.find("+=") + 2);
- }
- else if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableDec)
- {
- valueOfVar = text.substr(text.find("-=") + 2);
- }
- else if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableAssign)
- {
- valueOfVar = text.substr(text.find("=") + 1);
- }
- else if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindEndInstr)
- {
- break;
- }
-
- while (valueOfVar.find(";") != std::string::npos &&
- keyword.first.keyword_kind != LibCompiler::KeywordKind::kKeywordKindEndInstr)
- {
- valueOfVar.erase(valueOfVar.find(";"));
- }
-
- std::string varName = text;
-
- if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableInc)
- {
- varName.erase(varName.find("+="));
- }
- else if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableDec)
- {
- varName.erase(varName.find("-="));
- }
- else if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableAssign)
- {
- varName.erase(varName.find("="));
- }
- else if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindEndInstr)
- {
- varName.erase(varName.find(";"));
- }
-
- static Boolean typeFound = false;
-
- for (auto& keyword : kKeywords)
- {
- if (keyword.keyword_kind == LibCompiler::kKeywordKindType)
- {
- if (text.find(keyword.keyword_name) != std::string::npos)
- {
- if (text[text.find(keyword.keyword_name)] == ' ')
- {
- typeFound = false;
- continue;
- }
-
- typeFound = true;
- }
- }
- }
-
- std::string instr = "mov ";
-
- if (typeFound && keyword.first.keyword_kind != LibCompiler::KeywordKind::kKeywordKindVariableInc &&
- keyword.first.keyword_kind != LibCompiler::KeywordKind::kKeywordKindVariableDec)
- {
- if (kRegisterMap.size() > kRegisterList.size())
- {
- ++kFunctionEmbedLevel;
- }
-
- while (varName.find(" ") != std::string::npos)
- {
- varName.erase(varName.find(" "), 1);
- }
-
- while (varName.find("\t") != std::string::npos)
- {
- varName.erase(varName.find("\t"), 1);
- }
-
- for (size_t i = 0; !isalnum(valueOfVar[i]); i++)
- {
- if (i > valueOfVar.size())
- break;
-
- valueOfVar.erase(i, 1);
- }
-
- constexpr auto cTrueVal = "true";
- constexpr auto cFalseVal = "false";
-
- if (valueOfVar == cTrueVal)
- {
- valueOfVar = "1";
- }
- else if (valueOfVar == cFalseVal)
- {
- valueOfVar = "0";
- }
-
- std::size_t indexRight = 0UL;
-
- for (auto pairRight : kRegisterMap)
- {
- ++indexRight;
-
- if (pairRight != valueOfVar)
- {
- if (valueOfVar[0] == '\"')
- {
-
- syntax_tree.fUserValue = "segment .data64 __LIBCOMPILER_LOCAL_VAR_" + varName + ": db " + valueOfVar + ", 0\n\n";
- syntax_tree.fUserValue += instr + kRegisterList[kRegisterMap.size() - 1] + ", " + "__LIBCOMPILER_LOCAL_VAR_" + varName + "\n";
- kOrigin += 1UL;
- }
- else
- {
- syntax_tree.fUserValue = instr + kRegisterList[kRegisterMap.size() - 1] + ", " + valueOfVar + "\n";
- kOrigin += 1UL;
- }
-
- goto done;
- }
- }
-
- if (((int)indexRight - 1) < 0)
- {
- if (valueOfVar[0] == '\"')
- {
-
- syntax_tree.fUserValue = "segment .data64 __LIBCOMPILER_LOCAL_VAR_" + varName + ": db " + valueOfVar + ", 0\n";
- syntax_tree.fUserValue += instr + kRegisterList[kRegisterMap.size()] + ", " + "__LIBCOMPILER_LOCAL_VAR_" + varName + "\n";
- kOrigin += 1UL;
- }
- else
- {
- syntax_tree.fUserValue = instr + kRegisterList[kRegisterMap.size()] + ", " + valueOfVar + "\n";
- kOrigin += 1UL;
- }
-
- goto done;
- }
-
- if (valueOfVar[0] != '\"' &&
- valueOfVar[0] != '\'' &&
- !isdigit(valueOfVar[0]))
- {
- for (auto pair : kRegisterMap)
- {
- if (pair == valueOfVar)
- goto done;
- }
-
- Detail::print_error("Variable not declared: " + varName, file);
- return false;
- }
-
- done:
- for (auto& keyword : kKeywords)
- {
- if (keyword.keyword_kind == LibCompiler::kKeywordKindType &&
- varName.find(keyword.keyword_name) != std::string::npos)
- {
- varName.erase(varName.find(keyword.keyword_name), keyword.keyword_name.size());
- break;
- }
- }
-
- kRegisterMap.push_back(varName);
-
- break;
- }
-
- if (kKeywords[keyword.second - 1].keyword_kind == LibCompiler::kKeywordKindType ||
- kKeywords[keyword.second - 1].keyword_kind == LibCompiler::kKeywordKindTypePtr)
- {
- syntax_tree.fUserValue = "\n";
- continue;
- }
-
- if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindEndInstr)
- {
- syntax_tree.fUserValue = "\n";
- continue;
- }
-
- if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableInc)
- {
- instr = "add ";
- }
- else if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableDec)
- {
- instr = "sub ";
- }
-
- std::string varErrCpy = varName;
-
- while (varName.find(" ") != std::string::npos)
- {
- varName.erase(varName.find(" "), 1);
- }
-
- while (varName.find("\t") != std::string::npos)
- {
- varName.erase(varName.find("\t"), 1);
- }
-
- std::size_t indxReg = 0UL;
-
- for (size_t i = 0; !isalnum(valueOfVar[i]); i++)
- {
- if (i > valueOfVar.size())
- break;
-
- valueOfVar.erase(i, 1);
- }
-
- while (valueOfVar.find(" ") != std::string::npos)
- {
- valueOfVar.erase(valueOfVar.find(" "), 1);
- }
-
- while (valueOfVar.find("\t") != std::string::npos)
- {
- valueOfVar.erase(valueOfVar.find("\t"), 1);
- }
-
- constexpr auto cTrueVal = "true";
- constexpr auto cFalseVal = "false";
-
- /// interpet boolean values, since we're on C++
-
- if (valueOfVar == cTrueVal)
- {
- valueOfVar = "1";
- }
- else if (valueOfVar == cFalseVal)
- {
- valueOfVar = "0";
- }
-
- for (auto pair : kRegisterMap)
- {
- ++indxReg;
-
- if (pair != varName)
- continue;
-
- std::size_t indexRight = 0ul;
-
- for (auto pairRight : kRegisterMap)
- {
- ++indexRight;
-
- if (pairRight != varName)
- {
- syntax_tree.fUserValue = instr + kRegisterList[kRegisterMap.size()] + ", " + valueOfVar + "\n";
- kOrigin += 1UL;
- continue;
- }
-
- syntax_tree.fUserValue = instr + kRegisterList[indexRight - 1] + ", " + valueOfVar + "\n";
- kOrigin += 1UL;
- break;
- }
-
- break;
- }
-
- if (syntax_tree.fUserValue.empty())
- {
- Detail::print_error("Variable not declared: " + varName, file);
- }
-
- break;
- }
- case LibCompiler::KeywordKind::kKeywordKindReturn: {
- try
- {
- auto pos = text.find("return") + strlen("return") + 1;
- std::string subText = text.substr(pos);
- subText = subText.erase(subText.find(";"));
- size_t indxReg = 0UL;
-
- if (subText[0] != '\"' &&
- subText[0] != '\'')
- {
- if (!isdigit(subText[0]))
- {
- for (auto pair : kRegisterMap)
- {
- ++indxReg;
-
- if (pair != subText)
- continue;
-
- syntax_tree.fUserValue = "mov rax, " + kRegisterList[indxReg - 1] + "\nret\n";
- kOrigin += 1UL;
-
- break;
- }
- }
- else
- {
- syntax_tree.fUserValue = "mov rax, " + subText + "\nret\n";
- kOrigin += 1UL;
-
- break;
- }
- }
- else
- {
- syntax_tree.fUserValue = "__LIBCOMPILER_LOCAL_RETURN_STRING: db " + subText + ", 0\nmov rcx, __LIBCOMPILER_LOCAL_RETURN_STRING\n";
- syntax_tree.fUserValue += "mov rax, rcx\nret\n";
- kOrigin += 1UL;
-
- break;
- }
-
- if (syntax_tree.fUserValue.empty())
- {
- if (subText.find("(") != std::string::npos)
- {
- subText.erase(subText.find("("));
-
- auto it = std::find_if(kOriginMap.begin(), kOriginMap.end(), [&subText](std::pair<std::string, std::uintptr_t> pair) -> bool {
- return pair.first.find(subText) != std::string::npos;
- });
-
- if (it == kOriginMap.end())
- Detail::print_error("Invalid return value: " + subText, file);
-
- std::stringstream ss;
- ss << it->second;
-
- syntax_tree.fUserValue = "jmp " + ss.str() + "\nret\n";
- kOrigin += 1UL;
- break;
- }
- }
-
- break;
- }
- catch (...)
- {
- syntax_tree.fUserValue = "ret\n";
- kOrigin += 1UL;
- }
- }
- default: {
- break;
- }
- }
-
- syntax_tree.fUserData = keyword.first;
- kState.fSyntaxTree->fLeafList.push_back(syntax_tree);
- }
+Boolean CompilerFrontendCPlusPlus::Compile(std::string text, const std::string file) {
+ if (text.empty()) return true;
+
+ // Clean whitespace and tabs
+ std::string cleanLine = text;
+ cleanLine.erase(std::remove(cleanLine.begin(), cleanLine.end(), '\t'), cleanLine.end());
+ cleanLine.erase(0, cleanLine.find_first_not_of(" \r\n"));
+ cleanLine.erase(cleanLine.find_last_not_of(" \r\n") + 1);
+
+ // Skip empty, doc, or block comment lines
+ if (cleanLine.empty() || cleanLine.starts_with("///") || cleanLine.starts_with("//") ||
+ cleanLine.starts_with("/*"))
+ return true;
+
+ std::size_t index = 0UL;
+ std::vector<std::pair<LibCompiler::CompilerKeyword, std::size_t>> keywords_list;
+
+ Boolean found = false;
+ static Boolean commentBlock = false;
+
+ for (auto& keyword : kKeywords) {
+ if (text.find(keyword.keyword_name) != std::string::npos) {
+ switch (keyword.keyword_kind) {
+ case LibCompiler::kKeywordKindCommentMultiLineStart: {
+ commentBlock = true;
+ return true;
+ }
+ case LibCompiler::kKeywordKindCommentMultiLineEnd: {
+ commentBlock = false;
+ break;
+ }
+ case LibCompiler::kKeywordKindCommentInline: {
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (text[text.find(keyword.keyword_name) - 1] == '+' &&
+ keyword.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableAssign)
+ continue;
+
+ if (text[text.find(keyword.keyword_name) - 1] == '-' &&
+ keyword.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableAssign)
+ continue;
+
+ if (text[text.find(keyword.keyword_name) + 1] == '=' &&
+ keyword.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableAssign)
+ continue;
+
+ keywords_list.emplace_back(std::make_pair(keyword, index));
+ ++index;
+
+ found = true;
+ }
+ }
+
+ if (!found && !commentBlock) {
+ for (size_t i = 0; i < text.size(); i++) {
+ if (isalnum(text[i])) {
+ Detail::print_error("syntax error: " + text, file);
+ return false;
+ }
+ }
+ }
+
+ for (auto& keyword : keywords_list) {
+ auto syntax_tree = LibCompiler::SyntaxLeafList::SyntaxLeaf();
+
+ switch (keyword.first.keyword_kind) {
+ case LibCompiler::KeywordKind::kKeywordKindClass: {
+ ++kOnClassScope;
+ break;
+ }
+ case LibCompiler::KeywordKind::kKeywordKindIf: {
+ auto expr = text.substr(
+ text.find(keyword.first.keyword_name) + keyword.first.keyword_name.size() + 1,
+ text.find(")") - 1);
+
+ if (expr.find(">=") != std::string::npos) {
+ auto left = text.substr(
+ text.find(keyword.first.keyword_name) + keyword.first.keyword_name.size() + 2,
+ expr.find("<=") + strlen("<="));
+ auto right = text.substr(expr.find(">=") + strlen(">="), text.find(")") - 1);
+
+ size_t i = right.size() - 1;
+
+ try {
+ while (!std::isalnum(right[i])) {
+ right.erase(i, 1);
+ --i;
+ }
+
+ right.erase(0, i);
+ } catch (...) {
+ right.erase(0, i);
+ }
+
+ i = left.size() - 1;
+ try {
+ while (!std::isalnum(left[i])) {
+ left.erase(i, 1);
+ --i;
+ }
+
+ left.erase(0, i);
+ } catch (...) {
+ left.erase(0, i);
+ }
+
+ if (!isdigit(left[0]) || !isdigit(right[0])) {
+ auto indexRight = 0UL;
+
+ auto& valueOfVar = !isdigit(left[0]) ? left : right;
+
+ for (auto pairRight : kRegisterMap) {
+ ++indexRight;
+
+ if (pairRight != valueOfVar) {
+ auto& valueOfVarOpposite = isdigit(left[0]) ? left : right;
+
+ syntax_tree.fUserValue +=
+ "mov " + kRegisterList[indexRight + 1] + ", " + valueOfVarOpposite + "\n";
+ syntax_tree.fUserValue += "cmp " + kRegisterList[kRegisterMap.size() - 1] + "," +
+ kRegisterList[indexRight + 1] + "\n";
+
+ goto done_iterarting_on_if;
+ }
+
+ auto& valueOfVarOpposite = isdigit(left[0]) ? left : right;
+
+ syntax_tree.fUserValue +=
+ "mov " + kRegisterList[indexRight + 1] + ", " + valueOfVarOpposite + "\n";
+ syntax_tree.fUserValue += "cmp " + kRegisterList[kRegisterMap.size() - 1] + ", " +
+ kRegisterList[indexRight + 1] + "\n";
+
+ break;
+ }
+ }
+
+ done_iterarting_on_if:
+
+ std::string fnName = text;
+ fnName.erase(fnName.find(keyword.first.keyword_name));
+
+ for (auto& ch : fnName) {
+ if (ch == ' ') ch = '_';
+ }
+
+ syntax_tree.fUserValue +=
+ "jge __OFFSET_ON_TRUE_LC\nsegment .code64 __OFFSET_ON_TRUE_LC:\n";
+ }
+
+ break;
+ }
+ case LibCompiler::KeywordKind::kKeywordKindFunctionStart: {
+ for (auto& ch : text) {
+ if (isdigit(ch)) {
+ goto dont_accept;
+ }
+ }
+
+ goto accept;
+
+ dont_accept:
+ return false;
+
+ accept:
+ std::string fnName = text;
+ size_t indexFnName = 0;
+
+ // this one is for the type.
+ for (auto& ch : text) {
+ ++indexFnName;
+
+ if (ch == '\t') break;
+
+ if (ch == ' ') break;
+ }
+
+ fnName = text.substr(indexFnName);
+
+ if (text.find("return ") != std::string::npos) {
+ text.erase(0, text.find("return "));
+ break;
+ }
+
+ if (text.ends_with(";") && text.find("return") == std::string::npos)
+ goto LC_write_assembly;
+ else if (text.size() <= indexFnName)
+ Detail::print_error("Invalid function name: " + fnName, file);
+
+ indexFnName = 0;
+
+ for (auto& ch : fnName) {
+ if (ch == ' ' || ch == '\t') {
+ if (fnName[indexFnName - 1] != ')')
+ Detail::print_error("Invalid function name: " + fnName, file);
+
+ if ((indexFnName + 1) != fnName.size())
+ Detail::print_error("Extra characters after function name: " + fnName, file);
+ }
+
+ ++indexFnName;
+ }
+
+ syntax_tree.fUserValue = "public_segment .code64 __LIBCOMPILER_" + fnName + "\n";
+ ++kFunctionEmbedLevel;
+
+ kOriginMap.push_back({"__LIBCOMPILER_" + fnName, kOrigin});
+
+ break;
+
+ LC_write_assembly:
+ auto it = std::find_if(kOriginMap.begin(), kOriginMap.end(),
+ [&fnName](std::pair<std::string, std::uintptr_t> pair) -> bool {
+ return fnName == pair.first;
+ });
+
+ std::stringstream ss;
+ ss << std::hex << it->second;
+
+ if (it != kOriginMap.end()) {
+ syntax_tree.fUserValue = "jmp " + ss.str() + "\n";
+ kOrigin += 1UL;
+ }
+ }
+ case LibCompiler::KeywordKind::kKeywordKindFunctionEnd: {
+ if (kOnClassScope) --kOnClassScope;
+
+ if (text.ends_with(";")) break;
+
+ --kFunctionEmbedLevel;
+
+ if (kRegisterMap.size() > kRegisterList.size()) {
+ --kFunctionEmbedLevel;
+ }
+
+ if (kFunctionEmbedLevel < 1) kRegisterMap.clear();
+
+ break;
+ }
+ case LibCompiler::KeywordKind::kKeywordKindEndInstr:
+ case LibCompiler::KeywordKind::kKeywordKindVariableInc:
+ case LibCompiler::KeywordKind::kKeywordKindVariableDec:
+ case LibCompiler::KeywordKind::kKeywordKindVariableAssign: {
+ std::string valueOfVar = "";
+
+ if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableInc) {
+ valueOfVar = text.substr(text.find("+=") + 2);
+ } else if (keyword.first.keyword_kind ==
+ LibCompiler::KeywordKind::kKeywordKindVariableDec) {
+ valueOfVar = text.substr(text.find("-=") + 2);
+ } else if (keyword.first.keyword_kind ==
+ LibCompiler::KeywordKind::kKeywordKindVariableAssign) {
+ valueOfVar = text.substr(text.find("=") + 1);
+ } else if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindEndInstr) {
+ break;
+ }
+
+ while (valueOfVar.find(";") != std::string::npos &&
+ keyword.first.keyword_kind != LibCompiler::KeywordKind::kKeywordKindEndInstr) {
+ valueOfVar.erase(valueOfVar.find(";"));
+ }
+
+ std::string varName = text;
+
+ if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableInc) {
+ varName.erase(varName.find("+="));
+ } else if (keyword.first.keyword_kind ==
+ LibCompiler::KeywordKind::kKeywordKindVariableDec) {
+ varName.erase(varName.find("-="));
+ } else if (keyword.first.keyword_kind ==
+ LibCompiler::KeywordKind::kKeywordKindVariableAssign) {
+ varName.erase(varName.find("="));
+ } else if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindEndInstr) {
+ varName.erase(varName.find(";"));
+ }
+
+ static Boolean typeFound = false;
+
+ for (auto& keyword : kKeywords) {
+ if (keyword.keyword_kind == LibCompiler::kKeywordKindType) {
+ if (text.find(keyword.keyword_name) != std::string::npos) {
+ if (text[text.find(keyword.keyword_name)] == ' ') {
+ typeFound = false;
+ continue;
+ }
+
+ typeFound = true;
+ }
+ }
+ }
+
+ std::string instr = "mov ";
+
+ if (typeFound &&
+ keyword.first.keyword_kind != LibCompiler::KeywordKind::kKeywordKindVariableInc &&
+ keyword.first.keyword_kind != LibCompiler::KeywordKind::kKeywordKindVariableDec) {
+ if (kRegisterMap.size() > kRegisterList.size()) {
+ ++kFunctionEmbedLevel;
+ }
+
+ while (varName.find(" ") != std::string::npos) {
+ varName.erase(varName.find(" "), 1);
+ }
+
+ while (varName.find("\t") != std::string::npos) {
+ varName.erase(varName.find("\t"), 1);
+ }
+
+ for (size_t i = 0; !isalnum(valueOfVar[i]); i++) {
+ if (i > valueOfVar.size()) break;
+
+ valueOfVar.erase(i, 1);
+ }
+
+ constexpr auto cTrueVal = "true";
+ constexpr auto cFalseVal = "false";
+
+ if (valueOfVar == cTrueVal) {
+ valueOfVar = "1";
+ } else if (valueOfVar == cFalseVal) {
+ valueOfVar = "0";
+ }
+
+ std::size_t indexRight = 0UL;
+
+ for (auto pairRight : kRegisterMap) {
+ ++indexRight;
+
+ if (pairRight != valueOfVar) {
+ if (valueOfVar[0] == '\"') {
+ syntax_tree.fUserValue = "segment .data64 __LIBCOMPILER_LOCAL_VAR_" + varName +
+ ": db " + valueOfVar + ", 0\n\n";
+ syntax_tree.fUserValue += instr + kRegisterList[kRegisterMap.size() - 1] + ", " +
+ "__LIBCOMPILER_LOCAL_VAR_" + varName + "\n";
+ kOrigin += 1UL;
+ } else {
+ syntax_tree.fUserValue =
+ instr + kRegisterList[kRegisterMap.size() - 1] + ", " + valueOfVar + "\n";
+ kOrigin += 1UL;
+ }
+
+ goto done;
+ }
+ }
+
+ if (((int) indexRight - 1) < 0) {
+ if (valueOfVar[0] == '\"') {
+ syntax_tree.fUserValue = "segment .data64 __LIBCOMPILER_LOCAL_VAR_" + varName +
+ ": db " + valueOfVar + ", 0\n";
+ syntax_tree.fUserValue += instr + kRegisterList[kRegisterMap.size()] + ", " +
+ "__LIBCOMPILER_LOCAL_VAR_" + varName + "\n";
+ kOrigin += 1UL;
+ } else {
+ syntax_tree.fUserValue =
+ instr + kRegisterList[kRegisterMap.size()] + ", " + valueOfVar + "\n";
+ kOrigin += 1UL;
+ }
+
+ goto done;
+ }
+
+ if (valueOfVar[0] != '\"' && valueOfVar[0] != '\'' && !isdigit(valueOfVar[0])) {
+ for (auto pair : kRegisterMap) {
+ if (pair == valueOfVar) goto done;
+ }
+
+ Detail::print_error("Variable not declared: " + varName, file);
+ return false;
+ }
+
+ done:
+ for (auto& keyword : kKeywords) {
+ if (keyword.keyword_kind == LibCompiler::kKeywordKindType &&
+ varName.find(keyword.keyword_name) != std::string::npos) {
+ varName.erase(varName.find(keyword.keyword_name), keyword.keyword_name.size());
+ break;
+ }
+ }
+
+ kRegisterMap.push_back(varName);
+
+ break;
+ }
+
+ if (kKeywords[keyword.second - 1].keyword_kind == LibCompiler::kKeywordKindType ||
+ kKeywords[keyword.second - 1].keyword_kind == LibCompiler::kKeywordKindTypePtr) {
+ syntax_tree.fUserValue = "\n";
+ continue;
+ }
+
+ if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindEndInstr) {
+ syntax_tree.fUserValue = "\n";
+ continue;
+ }
+
+ if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableInc) {
+ instr = "add ";
+ } else if (keyword.first.keyword_kind ==
+ LibCompiler::KeywordKind::kKeywordKindVariableDec) {
+ instr = "sub ";
+ }
+
+ std::string varErrCpy = varName;
+
+ while (varName.find(" ") != std::string::npos) {
+ varName.erase(varName.find(" "), 1);
+ }
+
+ while (varName.find("\t") != std::string::npos) {
+ varName.erase(varName.find("\t"), 1);
+ }
+
+ std::size_t indxReg = 0UL;
+
+ for (size_t i = 0; !isalnum(valueOfVar[i]); i++) {
+ if (i > valueOfVar.size()) break;
+
+ valueOfVar.erase(i, 1);
+ }
+
+ while (valueOfVar.find(" ") != std::string::npos) {
+ valueOfVar.erase(valueOfVar.find(" "), 1);
+ }
+
+ while (valueOfVar.find("\t") != std::string::npos) {
+ valueOfVar.erase(valueOfVar.find("\t"), 1);
+ }
+
+ constexpr auto cTrueVal = "true";
+ constexpr auto cFalseVal = "false";
+
+ /// interpet boolean values, since we're on C++
+
+ if (valueOfVar == cTrueVal) {
+ valueOfVar = "1";
+ } else if (valueOfVar == cFalseVal) {
+ valueOfVar = "0";
+ }
+
+ for (auto pair : kRegisterMap) {
+ ++indxReg;
+
+ if (pair != varName) continue;
+
+ std::size_t indexRight = 0ul;
+
+ for (auto pairRight : kRegisterMap) {
+ ++indexRight;
+
+ if (pairRight != varName) {
+ syntax_tree.fUserValue =
+ instr + kRegisterList[kRegisterMap.size()] + ", " + valueOfVar + "\n";
+ kOrigin += 1UL;
+ continue;
+ }
+
+ syntax_tree.fUserValue =
+ instr + kRegisterList[indexRight - 1] + ", " + valueOfVar + "\n";
+ kOrigin += 1UL;
+ break;
+ }
+
+ break;
+ }
+
+ if (syntax_tree.fUserValue.empty()) {
+ Detail::print_error("Variable not declared: " + varName, file);
+ }
+
+ break;
+ }
+ case LibCompiler::KeywordKind::kKeywordKindReturn: {
+ try {
+ auto pos = text.find("return") + strlen("return") + 1;
+ std::string subText = text.substr(pos);
+ subText = subText.erase(subText.find(";"));
+ size_t indxReg = 0UL;
+
+ if (subText[0] != '\"' && subText[0] != '\'') {
+ if (!isdigit(subText[0])) {
+ for (auto pair : kRegisterMap) {
+ ++indxReg;
+
+ if (pair != subText) continue;
+
+ syntax_tree.fUserValue = "mov rax, " + kRegisterList[indxReg - 1] + "\nret\n";
+ kOrigin += 1UL;
+
+ break;
+ }
+ } else {
+ syntax_tree.fUserValue = "mov rax, " + subText + "\nret\n";
+ kOrigin += 1UL;
+
+ break;
+ }
+ } else {
+ syntax_tree.fUserValue = "__LIBCOMPILER_LOCAL_RETURN_STRING: db " + subText +
+ ", 0\nmov rcx, __LIBCOMPILER_LOCAL_RETURN_STRING\n";
+ syntax_tree.fUserValue += "mov rax, rcx\nret\n";
+ kOrigin += 1UL;
+
+ break;
+ }
+
+ if (syntax_tree.fUserValue.empty()) {
+ if (subText.find("(") != std::string::npos) {
+ subText.erase(subText.find("("));
+
+ auto it =
+ std::find_if(kOriginMap.begin(), kOriginMap.end(),
+ [&subText](std::pair<std::string, std::uintptr_t> pair) -> bool {
+ return pair.first.find(subText) != std::string::npos;
+ });
+
+ if (it == kOriginMap.end())
+ Detail::print_error("Invalid return value: " + subText, file);
+
+ std::stringstream ss;
+ ss << it->second;
+
+ syntax_tree.fUserValue = "jmp " + ss.str() + "\nret\n";
+ kOrigin += 1UL;
+ break;
+ }
+ }
+
+ break;
+ } catch (...) {
+ syntax_tree.fUserValue = "ret\n";
+ kOrigin += 1UL;
+ }
+ }
+ default: {
+ break;
+ }
+ }
+
+ syntax_tree.fUserData = keyword.first;
+ kState.fSyntaxTree->fLeafList.push_back(syntax_tree);
+ }
lc_compile_ok:
- return true;
+ return true;
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -875,295 +753,275 @@ lc_compile_ok:
/////////////////////////////////////////////////////////////////////////////////////////
-class AssemblyCPlusPlusInterface final ASSEMBLY_INTERFACE
-{
-public:
- explicit AssemblyCPlusPlusInterface() = default;
- ~AssemblyCPlusPlusInterface() override = default;
+class AssemblyCPlusPlusInterface final ASSEMBLY_INTERFACE {
+ public:
+ explicit AssemblyCPlusPlusInterface() = default;
+ ~AssemblyCPlusPlusInterface() override = default;
- LIBCOMPILER_COPY_DEFAULT(AssemblyCPlusPlusInterface);
+ LIBCOMPILER_COPY_DEFAULT(AssemblyCPlusPlusInterface);
- [[maybe_unused]] static Int32 Arch() noexcept
- {
- return LibCompiler::AssemblyFactory::kArchAMD64;
- }
+ [[maybe_unused]] static Int32 Arch() noexcept { return LibCompiler::AssemblyFactory::kArchAMD64; }
- Int32 CompileToFormat(std::string& src, Int32 arch) override
- {
- if (arch != AssemblyCPlusPlusInterface::Arch())
- return 1;
+ Int32 CompileToFormat(std::string& src, Int32 arch) override {
+ if (arch != AssemblyCPlusPlusInterface::Arch()) return 1;
- if (kCompilerFrontend == nullptr)
- return 1;
+ if (kCompilerFrontend == nullptr) return 1;
- /* @brief copy contents wihtout extension */
- std::string src_file = src;
- std::ifstream src_fp = std::ifstream(src_file, std::ios::in);
+ /* @brief copy contents wihtout extension */
+ std::string src_file = src;
+ std::ifstream src_fp = std::ifstream(src_file, std::ios::in);
- const char* cExts[] = kAsmFileExts;
+ const char* cExts[] = kAsmFileExts;
- std::string dest = src_file;
- dest += cExts[2];
+ std::string dest = src_file;
+ dest += cExts[2];
- if (dest.empty())
- {
- dest = "CXX-LibCompiler-";
+ if (dest.empty()) {
+ dest = "CXX-LibCompiler-";
- std::random_device rd;
- auto seed_data = std::array<int, std::mt19937::state_size>{};
+ std::random_device rd;
+ auto seed_data = std::array<int, std::mt19937::state_size>{};
- std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd));
+ std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd));
- std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
- std::mt19937 generator(seq);
+ std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
+ std::mt19937 generator(seq);
- auto gen = uuids::uuid_random_generator(generator);
+ auto gen = uuids::uuid_random_generator(generator);
- auto id = gen();
- dest += uuids::to_string(id);
- }
+ auto id = gen();
+ dest += uuids::to_string(id);
+ }
- kState.fOutputAssembly = std::make_unique<std::ofstream>(dest);
+ kState.fOutputAssembly = std::make_unique<std::ofstream>(dest);
- auto fmt = LibCompiler::current_date();
+ auto fmt = LibCompiler::current_date();
- (*kState.fOutputAssembly) << "; Repository Path: /" << src_file << "\n";
+ (*kState.fOutputAssembly) << "; Repository Path: /" << src_file << "\n";
- std::filesystem::path path = std::filesystem::path("./");
+ std::filesystem::path path = std::filesystem::path("./");
- while (path != Detail::expand_home(std::filesystem::path("~")))
- {
- for (auto const& dir_entry : std::filesystem::recursive_directory_iterator{path})
- {
- if (dir_entry.is_directory() &&
- dir_entry.path().string().find(".git") != std::string::npos)
- goto break_loop;
- }
+ while (path != Detail::expand_home(std::filesystem::path("~"))) {
+ for (auto const& dir_entry : std::filesystem::recursive_directory_iterator{path}) {
+ if (dir_entry.is_directory() && dir_entry.path().string().find(".git") != std::string::npos)
+ goto break_loop;
+ }
- path = path.parent_path();
- break_loop:
- (*kState.fOutputAssembly) << "; Repository Style: Git\n";
- break;
- }
+ path = path.parent_path();
+ break_loop:
+ (*kState.fOutputAssembly) << "; Repository Style: Git\n";
+ break;
+ }
- std::stringstream stream;
- stream << kOrigin;
- std::string result(stream.str());
+ std::stringstream stream;
+ stream << kOrigin;
+ std::string result(stream.str());
- (*kState.fOutputAssembly)
- << "; Assembler Dialect: AMD64 LibCompiler Assembler. (Generated from C++)\n";
- (*kState.fOutputAssembly) << "; Date: " << fmt << "\n";
- (*kState.fOutputAssembly) << "#bits 64\n#org " + result
- << "\n";
+ (*kState.fOutputAssembly)
+ << "; Assembler Dialect: AMD64 LibCompiler Assembler. (Generated from C++)\n";
+ (*kState.fOutputAssembly) << "; Date: " << fmt << "\n";
+ (*kState.fOutputAssembly) << "#bits 64\n#org " + result << "\n";
- kState.fSyntaxTree = new LibCompiler::SyntaxLeafList();
+ kState.fSyntaxTree = new LibCompiler::SyntaxLeafList();
- // ===================================
- // Parse source file.
- // ===================================
+ // ===================================
+ // Parse source file.
+ // ===================================
- std::string line_source;
+ std::string line_source;
- while (std::getline(src_fp, line_source))
- {
- kCompilerFrontend->Compile(line_source, src);
- }
+ while (std::getline(src_fp, line_source)) {
+ kCompilerFrontend->Compile(line_source, src);
+ }
- for (auto& ast_generated : kState.fSyntaxTree->fLeafList)
- {
- (*kState.fOutputAssembly) << ast_generated.fUserValue;
- }
+ for (auto& ast_generated : kState.fSyntaxTree->fLeafList) {
+ (*kState.fOutputAssembly) << ast_generated.fUserValue;
+ }
- kState.fOutputAssembly->flush();
- kState.fOutputAssembly->close();
+ kState.fOutputAssembly->flush();
+ kState.fOutputAssembly->close();
- delete kState.fSyntaxTree;
- kState.fSyntaxTree = nullptr;
+ delete kState.fSyntaxTree;
+ kState.fSyntaxTree = nullptr;
- if (kAcceptableErrors > 0)
- return 1;
+ if (kAcceptableErrors > 0) return 1;
- return kExitOK;
- }
+ return kExitOK;
+ }
};
/////////////////////////////////////////////////////////////////////////////////////////
-static void cxx_print_help()
-{
- kSplashCxx();
- kPrintF("%s", "No help available, see:\n");
- kPrintF("%s", "nekernel.org/docs/cxxdrv\n");
+static void cxx_print_help() {
+ kSplashCxx();
+ kPrintF("%s", "No help available, see:\n");
+ kPrintF("%s", "nekernel.org/docs/cxxdrv\n");
}
/////////////////////////////////////////////////////////////////////////////////////////
-#define kExtListCxx \
- { \
- ".cpp", ".cxx", ".cc", ".c++", ".cp" \
- }
-
-LIBCOMPILER_MODULE(CompilerCPlusPlusAMD64)
-{
- Boolean skip = false;
-
- kKeywords.push_back({.keyword_name = "if", .keyword_kind = LibCompiler::kKeywordKindIf});
- kKeywords.push_back({.keyword_name = "else", .keyword_kind = LibCompiler::kKeywordKindElse});
- kKeywords.push_back({.keyword_name = "else if", .keyword_kind = LibCompiler::kKeywordKindElseIf});
-
- kKeywords.push_back({.keyword_name = "class", .keyword_kind = LibCompiler::kKeywordKindClass});
- kKeywords.push_back({.keyword_name = "struct", .keyword_kind = LibCompiler::kKeywordKindClass});
- kKeywords.push_back({.keyword_name = "namespace", .keyword_kind = LibCompiler::kKeywordKindNamespace});
- kKeywords.push_back({.keyword_name = "typedef", .keyword_kind = LibCompiler::kKeywordKindTypedef});
- kKeywords.push_back({.keyword_name = "using", .keyword_kind = LibCompiler::kKeywordKindTypedef});
- kKeywords.push_back({.keyword_name = "{", .keyword_kind = LibCompiler::kKeywordKindBodyStart});
- kKeywords.push_back({.keyword_name = "}", .keyword_kind = LibCompiler::kKeywordKindBodyEnd});
- kKeywords.push_back({.keyword_name = "auto", .keyword_kind = LibCompiler::kKeywordKindVariable});
- kKeywords.push_back({.keyword_name = "int", .keyword_kind = LibCompiler::kKeywordKindType});
- kKeywords.push_back({.keyword_name = "Boolean", .keyword_kind = LibCompiler::kKeywordKindType});
- kKeywords.push_back({.keyword_name = "unsigned", .keyword_kind = LibCompiler::kKeywordKindType});
- kKeywords.push_back({.keyword_name = "short", .keyword_kind = LibCompiler::kKeywordKindType});
- kKeywords.push_back({.keyword_name = "char", .keyword_kind = LibCompiler::kKeywordKindType});
- kKeywords.push_back({.keyword_name = "long", .keyword_kind = LibCompiler::kKeywordKindType});
- kKeywords.push_back({.keyword_name = "float", .keyword_kind = LibCompiler::kKeywordKindType});
- kKeywords.push_back({.keyword_name = "double", .keyword_kind = LibCompiler::kKeywordKindType});
- kKeywords.push_back({.keyword_name = "void", .keyword_kind = LibCompiler::kKeywordKindType});
-
- kKeywords.push_back({.keyword_name = "auto*", .keyword_kind = LibCompiler::kKeywordKindVariablePtr});
- kKeywords.push_back({.keyword_name = "int*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
- kKeywords.push_back({.keyword_name = "Boolean*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
- kKeywords.push_back({.keyword_name = "unsigned*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
- kKeywords.push_back({.keyword_name = "short*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
- kKeywords.push_back({.keyword_name = "char*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
- kKeywords.push_back({.keyword_name = "long*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
- kKeywords.push_back({.keyword_name = "float*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
- kKeywords.push_back({.keyword_name = "double*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
- kKeywords.push_back({.keyword_name = "void*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
-
- kKeywords.push_back({.keyword_name = "(", .keyword_kind = LibCompiler::kKeywordKindFunctionStart});
- kKeywords.push_back({.keyword_name = ")", .keyword_kind = LibCompiler::kKeywordKindFunctionEnd});
- kKeywords.push_back({.keyword_name = "=", .keyword_kind = LibCompiler::kKeywordKindVariableAssign});
- kKeywords.push_back({.keyword_name = "+=", .keyword_kind = LibCompiler::kKeywordKindVariableInc});
- kKeywords.push_back({.keyword_name = "-=", .keyword_kind = LibCompiler::kKeywordKindVariableDec});
- kKeywords.push_back({.keyword_name = "const", .keyword_kind = LibCompiler::kKeywordKindConstant});
- kKeywords.push_back({.keyword_name = "*", .keyword_kind = LibCompiler::kKeywordKindPtr});
- kKeywords.push_back({.keyword_name = "->", .keyword_kind = LibCompiler::kKeywordKindPtrAccess});
- kKeywords.push_back({.keyword_name = ".", .keyword_kind = LibCompiler::kKeywordKindAccess});
- kKeywords.push_back({.keyword_name = ",", .keyword_kind = LibCompiler::kKeywordKindArgSeparator});
- kKeywords.push_back({.keyword_name = ";", .keyword_kind = LibCompiler::kKeywordKindEndInstr});
- kKeywords.push_back({.keyword_name = ":", .keyword_kind = LibCompiler::kKeywordKindSpecifier});
- kKeywords.push_back({.keyword_name = "public:", .keyword_kind = LibCompiler::kKeywordKindSpecifier});
- kKeywords.push_back({.keyword_name = "private:", .keyword_kind = LibCompiler::kKeywordKindSpecifier});
- kKeywords.push_back({.keyword_name = "protected:", .keyword_kind = LibCompiler::kKeywordKindSpecifier});
- kKeywords.push_back({.keyword_name = "final", .keyword_kind = LibCompiler::kKeywordKindSpecifier});
- kKeywords.push_back({.keyword_name = "return", .keyword_kind = LibCompiler::kKeywordKindReturn});
- kKeywords.push_back({.keyword_name = "--*", .keyword_kind = LibCompiler::kKeywordKindCommentMultiLineStart});
- kKeywords.push_back({.keyword_name = "*/", .keyword_kind = LibCompiler::kKeywordKindCommentMultiLineStart});
- kKeywords.push_back({.keyword_name = "--/", .keyword_kind = LibCompiler::kKeywordKindCommentInline});
- kKeywords.push_back({.keyword_name = "==", .keyword_kind = LibCompiler::kKeywordKindEq});
- kKeywords.push_back({.keyword_name = "!=", .keyword_kind = LibCompiler::kKeywordKindNotEq});
- kKeywords.push_back({.keyword_name = ">=", .keyword_kind = LibCompiler::kKeywordKindGreaterEq});
- kKeywords.push_back({.keyword_name = "<=", .keyword_kind = LibCompiler::kKeywordKindLessEq});
-
- kFactory.Mount(new AssemblyCPlusPlusInterface());
- kCompilerFrontend = new CompilerFrontendCPlusPlus();
-
- for (auto index = 1UL; index < argc; ++index)
- {
- if (argv[index][0] == '-')
- {
- if (skip)
- {
- skip = false;
- continue;
- }
-
- if (strcmp(argv[index], "-version") == 0)
- {
- kSplashCxx();
- return kExitOK;
- }
-
- if (strcmp(argv[index], "-cxx-verbose") == 0)
- {
- kState.fVerbose = true;
-
- continue;
- }
-
- if (strcmp(argv[index], "-h") == 0)
- {
- cxx_print_help();
-
- return kExitOK;
- }
-
- if (strcmp(argv[index], "-cxx-dialect") == 0)
- {
- if (kCompilerFrontend)
- std::cout << kCompilerFrontend->Language() << "\n";
-
- return kExitOK;
- }
-
- if (strcmp(argv[index], "-max-err") == 0)
- {
- try
- {
- kErrorLimit = std::strtol(argv[index + 1], nullptr, 10);
- }
- // catch anything here
- catch (...)
- {
- kErrorLimit = 0;
- }
-
- skip = true;
-
- continue;
- }
-
- std::string err = "Unknown option: ";
- err += argv[index];
-
- Detail::print_error(err, "cxxdrv");
-
- continue;
- }
-
- kFileList.emplace_back(argv[index]);
-
- std::string argv_i = argv[index];
-
- std::vector exts = kExtListCxx;
- Boolean found = false;
-
- for (std::string ext : exts)
- {
- if (argv_i.find(ext) != std::string::npos)
- {
- found = true;
- break;
- }
- }
-
- if (!found)
- {
- if (kState.fVerbose)
- {
- Detail::print_error(argv_i + " is not a valid C++ source.\n", "cxxdrv");
- }
-
- return 1;
- }
-
- std::cout << "CPlusPlusCompilerAMD64: Building: " << argv[index] << std::endl;
-
- if (kFactory.Compile(argv_i, kMachine) != kExitOK)
- return 1;
- }
-
- return kExitOK;
+#define kExtListCxx \
+ { ".cpp", ".cxx", ".cc", ".c++", ".cp" }
+
+LIBCOMPILER_MODULE(CompilerCPlusPlusAMD64) {
+ Boolean skip = false;
+
+ kKeywords.push_back({.keyword_name = "if", .keyword_kind = LibCompiler::kKeywordKindIf});
+ kKeywords.push_back({.keyword_name = "else", .keyword_kind = LibCompiler::kKeywordKindElse});
+ kKeywords.push_back({.keyword_name = "else if", .keyword_kind = LibCompiler::kKeywordKindElseIf});
+
+ kKeywords.push_back({.keyword_name = "class", .keyword_kind = LibCompiler::kKeywordKindClass});
+ kKeywords.push_back({.keyword_name = "struct", .keyword_kind = LibCompiler::kKeywordKindClass});
+ kKeywords.push_back(
+ {.keyword_name = "namespace", .keyword_kind = LibCompiler::kKeywordKindNamespace});
+ kKeywords.push_back(
+ {.keyword_name = "typedef", .keyword_kind = LibCompiler::kKeywordKindTypedef});
+ kKeywords.push_back({.keyword_name = "using", .keyword_kind = LibCompiler::kKeywordKindTypedef});
+ kKeywords.push_back({.keyword_name = "{", .keyword_kind = LibCompiler::kKeywordKindBodyStart});
+ kKeywords.push_back({.keyword_name = "}", .keyword_kind = LibCompiler::kKeywordKindBodyEnd});
+ kKeywords.push_back({.keyword_name = "auto", .keyword_kind = LibCompiler::kKeywordKindVariable});
+ kKeywords.push_back({.keyword_name = "int", .keyword_kind = LibCompiler::kKeywordKindType});
+ kKeywords.push_back({.keyword_name = "Boolean", .keyword_kind = LibCompiler::kKeywordKindType});
+ kKeywords.push_back({.keyword_name = "unsigned", .keyword_kind = LibCompiler::kKeywordKindType});
+ kKeywords.push_back({.keyword_name = "short", .keyword_kind = LibCompiler::kKeywordKindType});
+ kKeywords.push_back({.keyword_name = "char", .keyword_kind = LibCompiler::kKeywordKindType});
+ kKeywords.push_back({.keyword_name = "long", .keyword_kind = LibCompiler::kKeywordKindType});
+ kKeywords.push_back({.keyword_name = "float", .keyword_kind = LibCompiler::kKeywordKindType});
+ kKeywords.push_back({.keyword_name = "double", .keyword_kind = LibCompiler::kKeywordKindType});
+ kKeywords.push_back({.keyword_name = "void", .keyword_kind = LibCompiler::kKeywordKindType});
+
+ kKeywords.push_back(
+ {.keyword_name = "auto*", .keyword_kind = LibCompiler::kKeywordKindVariablePtr});
+ kKeywords.push_back({.keyword_name = "int*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
+ kKeywords.push_back(
+ {.keyword_name = "Boolean*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
+ kKeywords.push_back(
+ {.keyword_name = "unsigned*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
+ kKeywords.push_back({.keyword_name = "short*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
+ kKeywords.push_back({.keyword_name = "char*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
+ kKeywords.push_back({.keyword_name = "long*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
+ kKeywords.push_back({.keyword_name = "float*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
+ kKeywords.push_back(
+ {.keyword_name = "double*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
+ kKeywords.push_back({.keyword_name = "void*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
+
+ kKeywords.push_back(
+ {.keyword_name = "(", .keyword_kind = LibCompiler::kKeywordKindFunctionStart});
+ kKeywords.push_back({.keyword_name = ")", .keyword_kind = LibCompiler::kKeywordKindFunctionEnd});
+ kKeywords.push_back(
+ {.keyword_name = "=", .keyword_kind = LibCompiler::kKeywordKindVariableAssign});
+ kKeywords.push_back({.keyword_name = "+=", .keyword_kind = LibCompiler::kKeywordKindVariableInc});
+ kKeywords.push_back({.keyword_name = "-=", .keyword_kind = LibCompiler::kKeywordKindVariableDec});
+ kKeywords.push_back({.keyword_name = "const", .keyword_kind = LibCompiler::kKeywordKindConstant});
+ kKeywords.push_back({.keyword_name = "*", .keyword_kind = LibCompiler::kKeywordKindPtr});
+ kKeywords.push_back({.keyword_name = "->", .keyword_kind = LibCompiler::kKeywordKindPtrAccess});
+ kKeywords.push_back({.keyword_name = ".", .keyword_kind = LibCompiler::kKeywordKindAccess});
+ kKeywords.push_back({.keyword_name = ",", .keyword_kind = LibCompiler::kKeywordKindArgSeparator});
+ kKeywords.push_back({.keyword_name = ";", .keyword_kind = LibCompiler::kKeywordKindEndInstr});
+ kKeywords.push_back({.keyword_name = ":", .keyword_kind = LibCompiler::kKeywordKindSpecifier});
+ kKeywords.push_back(
+ {.keyword_name = "public:", .keyword_kind = LibCompiler::kKeywordKindSpecifier});
+ kKeywords.push_back(
+ {.keyword_name = "private:", .keyword_kind = LibCompiler::kKeywordKindSpecifier});
+ kKeywords.push_back(
+ {.keyword_name = "protected:", .keyword_kind = LibCompiler::kKeywordKindSpecifier});
+ kKeywords.push_back(
+ {.keyword_name = "final", .keyword_kind = LibCompiler::kKeywordKindSpecifier});
+ kKeywords.push_back({.keyword_name = "return", .keyword_kind = LibCompiler::kKeywordKindReturn});
+ kKeywords.push_back(
+ {.keyword_name = "--*", .keyword_kind = LibCompiler::kKeywordKindCommentMultiLineStart});
+ kKeywords.push_back(
+ {.keyword_name = "*/", .keyword_kind = LibCompiler::kKeywordKindCommentMultiLineStart});
+ kKeywords.push_back(
+ {.keyword_name = "--/", .keyword_kind = LibCompiler::kKeywordKindCommentInline});
+ kKeywords.push_back({.keyword_name = "==", .keyword_kind = LibCompiler::kKeywordKindEq});
+ kKeywords.push_back({.keyword_name = "!=", .keyword_kind = LibCompiler::kKeywordKindNotEq});
+ kKeywords.push_back({.keyword_name = ">=", .keyword_kind = LibCompiler::kKeywordKindGreaterEq});
+ kKeywords.push_back({.keyword_name = "<=", .keyword_kind = LibCompiler::kKeywordKindLessEq});
+
+ kFactory.Mount(new AssemblyCPlusPlusInterface());
+ kCompilerFrontend = new CompilerFrontendCPlusPlus();
+
+ for (auto index = 1UL; index < argc; ++index) {
+ if (argv[index][0] == '-') {
+ if (skip) {
+ skip = false;
+ continue;
+ }
+
+ if (strcmp(argv[index], "-version") == 0) {
+ kSplashCxx();
+ return kExitOK;
+ }
+
+ if (strcmp(argv[index], "-cxx-verbose") == 0) {
+ kState.fVerbose = true;
+
+ continue;
+ }
+
+ if (strcmp(argv[index], "-h") == 0) {
+ cxx_print_help();
+
+ return kExitOK;
+ }
+
+ if (strcmp(argv[index], "-cxx-dialect") == 0) {
+ if (kCompilerFrontend) std::cout << kCompilerFrontend->Language() << "\n";
+
+ return kExitOK;
+ }
+
+ if (strcmp(argv[index], "-max-err") == 0) {
+ try {
+ kErrorLimit = std::strtol(argv[index + 1], nullptr, 10);
+ }
+ // catch anything here
+ catch (...) {
+ kErrorLimit = 0;
+ }
+
+ skip = true;
+
+ continue;
+ }
+
+ std::string err = "Unknown option: ";
+ err += argv[index];
+
+ Detail::print_error(err, "cxxdrv");
+
+ continue;
+ }
+
+ kFileList.emplace_back(argv[index]);
+
+ std::string argv_i = argv[index];
+
+ std::vector exts = kExtListCxx;
+ Boolean found = false;
+
+ for (std::string ext : exts) {
+ if (argv_i.find(ext) != std::string::npos) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ if (kState.fVerbose) {
+ Detail::print_error(argv_i + " is not a valid C++ source.\n", "cxxdrv");
+ }
+
+ return 1;
+ }
+
+ std::cout << "CPlusPlusCompilerAMD64: Building: " << argv[index] << std::endl;
+
+ if (kFactory.Compile(argv_i, kMachine) != kExitOK) return 1;
+ }
+
+ return kExitOK;
}
// Last rev 8-1-24
diff --git a/dev/LibCompiler/src/CPlusPlusCompilerPreProcessor.cc b/dev/LibCompiler/src/CPlusPlusCompilerPreProcessor.cc
index 336ca5a..aa3407a 100644
--- a/dev/LibCompiler/src/CPlusPlusCompilerPreProcessor.cc
+++ b/dev/LibCompiler/src/CPlusPlusCompilerPreProcessor.cc
@@ -9,8 +9,8 @@
/// BUGS: 0
-#include <LibCompiler/Parser.h>
#include <LibCompiler/ErrorID.h>
+#include <LibCompiler/Parser.h>
#include <algorithm>
#include <filesystem>
#include <fstream>
@@ -32,64 +32,56 @@ typedef Int32 (*bpp_parser_fn_t)(std::string& line, std::ifstream& hdr_file, std
/////////////////////////////////////////////////////////////////////////////////////////
-namespace Detail
-{
- enum
- {
- kEqual,
- kGreaterEqThan,
- kLesserEqThan,
- kGreaterThan,
- kLesserThan,
- kNotEqual,
- };
-
- struct bpp_macro_condition final
- {
- int32_t fType;
- std::string fTypeName;
- };
-
- struct bpp_macro final
- {
- std::vector<std::string> fArgs;
- std::string fName;
- std::string fValue;
-
- void Print()
- {
- std::cout << "name: " << fName << "\n";
- std::cout << "value: " << fValue << "\n";
-
- for (auto& arg : fArgs)
- {
- std::cout << "arg: " << arg << "\n";
- }
- }
- };
-
- class bpp_pragma final
- {
- public:
- explicit bpp_pragma() = default;
- ~bpp_pragma() = default;
-
- LIBCOMPILER_COPY_DEFAULT(bpp_pragma);
-
- std::string fMacroName;
- bpp_parser_fn_t fParse;
- };
-} // namespace Detail
-
-static std::vector<std::string> kFiles;
+namespace Detail {
+enum {
+ kEqual,
+ kGreaterEqThan,
+ kLesserEqThan,
+ kGreaterThan,
+ kLesserThan,
+ kNotEqual,
+};
+
+struct bpp_macro_condition final {
+ int32_t fType;
+ std::string fTypeName;
+};
+
+struct bpp_macro final {
+ std::vector<std::string> fArgs;
+ std::string fName;
+ std::string fValue;
+
+ void Print() {
+ std::cout << "name: " << fName << "\n";
+ std::cout << "value: " << fValue << "\n";
+
+ for (auto& arg : fArgs) {
+ std::cout << "arg: " << arg << "\n";
+ }
+ }
+};
+
+class bpp_pragma final {
+ public:
+ explicit bpp_pragma() = default;
+ ~bpp_pragma() = default;
+
+ LIBCOMPILER_COPY_DEFAULT(bpp_pragma);
+
+ std::string fMacroName;
+ bpp_parser_fn_t fParse;
+};
+} // namespace Detail
+
+static std::vector<std::string> kFiles;
static std::vector<Detail::bpp_macro> kMacros;
-static std::vector<std::string> kIncludes;
+static std::vector<std::string> kIncludes;
static std::string kWorkingDir;
-static std::vector<std::string> kKeywords = {
- "include", "if", "pragma", "def", "elif",
- "ifdef", "ifndef", "else", "warning", "error"};
+static std::vector<std::string> kKeywords = {"include", "if", "pragma", "def", "elif",
+ "ifdef", "ifndef", "else", "warning", "error"};
#define kKeywordCxxCnt kKeywords.size()
@@ -100,182 +92,145 @@ static std::vector<std::string> kKeywords = {
/////////////////////////////////////////////////////////////////////////////////////////
-int32_t bpp_parse_if_condition(Detail::bpp_macro_condition& cond,
- Detail::bpp_macro& macro,
- bool& inactive_code,
- bool& defined,
- std::string& macro_str)
-{
- if (cond.fType == Detail::kEqual)
- {
- auto substr_macro =
- macro_str.substr(macro_str.find(macro.fName) + macro.fName.size());
-
- if (substr_macro.find(macro.fValue) != std::string::npos)
- {
- if (macro.fValue == "0")
- {
- defined = false;
- inactive_code = true;
-
- return 1;
- }
-
- defined = true;
- inactive_code = false;
-
- return 1;
- }
- }
- else if (cond.fType == Detail::kNotEqual)
- {
- auto substr_macro =
- macro_str.substr(macro_str.find(macro.fName) + macro.fName.size());
-
- if (substr_macro.find(macro.fName) != std::string::npos)
- {
- if (substr_macro.find(macro.fValue) != std::string::npos)
- {
- defined = false;
- inactive_code = true;
-
- return 1;
- }
-
- defined = true;
- inactive_code = false;
-
- return 1;
- }
-
- return 0;
- }
-
- auto substr_macro =
- macro_str.substr(macro_str.find(macro.fName) + macro.fName.size());
-
- std::string number;
-
- for (auto& macro_num : kMacros)
- {
- if (substr_macro.find(macro_num.fName) != std::string::npos)
- {
- for (size_t i = 0; i < macro_num.fName.size(); ++i)
- {
- if (isdigit(macro_num.fValue[i]))
- {
- number += macro_num.fValue[i];
- }
- else
- {
- number.clear();
- break;
- }
- }
-
- break;
- }
- }
-
- size_t y = 2;
-
- /* last try */
- for (; y < macro_str.size(); y++)
- {
- if (isdigit(macro_str[y]))
- {
- for (size_t x = y; x < macro_str.size(); x++)
- {
- if (macro_str[x] == ' ')
- break;
-
- number += macro_str[x];
- }
-
- break;
- }
- }
-
- size_t rhs = atol(macro.fValue.c_str());
- size_t lhs = atol(number.c_str());
-
- if (lhs == 0)
- {
- number.clear();
- ++y;
-
- for (; y < macro_str.size(); y++)
- {
- if (isdigit(macro_str[y]))
- {
- for (size_t x = y; x < macro_str.size(); x++)
- {
- if (macro_str[x] == ' ')
- break;
-
- number += macro_str[x];
- }
-
- break;
- }
- }
-
- lhs = atol(number.c_str());
- }
-
- if (cond.fType == Detail::kGreaterThan)
- {
- if (lhs < rhs)
- {
- defined = true;
- inactive_code = false;
-
- return 1;
- }
-
- return 0;
- }
-
- if (cond.fType == Detail::kGreaterEqThan)
- {
- if (lhs <= rhs)
- {
- defined = true;
- inactive_code = false;
-
- return 1;
- }
-
- return 0;
- }
-
- if (cond.fType == Detail::kLesserEqThan)
- {
- if (lhs >= rhs)
- {
- defined = true;
- inactive_code = false;
-
- return 1;
- }
-
- return 0;
- }
-
- if (cond.fType == Detail::kLesserThan)
- {
- if (lhs > rhs)
- {
- defined = true;
- inactive_code = false;
-
- return 1;
- }
-
- return 0;
- }
-
- return 0;
+int32_t bpp_parse_if_condition(Detail::bpp_macro_condition& cond, Detail::bpp_macro& macro,
+ bool& inactive_code, bool& defined, std::string& macro_str) {
+ if (cond.fType == Detail::kEqual) {
+ auto substr_macro = macro_str.substr(macro_str.find(macro.fName) + macro.fName.size());
+
+ if (substr_macro.find(macro.fValue) != std::string::npos) {
+ if (macro.fValue == "0") {
+ defined = false;
+ inactive_code = true;
+
+ return 1;
+ }
+
+ defined = true;
+ inactive_code = false;
+
+ return 1;
+ }
+ } else if (cond.fType == Detail::kNotEqual) {
+ auto substr_macro = macro_str.substr(macro_str.find(macro.fName) + macro.fName.size());
+
+ if (substr_macro.find(macro.fName) != std::string::npos) {
+ if (substr_macro.find(macro.fValue) != std::string::npos) {
+ defined = false;
+ inactive_code = true;
+
+ return 1;
+ }
+
+ defined = true;
+ inactive_code = false;
+
+ return 1;
+ }
+
+ return 0;
+ }
+
+ auto substr_macro = macro_str.substr(macro_str.find(macro.fName) + macro.fName.size());
+
+ std::string number;
+
+ for (auto& macro_num : kMacros) {
+ if (substr_macro.find(macro_num.fName) != std::string::npos) {
+ for (size_t i = 0; i < macro_num.fName.size(); ++i) {
+ if (isdigit(macro_num.fValue[i])) {
+ number += macro_num.fValue[i];
+ } else {
+ number.clear();
+ break;
+ }
+ }
+
+ break;
+ }
+ }
+
+ size_t y = 2;
+
+ /* last try */
+ for (; y < macro_str.size(); y++) {
+ if (isdigit(macro_str[y])) {
+ for (size_t x = y; x < macro_str.size(); x++) {
+ if (macro_str[x] == ' ') break;
+
+ number += macro_str[x];
+ }
+
+ break;
+ }
+ }
+
+ size_t rhs = atol(macro.fValue.c_str());
+ size_t lhs = atol(number.c_str());
+
+ if (lhs == 0) {
+ number.clear();
+ ++y;
+
+ for (; y < macro_str.size(); y++) {
+ if (isdigit(macro_str[y])) {
+ for (size_t x = y; x < macro_str.size(); x++) {
+ if (macro_str[x] == ' ') break;
+
+ number += macro_str[x];
+ }
+
+ break;
+ }
+ }
+
+ lhs = atol(number.c_str());
+ }
+
+ if (cond.fType == Detail::kGreaterThan) {
+ if (lhs < rhs) {
+ defined = true;
+ inactive_code = false;
+
+ return 1;
+ }
+
+ return 0;
+ }
+
+ if (cond.fType == Detail::kGreaterEqThan) {
+ if (lhs <= rhs) {
+ defined = true;
+ inactive_code = false;
+
+ return 1;
+ }
+
+ return 0;
+ }
+
+ if (cond.fType == Detail::kLesserEqThan) {
+ if (lhs >= rhs) {
+ defined = true;
+ inactive_code = false;
+
+ return 1;
+ }
+
+ return 0;
+ }
+
+ if (cond.fType == Detail::kLesserThan) {
+ if (lhs > rhs) {
+ defined = true;
+ inactive_code = false;
+
+ return 1;
+ }
+
+ return 0;
+ }
+
+ return 0;
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -293,613 +248,484 @@ std::vector<std::string> kAllIncludes;
/////////////////////////////////////////////////////////////////////////////////////////
-void bpp_parse_file(std::ifstream& hdr_file, std::ofstream& pp_out)
-{
- std::string hdr_line;
- std::string line_after_include;
-
- bool inactive_code = false;
- bool defined = false;
-
- try
- {
- while (std::getline(hdr_file, hdr_line))
- {
- if (inactive_code)
- {
- if (hdr_line.find("#endif") == std::string::npos)
- {
- continue;
- }
- else if (hdr_line[0] == kMacroPrefix &&
- hdr_line.find("#endif") != std::string::npos)
- {
-
- inactive_code = false;
- }
-
- if (hdr_line.find("*/") != std::string::npos)
- {
- continue;
- }
- }
-
- if (hdr_line.find("--/") != std::string::npos)
- {
- hdr_line.erase(hdr_line.find("--/"));
- }
-
- if (hdr_line.find("--*") != std::string::npos)
- {
- inactive_code = true;
- // get rid of comment.
- hdr_line.erase(hdr_line.find("--*"));
- }
-
- /// BPP 'brief' documentation.
- if (hdr_line.find("@brief") != std::string::npos)
- {
- hdr_line.erase(hdr_line.find("@brief"));
-
- // TODO: Write an <file_name>.html or append to it.
- }
-
- if (hdr_line[0] == kMacroPrefix &&
- hdr_line.find("endif") != std::string::npos)
- {
- if (!defined && inactive_code)
- {
- inactive_code = false;
- defined = false;
-
- continue;
- }
-
- continue;
- }
-
- if (!defined && inactive_code)
- {
- continue;
- }
-
- if (defined && inactive_code)
- {
- continue;
- }
-
- for (auto macro : kMacros)
- {
- if (LibCompiler::find_word(hdr_line, macro.fName))
- {
- if (hdr_line.substr(hdr_line.find(macro.fName)).find(macro.fName + '(') != LibCompiler::String::npos)
- {
- if (!macro.fArgs.empty())
- {
- LibCompiler::String symbol_val = macro.fValue;
- std::vector<LibCompiler::String> args;
-
- size_t x_arg_indx = 0;
-
- LibCompiler::String line_after_define = hdr_line;
- LibCompiler::String str_arg;
-
- if (line_after_define.find("(") != LibCompiler::String::npos)
- {
- line_after_define.erase(0, line_after_define.find("(") + 1);
-
- for (auto& subc : line_after_define)
- {
- if (subc == ' ' || subc == '\t')
- continue;
-
- if (subc == ',' || subc == ')')
- {
- if (str_arg.empty())
- continue;
-
- args.push_back(str_arg);
-
- str_arg.clear();
-
- continue;
- }
-
- str_arg.push_back(subc);
- }
- }
-
- for (auto arg : macro.fArgs)
- {
- if (symbol_val.find(macro.fArgs[x_arg_indx]) != LibCompiler::String::npos)
- {
- symbol_val.replace(symbol_val.find(macro.fArgs[x_arg_indx]), macro.fArgs[x_arg_indx].size(),
- args[x_arg_indx]);
- ++x_arg_indx;
- }
- else
- {
- throw std::runtime_error("bpp: Internal error.");
- }
- }
-
- auto len = macro.fName.size();
- len += symbol_val.size();
- len += 2; // ( and )
-
- hdr_line.erase(hdr_line.find(")"), 1);
-
- hdr_line.replace(hdr_line.find(hdr_line.substr(hdr_line.find(macro.fName + '('))), len,
- symbol_val);
- }
- else
- {
- auto value = macro.fValue;
-
- hdr_line.replace(hdr_line.find(macro.fName), macro.fName.size(),
- value);
- }
- }
- }
- }
-
- if (hdr_line[0] == kMacroPrefix &&
- hdr_line.find("define ") != std::string::npos)
- {
- auto line_after_define =
- hdr_line.substr(hdr_line.find("define ") + strlen("define "));
-
- std::string macro_value;
- std::string macro_key;
-
- std::size_t pos = 0UL;
-
- std::vector<std::string> args;
- bool on_args = false;
-
- for (auto& ch : line_after_define)
- {
- ++pos;
-
- if (ch == '(')
- {
- on_args = true;
- continue;
- }
-
- if (ch == ')')
- {
- on_args = false;
- continue;
- }
-
- if (ch == '\\')
- continue;
-
- if (on_args)
- continue;
-
- if (ch == ' ')
- {
- for (size_t i = pos; i < line_after_define.size(); i++)
- {
- macro_value += line_after_define[i];
- }
-
- break;
- }
-
- macro_key += ch;
- }
-
- std::string str;
-
- if (line_after_define.find("(") != LibCompiler::String::npos)
- {
- line_after_define.erase(0, line_after_define.find("(") + 1);
-
- for (auto& subc : line_after_define)
- {
- if (subc == ',' || subc == ')')
- {
- if (str.empty())
- continue;
-
- args.push_back(str);
-
- str.clear();
-
- continue;
- }
-
- str.push_back(subc);
- }
- }
-
- Detail::bpp_macro macro;
-
- macro.fArgs = args;
- macro.fName = macro_key;
- macro.fValue = macro_value;
-
- kMacros.emplace_back(macro);
-
- continue;
- }
-
- if (hdr_line[0] != kMacroPrefix)
- {
- if (inactive_code)
- {
- continue;
- }
-
- pp_out << hdr_line << std::endl;
-
- continue;
- }
-
- if (hdr_line[0] == kMacroPrefix &&
- hdr_line.find("ifndef") != std::string::npos)
- {
- auto line_after_ifndef =
- hdr_line.substr(hdr_line.find("ifndef") + strlen("ifndef") + 1);
- std::string macro;
-
- for (auto& ch : line_after_ifndef)
- {
- if (ch == ' ')
- {
- break;
- }
-
- macro += ch;
- }
-
- if (macro == "0")
- {
- defined = true;
- inactive_code = false;
- continue;
- }
-
- if (macro == "1")
- {
- defined = false;
- inactive_code = true;
-
- continue;
- }
-
- bool found = false;
-
- defined = true;
- inactive_code = false;
-
- for (auto& macro_ref : kMacros)
- {
- if (hdr_line.find(macro_ref.fName) != std::string::npos)
- {
- found = true;
- break;
- }
- }
-
- if (found)
- {
- defined = false;
- inactive_code = true;
-
- continue;
- }
- }
- else if (hdr_line[0] == kMacroPrefix &&
- hdr_line.find("else") != std::string::npos)
- {
- if (!defined && inactive_code)
- {
- inactive_code = false;
- defined = true;
-
- continue;
- }
- else
- {
- defined = false;
- inactive_code = true;
-
- continue;
- }
- }
- else if (hdr_line[0] == kMacroPrefix &&
- hdr_line.find("ifdef") != std::string::npos)
- {
- auto line_after_ifdef =
- hdr_line.substr(hdr_line.find("ifdef") + strlen("ifdef") + 1);
- std::string macro;
-
- for (auto& ch : line_after_ifdef)
- {
- if (ch == ' ')
- {
- break;
- }
-
- macro += ch;
- }
-
- if (macro == "0")
- {
- defined = false;
- inactive_code = true;
-
- continue;
- }
-
- if (macro == "1")
- {
- defined = true;
- inactive_code = false;
-
- continue;
- }
-
- defined = false;
- inactive_code = true;
-
- for (auto& macro_ref : kMacros)
- {
- if (hdr_line.find(macro_ref.fName) != std::string::npos)
- {
- defined = true;
- inactive_code = false;
-
- break;
- }
- }
- }
- else if (hdr_line[0] == kMacroPrefix &&
- hdr_line.find("if") != std::string::npos)
- {
- inactive_code = true;
-
- std::vector<Detail::bpp_macro_condition> bpp_macro_condition_list = {
- {
- .fType = Detail::kEqual,
- .fTypeName = "==",
- },
- {
- .fType = Detail::kNotEqual,
- .fTypeName = "!=",
- },
- {
- .fType = Detail::kLesserThan,
- .fTypeName = "<",
- },
- {
- .fType = Detail::kGreaterThan,
- .fTypeName = ">",
- },
- {
- .fType = Detail::kLesserEqThan,
- .fTypeName = "<=",
- },
- {
- .fType = Detail::kGreaterEqThan,
- .fTypeName = ">=",
- },
- };
-
- int32_t good_to_go = 0;
-
- for (auto& macro_condition : bpp_macro_condition_list)
- {
- if (hdr_line.find(macro_condition.fTypeName) != std::string::npos)
- {
- for (auto& found_macro : kMacros)
- {
- if (hdr_line.find(found_macro.fName) != std::string::npos)
- {
- good_to_go =
- bpp_parse_if_condition(macro_condition, found_macro,
- inactive_code, defined, hdr_line);
-
- break;
- }
- }
- }
- }
-
- if (good_to_go)
- continue;
-
- auto line_after_if =
- hdr_line.substr(hdr_line.find("if") + strlen("if") + 1);
- std::string macro;
-
- for (auto& ch : line_after_if)
- {
- if (ch == ' ')
- {
- break;
- }
-
- macro += ch;
- }
-
- if (macro == "0")
- {
- defined = false;
- inactive_code = true;
- continue;
- }
-
- if (macro == "1")
- {
- defined = true;
- inactive_code = false;
-
- continue;
- }
-
- // last try, is it defined to be one?
- for (auto& macro_ref : kMacros)
- {
- if (macro_ref.fName.find(macro) != std::string::npos &&
- macro_ref.fValue == "1")
- {
- inactive_code = false;
- defined = true;
-
- break;
- }
- }
- }
- else if (hdr_line[0] == kMacroPrefix &&
- hdr_line.find("warning") != std::string::npos)
- {
- auto line_after_warning =
- hdr_line.substr(hdr_line.find("warning") + strlen("warning") + 1);
- std::string message;
-
- for (auto& ch : line_after_warning)
- {
- if (ch == '\r' || ch == '\n')
- {
- break;
- }
-
- message += ch;
- }
-
- std::cout << "warn: " << message << std::endl;
- }
- else if (hdr_line[0] == kMacroPrefix &&
- hdr_line.find("error") != std::string::npos)
- {
- auto line_after_warning =
- hdr_line.substr(hdr_line.find("error") + strlen("error") + 1);
- std::string message;
-
- for (auto& ch : line_after_warning)
- {
- if (ch == '\r' || ch == '\n')
- {
- break;
- }
-
- message += ch;
- }
-
- throw std::runtime_error("error: " + message);
- }
- else if (hdr_line[0] == kMacroPrefix &&
- hdr_line.find("include ") != std::string::npos)
- {
- line_after_include =
- hdr_line.substr(hdr_line.find("include ") + strlen("include "));
-
- kIncludeFile:
- auto it = std::find(kAllIncludes.cbegin(), kAllIncludes.cend(),
- line_after_include);
-
- if (it != kAllIncludes.cend())
- {
- continue;
- }
-
- std::string path;
-
- kAllIncludes.push_back(line_after_include);
-
- bool enable = false;
- bool not_local = false;
-
- for (auto& ch : line_after_include)
- {
- if (ch == ' ')
- continue;
-
- if (ch == '<')
- {
- not_local = true;
- enable = true;
-
- continue;
- }
-
- if (ch == '\"')
- {
- not_local = false;
- enable = true;
- continue;
- }
-
- if (enable)
- {
- path += ch;
- }
- }
-
- if (not_local)
- {
- bool open = false;
-
- if (path.ends_with('>'))
- {
- path.erase(path.find('>'));
- }
-
- if (path.ends_with('"'))
- {
- path.erase(path.find('"'));
- }
-
- for (auto& include : kIncludes)
- {
- std::string header_path = include;
- header_path.push_back('-');
- header_path += path;
-
- std::ifstream header(header_path);
-
- if (!header.is_open())
- continue;
-
- open = true;
-
- bpp_parse_file(header, pp_out);
-
- break;
- }
-
- if (!open)
- {
- throw std::runtime_error("bpp: no such include file: " + path);
- }
- }
- else
- {
- std::ifstream header(path);
-
- if (!header.is_open())
- throw std::runtime_error("bpp: no such include file: " + path);
-
- bpp_parse_file(header, pp_out);
- }
- }
- else
- {
- std::cerr << ("bpp: unknown pre-processor directive, " + hdr_line)
- << "\n";
- continue;
- }
- }
- }
- catch (std::out_of_range& oor)
- {
- return;
- }
+void bpp_parse_file(std::ifstream& hdr_file, std::ofstream& pp_out) {
+ std::string hdr_line;
+ std::string line_after_include;
+
+ bool inactive_code = false;
+ bool defined = false;
+
+ try {
+ while (std::getline(hdr_file, hdr_line)) {
+ if (inactive_code) {
+ if (hdr_line.find("#endif") == std::string::npos) {
+ continue;
+ } else if (hdr_line[0] == kMacroPrefix && hdr_line.find("#endif") != std::string::npos) {
+ inactive_code = false;
+ }
+
+ if (hdr_line.find("*/") != std::string::npos) {
+ continue;
+ }
+ }
+
+ if (hdr_line.find("--/") != std::string::npos) {
+ hdr_line.erase(hdr_line.find("--/"));
+ }
+
+ if (hdr_line.find("--*") != std::string::npos) {
+ inactive_code = true;
+ // get rid of comment.
+ hdr_line.erase(hdr_line.find("--*"));
+ }
+
+ /// BPP 'brief' documentation.
+ if (hdr_line.find("@brief") != std::string::npos) {
+ hdr_line.erase(hdr_line.find("@brief"));
+
+ // TODO: Write an <file_name>.html or append to it.
+ }
+
+ if (hdr_line[0] == kMacroPrefix && hdr_line.find("endif") != std::string::npos) {
+ if (!defined && inactive_code) {
+ inactive_code = false;
+ defined = false;
+
+ continue;
+ }
+
+ continue;
+ }
+
+ if (!defined && inactive_code) {
+ continue;
+ }
+
+ if (defined && inactive_code) {
+ continue;
+ }
+
+ for (auto macro : kMacros) {
+ if (LibCompiler::find_word(hdr_line, macro.fName)) {
+ if (hdr_line.substr(hdr_line.find(macro.fName)).find(macro.fName + '(') !=
+ LibCompiler::String::npos) {
+ if (!macro.fArgs.empty()) {
+ LibCompiler::String symbol_val = macro.fValue;
+ std::vector<LibCompiler::String> args;
+
+ size_t x_arg_indx = 0;
+
+ LibCompiler::String line_after_define = hdr_line;
+ LibCompiler::String str_arg;
+
+ if (line_after_define.find("(") != LibCompiler::String::npos) {
+ line_after_define.erase(0, line_after_define.find("(") + 1);
+
+ for (auto& subc : line_after_define) {
+ if (subc == ' ' || subc == '\t') continue;
+
+ if (subc == ',' || subc == ')') {
+ if (str_arg.empty()) continue;
+
+ args.push_back(str_arg);
+
+ str_arg.clear();
+
+ continue;
+ }
+
+ str_arg.push_back(subc);
+ }
+ }
+
+ for (auto arg : macro.fArgs) {
+ if (symbol_val.find(macro.fArgs[x_arg_indx]) != LibCompiler::String::npos) {
+ symbol_val.replace(symbol_val.find(macro.fArgs[x_arg_indx]),
+ macro.fArgs[x_arg_indx].size(), args[x_arg_indx]);
+ ++x_arg_indx;
+ } else {
+ throw std::runtime_error("bpp: Internal error.");
+ }
+ }
+
+ auto len = macro.fName.size();
+ len += symbol_val.size();
+ len += 2; // ( and )
+
+ hdr_line.erase(hdr_line.find(")"), 1);
+
+ hdr_line.replace(hdr_line.find(hdr_line.substr(hdr_line.find(macro.fName + '('))),
+ len, symbol_val);
+ } else {
+ auto value = macro.fValue;
+
+ hdr_line.replace(hdr_line.find(macro.fName), macro.fName.size(), value);
+ }
+ }
+ }
+ }
+
+ if (hdr_line[0] == kMacroPrefix && hdr_line.find("define ") != std::string::npos) {
+ auto line_after_define = hdr_line.substr(hdr_line.find("define ") + strlen("define "));
+
+ std::string macro_value;
+ std::string macro_key;
+
+ std::size_t pos = 0UL;
+
+ std::vector<std::string> args;
+ bool on_args = false;
+
+ for (auto& ch : line_after_define) {
+ ++pos;
+
+ if (ch == '(') {
+ on_args = true;
+ continue;
+ }
+
+ if (ch == ')') {
+ on_args = false;
+ continue;
+ }
+
+ if (ch == '\\') continue;
+
+ if (on_args) continue;
+
+ if (ch == ' ') {
+ for (size_t i = pos; i < line_after_define.size(); i++) {
+ macro_value += line_after_define[i];
+ }
+
+ break;
+ }
+
+ macro_key += ch;
+ }
+
+ std::string str;
+
+ if (line_after_define.find("(") != LibCompiler::String::npos) {
+ line_after_define.erase(0, line_after_define.find("(") + 1);
+
+ for (auto& subc : line_after_define) {
+ if (subc == ',' || subc == ')') {
+ if (str.empty()) continue;
+
+ args.push_back(str);
+
+ str.clear();
+
+ continue;
+ }
+
+ str.push_back(subc);
+ }
+ }
+
+ Detail::bpp_macro macro;
+
+ macro.fArgs = args;
+ macro.fName = macro_key;
+ macro.fValue = macro_value;
+
+ kMacros.emplace_back(macro);
+
+ continue;
+ }
+
+ if (hdr_line[0] != kMacroPrefix) {
+ if (inactive_code) {
+ continue;
+ }
+
+ pp_out << hdr_line << std::endl;
+
+ continue;
+ }
+
+ if (hdr_line[0] == kMacroPrefix && hdr_line.find("ifndef") != std::string::npos) {
+ auto line_after_ifndef = hdr_line.substr(hdr_line.find("ifndef") + strlen("ifndef") + 1);
+ std::string macro;
+
+ for (auto& ch : line_after_ifndef) {
+ if (ch == ' ') {
+ break;
+ }
+
+ macro += ch;
+ }
+
+ if (macro == "0") {
+ defined = true;
+ inactive_code = false;
+ continue;
+ }
+
+ if (macro == "1") {
+ defined = false;
+ inactive_code = true;
+
+ continue;
+ }
+
+ bool found = false;
+
+ defined = true;
+ inactive_code = false;
+
+ for (auto& macro_ref : kMacros) {
+ if (hdr_line.find(macro_ref.fName) != std::string::npos) {
+ found = true;
+ break;
+ }
+ }
+
+ if (found) {
+ defined = false;
+ inactive_code = true;
+
+ continue;
+ }
+ } else if (hdr_line[0] == kMacroPrefix && hdr_line.find("else") != std::string::npos) {
+ if (!defined && inactive_code) {
+ inactive_code = false;
+ defined = true;
+
+ continue;
+ } else {
+ defined = false;
+ inactive_code = true;
+
+ continue;
+ }
+ } else if (hdr_line[0] == kMacroPrefix && hdr_line.find("ifdef") != std::string::npos) {
+ auto line_after_ifdef = hdr_line.substr(hdr_line.find("ifdef") + strlen("ifdef") + 1);
+ std::string macro;
+
+ for (auto& ch : line_after_ifdef) {
+ if (ch == ' ') {
+ break;
+ }
+
+ macro += ch;
+ }
+
+ if (macro == "0") {
+ defined = false;
+ inactive_code = true;
+
+ continue;
+ }
+
+ if (macro == "1") {
+ defined = true;
+ inactive_code = false;
+
+ continue;
+ }
+
+ defined = false;
+ inactive_code = true;
+
+ for (auto& macro_ref : kMacros) {
+ if (hdr_line.find(macro_ref.fName) != std::string::npos) {
+ defined = true;
+ inactive_code = false;
+
+ break;
+ }
+ }
+ } else if (hdr_line[0] == kMacroPrefix && hdr_line.find("if") != std::string::npos) {
+ inactive_code = true;
+
+ std::vector<Detail::bpp_macro_condition> bpp_macro_condition_list = {
+ {
+ .fType = Detail::kEqual,
+ .fTypeName = "==",
+ },
+ {
+ .fType = Detail::kNotEqual,
+ .fTypeName = "!=",
+ },
+ {
+ .fType = Detail::kLesserThan,
+ .fTypeName = "<",
+ },
+ {
+ .fType = Detail::kGreaterThan,
+ .fTypeName = ">",
+ },
+ {
+ .fType = Detail::kLesserEqThan,
+ .fTypeName = "<=",
+ },
+ {
+ .fType = Detail::kGreaterEqThan,
+ .fTypeName = ">=",
+ },
+ };
+
+ int32_t good_to_go = 0;
+
+ for (auto& macro_condition : bpp_macro_condition_list) {
+ if (hdr_line.find(macro_condition.fTypeName) != std::string::npos) {
+ for (auto& found_macro : kMacros) {
+ if (hdr_line.find(found_macro.fName) != std::string::npos) {
+ good_to_go = bpp_parse_if_condition(macro_condition, found_macro, inactive_code,
+ defined, hdr_line);
+
+ break;
+ }
+ }
+ }
+ }
+
+ if (good_to_go) continue;
+
+ auto line_after_if = hdr_line.substr(hdr_line.find("if") + strlen("if") + 1);
+ std::string macro;
+
+ for (auto& ch : line_after_if) {
+ if (ch == ' ') {
+ break;
+ }
+
+ macro += ch;
+ }
+
+ if (macro == "0") {
+ defined = false;
+ inactive_code = true;
+ continue;
+ }
+
+ if (macro == "1") {
+ defined = true;
+ inactive_code = false;
+
+ continue;
+ }
+
+ // last try, is it defined to be one?
+ for (auto& macro_ref : kMacros) {
+ if (macro_ref.fName.find(macro) != std::string::npos && macro_ref.fValue == "1") {
+ inactive_code = false;
+ defined = true;
+
+ break;
+ }
+ }
+ } else if (hdr_line[0] == kMacroPrefix && hdr_line.find("warning") != std::string::npos) {
+ auto line_after_warning = hdr_line.substr(hdr_line.find("warning") + strlen("warning") + 1);
+ std::string message;
+
+ for (auto& ch : line_after_warning) {
+ if (ch == '\r' || ch == '\n') {
+ break;
+ }
+
+ message += ch;
+ }
+
+ std::cout << "warn: " << message << std::endl;
+ } else if (hdr_line[0] == kMacroPrefix && hdr_line.find("error") != std::string::npos) {
+ auto line_after_warning = hdr_line.substr(hdr_line.find("error") + strlen("error") + 1);
+ std::string message;
+
+ for (auto& ch : line_after_warning) {
+ if (ch == '\r' || ch == '\n') {
+ break;
+ }
+
+ message += ch;
+ }
+
+ throw std::runtime_error("error: " + message);
+ } else if (hdr_line[0] == kMacroPrefix && hdr_line.find("include ") != std::string::npos) {
+ line_after_include = hdr_line.substr(hdr_line.find("include ") + strlen("include "));
+
+ kIncludeFile:
+ auto it = std::find(kAllIncludes.cbegin(), kAllIncludes.cend(), line_after_include);
+
+ if (it != kAllIncludes.cend()) {
+ continue;
+ }
+
+ std::string path;
+
+ kAllIncludes.push_back(line_after_include);
+
+ bool enable = false;
+ bool not_local = false;
+
+ for (auto& ch : line_after_include) {
+ if (ch == ' ') continue;
+
+ if (ch == '<') {
+ not_local = true;
+ enable = true;
+
+ continue;
+ }
+
+ if (ch == '\"') {
+ not_local = false;
+ enable = true;
+ continue;
+ }
+
+ if (enable) {
+ path += ch;
+ }
+ }
+
+ if (not_local) {
+ bool open = false;
+
+ if (path.ends_with('>')) {
+ path.erase(path.find('>'));
+ }
+
+ if (path.ends_with('"')) {
+ path.erase(path.find('"'));
+ }
+
+ for (auto& include : kIncludes) {
+ std::string header_path = include;
+ header_path.push_back('-');
+ header_path += path;
+
+ std::ifstream header(header_path);
+
+ if (!header.is_open()) continue;
+
+ open = true;
+
+ bpp_parse_file(header, pp_out);
+
+ break;
+ }
+
+ if (!open) {
+ throw std::runtime_error("bpp: no such include file: " + path);
+ }
+ } else {
+ std::ifstream header(path);
+
+ if (!header.is_open()) throw std::runtime_error("bpp: no such include file: " + path);
+
+ bpp_parse_file(header, pp_out);
+ }
+ } else {
+ std::cerr << ("bpp: unknown pre-processor directive, " + hdr_line) << "\n";
+ continue;
+ }
+ }
+ } catch (std::out_of_range& oor) {
+ return;
+ }
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -908,177 +734,157 @@ void bpp_parse_file(std::ifstream& hdr_file, std::ofstream& pp_out)
/////////////////////////////////////////////////////////////////////////////////////////
-LIBCOMPILER_MODULE(CPlusPlusPreprocessorMain)
-{
- try
- {
- bool skip = false;
- bool double_skip = false;
+LIBCOMPILER_MODULE(CPlusPlusPreprocessorMain) {
+ try {
+ bool skip = false;
+ bool double_skip = false;
+
+ Detail::bpp_macro macro_1;
+
+ macro_1.fName = "__true";
+ macro_1.fValue = "1";
+
+ kMacros.push_back(macro_1);
+
+ Detail::bpp_macro macro_unreachable;
+
+ macro_unreachable.fName = "__unreachable";
+ macro_unreachable.fValue = "__libcompiler_unreachable";
+
+ kMacros.push_back(macro_unreachable);
+
+ Detail::bpp_macro macro_0;
- Detail::bpp_macro macro_1;
+ macro_0.fName = "__false";
+ macro_0.fValue = "0";
- macro_1.fName = "__true";
- macro_1.fValue = "1";
+ kMacros.push_back(macro_0);
- kMacros.push_back(macro_1);
+ Detail::bpp_macro macro_zka;
- Detail::bpp_macro macro_unreachable;
+ macro_zka.fName = "__LIBCOMPILER__";
+ macro_zka.fValue = "1";
- macro_unreachable.fName = "__unreachable";
- macro_unreachable.fValue = "__libcompiler_unreachable";
+ kMacros.push_back(macro_zka);
- kMacros.push_back(macro_unreachable);
+ Detail::bpp_macro macro_cxx;
- Detail::bpp_macro macro_0;
+ macro_cxx.fName = "__cplusplus";
+ macro_cxx.fValue = "202302L";
- macro_0.fName = "__false";
- macro_0.fValue = "0";
+ kMacros.push_back(macro_cxx);
- kMacros.push_back(macro_0);
+ Detail::bpp_macro macro_size_t;
+ macro_size_t.fName = "__SIZE_TYPE__";
+ macro_size_t.fValue = "unsigned long long int";
- Detail::bpp_macro macro_zka;
+ kMacros.push_back(macro_size_t);
- macro_zka.fName = "__LIBCOMPILER__";
- macro_zka.fValue = "1";
+ macro_size_t.fName = "__UINT32_TYPE__";
+ macro_size_t.fValue = "unsigned int";
- kMacros.push_back(macro_zka);
+ kMacros.push_back(macro_size_t);
- Detail::bpp_macro macro_cxx;
+ macro_size_t.fName = "__UINTPTR_TYPE__";
+ macro_size_t.fValue = "unsigned int";
- macro_cxx.fName = "__cplusplus";
- macro_cxx.fValue = "202302L";
+ kMacros.push_back(macro_size_t);
- kMacros.push_back(macro_cxx);
+ for (auto index = 1UL; index < argc; ++index) {
+ if (skip) {
+ skip = false;
+ continue;
+ }
- Detail::bpp_macro macro_size_t;
- macro_size_t.fName = "__SIZE_TYPE__";
- macro_size_t.fValue = "unsigned long long int";
+ if (double_skip) {
+ ++index;
+ double_skip = false;
+ continue;
+ }
- kMacros.push_back(macro_size_t);
+ if (argv[index][0] == '-') {
+ if (strcmp(argv[index], "--bpp:ver") == 0) {
+ printf("%s\n", "bpp v1.11, (c) Amlal El Mahrouss");
+ return 0;
+ }
- macro_size_t.fName = "__UINT32_TYPE__";
- macro_size_t.fValue = "unsigned int";
+ if (strcmp(argv[index], "--bpp:?") == 0) {
+ printf("%s\n", "NE Preprocessor Driver v1.11, (c) Amlal El Mahrouss");
+ printf("%s\n", "--bpp:working-dir <path>: set directory to working path.");
+ printf("%s\n", "--bpp:include-dir <path>: add directory to include path.");
+ printf("%s\n", "--bpp:def <name> <value>: define a macro.");
+ printf("%s\n", "--bpp:ver: print the version.");
+ printf("%s\n", "--bpp:?: show help (this current command).");
- kMacros.push_back(macro_size_t);
+ return 0;
+ }
- macro_size_t.fName = "__UINTPTR_TYPE__";
- macro_size_t.fValue = "unsigned int";
+ if (strcmp(argv[index], "--bpp:include-dir") == 0) {
+ std::string inc = argv[index + 1];
- kMacros.push_back(macro_size_t);
+ skip = true;
- for (auto index = 1UL; index < argc; ++index)
- {
- if (skip)
- {
- skip = false;
- continue;
- }
+ kIncludes.push_back(inc);
+ }
- if (double_skip)
- {
- ++index;
- double_skip = false;
- continue;
- }
+ if (strcmp(argv[index], "--bpp:working-dir") == 0) {
+ std::string inc = argv[index + 1];
+ skip = true;
+ kWorkingDir = inc;
+ }
- if (argv[index][0] == '-')
- {
- if (strcmp(argv[index], "--bpp:ver") == 0)
- {
- printf("%s\n", "bpp v1.11, (c) Amlal El Mahrouss");
- return 0;
- }
+ if (strcmp(argv[index], "--bpp:def") == 0 && argv[index + 1] != nullptr &&
+ argv[index + 2] != nullptr) {
+ std::string macro_key = argv[index + 1];
- if (strcmp(argv[index], "--bpp:?") == 0)
- {
- printf("%s\n", "NE Preprocessor Driver v1.11, (c) Amlal El Mahrouss");
- printf("%s\n", "--bpp:working-dir <path>: set directory to working path.");
- printf("%s\n", "--bpp:include-dir <path>: add directory to include path.");
- printf("%s\n", "--bpp:def <name> <value>: define a macro.");
- printf("%s\n", "--bpp:ver: print the version.");
- printf("%s\n", "--bpp:?: show help (this current command).");
+ std::string macro_value;
+ bool is_string = false;
- return 0;
- }
+ for (int argv_find_len = 0; argv_find_len < strlen(argv[index]); ++argv_find_len) {
+ if (!isdigit(argv[index][argv_find_len])) {
+ is_string = true;
+ macro_value += "\"";
- if (strcmp(argv[index], "--bpp:include-dir") == 0)
- {
- std::string inc = argv[index + 1];
+ break;
+ }
+ }
- skip = true;
+ macro_value += argv[index + 2];
- kIncludes.push_back(inc);
- }
+ if (is_string) macro_value += "\"";
- if (strcmp(argv[index], "--bpp:working-dir") == 0)
- {
- std::string inc = argv[index + 1];
- skip = true;
- kWorkingDir = inc;
- }
+ Detail::bpp_macro macro;
+ macro.fName = macro_key;
+ macro.fValue = macro_value;
- if (strcmp(argv[index], "--bpp:def") == 0 && argv[index + 1] != nullptr &&
- argv[index + 2] != nullptr)
- {
- std::string macro_key = argv[index + 1];
+ kMacros.push_back(macro);
- std::string macro_value;
- bool is_string = false;
+ double_skip = true;
+ }
- for (int argv_find_len = 0; argv_find_len < strlen(argv[index]);
- ++argv_find_len)
- {
- if (!isdigit(argv[index][argv_find_len]))
- {
- is_string = true;
- macro_value += "\"";
+ continue;
+ }
- break;
- }
- }
+ kFiles.emplace_back(argv[index]);
+ }
- macro_value += argv[index + 2];
+ if (kFiles.empty()) return LIBCOMPILER_EXEC_ERROR;
- if (is_string)
- macro_value += "\"";
+ for (auto& file : kFiles) {
+ if (!std::filesystem::exists(file)) continue;
- Detail::bpp_macro macro;
- macro.fName = macro_key;
- macro.fValue = macro_value;
+ std::ifstream file_descriptor(file);
+ std::ofstream file_descriptor_pp(file + ".pp");
- kMacros.push_back(macro);
+ bpp_parse_file(file_descriptor, file_descriptor_pp);
+ }
- double_skip = true;
- }
-
- continue;
- }
+ return 0;
+ } catch (const std::runtime_error& e) {
+ std::cout << e.what() << '\n';
+ }
- kFiles.emplace_back(argv[index]);
- }
-
- if (kFiles.empty())
- return LIBCOMPILER_EXEC_ERROR;
-
- for (auto& file : kFiles)
- {
- if (!std::filesystem::exists(file))
- continue;
-
- std::ifstream file_descriptor(file);
- std::ofstream file_descriptor_pp(file + ".pp");
-
- bpp_parse_file(file_descriptor, file_descriptor_pp);
- }
-
- return 0;
- }
- catch (const std::runtime_error& e)
- {
- std::cout << e.what() << '\n';
- }
-
- return 1;
+ return 1;
}
// Last rev 8-1-24
diff --git a/dev/LibCompiler/src/Detail/AsmUtils.h b/dev/LibCompiler/src/Detail/AsmUtils.h
index 997564c..358700a 100644
--- a/dev/LibCompiler/src/Detail/AsmUtils.h
+++ b/dev/LibCompiler/src/Detail/AsmUtils.h
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
+ Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
------------------------------------------- */
@@ -11,106 +11,86 @@
using namespace LibCompiler;
-namespace Detail
-{
- extern void print_error(std::string reason, std::string file) noexcept;
- extern void print_warning(std::string reason, std::string file) noexcept;
-} // namespace Detail
+namespace Detail {
+extern void print_error(std::string reason, std::string file) noexcept;
+extern void print_warning(std::string reason, std::string file) noexcept;
+} // namespace Detail
/// @brief Get Number from lineBuffer.
/// @param lineBuffer the lineBuffer to fetch from.
/// @param numberKey where to seek that number.
/// @return
-static NumberCast32 GetNumber32(std::string lineBuffer, std::string numberKey)
-{
- auto pos = lineBuffer.find(numberKey) + numberKey.size();
-
- while (lineBuffer[pos] == ' ')
- {
- ++pos;
- }
-
- switch (lineBuffer[pos + 1])
- {
- case 'x': {
- if (auto res = strtol(lineBuffer.substr(pos).c_str(), nullptr, 16); !res)
- {
- if (errno != 0)
- {
- Detail::print_error("invalid hex number: " + lineBuffer, "LibCompiler");
- throw std::runtime_error("invalid_hex");
- }
- }
-
- NumberCast32 numOffset(strtol(lineBuffer.substr(pos).c_str(), nullptr, 16));
-
- if (kVerbose)
- {
- kStdOut << "asm: found a base 16 number here: " << lineBuffer.substr(pos)
- << "\n";
- }
-
- return numOffset;
- }
- case 'b': {
- if (auto res = strtol(lineBuffer.substr(pos).c_str(), nullptr, 2); !res)
- {
- if (errno != 0)
- {
- Detail::print_error("invalid binary number:" + lineBuffer, "LibCompiler");
- throw std::runtime_error("invalid_bin");
- }
- }
-
- NumberCast32 numOffset(strtol(lineBuffer.substr(pos).c_str(), nullptr, 2));
-
- if (kVerbose)
- {
- kStdOut << "asm: found a base 2 number here:" << lineBuffer.substr(pos)
- << "\n";
- }
-
- return numOffset;
- }
- case 'o': {
- if (auto res = strtol(lineBuffer.substr(pos).c_str(), nullptr, 7); !res)
- {
- if (errno != 0)
- {
- Detail::print_error("invalid octal number: " + lineBuffer, "LibCompiler");
- throw std::runtime_error("invalid_octal");
- }
- }
-
- NumberCast32 numOffset(strtol(lineBuffer.substr(pos).c_str(), nullptr, 7));
-
- if (kVerbose)
- {
- kStdOut << "asm: found a base 8 number here:" << lineBuffer.substr(pos)
- << "\n";
- }
-
- return numOffset;
- }
- default: {
- if (auto res = strtol(lineBuffer.substr(pos).c_str(), nullptr, 10); !res)
- {
- if (errno != 0)
- {
- Detail::print_error("invalid hex number: " + lineBuffer, "LibCompiler");
- throw std::runtime_error("invalid_hex");
- }
- }
-
- NumberCast32 numOffset(strtol(lineBuffer.substr(pos).c_str(), nullptr, 10));
-
- if (kVerbose)
- {
- kStdOut << "asm: found a base 10 number here:" << lineBuffer.substr(pos)
- << "\n";
- }
-
- return numOffset;
- }
- }
+static NumberCast32 GetNumber32(std::string lineBuffer, std::string numberKey) {
+ auto pos = lineBuffer.find(numberKey) + numberKey.size();
+
+ while (lineBuffer[pos] == ' ') {
+ ++pos;
+ }
+
+ switch (lineBuffer[pos + 1]) {
+ case 'x': {
+ if (auto res = strtol(lineBuffer.substr(pos).c_str(), nullptr, 16); !res) {
+ if (errno != 0) {
+ Detail::print_error("invalid hex number: " + lineBuffer, "LibCompiler");
+ throw std::runtime_error("invalid_hex");
+ }
+ }
+
+ NumberCast32 numOffset(strtol(lineBuffer.substr(pos).c_str(), nullptr, 16));
+
+ if (kVerbose) {
+ kStdOut << "asm: found a base 16 number here: " << lineBuffer.substr(pos) << "\n";
+ }
+
+ return numOffset;
+ }
+ case 'b': {
+ if (auto res = strtol(lineBuffer.substr(pos).c_str(), nullptr, 2); !res) {
+ if (errno != 0) {
+ Detail::print_error("invalid binary number:" + lineBuffer, "LibCompiler");
+ throw std::runtime_error("invalid_bin");
+ }
+ }
+
+ NumberCast32 numOffset(strtol(lineBuffer.substr(pos).c_str(), nullptr, 2));
+
+ if (kVerbose) {
+ kStdOut << "asm: found a base 2 number here:" << lineBuffer.substr(pos) << "\n";
+ }
+
+ return numOffset;
+ }
+ case 'o': {
+ if (auto res = strtol(lineBuffer.substr(pos).c_str(), nullptr, 7); !res) {
+ if (errno != 0) {
+ Detail::print_error("invalid octal number: " + lineBuffer, "LibCompiler");
+ throw std::runtime_error("invalid_octal");
+ }
+ }
+
+ NumberCast32 numOffset(strtol(lineBuffer.substr(pos).c_str(), nullptr, 7));
+
+ if (kVerbose) {
+ kStdOut << "asm: found a base 8 number here:" << lineBuffer.substr(pos) << "\n";
+ }
+
+ return numOffset;
+ }
+ default: {
+ if (auto res = strtol(lineBuffer.substr(pos).c_str(), nullptr, 10); !res) {
+ if (errno != 0) {
+ Detail::print_error("invalid hex number: " + lineBuffer, "LibCompiler");
+ throw std::runtime_error("invalid_hex");
+ }
+ }
+
+ NumberCast32 numOffset(strtol(lineBuffer.substr(pos).c_str(), nullptr, 10));
+
+ if (kVerbose) {
+ kStdOut << "asm: found a base 10 number here:" << lineBuffer.substr(pos) << "\n";
+ }
+
+ return numOffset;
+ }
+ }
}
diff --git a/dev/LibCompiler/src/Detail/ClUtils.h b/dev/LibCompiler/src/Detail/ClUtils.h
index fe788a2..024d0d2 100644
--- a/dev/LibCompiler/src/Detail/ClUtils.h
+++ b/dev/LibCompiler/src/Detail/ClUtils.h
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
+ Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
------------------------------------------- */
diff --git a/dev/LibCompiler/src/DynamicLinkerPEF.cc b/dev/LibCompiler/src/DynamicLinkerPEF.cc
index 6410885..abbf364 100644
--- a/dev/LibCompiler/src/DynamicLinkerPEF.cc
+++ b/dev/LibCompiler/src/DynamicLinkerPEF.cc
@@ -1,9 +1,9 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved
+ Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved
- @file DynamicLinker64PEF.cc
- @brief: C++ 64-Bit PEF Linker.
+ @file DynamicLinker64PEF.cc
+ @brief: C++ 64-Bit PEF Linker.
------------------------------------------- */
@@ -31,756 +31,635 @@
#include <LibCompiler/AE.h>
#include <cstdint>
-#define kLinkerVersionStr "\e[0;97m NeKernel 64-Bit Linker (Preferred Executable) %s, (c) Amlal El Mahrouss 2024-2025, all rights reserved.\n"
+#define kLinkerVersionStr \
+ "\e[0;97m NeKernel 64-Bit Linker (Preferred Executable) %s, (c) Amlal El Mahrouss 2024-2025, " \
+ "all rights reserved.\n"
#define MemoryCopy(DST, SRC, SZ) memcpy(DST, SRC, SZ)
-#define StringCompare(DST, SRC) strcmp(DST, SRC)
+#define StringCompare(DST, SRC) strcmp(DST, SRC)
-#define kPefNoCpu (0U)
+#define kPefNoCpu (0U)
#define kPefNoSubCpu (0U)
-#define kStdOut (std::cout << "\e[0;31m" \
- << "ld64: " \
- << "\e[0;97m")
+#define kStdOut (std::cout << "\e[0;31m" << "ld64: " << "\e[0;97m")
#define kLinkerDefaultOrigin kPefBaseOrigin
-#define kLinkerId (0x5046FF)
-#define kLinkerAbiContainer "Container:ABI:"
+#define kLinkerId (0x5046FF)
+#define kLinkerAbiContainer "Container:ABI:"
-#define kPrintF printf
+#define kPrintF printf
#define kLinkerSplash() kPrintF(kLinkerVersionStr, kDistVersion)
/// @brief PEF stack size symbol.
#define kLinkerStackSizeSymbol "__PEFSizeOfReserveStack"
-namespace Detail
-{
- struct DynamicLinkerBlob final
- {
- std::vector<CharType> mBlob{}; // PEF code/bss/data blob.
- UIntPtr mOffset{0UL}; // the offset of the PEF container header...
- };
-} // namespace Detail
-
-enum
-{
- kABITypeStart = 0x1010, /* Invalid ABI start of ABI list. */
- kABITypeNE = 0x5046, /* PF (NeKernel's PEF ABI) */
- kABITypeInvalid = 0xFFFF,
+namespace Detail {
+struct DynamicLinkerBlob final {
+ std::vector<CharType> mBlob{}; // PEF code/bss/data blob.
+ UIntPtr mOffset{0UL}; // the offset of the PEF container header...
};
+} // namespace Detail
-static LibCompiler::String kOutput = "a.out";
-static Int32 kAbi = kABITypeNE;
-static Int32 kSubArch = kPefNoSubCpu;
-static Int32 kArch = LibCompiler::kPefArchInvalid;
-static Bool kFatBinaryEnable = false;
-static Bool kStartFound = false;
-static Bool kDuplicateSymbols = false;
-static Bool kVerbose = false;
+enum {
+ kABITypeStart = 0x1010, /* Invalid ABI start of ABI list. */
+ kABITypeNE = 0x5046, /* PF (NeKernel's PEF ABI) */
+ kABITypeInvalid = 0xFFFF,
+};
+
+static LibCompiler::String kOutput = "a.out";
+static Int32 kAbi = kABITypeNE;
+static Int32 kSubArch = kPefNoSubCpu;
+static Int32 kArch = LibCompiler::kPefArchInvalid;
+static Bool kFatBinaryEnable = false;
+static Bool kStartFound = false;
+static Bool kDuplicateSymbols = false;
+static Bool kVerbose = false;
/* ld64 is to be found, mld is to be found at runtime. */
static const CharType* kLdDefineSymbol = ":UndefinedSymbol:";
static const CharType* kLdDynamicSym = ":RuntimeSymbol:";
/* object code and list. */
-static std::vector<LibCompiler::String> kObjectList;
+static std::vector<LibCompiler::String> kObjectList;
static std::vector<Detail::DynamicLinkerBlob> kObjectBytes;
-static uintptr_t kMIBCount = 8;
+static uintptr_t kMIBCount = 8;
static uintptr_t kByteCount = 1024;
/// @brief NE 64-bit Linker.
/// @note This linker is made for PEF executable, thus NE based OSes.
-LIBCOMPILER_MODULE(DynamicLinker64PEF)
-{
- bool is_executable = true;
-
- /**
- * @brief parse flags and trigger options.
- */
- for (size_t linker_arg = 1; linker_arg < argc; ++linker_arg)
- {
- if (StringCompare(argv[linker_arg], "-help") == 0)
- {
- kLinkerSplash();
-
- kStdOut << "-version: Show linker version.\n";
- kStdOut << "-help: Show linker help.\n";
- kStdOut << "-ld-verbose: Enable linker trace.\n";
- kStdOut << "-dylib: Output as a Dyanmic PEF.\n";
- kStdOut << "-fat: Output as a FAT PEF.\n";
- kStdOut << "-32k: Output as a 32x0 PEF.\n";
- kStdOut << "-64k: Output as a 64x0 PEF.\n";
- kStdOut << "-amd64: Output as a AMD64 PEF.\n";
- kStdOut << "-rv64: Output as a RISC-V PEF.\n";
- kStdOut << "-power64: Output as a POWER PEF.\n";
- kStdOut << "-arm64: Output as a ARM64 PEF.\n";
- kStdOut << "-output: Select the output file name.\n";
-
- return EXIT_SUCCESS;
- }
- else if (StringCompare(argv[linker_arg], "-version") == 0)
- {
- kLinkerSplash();
- return EXIT_SUCCESS;
- }
- else if (StringCompare(argv[linker_arg], "-fat-binary") == 0)
- {
- kFatBinaryEnable = true;
-
- continue;
- }
- else if (StringCompare(argv[linker_arg], "-64k") == 0)
- {
- kArch = LibCompiler::kPefArch64000;
-
- continue;
- }
- else if (StringCompare(argv[linker_arg], "-amd64") == 0)
- {
- kArch = LibCompiler::kPefArchAMD64;
-
- continue;
- }
- else if (StringCompare(argv[linker_arg], "-32k") == 0)
- {
- kArch = LibCompiler::kPefArch32000;
-
- continue;
- }
- else if (StringCompare(argv[linker_arg], "-power64") == 0)
- {
- kArch = LibCompiler::kPefArchPowerPC;
-
- continue;
- }
- else if (StringCompare(argv[linker_arg], "-riscv64") == 0)
- {
- kArch = LibCompiler::kPefArchRISCV;
-
- continue;
- }
- else if (StringCompare(argv[linker_arg], "-arm64") == 0)
- {
- kArch = LibCompiler::kPefArchARM64;
-
- continue;
- }
- else if (StringCompare(argv[linker_arg], "-ld-verbose") == 0)
- {
- kVerbose = true;
-
- continue;
- }
- else if (StringCompare(argv[linker_arg], "-dylib") == 0)
- {
- if (kOutput.empty())
- {
- continue;
- }
-
- if (kOutput.find(kPefExt) != LibCompiler::String::npos)
- kOutput.erase(kOutput.find(kPefExt), strlen(kPefExt));
-
- kOutput += kPefDylibExt;
-
- is_executable = false;
-
- continue;
- }
- else if (StringCompare(argv[linker_arg], "-output") == 0)
- {
- if ((linker_arg + 1) > argc)
- continue;
-
- kOutput = argv[linker_arg + 1];
- ++linker_arg;
-
- continue;
- }
- else
- {
- if (argv[linker_arg][0] == '-')
- {
- kStdOut << "unknown flag: " << argv[linker_arg] << "\n";
- return EXIT_FAILURE;
- }
-
- kObjectList.emplace_back(argv[linker_arg]);
-
- continue;
- }
- }
-
- if (kOutput.empty())
- {
- kStdOut << "no output filename set." << std::endl;
- return LIBCOMPILER_EXEC_ERROR;
- }
- else if (kObjectList.empty())
- {
- kStdOut << "no input files." << std::endl;
- return LIBCOMPILER_EXEC_ERROR;
- }
- else
- {
- namespace FS = std::filesystem;
-
- // check for existing files, if they don't throw an error.
- for (auto& obj : kObjectList)
- {
- if (!FS::exists(obj))
- {
- // if filesystem doesn't find file
- // -> throw error.
- kStdOut << "no such file: " << obj << std::endl;
- return LIBCOMPILER_EXEC_ERROR;
- }
- }
- }
-
- // PEF expects a valid target architecture when outputing a binary.
- if (kArch == 0)
- {
- kStdOut << "no target architecture set, can't continue." << std::endl;
- return LIBCOMPILER_EXEC_ERROR;
- }
-
- LibCompiler::PEFContainer pef_container{};
-
- int32_t archs = kArch;
-
- pef_container.Count = 0UL;
- pef_container.Kind = is_executable ? LibCompiler::kPefKindExec : LibCompiler::kPefKindDylib;
- pef_container.SubCpu = kSubArch;
- pef_container.Linker = kLinkerId; // Amlal El Mahrouss Linker
- pef_container.Abi = kAbi; // Multi-Processor UX ABI
- pef_container.Magic[0] = kPefMagic[kFatBinaryEnable ? 2 : 0];
- pef_container.Magic[1] = kPefMagic[1];
- pef_container.Magic[2] = kPefMagic[kFatBinaryEnable ? 0 : 2];
- pef_container.Magic[3] = kPefMagic[3];
- pef_container.Version = kPefVersion;
-
- // specify the start address, can be 0x10000
- pef_container.Start = kLinkerDefaultOrigin;
- pef_container.HdrSz = sizeof(LibCompiler::PEFContainer);
-
- std::ofstream output_fc(kOutput, std::ofstream::binary);
-
- if (output_fc.bad())
- {
- if (kVerbose)
- {
- kStdOut << "error: " << strerror(errno) << "\n";
- }
-
- return LIBCOMPILER_FILE_NOT_FOUND;
- }
-
- //! Read AE to convert as PEF.
-
- std::vector<LibCompiler::PEFCommandHeader> command_headers;
- LibCompiler::Utils::AEReadableProtocol reader_protocol{};
-
- for (const auto& objectFile : kObjectList)
- {
- if (!std::filesystem::exists(objectFile))
- continue;
-
- LibCompiler::AEHeader hdr{};
-
- reader_protocol.FP = std::ifstream(objectFile, std::ifstream::binary);
- reader_protocol.FP >> hdr;
-
- auto ae_header = hdr;
-
- if (ae_header.fMagic[0] == kAEMag0 && ae_header.fMagic[1] == kAEMag1 &&
- ae_header.fSize == sizeof(LibCompiler::AEHeader))
- {
- if (ae_header.fArch != kArch)
- {
- if (kVerbose)
- kStdOut << "info: is this a FAT binary? : ";
-
- if (!kFatBinaryEnable)
- {
- if (kVerbose)
- kStdOut << "No.\n";
-
- kStdOut << "error: object " << objectFile
- << " is a different kind of architecture and output isn't "
- "treated as a FAT binary."
- << std::endl;
-
- return LIBCOMPILER_FAT_ERROR;
- }
- else
- {
- if (kVerbose)
- {
- kStdOut << "Architecture matches what we expect.\n";
- }
- }
- }
-
- // append arch type to archs varaible.
- archs |= ae_header.fArch;
- std::size_t cnt = ae_header.fCount;
-
- if (kVerbose)
- kStdOut << "object header found, record count: " << cnt << "\n";
-
- pef_container.Count = cnt;
-
- char_type* raw_ae_records =
- new char_type[cnt * sizeof(LibCompiler::AERecordHeader)];
-
- if (!raw_ae_records)
- {
- if (kVerbose)
- kStdOut << "allocation failure for records of n: " << cnt << "\n";
- }
-
- memset(raw_ae_records, 0, cnt * sizeof(LibCompiler::AERecordHeader));
-
- auto* ae_records = reader_protocol.Read(raw_ae_records, cnt);
-
- for (size_t ae_record_index = 0; ae_record_index < cnt;
- ++ae_record_index)
- {
- LibCompiler::PEFCommandHeader command_header{0};
- std::size_t offset_of_obj = ae_records[ae_record_index].fOffset;
-
- MemoryCopy(command_header.Name, ae_records[ae_record_index].fName,
- kPefNameLen);
-
- LibCompiler::String cmd_hdr_name(command_header.Name);
-
- // check this header if it's any valid.
- if (cmd_hdr_name.find(kPefCode64) ==
- LibCompiler::String::npos &&
- cmd_hdr_name.find(kPefData64) ==
- LibCompiler::String::npos &&
- cmd_hdr_name.find(kPefZero64) ==
- LibCompiler::String::npos)
- {
- if (cmd_hdr_name.find(kPefStart) ==
- LibCompiler::String::npos &&
- *command_header.Name == 0)
- {
- if (cmd_hdr_name.find(kLdDefineSymbol) !=
- LibCompiler::String::npos)
- {
- goto ld_mark_header;
- }
- else
- {
- continue;
- }
- }
- }
-
- if (cmd_hdr_name.find(kPefStart) !=
- LibCompiler::String::npos &&
- cmd_hdr_name.find(kPefCode64) !=
- LibCompiler::String::npos)
- {
- kStartFound = true;
- }
-
- ld_mark_header:
- command_header.Offset = offset_of_obj;
- command_header.Kind = ae_records[ae_record_index].fKind;
- command_header.Size = ae_records[ae_record_index].fSize;
- command_header.Cpu = ae_header.fArch;
- command_header.SubCpu = ae_header.fSubArch;
-
- if (kVerbose)
- {
- kStdOut << "Record: "
- << ae_records[ae_record_index].fName << " is marked.\n";
-
- kStdOut << "Record offset: " << command_header.Offset << "\n";
- }
-
- command_headers.emplace_back(command_header);
- }
-
- delete[] raw_ae_records;
- raw_ae_records = nullptr;
-
- std::vector<char> bytes;
- bytes.resize(ae_header.fCodeSize);
-
- // TODO: Port this to NeFS.
-
- reader_protocol.FP.seekg(std::streamsize(ae_header.fStartCode));
- reader_protocol.FP.read(bytes.data(), std::streamsize(ae_header.fCodeSize));
-
- kObjectBytes.push_back({.mBlob = bytes, .mOffset = ae_header.fStartCode});
-
- // Blob was written, close fp.
-
- reader_protocol.FP.close();
-
- continue;
- }
-
- kStdOut << "Not an object container: " << objectFile << std::endl;
- // don't continue, it is a fatal error.
- return LIBCOMPILER_EXEC_ERROR;
- }
-
- pef_container.Cpu = archs;
-
- output_fc << pef_container;
-
- if (kVerbose)
- {
- kStdOut << "Wrote container header.\n";
- }
-
- output_fc.seekp(std::streamsize(pef_container.HdrSz));
-
- std::vector<LibCompiler::String> not_found;
- std::vector<LibCompiler::String> symbols;
-
- // step 2: check for errors (multiple symbols, undefined ones)
-
- for (auto& command_hdr : command_headers)
- {
- // check if this symbol needs to be resolved.
- if (LibCompiler::String(command_hdr.Name).find(kLdDefineSymbol) !=
- LibCompiler::String::npos &&
- LibCompiler::String(command_hdr.Name).find(kLdDynamicSym) == LibCompiler::String::npos)
- {
- if (kVerbose)
- kStdOut << "Found undefined symbol: " << command_hdr.Name << "\n";
-
- if (auto it = std::find(not_found.begin(), not_found.end(),
- LibCompiler::String(command_hdr.Name));
- it == not_found.end())
- {
- not_found.emplace_back(command_hdr.Name);
- }
- }
-
- symbols.emplace_back(command_hdr.Name);
- }
-
- // Now try to solve these symbols.
-
- for (size_t not_found_idx = 0; not_found_idx < command_headers.size();
- ++not_found_idx)
- {
- if (const auto it = std::find(not_found.begin(), not_found.end(),
- LibCompiler::String(command_headers[not_found_idx].Name));
- it != not_found.end())
- {
- LibCompiler::String symbol_imp = *it;
-
- if (symbol_imp.find(kLdDefineSymbol) == LibCompiler::String::npos)
- continue;
-
- // erase the lookup prefix.
- symbol_imp.erase(
- 0, symbol_imp.find(kLdDefineSymbol) + strlen(kLdDefineSymbol));
-
- // demangle everything.
- while (symbol_imp.find('$') != LibCompiler::String::npos)
- symbol_imp.erase(symbol_imp.find('$'), 1);
+LIBCOMPILER_MODULE(DynamicLinker64PEF) {
+ bool is_executable = true;
+
+ /**
+ * @brief parse flags and trigger options.
+ */
+ for (size_t linker_arg = 1; linker_arg < argc; ++linker_arg) {
+ if (StringCompare(argv[linker_arg], "-help") == 0) {
+ kLinkerSplash();
+
+ kStdOut << "-version: Show linker version.\n";
+ kStdOut << "-help: Show linker help.\n";
+ kStdOut << "-ld-verbose: Enable linker trace.\n";
+ kStdOut << "-dylib: Output as a Dyanmic PEF.\n";
+ kStdOut << "-fat: Output as a FAT PEF.\n";
+ kStdOut << "-32k: Output as a 32x0 PEF.\n";
+ kStdOut << "-64k: Output as a 64x0 PEF.\n";
+ kStdOut << "-amd64: Output as a AMD64 PEF.\n";
+ kStdOut << "-rv64: Output as a RISC-V PEF.\n";
+ kStdOut << "-power64: Output as a POWER PEF.\n";
+ kStdOut << "-arm64: Output as a ARM64 PEF.\n";
+ kStdOut << "-output: Select the output file name.\n";
+
+ return EXIT_SUCCESS;
+ } else if (StringCompare(argv[linker_arg], "-version") == 0) {
+ kLinkerSplash();
+ return EXIT_SUCCESS;
+ } else if (StringCompare(argv[linker_arg], "-fat-binary") == 0) {
+ kFatBinaryEnable = true;
+
+ continue;
+ } else if (StringCompare(argv[linker_arg], "-64k") == 0) {
+ kArch = LibCompiler::kPefArch64000;
+
+ continue;
+ } else if (StringCompare(argv[linker_arg], "-amd64") == 0) {
+ kArch = LibCompiler::kPefArchAMD64;
+
+ continue;
+ } else if (StringCompare(argv[linker_arg], "-32k") == 0) {
+ kArch = LibCompiler::kPefArch32000;
+
+ continue;
+ } else if (StringCompare(argv[linker_arg], "-power64") == 0) {
+ kArch = LibCompiler::kPefArchPowerPC;
+
+ continue;
+ } else if (StringCompare(argv[linker_arg], "-riscv64") == 0) {
+ kArch = LibCompiler::kPefArchRISCV;
+
+ continue;
+ } else if (StringCompare(argv[linker_arg], "-arm64") == 0) {
+ kArch = LibCompiler::kPefArchARM64;
+
+ continue;
+ } else if (StringCompare(argv[linker_arg], "-ld-verbose") == 0) {
+ kVerbose = true;
+
+ continue;
+ } else if (StringCompare(argv[linker_arg], "-dylib") == 0) {
+ if (kOutput.empty()) {
+ continue;
+ }
+
+ if (kOutput.find(kPefExt) != LibCompiler::String::npos)
+ kOutput.erase(kOutput.find(kPefExt), strlen(kPefExt));
+
+ kOutput += kPefDylibExt;
+
+ is_executable = false;
+
+ continue;
+ } else if (StringCompare(argv[linker_arg], "-output") == 0) {
+ if ((linker_arg + 1) > argc) continue;
+
+ kOutput = argv[linker_arg + 1];
+ ++linker_arg;
+
+ continue;
+ } else {
+ if (argv[linker_arg][0] == '-') {
+ kStdOut << "unknown flag: " << argv[linker_arg] << "\n";
+ return EXIT_FAILURE;
+ }
+
+ kObjectList.emplace_back(argv[linker_arg]);
+
+ continue;
+ }
+ }
+
+ if (kOutput.empty()) {
+ kStdOut << "no output filename set." << std::endl;
+ return LIBCOMPILER_EXEC_ERROR;
+ } else if (kObjectList.empty()) {
+ kStdOut << "no input files." << std::endl;
+ return LIBCOMPILER_EXEC_ERROR;
+ } else {
+ namespace FS = std::filesystem;
+
+ // check for existing files, if they don't throw an error.
+ for (auto& obj : kObjectList) {
+ if (!FS::exists(obj)) {
+ // if filesystem doesn't find file
+ // -> throw error.
+ kStdOut << "no such file: " << obj << std::endl;
+ return LIBCOMPILER_EXEC_ERROR;
+ }
+ }
+ }
+
+ // PEF expects a valid target architecture when outputing a binary.
+ if (kArch == 0) {
+ kStdOut << "no target architecture set, can't continue." << std::endl;
+ return LIBCOMPILER_EXEC_ERROR;
+ }
+
+ LibCompiler::PEFContainer pef_container{};
+
+ int32_t archs = kArch;
+
+ pef_container.Count = 0UL;
+ pef_container.Kind = is_executable ? LibCompiler::kPefKindExec : LibCompiler::kPefKindDylib;
+ pef_container.SubCpu = kSubArch;
+ pef_container.Linker = kLinkerId; // Amlal El Mahrouss Linker
+ pef_container.Abi = kAbi; // Multi-Processor UX ABI
+ pef_container.Magic[0] = kPefMagic[kFatBinaryEnable ? 2 : 0];
+ pef_container.Magic[1] = kPefMagic[1];
+ pef_container.Magic[2] = kPefMagic[kFatBinaryEnable ? 0 : 2];
+ pef_container.Magic[3] = kPefMagic[3];
+ pef_container.Version = kPefVersion;
+
+ // specify the start address, can be 0x10000
+ pef_container.Start = kLinkerDefaultOrigin;
+ pef_container.HdrSz = sizeof(LibCompiler::PEFContainer);
+
+ std::ofstream output_fc(kOutput, std::ofstream::binary);
+
+ if (output_fc.bad()) {
+ if (kVerbose) {
+ kStdOut << "error: " << strerror(errno) << "\n";
+ }
+
+ return LIBCOMPILER_FILE_NOT_FOUND;
+ }
+
+ //! Read AE to convert as PEF.
+
+ std::vector<LibCompiler::PEFCommandHeader> command_headers;
+ LibCompiler::Utils::AEReadableProtocol reader_protocol{};
+
+ for (const auto& objectFile : kObjectList) {
+ if (!std::filesystem::exists(objectFile)) continue;
+
+ LibCompiler::AEHeader hdr{};
+
+ reader_protocol.FP = std::ifstream(objectFile, std::ifstream::binary);
+ reader_protocol.FP >> hdr;
+
+ auto ae_header = hdr;
+
+ if (ae_header.fMagic[0] == kAEMag0 && ae_header.fMagic[1] == kAEMag1 &&
+ ae_header.fSize == sizeof(LibCompiler::AEHeader)) {
+ if (ae_header.fArch != kArch) {
+ if (kVerbose) kStdOut << "info: is this a FAT binary? : ";
+
+ if (!kFatBinaryEnable) {
+ if (kVerbose) kStdOut << "No.\n";
+
+ kStdOut << "error: object " << objectFile
+ << " is a different kind of architecture and output isn't "
+ "treated as a FAT binary."
+ << std::endl;
+
+ return LIBCOMPILER_FAT_ERROR;
+ } else {
+ if (kVerbose) {
+ kStdOut << "Architecture matches what we expect.\n";
+ }
+ }
+ }
+
+ // append arch type to archs varaible.
+ archs |= ae_header.fArch;
+ std::size_t cnt = ae_header.fCount;
+
+ if (kVerbose) kStdOut << "object header found, record count: " << cnt << "\n";
+
+ pef_container.Count = cnt;
+
+ char_type* raw_ae_records = new char_type[cnt * sizeof(LibCompiler::AERecordHeader)];
+
+ if (!raw_ae_records) {
+ if (kVerbose) kStdOut << "allocation failure for records of n: " << cnt << "\n";
+ }
+
+ memset(raw_ae_records, 0, cnt * sizeof(LibCompiler::AERecordHeader));
+
+ auto* ae_records = reader_protocol.Read(raw_ae_records, cnt);
+
+ for (size_t ae_record_index = 0; ae_record_index < cnt; ++ae_record_index) {
+ LibCompiler::PEFCommandHeader command_header{0};
+ std::size_t offset_of_obj = ae_records[ae_record_index].fOffset;
+
+ MemoryCopy(command_header.Name, ae_records[ae_record_index].fName, kPefNameLen);
+
+ LibCompiler::String cmd_hdr_name(command_header.Name);
+
+ // check this header if it's any valid.
+ if (cmd_hdr_name.find(kPefCode64) == LibCompiler::String::npos &&
+ cmd_hdr_name.find(kPefData64) == LibCompiler::String::npos &&
+ cmd_hdr_name.find(kPefZero64) == LibCompiler::String::npos) {
+ if (cmd_hdr_name.find(kPefStart) == LibCompiler::String::npos &&
+ *command_header.Name == 0) {
+ if (cmd_hdr_name.find(kLdDefineSymbol) != LibCompiler::String::npos) {
+ goto ld_mark_header;
+ } else {
+ continue;
+ }
+ }
+ }
+
+ if (cmd_hdr_name.find(kPefStart) != LibCompiler::String::npos &&
+ cmd_hdr_name.find(kPefCode64) != LibCompiler::String::npos) {
+ kStartFound = true;
+ }
+
+ ld_mark_header:
+ command_header.Offset = offset_of_obj;
+ command_header.Kind = ae_records[ae_record_index].fKind;
+ command_header.Size = ae_records[ae_record_index].fSize;
+ command_header.Cpu = ae_header.fArch;
+ command_header.SubCpu = ae_header.fSubArch;
+
+ if (kVerbose) {
+ kStdOut << "Record: " << ae_records[ae_record_index].fName << " is marked.\n";
+
+ kStdOut << "Record offset: " << command_header.Offset << "\n";
+ }
+
+ command_headers.emplace_back(command_header);
+ }
+
+ delete[] raw_ae_records;
+ raw_ae_records = nullptr;
+
+ std::vector<char> bytes;
+ bytes.resize(ae_header.fCodeSize);
+
+ // TODO: Port this to NeFS.
+
+ reader_protocol.FP.seekg(std::streamsize(ae_header.fStartCode));
+ reader_protocol.FP.read(bytes.data(), std::streamsize(ae_header.fCodeSize));
+
+ kObjectBytes.push_back({.mBlob = bytes, .mOffset = ae_header.fStartCode});
+
+ // Blob was written, close fp.
+
+ reader_protocol.FP.close();
+
+ continue;
+ }
+
+ kStdOut << "Not an object container: " << objectFile << std::endl;
+ // don't continue, it is a fatal error.
+ return LIBCOMPILER_EXEC_ERROR;
+ }
+
+ pef_container.Cpu = archs;
+
+ output_fc << pef_container;
+
+ if (kVerbose) {
+ kStdOut << "Wrote container header.\n";
+ }
+
+ output_fc.seekp(std::streamsize(pef_container.HdrSz));
+
+ std::vector<LibCompiler::String> not_found;
+ std::vector<LibCompiler::String> symbols;
+
+ // step 2: check for errors (multiple symbols, undefined ones)
+
+ for (auto& command_hdr : command_headers) {
+ // check if this symbol needs to be resolved.
+ if (LibCompiler::String(command_hdr.Name).find(kLdDefineSymbol) != LibCompiler::String::npos &&
+ LibCompiler::String(command_hdr.Name).find(kLdDynamicSym) == LibCompiler::String::npos) {
+ if (kVerbose) kStdOut << "Found undefined symbol: " << command_hdr.Name << "\n";
+
+ if (auto it =
+ std::find(not_found.begin(), not_found.end(), LibCompiler::String(command_hdr.Name));
+ it == not_found.end()) {
+ not_found.emplace_back(command_hdr.Name);
+ }
+ }
+
+ symbols.emplace_back(command_hdr.Name);
+ }
+
+ // Now try to solve these symbols.
+
+ for (size_t not_found_idx = 0; not_found_idx < command_headers.size(); ++not_found_idx) {
+ if (const auto it = std::find(not_found.begin(), not_found.end(),
+ LibCompiler::String(command_headers[not_found_idx].Name));
+ it != not_found.end()) {
+ LibCompiler::String symbol_imp = *it;
+
+ if (symbol_imp.find(kLdDefineSymbol) == LibCompiler::String::npos) continue;
+
+ // erase the lookup prefix.
+ symbol_imp.erase(0, symbol_imp.find(kLdDefineSymbol) + strlen(kLdDefineSymbol));
+
+ // demangle everything.
+ while (symbol_imp.find('$') != LibCompiler::String::npos)
+ symbol_imp.erase(symbol_imp.find('$'), 1);
+
+ // the reason we do is because, this may not match the symbol, and we need
+ // to look for other matching symbols.
+ for (auto& command_hdr : command_headers) {
+ if (LibCompiler::String(command_hdr.Name).find(symbol_imp) != LibCompiler::String::npos &&
+ LibCompiler::String(command_hdr.Name).find(kLdDefineSymbol) ==
+ LibCompiler::String::npos) {
+ LibCompiler::String undefined_symbol = command_hdr.Name;
+ auto result_of_sym = undefined_symbol.substr(undefined_symbol.find(symbol_imp));
+
+ for (int i = 0; result_of_sym[i] != 0; ++i) {
+ if (result_of_sym[i] != symbol_imp[i]) goto ld_continue_search;
+ }
+
+ not_found.erase(it);
+
+ if (kVerbose) kStdOut << "found symbol: " << command_hdr.Name << "\n";
+
+ break;
+ }
+ }
+
+ ld_continue_search:
+ continue;
+ }
+ }
+
+ // step 3: check for errors (recheck if we have those symbols.)
+
+ if (!kStartFound && is_executable) {
+ if (kVerbose)
+ kStdOut << "undefined entrypoint: " << kPefStart
+ << ", you may have forget to link "
+ "against your compiler's runtime library.\n";
+
+ kStdOut << "undefined entrypoint " << kPefStart << " for executable: " << kOutput << "\n";
+ }
+
+ // step 4: write all PEF commands.
+
+ LibCompiler::PEFCommandHeader date_cmd_hdr{};
+
+ time_t timestamp = time(nullptr);
+
+ LibCompiler::String timeStampStr = "Container:BuildEpoch:";
+ timeStampStr += std::to_string(timestamp);
+
+ strncpy(date_cmd_hdr.Name, timeStampStr.c_str(), timeStampStr.size());
+
+ date_cmd_hdr.Flags = 0;
+ date_cmd_hdr.Kind = LibCompiler::kPefZero;
+ date_cmd_hdr.Offset = output_fc.tellp();
+ date_cmd_hdr.Size = timeStampStr.size();
+
+ command_headers.push_back(date_cmd_hdr);
+
+ LibCompiler::PEFCommandHeader abi_cmd_hdr{};
+
+ LibCompiler::String abi = kLinkerAbiContainer;
+
+ switch (kArch) {
+ case LibCompiler::kPefArchAMD64: {
+ abi += "MSFT";
+ break;
+ }
+ case LibCompiler::kPefArchPowerPC: {
+ abi += "SYSV";
+ break;
+ }
+ case LibCompiler::kPefArch32000:
+ case LibCompiler::kPefArch64000: {
+ abi += " ZWS";
+ break;
+ }
+ default: {
+ abi += " IDK";
+ break;
+ }
+ }
+
+ MemoryCopy(abi_cmd_hdr.Name, abi.c_str(), abi.size());
+
+ abi_cmd_hdr.Size = abi.size();
+ abi_cmd_hdr.Offset = output_fc.tellp();
+ abi_cmd_hdr.Flags = 0;
+ abi_cmd_hdr.Kind = LibCompiler::kPefLinkerID;
+
+ command_headers.push_back(abi_cmd_hdr);
+
+ LibCompiler::PEFCommandHeader stack_cmd_hdr{0};
+
+ stack_cmd_hdr.Cpu = kArch;
+ stack_cmd_hdr.Flags = 0;
+ stack_cmd_hdr.Size = sizeof(uintptr_t);
+ stack_cmd_hdr.Offset = 0;
+
+ MemoryCopy(stack_cmd_hdr.Name, kLinkerStackSizeSymbol, strlen(kLinkerStackSizeSymbol));
+
+ command_headers.push_back(stack_cmd_hdr);
+
+ LibCompiler::PEFCommandHeader uuid_cmd_hdr{};
+
+ std::random_device rd;
+
+ auto seedData = std::array<int, std::mt19937::state_size>{};
+ std::generate(std::begin(seedData), std::end(seedData), std::ref(rd));
+ std::seed_seq seq(std::begin(seedData), std::end(seedData));
+ std::mt19937 generator(seq);
+
+ auto gen = uuids::uuid_random_generator{generator};
+ uuids::uuid id = gen();
+ auto uuidStr = uuids::to_string(id);
+
+ MemoryCopy(uuid_cmd_hdr.Name, "Container:GUID:4:", strlen("Container:GUID:4:"));
+ MemoryCopy(uuid_cmd_hdr.Name + strlen("Container:GUID:4:"), uuidStr.c_str(), uuidStr.size());
+
+ uuid_cmd_hdr.Size = strlen(uuid_cmd_hdr.Name);
+ uuid_cmd_hdr.Offset = output_fc.tellp();
+ uuid_cmd_hdr.Flags = LibCompiler::kPefLinkerID;
+ uuid_cmd_hdr.Kind = LibCompiler::kPefZero;
+
+ command_headers.push_back(uuid_cmd_hdr);
+
+ // prepare a symbol vector.
+ std::vector<LibCompiler::String> undef_symbols;
+ std::vector<LibCompiler::String> dupl_symbols;
+ std::vector<LibCompiler::String> resolve_symbols;
+
+ constexpr Int32 cPaddingOffset = 16;
+
+ size_t previous_offset =
+ (command_headers.size() * sizeof(LibCompiler::PEFCommandHeader)) + cPaddingOffset;
+
+ // Finally write down the command headers.
+ // And check for any duplications
+ for (size_t commandHeaderIndex = 0UL; commandHeaderIndex < command_headers.size();
+ ++commandHeaderIndex) {
+ if (LibCompiler::String(command_headers[commandHeaderIndex].Name).find(kLdDefineSymbol) !=
+ LibCompiler::String::npos &&
+ LibCompiler::String(command_headers[commandHeaderIndex].Name).find(kLdDynamicSym) ==
+ LibCompiler::String::npos) {
+ // ignore :UndefinedSymbol: headers, they do not contain code.
+ continue;
+ }
+
+ LibCompiler::String symbol_name = command_headers[commandHeaderIndex].Name;
+
+ if (!symbol_name.empty()) {
+ undef_symbols.emplace_back(symbol_name);
+ }
+
+ command_headers[commandHeaderIndex].Offset += previous_offset;
+ previous_offset += command_headers[commandHeaderIndex].Size;
+
+ LibCompiler::String name = command_headers[commandHeaderIndex].Name;
+
+ /// so this is valid when we get to the entrypoint.
+ /// it is always a code64 container. And should equal to kPefStart as well.
+ /// this chunk of code updates the pef_container.Start with the updated offset.
+ if (name.find(kPefStart) != LibCompiler::String::npos &&
+ name.find(kPefCode64) != LibCompiler::String::npos) {
+ pef_container.Start = command_headers[commandHeaderIndex].Offset;
+ auto tellCurPos = output_fc.tellp();
+
+ output_fc.seekp(0);
+ output_fc << pef_container;
+
+ output_fc.seekp(tellCurPos);
+ }
+
+ if (kVerbose) {
+ kStdOut << "Command header name: " << name << "\n";
+ kStdOut << "Real address of command header content: "
+ << command_headers[commandHeaderIndex].Offset << "\n";
+ }
+
+ output_fc << command_headers[commandHeaderIndex];
+
+ for (size_t sub_command_header_index = 0UL; sub_command_header_index < command_headers.size();
+ ++sub_command_header_index) {
+ if (sub_command_header_index == commandHeaderIndex) continue;
+
+ if (LibCompiler::String(command_headers[sub_command_header_index].Name)
+ .find(kLdDefineSymbol) != LibCompiler::String::npos &&
+ LibCompiler::String(command_headers[sub_command_header_index].Name).find(kLdDynamicSym) ==
+ LibCompiler::String::npos) {
+ if (kVerbose) {
+ kStdOut << "ignore :UndefinedSymbol: command header...\n";
+ }
+
+ // ignore :UndefinedSymbol: headers, they do not contain code.
+ continue;
+ }
+
+ auto& command_hdr = command_headers[sub_command_header_index];
+
+ if (command_hdr.Name == LibCompiler::String(command_headers[commandHeaderIndex].Name)) {
+ if (std::find(dupl_symbols.cbegin(), dupl_symbols.cend(), command_hdr.Name) ==
+ dupl_symbols.cend()) {
+ dupl_symbols.emplace_back(command_hdr.Name);
+ }
+
+ if (kVerbose) kStdOut << "found duplicate symbol: " << command_hdr.Name << "\n";
+
+ kDuplicateSymbols = true;
+ }
+ }
+ }
+
+ if (!dupl_symbols.empty()) {
+ for (auto& symbol : dupl_symbols) {
+ kStdOut << "Multiple symbols of: " << symbol << " detected, cannot continue.\n";
+ }
+
+ return LIBCOMPILER_EXEC_ERROR;
+ }
+
+ // step 2.5: write program bytes.
- // the reason we do is because, this may not match the symbol, and we need
- // to look for other matching symbols.
- for (auto& command_hdr : command_headers)
- {
- if (LibCompiler::String(command_hdr.Name).find(symbol_imp) !=
- LibCompiler::String::npos &&
- LibCompiler::String(command_hdr.Name).find(kLdDefineSymbol) ==
- LibCompiler::String::npos)
- {
- LibCompiler::String undefined_symbol = command_hdr.Name;
- auto result_of_sym =
- undefined_symbol.substr(undefined_symbol.find(symbol_imp));
+ for (auto& struct_of_blob : kObjectBytes) {
+ output_fc.write(struct_of_blob.mBlob.data(), struct_of_blob.mBlob.size());
+ }
- for (int i = 0; result_of_sym[i] != 0; ++i)
- {
- if (result_of_sym[i] != symbol_imp[i])
- goto ld_continue_search;
- }
+ if (kVerbose) {
+ kStdOut << "wrote contents of: " << kOutput << "\n";
+ }
- not_found.erase(it);
+ // step 3: check if we have those symbols
+
+ std::vector<LibCompiler::String> unreferenced_symbols;
+
+ for (auto& command_hdr : command_headers) {
+ if (auto it =
+ std::find(not_found.begin(), not_found.end(), LibCompiler::String(command_hdr.Name));
+ it != not_found.end()) {
+ unreferenced_symbols.emplace_back(command_hdr.Name);
+ }
+ }
- if (kVerbose)
- kStdOut << "found symbol: " << command_hdr.Name << "\n";
+ if (!unreferenced_symbols.empty()) {
+ for (auto& unreferenced_symbol : unreferenced_symbols) {
+ kStdOut << "undefined symbol " << unreferenced_symbol << "\n";
+ }
- break;
- }
- }
+ return LIBCOMPILER_EXEC_ERROR;
+ }
- ld_continue_search:
- continue;
- }
- }
+ if (!kStartFound || kDuplicateSymbols && std::filesystem::exists(kOutput) ||
+ !unreferenced_symbols.empty()) {
+ if (kVerbose) {
+ kStdOut << "file: " << kOutput << ", is corrupt, removing file...\n";
+ }
- // step 3: check for errors (recheck if we have those symbols.)
-
- if (!kStartFound && is_executable)
- {
- if (kVerbose)
- kStdOut
- << "undefined entrypoint: " << kPefStart << ", you may have forget to link "
- "against your compiler's runtime library.\n";
+ return LIBCOMPILER_EXEC_ERROR;
+ }
- kStdOut << "undefined entrypoint " << kPefStart
- << " for executable: " << kOutput << "\n";
- }
-
- // step 4: write all PEF commands.
-
- LibCompiler::PEFCommandHeader date_cmd_hdr{};
-
- time_t timestamp = time(nullptr);
-
- LibCompiler::String timeStampStr = "Container:BuildEpoch:";
- timeStampStr += std::to_string(timestamp);
-
- strncpy(date_cmd_hdr.Name, timeStampStr.c_str(), timeStampStr.size());
-
- date_cmd_hdr.Flags = 0;
- date_cmd_hdr.Kind = LibCompiler::kPefZero;
- date_cmd_hdr.Offset = output_fc.tellp();
- date_cmd_hdr.Size = timeStampStr.size();
-
- command_headers.push_back(date_cmd_hdr);
-
- LibCompiler::PEFCommandHeader abi_cmd_hdr{};
-
- LibCompiler::String abi = kLinkerAbiContainer;
-
- switch (kArch)
- {
- case LibCompiler::kPefArchAMD64: {
- abi += "MSFT";
- break;
- }
- case LibCompiler::kPefArchPowerPC: {
- abi += "SYSV";
- break;
- }
- case LibCompiler::kPefArch32000:
- case LibCompiler::kPefArch64000: {
- abi += " ZWS";
- break;
- }
- default: {
- abi += " IDK";
- break;
- }
- }
-
- MemoryCopy(abi_cmd_hdr.Name, abi.c_str(), abi.size());
-
- abi_cmd_hdr.Size = abi.size();
- abi_cmd_hdr.Offset = output_fc.tellp();
- abi_cmd_hdr.Flags = 0;
- abi_cmd_hdr.Kind = LibCompiler::kPefLinkerID;
-
- command_headers.push_back(abi_cmd_hdr);
-
- LibCompiler::PEFCommandHeader stack_cmd_hdr{0};
-
- stack_cmd_hdr.Cpu = kArch;
- stack_cmd_hdr.Flags = 0;
- stack_cmd_hdr.Size = sizeof(uintptr_t);
- stack_cmd_hdr.Offset = 0;
-
- MemoryCopy(stack_cmd_hdr.Name, kLinkerStackSizeSymbol, strlen(kLinkerStackSizeSymbol));
-
- command_headers.push_back(stack_cmd_hdr);
-
- LibCompiler::PEFCommandHeader uuid_cmd_hdr{};
-
- std::random_device rd;
-
- auto seedData = std::array<int, std::mt19937::state_size>{};
- std::generate(std::begin(seedData), std::end(seedData), std::ref(rd));
- std::seed_seq seq(std::begin(seedData), std::end(seedData));
- std::mt19937 generator(seq);
-
- auto gen = uuids::uuid_random_generator{generator};
- uuids::uuid id = gen();
- auto uuidStr = uuids::to_string(id);
-
- MemoryCopy(uuid_cmd_hdr.Name, "Container:GUID:4:", strlen("Container:GUID:4:"));
- MemoryCopy(uuid_cmd_hdr.Name + strlen("Container:GUID:4:"), uuidStr.c_str(),
- uuidStr.size());
-
- uuid_cmd_hdr.Size = strlen(uuid_cmd_hdr.Name);
- uuid_cmd_hdr.Offset = output_fc.tellp();
- uuid_cmd_hdr.Flags = LibCompiler::kPefLinkerID;
- uuid_cmd_hdr.Kind = LibCompiler::kPefZero;
-
- command_headers.push_back(uuid_cmd_hdr);
-
- // prepare a symbol vector.
- std::vector<LibCompiler::String> undef_symbols;
- std::vector<LibCompiler::String> dupl_symbols;
- std::vector<LibCompiler::String> resolve_symbols;
-
- constexpr Int32 cPaddingOffset = 16;
-
- size_t previous_offset = (command_headers.size() * sizeof(LibCompiler::PEFCommandHeader)) + cPaddingOffset;
-
- // Finally write down the command headers.
- // And check for any duplications
- for (size_t commandHeaderIndex = 0UL;
- commandHeaderIndex < command_headers.size(); ++commandHeaderIndex)
- {
- if (LibCompiler::String(command_headers[commandHeaderIndex].Name)
- .find(kLdDefineSymbol) != LibCompiler::String::npos &&
- LibCompiler::String(command_headers[commandHeaderIndex].Name)
- .find(kLdDynamicSym) == LibCompiler::String::npos)
- {
- // ignore :UndefinedSymbol: headers, they do not contain code.
- continue;
- }
-
- LibCompiler::String symbol_name = command_headers[commandHeaderIndex].Name;
-
- if (!symbol_name.empty())
- {
- undef_symbols.emplace_back(symbol_name);
- }
-
- command_headers[commandHeaderIndex].Offset += previous_offset;
- previous_offset += command_headers[commandHeaderIndex].Size;
-
- LibCompiler::String name = command_headers[commandHeaderIndex].Name;
-
- /// so this is valid when we get to the entrypoint.
- /// it is always a code64 container. And should equal to kPefStart as well.
- /// this chunk of code updates the pef_container.Start with the updated offset.
- if (name.find(kPefStart) != LibCompiler::String::npos &&
- name.find(kPefCode64) != LibCompiler::String::npos)
- {
- pef_container.Start = command_headers[commandHeaderIndex].Offset;
- auto tellCurPos = output_fc.tellp();
-
- output_fc.seekp(0);
- output_fc << pef_container;
-
- output_fc.seekp(tellCurPos);
- }
-
- if (kVerbose)
- {
- kStdOut << "Command header name: " << name << "\n";
- kStdOut << "Real address of command header content: " << command_headers[commandHeaderIndex].Offset << "\n";
- }
-
- output_fc << command_headers[commandHeaderIndex];
-
- for (size_t sub_command_header_index = 0UL;
- sub_command_header_index < command_headers.size();
- ++sub_command_header_index)
- {
- if (sub_command_header_index == commandHeaderIndex)
- continue;
-
- if (LibCompiler::String(command_headers[sub_command_header_index].Name)
- .find(kLdDefineSymbol) != LibCompiler::String::npos &&
- LibCompiler::String(command_headers[sub_command_header_index].Name)
- .find(kLdDynamicSym) == LibCompiler::String::npos)
- {
- if (kVerbose)
- {
- kStdOut << "ignore :UndefinedSymbol: command header...\n";
- }
-
- // ignore :UndefinedSymbol: headers, they do not contain code.
- continue;
- }
-
- auto& command_hdr = command_headers[sub_command_header_index];
-
- if (command_hdr.Name ==
- LibCompiler::String(command_headers[commandHeaderIndex].Name))
- {
- if (std::find(dupl_symbols.cbegin(), dupl_symbols.cend(),
- command_hdr.Name) == dupl_symbols.cend())
- {
- dupl_symbols.emplace_back(command_hdr.Name);
- }
-
- if (kVerbose)
- kStdOut << "found duplicate symbol: " << command_hdr.Name
- << "\n";
-
- kDuplicateSymbols = true;
- }
- }
- }
-
- if (!dupl_symbols.empty())
- {
- for (auto& symbol : dupl_symbols)
- {
- kStdOut << "Multiple symbols of: " << symbol << " detected, cannot continue.\n";
- }
-
- return LIBCOMPILER_EXEC_ERROR;
- }
-
- // step 2.5: write program bytes.
-
- for (auto& struct_of_blob : kObjectBytes)
- {
- output_fc.write(struct_of_blob.mBlob.data(), struct_of_blob.mBlob.size());
- }
-
- if (kVerbose)
- {
- kStdOut << "wrote contents of: " << kOutput << "\n";
- }
-
- // step 3: check if we have those symbols
-
- std::vector<LibCompiler::String> unreferenced_symbols;
-
- for (auto& command_hdr : command_headers)
- {
- if (auto it = std::find(not_found.begin(), not_found.end(),
- LibCompiler::String(command_hdr.Name));
- it != not_found.end())
- {
- unreferenced_symbols.emplace_back(command_hdr.Name);
- }
- }
-
- if (!unreferenced_symbols.empty())
- {
- for (auto& unreferenced_symbol : unreferenced_symbols)
- {
- kStdOut << "undefined symbol " << unreferenced_symbol << "\n";
- }
-
- return LIBCOMPILER_EXEC_ERROR;
- }
-
- if (!kStartFound || kDuplicateSymbols && std::filesystem::exists(kOutput) ||
- !unreferenced_symbols.empty())
- {
- if (kVerbose)
- {
- kStdOut << "file: " << kOutput
- << ", is corrupt, removing file...\n";
- }
-
- return LIBCOMPILER_EXEC_ERROR;
- }
-
- return LIBCOMPILER_SUCCESSS;
+ return LIBCOMPILER_SUCCESSS;
}
// Last rev 13-1-24
diff --git a/dev/LibCompiler/src/StringView.cc b/dev/LibCompiler/src/StringView.cc
index a3bbb4c..41ee636 100644
--- a/dev/LibCompiler/src/StringView.cc
+++ b/dev/LibCompiler/src/StringView.cc
@@ -20,237 +20,188 @@
#include <LibCompiler/StringView.h>
-namespace LibCompiler
-{
- CharType* StringView::Data()
- {
- return m_Data;
- }
-
- const CharType* StringView::CData() const
- {
- return m_Data;
- }
-
- SizeType StringView::Length() const
- {
- return strlen(m_Data);
- }
-
- bool StringView::operator==(const StringView& rhs) const
- {
- if (rhs.Length() != Length())
- return false;
-
- for (SizeType index = 0; index < Length(); ++index)
- {
- if (rhs.m_Data[index] != m_Data[index])
- return false;
- }
-
- return true;
- }
-
- bool StringView::operator==(const CharType* rhs) const
- {
- if (string_length(rhs) != Length())
- return false;
-
- for (SizeType index = 0; index < string_length(rhs); ++index)
- {
- if (rhs[index] != m_Data[index])
- return false;
- }
-
- return true;
- }
-
- bool StringView::operator!=(const StringView& rhs) const
- {
- if (rhs.Length() != Length())
- return false;
-
- for (SizeType index = 0; index < rhs.Length(); ++index)
- {
- if (rhs.m_Data[index] == m_Data[index])
- return false;
- }
-
- return true;
- }
-
- bool StringView::operator!=(const CharType* rhs) const
- {
- if (string_length(rhs) != Length())
- return false;
-
- for (SizeType index = 0; index < string_length(rhs); ++index)
- {
- if (rhs[index] == m_Data[index])
- return false;
- }
-
- return true;
- }
-
- StringView StringBuilder::Construct(const CharType* data)
- {
- if (!data || *data == 0)
- return StringView(0);
-
- StringView view(strlen(data));
- view += data;
-
- return view;
- }
-
- const char* StringBuilder::FromInt(const char* fmt, int i)
- {
- if (!fmt)
- return ("-1");
-
- auto ret_len = 8 + string_length(fmt);
- char* ret = new char[ret_len];
-
- if (!ret)
- return ("-1");
-
- memset(ret, 0, ret_len);
-
- CharType result[sizeof(int64_t)];
-
- if (!to_str(result, sizeof(int64_t), i))
- {
- delete[] ret;
- return ("-1");
- }
-
- const auto fmt_len = string_length(fmt);
- const auto res_len = string_length(result);
-
- for (SizeType idx = 0; idx < fmt_len; ++idx)
- {
- if (fmt[idx] == '%')
- {
- SizeType result_cnt = idx;
-
- for (auto y_idx = 0; y_idx < res_len; ++y_idx)
- {
- ret[y_idx] = result[result_cnt];
- ++result_cnt;
- }
-
- break;
- }
-
- ret[idx] = fmt[idx];
- }
-
- return ret; /* Copy that ret into a buffer, Alloca allocates to the stack */
- }
-
- const char* StringBuilder::FromBool(const char* fmt, bool i)
- {
- if (!fmt)
- return ("?");
-
- const char* boolean_expr = i ? "true" : "false";
- char* ret = new char[i ? 4 : 5 + string_length(fmt)];
-
- if (!ret)
- return ("?");
-
- const auto fmt_len = string_length(fmt);
- const auto res_len = string_length(boolean_expr);
-
- for (SizeType idx = 0; idx < fmt_len; ++idx)
- {
- if (fmt[idx] == '%')
- {
- SizeType result_cnt = idx;
-
- for (auto y_idx = idx; y_idx < res_len; ++y_idx)
- {
- ret[result_cnt] = boolean_expr[y_idx];
- ++result_cnt;
- }
-
- break;
- }
-
- ret[idx] = fmt[idx];
- }
-
- return ret;
- }
+namespace LibCompiler {
+CharType* StringView::Data() {
+ return m_Data;
+}
- bool StringBuilder::Equals(const char* lhs, const char* rhs)
- {
- if (string_length(rhs) != string_length(lhs))
- return false;
+const CharType* StringView::CData() const {
+ return m_Data;
+}
- for (SizeType index = 0; index < string_length(rhs); ++index)
- {
- if (rhs[index] != lhs[index])
- return false;
- }
-
- return true;
- }
+SizeType StringView::Length() const {
+ return strlen(m_Data);
+}
- const char* StringBuilder::Format(const char* fmt, const char* fmtRight)
- {
- if (!fmt || !fmtRight)
- return ("?");
-
- char* ret = new char[string_length(fmtRight) + string_length(fmtRight)];
- if (!ret)
- return ("?");
-
- for (SizeType idx = 0; idx < string_length(fmt); ++idx)
- {
- if (fmt[idx] == '%')
- {
- SizeType result_cnt = idx;
-
- for (SizeType y_idx = 0; y_idx < string_length(fmtRight); ++y_idx)
- {
- ret[result_cnt] = fmtRight[y_idx];
- ++result_cnt;
- }
-
- break;
- }
-
- ret[idx] = fmt[idx];
- }
-
- return ret;
- }
-
- StringView& StringView::operator+=(const CharType* rhs)
- {
- if (strlen(rhs) > this->m_Sz)
- {
- throw std::runtime_error("out_of_bounds: StringView");
- }
-
- memcpy(this->m_Data + this->m_Cur, rhs, strlen(rhs));
- this->m_Cur += strlen(rhs);
-
- return *this;
- }
-
- StringView& StringView::operator+=(const StringView& rhs)
- {
- if (rhs.m_Cur > this->m_Sz)
- {
- throw std::runtime_error("out_of_bounds: StringView");
- }
-
- memcpy(this->m_Data + this->m_Cur, rhs.CData(), strlen(rhs.CData()));
- this->m_Cur += strlen(rhs.CData());
-
- return *this;
- }
-} // namespace LibCompiler
+bool StringView::operator==(const StringView& rhs) const {
+ if (rhs.Length() != Length()) return false;
+
+ for (SizeType index = 0; index < Length(); ++index) {
+ if (rhs.m_Data[index] != m_Data[index]) return false;
+ }
+
+ return true;
+}
+
+bool StringView::operator==(const CharType* rhs) const {
+ if (string_length(rhs) != Length()) return false;
+
+ for (SizeType index = 0; index < string_length(rhs); ++index) {
+ if (rhs[index] != m_Data[index]) return false;
+ }
+
+ return true;
+}
+
+bool StringView::operator!=(const StringView& rhs) const {
+ if (rhs.Length() != Length()) return false;
+
+ for (SizeType index = 0; index < rhs.Length(); ++index) {
+ if (rhs.m_Data[index] == m_Data[index]) return false;
+ }
+
+ return true;
+}
+
+bool StringView::operator!=(const CharType* rhs) const {
+ if (string_length(rhs) != Length()) return false;
+
+ for (SizeType index = 0; index < string_length(rhs); ++index) {
+ if (rhs[index] == m_Data[index]) return false;
+ }
+
+ return true;
+}
+
+StringView StringBuilder::Construct(const CharType* data) {
+ if (!data || *data == 0) return StringView(0);
+
+ StringView view(strlen(data));
+ view += data;
+
+ return view;
+}
+
+const char* StringBuilder::FromInt(const char* fmt, int i) {
+ if (!fmt) return ("-1");
+
+ auto ret_len = 8 + string_length(fmt);
+ char* ret = new char[ret_len];
+
+ if (!ret) return ("-1");
+
+ memset(ret, 0, ret_len);
+
+ CharType result[sizeof(int64_t)];
+
+ if (!to_str(result, sizeof(int64_t), i)) {
+ delete[] ret;
+ return ("-1");
+ }
+
+ const auto fmt_len = string_length(fmt);
+ const auto res_len = string_length(result);
+
+ for (SizeType idx = 0; idx < fmt_len; ++idx) {
+ if (fmt[idx] == '%') {
+ SizeType result_cnt = idx;
+
+ for (auto y_idx = 0; y_idx < res_len; ++y_idx) {
+ ret[y_idx] = result[result_cnt];
+ ++result_cnt;
+ }
+
+ break;
+ }
+
+ ret[idx] = fmt[idx];
+ }
+
+ return ret; /* Copy that ret into a buffer, Alloca allocates to the stack */
+}
+
+const char* StringBuilder::FromBool(const char* fmt, bool i) {
+ if (!fmt) return ("?");
+
+ const char* boolean_expr = i ? "true" : "false";
+ char* ret = new char[i ? 4 : 5 + string_length(fmt)];
+
+ if (!ret) return ("?");
+
+ const auto fmt_len = string_length(fmt);
+ const auto res_len = string_length(boolean_expr);
+
+ for (SizeType idx = 0; idx < fmt_len; ++idx) {
+ if (fmt[idx] == '%') {
+ SizeType result_cnt = idx;
+
+ for (auto y_idx = idx; y_idx < res_len; ++y_idx) {
+ ret[result_cnt] = boolean_expr[y_idx];
+ ++result_cnt;
+ }
+
+ break;
+ }
+
+ ret[idx] = fmt[idx];
+ }
+
+ return ret;
+}
+
+bool StringBuilder::Equals(const char* lhs, const char* rhs) {
+ if (string_length(rhs) != string_length(lhs)) return false;
+
+ for (SizeType index = 0; index < string_length(rhs); ++index) {
+ if (rhs[index] != lhs[index]) return false;
+ }
+
+ return true;
+}
+
+const char* StringBuilder::Format(const char* fmt, const char* fmtRight) {
+ if (!fmt || !fmtRight) return ("?");
+
+ char* ret = new char[string_length(fmtRight) + string_length(fmtRight)];
+ if (!ret) return ("?");
+
+ for (SizeType idx = 0; idx < string_length(fmt); ++idx) {
+ if (fmt[idx] == '%') {
+ SizeType result_cnt = idx;
+
+ for (SizeType y_idx = 0; y_idx < string_length(fmtRight); ++y_idx) {
+ ret[result_cnt] = fmtRight[y_idx];
+ ++result_cnt;
+ }
+
+ break;
+ }
+
+ ret[idx] = fmt[idx];
+ }
+
+ return ret;
+}
+
+StringView& StringView::operator+=(const CharType* rhs) {
+ if (strlen(rhs) > this->m_Sz) {
+ throw std::runtime_error("out_of_bounds: StringView");
+ }
+
+ memcpy(this->m_Data + this->m_Cur, rhs, strlen(rhs));
+ this->m_Cur += strlen(rhs);
+
+ return *this;
+}
+
+StringView& StringView::operator+=(const StringView& rhs) {
+ if (rhs.m_Cur > this->m_Sz) {
+ throw std::runtime_error("out_of_bounds: StringView");
+ }
+
+ memcpy(this->m_Data + this->m_Cur, rhs.CData(), strlen(rhs.CData()));
+ this->m_Cur += strlen(rhs.CData());
+
+ return *this;
+}
+} // namespace LibCompiler
diff --git a/dev/LibDebugger/DebuggerContract.h b/dev/LibDebugger/DebuggerContract.h
index 0ef88a2..0f4bc10 100644
--- a/dev/LibDebugger/DebuggerContract.h
+++ b/dev/LibDebugger/DebuggerContract.h
@@ -1,49 +1,44 @@
/***
- (C) 2025 Amlal El Mahrouss
+ (C) 2025 Amlal El Mahrouss
*/
#pragma once
#include <cstdint>
-#include <unordered_map>
#include <string>
+#include <unordered_map>
+
+namespace LibDebugger {
+class DebuggerContract;
+
+/// \brief Process ID
+typedef uint64_t ProcessID;
+
+/// \brief Address type, a la BSD.
+typedef char* CAddress;
+
+/// \brief Debugger contract class in C++, as per the design states.
+/// \author Amlal El Mahrouss
+class DebuggerContract {
+ public:
+ explicit DebuggerContract() = default;
+ virtual ~DebuggerContract() = default;
+
+ public:
+ DebuggerContract& operator=(const DebuggerContract&) = default;
+ DebuggerContract(const DebuggerContract&) = default;
+
+ public:
+ virtual bool Attach(std::string path, std::string argv, ProcessID& pid) noexcept = 0;
+ virtual bool Breakpoint(std::string symbol) noexcept = 0;
+ virtual bool Break() noexcept = 0;
+ virtual bool Continue() noexcept = 0;
+ virtual bool Detach() noexcept = 0;
+
+ virtual std::unordered_map<uintptr_t, uintptr_t>& Get() { return m_breakpoints; }
-namespace LibDebugger
-{
- class DebuggerContract;
-
- /// \brief Process ID
- typedef uint64_t ProcessID;
-
- /// \brief Address type, a la BSD.
- typedef char* CAddress;
-
- /// \brief Debugger contract class in C++, as per the design states.
- /// \author Amlal El Mahrouss
- class DebuggerContract
- {
- public:
- explicit DebuggerContract() = default;
- virtual ~DebuggerContract() = default;
-
- public:
- DebuggerContract& operator=(const DebuggerContract&) = default;
- DebuggerContract(const DebuggerContract&) = default;
-
- public:
- virtual bool Attach(std::string path, std::string argv, ProcessID& pid) noexcept = 0;
- virtual bool Breakpoint(std::string symbol) noexcept = 0;
- virtual bool Break() noexcept = 0;
- virtual bool Continue() noexcept = 0;
- virtual bool Detach() noexcept = 0;
-
- virtual std::unordered_map<uintptr_t, uintptr_t>& Get()
- {
- return m_breakpoints;
- }
-
- protected:
- ProcessID m_pid;
- std::unordered_map<uintptr_t, uintptr_t> m_breakpoints;
- };
-} // namespace LibDebugger
+ protected:
+ ProcessID m_pid;
+ std::unordered_map<uintptr_t, uintptr_t> m_breakpoints;
+};
+} // namespace LibDebugger
diff --git a/dev/LibDebugger/NeKernelContract.h b/dev/LibDebugger/NeKernelContract.h
index e6b40d0..8e54ab2 100644
--- a/dev/LibDebugger/NeKernelContract.h
+++ b/dev/LibDebugger/NeKernelContract.h
@@ -1,6 +1,6 @@
/***
- (C) 2025 Amlal El Mahrouss
+ (C) 2025 Amlal El Mahrouss
*/
#ifndef LD_NEKERNEL_CONTRACT_H
@@ -21,47 +21,43 @@
#define kDebugMag3 'G'
#define kDebugSourceFile 23
-#define kDebugLine 33
-#define kDebugTeam 43
-#define kDebugEOP 49
-
-namespace LibDebugger::NeKernel
-{
- class NeKernelContract;
-
- namespace Detail
- {
- class NeKernelPortHeader;
-
- inline constexpr size_t kDebugTypeLen = 256U;
-
- typedef char rt_debug_type[kDebugTypeLen];
-
- class NeKernelPortHeader final
- {
- public:
- int16_t fPort;
- int16_t fPortBsy;
- };
- } // namespace Detail
-
- class NeKernelContract : public DebuggerContract
- {
- public:
- NeKernelContract();
- virtual ~NeKernelContract();
-
- // Override additional methods from DebuggerContract
- virtual bool Attach(std::string path, std::string argv, ProcessID& pid) noexcept override;
- virtual bool Breakpoint(std::string symbol) noexcept override;
- virtual bool Break() noexcept override;
- virtual bool Continue() noexcept override;
- virtual bool Detach() noexcept override;
-
- private:
- std::string m_ip_address;
- std::string m_port;
- };
-} // namespace LibDebugger::NeKernel
-
-#endif // LD_NEKERNEL_CONTRACT_H \ No newline at end of file
+#define kDebugLine 33
+#define kDebugTeam 43
+#define kDebugEOP 49
+
+namespace LibDebugger::NeKernel {
+class NeKernelContract;
+
+namespace Detail {
+ class NeKernelPortHeader;
+
+ inline constexpr size_t kDebugTypeLen = 256U;
+
+ typedef char rt_debug_type[kDebugTypeLen];
+
+ class NeKernelPortHeader final {
+ public:
+ int16_t fPort;
+ int16_t fPortBsy;
+ };
+} // namespace Detail
+
+class NeKernelContract : public DebuggerContract {
+ public:
+ NeKernelContract();
+ virtual ~NeKernelContract();
+
+ // Override additional methods from DebuggerContract
+ virtual bool Attach(std::string path, std::string argv, ProcessID& pid) noexcept override;
+ virtual bool Breakpoint(std::string symbol) noexcept override;
+ virtual bool Break() noexcept override;
+ virtual bool Continue() noexcept override;
+ virtual bool Detach() noexcept override;
+
+ private:
+ std::string m_ip_address;
+ std::string m_port;
+};
+} // namespace LibDebugger::NeKernel
+
+#endif // LD_NEKERNEL_CONTRACT_H \ No newline at end of file
diff --git a/dev/LibDebugger/POSIXMachContract.h b/dev/LibDebugger/POSIXMachContract.h
index fbfe928..5904cd2 100644
--- a/dev/LibDebugger/POSIXMachContract.h
+++ b/dev/LibDebugger/POSIXMachContract.h
@@ -1,5 +1,5 @@
/***
- (C) 2025 Amlal El Mahrouss
+ (C) 2025 Amlal El Mahrouss
*/
#pragma once
@@ -9,163 +9,150 @@
/// @file POSIXMachContract.h
/// @brief POSIX Mach debugger.
-#include <LibDebugger/DebuggerContract.h>
#include <LibCompiler/Defines.h>
+#include <LibDebugger/DebuggerContract.h>
+#include <stdint.h>
#include <sys/ptrace.h>
#include <sys/types.h>
-#include <sys/wait.h>
#include <sys/user.h>
+#include <sys/wait.h>
#include <unistd.h>
-#include <stdint.h>
#include <filesystem>
#include <iostream>
+#include <dlfcn.h>
+#include <mach-o/dyld.h>
#include <mach/mach.h>
#include <mach/mach_error.h>
#include <signal.h>
-#include <mach-o/dyld.h>
-#include <dlfcn.h>
-LC_IMPORT_C kern_return_t mach_vm_write(
- vm_map_t target_task,
- mach_vm_address_t address,
- vm_offset_t data,
- mach_msg_type_number_t dataCnt);
+LC_IMPORT_C kern_return_t mach_vm_write(vm_map_t target_task, mach_vm_address_t address,
+ vm_offset_t data, mach_msg_type_number_t dataCnt);
-LC_IMPORT_C kern_return_t mach_vm_protect(vm_map_t target_task, mach_vm_address_t address, mach_vm_size_t size, boolean_t set_maximum, vm_prot_t new_protection);
+LC_IMPORT_C kern_return_t mach_vm_protect(vm_map_t target_task, mach_vm_address_t address,
+ mach_vm_size_t size, boolean_t set_maximum,
+ vm_prot_t new_protection);
-#define PTRACE_ATTACH PT_ATTACHEXC
-#define PTRACE_DETACH PT_DETACH
+#define PTRACE_ATTACH PT_ATTACHEXC
+#define PTRACE_DETACH PT_DETACH
#define PTRACE_POKETEXT PT_WRITE_I
-#define PTRACE_CONT PT_CONTINUE
+#define PTRACE_CONT PT_CONTINUE
#define PTRACE_PEEKTEXT PT_READ_I
-namespace LibDebugger::POSIX
-{
- /// \brief POSIXMachContract engine interface class in C++
- /// \author Amlal El Mahrouss
- class POSIXMachContract : public DebuggerContract
- {
- public:
- explicit POSIXMachContract() = default;
- ~POSIXMachContract() override = default;
+namespace LibDebugger::POSIX {
+/// \brief POSIXMachContract engine interface class in C++
+/// \author Amlal El Mahrouss
+class POSIXMachContract : public DebuggerContract {
+ public:
+ explicit POSIXMachContract() = default;
+ ~POSIXMachContract() override = default;
- public:
- POSIXMachContract& operator=(const POSIXMachContract&) = default;
- POSIXMachContract(const POSIXMachContract&) = default;
+ public:
+ POSIXMachContract& operator=(const POSIXMachContract&) = default;
+ POSIXMachContract(const POSIXMachContract&) = default;
- public:
- BOOL Attach(std::string path, std::string argv, ProcessID& pid) noexcept override
- {
- pid = fork();
+ public:
+ BOOL Attach(std::string path, std::string argv, ProcessID& pid) noexcept override {
+ pid = fork();
- if (pid == 0)
- {
- if (argv.empty())
- {
- ptrace(PT_TRACE_ME, 0, nullptr, 0);
- kill(getpid(), SIGSTOP);
- }
+ if (pid == 0) {
+ if (argv.empty()) {
+ ptrace(PT_TRACE_ME, 0, nullptr, 0);
+ kill(getpid(), SIGSTOP);
+ }
- std::vector<char*> argv_arr;
+ std::vector<char*> argv_arr;
- argv_arr.push_back(const_cast<char*>(path.c_str()));
- argv_arr.push_back(const_cast<char*>(argv.c_str()));
- argv_arr.push_back(nullptr);
+ argv_arr.push_back(const_cast<char*>(path.c_str()));
+ argv_arr.push_back(const_cast<char*>(argv.c_str()));
+ argv_arr.push_back(nullptr);
- execv(path.c_str(), argv_arr.data());
+ execv(path.c_str(), argv_arr.data());
- _exit(1);
- }
+ _exit(1);
+ }
- m_path = path;
- m_pid = pid;
+ m_path = path;
+ m_pid = pid;
- pid = this->m_pid;
+ pid = this->m_pid;
- return true;
- }
+ return true;
+ }
- void SetPath(std::string path) noexcept
- {
- if (path.empty())
- {
- return;
- }
+ void SetPath(std::string path) noexcept {
+ if (path.empty()) {
+ return;
+ }
- m_path = path;
- }
+ m_path = path;
+ }
- BOOL Breakpoint(std::string symbol) noexcept override
- {
- if (!m_path.empty() && std::filesystem::exists(m_path) && std::filesystem::is_regular_file(m_path))
- {
- auto handle = dlopen(m_path.c_str(), RTLD_LAZY);
+ BOOL Breakpoint(std::string symbol) noexcept override {
+ if (!m_path.empty() && std::filesystem::exists(m_path) &&
+ std::filesystem::is_regular_file(m_path)) {
+ auto handle = dlopen(m_path.c_str(), RTLD_LAZY);
- if (handle == nullptr)
- {
- return false;
- }
+ if (handle == nullptr) {
+ return false;
+ }
- auto addr = dlsym(handle, symbol.c_str());
+ auto addr = dlsym(handle, symbol.c_str());
- if (addr == nullptr)
- {
- return false;
- }
+ if (addr == nullptr) {
+ return false;
+ }
- task_read_t task;
- task_for_pid(mach_task_self(), m_pid, &task);
+ task_read_t task;
+ task_for_pid(mach_task_self(), m_pid, &task);
- uint32_t brk_inst = 0xD43E0000;
+ uint32_t brk_inst = 0xD43E0000;
- mach_vm_protect(task, (mach_vm_address_t)addr, sizeof(uint32_t), false, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
- mach_vm_write(task, (mach_vm_address_t)addr, (vm_offset_t)&brk_inst, sizeof(addr));
+ mach_vm_protect(task, (mach_vm_address_t) addr, sizeof(uint32_t), false,
+ VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
+ mach_vm_write(task, (mach_vm_address_t) addr, (vm_offset_t) &brk_inst, sizeof(addr));
- return true;
- }
+ return true;
+ }
- return false;
- }
+ return false;
+ }
- BOOL Break() noexcept override
- {
- task_read_t task;
- task_for_pid(mach_task_self(), m_pid, &task);
+ BOOL Break() noexcept override {
+ task_read_t task;
+ task_for_pid(mach_task_self(), m_pid, &task);
- kern_return_t ret = task_suspend(task);
+ kern_return_t ret = task_suspend(task);
- return ret == KERN_SUCCESS;
- }
+ return ret == KERN_SUCCESS;
+ }
- BOOL Continue() noexcept override
- {
- task_read_t task;
- task_for_pid(mach_task_self(), m_pid, &task);
+ BOOL Continue() noexcept override {
+ task_read_t task;
+ task_for_pid(mach_task_self(), m_pid, &task);
- kern_return_t ret = task_resume(task);
+ kern_return_t ret = task_resume(task);
- return ret == KERN_SUCCESS;
- }
+ return ret == KERN_SUCCESS;
+ }
- BOOL Detach() noexcept override
- {
- this->Continue();
+ BOOL Detach() noexcept override {
+ this->Continue();
- task_read_t task;
- task_for_pid(mach_task_self(), m_pid, &task);
+ task_read_t task;
+ task_for_pid(mach_task_self(), m_pid, &task);
- kern_return_t kr = mach_port_deallocate(mach_task_self(), task);
+ kern_return_t kr = mach_port_deallocate(mach_task_self(), task);
- return kr = KERN_SUCCESS;
- }
+ return kr = KERN_SUCCESS;
+ }
- private:
- ProcessID m_pid{0};
- std::string m_path;
- };
-} // namespace LibDebugger::POSIX
+ private:
+ ProcessID m_pid{0};
+ std::string m_path;
+};
+} // namespace LibDebugger::POSIX
#endif
diff --git a/dev/LibDebugger/src/POSIXMachContract.cc b/dev/LibDebugger/src/POSIXMachContract.cc
index 2f30f09..2753e9a 100644
--- a/dev/LibDebugger/src/POSIXMachContract.cc
+++ b/dev/LibDebugger/src/POSIXMachContract.cc
@@ -1,120 +1,102 @@
/***
- (C) 2025 Amlal El Mahrouss
+ (C) 2025 Amlal El Mahrouss
*/
- #ifdef __APPLE__
+#ifdef __APPLE__
-#include <iostream>
#include <LibCompiler/Defines.h>
-#include <Vendor/Dialogs.h>
#include <LibDebugger/POSIXMachContract.h>
+#include <Vendor/Dialogs.h>
#include <cstdint>
+#include <iostream>
#include <string>
-static BOOL kKeepRunning = false;
+static BOOL kKeepRunning = false;
static LibDebugger::POSIX::POSIXMachContract kDebugger;
-static LibDebugger::ProcessID kPID = 0L;
-static LibDebugger::CAddress kActiveAddress = nullptr;
-static std::string kPath = "";
+static LibDebugger::ProcessID kPID = 0L;
+static LibDebugger::CAddress kActiveAddress = nullptr;
+static std::string kPath = "";
#define kBlank "\e[0;30m"
-#define kRed "\e[0;31m"
+#define kRed "\e[0;31m"
#define kWhite "\e[0;97m"
#define kStdOut (std::cout << kRed << "dbg: " << kWhite)
/// @internal
/// @brief Handles CTRL-C signal on debugger.
-static void dbgi_ctrlc_handler(std::int32_t _)
-{
- if (!kPID)
- {
- return;
- }
+static void dbgi_ctrlc_handler(std::int32_t _) {
+ if (!kPID) {
+ return;
+ }
- auto list = kDebugger.Get();
+ auto list = kDebugger.Get();
- kDebugger.Break();
+ kDebugger.Break();
- pfd::notify("Debugger Event", "Breakpoint hit!");
+ pfd::notify("Debugger Event", "Breakpoint hit!");
- kKeepRunning = false;
+ kKeepRunning = false;
}
-LIBCOMPILER_MODULE(DebuggerMachPOSIX)
-{
- pfd::notify("Debugger Event", "Userland Debugger\n(C) 2025 Amlal El Mahrouss, all rights reserved.");
-
- if (argc >= 3 && std::string(argv[1]) == "-p" &&
- argv[2] != nullptr)
- {
- kPath = argv[2];
- kDebugger.SetPath(kPath);
-
- kStdOut << "[+] Path set to: " << kPath << "\n";
- }
-
- ::signal(SIGINT, dbgi_ctrlc_handler);
-
- while (YES)
- {
- if (kKeepRunning)
- {
- continue;
- }
-
- std::string cmd;
- std::getline(std::cin, cmd);
-
- if (cmd == "c" ||
- cmd == "cont" ||
- cmd == "continue")
- {
- if (kDebugger.Continue())
- {
- kKeepRunning = true;
-
- kStdOut << "[+] Continuing...\n";
-
- pfd::notify("Debugger Event", "Continuing...");
- }
- }
-
- if (cmd == "d" ||
- cmd == "detach")
- kDebugger.Detach();
-
- if (cmd == "start")
- {
- kStdOut << "[?] Enter a argument to use: ";
- std::getline(std::cin, cmd);
-
- kDebugger.Attach(kPath, cmd, kPID);
- }
-
- if (cmd == "exit")
- {
- if (kPID > 0)
- kDebugger.Detach();
-
- break;
- }
-
- if (cmd == "break" ||
- cmd == "b")
- {
- kStdOut << "[?] Enter a symbol to break on: ";
-
- std::getline(std::cin, cmd);
-
- if (kDebugger.Breakpoint(cmd))
- {
- pfd::notify("Debugger Event", "Add Breakpoint at: " + cmd);
- }
- }
- }
-
- return EXIT_SUCCESS;
+LIBCOMPILER_MODULE(DebuggerMachPOSIX) {
+ pfd::notify("Debugger Event",
+ "Userland Debugger\n(C) 2025 Amlal El Mahrouss, all rights reserved.");
+
+ if (argc >= 3 && std::string(argv[1]) == "-p" && argv[2] != nullptr) {
+ kPath = argv[2];
+ kDebugger.SetPath(kPath);
+
+ kStdOut << "[+] Path set to: " << kPath << "\n";
+ }
+
+ ::signal(SIGINT, dbgi_ctrlc_handler);
+
+ while (YES) {
+ if (kKeepRunning) {
+ continue;
+ }
+
+ std::string cmd;
+ std::getline(std::cin, cmd);
+
+ if (cmd == "c" || cmd == "cont" || cmd == "continue") {
+ if (kDebugger.Continue()) {
+ kKeepRunning = true;
+
+ kStdOut << "[+] Continuing...\n";
+
+ pfd::notify("Debugger Event", "Continuing...");
+ }
+ }
+
+ if (cmd == "d" || cmd == "detach") kDebugger.Detach();
+
+ if (cmd == "start") {
+ kStdOut << "[?] Enter a argument to use: ";
+ std::getline(std::cin, cmd);
+
+ kDebugger.Attach(kPath, cmd, kPID);
+ }
+
+ if (cmd == "exit") {
+ if (kPID > 0) kDebugger.Detach();
+
+ break;
+ }
+
+ if (cmd == "break" || cmd == "b") {
+ kStdOut << "[?] Enter a symbol to break on: ";
+
+ std::getline(std::cin, cmd);
+
+ if (kDebugger.Breakpoint(cmd)) {
+ pfd::notify("Debugger Event", "Add Breakpoint at: " + cmd);
+ }
+ }
+ }
+
+ return EXIT_SUCCESS;
}
#endif \ No newline at end of file
diff --git a/dev/Vendor/Dialogs.h b/dev/Vendor/Dialogs.h
index fd64026..ce50b81 100644
--- a/dev/Vendor/Dialogs.h
+++ b/dev/Vendor/Dialogs.h
@@ -16,45 +16,45 @@
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
-#include <windows.h>
#include <commdlg.h>
-#include <shlobj.h>
-#include <shobjidl.h> // IFileDialog
#include <shellapi.h>
+#include <shlobj.h>
+#include <shobjidl.h> // IFileDialog
#include <strsafe.h>
-#include <future> // std::async
-#include <userenv.h> // GetUserProfileDirectory()
+#include <userenv.h> // GetUserProfileDirectory()
+#include <windows.h>
+#include <future> // std::async
#elif __EMSCRIPTEN__
#include <emscripten.h>
#else
#ifndef _POSIX_C_SOURCE
-#define _POSIX_C_SOURCE 2 // for popen()
+#define _POSIX_C_SOURCE 2 // for popen()
#endif
#ifdef __APPLE__
#ifndef _DARWIN_C_SOURCE
#define _DARWIN_C_SOURCE
#endif
#endif
-#include <cstdio> // popen()
-#include <cstdlib> // std::getenv()
-#include <fcntl.h> // fcntl()
-#include <unistd.h> // read(), pipe(), dup2(), getuid()
-#include <csignal> // ::kill, std::signal
-#include <sys/stat.h> // stat()
-#include <sys/wait.h> // waitpid()
-#include <pwd.h> // getpwnam()
+#include <fcntl.h> // fcntl()
+#include <pwd.h> // getpwnam()
+#include <sys/stat.h> // stat()
+#include <sys/wait.h> // waitpid()
+#include <unistd.h> // read(), pipe(), dup2(), getuid()
+#include <csignal> // ::kill, std::signal
+#include <cstdio> // popen()
+#include <cstdlib> // std::getenv()
#endif
-#include <string> // std::string
-#include <memory> // std::shared_ptr
-#include <iostream> // std::ostream
-#include <map> // std::map
-#include <set> // std::set
-#include <regex> // std::regex
-#include <thread> // std::mutex, std::this_thread
-#include <chrono> // std::chrono
+#include <chrono> // std::chrono
+#include <iostream> // std::ostream
+#include <map> // std::map
+#include <memory> // std::shared_ptr
+#include <regex> // std::regex
+#include <set> // std::set
+#include <string> // std::string
+#include <thread> // std::mutex, std::this_thread
// Versions of mingw64 g++ up to 9.3.0 do not have a complete IFileDialog
#ifndef PFD_HAS_IFILEDIALOG
@@ -67,1915 +67,1672 @@
#endif
#endif
-namespace pfd
-{
-
- enum class button
- {
- cancel = -1,
- ok,
- yes,
- no,
- abort,
- retry,
- ignore,
- };
-
- enum class choice
- {
- ok = 0,
- ok_cancel,
- yes_no,
- yes_no_cancel,
- retry_cancel,
- abort_retry_ignore,
- };
-
- enum class icon
- {
- info = 0,
- warning,
- error,
- question,
- };
-
- // Additional option flags for various dialog constructors
- enum class opt : uint8_t
- {
- none = 0,
- // For file open, allow multiselect.
- multiselect = 0x1,
- // For file save, force overwrite and disable the confirmation dialog.
- force_overwrite = 0x2,
- // For folder select, force path to be the provided argument instead
- // of the last opened directory, which is the Microsoft-recommended,
- // user-friendly behaviour.
- force_path = 0x4,
- };
-
- inline opt operator|(opt a, opt b)
- {
- return opt(uint8_t(a) | uint8_t(b));
- }
- inline bool operator&(opt a, opt b)
- {
- return bool(uint8_t(a) & uint8_t(b));
- }
-
- // The settings class, only exposing to the user a way to set verbose mode
- // and to force a rescan of installed desktop helpers (zenity, kdialog…).
- class settings
- {
- public:
- static bool available();
-
- static void verbose(bool value);
- static void rescan();
-
- protected:
- explicit settings(bool resync = false);
-
- bool check_program(std::string const& program);
-
- inline bool is_osascript() const;
- inline bool is_zenity() const;
- inline bool is_kdialog() const;
-
- enum class flag
- {
- is_scanned = 0,
- is_verbose,
-
- has_zenity,
- has_matedialog,
- has_qarma,
- has_kdialog,
- is_vista,
-
- max_flag,
- };
-
- // Static array of flags for internal state
- bool const& flags(flag in_flag) const;
-
- // Non-const getter for the static array of flags
- bool& flags(flag in_flag);
- };
-
- // Internal classes, not to be used by client applications
- namespace internal
- {
-
- // Process wait timeout, in milliseconds
- static int const default_wait_timeout = 20;
-
- class executor
- {
- friend class dialog;
-
- public:
- // High level function to get the result of a command
- std::string result(int* exit_code = nullptr);
-
- // High level function to abort
- bool kill();
+namespace pfd {
+
+enum class button {
+ cancel = -1,
+ ok,
+ yes,
+ no,
+ abort,
+ retry,
+ ignore,
+};
+
+enum class choice {
+ ok = 0,
+ ok_cancel,
+ yes_no,
+ yes_no_cancel,
+ retry_cancel,
+ abort_retry_ignore,
+};
+
+enum class icon {
+ info = 0,
+ warning,
+ error,
+ question,
+};
+
+// Additional option flags for various dialog constructors
+enum class opt : uint8_t {
+ none = 0,
+ // For file open, allow multiselect.
+ multiselect = 0x1,
+ // For file save, force overwrite and disable the confirmation dialog.
+ force_overwrite = 0x2,
+ // For folder select, force path to be the provided argument instead
+ // of the last opened directory, which is the Microsoft-recommended,
+ // user-friendly behaviour.
+ force_path = 0x4,
+};
+
+inline opt operator|(opt a, opt b) {
+ return opt(uint8_t(a) | uint8_t(b));
+}
+inline bool operator&(opt a, opt b) {
+ return bool(uint8_t(a) & uint8_t(b));
+}
+
+// The settings class, only exposing to the user a way to set verbose mode
+// and to force a rescan of installed desktop helpers (zenity, kdialog…).
+class settings {
+ public:
+ static bool available();
+
+ static void verbose(bool value);
+ static void rescan();
+
+ protected:
+ explicit settings(bool resync = false);
+
+ bool check_program(std::string const& program);
+
+ inline bool is_osascript() const;
+ inline bool is_zenity() const;
+ inline bool is_kdialog() const;
+
+ enum class flag {
+ is_scanned = 0,
+ is_verbose,
+
+ has_zenity,
+ has_matedialog,
+ has_qarma,
+ has_kdialog,
+ is_vista,
+
+ max_flag,
+ };
+
+ // Static array of flags for internal state
+ bool const& flags(flag in_flag) const;
+
+ // Non-const getter for the static array of flags
+ bool& flags(flag in_flag);
+};
+
+// Internal classes, not to be used by client applications
+namespace internal {
+
+ // Process wait timeout, in milliseconds
+ static int const default_wait_timeout = 20;
+
+ class executor {
+ friend class dialog;
+
+ public:
+ // High level function to get the result of a command
+ std::string result(int* exit_code = nullptr);
+
+ // High level function to abort
+ bool kill();
#if _WIN32
- void start_func(std::function<std::string(int*)> const& fun);
- static BOOL CALLBACK enum_windows_callback(HWND hwnd, LPARAM lParam);
+ void start_func(std::function<std::string(int*)> const& fun);
+ static BOOL CALLBACK enum_windows_callback(HWND hwnd, LPARAM lParam);
#elif __EMSCRIPTEN__
- void start(int exit_code);
+ void start(int exit_code);
#else
- void start_process(std::vector<std::string> const& command);
+ void start_process(std::vector<std::string> const& command);
#endif
- ~executor();
+ ~executor();
- protected:
- bool ready(int timeout = default_wait_timeout);
- void stop();
+ protected:
+ bool ready(int timeout = default_wait_timeout);
+ void stop();
- private:
- bool m_running = false;
- std::string m_stdout;
- int m_exit_code = -1;
+ private:
+ bool m_running = false;
+ std::string m_stdout;
+ int m_exit_code = -1;
#if _WIN32
- std::future<std::string> m_future;
- std::set<HWND> m_windows;
- std::condition_variable m_cond;
- std::mutex m_mutex;
- DWORD m_tid;
+ std::future<std::string> m_future;
+ std::set<HWND> m_windows;
+ std::condition_variable m_cond;
+ std::mutex m_mutex;
+ DWORD m_tid;
#elif __EMSCRIPTEN__ || __NX__
- // FIXME: do something
+ // FIXME: do something
#else
- pid_t m_pid = 0;
- int m_fd = -1;
+ pid_t m_pid = 0;
+ int m_fd = -1;
#endif
- };
+ };
- class platform
- {
- protected:
+ class platform {
+ protected:
#if _WIN32
- // Helper class around LoadLibraryA() and GetProcAddress() with some safety
- class dll
- {
- public:
- dll(std::string const& name);
- ~dll();
-
- template <typename T>
- class proc
- {
- public:
- proc(dll const& lib, std::string const& sym)
- : m_proc(reinterpret_cast<T*>((void*)::GetProcAddress(lib.handle, sym.c_str())))
- {
- }
-
- operator bool() const
- {
- return m_proc != nullptr;
- }
- operator T*() const
- {
- return m_proc;
- }
-
- private:
- T* m_proc;
- };
-
- private:
- HMODULE handle;
- };
-
- // Helper class around CoInitialize() and CoUnInitialize()
- class ole32_dll : public dll
- {
- public:
- ole32_dll();
- ~ole32_dll();
- bool is_initialized();
-
- private:
- HRESULT m_state;
- };
-
- // Helper class around CreateActCtx() and ActivateActCtx()
- class new_style_context
- {
- public:
- new_style_context();
- ~new_style_context();
-
- private:
- HANDLE create();
- ULONG_PTR m_cookie = 0;
- };
+ // Helper class around LoadLibraryA() and GetProcAddress() with some safety
+ class dll {
+ public:
+ dll(std::string const& name);
+ ~dll();
+
+ template <typename T>
+ class proc {
+ public:
+ proc(dll const& lib, std::string const& sym)
+ : m_proc(reinterpret_cast<T*>((void*) ::GetProcAddress(lib.handle, sym.c_str()))) {}
+
+ operator bool() const { return m_proc != nullptr; }
+ operator T*() const { return m_proc; }
+
+ private:
+ T* m_proc;
+ };
+
+ private:
+ HMODULE handle;
+ };
+
+ // Helper class around CoInitialize() and CoUnInitialize()
+ class ole32_dll : public dll {
+ public:
+ ole32_dll();
+ ~ole32_dll();
+ bool is_initialized();
+
+ private:
+ HRESULT m_state;
+ };
+
+ // Helper class around CreateActCtx() and ActivateActCtx()
+ class new_style_context {
+ public:
+ new_style_context();
+ ~new_style_context();
+
+ private:
+ HANDLE create();
+ ULONG_PTR m_cookie = 0;
+ };
#endif
- };
-
- class dialog : protected settings, protected platform
- {
- public:
- bool ready(int timeout = default_wait_timeout) const;
- bool kill() const;
-
- protected:
- explicit dialog();
-
- std::vector<std::string> desktop_helper() const;
- static std::string buttons_to_name(choice _choice);
- static std::string get_icon_name(icon _icon);
-
- std::string powershell_quote(std::string const& str) const;
- std::string osascript_quote(std::string const& str) const;
- std::string shell_quote(std::string const& str) const;
-
- // Keep handle to executing command
- std::shared_ptr<executor> m_async;
- };
-
- class file_dialog : public dialog
- {
- protected:
- enum type
- {
- open,
- save,
- folder,
- };
-
- file_dialog(type in_type,
- std::string const& title,
- std::string const& default_path = "",
- std::vector<std::string> const& filters = {},
- opt options = opt::none);
-
- protected:
- std::string string_result();
- std::vector<std::string> vector_result();
+ };
+
+ class dialog : protected settings, protected platform {
+ public:
+ bool ready(int timeout = default_wait_timeout) const;
+ bool kill() const;
+
+ protected:
+ explicit dialog();
+
+ std::vector<std::string> desktop_helper() const;
+ static std::string buttons_to_name(choice _choice);
+ static std::string get_icon_name(icon _icon);
+
+ std::string powershell_quote(std::string const& str) const;
+ std::string osascript_quote(std::string const& str) const;
+ std::string shell_quote(std::string const& str) const;
+
+ // Keep handle to executing command
+ std::shared_ptr<executor> m_async;
+ };
+
+ class file_dialog : public dialog {
+ protected:
+ enum type {
+ open,
+ save,
+ folder,
+ };
+
+ file_dialog(type in_type, std::string const& title, std::string const& default_path = "",
+ std::vector<std::string> const& filters = {}, opt options = opt::none);
+
+ protected:
+ std::string string_result();
+ std::vector<std::string> vector_result();
#if _WIN32
- static int CALLBACK bffcallback(HWND hwnd, UINT uMsg, LPARAM, LPARAM pData);
+ static int CALLBACK bffcallback(HWND hwnd, UINT uMsg, LPARAM, LPARAM pData);
#if PFD_HAS_IFILEDIALOG
- std::string select_folder_vista(IFileDialog* ifd, bool force_path);
+ std::string select_folder_vista(IFileDialog* ifd, bool force_path);
#endif
- std::wstring m_wtitle;
- std::wstring m_wdefault_path;
+ std::wstring m_wtitle;
+ std::wstring m_wdefault_path;
- std::vector<std::string> m_vector_result;
+ std::vector<std::string> m_vector_result;
#endif
- };
-
- } // namespace internal
-
- //
- // The path class provides some platform-specific path constants
- //
-
- class path : protected internal::platform
- {
- public:
- static std::string home();
- static std::string separator();
- };
-
- //
- // The notify widget
- //
-
- class notify : public internal::dialog
- {
- public:
- notify(std::string const& title,
- std::string const& message,
- icon _icon = icon::info);
- };
-
- //
- // The message widget
- //
-
- class message : public internal::dialog
- {
- public:
- message(std::string const& title,
- std::string const& text,
- choice _choice = choice::ok_cancel,
- icon _icon = icon::info);
-
- button result();
-
- private:
- // Some extra logic to map the exit code to button number
- std::map<int, button> m_mappings;
- };
-
- //
- // The open_file, save_file, and open_folder widgets
- //
-
- class open_file : public internal::file_dialog
- {
- public:
- open_file(std::string const& title,
- std::string const& default_path = "",
- std::vector<std::string> const& filters = {"All Files", "*"},
- opt options = opt::none);
+ };
+
+} // namespace internal
+
+//
+// The path class provides some platform-specific path constants
+//
+
+class path : protected internal::platform {
+ public:
+ static std::string home();
+ static std::string separator();
+};
+
+//
+// The notify widget
+//
+
+class notify : public internal::dialog {
+ public:
+ notify(std::string const& title, std::string const& message, icon _icon = icon::info);
+};
+
+//
+// The message widget
+//
+
+class message : public internal::dialog {
+ public:
+ message(std::string const& title, std::string const& text, choice _choice = choice::ok_cancel,
+ icon _icon = icon::info);
+
+ button result();
+
+ private:
+ // Some extra logic to map the exit code to button number
+ std::map<int, button> m_mappings;
+};
+
+//
+// The open_file, save_file, and open_folder widgets
+//
+
+class open_file : public internal::file_dialog {
+ public:
+ open_file(std::string const& title, std::string const& default_path = "",
+ std::vector<std::string> const& filters = {"All Files", "*"}, opt options = opt::none);
#if defined(__has_cpp_attribute)
#if __has_cpp_attribute(deprecated)
- // Backwards compatibility
- [[deprecated("Use pfd::opt::multiselect instead of allow_multiselect")]]
+ // Backwards compatibility
+ [[deprecated("Use pfd::opt::multiselect instead of allow_multiselect")]]
#endif
#endif
- open_file(std::string const& title,
- std::string const& default_path,
- std::vector<std::string> const& filters,
- bool allow_multiselect);
-
- std::vector<std::string> result();
- };
-
- class save_file : public internal::file_dialog
- {
- public:
- save_file(std::string const& title,
- std::string const& default_path = "",
- std::vector<std::string> const& filters = {"All Files", "*"},
- opt options = opt::none);
+ open_file(std::string const& title, std::string const& default_path,
+ std::vector<std::string> const& filters, bool allow_multiselect);
+
+ std::vector<std::string> result();
+};
+
+class save_file : public internal::file_dialog {
+ public:
+ save_file(std::string const& title, std::string const& default_path = "",
+ std::vector<std::string> const& filters = {"All Files", "*"}, opt options = opt::none);
#if defined(__has_cpp_attribute)
#if __has_cpp_attribute(deprecated)
- // Backwards compatibility
- [[deprecated("Use pfd::opt::force_overwrite instead of confirm_overwrite")]]
+ // Backwards compatibility
+ [[deprecated("Use pfd::opt::force_overwrite instead of confirm_overwrite")]]
#endif
#endif
- save_file(std::string const& title,
- std::string const& default_path,
- std::vector<std::string> const& filters,
- bool confirm_overwrite);
-
- std::string result();
- };
-
- class select_folder : public internal::file_dialog
- {
- public:
- select_folder(std::string const& title,
- std::string const& default_path = "",
- opt options = opt::none);
-
- std::string result();
- };
-
- //
- // Below this are all the method implementations. You may choose to define the
- // macro PFD_SKIP_IMPLEMENTATION everywhere before including this header except
- // in one place. This may reduce compilation times.
- //
+ save_file(std::string const& title, std::string const& default_path,
+ std::vector<std::string> const& filters, bool confirm_overwrite);
+
+ std::string result();
+};
+
+class select_folder : public internal::file_dialog {
+ public:
+ select_folder(std::string const& title, std::string const& default_path = "",
+ opt options = opt::none);
+
+ std::string result();
+};
+
+//
+// Below this are all the method implementations. You may choose to define the
+// macro PFD_SKIP_IMPLEMENTATION everywhere before including this header except
+// in one place. This may reduce compilation times.
+//
#if !defined PFD_SKIP_IMPLEMENTATION
- // internal free functions implementations
+// internal free functions implementations
- namespace internal
- {
+namespace internal {
#if _WIN32
- static inline std::wstring str2wstr(std::string const& str)
- {
- int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.size(), nullptr, 0);
- std::wstring ret(len, '\0');
- MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.size(), (LPWSTR)ret.data(), (int)ret.size());
- return ret;
- }
-
- static inline std::string wstr2str(std::wstring const& str)
- {
- int len = WideCharToMultiByte(CP_UTF8, 0, str.c_str(), (int)str.size(), nullptr, 0, nullptr, nullptr);
- std::string ret(len, '\0');
- WideCharToMultiByte(CP_UTF8, 0, str.c_str(), (int)str.size(), (LPSTR)ret.data(), (int)ret.size(), nullptr, nullptr);
- return ret;
- }
-
- static inline bool is_vista()
- {
- OSVERSIONINFOEXW osvi;
- memset(&osvi, 0, sizeof(osvi));
- DWORDLONG const mask = VerSetConditionMask(
- VerSetConditionMask(
- VerSetConditionMask(
- 0, VER_MAJORVERSION, VER_GREATER_EQUAL),
- VER_MINORVERSION, VER_GREATER_EQUAL),
- VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
- osvi.dwOSVersionInfoSize = sizeof(osvi);
- osvi.dwMajorVersion = HIBYTE(_WIN32_WINNT_VISTA);
- osvi.dwMinorVersion = LOBYTE(_WIN32_WINNT_VISTA);
- osvi.wServicePackMajor = 0;
-
- return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, mask) != FALSE;
- }
+ static inline std::wstring str2wstr(std::string const& str) {
+ int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int) str.size(), nullptr, 0);
+ std::wstring ret(len, '\0');
+ MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int) str.size(), (LPWSTR) ret.data(),
+ (int) ret.size());
+ return ret;
+ }
+
+ static inline std::string wstr2str(std::wstring const& str) {
+ int len = WideCharToMultiByte(CP_UTF8, 0, str.c_str(), (int) str.size(), nullptr, 0, nullptr,
+ nullptr);
+ std::string ret(len, '\0');
+ WideCharToMultiByte(CP_UTF8, 0, str.c_str(), (int) str.size(), (LPSTR) ret.data(),
+ (int) ret.size(), nullptr, nullptr);
+ return ret;
+ }
+
+ static inline bool is_vista() {
+ OSVERSIONINFOEXW osvi;
+ memset(&osvi, 0, sizeof(osvi));
+ DWORDLONG const mask = VerSetConditionMask(
+ VerSetConditionMask(VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL),
+ VER_MINORVERSION, VER_GREATER_EQUAL),
+ VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
+ osvi.dwOSVersionInfoSize = sizeof(osvi);
+ osvi.dwMajorVersion = HIBYTE(_WIN32_WINNT_VISTA);
+ osvi.dwMinorVersion = LOBYTE(_WIN32_WINNT_VISTA);
+ osvi.wServicePackMajor = 0;
+
+ return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR,
+ mask) != FALSE;
+ }
#endif
- // This is necessary until C++20 which will have std::string::ends_with() etc.
+ // This is necessary until C++20 which will have std::string::ends_with() etc.
- static inline bool ends_with(std::string const& str, std::string const& suffix)
- {
- return suffix.size() <= str.size() &&
- str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
- }
+ static inline bool ends_with(std::string const& str, std::string const& suffix) {
+ return suffix.size() <= str.size() &&
+ str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
+ }
- static inline bool starts_with(std::string const& str, std::string const& prefix)
- {
- return prefix.size() <= str.size() &&
- str.compare(0, prefix.size(), prefix) == 0;
- }
+ static inline bool starts_with(std::string const& str, std::string const& prefix) {
+ return prefix.size() <= str.size() && str.compare(0, prefix.size(), prefix) == 0;
+ }
- // This is necessary until C++17 which will have std::filesystem::is_directory
+ // This is necessary until C++17 which will have std::filesystem::is_directory
- static inline bool is_directory(std::string const& path)
- {
+ static inline bool is_directory(std::string const& path) {
#if _WIN32
- auto attr = GetFileAttributesA(path.c_str());
- return attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY);
+ auto attr = GetFileAttributesA(path.c_str());
+ return attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY);
#elif __EMSCRIPTEN__
- // TODO
- return false;
+ // TODO
+ return false;
#else
- struct stat s;
- return stat(path.c_str(), &s) == 0 && S_ISDIR(s.st_mode);
+ struct stat s;
+ return stat(path.c_str(), &s) == 0 && S_ISDIR(s.st_mode);
#endif
- }
+ }
- // This is necessary because getenv is not thread-safe
+ // This is necessary because getenv is not thread-safe
- static inline std::string getenv(std::string const& str)
- {
+ static inline std::string getenv(std::string const& str) {
#if _MSC_VER
- char* buf = nullptr;
- size_t size = 0;
- if (_dupenv_s(&buf, &size, str.c_str()) == 0 && buf)
- {
- std::string ret(buf);
- free(buf);
- return ret;
- }
- return "";
+ char* buf = nullptr;
+ size_t size = 0;
+ if (_dupenv_s(&buf, &size, str.c_str()) == 0 && buf) {
+ std::string ret(buf);
+ free(buf);
+ return ret;
+ }
+ return "";
#else
- auto buf = std::getenv(str.c_str());
- return buf ? buf : "";
+ auto buf = std::getenv(str.c_str());
+ return buf ? buf : "";
#endif
- }
+ }
- } // namespace internal
+} // namespace internal
- // settings implementation
+// settings implementation
- inline settings::settings(bool resync)
- {
- flags(flag::is_scanned) &= !resync;
+inline settings::settings(bool resync) {
+ flags(flag::is_scanned) &= !resync;
- if (flags(flag::is_scanned))
- return;
+ if (flags(flag::is_scanned)) return;
- auto pfd_verbose = internal::getenv("PFD_VERBOSE");
- auto match_no = std::regex("(|0|no|false)", std::regex_constants::icase);
- if (!std::regex_match(pfd_verbose, match_no))
- flags(flag::is_verbose) = true;
+ auto pfd_verbose = internal::getenv("PFD_VERBOSE");
+ auto match_no = std::regex("(|0|no|false)", std::regex_constants::icase);
+ if (!std::regex_match(pfd_verbose, match_no)) flags(flag::is_verbose) = true;
#if _WIN32
- flags(flag::is_vista) = internal::is_vista();
+ flags(flag::is_vista) = internal::is_vista();
#elif !__APPLE__
- flags(flag::has_zenity) = check_program("zenity");
- flags(flag::has_matedialog) = check_program("matedialog");
- flags(flag::has_qarma) = check_program("qarma");
- flags(flag::has_kdialog) = check_program("kdialog");
-
- // If multiple helpers are available, try to default to the best one
- if (flags(flag::has_zenity) && flags(flag::has_kdialog))
- {
- auto desktop_name = internal::getenv("XDG_SESSION_DESKTOP");
- if (desktop_name == std::string("gnome"))
- flags(flag::has_kdialog) = false;
- else if (desktop_name == std::string("KDE"))
- flags(flag::has_zenity) = false;
- }
+ flags(flag::has_zenity) = check_program("zenity");
+ flags(flag::has_matedialog) = check_program("matedialog");
+ flags(flag::has_qarma) = check_program("qarma");
+ flags(flag::has_kdialog) = check_program("kdialog");
+
+ // If multiple helpers are available, try to default to the best one
+ if (flags(flag::has_zenity) && flags(flag::has_kdialog)) {
+ auto desktop_name = internal::getenv("XDG_SESSION_DESKTOP");
+ if (desktop_name == std::string("gnome"))
+ flags(flag::has_kdialog) = false;
+ else if (desktop_name == std::string("KDE"))
+ flags(flag::has_zenity) = false;
+ }
#endif
- flags(flag::is_scanned) = true;
- }
+ flags(flag::is_scanned) = true;
+}
- inline bool settings::available()
- {
+inline bool settings::available() {
#if _WIN32
- return true;
+ return true;
#elif __APPLE__
- return true;
+ return true;
#elif __EMSCRIPTEN__
- // FIXME: Return true after implementation is complete.
- return false;
+ // FIXME: Return true after implementation is complete.
+ return false;
#else
- settings tmp;
- return tmp.flags(flag::has_zenity) ||
- tmp.flags(flag::has_matedialog) ||
- tmp.flags(flag::has_qarma) ||
- tmp.flags(flag::has_kdialog);
+ settings tmp;
+ return tmp.flags(flag::has_zenity) || tmp.flags(flag::has_matedialog) ||
+ tmp.flags(flag::has_qarma) || tmp.flags(flag::has_kdialog);
#endif
- }
+}
- inline void settings::verbose(bool value)
- {
- settings().flags(flag::is_verbose) = value;
- }
+inline void settings::verbose(bool value) {
+ settings().flags(flag::is_verbose) = value;
+}
- inline void settings::rescan()
- {
- settings(/* resync = */ true);
- }
+inline void settings::rescan() {
+ settings(/* resync = */ true);
+}
- // Check whether a program is present using “which”.
- inline bool settings::check_program(std::string const& program)
- {
+// Check whether a program is present using “which”.
+inline bool settings::check_program(std::string const& program) {
#if _WIN32
- (void)program;
- return false;
+ (void) program;
+ return false;
#elif __EMSCRIPTEN__
- (void)program;
- return false;
+ (void) program;
+ return false;
#else
- int exit_code = -1;
- internal::executor async;
- async.start_process({"/bin/sh", "-c", "which " + program});
- async.result(&exit_code);
- return exit_code == 0;
+ int exit_code = -1;
+ internal::executor async;
+ async.start_process({"/bin/sh", "-c", "which " + program});
+ async.result(&exit_code);
+ return exit_code == 0;
#endif
- }
+}
- inline bool settings::is_osascript() const
- {
+inline bool settings::is_osascript() const {
#if __APPLE__
- return true;
+ return true;
#else
- return false;
+ return false;
#endif
- }
-
- inline bool settings::is_zenity() const
- {
- return flags(flag::has_zenity) ||
- flags(flag::has_matedialog) ||
- flags(flag::has_qarma);
- }
-
- inline bool settings::is_kdialog() const
- {
- return flags(flag::has_kdialog);
- }
-
- inline bool const& settings::flags(flag in_flag) const
- {
- static bool flags[size_t(flag::max_flag)];
- return flags[size_t(in_flag)];
- }
-
- inline bool& settings::flags(flag in_flag)
- {
- return const_cast<bool&>(static_cast<settings const*>(this)->flags(in_flag));
- }
-
- // path implementation
- inline std::string path::home()
- {
+}
+
+inline bool settings::is_zenity() const {
+ return flags(flag::has_zenity) || flags(flag::has_matedialog) || flags(flag::has_qarma);
+}
+
+inline bool settings::is_kdialog() const {
+ return flags(flag::has_kdialog);
+}
+
+inline bool const& settings::flags(flag in_flag) const {
+ static bool flags[size_t(flag::max_flag)];
+ return flags[size_t(in_flag)];
+}
+
+inline bool& settings::flags(flag in_flag) {
+ return const_cast<bool&>(static_cast<settings const*>(this)->flags(in_flag));
+}
+
+// path implementation
+inline std::string path::home() {
#if _WIN32
- // First try the USERPROFILE environment variable
- auto user_profile = internal::getenv("USERPROFILE");
- if (user_profile.size() > 0)
- return user_profile;
- // Otherwise, try GetUserProfileDirectory()
- HANDLE token = nullptr;
- DWORD len = MAX_PATH;
- char buf[MAX_PATH] = {'\0'};
- if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
- {
- dll userenv("userenv.dll");
- dll::proc<BOOL WINAPI(HANDLE, LPSTR, LPDWORD)> get_user_profile_directory(userenv, "GetUserProfileDirectoryA");
- get_user_profile_directory(token, buf, &len);
- CloseHandle(token);
- if (*buf)
- return buf;
- }
+ // First try the USERPROFILE environment variable
+ auto user_profile = internal::getenv("USERPROFILE");
+ if (user_profile.size() > 0) return user_profile;
+ // Otherwise, try GetUserProfileDirectory()
+ HANDLE token = nullptr;
+ DWORD len = MAX_PATH;
+ char buf[MAX_PATH] = {'\0'};
+ if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) {
+ dll userenv("userenv.dll");
+ dll::proc<BOOL WINAPI(HANDLE, LPSTR, LPDWORD)> get_user_profile_directory(
+ userenv, "GetUserProfileDirectoryA");
+ get_user_profile_directory(token, buf, &len);
+ CloseHandle(token);
+ if (*buf) return buf;
+ }
#elif __EMSCRIPTEN__
- return "/";
+ return "/";
#else
- // First try the HOME environment variable
- auto home = internal::getenv("HOME");
- if (home.size() > 0)
- return home;
- // Otherwise, try getpwuid_r()
- size_t len = 4096;
+ // First try the HOME environment variable
+ auto home = internal::getenv("HOME");
+ if (home.size() > 0) return home;
+ // Otherwise, try getpwuid_r()
+ size_t len = 4096;
#if defined(_SC_GETPW_R_SIZE_MAX)
- auto size_max = sysconf(_SC_GETPW_R_SIZE_MAX);
- if (size_max != -1)
- len = size_t(size_max);
+ auto size_max = sysconf(_SC_GETPW_R_SIZE_MAX);
+ if (size_max != -1) len = size_t(size_max);
#endif
- std::vector<char> buf(len);
- struct passwd pwd, *result;
- if (getpwuid_r(getuid(), &pwd, buf.data(), buf.size(), &result) == 0)
- return result->pw_dir;
+ std::vector<char> buf(len);
+ struct passwd pwd, *result;
+ if (getpwuid_r(getuid(), &pwd, buf.data(), buf.size(), &result) == 0) return result->pw_dir;
#endif
- return "/";
- }
+ return "/";
+}
- inline std::string path::separator()
- {
+inline std::string path::separator() {
#if _WIN32
- return "\\";
+ return "\\";
#else
- return "/";
+ return "/";
#endif
- }
+}
- // executor implementation
+// executor implementation
- inline std::string internal::executor::result(int* exit_code /* = nullptr */)
- {
- stop();
- if (exit_code)
- *exit_code = m_exit_code;
- return m_stdout;
- }
+inline std::string internal::executor::result(int* exit_code /* = nullptr */) {
+ stop();
+ if (exit_code) *exit_code = m_exit_code;
+ return m_stdout;
+}
- inline bool internal::executor::kill()
- {
+inline bool internal::executor::kill() {
#if _WIN32
- if (m_future.valid())
- {
- // Close all windows that weren’t open when we started the future
- auto previous_windows = m_windows;
- EnumWindows(&enum_windows_callback, (LPARAM)this);
- for (auto hwnd : m_windows)
- if (previous_windows.find(hwnd) == previous_windows.end())
- {
- SendMessage(hwnd, WM_CLOSE, 0, 0);
- // Also send IDNO in case of a Yes/No or Abort/Retry/Ignore messagebox
- SendMessage(hwnd, WM_COMMAND, IDNO, 0);
- }
- }
+ if (m_future.valid()) {
+ // Close all windows that weren’t open when we started the future
+ auto previous_windows = m_windows;
+ EnumWindows(&enum_windows_callback, (LPARAM) this);
+ for (auto hwnd : m_windows)
+ if (previous_windows.find(hwnd) == previous_windows.end()) {
+ SendMessage(hwnd, WM_CLOSE, 0, 0);
+ // Also send IDNO in case of a Yes/No or Abort/Retry/Ignore messagebox
+ SendMessage(hwnd, WM_COMMAND, IDNO, 0);
+ }
+ }
#elif __EMSCRIPTEN__ || __NX__
- // FIXME: do something
- return false; // cannot kill
+ // FIXME: do something
+ return false; // cannot kill
#else
- ::kill(m_pid, SIGKILL);
+ ::kill(m_pid, SIGKILL);
#endif
- stop();
- return true;
- }
+ stop();
+ return true;
+}
#if _WIN32
- inline BOOL CALLBACK internal::executor::enum_windows_callback(HWND hwnd, LPARAM lParam)
- {
- auto that = (executor*)lParam;
-
- DWORD pid;
- auto tid = GetWindowThreadProcessId(hwnd, &pid);
- if (tid == that->m_tid)
- that->m_windows.insert(hwnd);
- return TRUE;
- }
+inline BOOL CALLBACK internal::executor::enum_windows_callback(HWND hwnd, LPARAM lParam) {
+ auto that = (executor*) lParam;
+
+ DWORD pid;
+ auto tid = GetWindowThreadProcessId(hwnd, &pid);
+ if (tid == that->m_tid) that->m_windows.insert(hwnd);
+ return TRUE;
+}
#endif
#if _WIN32
- inline void internal::executor::start_func(std::function<std::string(int*)> const& fun)
- {
- stop();
-
- auto trampoline = [fun, this]() {
- // Save our thread id so that the caller can cancel us
- m_tid = GetCurrentThreadId();
- EnumWindows(&enum_windows_callback, (LPARAM)this);
- m_cond.notify_all();
- return fun(&m_exit_code);
- };
-
- std::unique_lock<std::mutex> lock(m_mutex);
- m_future = std::async(std::launch::async, trampoline);
- m_cond.wait(lock);
- m_running = true;
- }
+inline void internal::executor::start_func(std::function<std::string(int*)> const& fun) {
+ stop();
+
+ auto trampoline = [fun, this]() {
+ // Save our thread id so that the caller can cancel us
+ m_tid = GetCurrentThreadId();
+ EnumWindows(&enum_windows_callback, (LPARAM) this);
+ m_cond.notify_all();
+ return fun(&m_exit_code);
+ };
+
+ std::unique_lock<std::mutex> lock(m_mutex);
+ m_future = std::async(std::launch::async, trampoline);
+ m_cond.wait(lock);
+ m_running = true;
+}
#elif __EMSCRIPTEN__
- inline void internal::executor::start(int exit_code)
- {
- m_exit_code = exit_code;
- }
+inline void internal::executor::start(int exit_code) {
+ m_exit_code = exit_code;
+}
#else
- inline void internal::executor::start_process(std::vector<std::string> const& command)
- {
- stop();
- m_stdout.clear();
- m_exit_code = -1;
-
- int in[2], out[2];
- if (pipe(in) != 0 || pipe(out) != 0)
- return;
-
- m_pid = fork();
- if (m_pid < 0)
- return;
-
- close(in[m_pid ? 0 : 1]);
- close(out[m_pid ? 1 : 0]);
-
- if (m_pid == 0)
- {
- dup2(in[0], STDIN_FILENO);
- dup2(out[1], STDOUT_FILENO);
-
- // Ignore stderr so that it doesn’t pollute the console (e.g. GTK+ errors from zenity)
- int fd = open("/dev/null", O_WRONLY);
- dup2(fd, STDERR_FILENO);
- close(fd);
-
- std::vector<char*> args;
- std::transform(command.cbegin(), command.cend(), std::back_inserter(args),
- [](std::string const& s) { return const_cast<char*>(s.c_str()); });
- args.push_back(nullptr); // null-terminate argv[]
-
- execvp(args[0], args.data());
- exit(1);
- }
-
- close(in[1]);
- m_fd = out[0];
- auto flags = fcntl(m_fd, F_GETFL);
- fcntl(m_fd, F_SETFL, flags | O_NONBLOCK);
-
- m_running = true;
- }
+inline void internal::executor::start_process(std::vector<std::string> const& command) {
+ stop();
+ m_stdout.clear();
+ m_exit_code = -1;
+
+ int in[2], out[2];
+ if (pipe(in) != 0 || pipe(out) != 0) return;
+
+ m_pid = fork();
+ if (m_pid < 0) return;
+
+ close(in[m_pid ? 0 : 1]);
+ close(out[m_pid ? 1 : 0]);
+
+ if (m_pid == 0) {
+ dup2(in[0], STDIN_FILENO);
+ dup2(out[1], STDOUT_FILENO);
+
+ // Ignore stderr so that it doesn’t pollute the console (e.g. GTK+ errors from zenity)
+ int fd = open("/dev/null", O_WRONLY);
+ dup2(fd, STDERR_FILENO);
+ close(fd);
+
+ std::vector<char*> args;
+ std::transform(command.cbegin(), command.cend(), std::back_inserter(args),
+ [](std::string const& s) { return const_cast<char*>(s.c_str()); });
+ args.push_back(nullptr); // null-terminate argv[]
+
+ execvp(args[0], args.data());
+ exit(1);
+ }
+
+ close(in[1]);
+ m_fd = out[0];
+ auto flags = fcntl(m_fd, F_GETFL);
+ fcntl(m_fd, F_SETFL, flags | O_NONBLOCK);
+
+ m_running = true;
+}
#endif
- inline internal::executor::~executor()
- {
- stop();
- }
+inline internal::executor::~executor() {
+ stop();
+}
- inline bool internal::executor::ready(int timeout /* = default_wait_timeout */)
- {
- if (!m_running)
- return true;
+inline bool internal::executor::ready(int timeout /* = default_wait_timeout */) {
+ if (!m_running) return true;
#if _WIN32
- if (m_future.valid())
- {
- auto status = m_future.wait_for(std::chrono::milliseconds(timeout));
- if (status != std::future_status::ready)
- {
- // On Windows, we need to run the message pump. If the async
- // thread uses a Windows API dialog, it may be attached to the
- // main thread and waiting for messages that only we can dispatch.
- MSG msg;
- while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- return false;
- }
-
- m_stdout = m_future.get();
- }
+ if (m_future.valid()) {
+ auto status = m_future.wait_for(std::chrono::milliseconds(timeout));
+ if (status != std::future_status::ready) {
+ // On Windows, we need to run the message pump. If the async
+ // thread uses a Windows API dialog, it may be attached to the
+ // main thread and waiting for messages that only we can dispatch.
+ MSG msg;
+ while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ return false;
+ }
+
+ m_stdout = m_future.get();
+ }
#elif __EMSCRIPTEN__ || __NX__
- // FIXME: do something
- (void)timeout;
+ // FIXME: do something
+ (void) timeout;
#else
- char buf[BUFSIZ];
- ssize_t received = read(m_fd, buf, BUFSIZ); // Flawfinder: ignore
- if (received > 0)
- {
- m_stdout += std::string(buf, received);
- return false;
- }
-
- // Reap child process if it is dead. It is possible that the system has already reaped it
- // (this happens when the calling application handles or ignores SIG_CHLD) and results in
- // waitpid() failing with ECHILD. Otherwise we assume the child is running and we sleep for
- // a little while.
- int status;
- pid_t child = waitpid(m_pid, &status, WNOHANG);
- if (child != m_pid && (child >= 0 || errno != ECHILD))
- {
- // FIXME: this happens almost always at first iteration
- std::this_thread::sleep_for(std::chrono::milliseconds(timeout));
- return false;
- }
-
- close(m_fd);
- m_exit_code = WEXITSTATUS(status);
+ char buf[BUFSIZ];
+ ssize_t received = read(m_fd, buf, BUFSIZ); // Flawfinder: ignore
+ if (received > 0) {
+ m_stdout += std::string(buf, received);
+ return false;
+ }
+
+ // Reap child process if it is dead. It is possible that the system has already reaped it
+ // (this happens when the calling application handles or ignores SIG_CHLD) and results in
+ // waitpid() failing with ECHILD. Otherwise we assume the child is running and we sleep for
+ // a little while.
+ int status;
+ pid_t child = waitpid(m_pid, &status, WNOHANG);
+ if (child != m_pid && (child >= 0 || errno != ECHILD)) {
+ // FIXME: this happens almost always at first iteration
+ std::this_thread::sleep_for(std::chrono::milliseconds(timeout));
+ return false;
+ }
+
+ close(m_fd);
+ m_exit_code = WEXITSTATUS(status);
#endif
- m_running = false;
- return true;
- }
+ m_running = false;
+ return true;
+}
- inline void internal::executor::stop()
- {
- // Loop until the user closes the dialog
- while (!ready())
- ;
- }
+inline void internal::executor::stop() {
+ // Loop until the user closes the dialog
+ while (!ready());
+}
- // dll implementation
+// dll implementation
#if _WIN32
- inline internal::platform::dll::dll(std::string const& name)
- : handle(::LoadLibraryA(name.c_str()))
- {
- }
+inline internal::platform::dll::dll(std::string const& name)
+ : handle(::LoadLibraryA(name.c_str())) {}
- inline internal::platform::dll::~dll()
- {
- if (handle)
- ::FreeLibrary(handle);
- }
-#endif // _WIN32
+inline internal::platform::dll::~dll() {
+ if (handle) ::FreeLibrary(handle);
+}
+#endif // _WIN32
- // ole32_dll implementation
+// ole32_dll implementation
#if _WIN32
- inline internal::platform::ole32_dll::ole32_dll()
- : dll("ole32.dll")
- {
- // Use COINIT_MULTITHREADED because COINIT_APARTMENTTHREADED causes crashes.
- // See https://github.com/samhocevar/portable-file-dialogs/issues/51
- auto coinit = proc<HRESULT WINAPI(LPVOID, DWORD)>(*this, "CoInitializeEx");
- m_state = coinit(nullptr, COINIT_MULTITHREADED);
- }
-
- inline internal::platform::ole32_dll::~ole32_dll()
- {
- if (is_initialized())
- proc<void WINAPI()>(*this, "CoUninitialize")();
- }
-
- inline bool internal::platform::ole32_dll::is_initialized()
- {
- return m_state == S_OK || m_state == S_FALSE;
- }
+inline internal::platform::ole32_dll::ole32_dll() : dll("ole32.dll") {
+ // Use COINIT_MULTITHREADED because COINIT_APARTMENTTHREADED causes crashes.
+ // See https://github.com/samhocevar/portable-file-dialogs/issues/51
+ auto coinit = proc<HRESULT WINAPI(LPVOID, DWORD)>(*this, "CoInitializeEx");
+ m_state = coinit(nullptr, COINIT_MULTITHREADED);
+}
+
+inline internal::platform::ole32_dll::~ole32_dll() {
+ if (is_initialized()) proc<void WINAPI()>(*this, "CoUninitialize")();
+}
+
+inline bool internal::platform::ole32_dll::is_initialized() {
+ return m_state == S_OK || m_state == S_FALSE;
+}
#endif
- // new_style_context implementation
+// new_style_context implementation
#if _WIN32
- inline internal::platform::new_style_context::new_style_context()
- {
- // Only create one activation context for the whole app lifetime.
- static HANDLE hctx = create();
-
- if (hctx != INVALID_HANDLE_VALUE)
- ActivateActCtx(hctx, &m_cookie);
- }
-
- inline internal::platform::new_style_context::~new_style_context()
- {
- DeactivateActCtx(0, m_cookie);
- }
-
- inline HANDLE internal::platform::new_style_context::create()
- {
- // This “hack” seems to be necessary for this code to work on windows XP.
- // Without it, dialogs do not show and close immediately. GetError()
- // returns 0 so I don’t know what causes this. I was not able to reproduce
- // this behavior on Windows 7 and 10 but just in case, let it be here for
- // those versions too.
- // This hack is not required if other dialogs are used (they load comdlg32
- // automatically), only if message boxes are used.
- dll comdlg32("comdlg32.dll");
-
- // Using approach as shown here: https://stackoverflow.com/a/10444161
- UINT len = ::GetSystemDirectoryA(nullptr, 0);
- std::string sys_dir(len, '\0');
- ::GetSystemDirectoryA(&sys_dir[0], len);
-
- ACTCTXA act_ctx =
- {
- // Do not set flag ACTCTX_FLAG_SET_PROCESS_DEFAULT, since it causes a
- // crash with error “default context is already set”.
- sizeof(act_ctx),
- ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID,
- "shell32.dll",
- 0,
- 0,
- sys_dir.c_str(),
- (LPCSTR)124,
- nullptr,
- 0,
- };
-
- return ::CreateActCtxA(&act_ctx);
- }
-#endif // _WIN32
-
- // dialog implementation
-
- inline bool internal::dialog::ready(int timeout /* = default_wait_timeout */) const
- {
- return m_async->ready(timeout);
- }
-
- inline bool internal::dialog::kill() const
- {
- return m_async->kill();
- }
-
- inline internal::dialog::dialog()
- : m_async(std::make_shared<executor>())
- {
- }
-
- inline std::vector<std::string> internal::dialog::desktop_helper() const
- {
+inline internal::platform::new_style_context::new_style_context() {
+ // Only create one activation context for the whole app lifetime.
+ static HANDLE hctx = create();
+
+ if (hctx != INVALID_HANDLE_VALUE) ActivateActCtx(hctx, &m_cookie);
+}
+
+inline internal::platform::new_style_context::~new_style_context() {
+ DeactivateActCtx(0, m_cookie);
+}
+
+inline HANDLE internal::platform::new_style_context::create() {
+ // This “hack” seems to be necessary for this code to work on windows XP.
+ // Without it, dialogs do not show and close immediately. GetError()
+ // returns 0 so I don’t know what causes this. I was not able to reproduce
+ // this behavior on Windows 7 and 10 but just in case, let it be here for
+ // those versions too.
+ // This hack is not required if other dialogs are used (they load comdlg32
+ // automatically), only if message boxes are used.
+ dll comdlg32("comdlg32.dll");
+
+ // Using approach as shown here: https://stackoverflow.com/a/10444161
+ UINT len = ::GetSystemDirectoryA(nullptr, 0);
+ std::string sys_dir(len, '\0');
+ ::GetSystemDirectoryA(&sys_dir[0], len);
+
+ ACTCTXA act_ctx = {
+ // Do not set flag ACTCTX_FLAG_SET_PROCESS_DEFAULT, since it causes a
+ // crash with error “default context is already set”.
+ sizeof(act_ctx),
+ ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID,
+ "shell32.dll",
+ 0,
+ 0,
+ sys_dir.c_str(),
+ (LPCSTR) 124,
+ nullptr,
+ 0,
+ };
+
+ return ::CreateActCtxA(&act_ctx);
+}
+#endif // _WIN32
+
+// dialog implementation
+
+inline bool internal::dialog::ready(int timeout /* = default_wait_timeout */) const {
+ return m_async->ready(timeout);
+}
+
+inline bool internal::dialog::kill() const {
+ return m_async->kill();
+}
+
+inline internal::dialog::dialog() : m_async(std::make_shared<executor>()) {}
+
+inline std::vector<std::string> internal::dialog::desktop_helper() const {
#if __APPLE__
- return {"osascript"};
+ return {"osascript"};
#else
- return {flags(flag::has_zenity) ? "zenity"
- : flags(flag::has_matedialog) ? "matedialog"
- : flags(flag::has_qarma) ? "qarma"
- : flags(flag::has_kdialog) ? "kdialog"
- : "echo"};
+ return {flags(flag::has_zenity) ? "zenity"
+ : flags(flag::has_matedialog) ? "matedialog"
+ : flags(flag::has_qarma) ? "qarma"
+ : flags(flag::has_kdialog) ? "kdialog"
+ : "echo"};
#endif
- }
-
- inline std::string internal::dialog::buttons_to_name(choice _choice)
- {
- switch (_choice)
- {
- case choice::ok_cancel:
- return "okcancel";
- case choice::yes_no:
- return "yesno";
- case choice::yes_no_cancel:
- return "yesnocancel";
- case choice::retry_cancel:
- return "retrycancel";
- case choice::abort_retry_ignore:
- return "abortretryignore";
- /* case choice::ok: */ default:
- return "ok";
- }
- }
-
- inline std::string internal::dialog::get_icon_name(icon _icon)
- {
- switch (_icon)
- {
- case icon::warning:
- return "warning";
- case icon::error:
- return "error";
- case icon::question:
- return "question";
- // Zenity wants "information" but WinForms wants "info"
- /* case icon::info: */ default:
+}
+
+inline std::string internal::dialog::buttons_to_name(choice _choice) {
+ switch (_choice) {
+ case choice::ok_cancel:
+ return "okcancel";
+ case choice::yes_no:
+ return "yesno";
+ case choice::yes_no_cancel:
+ return "yesnocancel";
+ case choice::retry_cancel:
+ return "retrycancel";
+ case choice::abort_retry_ignore:
+ return "abortretryignore";
+ /* case choice::ok: */ default:
+ return "ok";
+ }
+}
+
+inline std::string internal::dialog::get_icon_name(icon _icon) {
+ switch (_icon) {
+ case icon::warning:
+ return "warning";
+ case icon::error:
+ return "error";
+ case icon::question:
+ return "question";
+ // Zenity wants "information" but WinForms wants "info"
+ /* case icon::info: */ default:
#if _WIN32
- return "info";
+ return "info";
#else
- return "information";
+ return "information";
#endif
- }
- }
-
- // This is only used for debugging purposes
- inline std::ostream& operator<<(std::ostream& s, std::vector<std::string> const& v)
- {
- int not_first = 0;
- for (auto& e : v)
- s << (not_first++ ? " " : "") << e;
- return s;
- }
-
- // Properly quote a string for Powershell: replace ' or " with '' or ""
- // FIXME: we should probably get rid of newlines!
- // FIXME: the \" sequence seems unsafe, too!
- // XXX: this is no longer used but I would like to keep it around just in case
- inline std::string internal::dialog::powershell_quote(std::string const& str) const
- {
- return "'" + std::regex_replace(str, std::regex("['\"]"), "$&$&") + "'";
- }
-
- // Properly quote a string for osascript: replace \ or " with \\ or \"
- // XXX: this also used to replace ' with \' when popen was used, but it would be
- // smarter to do shell_quote(osascript_quote(...)) if this is needed again.
- inline std::string internal::dialog::osascript_quote(std::string const& str) const
- {
- return "\"" + std::regex_replace(str, std::regex("[\\\\\"]"), "\\$&") + "\"";
- }
-
- // Properly quote a string for the shell: just replace ' with '\''
- // XXX: this is no longer used but I would like to keep it around just in case
- inline std::string internal::dialog::shell_quote(std::string const& str) const
- {
- return "'" + std::regex_replace(str, std::regex("'"), "'\\''") + "'";
- }
-
- // file_dialog implementation
-
- inline internal::file_dialog::file_dialog(type in_type,
- std::string const& title,
- std::string const& default_path /* = "" */,
- std::vector<std::string> const& filters /* = {} */,
- opt options /* = opt::none */)
- {
+ }
+}
+
+// This is only used for debugging purposes
+inline std::ostream& operator<<(std::ostream& s, std::vector<std::string> const& v) {
+ int not_first = 0;
+ for (auto& e : v) s << (not_first++ ? " " : "") << e;
+ return s;
+}
+
+// Properly quote a string for Powershell: replace ' or " with '' or ""
+// FIXME: we should probably get rid of newlines!
+// FIXME: the \" sequence seems unsafe, too!
+// XXX: this is no longer used but I would like to keep it around just in case
+inline std::string internal::dialog::powershell_quote(std::string const& str) const {
+ return "'" + std::regex_replace(str, std::regex("['\"]"), "$&$&") + "'";
+}
+
+// Properly quote a string for osascript: replace \ or " with \\ or \"
+// XXX: this also used to replace ' with \' when popen was used, but it would be
+// smarter to do shell_quote(osascript_quote(...)) if this is needed again.
+inline std::string internal::dialog::osascript_quote(std::string const& str) const {
+ return "\"" + std::regex_replace(str, std::regex("[\\\\\"]"), "\\$&") + "\"";
+}
+
+// Properly quote a string for the shell: just replace ' with '\''
+// XXX: this is no longer used but I would like to keep it around just in case
+inline std::string internal::dialog::shell_quote(std::string const& str) const {
+ return "'" + std::regex_replace(str, std::regex("'"), "'\\''") + "'";
+}
+
+// file_dialog implementation
+
+inline internal::file_dialog::file_dialog(type in_type, std::string const& title,
+ std::string const& default_path /* = "" */,
+ std::vector<std::string> const& filters /* = {} */,
+ opt options /* = opt::none */) {
#if _WIN32
- std::string filter_list;
- std::regex whitespace(" *");
- for (size_t i = 0; i + 1 < filters.size(); i += 2)
- {
- filter_list += filters[i] + '\0';
- filter_list += std::regex_replace(filters[i + 1], whitespace, ";") + '\0';
- }
- filter_list += '\0';
-
- m_async->start_func([this, in_type, title, default_path, filter_list,
- options](int* exit_code) -> std::string {
- (void)exit_code;
- m_wtitle = internal::str2wstr(title);
- m_wdefault_path = internal::str2wstr(default_path);
- auto wfilter_list = internal::str2wstr(filter_list);
-
- // Initialise COM. This is required for the new folder selection window,
- // (see https://github.com/samhocevar/portable-file-dialogs/pull/21)
- // and to avoid random crashes with GetOpenFileNameW() (see
- // https://github.com/samhocevar/portable-file-dialogs/issues/51)
- ole32_dll ole32;
-
- // Folder selection uses a different method
- if (in_type == type::folder)
- {
+ std::string filter_list;
+ std::regex whitespace(" *");
+ for (size_t i = 0; i + 1 < filters.size(); i += 2) {
+ filter_list += filters[i] + '\0';
+ filter_list += std::regex_replace(filters[i + 1], whitespace, ";") + '\0';
+ }
+ filter_list += '\0';
+
+ m_async->start_func(
+ [this, in_type, title, default_path, filter_list, options](int* exit_code) -> std::string {
+ (void) exit_code;
+ m_wtitle = internal::str2wstr(title);
+ m_wdefault_path = internal::str2wstr(default_path);
+ auto wfilter_list = internal::str2wstr(filter_list);
+
+ // Initialise COM. This is required for the new folder selection window,
+ // (see https://github.com/samhocevar/portable-file-dialogs/pull/21)
+ // and to avoid random crashes with GetOpenFileNameW() (see
+ // https://github.com/samhocevar/portable-file-dialogs/issues/51)
+ ole32_dll ole32;
+
+ // Folder selection uses a different method
+ if (in_type == type::folder) {
#if PFD_HAS_IFILEDIALOG
- if (flags(flag::is_vista))
- {
- // On Vista and higher we should be able to use IFileDialog for folder selection
- IFileDialog* ifd;
- HRESULT hr = dll::proc<HRESULT WINAPI(REFCLSID, LPUNKNOWN, DWORD, REFIID, LPVOID*)>(ole32, "CoCreateInstance")(CLSID_FileOpenDialog, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&ifd));
-
- // In case CoCreateInstance fails (which it should not), try legacy approach
- if (SUCCEEDED(hr))
- return select_folder_vista(ifd, options & opt::force_path);
- }
+ if (flags(flag::is_vista)) {
+ // On Vista and higher we should be able to use IFileDialog for folder selection
+ IFileDialog* ifd;
+ HRESULT hr = dll::proc<HRESULT WINAPI(REFCLSID, LPUNKNOWN, DWORD, REFIID, LPVOID*)>(
+ ole32, "CoCreateInstance")(CLSID_FileOpenDialog, nullptr, CLSCTX_INPROC_SERVER,
+ IID_PPV_ARGS(&ifd));
+
+ // In case CoCreateInstance fails (which it should not), try legacy approach
+ if (SUCCEEDED(hr)) return select_folder_vista(ifd, options & opt::force_path);
+ }
#endif
- BROWSEINFOW bi;
- memset(&bi, 0, sizeof(bi));
-
- bi.lpfn = &bffcallback;
- bi.lParam = (LPARAM)this;
-
- if (flags(flag::is_vista))
- {
- if (ole32.is_initialized())
- bi.ulFlags |= BIF_NEWDIALOGSTYLE;
- bi.ulFlags |= BIF_EDITBOX;
- bi.ulFlags |= BIF_STATUSTEXT;
- }
-
- auto* list = SHBrowseForFolderW(&bi);
- std::string ret;
- if (list)
- {
- auto buffer = new wchar_t[MAX_PATH];
- SHGetPathFromIDListW(list, buffer);
- dll::proc<void WINAPI(LPVOID)>(ole32, "CoTaskMemFree")(list);
- ret = internal::wstr2str(buffer);
- delete[] buffer;
- }
- return ret;
- }
-
- OPENFILENAMEW ofn;
- memset(&ofn, 0, sizeof(ofn));
- ofn.lStructSize = sizeof(OPENFILENAMEW);
- ofn.hwndOwner = GetActiveWindow();
-
- ofn.lpstrFilter = wfilter_list.c_str();
-
- auto woutput = std::wstring(MAX_PATH * 256, L'\0');
- ofn.lpstrFile = (LPWSTR)woutput.data();
- ofn.nMaxFile = (DWORD)woutput.size();
- if (!m_wdefault_path.empty())
- {
- // If a directory was provided, use it as the initial directory. If
- // a valid path was provided, use it as the initial file. Otherwise,
- // let the Windows API decide.
- auto path_attr = GetFileAttributesW(m_wdefault_path.c_str());
- if (path_attr != INVALID_FILE_ATTRIBUTES && (path_attr & FILE_ATTRIBUTE_DIRECTORY))
- ofn.lpstrInitialDir = m_wdefault_path.c_str();
- else if (m_wdefault_path.size() <= woutput.size())
- //second argument is size of buffer, not length of string
- StringCchCopyW(ofn.lpstrFile, MAX_PATH * 256 + 1, m_wdefault_path.c_str());
- else
- {
- ofn.lpstrFileTitle = (LPWSTR)m_wdefault_path.data();
- ofn.nMaxFileTitle = (DWORD)m_wdefault_path.size();
- }
- }
- ofn.lpstrTitle = m_wtitle.c_str();
- ofn.Flags = OFN_NOCHANGEDIR | OFN_EXPLORER;
-
- dll comdlg32("comdlg32.dll");
-
- // Apply new visual style (required for windows XP)
- new_style_context ctx;
-
- if (in_type == type::save)
- {
- if (!(options & opt::force_overwrite))
- ofn.Flags |= OFN_OVERWRITEPROMPT;
-
- dll::proc<BOOL WINAPI(LPOPENFILENAMEW)> get_save_file_name(comdlg32, "GetSaveFileNameW");
- if (get_save_file_name(&ofn) == 0)
- return "";
- return internal::wstr2str(woutput.c_str());
- }
- else
- {
- if (options & opt::multiselect)
- ofn.Flags |= OFN_ALLOWMULTISELECT;
- ofn.Flags |= OFN_PATHMUSTEXIST;
-
- dll::proc<BOOL WINAPI(LPOPENFILENAMEW)> get_open_file_name(comdlg32, "GetOpenFileNameW");
- if (get_open_file_name(&ofn) == 0)
- return "";
- }
-
- std::string prefix;
- for (wchar_t const* p = woutput.c_str(); *p;)
- {
- auto filename = internal::wstr2str(p);
- p += wcslen(p);
- // In multiselect mode, we advance p one wchar further and
- // check for another filename. If there is one and the
- // prefix is empty, it means we just read the prefix.
- if ((options & opt::multiselect) && *++p && prefix.empty())
- {
- prefix = filename + "/";
- continue;
- }
-
- m_vector_result.push_back(prefix + filename);
- }
-
- return "";
- });
+ BROWSEINFOW bi;
+ memset(&bi, 0, sizeof(bi));
+
+ bi.lpfn = &bffcallback;
+ bi.lParam = (LPARAM) this;
+
+ if (flags(flag::is_vista)) {
+ if (ole32.is_initialized()) bi.ulFlags |= BIF_NEWDIALOGSTYLE;
+ bi.ulFlags |= BIF_EDITBOX;
+ bi.ulFlags |= BIF_STATUSTEXT;
+ }
+
+ auto* list = SHBrowseForFolderW(&bi);
+ std::string ret;
+ if (list) {
+ auto buffer = new wchar_t[MAX_PATH];
+ SHGetPathFromIDListW(list, buffer);
+ dll::proc<void WINAPI(LPVOID)>(ole32, "CoTaskMemFree")(list);
+ ret = internal::wstr2str(buffer);
+ delete[] buffer;
+ }
+ return ret;
+ }
+
+ OPENFILENAMEW ofn;
+ memset(&ofn, 0, sizeof(ofn));
+ ofn.lStructSize = sizeof(OPENFILENAMEW);
+ ofn.hwndOwner = GetActiveWindow();
+
+ ofn.lpstrFilter = wfilter_list.c_str();
+
+ auto woutput = std::wstring(MAX_PATH * 256, L'\0');
+ ofn.lpstrFile = (LPWSTR) woutput.data();
+ ofn.nMaxFile = (DWORD) woutput.size();
+ if (!m_wdefault_path.empty()) {
+ // If a directory was provided, use it as the initial directory. If
+ // a valid path was provided, use it as the initial file. Otherwise,
+ // let the Windows API decide.
+ auto path_attr = GetFileAttributesW(m_wdefault_path.c_str());
+ if (path_attr != INVALID_FILE_ATTRIBUTES && (path_attr & FILE_ATTRIBUTE_DIRECTORY))
+ ofn.lpstrInitialDir = m_wdefault_path.c_str();
+ else if (m_wdefault_path.size() <= woutput.size())
+ // second argument is size of buffer, not length of string
+ StringCchCopyW(ofn.lpstrFile, MAX_PATH * 256 + 1, m_wdefault_path.c_str());
+ else {
+ ofn.lpstrFileTitle = (LPWSTR) m_wdefault_path.data();
+ ofn.nMaxFileTitle = (DWORD) m_wdefault_path.size();
+ }
+ }
+ ofn.lpstrTitle = m_wtitle.c_str();
+ ofn.Flags = OFN_NOCHANGEDIR | OFN_EXPLORER;
+
+ dll comdlg32("comdlg32.dll");
+
+ // Apply new visual style (required for windows XP)
+ new_style_context ctx;
+
+ if (in_type == type::save) {
+ if (!(options & opt::force_overwrite)) ofn.Flags |= OFN_OVERWRITEPROMPT;
+
+ dll::proc<BOOL WINAPI(LPOPENFILENAMEW)> get_save_file_name(comdlg32, "GetSaveFileNameW");
+ if (get_save_file_name(&ofn) == 0) return "";
+ return internal::wstr2str(woutput.c_str());
+ } else {
+ if (options & opt::multiselect) ofn.Flags |= OFN_ALLOWMULTISELECT;
+ ofn.Flags |= OFN_PATHMUSTEXIST;
+
+ dll::proc<BOOL WINAPI(LPOPENFILENAMEW)> get_open_file_name(comdlg32, "GetOpenFileNameW");
+ if (get_open_file_name(&ofn) == 0) return "";
+ }
+
+ std::string prefix;
+ for (wchar_t const* p = woutput.c_str(); *p;) {
+ auto filename = internal::wstr2str(p);
+ p += wcslen(p);
+ // In multiselect mode, we advance p one wchar further and
+ // check for another filename. If there is one and the
+ // prefix is empty, it means we just read the prefix.
+ if ((options & opt::multiselect) && *++p && prefix.empty()) {
+ prefix = filename + "/";
+ continue;
+ }
+
+ m_vector_result.push_back(prefix + filename);
+ }
+
+ return "";
+ });
#elif __EMSCRIPTEN__
- // FIXME: do something
- (void)in_type;
- (void)title;
- (void)default_path;
- (void)filters;
- (void)options;
+ // FIXME: do something
+ (void) in_type;
+ (void) title;
+ (void) default_path;
+ (void) filters;
+ (void) options;
#else
- auto command = desktop_helper();
-
- if (is_osascript())
- {
- std::string script = "set ret to choose";
- switch (in_type)
- {
- case type::save:
- script += " file name";
- break;
- case type::open:
- default:
- script += " file";
- if (options & opt::multiselect)
- script += " with multiple selections allowed";
- break;
- case type::folder:
- script += " folder";
- break;
- }
-
- if (default_path.size())
- {
- if (in_type == type::folder || is_directory(default_path))
- script += " default location ";
- else
- script += " default name ";
- script += osascript_quote(default_path);
- }
-
- script += " with prompt " + osascript_quote(title);
-
- if (in_type == type::open)
- {
- // Concatenate all user-provided filter patterns
- std::string patterns;
- for (size_t i = 0; i < filters.size() / 2; ++i)
- patterns += " " + filters[2 * i + 1];
-
- // Split the pattern list to check whether "*" is in there; if it
- // is, we have to disable filters because there is no mechanism in
- // OS X for the user to override the filter.
- std::regex sep("\\s+");
- std::string filter_list;
- bool has_filter = true;
- std::sregex_token_iterator iter(patterns.begin(), patterns.end(), sep, -1);
- std::sregex_token_iterator end;
- for (; iter != end; ++iter)
- {
- auto pat = iter->str();
- if (pat == "*" || pat == "*.*")
- has_filter = false;
- else if (internal::starts_with(pat, "*."))
- filter_list += "," + osascript_quote(pat.substr(2, pat.size() - 2));
- }
-
- if (has_filter && filter_list.size() > 0)
- {
- // There is a weird AppleScript bug where file extensions of length != 3 are
- // ignored, e.g. type{"txt"} works, but type{"json"} does not. Fortunately if
- // the whole list starts with a 3-character extension, everything works again.
- // We use "///" for such an extension because we are sure it cannot appear in
- // an actual filename.
- script += " of type {\"///\"" + filter_list + "}";
- }
- }
-
- if (in_type == type::open && (options & opt::multiselect))
- {
- script += "\nset s to \"\"";
- script += "\nrepeat with i in ret";
- script += "\n set s to s & (POSIX path of i) & \"\\n\"";
- script += "\nend repeat";
- script += "\ncopy s to stdout";
- }
- else
- {
- script += "\nPOSIX path of ret";
- }
-
- command.push_back("-e");
- command.push_back(script);
- }
- else if (is_zenity())
- {
- command.push_back("--file-selection");
-
- // If the default path is a directory, make sure it ends with "/" otherwise zenity will
- // open the file dialog in the parent directory.
- auto filename_arg = "--filename=" + default_path;
- if (in_type != type::folder && !ends_with(default_path, "/") && internal::is_directory(default_path))
- filename_arg += "/";
- command.push_back(filename_arg);
-
- command.push_back("--title");
- command.push_back(title);
- command.push_back("--separator=\n");
-
- for (size_t i = 0; i < filters.size() / 2; ++i)
- {
- command.push_back("--file-filter");
- command.push_back(filters[2 * i] + "|" + filters[2 * i + 1]);
- }
-
- if (in_type == type::save)
- command.push_back("--save");
- if (in_type == type::folder)
- command.push_back("--directory");
- if (!(options & opt::force_overwrite))
- command.push_back("--confirm-overwrite");
- if (options & opt::multiselect)
- command.push_back("--multiple");
- }
- else if (is_kdialog())
- {
- switch (in_type)
- {
- case type::save:
- command.push_back("--getsavefilename");
- break;
- case type::open:
- command.push_back("--getopenfilename");
- break;
- case type::folder:
- command.push_back("--getexistingdirectory");
- break;
- }
- if (options & opt::multiselect)
- {
- command.push_back("--multiple");
- command.push_back("--separate-output");
- }
-
- command.push_back(default_path);
-
- std::string filter;
- for (size_t i = 0; i < filters.size() / 2; ++i)
- filter += (i == 0 ? "" : " | ") + filters[2 * i] + "(" + filters[2 * i + 1] + ")";
- command.push_back(filter);
-
- command.push_back("--title");
- command.push_back(title);
- }
-
- if (flags(flag::is_verbose))
- std::cerr << "pfd: " << command << std::endl;
-
- m_async->start_process(command);
+ auto command = desktop_helper();
+
+ if (is_osascript()) {
+ std::string script = "set ret to choose";
+ switch (in_type) {
+ case type::save:
+ script += " file name";
+ break;
+ case type::open:
+ default:
+ script += " file";
+ if (options & opt::multiselect) script += " with multiple selections allowed";
+ break;
+ case type::folder:
+ script += " folder";
+ break;
+ }
+
+ if (default_path.size()) {
+ if (in_type == type::folder || is_directory(default_path))
+ script += " default location ";
+ else
+ script += " default name ";
+ script += osascript_quote(default_path);
+ }
+
+ script += " with prompt " + osascript_quote(title);
+
+ if (in_type == type::open) {
+ // Concatenate all user-provided filter patterns
+ std::string patterns;
+ for (size_t i = 0; i < filters.size() / 2; ++i) patterns += " " + filters[2 * i + 1];
+
+ // Split the pattern list to check whether "*" is in there; if it
+ // is, we have to disable filters because there is no mechanism in
+ // OS X for the user to override the filter.
+ std::regex sep("\\s+");
+ std::string filter_list;
+ bool has_filter = true;
+ std::sregex_token_iterator iter(patterns.begin(), patterns.end(), sep, -1);
+ std::sregex_token_iterator end;
+ for (; iter != end; ++iter) {
+ auto pat = iter->str();
+ if (pat == "*" || pat == "*.*")
+ has_filter = false;
+ else if (internal::starts_with(pat, "*."))
+ filter_list += "," + osascript_quote(pat.substr(2, pat.size() - 2));
+ }
+
+ if (has_filter && filter_list.size() > 0) {
+ // There is a weird AppleScript bug where file extensions of length != 3 are
+ // ignored, e.g. type{"txt"} works, but type{"json"} does not. Fortunately if
+ // the whole list starts with a 3-character extension, everything works again.
+ // We use "///" for such an extension because we are sure it cannot appear in
+ // an actual filename.
+ script += " of type {\"///\"" + filter_list + "}";
+ }
+ }
+
+ if (in_type == type::open && (options & opt::multiselect)) {
+ script += "\nset s to \"\"";
+ script += "\nrepeat with i in ret";
+ script += "\n set s to s & (POSIX path of i) & \"\\n\"";
+ script += "\nend repeat";
+ script += "\ncopy s to stdout";
+ } else {
+ script += "\nPOSIX path of ret";
+ }
+
+ command.push_back("-e");
+ command.push_back(script);
+ } else if (is_zenity()) {
+ command.push_back("--file-selection");
+
+ // If the default path is a directory, make sure it ends with "/" otherwise zenity will
+ // open the file dialog in the parent directory.
+ auto filename_arg = "--filename=" + default_path;
+ if (in_type != type::folder && !ends_with(default_path, "/") &&
+ internal::is_directory(default_path))
+ filename_arg += "/";
+ command.push_back(filename_arg);
+
+ command.push_back("--title");
+ command.push_back(title);
+ command.push_back("--separator=\n");
+
+ for (size_t i = 0; i < filters.size() / 2; ++i) {
+ command.push_back("--file-filter");
+ command.push_back(filters[2 * i] + "|" + filters[2 * i + 1]);
+ }
+
+ if (in_type == type::save) command.push_back("--save");
+ if (in_type == type::folder) command.push_back("--directory");
+ if (!(options & opt::force_overwrite)) command.push_back("--confirm-overwrite");
+ if (options & opt::multiselect) command.push_back("--multiple");
+ } else if (is_kdialog()) {
+ switch (in_type) {
+ case type::save:
+ command.push_back("--getsavefilename");
+ break;
+ case type::open:
+ command.push_back("--getopenfilename");
+ break;
+ case type::folder:
+ command.push_back("--getexistingdirectory");
+ break;
+ }
+ if (options & opt::multiselect) {
+ command.push_back("--multiple");
+ command.push_back("--separate-output");
+ }
+
+ command.push_back(default_path);
+
+ std::string filter;
+ for (size_t i = 0; i < filters.size() / 2; ++i)
+ filter += (i == 0 ? "" : " | ") + filters[2 * i] + "(" + filters[2 * i + 1] + ")";
+ command.push_back(filter);
+
+ command.push_back("--title");
+ command.push_back(title);
+ }
+
+ if (flags(flag::is_verbose)) std::cerr << "pfd: " << command << std::endl;
+
+ m_async->start_process(command);
#endif
- }
+}
- inline std::string internal::file_dialog::string_result()
- {
+inline std::string internal::file_dialog::string_result() {
#if _WIN32
- return m_async->result();
+ return m_async->result();
#else
- auto ret = m_async->result();
- // Strip potential trailing newline (zenity). Also strip trailing slash
- // added by osascript for consistency with other backends.
- while (!ret.empty() && (ret.back() == '\n' || ret.back() == '/'))
- ret.pop_back();
- return ret;
+ auto ret = m_async->result();
+ // Strip potential trailing newline (zenity). Also strip trailing slash
+ // added by osascript for consistency with other backends.
+ while (!ret.empty() && (ret.back() == '\n' || ret.back() == '/')) ret.pop_back();
+ return ret;
#endif
- }
+}
- inline std::vector<std::string> internal::file_dialog::vector_result()
- {
+inline std::vector<std::string> internal::file_dialog::vector_result() {
#if _WIN32
- m_async->result();
- return m_vector_result;
+ m_async->result();
+ return m_vector_result;
#else
- std::vector<std::string> ret;
- auto result = m_async->result();
- for (;;)
- {
- // Split result along newline characters
- auto i = result.find('\n');
- if (i == 0 || i == std::string::npos)
- break;
- ret.push_back(result.substr(0, i));
- result = result.substr(i + 1, result.size());
- }
- return ret;
+ std::vector<std::string> ret;
+ auto result = m_async->result();
+ for (;;) {
+ // Split result along newline characters
+ auto i = result.find('\n');
+ if (i == 0 || i == std::string::npos) break;
+ ret.push_back(result.substr(0, i));
+ result = result.substr(i + 1, result.size());
+ }
+ return ret;
#endif
- }
+}
#if _WIN32
- // Use a static function to pass as BFFCALLBACK for legacy folder select
- inline int CALLBACK internal::file_dialog::bffcallback(HWND hwnd, UINT uMsg, LPARAM, LPARAM pData)
- {
- auto inst = (file_dialog*)pData;
- switch (uMsg)
- {
- case BFFM_INITIALIZED:
- SendMessage(hwnd, BFFM_SETSELECTIONW, TRUE, (LPARAM)inst->m_wdefault_path.c_str());
- break;
- }
- return 0;
- }
+// Use a static function to pass as BFFCALLBACK for legacy folder select
+inline int CALLBACK internal::file_dialog::bffcallback(HWND hwnd, UINT uMsg, LPARAM, LPARAM pData) {
+ auto inst = (file_dialog*) pData;
+ switch (uMsg) {
+ case BFFM_INITIALIZED:
+ SendMessage(hwnd, BFFM_SETSELECTIONW, TRUE, (LPARAM) inst->m_wdefault_path.c_str());
+ break;
+ }
+ return 0;
+}
#if PFD_HAS_IFILEDIALOG
- inline std::string internal::file_dialog::select_folder_vista(IFileDialog* ifd, bool force_path)
- {
- std::string result;
-
- IShellItem* folder;
-
- // Load library at runtime so app doesn't link it at load time (which will fail on windows XP)
- dll shell32("shell32.dll");
- dll::proc<HRESULT WINAPI(PCWSTR, IBindCtx*, REFIID, void**)>
- create_item(shell32, "SHCreateItemFromParsingName");
-
- if (!create_item)
- return "";
-
- auto hr = create_item(m_wdefault_path.c_str(),
- nullptr,
- IID_PPV_ARGS(&folder));
-
- // Set default folder if found. This only sets the default folder. If
- // Windows has any info about the most recently selected folder, it
- // will display it instead. Generally, calling SetFolder() to set the
- // current directory “is not a good or expected user experience and
- // should therefore be avoided”:
- // https://docs.microsoft.com/windows/win32/api/shobjidl_core/nf-shobjidl_core-ifiledialog-setfolder
- if (SUCCEEDED(hr))
- {
- if (force_path)
- ifd->SetFolder(folder);
- else
- ifd->SetDefaultFolder(folder);
- folder->Release();
- }
-
- // Set the dialog title and option to select folders
- ifd->SetOptions(FOS_PICKFOLDERS | FOS_FORCEFILESYSTEM);
- ifd->SetTitle(m_wtitle.c_str());
-
- hr = ifd->Show(GetActiveWindow());
- if (SUCCEEDED(hr))
- {
- IShellItem* item;
- hr = ifd->GetResult(&item);
- if (SUCCEEDED(hr))
- {
- wchar_t* wname = nullptr;
- // This is unlikely to fail because we use FOS_FORCEFILESYSTEM, but try
- // to output a debug message just in case.
- if (SUCCEEDED(item->GetDisplayName(SIGDN_FILESYSPATH, &wname)))
- {
- result = internal::wstr2str(std::wstring(wname));
- dll::proc<void WINAPI(LPVOID)>(ole32_dll(), "CoTaskMemFree")(wname);
- }
- else
- {
- if (SUCCEEDED(item->GetDisplayName(SIGDN_NORMALDISPLAY, &wname)))
- {
- auto name = internal::wstr2str(std::wstring(wname));
- dll::proc<void WINAPI(LPVOID)>(ole32_dll(), "CoTaskMemFree")(wname);
- std::cerr << "pfd: failed to get path for " << name << std::endl;
- }
- else
- std::cerr << "pfd: item of unknown type selected" << std::endl;
- }
-
- item->Release();
- }
- }
-
- ifd->Release();
-
- return result;
- }
+inline std::string internal::file_dialog::select_folder_vista(IFileDialog* ifd, bool force_path) {
+ std::string result;
+
+ IShellItem* folder;
+
+ // Load library at runtime so app doesn't link it at load time (which will fail on windows XP)
+ dll shell32("shell32.dll");
+ dll::proc<HRESULT WINAPI(PCWSTR, IBindCtx*, REFIID, void**)> create_item(
+ shell32, "SHCreateItemFromParsingName");
+
+ if (!create_item) return "";
+
+ auto hr = create_item(m_wdefault_path.c_str(), nullptr, IID_PPV_ARGS(&folder));
+
+ // Set default folder if found. This only sets the default folder. If
+ // Windows has any info about the most recently selected folder, it
+ // will display it instead. Generally, calling SetFolder() to set the
+ // current directory “is not a good or expected user experience and
+ // should therefore be avoided”:
+ // https://docs.microsoft.com/windows/win32/api/shobjidl_core/nf-shobjidl_core-ifiledialog-setfolder
+ if (SUCCEEDED(hr)) {
+ if (force_path)
+ ifd->SetFolder(folder);
+ else
+ ifd->SetDefaultFolder(folder);
+ folder->Release();
+ }
+
+ // Set the dialog title and option to select folders
+ ifd->SetOptions(FOS_PICKFOLDERS | FOS_FORCEFILESYSTEM);
+ ifd->SetTitle(m_wtitle.c_str());
+
+ hr = ifd->Show(GetActiveWindow());
+ if (SUCCEEDED(hr)) {
+ IShellItem* item;
+ hr = ifd->GetResult(&item);
+ if (SUCCEEDED(hr)) {
+ wchar_t* wname = nullptr;
+ // This is unlikely to fail because we use FOS_FORCEFILESYSTEM, but try
+ // to output a debug message just in case.
+ if (SUCCEEDED(item->GetDisplayName(SIGDN_FILESYSPATH, &wname))) {
+ result = internal::wstr2str(std::wstring(wname));
+ dll::proc<void WINAPI(LPVOID)>(ole32_dll(), "CoTaskMemFree")(wname);
+ } else {
+ if (SUCCEEDED(item->GetDisplayName(SIGDN_NORMALDISPLAY, &wname))) {
+ auto name = internal::wstr2str(std::wstring(wname));
+ dll::proc<void WINAPI(LPVOID)>(ole32_dll(), "CoTaskMemFree")(wname);
+ std::cerr << "pfd: failed to get path for " << name << std::endl;
+ } else
+ std::cerr << "pfd: item of unknown type selected" << std::endl;
+ }
+
+ item->Release();
+ }
+ }
+
+ ifd->Release();
+
+ return result;
+}
#endif
#endif
- // notify implementation
+// notify implementation
- inline notify::notify(std::string const& title,
- std::string const& message,
- icon _icon /* = icon::info */)
- {
- if (_icon == icon::question) // Not supported by notifications
- _icon = icon::info;
+inline notify::notify(std::string const& title, std::string const& message,
+ icon _icon /* = icon::info */) {
+ if (_icon == icon::question) // Not supported by notifications
+ _icon = icon::info;
#if _WIN32
- // Use a static shared pointer for notify_icon so that we can delete
- // it whenever we need to display a new one, and we can also wait
- // until the program has finished running.
- struct notify_icon_data : public NOTIFYICONDATAW
- {
- ~notify_icon_data()
- {
- Shell_NotifyIconW(NIM_DELETE, this);
- }
- };
-
- static std::shared_ptr<notify_icon_data> nid;
-
- // Release the previous notification icon, if any, and allocate a new
- // one. Note that std::make_shared() does value initialization, so there
- // is no need to memset the structure.
- nid = nullptr;
- nid = std::make_shared<notify_icon_data>();
-
- // For XP support
- nid->cbSize = NOTIFYICONDATAW_V2_SIZE;
- nid->hWnd = nullptr;
- nid->uID = 0;
-
- // Flag Description:
- // - NIF_ICON The hIcon member is valid.
- // - NIF_MESSAGE The uCallbackMessage member is valid.
- // - NIF_TIP The szTip member is valid.
- // - NIF_STATE The dwState and dwStateMask members are valid.
- // - NIF_INFO Use a balloon ToolTip instead of a standard ToolTip. The szInfo, uTimeout, szInfoTitle, and dwInfoFlags members are valid.
- // - NIF_GUID Reserved.
- nid->uFlags = NIF_MESSAGE | NIF_ICON | NIF_INFO;
-
- // Flag Description
- // - NIIF_ERROR An error icon.
- // - NIIF_INFO An information icon.
- // - NIIF_NONE No icon.
- // - NIIF_WARNING A warning icon.
- // - NIIF_ICON_MASK Version 6.0. Reserved.
- // - NIIF_NOSOUND Version 6.0. Do not play the associated sound. Applies only to balloon ToolTips
- switch (_icon)
- {
- case icon::warning:
- nid->dwInfoFlags = NIIF_WARNING;
- break;
- case icon::error:
- nid->dwInfoFlags = NIIF_ERROR;
- break;
- /* case icon::info: */ default:
- nid->dwInfoFlags = NIIF_INFO;
- break;
- }
-
- ENUMRESNAMEPROC icon_enum_callback = [](HMODULE, LPCTSTR, LPTSTR lpName, LONG_PTR lParam) -> BOOL {
- ((NOTIFYICONDATAW*)lParam)->hIcon = ::LoadIcon(GetModuleHandle(nullptr), lpName);
- return false;
- };
-
- nid->hIcon = ::LoadIcon(nullptr, IDI_APPLICATION);
- ::EnumResourceNames(nullptr, RT_GROUP_ICON, icon_enum_callback, (LONG_PTR)nid.get());
-
- nid->uTimeout = 5000;
-
- StringCchCopyW(nid->szInfoTitle, ARRAYSIZE(nid->szInfoTitle), internal::str2wstr(title).c_str());
- StringCchCopyW(nid->szInfo, ARRAYSIZE(nid->szInfo), internal::str2wstr(message).c_str());
-
- // Display the new icon
- Shell_NotifyIconW(NIM_ADD, nid.get());
+ // Use a static shared pointer for notify_icon so that we can delete
+ // it whenever we need to display a new one, and we can also wait
+ // until the program has finished running.
+ struct notify_icon_data : public NOTIFYICONDATAW {
+ ~notify_icon_data() { Shell_NotifyIconW(NIM_DELETE, this); }
+ };
+
+ static std::shared_ptr<notify_icon_data> nid;
+
+ // Release the previous notification icon, if any, and allocate a new
+ // one. Note that std::make_shared() does value initialization, so there
+ // is no need to memset the structure.
+ nid = nullptr;
+ nid = std::make_shared<notify_icon_data>();
+
+ // For XP support
+ nid->cbSize = NOTIFYICONDATAW_V2_SIZE;
+ nid->hWnd = nullptr;
+ nid->uID = 0;
+
+ // Flag Description:
+ // - NIF_ICON The hIcon member is valid.
+ // - NIF_MESSAGE The uCallbackMessage member is valid.
+ // - NIF_TIP The szTip member is valid.
+ // - NIF_STATE The dwState and dwStateMask members are valid.
+ // - NIF_INFO Use a balloon ToolTip instead of a standard ToolTip. The szInfo, uTimeout,
+ // szInfoTitle, and dwInfoFlags members are valid.
+ // - NIF_GUID Reserved.
+ nid->uFlags = NIF_MESSAGE | NIF_ICON | NIF_INFO;
+
+ // Flag Description
+ // - NIIF_ERROR An error icon.
+ // - NIIF_INFO An information icon.
+ // - NIIF_NONE No icon.
+ // - NIIF_WARNING A warning icon.
+ // - NIIF_ICON_MASK Version 6.0. Reserved.
+ // - NIIF_NOSOUND Version 6.0. Do not play the associated sound. Applies only to balloon
+ // ToolTips
+ switch (_icon) {
+ case icon::warning:
+ nid->dwInfoFlags = NIIF_WARNING;
+ break;
+ case icon::error:
+ nid->dwInfoFlags = NIIF_ERROR;
+ break;
+ /* case icon::info: */ default:
+ nid->dwInfoFlags = NIIF_INFO;
+ break;
+ }
+
+ ENUMRESNAMEPROC icon_enum_callback = [](HMODULE, LPCTSTR, LPTSTR lpName,
+ LONG_PTR lParam) -> BOOL {
+ ((NOTIFYICONDATAW*) lParam)->hIcon = ::LoadIcon(GetModuleHandle(nullptr), lpName);
+ return false;
+ };
+
+ nid->hIcon = ::LoadIcon(nullptr, IDI_APPLICATION);
+ ::EnumResourceNames(nullptr, RT_GROUP_ICON, icon_enum_callback, (LONG_PTR) nid.get());
+
+ nid->uTimeout = 5000;
+
+ StringCchCopyW(nid->szInfoTitle, ARRAYSIZE(nid->szInfoTitle), internal::str2wstr(title).c_str());
+ StringCchCopyW(nid->szInfo, ARRAYSIZE(nid->szInfo), internal::str2wstr(message).c_str());
+
+ // Display the new icon
+ Shell_NotifyIconW(NIM_ADD, nid.get());
#elif __EMSCRIPTEN__
- // FIXME: do something
- (void)title;
- (void)message;
+ // FIXME: do something
+ (void) title;
+ (void) message;
#else
- auto command = desktop_helper();
-
- if (is_osascript())
- {
- command.push_back("-e");
- command.push_back("display notification " + osascript_quote(message) +
- " with title " + osascript_quote(title));
- }
- else if (is_zenity())
- {
- command.push_back("--notification");
- command.push_back("--window-icon");
- command.push_back(get_icon_name(_icon));
- command.push_back("--text");
- command.push_back(title + "\n" + message);
- }
- else if (is_kdialog())
- {
- command.push_back("--icon");
- command.push_back(get_icon_name(_icon));
- command.push_back("--title");
- command.push_back(title);
- command.push_back("--passivepopup");
- command.push_back(message);
- command.push_back("5");
- }
-
- if (flags(flag::is_verbose))
- std::cerr << "pfd: " << command << std::endl;
-
- m_async->start_process(command);
+ auto command = desktop_helper();
+
+ if (is_osascript()) {
+ command.push_back("-e");
+ command.push_back("display notification " + osascript_quote(message) + " with title " +
+ osascript_quote(title));
+ } else if (is_zenity()) {
+ command.push_back("--notification");
+ command.push_back("--window-icon");
+ command.push_back(get_icon_name(_icon));
+ command.push_back("--text");
+ command.push_back(title + "\n" + message);
+ } else if (is_kdialog()) {
+ command.push_back("--icon");
+ command.push_back(get_icon_name(_icon));
+ command.push_back("--title");
+ command.push_back(title);
+ command.push_back("--passivepopup");
+ command.push_back(message);
+ command.push_back("5");
+ }
+
+ if (flags(flag::is_verbose)) std::cerr << "pfd: " << command << std::endl;
+
+ m_async->start_process(command);
#endif
- }
+}
- // message implementation
+// message implementation
- inline message::message(std::string const& title,
- std::string const& text,
- choice _choice /* = choice::ok_cancel */,
- icon _icon /* = icon::info */)
- {
+inline message::message(std::string const& title, std::string const& text,
+ choice _choice /* = choice::ok_cancel */, icon _icon /* = icon::info */) {
#if _WIN32
- // Use MB_SYSTEMMODAL rather than MB_TOPMOST to ensure the message window is brought
- // to front. See https://github.com/samhocevar/portable-file-dialogs/issues/52
- UINT style = MB_SYSTEMMODAL;
- switch (_icon)
- {
- case icon::warning:
- style |= MB_ICONWARNING;
- break;
- case icon::error:
- style |= MB_ICONERROR;
- break;
- case icon::question:
- style |= MB_ICONQUESTION;
- break;
- /* case icon::info: */ default:
- style |= MB_ICONINFORMATION;
- break;
- }
-
- switch (_choice)
- {
- case choice::ok_cancel:
- style |= MB_OKCANCEL;
- break;
- case choice::yes_no:
- style |= MB_YESNO;
- break;
- case choice::yes_no_cancel:
- style |= MB_YESNOCANCEL;
- break;
- case choice::retry_cancel:
- style |= MB_RETRYCANCEL;
- break;
- case choice::abort_retry_ignore:
- style |= MB_ABORTRETRYIGNORE;
- break;
- /* case choice::ok: */ default:
- style |= MB_OK;
- break;
- }
-
- m_mappings[IDCANCEL] = button::cancel;
- m_mappings[IDOK] = button::ok;
- m_mappings[IDYES] = button::yes;
- m_mappings[IDNO] = button::no;
- m_mappings[IDABORT] = button::abort;
- m_mappings[IDRETRY] = button::retry;
- m_mappings[IDIGNORE] = button::ignore;
-
- m_async->start_func([text, title, style](int* exit_code) -> std::string {
- auto wtext = internal::str2wstr(text);
- auto wtitle = internal::str2wstr(title);
- // Apply new visual style (required for all Windows versions)
- new_style_context ctx;
- *exit_code = MessageBoxW(GetActiveWindow(), wtext.c_str(), wtitle.c_str(), style);
- return "";
- });
+ // Use MB_SYSTEMMODAL rather than MB_TOPMOST to ensure the message window is brought
+ // to front. See https://github.com/samhocevar/portable-file-dialogs/issues/52
+ UINT style = MB_SYSTEMMODAL;
+ switch (_icon) {
+ case icon::warning:
+ style |= MB_ICONWARNING;
+ break;
+ case icon::error:
+ style |= MB_ICONERROR;
+ break;
+ case icon::question:
+ style |= MB_ICONQUESTION;
+ break;
+ /* case icon::info: */ default:
+ style |= MB_ICONINFORMATION;
+ break;
+ }
+
+ switch (_choice) {
+ case choice::ok_cancel:
+ style |= MB_OKCANCEL;
+ break;
+ case choice::yes_no:
+ style |= MB_YESNO;
+ break;
+ case choice::yes_no_cancel:
+ style |= MB_YESNOCANCEL;
+ break;
+ case choice::retry_cancel:
+ style |= MB_RETRYCANCEL;
+ break;
+ case choice::abort_retry_ignore:
+ style |= MB_ABORTRETRYIGNORE;
+ break;
+ /* case choice::ok: */ default:
+ style |= MB_OK;
+ break;
+ }
+
+ m_mappings[IDCANCEL] = button::cancel;
+ m_mappings[IDOK] = button::ok;
+ m_mappings[IDYES] = button::yes;
+ m_mappings[IDNO] = button::no;
+ m_mappings[IDABORT] = button::abort;
+ m_mappings[IDRETRY] = button::retry;
+ m_mappings[IDIGNORE] = button::ignore;
+
+ m_async->start_func([text, title, style](int* exit_code) -> std::string {
+ auto wtext = internal::str2wstr(text);
+ auto wtitle = internal::str2wstr(title);
+ // Apply new visual style (required for all Windows versions)
+ new_style_context ctx;
+ *exit_code = MessageBoxW(GetActiveWindow(), wtext.c_str(), wtitle.c_str(), style);
+ return "";
+ });
#elif __EMSCRIPTEN__
- std::string full_message;
- switch (_icon)
- {
- case icon::warning:
- full_message = "⚠️";
- break;
- case icon::error:
- full_message = "⛔";
- break;
- case icon::question:
- full_message = "❓";
- break;
- /* case icon::info: */ default:
- full_message = "ℹ";
- break;
- }
-
- full_message += ' ' + title + "\n\n" + text;
-
- // This does not really start an async task; it just passes the
- // EM_ASM_INT return value to a fake start() function.
- m_async->start(EM_ASM_INT(
- {
- if ($1)
- return window.confirm(UTF8ToString($0)) ? 0 : -1;
- alert(UTF8ToString($0));
- return 0;
- },
- full_message.c_str(), _choice == choice::ok_cancel));
+ std::string full_message;
+ switch (_icon) {
+ case icon::warning:
+ full_message = "⚠️";
+ break;
+ case icon::error:
+ full_message = "⛔";
+ break;
+ case icon::question:
+ full_message = "❓";
+ break;
+ /* case icon::info: */ default:
+ full_message = "ℹ";
+ break;
+ }
+
+ full_message += ' ' + title + "\n\n" + text;
+
+ // This does not really start an async task; it just passes the
+ // EM_ASM_INT return value to a fake start() function.
+ m_async->start(EM_ASM_INT(
+ {
+ if ($1) return window.confirm(UTF8ToString($0)) ? 0 : -1;
+ alert(UTF8ToString($0));
+ return 0;
+ },
+ full_message.c_str(), _choice == choice::ok_cancel));
#else
- auto command = desktop_helper();
-
- if (is_osascript())
- {
- std::string script = "display dialog " + osascript_quote(text) +
- " with title " + osascript_quote(title);
- auto if_cancel = button::cancel;
- switch (_choice)
- {
- case choice::ok_cancel:
- script += "buttons {\"OK\", \"Cancel\"}"
- " default button \"OK\""
- " cancel button \"Cancel\"";
- break;
- case choice::yes_no:
- script += "buttons {\"Yes\", \"No\"}"
- " default button \"Yes\""
- " cancel button \"No\"";
- if_cancel = button::no;
- break;
- case choice::yes_no_cancel:
- script += "buttons {\"Yes\", \"No\", \"Cancel\"}"
- " default button \"Yes\""
- " cancel button \"Cancel\"";
- break;
- case choice::retry_cancel:
- script += "buttons {\"Retry\", \"Cancel\"}"
- " default button \"Retry\""
- " cancel button \"Cancel\"";
- break;
- case choice::abort_retry_ignore:
- script += "buttons {\"Abort\", \"Retry\", \"Ignore\"}"
- " default button \"Abort\""
- " cancel button \"Retry\"";
- if_cancel = button::retry;
- break;
- case choice::ok:
- default:
- script += "buttons {\"OK\"}"
- " default button \"OK\""
- " cancel button \"OK\"";
- if_cancel = button::ok;
- break;
- }
- m_mappings[1] = if_cancel;
- m_mappings[256] = if_cancel; // XXX: I think this was never correct
- script += " with icon ";
- switch (_icon)
- {
-#define PFD_OSX_ICON(n) "alias ((path to library folder from system domain) as text " \
- "& \"CoreServices:CoreTypes.bundle:Contents:Resources:" n ".icns\")"
- case icon::info:
- default:
- script += PFD_OSX_ICON("ToolBarInfo");
- break;
- case icon::warning:
- script += "caution";
- break;
- case icon::error:
- script += "stop";
- break;
- case icon::question:
- script += PFD_OSX_ICON("GenericQuestionMarkIcon");
- break;
+ auto command = desktop_helper();
+
+ if (is_osascript()) {
+ std::string script =
+ "display dialog " + osascript_quote(text) + " with title " + osascript_quote(title);
+ auto if_cancel = button::cancel;
+ switch (_choice) {
+ case choice::ok_cancel:
+ script +=
+ "buttons {\"OK\", \"Cancel\"}"
+ " default button \"OK\""
+ " cancel button \"Cancel\"";
+ break;
+ case choice::yes_no:
+ script +=
+ "buttons {\"Yes\", \"No\"}"
+ " default button \"Yes\""
+ " cancel button \"No\"";
+ if_cancel = button::no;
+ break;
+ case choice::yes_no_cancel:
+ script +=
+ "buttons {\"Yes\", \"No\", \"Cancel\"}"
+ " default button \"Yes\""
+ " cancel button \"Cancel\"";
+ break;
+ case choice::retry_cancel:
+ script +=
+ "buttons {\"Retry\", \"Cancel\"}"
+ " default button \"Retry\""
+ " cancel button \"Cancel\"";
+ break;
+ case choice::abort_retry_ignore:
+ script +=
+ "buttons {\"Abort\", \"Retry\", \"Ignore\"}"
+ " default button \"Abort\""
+ " cancel button \"Retry\"";
+ if_cancel = button::retry;
+ break;
+ case choice::ok:
+ default:
+ script +=
+ "buttons {\"OK\"}"
+ " default button \"OK\""
+ " cancel button \"OK\"";
+ if_cancel = button::ok;
+ break;
+ }
+ m_mappings[1] = if_cancel;
+ m_mappings[256] = if_cancel; // XXX: I think this was never correct
+ script += " with icon ";
+ switch (_icon) {
+#define PFD_OSX_ICON(n) \
+ "alias ((path to library folder from system domain) as text " \
+ "& \"CoreServices:CoreTypes.bundle:Contents:Resources:" n ".icns\")"
+ case icon::info:
+ default:
+ script += PFD_OSX_ICON("ToolBarInfo");
+ break;
+ case icon::warning:
+ script += "caution";
+ break;
+ case icon::error:
+ script += "stop";
+ break;
+ case icon::question:
+ script += PFD_OSX_ICON("GenericQuestionMarkIcon");
+ break;
#undef PFD_OSX_ICON
- }
-
- command.push_back("-e");
- command.push_back(script);
- }
- else if (is_zenity())
- {
- switch (_choice)
- {
- case choice::ok_cancel:
- command.insert(command.end(), {"--question", "--cancel-label=Cancel", "--ok-label=OK"});
- break;
- case choice::yes_no:
- // Do not use standard --question because it causes “No” to return -1,
- // which is inconsistent with the “Yes/No/Cancel” mode below.
- command.insert(command.end(), {"--question", "--switch", "--extra-button=No", "--extra-button=Yes"});
- break;
- case choice::yes_no_cancel:
- command.insert(command.end(), {"--question", "--switch", "--extra-button=Cancel", "--extra-button=No", "--extra-button=Yes"});
- break;
- case choice::retry_cancel:
- command.insert(command.end(), {"--question", "--switch", "--extra-button=Cancel", "--extra-button=Retry"});
- break;
- case choice::abort_retry_ignore:
- command.insert(command.end(), {"--question", "--switch", "--extra-button=Ignore", "--extra-button=Abort", "--extra-button=Retry"});
- break;
- case choice::ok:
- default:
- switch (_icon)
- {
- case icon::error:
- command.push_back("--error");
- break;
- case icon::warning:
- command.push_back("--warning");
- break;
- default:
- command.push_back("--info");
- break;
- }
- }
-
- command.insert(command.end(), {"--title", title,
- "--width=300", "--height=0", // sensible defaults
- "--no-markup", // do not interpret text as Pango markup
- "--text", text,
- "--icon-name=dialog-" + get_icon_name(_icon)});
- }
- else if (is_kdialog())
- {
- if (_choice == choice::ok)
- {
- switch (_icon)
- {
- case icon::error:
- command.push_back("--error");
- break;
- case icon::warning:
- command.push_back("--sorry");
- break;
- default:
- command.push_back("--msgbox");
- break;
- }
- }
- else
- {
- std::string flag = "--";
- if (_icon == icon::warning || _icon == icon::error)
- flag += "warning";
- flag += "yesno";
- if (_choice == choice::yes_no_cancel)
- flag += "cancel";
- command.push_back(flag);
- if (_choice == choice::yes_no || _choice == choice::yes_no_cancel)
- {
- m_mappings[0] = button::yes;
- m_mappings[256] = button::no;
- }
- }
-
- command.push_back(text);
- command.push_back("--title");
- command.push_back(title);
-
- // Must be after the above part
- if (_choice == choice::ok_cancel)
- command.insert(command.end(), {"--yes-label", "OK", "--no-label", "Cancel"});
- }
-
- if (flags(flag::is_verbose))
- std::cerr << "pfd: " << command << std::endl;
-
- m_async->start_process(command);
+ }
+
+ command.push_back("-e");
+ command.push_back(script);
+ } else if (is_zenity()) {
+ switch (_choice) {
+ case choice::ok_cancel:
+ command.insert(command.end(), {"--question", "--cancel-label=Cancel", "--ok-label=OK"});
+ break;
+ case choice::yes_no:
+ // Do not use standard --question because it causes “No” to return -1,
+ // which is inconsistent with the “Yes/No/Cancel” mode below.
+ command.insert(command.end(),
+ {"--question", "--switch", "--extra-button=No", "--extra-button=Yes"});
+ break;
+ case choice::yes_no_cancel:
+ command.insert(command.end(), {"--question", "--switch", "--extra-button=Cancel",
+ "--extra-button=No", "--extra-button=Yes"});
+ break;
+ case choice::retry_cancel:
+ command.insert(command.end(),
+ {"--question", "--switch", "--extra-button=Cancel", "--extra-button=Retry"});
+ break;
+ case choice::abort_retry_ignore:
+ command.insert(command.end(), {"--question", "--switch", "--extra-button=Ignore",
+ "--extra-button=Abort", "--extra-button=Retry"});
+ break;
+ case choice::ok:
+ default:
+ switch (_icon) {
+ case icon::error:
+ command.push_back("--error");
+ break;
+ case icon::warning:
+ command.push_back("--warning");
+ break;
+ default:
+ command.push_back("--info");
+ break;
+ }
+ }
+
+ command.insert(command.end(),
+ {"--title", title, "--width=300", "--height=0", // sensible defaults
+ "--no-markup", // do not interpret text as Pango markup
+ "--text", text, "--icon-name=dialog-" + get_icon_name(_icon)});
+ } else if (is_kdialog()) {
+ if (_choice == choice::ok) {
+ switch (_icon) {
+ case icon::error:
+ command.push_back("--error");
+ break;
+ case icon::warning:
+ command.push_back("--sorry");
+ break;
+ default:
+ command.push_back("--msgbox");
+ break;
+ }
+ } else {
+ std::string flag = "--";
+ if (_icon == icon::warning || _icon == icon::error) flag += "warning";
+ flag += "yesno";
+ if (_choice == choice::yes_no_cancel) flag += "cancel";
+ command.push_back(flag);
+ if (_choice == choice::yes_no || _choice == choice::yes_no_cancel) {
+ m_mappings[0] = button::yes;
+ m_mappings[256] = button::no;
+ }
+ }
+
+ command.push_back(text);
+ command.push_back("--title");
+ command.push_back(title);
+
+ // Must be after the above part
+ if (_choice == choice::ok_cancel)
+ command.insert(command.end(), {"--yes-label", "OK", "--no-label", "Cancel"});
+ }
+
+ if (flags(flag::is_verbose)) std::cerr << "pfd: " << command << std::endl;
+
+ m_async->start_process(command);
#endif
- }
-
- inline button message::result()
- {
- int exit_code;
- auto ret = m_async->result(&exit_code);
- // osascript will say "button returned:Cancel\n"
- // and others will just say "Cancel\n"
- if (internal::ends_with(ret, "Cancel\n"))
- return button::cancel;
- if (internal::ends_with(ret, "OK\n"))
- return button::ok;
- if (internal::ends_with(ret, "Yes\n"))
- return button::yes;
- if (internal::ends_with(ret, "No\n"))
- return button::no;
- if (internal::ends_with(ret, "Abort\n"))
- return button::abort;
- if (internal::ends_with(ret, "Retry\n"))
- return button::retry;
- if (internal::ends_with(ret, "Ignore\n"))
- return button::ignore;
- if (m_mappings.count(exit_code) != 0)
- return m_mappings[exit_code];
- return exit_code == 0 ? button::ok : button::cancel;
- }
-
- // open_file implementation
-
- inline open_file::open_file(std::string const& title,
- std::string const& default_path /* = "" */,
- std::vector<std::string> const& filters /* = { "All Files", "*" } */,
- opt options /* = opt::none */)
- : file_dialog(type::open, title, default_path, filters, options)
- {
- }
-
- inline open_file::open_file(std::string const& title,
- std::string const& default_path,
- std::vector<std::string> const& filters,
- bool allow_multiselect)
- : open_file(title, default_path, filters, (allow_multiselect ? opt::multiselect : opt::none))
- {
- }
-
- inline std::vector<std::string> open_file::result()
- {
- return vector_result();
- }
-
- // save_file implementation
-
- inline save_file::save_file(std::string const& title,
- std::string const& default_path /* = "" */,
- std::vector<std::string> const& filters /* = { "All Files", "*" } */,
- opt options /* = opt::none */)
- : file_dialog(type::save, title, default_path, filters, options)
- {
- }
-
- inline save_file::save_file(std::string const& title,
- std::string const& default_path,
- std::vector<std::string> const& filters,
- bool confirm_overwrite)
- : save_file(title, default_path, filters, (confirm_overwrite ? opt::none : opt::force_overwrite))
- {
- }
-
- inline std::string save_file::result()
- {
- return string_result();
- }
-
- // select_folder implementation
-
- inline select_folder::select_folder(std::string const& title,
- std::string const& default_path /* = "" */,
- opt options /* = opt::none */)
- : file_dialog(type::folder, title, default_path, {}, options)
- {
- }
-
- inline std::string select_folder::result()
- {
- return string_result();
- }
-
-#endif // PFD_SKIP_IMPLEMENTATION
-
-} // namespace pfd \ No newline at end of file
+}
+
+inline button message::result() {
+ int exit_code;
+ auto ret = m_async->result(&exit_code);
+ // osascript will say "button returned:Cancel\n"
+ // and others will just say "Cancel\n"
+ if (internal::ends_with(ret, "Cancel\n")) return button::cancel;
+ if (internal::ends_with(ret, "OK\n")) return button::ok;
+ if (internal::ends_with(ret, "Yes\n")) return button::yes;
+ if (internal::ends_with(ret, "No\n")) return button::no;
+ if (internal::ends_with(ret, "Abort\n")) return button::abort;
+ if (internal::ends_with(ret, "Retry\n")) return button::retry;
+ if (internal::ends_with(ret, "Ignore\n")) return button::ignore;
+ if (m_mappings.count(exit_code) != 0) return m_mappings[exit_code];
+ return exit_code == 0 ? button::ok : button::cancel;
+}
+
+// open_file implementation
+
+inline open_file::open_file(std::string const& title, std::string const& default_path /* = "" */,
+ std::vector<std::string> const& filters /* = { "All Files", "*" } */,
+ opt options /* = opt::none */)
+ : file_dialog(type::open, title, default_path, filters, options) {}
+
+inline open_file::open_file(std::string const& title, std::string const& default_path,
+ std::vector<std::string> const& filters, bool allow_multiselect)
+ : open_file(title, default_path, filters, (allow_multiselect ? opt::multiselect : opt::none)) {}
+
+inline std::vector<std::string> open_file::result() {
+ return vector_result();
+}
+
+// save_file implementation
+
+inline save_file::save_file(std::string const& title, std::string const& default_path /* = "" */,
+ std::vector<std::string> const& filters /* = { "All Files", "*" } */,
+ opt options /* = opt::none */)
+ : file_dialog(type::save, title, default_path, filters, options) {}
+
+inline save_file::save_file(std::string const& title, std::string const& default_path,
+ std::vector<std::string> const& filters, bool confirm_overwrite)
+ : save_file(title, default_path, filters,
+ (confirm_overwrite ? opt::none : opt::force_overwrite)) {}
+
+inline std::string save_file::result() {
+ return string_result();
+}
+
+// select_folder implementation
+
+inline select_folder::select_folder(std::string const& title,
+ std::string const& default_path /* = "" */,
+ opt options /* = opt::none */)
+ : file_dialog(type::folder, title, default_path, {}, options) {}
+
+inline std::string select_folder::result() {
+ return string_result();
+}
+
+#endif // PFD_SKIP_IMPLEMENTATION
+
+} // namespace pfd \ No newline at end of file
diff --git a/tests/example.cc b/tests/example.cc
index 718e46f..83e664a 100644
--- a/tests/example.cc
+++ b/tests/example.cc
@@ -1,19 +1,16 @@
#define AppMain int __ImageStart
#warning TestCase #1
-int bar()
-{
- int yyy = 100;
- return yyy;
+int bar() {
+ int yyy = 100;
+ return yyy;
}
-int foo()
-{
- int arg1 = 0;
- return bar();
+int foo() {
+ int arg1 = 0;
+ return bar();
}
-AppMain()
-{
- return foo();
+AppMain() {
+ return foo();
}
diff --git a/tools/asm.cc b/tools/asm.cc
index 4845c99..118ab22 100644
--- a/tools/asm.cc
+++ b/tools/asm.cc
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
+ Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
------------------------------------------- */
@@ -9,8 +9,8 @@
#include <LibCompiler/Defines.h>
#include <LibCompiler/Version.h>
-#include <iostream>
#include <cstring>
+#include <iostream>
#include <string>
#include <vector>
@@ -19,94 +19,79 @@ LC_IMPORT_C int AssemblerMainARM64(int argc, char const* argv[]);
LC_IMPORT_C int AssemblerMain64x0(int argc, char const* argv[]);
LC_IMPORT_C int AssemblerMainAMD64(int argc, char const* argv[]);
-enum AsmKind : Int32
-{
- kX64Assembler,
- k64X0Assembler,
- kPOWER64Assembler,
- kARM64Assembler,
- kAssemblerCount,
+enum AsmKind : Int32 {
+ kX64Assembler,
+ k64X0Assembler,
+ kPOWER64Assembler,
+ kARM64Assembler,
+ kAssemblerCount,
};
-int main(int argc, char const* argv[])
-{
- std::vector<const char*> arg_vec_cstr;
- arg_vec_cstr.push_back(argv[0]);
+int main(int argc, char const* argv[]) {
+ std::vector<const char*> arg_vec_cstr;
+ arg_vec_cstr.push_back(argv[0]);
- const Int32 kInvalidAssembler = -1;
- Int32 asm_type = kInvalidAssembler;
+ const Int32 kInvalidAssembler = -1;
+ Int32 asm_type = kInvalidAssembler;
- for (size_t index_arg = 1; index_arg < argc; ++index_arg)
- {
- if (strstr(argv[index_arg], "--asm:h"))
- {
- std::printf("asm: Frontend Assembler (64x0, power64, arm64, x64).\n");
- std::printf("asm: Version: %s, Release: %s.\n", kDistVersion, kDistRelease);
- std::printf("asm: Designed by Amlal El Mahrouss, Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved.\n");
- std::printf("LibCompiler: Designed by Amlal El Mahrouss, Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved.\n");
+ for (size_t index_arg = 1; index_arg < argc; ++index_arg) {
+ if (strstr(argv[index_arg], "--asm:h")) {
+ std::printf("asm: Frontend Assembler (64x0, power64, arm64, x64).\n");
+ std::printf("asm: Version: %s, Release: %s.\n", kDistVersion, kDistRelease);
+ std::printf(
+ "asm: Designed by Amlal El Mahrouss, Copyright (C) 2024-2025 Amlal El Mahrouss, all "
+ "rights reserved.\n");
+ std::printf(
+ "LibCompiler: Designed by Amlal El Mahrouss, Copyright (C) 2024-2025 Amlal El Mahrouss, "
+ "all rights reserved.\n");
- return 0;
- }
- else if (strstr(argv[index_arg], "--asm:x64"))
- {
- asm_type = kX64Assembler;
- }
- else if (strstr(argv[index_arg], "--asm:aarch64"))
- {
- asm_type = kARM64Assembler;
- }
- else if (strstr(argv[index_arg], "--asm:64x0"))
- {
- asm_type = k64X0Assembler;
- }
- else if (strstr(argv[index_arg], "--asm:power64"))
- {
- asm_type = kPOWER64Assembler;
- }
- else
- {
- arg_vec_cstr.push_back(argv[index_arg]);
- }
- }
+ return 0;
+ } else if (strstr(argv[index_arg], "--asm:x64")) {
+ asm_type = kX64Assembler;
+ } else if (strstr(argv[index_arg], "--asm:aarch64")) {
+ asm_type = kARM64Assembler;
+ } else if (strstr(argv[index_arg], "--asm:64x0")) {
+ asm_type = k64X0Assembler;
+ } else if (strstr(argv[index_arg], "--asm:power64")) {
+ asm_type = kPOWER64Assembler;
+ } else {
+ arg_vec_cstr.push_back(argv[index_arg]);
+ }
+ }
- switch (asm_type)
- {
- case kPOWER64Assembler: {
- if (int32_t code = AssemblerMainPower64(arg_vec_cstr.size(), arg_vec_cstr.data()); code)
- {
- std::printf("asm: frontend exited with code %i.\n", code);
- return code;
- }
- break;
- }
- case k64X0Assembler: {
- if (int32_t code = AssemblerMain64x0(arg_vec_cstr.size(), arg_vec_cstr.data()); code)
- {
- std::printf("asm: frontend exited with code %i.\n", code);
- return code;
- }
- break;
- }
- case kARM64Assembler: {
- if (int32_t code = AssemblerMainARM64(arg_vec_cstr.size(), arg_vec_cstr.data()); code)
- {
- std::printf("asm: frontend exited with code %i.\n", code);
- return code;
- }
- break;
- }
- case kX64Assembler: {
- if (int32_t code = AssemblerMainAMD64(arg_vec_cstr.size(), arg_vec_cstr.data()); code)
- {
- std::printf("asm: frontend exited with code %i.\n", code);
- return code;
- }
- break;
- }
- default: {
- return EXIT_FAILURE;
- }
- }
+ switch (asm_type) {
+ case kPOWER64Assembler: {
+ if (int32_t code = AssemblerMainPower64(arg_vec_cstr.size(), arg_vec_cstr.data()); code) {
+ std::printf("asm: frontend exited with code %i.\n", code);
+ return code;
+ }
+ break;
+ }
+ case k64X0Assembler: {
+ if (int32_t code = AssemblerMain64x0(arg_vec_cstr.size(), arg_vec_cstr.data()); code) {
+ std::printf("asm: frontend exited with code %i.\n", code);
+ return code;
+ }
+ break;
+ }
+ case kARM64Assembler: {
+ if (int32_t code = AssemblerMainARM64(arg_vec_cstr.size(), arg_vec_cstr.data()); code) {
+ std::printf("asm: frontend exited with code %i.\n", code);
+ return code;
+ }
+ break;
+ }
+ case kX64Assembler: {
+ if (int32_t code = AssemblerMainAMD64(arg_vec_cstr.size(), arg_vec_cstr.data()); code) {
+ std::printf("asm: frontend exited with code %i.\n", code);
+ return code;
+ }
+ break;
+ }
+ default: {
+ return EXIT_FAILURE;
+ }
+ }
- return EXIT_SUCCESS;
+ return EXIT_SUCCESS;
}
diff --git a/tools/cppdrv.cc b/tools/cppdrv.cc
index 72cfb36..8b6238b 100644
--- a/tools/cppdrv.cc
+++ b/tools/cppdrv.cc
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
+ Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
------------------------------------------- */
@@ -10,21 +10,18 @@
#include <LibCompiler/Defines.h>
#include <LibCompiler/ErrorID.h>
#include <LibCompiler/Version.h>
-#include <iostream>
#include <cstring>
+#include <iostream>
#include <vector>
LC_IMPORT_C int CPlusPlusPreprocessorMain(int argc, char const* argv[]);
-int main(int argc, char const* argv[])
-{
- if (auto code = CPlusPlusPreprocessorMain(2, argv);
- code > 0)
- {
- std::printf("cppdrv: preprocessor exited with code %i.\n", code);
+int main(int argc, char const* argv[]) {
+ if (auto code = CPlusPlusPreprocessorMain(2, argv); code > 0) {
+ std::printf("cppdrv: preprocessor exited with code %i.\n", code);
- return LIBCOMPILER_EXEC_ERROR;
- }
+ return LIBCOMPILER_EXEC_ERROR;
+ }
- return LIBCOMPILER_SUCCESSS;
+ return LIBCOMPILER_SUCCESSS;
} \ No newline at end of file
diff --git a/tools/cxxdrv.cc b/tools/cxxdrv.cc
index 1d59c5c..400e116 100644
--- a/tools/cxxdrv.cc
+++ b/tools/cxxdrv.cc
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
+ Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
------------------------------------------- */
@@ -10,66 +10,52 @@
#include <LibCompiler/Defines.h>
#include <LibCompiler/ErrorID.h>
#include <LibCompiler/Version.h>
-#include <iostream>
#include <cstring>
#include <vector>
LC_IMPORT_C int CompilerCPlusPlusAMD64(int argc, char const* argv[]);
LC_IMPORT_C int AssemblerMainAMD64(int argc, char const* argv[]);
-int main(int argc, char const* argv[])
-{
- std::vector<std::string> args_list_cxx;
- std::vector<std::string> args_list_asm;
-
- for (size_t index_arg = 0; index_arg < argc; ++index_arg)
- {
- if (strstr(argv[index_arg], ".cxx") ||
- strstr(argv[index_arg], ".cpp") ||
- strstr(argv[index_arg], ".cc") ||
- strstr(argv[index_arg], ".c++") ||
- strstr(argv[index_arg], ".C"))
- {
- std::string arg = argv[index_arg];
-
- arg += ".pp.masm";
- args_list_asm.push_back(arg);
-
- arg = argv[index_arg];
- arg += ".pp";
-
- args_list_cxx.push_back(arg);
- }
- else if (strstr(argv[index_arg], ".c"))
- {
- std::printf("cxxdrv: error: Not a C driver.\n");
- return EXIT_FAILURE;
- }
- }
-
- for (auto& cli : args_list_cxx)
- {
- const char* arr_cli[] = {argv[0], cli.data()};
-
- if (auto code = CompilerCPlusPlusAMD64(2, arr_cli);
- code > 0)
- {
- std::printf("cxxdrv: compiler exited with code %i.\n", code);
-
- return LIBCOMPILER_EXEC_ERROR;
- }
- }
-
- for (auto& cli : args_list_asm)
- {
- const char* arr_cli[] = {argv[0], cli.data()};
-
- if (auto code = AssemblerMainAMD64(2, arr_cli);
- code > 0)
- {
- std::printf("cxxdrv: assembler exited with code %i.\n", code);
- }
- }
-
- return LIBCOMPILER_EXEC_ERROR;
+int main(int argc, char const* argv[]) {
+ std::vector<std::string> args_list_cxx;
+ std::vector<std::string> args_list_asm;
+
+ for (size_t index_arg = 0; index_arg < argc; ++index_arg) {
+ if (strstr(argv[index_arg], ".cxx") || strstr(argv[index_arg], ".cpp") ||
+ strstr(argv[index_arg], ".cc") || strstr(argv[index_arg], ".c++") ||
+ strstr(argv[index_arg], ".C")) {
+ std::string arg = argv[index_arg];
+
+ arg += ".pp.masm";
+ args_list_asm.push_back(arg);
+
+ arg = argv[index_arg];
+ arg += ".pp";
+
+ args_list_cxx.push_back(arg);
+ } else if (strstr(argv[index_arg], ".c")) {
+ std::printf("cxxdrv: error: Not a C driver.\n");
+ return EXIT_FAILURE;
+ }
+ }
+
+ for (auto& cli : args_list_cxx) {
+ const char* arr_cli[] = {argv[0], cli.data()};
+
+ if (auto code = CompilerCPlusPlusAMD64(2, arr_cli); code > 0) {
+ std::printf("cxxdrv: compiler exited with code %i.\n", code);
+
+ return LIBCOMPILER_EXEC_ERROR;
+ }
+ }
+
+ for (auto& cli : args_list_asm) {
+ const char* arr_cli[] = {argv[0], cli.data()};
+
+ if (auto code = AssemblerMainAMD64(2, arr_cli); code > 0) {
+ std::printf("cxxdrv: assembler exited with code %i.\n", code);
+ }
+ }
+
+ return LIBCOMPILER_EXEC_ERROR;
}
diff --git a/tools/dbg.cc b/tools/dbg.cc
index 67b942e..b9be862 100644
--- a/tools/dbg.cc
+++ b/tools/dbg.cc
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
+ Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
------------------------------------------- */
@@ -13,7 +13,6 @@ LC_IMPORT_C int DebuggerMachPOSIX(int argc, char const* argv[]);
/// @brief Debugger entrypoint.
/// @return Status code of debugger.
-int main(int argc, char const* argv[])
-{
- return DebuggerMachPOSIX(argc, argv);
+int main(int argc, char const* argv[]) {
+ return DebuggerMachPOSIX(argc, argv);
}
diff --git a/tools/kdbg.cc b/tools/kdbg.cc
index 5aae438..11901e3 100644
--- a/tools/kdbg.cc
+++ b/tools/kdbg.cc
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
+ Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
------------------------------------------- */
@@ -13,7 +13,6 @@ LC_IMPORT_C int DebuggerNeKernel(int argc, char const* argv[]);
/// @brief Debugger entrypoint.
/// @return Status code of debugger.
-int main(int argc, char const* argv[])
-{
- return DebuggerNeKernel(argc, argv);
+int main(int argc, char const* argv[]) {
+ return DebuggerNeKernel(argc, argv);
}
diff --git a/tools/ld64.cc b/tools/ld64.cc
index 48c1368..fec1314 100644
--- a/tools/ld64.cc
+++ b/tools/ld64.cc
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
+ Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved
------------------------------------------- */
@@ -11,12 +11,10 @@
LC_IMPORT_C int DynamicLinker64PEF(int argc, char const* argv[]);
-int main(int argc, char const* argv[])
-{
- if (argc < 1)
- {
- return 1;
- }
+int main(int argc, char const* argv[]) {
+ if (argc < 1) {
+ return 1;
+ }
- return DynamicLinker64PEF(argc, argv);
+ return DynamicLinker64PEF(argc, argv);
}