Merge branch 'master' of https://codeberg.org/eaxcc/eaxcc
This commit is contained in:
@ -5,38 +5,22 @@
|
||||
#include "../source/assembler.c"
|
||||
|
||||
int main (void) {
|
||||
token_array = malloc (144UL * sizeof (* token_array));
|
||||
unsigned int index;
|
||||
|
||||
assemble (OPERATION_ADD_F, SIZE_64B,
|
||||
TYPE_REGISTER, OPERAND_REGISTER_1,
|
||||
TYPE_REGISTER, OPERAND_REGISTER_2);
|
||||
output_array = malloc (144UL * sizeof (* output_array));
|
||||
|
||||
assemble (OPERATION_ADD_F, SIZE_32B,
|
||||
TYPE_REGISTER, OPERAND_REGISTER_1,
|
||||
TYPE_VARIABLE, 12);
|
||||
build_regular (ADC, D64, REG, R1, REG, R2);
|
||||
build_regular (ADC, D32, REG, R1, MEM, 12);
|
||||
build_regular (ADC, D16, MEM, 12, REG, R10);
|
||||
build_regular (ADC, D8, REG, R3, IMM, 0X77);
|
||||
build_special_1 (LOCK);
|
||||
build_special_2 (PAUSE);
|
||||
|
||||
assemble (OPERATION_ADD_F, SIZE_16B,
|
||||
TYPE_VARIABLE, 12,
|
||||
TYPE_REGISTER, OPERAND_REGISTER_A);
|
||||
|
||||
assemble (OPERATION_ADD_F, SIZE_8B,
|
||||
TYPE_REGISTER, OPERAND_REGISTER_3,
|
||||
TYPE_CONSTANT, 0X77);
|
||||
|
||||
for (int index = 0; index < token_count; ++index) {
|
||||
printf ("%02X \n", token_array [index]);
|
||||
for (index = 0; index < output_count; ++index) {
|
||||
printf ("%02X \n", output_array [index]);
|
||||
}
|
||||
|
||||
free (token_array);
|
||||
free (output_array);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
//~xor rcx rdx
|
||||
//~48 31 D1
|
||||
//~WORKS AS EXPECTED!
|
||||
|
||||
//~90 48 11 D1
|
||||
//~90 13 0D 14 10 00 00
|
||||
//~90 66 44 11 15 09 10 00 00
|
||||
//~90 80 D3 77
|
||||
|
@ -153,19 +153,6 @@ entry $
|
||||
nop
|
||||
nop
|
||||
|
||||
nop
|
||||
adc rcx, rdx; 48 31 D1
|
||||
nop
|
||||
adc ecx, [x4]; 33 0D 14 10 00 00
|
||||
nop
|
||||
adc [x2], r10w; 66 44 31 15 09 10 00 00
|
||||
nop
|
||||
adc bl, 077h; 80 F3 77
|
||||
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
nop
|
||||
enter 2, 2
|
||||
nop
|
||||
@ -180,6 +167,77 @@ entry $
|
||||
sysexit
|
||||
nop
|
||||
cpuid
|
||||
nop
|
||||
movbe rax, [x8]
|
||||
nop
|
||||
movbe rcx, [x8]
|
||||
nop
|
||||
movsq
|
||||
nop
|
||||
neg rax
|
||||
nop
|
||||
neg dword[x4]
|
||||
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
nop
|
||||
inc byte[x1]
|
||||
nop
|
||||
inc word[x2]
|
||||
nop
|
||||
inc dword[x4]
|
||||
nop
|
||||
inc qword[x8]
|
||||
nop
|
||||
inc cl
|
||||
nop
|
||||
inc cx
|
||||
nop
|
||||
inc ecx
|
||||
nop
|
||||
inc rcx
|
||||
nop
|
||||
inc r9b
|
||||
nop
|
||||
inc r9w
|
||||
nop
|
||||
inc r9d
|
||||
nop
|
||||
inc r9
|
||||
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
nop
|
||||
adc rcx, rdx; 48 31 D1
|
||||
nop
|
||||
adc ecx, [x4]; 33 0D 14 10 00 00
|
||||
nop
|
||||
adc [x2], r10w; 66 44 31 15 09 10 00 00
|
||||
nop
|
||||
adc bl, 077h; 80 F3 77
|
||||
;~assemble (ADC, D64, REG, R1, REG, R2);
|
||||
;~assemble (ADC, D32, REG, R1, MEM, 12);
|
||||
;~assemble (ADC, D16, MEM, 12, REG, R10);
|
||||
;~assemble (ADC, D8, REG, R3, IMM, 0X77);
|
||||
;~48 11 D1
|
||||
;~13 0D 14 10 00 00
|
||||
;~66 44 11 15 09 10 00 00
|
||||
;~80 D3 77
|
||||
;~48
|
||||
;~11
|
||||
;~D1
|
||||
;~13
|
||||
;~0D
|
||||
;~66
|
||||
;~44
|
||||
;~11
|
||||
;~15
|
||||
;~80
|
||||
;~D3
|
||||
|
||||
nop
|
||||
|
||||
|
@ -1,155 +1,137 @@
|
||||
#include "assembler.h"
|
||||
|
||||
static next token_count = 0;
|
||||
static byte * token_array = NULL;
|
||||
#include <stdlib.h>
|
||||
|
||||
static void token_print (byte data) {
|
||||
token_array [token_count] = data;
|
||||
|
||||
token_count += 1;
|
||||
}
|
||||
|
||||
static inline form valid (form data) { return ((data >= 0) && (data <= 15)); }
|
||||
static inline form lower (form data) { return ((data >= 0) && (data <= 7)); }
|
||||
static inline form upper (form data) { return ((data >= 8) && (data <= 15)); }
|
||||
|
||||
static inline
|
||||
void format_short_prefix (void) {
|
||||
token_print (0X66);
|
||||
}
|
||||
|
||||
static inline
|
||||
void format_long_prefix (size_index size,
|
||||
type_index to,
|
||||
form destination,
|
||||
type_index from,
|
||||
form source) {
|
||||
token_print (0X40 +
|
||||
0X01 * ((to == TYPE_REGISTER) && (upper (destination))) +
|
||||
0X04 * ((from == TYPE_REGISTER) && (upper (source))) +
|
||||
0X08 * (size == SIZE_64B));
|
||||
}
|
||||
|
||||
static inline
|
||||
void format_register_direction (size_index size,
|
||||
form destination,
|
||||
form source) {
|
||||
token_print (0XC0 +
|
||||
0X01 * (destination % 8) +
|
||||
0X08 * (source % 8));
|
||||
}
|
||||
/*
|
||||
static inline
|
||||
void format_register_indirection (size_index size,
|
||||
form destination) {
|
||||
byte format = 0XF0;
|
||||
|
||||
format += destination % 8;
|
||||
|
||||
token_print (format);
|
||||
}
|
||||
gcc -c -ansi -Wall -Wextra -Wpedantic -Werror:
|
||||
-- warns about trailing comma in enumerations.
|
||||
-- kept because of chad coding standard.
|
||||
-- unused functions for now, obviously...
|
||||
clang -c -ansi -Weverything -Werror:
|
||||
-- exactly same warnings as with gcc above.
|
||||
splint -fcnuse +boolint +charint assembler.c:
|
||||
-- we obviously ignore unused functions for now.
|
||||
-- we assume bool is int, which is true.
|
||||
-- we assume char is int, which is true.
|
||||
-- assembler.c:167:13: Function fabs shadows outer declaration
|
||||
-- ^ function from <math.h>, which we don't even use.
|
||||
splint assembler.h:
|
||||
-- no warnings at all.
|
||||
*/
|
||||
static inline
|
||||
void format_register_redirection (size_index size,
|
||||
form direction) {
|
||||
token_print (0X05 +
|
||||
0X08 * (direction % 8));
|
||||
|
||||
#define REGULAR_START (ADD)
|
||||
#define REGULAR_COUNT (UMUL - REGULAR_START)
|
||||
#define IRREGULAR_START (UMUL)
|
||||
#define IRREGULAR_COUNT (NOP - IRREGULAR_START)
|
||||
#define SPECIAL_1_START (NOP)
|
||||
#define SPECIAL_1_COUNT (SYSENTER - SPECIAL_1_START)
|
||||
#define SPECIAL_2_START (SYSENTER)
|
||||
#define SPECIAL_2_COUNT (ENTER - SPECIAL_2_START)
|
||||
|
||||
typedef signed int form;
|
||||
typedef unsigned int next;
|
||||
typedef unsigned char byte;
|
||||
|
||||
static next input_count; /* SHOULD I EXPOSE THESE? */
|
||||
static form * input_array;
|
||||
static next output_count;
|
||||
static byte * output_array;
|
||||
|
||||
static void place (form when, byte data) {
|
||||
output_array [output_count] = data;
|
||||
|
||||
output_count += (next) when;
|
||||
}
|
||||
|
||||
static inline
|
||||
void format_constant (size_index size) {
|
||||
token_print (0X80 +
|
||||
0X01 * (size != SIZE_8B));
|
||||
static form valid (form data) { return ((data >= 0) && (data <= 15)); }
|
||||
static form lower (form data) { return ((data >= 0) && (data <= 7)); }
|
||||
static form upper (form data) { return ((data >= 8) && (data <= 15)); }
|
||||
|
||||
static void build_short_prefix (form when) {
|
||||
place (when, 0X66);
|
||||
}
|
||||
|
||||
static inline
|
||||
void format_regular_instruction (byte format,
|
||||
size_index size,
|
||||
type_index to,
|
||||
form destination,
|
||||
type_index from,
|
||||
form source) {
|
||||
//~format += 0X01 * (size != SIZE_8B);
|
||||
//~format += 0X02 * ((to == TYPE_REGISTER) && (from == TYPE_VARIABLE));
|
||||
//~format += 0XC0 * ((to == TYPE_REGISTER) && (from == TYPE_CONSTANT));
|
||||
//~format += 0X04 * ((to == TYPE_VARIABLE) && (from == TYPE_CONSTANT));
|
||||
|
||||
//~if ((to == TYPE_REGISTER) && (from == TYPE_CONSTANT)) {
|
||||
//~format += destination % 8;
|
||||
//~}
|
||||
|
||||
//~token_print (format);
|
||||
|
||||
token_print (format +
|
||||
destination % 8 * ((to == TYPE_REGISTER) && (from == TYPE_CONSTANT)) +
|
||||
0X01 * (size != SIZE_8B) +
|
||||
0X02 * ((to == TYPE_REGISTER) && (from == TYPE_VARIABLE)) +
|
||||
0XC0 * ((to == TYPE_REGISTER) && (from == TYPE_CONSTANT)) +
|
||||
0X04 * ((to == TYPE_VARIABLE) && (from == TYPE_CONSTANT)));
|
||||
static void build_long_prefix (form when,
|
||||
size_index size,
|
||||
type_index to,
|
||||
form destination,
|
||||
type_index from,
|
||||
form source) {
|
||||
place (when, (byte) (0X40
|
||||
+ 0X01 * ((to == REG) && (upper (destination)))
|
||||
+ 0X04 * ((from == REG) && (upper (source)))
|
||||
+ 0X08 * (size == D64)));
|
||||
}
|
||||
|
||||
static inline
|
||||
void assemble_enter (form dynamic_storage,
|
||||
form nesting_level) {
|
||||
token_print (0XC8);
|
||||
token_print ((dynamic_storage / 1) % 256); // FIX LATER
|
||||
token_print ((dynamic_storage / 256) % 256);
|
||||
token_print ((nesting_level / 1) % 256);
|
||||
static void build_register_direction (form when,
|
||||
form destination,
|
||||
form source) { /* LENGTH */
|
||||
place (when, (byte) (0XC0 + 0X01 * (destination % 8) + 0X08 * (source % 8)));
|
||||
}
|
||||
|
||||
static inline void assemble_leave (void) { token_print (0XC9); }
|
||||
static inline void assemble_system_call (void) { token_print (0X0F); token_print (0X05); }
|
||||
static inline void assemble_system_return (void) { token_print (0X0F); token_print (0X07); }
|
||||
static inline void assemble_system_enter (void) { token_print (0X0F); token_print (0X34); }
|
||||
static inline void assemble_system_exit (void) { token_print (0X0F); token_print (0X35); }
|
||||
static inline void assemble_cpu_identifier (void) { token_print (0X0F); token_print (0XA2); }
|
||||
|
||||
static inline
|
||||
void assemble (operation_index operation,
|
||||
size_index size,
|
||||
type_index to,
|
||||
form destination,
|
||||
type_index from,
|
||||
form source) {
|
||||
byte code = 0X00;
|
||||
|
||||
if (size == SIZE_16B) {
|
||||
format_short_prefix ();
|
||||
}
|
||||
|
||||
if ((size == SIZE_64B)
|
||||
|| ((to == TYPE_REGISTER) && (upper (destination)))
|
||||
|| ((from == TYPE_REGISTER) && (upper (source)))) {
|
||||
format_long_prefix (size, to, destination, from, source);
|
||||
}
|
||||
|
||||
if (from == TYPE_CONSTANT) {
|
||||
format_constant (size);
|
||||
}
|
||||
|
||||
switch (operation) {
|
||||
case OPERATION_ADD: code = 0X00; break;
|
||||
case OPERATION_OR: code = 0X08; break;
|
||||
case OPERATION_ADD_F: code = 0X10; break;
|
||||
case OPERATION_SUBTRACT_F: code = 0X18; break;
|
||||
case OPERATION_AND: code = 0X20; break;
|
||||
case OPERATION_SUBTRACT: code = 0X28; break;
|
||||
case OPERATION_XOR: code = 0X30; break;
|
||||
case OPERATION_COMPARE: code = 0X38; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
format_regular_instruction (code, size, to, destination, from, source);
|
||||
|
||||
if ((to == TYPE_REGISTER) && (from == TYPE_REGISTER)) {
|
||||
format_register_direction (size, destination, source);
|
||||
}
|
||||
|
||||
if ((to == TYPE_REGISTER) && (from == TYPE_VARIABLE)) {
|
||||
format_register_redirection (size, destination);
|
||||
}
|
||||
|
||||
if ((to == TYPE_VARIABLE) && (from == TYPE_REGISTER)) {
|
||||
format_register_redirection (size, source);
|
||||
}
|
||||
static void build_register_redirection (form when,
|
||||
form direction) {
|
||||
place (when, (byte) (0X05 + 0X08 * (direction % 8)));
|
||||
}
|
||||
|
||||
static void build_constant (form when,
|
||||
size_index size) {
|
||||
place (when, (byte) (0X80 + 0X01 * (size != D8)));
|
||||
}
|
||||
|
||||
static void build_regular_instruction (form when,
|
||||
byte code,
|
||||
size_index size,
|
||||
type_index to,
|
||||
form destination,
|
||||
type_index from) {
|
||||
place (when, (byte) (code
|
||||
+ destination % 8 * ((to == REG) && (from == IMM))
|
||||
+ 0X01 * (size != D8)
|
||||
+ 0X02 * ((from == MEM) && (to == REG))
|
||||
+ 0X04 * ((from == IMM) && (to == MEM))
|
||||
+ 0XC0 * ((from == IMM) && (to == REG))));
|
||||
}
|
||||
|
||||
static void build_regular (operation_index operation,
|
||||
size_index size,
|
||||
type_index to,
|
||||
form destination,
|
||||
type_index from,
|
||||
form source) {
|
||||
build_short_prefix (size == D16);
|
||||
|
||||
build_long_prefix ((size == D64)
|
||||
|| ((to == REG) && (upper (destination)))
|
||||
|| ((from == REG) && (upper (source))),
|
||||
size, to, destination, from, source);
|
||||
|
||||
build_constant (from == IMM, size);
|
||||
|
||||
build_regular_instruction (1, (byte) (0X08 * operation),
|
||||
size, to, destination, from);
|
||||
|
||||
build_register_direction ((to == REG) && (from == REG),
|
||||
destination, source);
|
||||
|
||||
build_register_redirection ((to == REG) && (from == MEM), destination);
|
||||
build_register_redirection ((to == MEM) && (from == REG), source);
|
||||
}
|
||||
|
||||
static void build_special_1 (operation_index operation) {
|
||||
const byte data [1 * SPECIAL_1_COUNT] = {
|
||||
0X90, 0XC3, 0XCB, 0XC9, 0XF0, 0XF4
|
||||
};
|
||||
|
||||
place (1, data [operation - SPECIAL_1_START]);
|
||||
}
|
||||
|
||||
static void build_special_2 (operation_index operation) {
|
||||
const byte data [2 * SPECIAL_2_COUNT] = {
|
||||
0X0F, 0X0F, 0X0F, 0X0F, 0XF3, 0X0F,
|
||||
0X34, 0X35, 0X05, 0X07, 0X90, 0XA2
|
||||
};
|
||||
|
||||
place (1, data [operation - SPECIAL_2_START]);
|
||||
place (1, data [operation - SPECIAL_2_START + SPECIAL_2_COUNT]);
|
||||
}
|
||||
|
@ -1,40 +1,48 @@
|
||||
#ifndef ASSEMBLER_H
|
||||
#define ASSEMBLER_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef enum {
|
||||
SIZE_256B, SIZE_128B, SIZE_64B,
|
||||
SIZE_32B, SIZE_16B, SIZE_8B,
|
||||
D64, D32, D16, D8,
|
||||
} size_index;
|
||||
|
||||
typedef enum {
|
||||
TYPE_REGISTER, TYPE_VARIABLE, TYPE_CONSTANT,
|
||||
NIL, REG, MEM, IMM,
|
||||
} type_index;
|
||||
|
||||
typedef enum {
|
||||
OPERATION_MOVE, OPERATION_ADD, OPERATION_SUBTRACT,
|
||||
OPERATION_MULTIPLY, OPERATION_DIVIDE, OPERATION_MODULUS,
|
||||
OPERATION_COMPARE, OPERATION_JUMP, OPERATION_XOR,
|
||||
OPERATION_AND, OPERATION_OR, OPERATION_NOT,
|
||||
OPERATION_IS, OPERATION_ABOVE, OPERATION_BELOW,
|
||||
OPERATION_IF, OPERATION_INCREMENT, OPERATION_DECREMENT,
|
||||
OPERATION_SYSTEM, OPERATION_CALL, OPERATION_RETURN,
|
||||
OPERATION_ENTER, OPERATION_LEAVE, OPERATION_EXIT,
|
||||
OPERATION_ADD_F, OPERATION_SUBTRACT_F,
|
||||
ADD, OR, ADC, SBB,
|
||||
AND, SUB, XOR, CMP,
|
||||
UMUL, UDIV, IMUL, IDIV,
|
||||
INC, DEC, NOT, NEG,
|
||||
NOP, RETN, RETF, LEAVE,
|
||||
LOCK, HLT,
|
||||
SYSENTER, SYSEXIT, SYSCALL, SYSRET,
|
||||
PAUSE, CPUID,
|
||||
ENTER, CALL, IN, OUT,
|
||||
JMP, JPE, JS, JPO,
|
||||
JE, JNE, JZ, JNZ,
|
||||
JA, JNA, JB, JNB,
|
||||
MOV, CMOVPE, CMOVS, CMOVPO,
|
||||
CMOVE, CMOVNE, CMOVZ, CMOVNZ,
|
||||
CMOVA, CMOVNA, CMOVB, CMOVNB,
|
||||
PUSH, POP, BSWAP, TEST,
|
||||
RCL, RCR, ROL, ROR,
|
||||
SHL, SHR, SAL, SAR,
|
||||
REP, REPE, REPNE, REPZ,
|
||||
LOOP, LOOPE, LOOPNE, MOVBE,
|
||||
XADD, XCHG, LEA, POPCNT,
|
||||
INTI, BSF, BSR, BOUND,
|
||||
FADD, FSUB, FMUL, FDIV,
|
||||
FNOP, FXAM, FABS, FSCALE,
|
||||
FSIN, FCOS, FSQRT, FCHS,
|
||||
FXCH, FREM, FLDPI, FLDZ,
|
||||
} operation_index;
|
||||
|
||||
typedef enum {
|
||||
OPERAND_REGISTER_0, OPERAND_REGISTER_1, OPERAND_REGISTER_2,
|
||||
OPERAND_REGISTER_3, OPERAND_REGISTER_4, OPERAND_REGISTER_5,
|
||||
OPERAND_REGISTER_6, OPERAND_REGISTER_7, OPERAND_REGISTER_8,
|
||||
OPERAND_REGISTER_9, OPERAND_REGISTER_A, OPERAND_REGISTER_B,
|
||||
OPERAND_REGISTER_C, OPERAND_REGISTER_D, OPERAND_REGISTER_E,
|
||||
OPERAND_REGISTER_F, OPERAND_REFERENCE, OPERAND_DEREFERENCE,
|
||||
R0, R1, R2, R3,
|
||||
R4, R5, R6, R7,
|
||||
R8, R9, R10, R11,
|
||||
R12, R13, R14, R15,
|
||||
} operand_index;
|
||||
|
||||
typedef signed int form;
|
||||
typedef unsigned int next;
|
||||
typedef unsigned char byte;
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user