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 */