]> git.mdlowis.com Git - proto/forth.git/commitdiff
added space allocations for system variables and stubbed out where builtin word defin...
authorMike Lowis <mike.lowis@gentex.com>
Tue, 16 Jul 2024 20:33:05 +0000 (16:33 -0400)
committerMike Lowis <mike.lowis@gentex.com>
Tue, 16 Jul 2024 20:33:05 +0000 (16:33 -0400)
asm.rb
asm.s
jonesforth.S

diff --git a/asm.rb b/asm.rb
index cb7eb4389fd01bf1c6fefda1581e0f92462aabc8..8ad54ef0580d37bfa6ba560f428e47fd1ba4de17 100755 (executable)
--- a/asm.rb
+++ b/asm.rb
@@ -37,40 +37,62 @@ def builtin(name, &code)
   $words[name] = Word.new(name, 0, code)
 end
 
-$input = $stdin
-$stack = []
-$state = 0
-$curr = nil
+#------------------------------------------
+# Interpreter/Compiler State
+#------------------------------------------
+$base   = 10
+$input  = $stdin
+$stack  = []
+$state  = 0
+$curr   = nil
 $buffer = ""
-$words = {
-#    'load-imm' => lambda {
-#        puts "load-imm"
-#        PROG.push(0x48)
-#        PROG.push(0xc7)
-#        PROG.push(0xC0 + $stack.pop)
-#        imm = $stack.pop
-#        PROG.push((imm >> 0) & 0xff)
-#        PROG.push((imm >> 8) & 0xff)
-#        PROG.push((imm >> 16) & 0xff)
-#        PROG.push((imm >> 24) & 0xff)
-#    },
-}
-
+$words  = {}
 
 #------------------------------------------
 # Stack Manipulation
 #------------------------------------------
-builtin('drop') { }
-builtin('swap') { }
-builtin('dup') { }
-builtin('over') { }
-builtin('rot') { }
-builtin('-rot') { }
-
-builtin('2drop') { }
-builtin('2swap') { }
-builtin('2dup') { }
-builtin('?dup') { }
+builtin('drop') {
+  pop()
+}
+
+builtin('swap') {
+  a = pop()
+  b = pop()
+  push a
+  push b
+}
+
+builtin('dup')  {
+  push $stack.last
+}
+
+builtin('over') {
+  push $stack[-2]
+}
+
+builtin('rot')  {
+
+}
+
+builtin('-rot') {
+
+}
+
+builtin('2drop') {
+
+}
+
+builtin('2swap') {
+
+}
+
+builtin('2dup') {
+
+}
+
+builtin('?dup') {
+
+}
 
 builtin('1+') { }
 builtin('1-') { }
@@ -83,10 +105,10 @@ builtin('8-') { }
 # Aritmetic
 #------------------------------------------
 builtin('+') { push(pop() + pop()) }
-builtin('-') { push(pop() - pop()) }
+builtin('-') { a = pop(); push(pop() - a) }
 builtin('*') { push(pop() * pop()) }
-builtin('/') { push(pop() / pop()) }
-builtin('%') { push(pop() % pop()) }
+builtin('/') { a = pop(); push(pop() / a) }
+builtin('%') { a = pop(); push(pop() % a) }
 
 #------------------------------------------
 # Comparison
@@ -105,7 +127,6 @@ builtin('0>')  { push(pop()  > 0) }
 builtin('0<=') { push(pop() <= 0) }
 builtin('0>=') { push(pop() >= 0) }
 
-
 #------------------------------------------
 # Bitwise Operations
 #------------------------------------------
@@ -127,7 +148,6 @@ builtin('invert') { push(~pop()) }
 #builtin('bcopy') {  }
 #builtin('bmove') {  }
 
-
 #------------------------------------------
 # Variables
 #------------------------------------------
@@ -147,13 +167,29 @@ builtin('invert') { push(~pop()) }
 #F_HIDDEN   The HIDDEN flag's actual value.
 #F_LENMASK  The length mask in the flags/len byte.
 
-
 #------------------------------------------
 # Compiler
 #------------------------------------------
 
+builtin('hex') {
+  $base = 16
+}
+
+builtin('dec') {
+  $base = 10
+}
+
+builtin('oct') {
+  $base = 8
+}
+
+builtin('bin') {
+  $base = 2
+}
+
 builtin('#') {
   $buffer = $input.gets
+#  puts  "      #{$buffer.inspect}"
 }
 
 builtin('.') {
@@ -165,11 +201,20 @@ builtin('.') {
 }
 
 builtin('word') do
-  if $buffer.length == 0 then
-    $buffer = $input.gets
+#  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
-  $buffer.slice!(/^\s*/)
-  push $buffer.slice!(/^[^\s]+/)
+#  puts "      word: #{word}"
+#  puts "    end word"
+  push word
 end
 
 builtin('create') do
@@ -200,52 +245,121 @@ word(';', IMM, [ ']', 'register' ])
 # Assembler Words
 #------------------------------------------
 
-def pack8(val)
-  PROG.push(val & 0xff)
+def pack8(val, off = nil)
+  PROG[off || PROG.length] = (val & 0xff)
 end
 
-def pack16(val)
-  PROG.push((val >> 0) & 0xff)
-  PROG.push((val >> 8) & 0xff)
+def pack16(val, off = nil)
+  off ||= PROG.length
+  PROG[off + 0] = ((val >> 0) & 0xff)
+  PROG[off + 1] = ((val >> 8) & 0xff)
 end
 
-def pack32(val)
-  PROG.push((val >> 0)  & 0xff)
-  PROG.push((val >> 8)  & 0xff)
-  PROG.push((val >> 16) & 0xff)
-  PROG.push((val >> 24) & 0xff)
+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)
-  PROG.push((val >> 0)  & 0xff)
-  PROG.push((val >> 8)  & 0xff)
-  PROG.push((val >> 16) & 0xff)
-  PROG.push((val >> 24) & 0xff)
-  PROG.push((val >> 32) & 0xff)
-  PROG.push((val >> 40) & 0xff)
-  PROG.push((val >> 48) & 0xff)
-  PROG.push((val >> 56) & 0xff)
+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
 
