github.com/goccy/go-jit@v0.0.0-20200514131505-ff78d45cf6af/internal/ccall/jit-gen-arm.c (about)

     1  /*
     2   * jit-gen-arm.c - Machine-dependent definitions for ARM.
     3   *
     4   * Copyright (C) 2003, 2004  Southern Storm Software, Pty Ltd.
     5   *
     6   * This file is part of the libjit library.
     7   *
     8   * The libjit library is free software: you can redistribute it and/or
     9   * modify it under the terms of the GNU Lesser General Public License
    10   * as published by the Free Software Foundation, either version 2.1 of
    11   * the License, or (at your option) any later version.
    12   *
    13   * The libjit library is distributed in the hope that it will be useful,
    14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    16   * Lesser General Public License for more details.
    17   *
    18   * You should have received a copy of the GNU Lesser General Public
    19   * License along with the libjit library.  If not, see
    20   * <http://www.gnu.org/licenses/>.
    21   */
    22  
    23  #include "jit-internal.h"
    24  
    25  #if defined(__arm) || defined(__arm__)
    26  
    27  #define	arm_execute		execute_prefix
    28  #define	arm_execute_cc	(execute_prefix | (1 << 20))
    29  #define	arm_execute_imm	(execute_prefix | (1 << 25))
    30  
    31  #include "jit-gen-arm.h"
    32  
    33  void _arm_mov_reg_imm
    34  	(arm_inst_buf *inst, int reg, int value, int execute_prefix)
    35  {
    36  	int bit;
    37  
    38  	/* Handle bytes in various positions */
    39  	for(bit = 0; bit <= (32 - 8); bit += 2)
    40  	{
    41  		if((value & (0xFF << bit)) == value)
    42  		{
    43  			arm_mov_reg_imm8_rotate
    44  				(*inst, reg, ((value >> bit) & 0xFF), (16 - bit / 2) & 0x0F);
    45  			return;
    46  		}
    47  	}
    48  
    49  	/* Handle inverted bytes in various positions */
    50  	value = ~value;
    51  	for(bit = 0; bit <= (32 - 8); bit += 2)
    52  	{
    53  		if((value & (0xFF << bit)) == value)
    54  		{
    55  			arm_alu_reg_imm8_rotate
    56  				(*inst, ARM_MVN, reg, 0,
    57  				 ((value >> bit) & 0xFF), (16 - bit / 2) & 0x0F);
    58  			return;
    59  		}
    60  	}
    61  
    62  	/* Build the value the hard way, byte by byte */
    63  	value = ~value;
    64  	if((value & 0xFF000000) != 0)
    65  	{
    66  		arm_mov_reg_imm8_rotate(*inst, reg, ((value >> 24) & 0xFF), 4);
    67  		if((value & 0x00FF0000) != 0)
    68  		{
    69  			arm_alu_reg_imm8_rotate
    70  				(*inst, ARM_ADD, reg, reg, ((value >> 16) & 0xFF), 8);
    71  		}
    72  		if((value & 0x0000FF00) != 0)
    73  		{
    74  			arm_alu_reg_imm8_rotate
    75  				(*inst, ARM_ADD, reg, reg, ((value >> 8) & 0xFF), 12);
    76  		}
    77  		if((value & 0x000000FF) != 0)
    78  		{
    79  			arm_alu_reg_imm8(*inst, ARM_ADD, reg, reg, (value & 0xFF));
    80  		}
    81  	}
    82  	else if((value & 0x00FF0000) != 0)
    83  	{
    84  		arm_mov_reg_imm8_rotate(*inst, reg, ((value >> 16) & 0xFF), 8);
    85  		if((value & 0x0000FF00) != 0)
    86  		{
    87  			arm_alu_reg_imm8_rotate
    88  				(*inst, ARM_ADD, reg, reg, ((value >> 8) & 0xFF), 12);
    89  		}
    90  		if((value & 0x000000FF) != 0)
    91  		{
    92  			arm_alu_reg_imm8(*inst, ARM_ADD, reg, reg, (value & 0xFF));
    93  		}
    94  	}
    95  	else if((value & 0x0000FF00) != 0)
    96  	{
    97  		arm_mov_reg_imm8_rotate(*inst, reg, ((value >> 8) & 0xFF), 12);
    98  		if((value & 0x000000FF) != 0)
    99  		{
   100  			arm_alu_reg_imm8(*inst, ARM_ADD, reg, reg, (value & 0xFF));
   101  		}
   102  	}
   103  	else
   104  	{
   105  		arm_mov_reg_imm8(*inst, reg, (value & 0xFF));
   106  	}
   107  }
   108  
   109  int arm_is_complex_imm(int value)
   110  {
   111  	int bit;
   112  	int inv_value = ~value;
   113  	for(bit = 0; bit <= (32 - 8); bit += 2)
   114  	{
   115  		if((value & (0xFF << bit)) == value)
   116  		{
   117  			return 0;
   118  		}
   119  		if((inv_value & (0xFF << bit)) == inv_value)
   120  		{
   121  			return 0;
   122  		}
   123  	}
   124  	return 1;
   125  }
   126  
   127  void _arm_alu_reg_imm
   128  	(arm_inst_buf *inst, int opc, int dreg,
   129  	 int sreg, int imm, int saveWork, int execute_prefix)
   130  {
   131  	int bit, tempreg;
   132  	for(bit = 0; bit <= (32 - 8); bit += 2)
   133  	{
   134  		if((imm & (0xFF << bit)) == imm)
   135  		{
   136  			arm_alu_reg_imm8_rotate
   137  				(*inst, opc, dreg, sreg,
   138  				 ((imm >> bit) & 0xFF), (16 - bit / 2) & 0x0F);
   139  			return;
   140  		}
   141  	}
   142  	if(saveWork)
   143  	{
   144  		if(dreg != ARM_R2 && sreg != ARM_R2)
   145  		{
   146  			tempreg = ARM_R2;
   147  		}
   148  		else if(dreg != ARM_R3 && sreg != ARM_R3)
   149  		{
   150  			tempreg = ARM_R3;
   151  		}
   152  		else
   153  		{
   154  			tempreg = ARM_R4;
   155  		}
   156  		arm_push_reg(*inst, tempreg);
   157  	}
   158  	else
   159  	{
   160  		tempreg = ARM_WORK;
   161  	}
   162  	_arm_mov_reg_imm(inst, tempreg, imm, execute_prefix);
   163  	arm_alu_reg_reg(*inst, opc, dreg, sreg, tempreg);
   164  	if(saveWork)
   165  	{
   166  		arm_pop_reg(*inst, tempreg);
   167  	}
   168  }
   169  
   170  #endif /* arm */