From fa51402a16d5176d8d0b6be8686b49387b43e4e6 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Tue, 13 Sep 2022 22:09:44 +0200 Subject: [PATCH] Added x64 instructions. --- src/compiler/asm_target.c | 25 ++++++++++++++++-- src/compiler/compiler_internal.h | 3 ++- src/compiler/parse_stmt.c | 4 +-- test/test_suite/asm/asm_ops_x64_1.c3t | 36 ++++++++++++++++++++++++++ test/test_suite2/asm/asm_ops_x64_1.c3t | 36 ++++++++++++++++++++++++++ 5 files changed, 99 insertions(+), 5 deletions(-) create mode 100644 test/test_suite/asm/asm_ops_x64_1.c3t create mode 100644 test/test_suite2/asm/asm_ops_x64_1.c3t diff --git a/src/compiler/asm_target.c b/src/compiler/asm_target.c index fd6e040a5..7bb7151b8 100644 --- a/src/compiler/asm_target.c +++ b/src/compiler/asm_target.c @@ -5,7 +5,7 @@ #include "compiler/asm/x86.h" #include "compiler/asm/aarch64.h" -#define ASM_PTR_HASH(name__) (uint32_t)(((uintptr_t)name__ >> 9) ^ ((uintptr_t)name__ >> 1)) +#define ASM_PTR_HASH(name__) (uint32_t)(((uintptr_t)name__ * 31) ^ ((uintptr_t)name__ >> 15)) const Clobbers NO_CLOBBER = { .mask[0] = 0 }; @@ -178,6 +178,7 @@ INLINE void reg_register(const char *name, AsmRegisterType reg_type, AsmArgBits if (!reg->name) { *reg = (AsmRegister) { .name = interned, .type = reg_type, .bits = bits, .clobber_index = clobber_id }; + asm_target.register_count++; return; } slot = (slot + 1) & ASM_REGISTER_MASK; @@ -284,7 +285,6 @@ static void init_asm_x86(void) if (!is_x64) { reg_instr_clob("aaa", rax_mask, 0); - reg_instr("int", "imm8"); reg_instr_clob("into", cc_flag_mask, NULL); } if (is_x64) @@ -356,6 +356,27 @@ static void init_asm_x86(void) reg_instr_clob("subl", rax_cc_mask, "rw:r32/mem, r32/mem/imm32"); reg_instr_clob("subq", rax_cc_mask, "rw:r64/mem, r64/mem/immi32/imm64"); reg_instr("hlt", NULL); + reg_instr("in", "w:r8/r16/r32, r16/imm8"); // Actually ensure reg_al_ax and dx + reg_instr_clob("incb", cc_flag_mask, "rw:r8/mem"); + reg_instr_clob("incw", cc_flag_mask, "rw:r16/mem"); + reg_instr_clob("incl", cc_flag_mask, "rw:r32/mem"); + reg_instr_clob("incq", cc_flag_mask, "rw:r64/mem"); + reg_instr("insb", NULL); + reg_instr("insw", NULL); + reg_instr("insl", NULL); + reg_instr_clob("int", cc_flag_mask, "imm8"); + reg_instr_clob("int3", cc_flag_mask, NULL); + reg_instr_clob("int1", cc_flag_mask, NULL); + reg_instr("invd", NULL); + reg_instr("invpcid", "r32/r64, mem"); + reg_instr("invlpg", "w:mem"); + reg_instr("invlpga", "r32, r64"); // c, a check this one! + reg_instr("iret", NULL); + reg_instr("iretl", NULL); + reg_instr("iretw", NULL); + reg_instr("iretq", NULL); + reg_instr("ret", NULL); + asm_target.clobber_name_list = X86ClobberNames; asm_target.extra_clobbers = "~{flags},~{dirflag},~{fspr}"; if (platform_target.arch == ARCH_TYPE_X86) diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 7cdc3cda1..ff478e0fa 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -162,7 +162,7 @@ typedef struct #define ASM_INSTRUCTION_MAX 0x1000 #define ASM_INSTRUCTION_MASK (ASM_INSTRUCTION_MAX - 1) -#define ASM_REGISTER_MAX 1024 +#define ASM_REGISTER_MAX 4096 #define ASM_REGISTER_MASK (ASM_REGISTER_MAX - 1) typedef struct @@ -172,6 +172,7 @@ typedef struct const char *extra_clobbers; AsmRegister registers[ASM_REGISTER_MAX]; AsmInstruction instructions[ASM_INSTRUCTION_MAX]; + unsigned register_count; } AsmTarget; typedef struct diff --git a/src/compiler/parse_stmt.c b/src/compiler/parse_stmt.c index 8ec646c10..6b92db729 100644 --- a/src/compiler/parse_stmt.c +++ b/src/compiler/parse_stmt.c @@ -254,13 +254,13 @@ static inline Expr *parse_asm_expr(ParseContext *c) static inline Ast *parse_asm_stmt(ParseContext *c) { Ast *asm_stmt = ast_new_curr(c, AST_ASM_STMT); - if (!tok_is(c, TOKEN_IDENT)) + if (!tok_is(c, TOKEN_IDENT) && !tok_is(c, TOKEN_INT)) { SEMA_ERROR_HERE("Expected an asm instruction here."); return poisoned_ast; } asm_stmt->asm_stmt.instruction = symstr(c); - advance_and_verify(c, TOKEN_IDENT); + advance(c); if (try_consume(c, TOKEN_DOT)) { if (!tok_is(c, TOKEN_IDENT)) diff --git a/test/test_suite/asm/asm_ops_x64_1.c3t b/test/test_suite/asm/asm_ops_x64_1.c3t new file mode 100644 index 000000000..c399bc821 --- /dev/null +++ b/test/test_suite/asm/asm_ops_x64_1.c3t @@ -0,0 +1,36 @@ +// #target: macos-x64 +module test; + +fn void main(char[][] args) +{ + int x; + if (args.len < 10) return; + asm + { + in $eax, 3; + in $ax, $dx; + incb $al; + incw $bx; + incl $eax; + incq $rax; + incl [&x]; + insb; + insw; + insl; + int 0x08; + int3; + // int1; Broken in LLVM + invd; + invlpg [&x]; + invpcid $rax, [&x]; + invlpga $ecx, $rax; + iret; + iretl; + iretw; + iretq; + } +} + +/* #expect: test.ll + +"in $$3, %eax\0Ain %dx, %ax\0Aincb %al\0Aincw %bx\0Aincl %eax\0Aincq %rax\0Aincl $0\0Ainsb \0Ainsw \0Ainsl \0Aint $$8\0Aint3 \0Ainvd \0Ainvlpg $0\0Ainvpcid $1, %rax\0Ainvlpga %rax, %ecx\0Airet \0Airetl \0Airetw \0Airetq \0A", "=*&m,*m,~{cc},~{rax},~{rbx},~{flags},~{dirflag},~{fspr}" diff --git a/test/test_suite2/asm/asm_ops_x64_1.c3t b/test/test_suite2/asm/asm_ops_x64_1.c3t new file mode 100644 index 000000000..c399bc821 --- /dev/null +++ b/test/test_suite2/asm/asm_ops_x64_1.c3t @@ -0,0 +1,36 @@ +// #target: macos-x64 +module test; + +fn void main(char[][] args) +{ + int x; + if (args.len < 10) return; + asm + { + in $eax, 3; + in $ax, $dx; + incb $al; + incw $bx; + incl $eax; + incq $rax; + incl [&x]; + insb; + insw; + insl; + int 0x08; + int3; + // int1; Broken in LLVM + invd; + invlpg [&x]; + invpcid $rax, [&x]; + invlpga $ecx, $rax; + iret; + iretl; + iretw; + iretq; + } +} + +/* #expect: test.ll + +"in $$3, %eax\0Ain %dx, %ax\0Aincb %al\0Aincw %bx\0Aincl %eax\0Aincq %rax\0Aincl $0\0Ainsb \0Ainsw \0Ainsl \0Aint $$8\0Aint3 \0Ainvd \0Ainvlpg $0\0Ainvpcid $1, %rax\0Ainvlpga %rax, %ecx\0Airet \0Airetl \0Airetw \0Airetq \0A", "=*&m,*m,~{cc},~{rax},~{rbx},~{flags},~{dirflag},~{fspr}"