summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--amd64.e20
-rw-r--r--elf.e26
-rw-r--r--linux.e101
-rw-r--r--quine.asm47
-rw-r--r--transform.e2
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