From 731ea9cbee62a6f0e3fb5ac6b5ea51c8e9dd5835 Mon Sep 17 00:00:00 2001 From: inglorion Date: Sun, 25 Nov 2012 00:33:56 -0800 Subject: [PATCH] Removed a number of special cases from the NASM generator --- lib/voodoo/generators/nasm_generator.rb | 152 +++++--------------------------- 1 file changed, 22 insertions(+), 130 deletions(-) diff --git a/lib/voodoo/generators/nasm_generator.rb b/lib/voodoo/generators/nasm_generator.rb index 158e65f..285b055 100644 --- a/lib/voodoo/generators/nasm_generator.rb +++ b/lib/voodoo/generators/nasm_generator.rb @@ -283,7 +283,7 @@ module Voodoo # Tests if an operand is an immediate operand def immediate_operand? operand - integer?(operand) || global?(operand) + integer?(operand) end # Tests if an operand is a memory operand @@ -353,17 +353,15 @@ module Voodoo end # Loads the value associated with the given symbol. - # Returns a register name (symbol) or a string that can - # be used to refer to the symbol's value. def load_symbol symbol, reg = @SCRATCH_REG x = @environment[symbol] if x.kind_of? Symbol - x.to_s + x elsif x.kind_of? Integer offset_reference x else # Assume global - symbol.to_s + symbol end end @@ -396,12 +394,8 @@ module Voodoo # Loads 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 + value_ref = load_value value, register + set_register register, value_ref end # @@ -416,35 +410,10 @@ module Voodoo raise "Cannot change value of global #{target}" end - if words.length == 1 - value = words[0] - if value == target - emit "; nothing to do; destination equals source\n" - else - target_ref = load_value target, @BX - if integer?(value) - if value.to_i == 0 - # Set destination to 0 - emit "xor #{@AX}, #{@AX}\n" - emit "mov #{target_ref}, #{@AX}\n" - else - value_ref = load_value value, @AX - emit "mov #{@WORD_NAME} #{target_ref}, #{value_ref}\n" - end - else - # Copy source to destination - eval_expr words, @RETURN_REG - emit "mov #{target_ref}, #{@RETURN_REG}\n" - end - end - else - op = words[0] - - if words.length == 3 && binop?(op) - # Binary operation - binop op, target, words[1], words[2] + if words.length != 1 || words[0] != target + if symbol?(target) && symbol?(@environment[target]) + eval_expr words, @environment[target] else - # Not a binary operation eval_expr words, @RETURN_REG target_ref = load_value target, @BX emit "mov #{target_ref}, #{@RETURN_REG}\n" @@ -476,82 +445,6 @@ module Voodoo emit "mov #{@WORD_NAME} #{addr_ref}, #{value_ref}\n" end - # - # == Binary Operations - # - - # Emit code for a binary operation - def binop op, target, x, y - if target == x - binop2 op, target, y - elsif symmetric_binop?(op) && y == target - binop2 op, target, x - else - # Cases that are handled specially - return div(target, x, y) if op == :div - return mod(target, x, y) if op == :mod - return mul(target, x, y) if op == :mul - - target_ref = load_value target, @BX - x_ref = load_value x, @DX - y_ref = load_value y, @CX - - mnemonic = action_to_mnemonic op - if [:asr, :bsr, :rol, :ror, :shl, :shr].member? op - if memory_operand? y_ref - emit "mov cl, #{y_ref}\n" - elsif y_ref != @CX - emit "mov #{@CX}, #{y_ref}\n" - end - y_ref = :cl - end - - if memory_operand?(target_ref) - if memory_operand?(x_ref) || memory_operand?(y_ref) - emit "mov #{@AX}, #{x_ref}\n" - emit "#{mnemonic} #{@AX}, #{y_ref}\n" - emit "mov #{target_ref}, #{@AX}\n" - else - emit "mov #{@WORD_NAME} #{target_ref}, #{x_ref}\n" - emit "#{mnemonic} #{@WORD_NAME} #{target_ref}, #{y_ref}\n" - end - else - if x_ref == target_ref - emit "#{mnemonic} #{x_ref}, #{y_ref}\n" - else - emit "mov #{target_ref}, #{x_ref}\n" - emit "#{mnemonic} #{target_ref}, #{y_ref}\n" - end - end - end - end - - # Emit code for a binary operation where the first operand - # is also the target - def binop2 op, target, y - # Cases that are handled specially - return div2(target, target, y) if op == :div - return mod2(target, y) if op == :mod - return mul2(target, y) if op == :mul - - target_ref = load_value target, @AX - y_ref = load_value y, @CX - mnemonic = action_to_mnemonic op - if [:asr, :bsr, :rol, :ror, :shl, :shr].member? op - if memory_operand? y_ref - emit "mov cl, #{y_ref}\n" - elsif y_ref != @CX - emit "mov #{@CX}, #{y_ref}\n" - end - emit "#{mnemonic} #{@WORD_NAME} #{target_ref}, cl\n" - elsif memory_operand?(target_ref) && memory_operand?(y_ref) - emit "mov #{@CX}, #{y_ref}\n" - emit "#{mnemonic} #{target_ref}, #{@CX}\n" - else - emit "#{mnemonic} #{@WORD_NAME} #{target_ref}, #{y_ref}\n" - end - end - # Divide x by y and store the quotient in target def div target, x, y eval_div x, y @@ -625,33 +518,36 @@ module Voodoo load_value_into_register words[1], register emit "#{action_to_mnemonic op} #{register}, cl\n" when :'auto-bytes' - auto_bytes words[1] + auto_bytes words[1], register when :'auto-words' - auto_words words[1] + auto_words words[1], register when :call call *words[1..-1] + emit "mov #{register}, #{@RETURN_REG}\n" if register != @RETURN_REG when :div eval_div words[1], words[2] set_register register, @AX when :'get-byte' - # Clear register - set_register register, 0 # Get address reference address_ref = load_address words[1], words[2], 1 # Load byte from address case register when :eax, :rax + set_register register, 0 set_register :al, address_ref when :ebx, :rbx + set_register register, 0 set_register :bl, address_ref when :ecx, :rcx + set_register register, 0 set_register :cl, address_ref when :edx, :rdx + set_register register, 0 set_register :dl, address_ref else - set_register @BX, 0 - set_register :bl, address_ref - set_register register, @BX + set_register @AX, 0 + set_register :al, address_ref + set_register register, @AX end when :'get-word' address_ref = load_address words[1], words[2], @WORDSIZE @@ -693,9 +589,11 @@ module Voodoo end elsif immediate_operand? y_ref emit "imul #{register}, #{x_ref}, #{y_ref}\n" - else - emit "mov #{register}, #{x_ref}\n" + elsif y_ref != register + emit "mov #{register}, #{x_ref}\n" unless x_ref == register emit "imul #{register}, #{y_ref}\n" + else + emit "imul #{register}, #{x_ref}\n" end end @@ -796,12 +694,6 @@ module Voodoo end end - # Load a value into a register - def load_value_into_register value, register - value_ref = load_value value, register - set_register register, value_ref - end - # Set a register to a value. # The value must be a valid operand to the mov instruction. def set_register register, value_ref -- 2.11.4.GIT