diff options
| -rw-r--r-- | amd64.e | 20 | ||||
| -rw-r--r-- | elf.e | 26 | ||||
| -rw-r--r-- | linux.e | 101 | ||||
| -rw-r--r-- | quine.asm | 47 | ||||
| -rw-r--r-- | transform.e | 2 |
5 files changed, 190 insertions, 6 deletions
diff --git a/amd64.e b/amd64.e index 8e53822..4b4a2bd 100644 --- a/amd64.e +++ b/amd64.e @@ -105,7 +105,7 @@ s" :bh" keyword ~ The condition codes. Yes, there sure is a lot of duplication in these ~ names. The names are based on Intel's documented mnemonics... ~ -~ "Above" and "below" are for unsigned comparisons. "Greater" and "less" are +~ "Above" and "below" are for unsigned comparisons. "Greater" and "less" are ~ for signed comparisons. ~ ~ This is documented on the individual opcode pages, and also in B.1.4.7. @@ -475,9 +475,15 @@ s" :cc-greater" keyword ~ (output point, source register -- output point) : push-reg64 reg64 0x50 opcodereg ; +: push-extrareg64 swap rex-b swap extrareg64 0x50 opcodereg ; + ~ Note the use of the B rex bit here; this instruction puts the register + ~ number in the opcode field, so it uses Table 3-1. ~ (output point, target register -- output point) : pop-reg64 reg64 0x58 opcodereg ; +: pop-extrareg64 swap rex-b swap extrareg64 0x58 opcodereg ; + ~ Note the use of the B rex bit here; this instruction puts the register + ~ number in the opcode field, so it uses Table 3-1. ~ (output point, immediate value -- output point) : push-imm32-extended64 swap 0x68 pack8 swap pack32 ; @@ -859,8 +865,16 @@ s" :cc-greater" keyword 3roll rex-w 0x3B pack8 3unroll reg64 swap addressing-reg64 ; -~ Pretend to xor left with right, and set the flags the same way as if we -~ actually had. +~ (output point, left register, right value -- output point) +: cmp-reg64-imm8 + 3roll rex-w 0x83 pack8 + ~ (left register, right value, output point) + 3roll 7 swap addressing-reg64 + ~ ( output point, right value) + pack8 ; + +~ Pretend to bitwise-and left with right, and set the flags the same way as +~ if we actually had. ~ ~ The names of the condition codes can be a little confusing when using them ~ after "test", because they're really premised on the idea that you did diff --git a/elf.e b/elf.e index 68eb6f2..7801bf6 100644 --- a/elf.e +++ b/elf.e @@ -107,6 +107,32 @@ ~ program header's size. current-offset 4 roll - L!' elf-program-header-size ; + +~ This alternate version of the program header isn't used by evoke.e, but +~ may be useful for other programs, such as hex.e. Its only difference from +~ the base version is that it adds the write permission. +: elf-program-header-writable + ~ * denotes mandatory fields according to breadbox + current-offset L!' elf-program-header + current-offset 3unroll + + 1 pack32 ~ *"loadable" segment type + 0x07 pack32 ~ *read+write+execute permission + 0 pack64 ~ *offset in file + L@' origin pack64 ~ *virtual address + ~ required, but can be anything, subject to alignment + 0 pack64 ~ physical address (ignored) + + L@' total-size pack64 ~ *size in file + L@' total-size pack64 ~ *size in memory + + 0 pack64 ~ segment alignment + ~ for relocation, but this doesn't apply to us + + ~ As with the file header, we use the label system to keep track of the + ~ program header's size. + current-offset 4 roll - L!' elf-program-header-size ; + ~ ~~~~~~~~~~~~~~~~ ~ ~~ That's it! ~~ ~ ~~~~~~~~~~~~~~~~ diff --git a/linux.e b/linux.e index c7e9bb3..bf5a3e1 100644 --- a/linux.e +++ b/linux.e @@ -8,9 +8,104 @@ ~ ~ Notice that rsi is our control stack, so we have to save it (for ~ syscalls with at least two parameters). We can use the value stack to do -~ that, since rsp is preserved. We don't save other registers because our -~ caller should do that, if it cares. -~ +~ that, since rsp is preserved, or we can use one of the other registers. We +~ don't ourselves save other registers because our caller should do that, if +~ it cares. + + +~ (call number -- return value) +: syscall-0 + [ here @ + :rax pop-reg64 ~ syscall number + syscall + :rax push-reg64 ~ return value + here ! ] ;asm + +~ (call number, first param -- return value) +: syscall-1 + [ here @ + :rdi pop-reg64 ~ first param + :rax pop-reg64 ~ syscall number + syscall + :rax push-reg64 ~ return value + here ! ] ;asm + +~ (call number, first param, second param -- return value) +: syscall-2 + [ here @ + :rsi :rbx mov-reg64-reg64 ~ save rsi + :rsi pop-reg64 ~ second param + :rdi pop-reg64 ~ first param + :rax pop-reg64 ~ syscall number + syscall + :rbx :rsi mov-reg64-reg64 ~ restore rsi + :rax push-reg64 ~ return value + here ! ] ;asm + +~ (call number, first param, second param, third param -- return value) +: syscall-3 + [ here @ + :rsi :rbx mov-reg64-reg64 ~ save rsi + :rdx pop-reg64 ~ third param + :rsi pop-reg64 ~ second param + :rdi pop-reg64 ~ first param + :rax pop-reg64 ~ syscall number + syscall + :rbx :rsi mov-reg64-reg64 ~ restore rsi + :rax push-reg64 ~ return value + here ! ] ;asm + +~ (call number, first param, second param, third param, fourth param +~ -- return value) +: syscall-4 + [ here @ + :rsi :rbx mov-reg64-reg64 ~ save rsi + :r10 pop-extrareg64 ~ fourth param + :rdx pop-reg64 ~ third param + :rsi pop-reg64 ~ second param + :rdi pop-reg64 ~ first param + :rax pop-reg64 ~ syscall number + syscall + :rbx :rsi mov-reg64-reg64 ~ restore rsi + :rax push-reg64 ~ return value + here ! ] ;asm + + +~ (call number, first param, second param, third param, fourth param, +~ fifth param -- return value) +: syscall-5 + [ here @ + :rsi :rbx mov-reg64-reg64 ~ save rsi + :r8 pop-extrareg64 ~ fifth param + :r10 pop-extrareg64 ~ fourth param + :rdx pop-reg64 ~ third param + :rsi pop-reg64 ~ second param + :rdi pop-reg64 ~ first param + :rax pop-reg64 ~ syscall number + syscall + :rbx :rsi mov-reg64-reg64 ~ restore rsi + :rax push-reg64 ~ return value + here ! ] ;asm + + +~ (call number, first param, second param, third param, fourth param, +~ fifth param, sixth param -- return value) +: syscall-6 + [ here @ + :rsi :rbx mov-reg64-reg64 ~ save rsi + :r9 pop-extrareg64 ~ sixth param + :r8 pop-extrareg64 ~ fifth param + :r10 pop-extrareg64 ~ fourth param + :rdx pop-reg64 ~ third param + :rsi pop-reg64 ~ second param + :rdi pop-reg64 ~ first param + :rax pop-reg64 ~ syscall number + syscall + :rbx :rsi mov-reg64-reg64 ~ restore rsi + :rax push-reg64 ~ return value + here ! ] ;asm + + ~ This does the Linux exit() system call, passing it an exit code taken ~ from the stack. It does not return. diff --git a/quine.asm b/quine.asm index 5c085ef..7d5d9fa 100644 --- a/quine.asm +++ b/quine.asm @@ -3863,6 +3863,14 @@ cold_start: dq litstring, "exit", early_find, entry_to_execution_token, early_comma dq early_here, fetch, lit, 8, packalign, early_here_store + ; This was "rex_b". + dq litstring, "rex-b", early_create, early_docol_codeword + dq litstring, "lit", early_find, entry_to_execution_token, early_comma + dq lit, 0x41, early_comma + dq litstring, "pack8", early_find, entry_to_execution_token, early_comma + dq litstring, "exit", early_find, entry_to_execution_token, early_comma + dq early_here, fetch, lit, 8, packalign, early_here_store + ; This was "rex_wb". dq litstring, "rex-wb", early_create, early_docol_codeword dq litstring, "lit", early_find, entry_to_execution_token, early_comma @@ -4669,6 +4677,18 @@ cold_start: dq litstring, "exit", early_find, entry_to_execution_token, early_comma dq early_here, fetch, lit, 8, packalign, early_here_store + ; This was "push_extrareg64". + dq litstring, "push-extrareg64", early_create, early_docol_codeword + dq litstring, "swap", early_find, entry_to_execution_token, early_comma + dq litstring, "rex-b", early_find, entry_to_execution_token, early_comma + dq litstring, "swap", early_find, entry_to_execution_token, early_comma + dq litstring, "extrareg64", early_find, entry_to_execution_token, early_comma + dq litstring, "lit", early_find, entry_to_execution_token, early_comma + dq lit, 0x50, early_comma + dq litstring, "opcodereg", early_find, entry_to_execution_token, early_comma + dq litstring, "exit", early_find, entry_to_execution_token, early_comma + dq early_here, fetch, lit, 8, packalign, early_here_store + ; This was "pop_reg64". dq litstring, "pop-reg64", early_create, early_docol_codeword dq litstring, "reg64", early_find, entry_to_execution_token, early_comma @@ -4678,6 +4698,19 @@ cold_start: dq litstring, "exit", early_find, entry_to_execution_token, early_comma dq early_here, fetch, lit, 8, packalign, early_here_store + ; This was "pop_extrareg64". + dq litstring, "pop-extrareg64", early_create, early_docol_codeword + dq litstring, "swap", early_find, entry_to_execution_token, early_comma + dq litstring, "rex-b", early_find, entry_to_execution_token, early_comma + dq litstring, "swap", early_find, entry_to_execution_token, early_comma + dq litstring, "extrareg64", early_find, entry_to_execution_token + dq early_comma + dq litstring, "lit", early_find, entry_to_execution_token, early_comma + dq lit, 0x58, early_comma + dq litstring, "opcodereg", early_find, entry_to_execution_token, early_comma + dq litstring, "exit", early_find, entry_to_execution_token, early_comma + dq early_here, fetch, lit, 8, packalign, early_here_store + ; This was push_imm32_extended64". dq litstring, "push-imm32-extended64", early_create, early_docol_codeword dq litstring, "swap", early_find, entry_to_execution_token, early_comma @@ -9856,6 +9889,8 @@ defword conditioncode, 0 ; output point defword rex_w, 0 dq docol, lit, 0x48, pack8, exit +defword rex_b, 0 + dq docol, lit, 0x41, pack8, exit defword rex_wb, 0 dq docol, lit, 0x49, pack8, exit @@ -10332,12 +10367,24 @@ defword push_reg64, 0 ; Stack: ; output point +; source register name +defword push_extrareg64, 0 + dq docol, swap, rex_b, swap, extrareg64, lit, 0x50, opcodereg, exit + +; Stack: +; output point ; target register name defword pop_reg64, 0 dq docol, reg64, lit, 0x58, opcodereg, exit ; Stack: ; output point +; target register name +defword pop_extrareg64, 0 + dq docol, swap, rex_b, swap, extrareg64, lit, 0x58, opcodereg, exit + +; Stack: +; output point ; immediate value defword push_imm32_extended64, 0 dq docol, swap, lit, 0x68, pack8, swap, pack32, exit diff --git a/transform.e b/transform.e index bd1a431..81e99b6 100644 --- a/transform.e +++ b/transform.e @@ -576,7 +576,9 @@ allocate-transform-state s" transform-state" variable dup s" syscall" stringcmp 0 = { drop 0 exit } if dup s" hlt" stringcmp 0 = { drop 0 exit } if dup s" push-reg64" stringcmp 0 = { drop -1 exit } if + dup s" push-extrareg64" stringcmp 0 = { drop -1 exit } if dup s" pop-reg64" stringcmp 0 = { drop -1 exit } if + dup s" pop-extrareg64" stringcmp 0 = { drop -1 exit } if dup s" push-imm32-extended64" stringcmp 0 = { drop -1 exit } if dup s" lea-reg64-disp8-reg64" stringcmp 0 = { drop -3 exit } if dup s" lea-reg64-disp32-reg64" stringcmp 0 = { drop -3 exit } if |