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
$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
#------------------------------------------
builtin('#') {
$buffer = $input.gets
-# puts " #{$buffer.inspect}"
}
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())
}
}
+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 }
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') {
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");
// 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");
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");