|
- /*
- Copyright (c) 2023 : Ognjen 'xolatile' Milan Robovic
-
- Xiasma is free software! You will redistribute it or modify it under the terms of the GNU General Public License by Free Software Foundation.
- And when you do redistribute it or modify it, it will use either version 3 of the License, or (at yours truly opinion) any later version.
- It is distributed in the hope that it will be useful or harmful, it really depends... But no warranty what so ever, seriously. See GNU/GPLv3.
- */
-
- #include <xolatile/xtandard.c>
-
- enum {
- FORMAT_NULL,
- FORMAT_REGISTER, FORMAT_VARIABLE, FORMAT_CONSTANT, FORMAT_VARIADIC,
- FORMAT_REGISTER_REGISTER, FORMAT_REGISTER_VARIABLE, FORMAT_REGISTER_CONSTANT, FORMAT_VARIABLE_REGISTER,
- FORMAT_VARIABLE_CONSTANT, FORMAT_VARIADIC_REGISTER, FORMAT_VARIADIC_VARIABLE, FORMAT_VARIADIC_CONSTANT,
- FORMAT_COUNT
- };
-
- enum {
- INSTRUCTION_NO_OPERATION, INSTRUCTION_MOVE, INSTRUCTION_CALL, INSTRUCTION_RETURN,
- INSTRUCTION_SYSTEM_ENTER, INSTRUCTION_SYSTEM_EXIT, INSTRUCTION_SYSTEM_CALL, INSTRUCTION_SYSTEM_RETURN,
- INSTRUCTION_ADD, INSTRUCTION_BIT_OR, INSTRUCTION_ADD_CARRY, INSTRUCTION_SUBTRACT_CARRY,
- INSTRUCTION_BIT_AND, INSTRUCTION_SUBTRACT, INSTRUCTION_BIT_EXCLUSIVE_OR, INSTRUCTION_COMPARE,
- INSTRUCTION_COUNT
- };
-
- enum {
- REGISTER_0_64, REGISTER_1_64, REGISTER_2_64, REGISTER_3_64, REGISTER_4_64, REGISTER_5_64, REGISTER_6_64, REGISTER_7_64,
- REGISTER_8_64, REGISTER_9_64, REGISTER_A_64, REGISTER_B_64, REGISTER_C_64, REGISTER_D_64, REGISTER_E_64, REGISTER_F_64,
- REGISTER_0_32, REGISTER_1_32, REGISTER_2_32, REGISTER_3_32, REGISTER_4_32, REGISTER_5_32, REGISTER_6_32, REGISTER_7_32,
- REGISTER_8_32, REGISTER_9_32, REGISTER_A_32, REGISTER_B_32, REGISTER_C_32, REGISTER_D_32, REGISTER_E_32, REGISTER_F_32,
- REGISTER_0_16, REGISTER_1_16, REGISTER_2_16, REGISTER_3_16, REGISTER_4_16, REGISTER_5_16, REGISTER_6_16, REGISTER_7_16,
- REGISTER_8_16, REGISTER_9_16, REGISTER_A_16, REGISTER_B_16, REGISTER_C_16, REGISTER_D_16, REGISTER_E_16, REGISTER_F_16,
- REGISTER_0_8, REGISTER_1_8, REGISTER_2_8, REGISTER_3_8, REGISTER_4_8, REGISTER_5_8, REGISTER_6_8, REGISTER_7_8,
- REGISTER_8_8, REGISTER_9_8, REGISTER_A_8, REGISTER_B_8, REGISTER_C_8, REGISTER_D_8, REGISTER_E_8, REGISTER_F_8,
- REGISTER_0_8X, REGISTER_1_8X, REGISTER_2_8X, REGISTER_3_8X,
- REGISTER_COUNT
- };
-
- static void (* encode [FORMAT_COUNT] [INSTRUCTION_COUNT]) (int instruction, int left, int right);
-
- static int data [16] = { 0 };
-
- static void data_push (int byte) { data [0]++; data [data [0]] = byte; }
- static void data_pop (void) { data [data [0]] = 0X00; data [0]--; }
- static int data_look (int look) { return (data [look]); }
- static int data_size (void) { return (data [0]); }
- static void data_free (void) { data [0] = 0; }
-
- static void data_echo (void) {
- char byte [4] = " ";
- int i;
-
- for (i = 0; i != data [0]; ++i) {
- byte [0] = "0123456789ABCDEF" [data [i + 1] / 16];
- byte [1] = "0123456789ABCDEF" [data [i + 1] % 16];
- echo (byte);
- }
- }
-
- static void unimplemented (int instruction, int left, int right) {
- (void) instruction;
- (void) left;
- (void) right;
-
- fatal_failure (1, "Unimplemented...");
- }
-
- static int register_word (char * name) {
- char * register_name [REGISTER_COUNT] = {
- "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
- "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
- "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d",
- "ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
- "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w",
- "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
- "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b",
- "ah", "ch", "dh", "bh"
- };
-
- int i;
-
- for (i = 0; i != REGISTER_COUNT; ++i) {
- if (string_compare (name, register_name [i]) != 0) {
- return (i);
- }
- }
-
- return (-1);
- }
-
- static int instruction_word (char * name) {
- char * instruction_name [INSTRUCTION_COUNT] = {
- "nop", "mov", "call", "ret", "sysenter", "sysexit", "syscall", "sysret",
- "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp"
- };
-
- int i;
-
- for (i = 0; i != INSTRUCTION_COUNT; ++i) {
- if (string_compare (name, instruction_name [i]) != 0) {
- return (i);
- }
- }
-
- return (-1);
- }
-
- static void prefix_register_size (int left, int right) {
- if ((left >= REGISTER_0_64) && (left <= REGISTER_7_64) && (right >= REGISTER_0_64) && (right <= REGISTER_7_64)) {
- data_push (0X48);
- } else if ((left >= REGISTER_8_64) && (left <= REGISTER_F_64) && (right >= REGISTER_0_64) && (right <= REGISTER_7_64)) {
- data_push (0X49);
- } else if ((left >= REGISTER_0_64) && (left <= REGISTER_7_64) && (right >= REGISTER_8_64) && (right <= REGISTER_F_64)) {
- data_push (0X4C);
- } else if ((left >= REGISTER_8_64) && (left <= REGISTER_F_64) && (right >= REGISTER_8_64) && (right <= REGISTER_F_64)) {
- data_push (0X4D);
- } else if ((left >= REGISTER_0_16) && (left <= REGISTER_7_16)) {
- data_push (0X66);
- } else if ((left >= REGISTER_8_16) && (left <= REGISTER_F_16)) {
- data_push (0X67);
- } else {
- fatal_failure (1, "prefix_register_size");
- }
- }
-
- static void infix_regular_instruction (int instruction) {
- switch (instruction) {
- case INSTRUCTION_ADD: data_push (0X01); break;
- case INSTRUCTION_BIT_OR: data_push (0X09); break;
- case INSTRUCTION_ADD_CARRY: data_push (0X11); break;
- case INSTRUCTION_SUBTRACT_CARRY: data_push (0X19); break;
- case INSTRUCTION_BIT_AND: data_push (0X21); break;
- case INSTRUCTION_SUBTRACT: data_push (0X29); break;
- case INSTRUCTION_BIT_EXCLUSIVE_OR: data_push (0X31); break;
- case INSTRUCTION_COMPARE: data_push (0X39); break;
- case INSTRUCTION_MOVE: data_push (0X89); break;
- }
- }
-
- static void suffix_register_combination (int left, int right) {
- data_push (((0X0C + ((right % 8) / 2)) << 4) | ((right % 2) * 8 + (left % 8)));
- }
-
- static void encode_regular_register_register (int instruction, int left, int right) {
- prefix_register_size (left, right);
- infix_regular_instruction (instruction);
- suffix_register_combination (left, right);
- }
-
- int main (void) {
- /* Won't be hardcoded, will use multiple files like 'gnatmake'... */
- char * source [48] = {
- "add", "rax", "r15",
- "or", "rcx", "r15",
- "adc", "rdx", "r15",
- "sbb", "rbx", "r15",
- "and", "rsp", "r15",
- "sub", "rbp", "r15",
- "xor", "rsi", "r15",
- "cmp", "rdi", "r15",
- "mov", "r8", "r15",
- "mov", "r9", "r15",
- "mov", "r10", "r15",
- "mov", "r11", "r15",
- "mov", "r12", "r15",
- "mov", "r13", "r15",
- "mov", "r14", "r15",
- "mov", "r15", "r15"
- };
-
- int buffer [48];
-
- int i, j;
-
- for (i = 0; i != FORMAT_COUNT; ++i) {
- for (j = 0; j != INSTRUCTION_COUNT; ++j) {
- encode [i] [j] = unimplemented;
- }
- }
-
- encode [FORMAT_REGISTER_REGISTER] [INSTRUCTION_ADD] = encode_regular_register_register;
- encode [FORMAT_REGISTER_REGISTER] [INSTRUCTION_BIT_OR] = encode_regular_register_register;
- encode [FORMAT_REGISTER_REGISTER] [INSTRUCTION_ADD_CARRY] = encode_regular_register_register;
- encode [FORMAT_REGISTER_REGISTER] [INSTRUCTION_SUBTRACT_CARRY] = encode_regular_register_register;
- encode [FORMAT_REGISTER_REGISTER] [INSTRUCTION_BIT_AND] = encode_regular_register_register;
- encode [FORMAT_REGISTER_REGISTER] [INSTRUCTION_SUBTRACT] = encode_regular_register_register;
- encode [FORMAT_REGISTER_REGISTER] [INSTRUCTION_BIT_EXCLUSIVE_OR] = encode_regular_register_register;
- encode [FORMAT_REGISTER_REGISTER] [INSTRUCTION_COMPARE] = encode_regular_register_register;
- encode [FORMAT_REGISTER_REGISTER] [INSTRUCTION_MOVE] = encode_regular_register_register;
-
- for (i = 0; i != 48; ++i) {
- /* These depend on format, will not assume IRR... */
- if ((buffer [i] = instruction_word (source [i])) == -1) {
- echo ("Word must be an instruction!\n");
- echo ("This '");
- echo (source [i]);
- echo ("' is not an instruction...\n");
- exit (EXIT_FAILURE);
- } ++i;
- if ((buffer [i] = register_word (source [i])) == -1) {
- echo ("Word must be a register!\n");
- echo ("This '");
- echo (source [i]);
- echo ("' is not a register...\n");
- exit (EXIT_FAILURE);
- } ++i;
- if ((buffer [i] = register_word (source [i])) == -1) {
- echo ("Word must be a register!\n");
- echo ("This '");
- echo (source [i]);
- echo ("' is not a register...\n");
- exit (EXIT_FAILURE);
- }
- echo ("\033[1;33m");
- echo (source [i - 2]);
- echo ("\033[0m \033[1;34m");
- echo (source [i - 1]);
- echo ("\033[0m \033[1;35m");
- echo (source [i]);
- echo ("\033[0m --- ");
- encode [FORMAT_REGISTER_REGISTER] [buffer [i - 2]] (buffer [i - 2], buffer [i - 1], buffer [i]);
- data_echo ();
- data_free ();
- echo ("\n");
- }
-
- return (EXIT_SUCCESS);
- }
|