xiasma/xiasma.c

231 lines
10 KiB
C
Raw Permalink Normal View History

2023-10-28 13:58:47 -04:00
/*
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);
}
2023-10-28 14:03:26 -04:00
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 --- ");
2023-10-28 13:58:47 -04:00
encode [FORMAT_REGISTER_REGISTER] [buffer [i - 2]] (buffer [i - 2], buffer [i - 1], buffer [i]);
data_echo ();
data_free ();
2023-10-28 14:03:26 -04:00
echo ("\n");
2023-10-28 13:58:47 -04:00
}
return (EXIT_SUCCESS);
}