From b0053072fa93f2e8738150ad69c61c89bfad8f53 Mon Sep 17 00:00:00 2001 From: inglorion Date: Sat, 3 Nov 2012 20:24:49 -0700 Subject: [PATCH] Implement auto-bytes and auto-words for ARM --- lib/voodoo/generators/arm_gas_generator.rb | 57 ++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 7 deletions(-) diff --git a/lib/voodoo/generators/arm_gas_generator.rb b/lib/voodoo/generators/arm_gas_generator.rb index bdbceab..2ff7537 100644 --- a/lib/voodoo/generators/arm_gas_generator.rb +++ b/lib/voodoo/generators/arm_gas_generator.rb @@ -60,11 +60,14 @@ module Voodoo # class ARMGasGenerator < CommonCodeGenerator def initialize params - @WORDSIZE = 4 + @WORDSIZE_BITS = 2 + @WORDSIZE = 1 << @WORDSIZE_BITS @CODE_ALIGNMENT = 4 @DATA_ALIGNMENT = @WORDSIZE @FUNCTION_ALIGNMENT = @WORDSIZE - + @STACK_ALIGNMENT_BITS = 3 + @STACK_ALIGNMENT = 1 << @STACK_ALIGNMENT_BITS + @INITIAL_FRAME_SIZE = 2 * @WORDSIZE @NREGISTER_ARGS = 4 @NREGISTER_LOCALS = 6 @@ -145,6 +148,39 @@ module Voodoo value.respond_to?(:[]) && value[0] == :'@' end + def auto_bytes value, register + if value.kind_of? Integer + grow_frame value + else + temporary = register == :sp ? @TEMPORARY : register + load_value_into_register value, temporary + auto_bytes_register temporary + end + emit "cpy #{register}, sp\n" unless register == :sp + end + + # auto-bytes where the value is supplied in a register and the return + # value will be in sp. register must not be sp. + def auto_bytes_register register + temporary = register == @TEMPORARY ? :r3 : @TEMPORARY + emit "add #{register}, #{register}, \##{@STACK_ALIGNMENT - 1}\n" + emit "mvn #{temporary}, \##{@STACK_ALIGNMENT - 1}\n" + emit "and #{register}, #{register}, #{temporary}\n" + emit "sub sp, #{temp1}\n" + end + + def auto_words value, register + if value.kind_of? Integer + auto_bytes(value * @WORDSIZE, register) + else + temporary = register == :sp ? @TEMPORARY : register + load_value_into_register value, temporary + emit "lsl #{temporary}, #{temporary}, \##{@WORDSIZE_BITS}\n" + auto_bytes_register temporary + emit "cpy #{register}, sp\n" unless register == :sp + end + end + # Begins a new block. def begin_block *code emit "# begin block\n" @@ -247,10 +283,7 @@ module Voodoo # Calculate frame size so that the stack pointer will # be properly aligned at the end of emit_function_prologue. - @frame_size = (clobbered.length + nstack_vars) * @WORDSIZE - if @frame_size % 8 != 0 - @frame_size = (@frame_size + 7) / 8 * 8 - end + @frame_size = stack_align((clobbered.length + nstack_vars) * @WORDSIZE) extra_space = @frame_size - clobbered.length * @WORDSIZE if extra_space > 0 emit "sub sp, sp, \##{extra_space}\n" @@ -437,6 +470,10 @@ module Voodoo # Evaluate expression op = expr[0] case op + when :'auto-bytes' + auto_bytes expr[1], register + when :'auto-words' + auto_words expr[1], register when :call call *expr[1..-1] emit "cpy #{register}, #{@RETURN}\n" if register != @RETURN @@ -524,7 +561,7 @@ module Voodoo # Grows the current frame by n words, plus padding to # respect alignment rules. def grow_frame nwords - increment = (nwords * @WORDSIZE + 7) / 8 * 8 + increment = stack_align(nwords * @WORDSIZE) emit "sub sp, sp, \##{increment}\n" @frame_size = @frame_size + increment @frame_offset = @frame_offset + increment @@ -787,6 +824,12 @@ module Voodoo end end + # Given n, returns the nearest multiple of @STACK_ALIGNMENT + # that is >= n. + def stack_align n + (n + @STACK_ALIGNMENT - 1) / @STACK_ALIGNMENT * @STACK_ALIGNMENT + end + # Define a string with the given value def string value code = '' -- 2.11.4.GIT