From 5e3f4c7d6e6944142d6d178de41c3c191b7b89ea Mon Sep 17 00:00:00 2001 From: inglorion Date: Mon, 12 Jul 2010 22:02:54 +0200 Subject: [PATCH] Added support for at-expressions to i386 and AMD64 targets. --- lib/voodoo/generators/nasm_generator.rb | 30 ++++++++++++++++++++++++++++++ lib/voodoo/parser.rb | 17 ++++++++++++++++- test/Makefile | 4 ++-- test/test | 2 ++ 4 files changed, 50 insertions(+), 3 deletions(-) diff --git a/lib/voodoo/generators/nasm_generator.rb b/lib/voodoo/generators/nasm_generator.rb index 9c0754c..3213299 100644 --- a/lib/voodoo/generators/nasm_generator.rb +++ b/lib/voodoo/generators/nasm_generator.rb @@ -185,6 +185,11 @@ module Voodoo # == Value Classification # + # Test if a value is an at-expression + def at_expr? value + value.respond_to?(:[]) && value[0] == :'@' + end + # Test if op is a binary operation def binop? op [:div, :mod, :sub].member?(op) || symmetric_operation?(op) @@ -271,6 +276,17 @@ module Voodoo end end + # Load the value at the given address. + # Invoking this code may clobber @BX. + def load_at address, reg = @SCRATCH_REG + if integer?(address) || global?(address) + "[#{address}]" + else + load_value_into_register address, @BX + "[#{@BX}]" + end + end + # Load the value associated with the given symbol. # Returns a string that can be used to refer to the loaded value. def load_symbol symbol, reg = @SCRATCH_REG @@ -298,6 +314,20 @@ module Voodoo value elsif symbol? value load_symbol value, reg + elsif at_expr? value + load_at value[1], reg + else + raise "Don't know how to load #{value.inspect}" + end + end + + # Load a value into a register. + def load_value_into_register value, register + load_code = load_value(value), register + if load_code == register.to_s + load_code + else + "mov #{register}, #{load_code}\n" end end diff --git a/lib/voodoo/parser.rb b/lib/voodoo/parser.rb index 0e582d7..d2baaeb 100644 --- a/lib/voodoo/parser.rb +++ b/lib/voodoo/parser.rb @@ -108,8 +108,23 @@ module Voodoo when /\s/ # Skip whitespace consume + when '@' + # Parse at-expression. + # '@' must be followed by a number or symbol. + consume + case lookahead + when /\d|-/ + expr = parse_number + when /\w|\\/ + expr = parse_symbol + else + raise "Invalid character (#{@lookahead.chr.inspect})" + + " at #{@line}:#{@char}; expecting number or symbol" + end + words << [:'@', expr] else - raise "Invalid character (#{@lookahead}) at #{@line}:#{@char}" + raise "Invalid character (#{@lookahead.chr.inspect})" + + " at #{@line}:#{@char}" end end diff --git a/test/Makefile b/test/Makefile index db71a4f..de2d64e 100644 --- a/test/Makefile +++ b/test/Makefile @@ -3,8 +3,8 @@ include ../Makefile.cfg NASM ?= nasm VOODOOC ?= env RUBYLIB=$(PWD)/../lib:$(RUBYLIB) ../bin/voodooc -TARGETS = bitwise call div fact goto hello if many-vars mod mul plusminus \ - set-byte set-word tail-calls vtable 99bottles gcd +TARGETS = at bitwise call div fact goto hello if many-vars mod mul \ + plusminus set-byte set-word tail-calls vtable 99bottles gcd all : $(TARGETS) diff --git a/test/test b/test/test index a95f87d..aa626e7 100755 --- a/test/test +++ b/test/test @@ -36,6 +36,8 @@ run_test2 hello "Hello, world!" run_test1 call +run_test1 at + run_test1 if run_test1 goto -- 2.11.4.GIT