diff --git a/twasm/README.md b/twasm/README.md index 2edc4ee..7295afd 100644 --- a/twasm/README.md +++ b/twasm/README.md @@ -267,8 +267,8 @@ entries are as follows: +----------+----------+----------+---------+ | 31 24 | 23 16 | 15 0 | +----------+----------+--------------------+ -| reserved | opcode | token ID | -| | dst=r/m | | +| opcode+r | opcode | token ID | +| dst=r | dst=r/m | | +----------+----------+--------------------+ 16 bytes @@ -300,24 +300,25 @@ entries are as follows: +-----------------+ | flags byte | +----------+------+ -| 95 89 | 88 | +| 95 89 | 88 | +----------+------+ | reserved | 8bit | +----------+------+ 1 byte -+----------------------------------------------------+ -| flagsX byte | -+----------+-----------+-------------+---------------+ -| 7 5 | 4 | 3 | 2 0 | -+----------+-----------+-------------+---------------+ -| reserved | no ModR/M | 0x0F prefix | operator flag | -+----------+-----------+-------------+---------------+ ++--------------------------------------------------------------+ +| flagsX byte | ++----------+---------+-----------+-------------+---------------+ +| 7 6 | 5 | 4 | 3 | 2 0 | ++----------+---------+-----------+-------------+---------------+ +| reserved | +r flag | no ModR/M | 0x0F prefix | operator flag | ++----------+---------+-----------+-------------+---------------+ ; flags key: 8bit ; tte has opcodes for r/m8 and r8 instead of r/m and r respectively ; flagsX key: ++r flag ; there is a +r variation of this opcode no ModR/M ; there is no ModR/M byte for this opcode 0x0F prefix ; there is a 0x0F prefix for this opcode operator flag ; contents of `reg` if applicable diff --git a/twasm/asm/main.asm b/twasm/asm/main.asm index a0b267e..0e060dc 100644 --- a/twasm/asm/main.asm +++ b/twasm/asm/main.asm @@ -63,7 +63,7 @@ start: pop rdi ; rdi = number of tokens in token table call assemble - mov rsi, msg_welcome + mov rsi, msg_welcome_1 call OUTPUT_ADDR jmp halt @@ -123,6 +123,8 @@ assemble: call print.debug pop rsi + mov esi, [.buffer_pointer] + sub esi, .buffer mov esi, [.next_output_byte] sub esi, OUTPUT_ADDR ; esi = relative address of label to start of program and edi, 0x0FFF ; edi = index to add address hash to @@ -210,7 +212,8 @@ assemble: call .get_next_tte mov rcx, rdi ; cx = operand tte pop rdi - push rcx ; pushes until after write_prefix_continue + push rcx ; pushes until after write_prefix_continue or before + ; plusr_continue ; di = tte of operator mov sil, 0 ; dst=r/m @@ -225,9 +228,40 @@ assemble: .operator_1_get_opcode_label: mov sil, 4 ; dst=rel .operator_1_get_opcode_continue: + push rdi + push rbx call get_opcode ; al = opcode ; dl = op flag + pop rbx ; flags + pop rdi ; di + + push rdx + and dl, 0x20 + cmp dl, 0x20 + pop rdx + jne .operator_1_plusr_continue + + mov sil, 1 ; dst=r + ; TODO only do this if we've confirmed the next token's a register xD + call .clear_write_buffer + call get_opcode + ; al = opcode + ; dl = op flag + pop rdi ; di = next tte. from early in .operator_1 + push rax + ; di = tte + call get_tte_typed_metadata + ; al = register typed metadata + mov ecx, eax ; cl = register typed metadata + shr ecx, 2 + and ecx, 111b ; cl = reg value + pop rax ; al = opcode + add eax, ecx ; opcode + r + call .write_byte + + jmp .loop_next_token + .operator_1_plusr_continue: push rdx and dl, 1000b cmp dl, 1000b @@ -240,8 +274,7 @@ assemble: .operator_1_write_prefix_continue call .write_byte pop rdx ; dl = op flag - - pop rdi ; di = next tte + pop rdi ; di = next tte. from early in .operator_1 push rdi and di, 0xFF00 @@ -318,7 +351,9 @@ assemble: call print.debug pop rsi - mov esi, [.next_output_byte] + mov esi, [.buffer_pointer] + sub esi, .buffer + add esi, [.next_output_byte] sub esi, OUTPUT_ADDR ; esi = relative address of label reference to start ; of program mov eax, 0x04 ; al = first 4 bits: # bytes reserved @@ -596,7 +631,9 @@ assemble: jmp .operator_2_register_label_32 .operator_2_register_label_8: - mov esi, [.next_output_byte] + mov esi, [.buffer_pointer] + sub esi, .buffer + add esi, [.next_output_byte] sub esi, OUTPUT_ADDR ; esi = relative address of label reference to start mov eax, 0x11 ; al = first 4 bits: # bits reserved ; 5th bit: abs flag @@ -606,7 +643,9 @@ assemble: call .write_byte jmp .loop_next_token .operator_2_register_label_16: - mov esi, [.next_output_byte] + mov esi, [.buffer_pointer] + sub esi, .buffer + add esi, [.next_output_byte] sub esi, OUTPUT_ADDR ; esi = relative address of label reference to start mov eax, 0x12 ; al = first 4 bits: # bits reserved ; 5th bit: abs flag @@ -617,7 +656,9 @@ assemble: call .write_byte jmp .loop_next_token .operator_2_register_label_32: - mov esi, [.next_output_byte] + mov esi, [.buffer_pointer] + sub esi, .buffer + add esi, [.next_output_byte] sub esi, OUTPUT_ADDR ; esi = relative address of label reference to start mov eax, 0x14 ; al = first 4 bits: # bits reserved ; 5th bit: abs flag @@ -990,19 +1031,8 @@ assemble: .tokens_processed dd 0 .tokens_total dd 0 - ; al = byte to write - .output_byte: - push rdx - mov edx, [.next_output_byte] ; get output byte's address - mov [edx], al ; write byte to that address - inc edx ; increment address - mov [.next_output_byte], edx ; put output byte's address - pop rdx - ret - .next_output_byte dd OUTPUT_ADDR ; next empty byte in output - ; TODO get rid of this sketchy bit of state - ; al = byte to push + ; buffered push .push_byte: push rcx mov ecx, [.buffer_pointer] @@ -1027,6 +1057,7 @@ assemble: ret ; al = byte to write + ; buffered write .write_byte: push rdx mov edx, [.buffer_pointer] @@ -1036,6 +1067,16 @@ assemble: pop rdx ret + .clear_write_buffer: + push rax + xor eax, eax + mov [.buffer], rax + mov [.buffer + 8], rax + mov eax, .buffer + mov [.buffer_pointer], eax + pop rax + ret + .flush_write_buffer: push rcx push rax @@ -1054,10 +1095,23 @@ assemble: pop rax pop rcx ret - .buffer dq 0, 0 ; octo word of space for max of 8 bytes per write + .buffer dq 0, 0 ; octo word of space for max of 16 bytes per write .buffer_end: .buffer_pointer dd .buffer ; points to current byte in buffer + ; al = byte to write + ; unbuffered output; prefer `.write_byte` + .output_byte: + push rdx + mov edx, [.next_output_byte] ; get output byte's address + mov [edx], al ; write byte to that address + inc edx ; increment address + mov [.next_output_byte], edx ; put output byte's address + pop rdx + ret + .next_output_byte dd OUTPUT_ADDR ; next empty byte in output + + .msg_unexpected_token db "unexpected token, aborting", 0x0A, 0x00 .msg_unsupported_memory_access db "unsupported memory access, aborting", 0x0A, 0x00 .msg_size_mismatch db "size mismatch, aborting", 0x0A, 0x00 @@ -1097,9 +1151,6 @@ resolve_awaiting_labels: cmp rdi, 0 je .break - mov rsi, .msg - call print.warn - push rax ; rdi = raxth hash in awaiting label table call add_label_hash @@ -1111,8 +1162,6 @@ resolve_awaiting_labels: mov esi, [AWAITING_LABEL_TABLE_ADDR + rax + 8] ; esi = address of reference sub edi, esi ; edi = offset - ; TODO fix this off-by-one error - dec edi ; also sub length of reference TODO handle non-4-length refs sub edi, 4 @@ -1132,7 +1181,7 @@ resolve_awaiting_labels: pop rdx jne .break - mov [OUTPUT_ADDR + 1 + rsi], edi + mov [OUTPUT_ADDR + rsi], edi shr rax, 4 inc rax @@ -1140,7 +1189,6 @@ resolve_awaiting_labels: .break: mov rsp, rbp ret - .msg db "resolve_awaiting_labels", 0x0A, 0x00 ; ------------------------------------------------------------------------------ ; get_tte_type @@ -1319,13 +1367,13 @@ get_ModRM: ; returned: ; al = opcode; the rest of rax is zeroed. ; dl = flagsX -; +----------------------------------------------------+ -; | flagsX byte | -; +----------+-----------+-------------+---------------+ -; | 7 5 | 4 | 3 | 2 0 | -; +----------+-----------+-------------+---------------+ -; | reserved | no ModR/M | 0x0F prefix | operator flag | -; +----------+-----------+-------------+---------------+ +; +--------------------------------------------------------------+ +; | flagsX byte | +; +----------+---------+-----------+-------------+---------------+ +; | 7 6 | 5 | 4 | 3 | 2 0 | +; +----------+---------+-----------+-------------+---------------+ +; | reserved | +r flag | no ModR/M | 0x0F prefix | operator flag | +; +----------+---------+-----------+-------------+---------------+ ; ; ------------------------------------------------------------------------------ @@ -2216,25 +2264,6 @@ print: .test_msg db 0x1B, "[1;33m", "[TEST]: ", 0x1B, "[0m", 0x00 .warn_msg db 0x1B, "[1;35m", "[WARN]: ", 0x1B, "[0m", 0x00 -; ------------------------------------------------------------------------------ -; print_least_4_bits -; -; description: -; prints the least significant 4 bits of rax for debugging reasons -; ------------------------------------------------------------------------------ - -print_least_4_bits: - push rax - push rsi - add eax, 0x30 - mov [.byte], al - mov rsi, .byte - call print.warn - pop rsi - pop rax - ret - .byte db 0x00, 0x0A, 0x00 - ; ------------------------------------------------------------------------------ ; halt ; @@ -3186,30 +3215,30 @@ opcodes: dw 0x0000 ; push - ; TODO add support for the +r variation dw 0x005F db 0xFF ; r/m - db 0x00 + db 0x50 ; +r db 0x68 ; imm16/32 db 0x6A ; imm8 dw 0x0000 - db 0x06 ; 6: r/m + db 0x26 ; 26: +r flag, r/m db 0x00 dw 0x0000 dd 0x00000000 ; pop - ; TODO add support for the +r variation dw 0x0060 db 0x8F ; r/m + db 0x58 ; +r + + dd 0x00000000 + + db 0x20 ; 20: +r flag, r/m db 0x00 - - dd 0x00000000 - - dd 0x00000000 + dw 0x0000 dd 0x00000000 @@ -3229,6 +3258,7 @@ opcodes: .by_id_end: msg_welcome db 0x1B, "[35m", "Welcome to Twasm", 0x1B, "[0m", 0x0A, 0x00 +msg_welcome_1 db 0x1B, "[35m", "Welcome to Twasm (from the next level)", 0x1B, "[0m", 0x0A, 0x00 msg_halt db "halted.", 0x0A, 0x00 whitespace_2 db " ", 0x0D @@ -3236,7 +3266,6 @@ whitespace_2 db " ", 0x0D ; test program align 128 program: - db "ret", 0x0A db "print:", 0x0A db " push rdx", 0x0A db " push rax", 0x0A