diff --git a/lang/src/codegen.asm b/lang/src/codegen.asm index 2bafc2f..09f6a67 100644 --- a/lang/src/codegen.asm +++ b/lang/src/codegen.asm @@ -213,11 +213,11 @@ codegen_arg_to_operand: xor rax, rax mov eax, 0 ; Operand.len = 0 shl eax, 16 - or eax, 8 ; Operand.width = 8 - shl eax, 4 - or eax, edi ; Operand.register + or eax, 8 ; Operand.width = 8 shl eax, 8 - or eax, OPERAND_REGISTER ; Operand.kind + or eax, edi ; Operand.register + shl eax, 8 + or eax, OPERAND_REGISTER ; Operand.kind mov rdx, 0 ; Operand.value = 0 jmp .epilogue @@ -233,8 +233,8 @@ codegen_arg_to_operand: xor rax, rax mov eax, 0 ; Operand.len = 0 shl eax, 16 - or eax, 8 ; Operand.width = 8 - shl eax, 4 + or eax, 8 ; Operand.width = 8 + shl eax, 8 ; or eax, 0 ; Operand.register = undef shl eax, 8 or eax, OPERAND_RBP_OFFSET ; Operand.kind @@ -352,7 +352,7 @@ codegen_allocate_place: mov eax, 0 ; Operand.len = 0 shl eax, 16 or eax, esi ; Operand.width - shl eax, 4 + shl eax, 8 ; or eax, 0 ; Operand.register = undef shl eax, 8 or eax, OPERAND_RBP_OFFSET ; Operand.kind @@ -393,7 +393,7 @@ codegen_allocate_value: shl eax, 16 mov rsi, [rsp + 8] ; width or eax, esi ; Operand.width - shl eax, 4 + shl eax, 8 or eax, ebx ; Operand.register shl eax, 8 or eax, OPERAND_REGISTER ; Operand.kind @@ -435,17 +435,13 @@ codegen_free_operand: cmp rbx, rax jne .done ; operand not at top of stack, can't free - mov al, byte [rsi + 1] ; Operand.width - shr al, 4 - movzx rax, al + movzx rax, word [rsi + 2] ; Operand.width sub rbx, rax mov dword [rdi + 0], ebx ; current_stack_size -= width jmp .done .free_reg: - xor rax, rax - mov al, byte [rsi + 1] ; Operand.register_and_width - and al, 0x0F ; get register index + movzx rax, byte [rsi + 1] ; Operand.register mov bx, word [rdi + 48] ; register_bitset btr bx, ax jnc .panic ; trying to free unallocated register @@ -1055,14 +1051,7 @@ codegen_expr: call vec_extend ; construct return operand - ; Operand { kind: REGISTER, register_and_width: (register | (width << 4)), len: 0, value: 0 } - mov eax, 0 ; len = 0 - shl eax, 16 - or eax, 8 ; width = 8 - shl eax, 4 - or eax, 0 ; register = rax - shl eax, 8 - or eax, OPERAND_REGISTER ; kind + mov rax, [rel OPERAND_RAX] mov rdx, 0 ; value = 0 jmp .done @@ -1071,10 +1060,9 @@ codegen_expr: mov [rsp + 16], rax ; scratch = *AstNode mov byte [rsp + 32], OPERAND_IMMEDIATE ; Operand.kind - mov bl, 8 ; width = 8 - shl bl, 4 ; register = undef - mov byte [rsp + 33], bl ; Operand.register_and_width - mov word [rsp + 34], 0 ; Operand.len = 0 + mov byte [rsp + 33], 0 ; Operand.register = undef + mov word [rsp + 34], 8 ; Operand.width = 8 + mov word [rsp + 36], 0 ; Operand.len = 0 mov rbx, [rax + 8] ; AstNode.data mov [rsp + 40], rbx ; Operand.value @@ -1166,10 +1154,10 @@ codegen_expr: lea rsi, [rsp + 48] ; right operand call codegen_free_operand - mov rdx, [rsp + 48] ; right operand - and rdx, 0xF000 ; Operand.width + ; move scratch to rhs, but preserve width + movzx rdx, word [rsp + 48 + 2] ; rhs.width + mov word [rsp + 64 + 2], dx ; scratch.width mov rax, [rsp + 64] ; scratch value - or rax, rdx ; preserve width mov rdx, [rsp + 72] mov [rsp + 48], rax ; right operand mov [rsp + 56], rdx @@ -1332,7 +1320,7 @@ codegen_expr: call vec_get mov rdx, [rax + 8] ; offset neg rdx - mov rax, qword [rel OPERAND_RBP_OFFSET] + mov rax, qword [rel OPERAND_RBP] mov [rsp + 16], rax mov [rsp + 24], rdx @@ -1372,7 +1360,8 @@ codegen_expr: ;; start-structs ;; struct Operand { ;; kind: u8 -;; register_and_width: u8, +;; register: u8, +;; width: u16, ;; len: u16, ;; value: u64, ;; } @@ -1387,12 +1376,22 @@ section .rdata OPERAND_IMMEDIATE equ 5 ; e.g. 0x10 OPERAND_CONSTANT equ 6 ; e.g. OPERAND_CONSTANT OPERAND_LABEL equ 7 ; e.g. label_1234 + OPERAND_REGISTER_PLACE equ 8 ; e.g. [rax] + OPERAND_RBP_PLACE equ 9 ; e.g. mov rax, [rbp - 8]; mov [rax], src ;; end-consts WIDTH_BYTE db 'byte ' WIDTH_WORD db 'word ' WIDTH_DWORD db 'dword ' WIDTH_QWORD db 'qword ' + ; Operand { kind: REGISTER, register: 0, width: 8, len: 0, padding: 0, value: 0 } + align 8 + OPERAND_RAX dq 0x0008_0001, 0 + align 8 + OPERAND_RDX dq 0x0008_0301, 0 + align 8 + OPERAND_RBP dq 0x0008_0002, 0 + section .text ;; rdi: *text @@ -1424,14 +1423,39 @@ codegen_write_operand: je .constant cmp bl, OPERAND_LABEL je .label + cmp bl, OPERAND_REGISTER_PLACE + je .reg_p + cmp bl, OPERAND_RBP_PLACE + je .rbp_offset jmp .panic +.reg_p: + mov rbx, rsi + + mov byte [rsp + 16], '[' + mov rdi, [rsp] ; *text + lea rsi, [rsp + 16] + call vec_push + + movzx rdi, byte [rbx + 1] ; Operand.register + movzx rsi, word [rbx + 2] ; Operand.width + lea rdx, [rsp + 16] ; buffer + call get_register_name + + mov rdi, [rsp] ; *text + mov rsi, rax ; buffer + call vec_extend + + mov byte [rsp + 16], ']' + mov rdi, [rsp] ; *text + lea rsi, [rsp + 16] + call vec_push + + .register: mov rbx, rsi - mov rdi, [rbx + 1] ; register_and_width - mov rsi, rdi - and dil, 0x0F ; low 4 bits = register - shr rsi, 4 ; high 4 bits = width + movzx rdi, byte [rbx + 1] ; Operand.register + movzx rsi, word [rbx + 2] ; Operand.width lea rdx, [rsp + 16] ; buffer call get_register_name @@ -1444,8 +1468,7 @@ codegen_write_operand: .rsp_offset: ; {width} [rbp {+/-} offset] mov rsi, [rsp + 8] ; op - mov sil, byte [rsi + 1] ; Operand.register_and_width - shr sil, 4 ; width + movzx rsi, word [rsi + 2] ; Operand.width mov rdi, [rsp] ; *text call codegen_write_width mov rbx, rax @@ -1521,8 +1544,8 @@ codegen_write_operand: ; write address name mov rax, [rsp + 8] ; op mov rdi, [rsp] ; *text - mov rsi, [rax + 8] ; op.value - mov rdx, [rax + 2] ; op.len + mov rsi, [rax + 8] ; Operand.value + mov rdx, [rax + 4] ; Operand.len mov dx, dx ; low 16 bits call vec_extend @@ -1607,10 +1630,10 @@ codegen_move_rbp_slot_src: ; construct dst Operand mov byte [rsp + 0], OPERAND_RBP_OFFSET ; Operand.kind - mov byte [rsp + 1], 0x80 ; Operand.register_and_width (width=8) - mov word [rsp + 2], 0 ; Operand.len = 0 - mov dword [rsp + 4], 0 ; padding - mov qword [rsp + 8], rdx ; Operand.value = rbp offset + mov byte [rsp + 1], 0 ; Operand.register = undef + mov word [rsp + 2], 8 ; Operand.width = 8 + mov word [rsp + 4], 0 ; Operand.len = 0 + mov qword [rsp + 8], rdx ; Operand.value = rbp offset mov rdx, rsi lea rsi, [rsp + 0] ; dst @@ -1849,19 +1872,17 @@ codegen_move_dst_src: jg .panic ; unsupported dst kind ; if dst.width != src.width - mov cl, byte [rsi + 1] ; dst.register_and_width - mov bl, byte [rdx + 1] ; src.register_and_width - shr cl, 4 - shr bl, 4 - cmp cl, bl + mov cx, word [rsi + 2] ; dst.width + mov bx, word [rdx + 2] ; src.width + cmp cx, bx jne .panic ; mismatched widths - ; if dst.width == 8 && src.kind == OPERAND_ADDRESS - xor rbx, rbx - cmp cl, 8 - cmovne rbx, [rdx + 0] - cmp bl, OPERAND_ADDRESS - je .panic ; address can only be moved to full-sized destinations + ; ; if dst.width == 8 && src.kind == OPERAND_ADDRESS + ; xor rbx, rbx + ; cmp cx, 8 + ; cmovne rbx, [rdx + 0] + ; cmp bl, OPERAND_ADDRESS + ; je .panic ; address can only be moved to full-sized destinations cmp byte [rsi + 0], OPERAND_REGISTER je .do_move ; if dst == register, do move @@ -1935,11 +1956,3 @@ section .rdata MUL_ dq "mul " DIV_ dq "div " - - ; Operand { kind: REGISTER, register: 0, width: 8, len: 0, padding: 0, value: 0 } - align 8 - OPERAND_RAX dq 0x0000_8001, 0 - align 8 - OPERAND_RDX dq 0x0000_8301, 0 - align 8 - OPERAND_RBP_OFFSET dq 0x0000_8002, 0 diff --git a/lang/tests/shared/defs.rs b/lang/tests/shared/defs.rs index 0aed8ef..ea4a3a3 100644 --- a/lang/tests/shared/defs.rs +++ b/lang/tests/shared/defs.rs @@ -64,6 +64,8 @@ pub const OPERAND_ADDRESS: u32 = 4; pub const OPERAND_IMMEDIATE: u32 = 5; pub const OPERAND_CONSTANT: u32 = 6; pub const OPERAND_LABEL: u32 = 7; +pub const OPERAND_REGISTER_PLACE: u32 = 8; +pub const OPERAND_RBP_PLACE: u32 = 9; pub const TOKEN_EOF: u8 = 0; pub const TOKEN_LET: u8 = 1; pub const TOKEN_IF: u8 = 2; @@ -247,7 +249,8 @@ pub struct FunctionCtx { #[derive(Debug)] pub struct Operand { pub kind: u8, - pub register_and_width: u8, + pub register: u8, + pub width: u16, pub len: u16, pub value: u64, }