154154-type condition () ::
155155 {aarch64_register (), '<' , integer ()}
156156 | {maybe_free_aarch64_register (), '<' , aarch64_register ()}
157+ | {integer (), '<' , maybe_free_aarch64_register ()}
157158 | {maybe_free_aarch64_register (), '==' , integer ()}
158159 | {maybe_free_aarch64_register (), '!=' , aarch64_register () | integer ()}
159160 | {'(int)' , maybe_free_aarch64_register (), '==' , integer ()}
@@ -757,15 +758,47 @@ if_else_block(
757758 jit_aarch64_asm :cc () | {tbz | tbnz , atom (), 0 ..63 } | {cbz , atom ()},
758759 non_neg_integer ()
759760 }.
760- if_block_cond (# state {stream_module = StreamModule , stream = Stream0 } = State0 , {Reg , '<' , 0 }) ->
761+ if_block_cond (# state {stream_module = StreamModule , stream = Stream0 } = State0 , {RegOrTuple , '<' , 0 }) ->
762+ Reg =
763+ case RegOrTuple of
764+ {free , Reg0 } -> Reg0 ;
765+ RegOrTuple -> RegOrTuple
766+ end ,
761767 I = jit_aarch64_asm :tbz (Reg , 63 , 0 ),
762768 Stream1 = StreamModule :append (Stream0 , I ),
763- State1 = State0 # state {stream = Stream1 },
764- {State1 , {tbz , Reg , 63 }, 0 };
769+ State1 = if_block_free_reg (RegOrTuple , State0 ),
770+ State2 = State1 # state {stream = Stream1 },
771+ {State2 , {tbz , Reg , 63 }, 0 };
772+ % Handle {Val, '<', Reg} - means Val < Reg, jump if false (i.e., if Val >= Reg or Reg <= Val)
765773if_block_cond (
766774 # state {stream_module = StreamModule , stream = Stream0 } = State0 ,
767- {Reg , '<' , Val }
768- ) when is_atom (Reg ), is_integer (Val ) ->
775+ {Val , '<' , RegOrTuple }
776+ ) when is_integer (Val ) ->
777+ Reg =
778+ case RegOrTuple of
779+ {free , Reg0 } -> Reg0 ;
780+ RegOrTuple -> RegOrTuple
781+ end ,
782+ I1 = jit_aarch64_asm :cmp (Reg , Val ),
783+ % le = less than or equal
784+ I2 = jit_aarch64_asm :bcc (le , 0 ),
785+ Code = <<
786+ I1 /binary ,
787+ I2 /binary
788+ >>,
789+ Stream1 = StreamModule :append (Stream0 , Code ),
790+ State1 = if_block_free_reg (RegOrTuple , State0 ),
791+ State2 = State1 # state {stream = Stream1 },
792+ {State2 , le , byte_size (I1 )};
793+ if_block_cond (
794+ # state {stream_module = StreamModule , stream = Stream0 } = State0 ,
795+ {RegOrTuple , '<' , Val }
796+ ) when is_integer (Val ), Val =/= 0 ->
797+ Reg =
798+ case RegOrTuple of
799+ {free , Reg0 } -> Reg0 ;
800+ RegOrTuple -> RegOrTuple
801+ end ,
769802 I1 = jit_aarch64_asm :cmp (Reg , Val ),
770803 % ge = greater than or equal
771804 I2 = jit_aarch64_asm :bcc (ge , 0 ),
@@ -774,8 +807,9 @@ if_block_cond(
774807 I2 /binary
775808 >>,
776809 Stream1 = StreamModule :append (Stream0 , Code ),
777- State1 = State0 # state {stream = Stream1 },
778- {State1 , ge , byte_size (I1 )};
810+ State1 = if_block_free_reg (RegOrTuple , State0 ),
811+ State2 = State1 # state {stream = Stream1 },
812+ {State2 , ge , byte_size (I1 )};
779813if_block_cond (
780814 # state {stream_module = StreamModule , stream = Stream0 } = State0 ,
781815 {RegOrTuple , '<' , RegB }
@@ -2073,8 +2107,10 @@ add(State, Reg, Val) ->
20732107% % @param Val immediate value to subtract
20742108% % @return Updated backend state
20752109% %-----------------------------------------------------------------------------
2076- - spec sub (state (), aarch64_register (), integer ()) -> state ().
2077- sub (# state {stream_module = StreamModule , stream = Stream0 } = State , Reg , Val ) ->
2110+ - spec sub (state (), aarch64_register (), integer () | aarch64_register ()) -> state ().
2111+ sub (State , Reg , Val ) when is_integer (Val ) ->
2112+ op_imm (State , sub , Reg , Reg , Val );
2113+ sub (# state {stream_module = StreamModule , stream = Stream0 } = State , Reg , Val ) when is_atom (Val ) ->
20782114 I1 = jit_aarch64_asm :sub (Reg , Reg , Val ),
20792115 Stream1 = StreamModule :append (Stream0 , I1 ),
20802116 State # state {stream = Stream1 }.
0 commit comments