-#builtin("virt-address") {
-#
-#}
-#
-#builtin("entry-offset") {
-#
-#}
-#
-#builtin("segment-size") {
-#
-#}
-#
-#builtin("segment-size") {
+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("@") {
+  push unpack64(pop())
+}
+
+builtin("!") {
+  off = pop()
+  val = pop()
+  pack64(val, off)
+}
+
+builtin("+!") {
+  off = pop()
+  val = pop()
+  pack64(unpack64(off) + val, off)
+}
+
+builtin("-!") {
+  off = pop()
+  val = pop()
+  pack64(unpack64(off) - val, off)
+}
+
+
+
 #
-#}
+#  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 }
 
 builtin('pack8')  { pack8(pop()) }
 builtin('pack16') { pack16(pop()) }
@@ -323,58 +437,53 @@ builtin('nop') {
 # Input Interpreter
 #------------------------------------------
 def interp()
-  while (not $input.eof?) || ($buffer.length > 0) do
+#  puts "  interp"
+  while (not $input.eof?) || ($buffer && $buffer.length > 0) do
     $words['word'].code.call()
     w = $stack.pop
-    next  if w.nil? or w.length == 0
+    break if w.nil?
     if $words[w] then
       if $state == 0 || (($words[w].flags & IMM) == IMM)
         $words[w].code.call
       else
         $curr.code << $words[w].code
       end
-    elsif w =~ /^[0-9]+$/
+    elsif w =~ /^[0-9A-Fa-f]+$/
       if $state == 0
-        push w.to_i
+        push w.to_i($base)
       else
         $curr.code << lambda{ push w.to_i }
       end
     else
       pp $stack
-      puts "?"
+      puts "#{w.inspect} ?"
       $stack = []
     end
   end
+#  puts "  end interp"
 end
 
 def interp_file(file)
+#  puts "interp file: #{file}"
   prev = $input
   $input = File.open(file, "rb")
   interp()
   $input = prev
+#  puts "end interp file: #{file}"
 end
 
-
-interp_file("asm.s")
-
-#$stdin.each_line do |line|
-#  line.split.each do |w|
-#  end
-#end
-#
-#File.read("asm.s").split.each do |w|
-#  if $words[w]
-#    $words[w].call()
-#  else
-#    $stack.push(w.to_i($base))
-#  end
-#end
-#
-# Set program length and write to disk
-PROG[96] = ((PROG.length >> 0)  & 0xFF)
-PROG[97] = ((PROG.length >> 8)  & 0xFF)
-PROG[98] = ((PROG.length >> 16) & 0xFF)
-PROG[99] = ((PROG.length >> 24) & 0xFF)
-File.binwrite("a.out", PROG.map{|b| b.chr }.join)
-
-
+#------------------------------------------
+# Parse Input and Generate Output
+#------------------------------------------
+if ARGV.length > 0
+  ARGV.each {|f| interp_file(f) }
+
+  # Set program length and write to disk
+  PROG[96] = ((PROG.length >> 0)  & 0xFF)
+  PROG[97] = ((PROG.length >> 8)  & 0xFF)
+  PROG[98] = ((PROG.length >> 16) & 0xFF)
+  PROG[99] = ((PROG.length >> 24) & 0xFF)
+  File.binwrite("a.out", PROG.map{|b| b.chr }.join)
+else
+  interp()
+end
diff --git a/asm.s b/asm.s
index d80ac93c3b6578124669889b3bb1175bb91ec6ad..f0bcc34953746c5d9e7d9988f22840c1655ebdb8 100644 (file)
--- a/asm.s
+++ b/asm.s
@@ -1,10 +1,35 @@
+# record our current offset for later use
+here
+
+# ----------------------------------------
+# SYSTEM VARIABLES
+# ----------------------------------------
+
 # Allocate space for variables
-# 0 pack64    # STATE
-# 0 pack64    # HERE
-# 0 pack64    # LATEST
-# 0 pack64    # S0
-# 0 pack64    # R0
+0 pack64    # LATEST
+0 pack64    # STATE
+0 pack64    # HERE
+0 pack64    # S0
+0 pack64    # R0
+
+# ----------------------------------------
+# DEFINE BUILTIN WORDS
+# ----------------------------------------
+
+# quit:
+# Loop Forever
+#   r0
+#   rsp!
+#   interpret
+# end
+
+# ----------------------------------------
+# ENTRY CODE STARTS HERE
+# ----------------------------------------
+
+# update our entry address to here
+here swap - entry-address +!
 
 60 rax load-imm
-0 rdi load-imm
+42 rdi load-imm
 syscall
index 8d23e392f6447011684cb4c65fa3bc293ee22b2f..487faba0d577949c6686266b15ef3cd658cf0904 100644 (file)
@@ -1053,7 +1053,7 @@ code_\label :                     // assembler code follows
 
 /*
        ! and @ (STORE and FETCH) store 32-bit words.  It's also useful to be able to read and write bytes
-       so we also define standard words C@ and C!.
+       so we also defe standard words C@ and C!.
 
        Byte-oriented operations only work on architectures which permit them (i386 is one of those).
  */