]> git.mdlowis.com Git - proto/forth.git/commitdiff
implemented variable, code, and end-code words
authorMike Lowis <mike.lowis@gentex.com>
Wed, 17 Jul 2024 20:45:06 +0000 (16:45 -0400)
committerMike Lowis <mike.lowis@gentex.com>
Wed, 17 Jul 2024 20:45:06 +0000 (16:45 -0400)
asm.rb
asm.s
test.c

diff --git a/asm.rb b/asm.rb
index 8ad54ef0580d37bfa6ba560f428e47fd1ba4de17..06ac54ba8b613adb7c447fe484fcc8fa4110fdcc 100755 (executable)
--- a/asm.rb
+++ b/asm.rb
@@ -25,6 +25,12 @@ PROG = [
 Word = Struct.new(:name, :flags, :code)
 IMM = 1
 
+class Integer
+  def between(a,b)
+    (self >= a) and (self <= b)
+  end
+end
+
 def push(arg); $stack.push(arg); end
 def pop(); $stack.pop(); end
 def do_word(code); code.each{|w| w.call() }; end
@@ -37,6 +43,110 @@ def builtin(name, &code)
   $words[name] = Word.new(name, 0, code)
 end
 
+def call(word)
+  $words[word].code.call()
+end
+
+def pack8(val, off = nil)
+  PROG[off || PROG.length] = (val & 0xff)
+end
+
+def pack16(val, off = nil)
+  off ||= PROG.length
+  PROG[off + 0] = ((val >> 0) & 0xff)
+  PROG[off + 1] = ((val >> 8) & 0xff)
+end
+
+def pack32(val, off = nil)
+  off ||= PROG.length
+  PROG[off + 0] = ((val >> 0)  & 0xff)
+  PROG[off + 1] = ((val >> 8)  & 0xff)
+  PROG[off + 2] = ((val >> 16) & 0xff)
+  PROG[off + 3] = ((val >> 24) & 0xff)
+end
+
+def pack64(val, off = nil)
+  off ||= PROG.length
+  PROG[off + 0] = ((val >> 0)  & 0xff)
+  PROG[off + 1] = ((val >> 8)  & 0xff)
+  PROG[off + 2] = ((val >> 16) & 0xff)
+  PROG[off + 3] = ((val >> 24) & 0xff)
+  PROG[off + 4] = ((val >> 32) & 0xff)
+  PROG[off + 5] = ((val >> 40) & 0xff)
+  PROG[off + 6] = ((val >> 48) & 0xff)
+  PROG[off + 7] = ((val >> 56) & 0xff)
+end
+
+def packBytes(bytes)
+  PROG.append(*bytes)
+end
+
+def packPadding(overflow)
+  padding = (8 - overflow)
+  padding.times{ pack8(0) } if padding < 8
+end
+
+def unpack8(off)
+  PROG[off]
+end
+
+def unpack16(off)
+  return (
+      PROG[off] |
+      (PROG[off] << 8)
+  )
+end
+
+def unpack32(off)
+  (
+    (PROG[off])       |
+    (PROG[off] << 8)  |
+    (PROG[off] << 16) |
+    (PROG[off] << 24)
+  )
+end
+
+def unpack64(off)
+  (
+    (PROG[off + 0])       |
+    (PROG[off + 1] << 8)  |
+    (PROG[off + 2] << 16) |
+    (PROG[off + 3] << 24) |
+    (PROG[off + 4] << 32) |
+    (PROG[off + 5] << 40) |
+    (PROG[off + 6] << 48) |
+    (PROG[off + 7] << 56)
+  )
+end
+
+def base_offset()
+  unpack64(24)
+end
+
+def mov_imm(val, reg)
+  if val == 0 then
+    if reg <= 7 then
+      packBytes([0x48, 0x31, 0xc0 + (reg * 9)])
+    else
+      packBytes([0x4d, 0x31, 0xc0 + ((reg - 8) * 9)])
+    end
+  elsif val.between(-2147483648,2147483647)
+    if reg <= 7 then
+      packBytes([0x48, 0xC7, 0xc0 | reg])
+    else
+      packBytes([0x49, 0xC7, 0xc0 | (reg - 8)])
+    end
+    pack32(val)
+  else
+    if reg <= 7 then
+      packBytes([0x48, 0xB8 + reg])
+    else
+      packBytes([0x49, 0xB8 + (reg - 8)])
+    end
+    pack64(val)
+  end
+end
+
 #------------------------------------------
 # Interpreter/Compiler State
 #------------------------------------------
@@ -189,7 +299,6 @@ builtin('bin') {
 
 builtin('#') {
   $buffer = $input.gets
-#  puts  "      #{$buffer.inspect}"
 }
 
 builtin('.') {
@@ -201,122 +310,99 @@ builtin('.') {
 }
 
 builtin('word') do
-#  puts "    word"
   word = nil
   while word.nil?
     if $buffer.length == 0 then
       $buffer = $input.gets
-#      puts  "      #{$buffer.inspect}"
       break if $buffer.nil?
     end
     $buffer.slice!(/^\s*/)
     word = $buffer.slice!(/^[^\s]+/)
   end
-#  puts "      word: #{word}"
-#  puts "    end word"
   push word
 end
 
-builtin('create') do
-  $curr = Word.new(pop(), 0, [])
+builtin('variable') do
+  offset = base_offset()
+  call('word')
+  name = pop()
+
+  allocation = (3 + ((name.length + 1) / 8.0).ceil) * 8
+  value_addr = (offset + PROG.length)
+  code_addr  = offset + (allocation * 8)
+
+  pack64(0)             # VALUE
+  pack64(code_addr)     # CODE ADDR
+  pack64(0)             # LINK - TODO: actually link to latest
+  pack8(name.length)    # NAME LEN
+  packBytes(name.bytes) # NAME
+  packPadding(PROG.length % 8)
+
+  mov_imm(value_addr, 0)              # load address
+  packBytes([0x48, 0x8D, 0x6D, 0x08]) # lea 0x8(%rbp),%rbp
+  packBytes([0x48, 0x89, 0x45, 0x00]) # mov %rax,(%rbp)
+  packPadding(PROG.length % 8)
 end
 
-builtin('[') do
-  $state = 1
-end
+builtin('code') do
+  offset = base_offset()
+  call('word')
+  name = pop()
+
+  allocation = (2 + ((name.length + 1) / 8.0).ceil) * 8
+  code_addr  = offset + (allocation * 8)
 
-builtin(']') do
-  $state = 0
+  pack64(code_addr)     # CODE ADDR
+  pack64(0)             # LINK - TODO: actually link to latest
+  pack8(name.length)    # NAME LEN
+  packBytes(name.bytes) # NAME
+  packPadding(PROG.length % 8)
 end
 
-builtin('register') do
-  code = $curr.code
-  $curr.code = lambda { do_word(code) }
-  $words[$curr.name] = $curr
-  pp $words
+builtin('end-code') do
+  call('ret')
+  packPadding(PROG.length % 8)
 end
 
-word(':', IMM, [ 'word', 'create', '[' ])
 
-word(';', IMM, [ ']', 'register' ])
+
+#builtin('create') do
+#  $curr = Word.new(pop(), 0, [])
+#end
+#
+#builtin('[') do
+#  $state = 1
+#end
+#
+#builtin(']') do
+#  $state = 0
+#end
+#
+#builtin('register') do
+#  code = $curr.code
+#  $curr.code = lambda { do_word(code) }
+#  $words[$curr.name] = $curr
+#  pp $words
+#end
+#
+#word(':', IMM, [ 'word', 'create', '[' ])
+#
+#word(';', IMM, [ ']', 'register' ])
 
 
 #------------------------------------------
 # Assembler Words
 #------------------------------------------
 
-def pack8(val, off = nil)
-  PROG[off || PROG.length] = (val & 0xff)
-end
-
-def pack16(val, off = nil)
-  off ||= PROG.length
-  PROG[off + 0] = ((val >> 0) & 0xff)
-  PROG[off + 1] = ((val >> 8) & 0xff)
-end
-
-def pack32(val, off = nil)
-  off ||= PROG.length
-  PROG[off + 0] = ((val >> 0)  & 0xff)
-  PROG[off + 1] = ((val >> 8)  & 0xff)
-  PROG[off + 2] = ((val >> 16) & 0xff)
-  PROG[off + 3] = ((val >> 24) & 0xff)
-end
-
-def pack64(val, off = nil)
-  off ||= PROG.length
-  PROG[off + 0] = ((val >> 0)  & 0xff)
-  PROG[off + 1] = ((val >> 8)  & 0xff)
-  PROG[off + 2] = ((val >> 16) & 0xff)
-  PROG[off + 3] = ((val >> 24) & 0xff)
-  PROG[off + 4] = ((val >> 32) & 0xff)
-  PROG[off + 5] = ((val >> 40) & 0xff)
-  PROG[off + 6] = ((val >> 48) & 0xff)
-  PROG[off + 7] = ((val >> 56) & 0xff)
-end
-
-def packBytes(bytes)
-  PROG.append(*bytes)
-end
-
-def unpack8(off)
-  PROG[off]
-end
-
-def unpack16(off)
-  return (
-      PROG[off] |
-      (PROG[off] << 8)
-  )
-end
-
-def unpack32(off)
-  (
-    (PROG[off])       |
-    (PROG[off] << 8)  |
-    (PROG[off] << 16) |
-    (PROG[off] << 24)
-  )
-end
-
-def unpack64(off)
-  (
-    (PROG[off + 0])       |
-    (PROG[off + 1] << 8)  |
-    (PROG[off + 2] << 16) |
-    (PROG[off + 3] << 24) |
-    (PROG[off + 4] << 32) |
-    (PROG[off + 5] << 40) |
-    (PROG[off + 6] << 48) |
-    (PROG[off + 7] << 56)
-  )
-end
-
-
 builtin("here") {
   push PROG.length
 }
 
+#builtin("allot") {
+#  packBytes(Array.new(pop()*8, 0))
+#}
+
+
 builtin("@") {
   push unpack64(pop())
 }
@@ -340,24 +426,11 @@ builtin("-!") {
 }
 
 
+builtin("set-entry-address") {
+  prev = unpack64(24)
+  pack64(prev + (PROG.length - 0x78), 24)
+}
 
-#
-#  0x7F, 0x45, 0x4C, 0x46, 0x02, 0x01, 0x01, 0x00, # 00
-#  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 08
-#  0x02, 0x00, 0x3E, 0x00, 0x01, 0x00, 0x00, 0x00, # 16
-#  0x78, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, # 24    e_entry: 0x0x00400078, (virtual memory address of entry point)
-#  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 32
-#  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 40
-#  0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, # 48
-#  0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, # 56
-#  0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, # 64
-#  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 72
-#  0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, # 78    p_vaddr:  0x00400000, (virtual address of segment in memory)
-#  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 86
-#  0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 94    p_filesz: 0x00011E02, (size in bytes of the segment in the file)
-#  0x00, 0x00, 0xC0, 0x7F, 0x00, 0x00, 0x00, 0x00, # 102   p_memsz:  0x7FC00000, (siz
-
-builtin("entry-address") { push 24 }
 builtin("virt-address")  { push 78 }
 builtin("segment-size")  { push 102 }
 
@@ -404,20 +477,7 @@ builtin('pop-reg') {
 builtin('load-imm') {
   reg = pop()
   val = pop()
-  if val == 0 then
-    if reg <= 7 then
-      packBytes([0x48, 0x31, 0xc0 + (reg * 9)])
-    else
-      packBytes([0x4d, 0x31, 0xc0 + ((reg - 8) * 9)])
-    end
-  else
-    if reg <= 7 then
-      packBytes([0x48, 0xC7, 0xc0 | reg])
-    else
-      packBytes([0x49, 0xC7, 0xc0 | (reg - 8)])
-    end
-    pack32(val)
-  end
+  mov_imm(val, reg)
 }
 
 builtin('syscall') {
diff --git a/asm.s b/asm.s
index f0bcc34953746c5d9e7d9988f22840c1655ebdb8..c848cac9aff4506401e552706f58d962eda3fd88 100644 (file)
--- a/asm.s
+++ b/asm.s
@@ -1,16 +1,29 @@
-# record our current offset for later use
-here
+# WORD DEFINITION STRUCTURE
+#
+# +----------------------+
+# | FLAGS | CODE ADDRESS |
+# +----------------------+
+# | LINK                 |
+# +----------------------+
+# | NAME LEN | NAME .... |
+# | .................... |
+# +----------------------+
+# | CODE ............... |
+# +----------------------+
+
+# ----------------------------------------
+# SYSTEM CONSTANTS
+# ----------------------------------------
 
 # ----------------------------------------
 # SYSTEM VARIABLES
 # ----------------------------------------
 
-# Allocate space for variables
-0 pack64    # LATEST
-0 pack64    # STATE
-0 pack64    # HERE
-0 pack64    # S0
-0 pack64    # R0
+variable latest
+variable state
+variable here
+variable S0
+variable R0
 
 # ----------------------------------------
 # DEFINE BUILTIN WORDS
@@ -23,12 +36,31 @@ here
 #   interpret
 # end
 
+# : ]
+#     begin
+#        bl find dup if
+#           -1 = if
+#             execute ?stack abort " Stack empty"
+#           else
+#             ,
+#           then
+#        else
+#          drop (number) postpone literal
+#        then
+#     again ;
+
+# : interpret
+#     begin
+#        bl find if  execute
+#           ?stack abort " Stack empty"
+#        else  number  then
+#     again ;
+
 # ----------------------------------------
 # ENTRY CODE STARTS HERE
 # ----------------------------------------
 
-# update our entry address to here
-here swap - entry-address +!
+set-entry-address
 
 60 rax load-imm
 42 rdi load-imm
diff --git a/test.c b/test.c
index ad595388222816877f69d8e725b1c5ca8487d613..dd07d7752db59e1e27f44df920fd284d6f2a0206 100644 (file)
--- a/test.c
+++ b/test.c
@@ -1,5 +1,13 @@
 void test(void)
 {
+//    leaq -8(%rbp),%rbp       /* push reg on to return stack */
+//    movq \reg,(%rbp)
+
+
+    asm("lea 8(%rbp), %rbp");
+    asm("mov %rax, (%rbp)");
+
+
 //    asm("mov     $60, %eax");
 //    asm("xor     %rdi, %rdi");
 //    asm("syscall");
@@ -13,9 +21,10 @@ void test(void)
 //    asm("push %rbx");
 //    asm("mov     $0x01020304, %rcx");
 //    asm("push %rcx");
-//    asm("mov     $0x0123456789, %rdx");
 //    asm("push %rdx");
 
+
+
     asm("xor %rax,%rax");
     asm("xor %rcx,%rcx");
     asm("xor %rdx,%rdx");
@@ -33,40 +42,22 @@ void test(void)
     asm("xor %r14,%r14");
     asm("xor %r15,%r15");
 
-    asm("pop %rax");
-    asm("pop %rcx");
-    asm("pop %rdx");
-    asm("pop %rbx");
-    asm("pop %rsp");
-    asm("pop %rbp");
-    asm("pop %rsi");
-    asm("pop %rdi");
-    asm("pop %r8");
-    asm("pop %r9");
-    asm("pop %r10");
-    asm("pop %r11");
-    asm("pop %r12");
-    asm("pop %r13");
-    asm("pop %r14");
-    asm("pop %r15");
-
-
-    asm("mov $0x2A,  %rax");
-    asm("mov $0x2A,  %rcx");
-    asm("mov $0x2A,  %rdx");
-    asm("mov $0x2A,  %rbx");
-    asm("mov $0x2A,  %rsp");
-    asm("mov $0x2A,  %rbp");
-    asm("mov $0x2A,  %rsi");
-    asm("mov $0x2A,  %rdi");
-    asm("mov $0x2A,  %r8");
-    asm("mov $0x2A,  %r9");
-    asm("mov $0x2A,  %r10");
-    asm("mov $0x2A,  %r11");
-    asm("mov $0x2A,  %r12");
-    asm("mov $0x2A,  %r13");
-    asm("mov $0x2A,  %r14");
-    asm("mov $0x2A,  %r15");
+    asm("mov $0x01,  %rax");
+    asm("mov $0x01,  %rcx");
+    asm("mov $0x01,  %rdx");
+    asm("mov $0x01,  %rbx");
+    asm("mov $0x01,  %rsp");
+    asm("mov $0x01,  %rbp");
+    asm("mov $0x01,  %rsi");
+    asm("mov $0x01,  %rdi");
+    asm("mov $0x01,  %r8");
+    asm("mov $0x01,  %r9");
+    asm("mov $0x01,  %r10");
+    asm("mov $0x01,  %r11");
+    asm("mov $0x01,  %r12");
+    asm("mov $0x01,  %r13");
+    asm("mov $0x01,  %r14");
+    asm("mov $0x01,  %r15");
 
     asm("syscall");