├── CMakeLists.txt ├── LIBTCGConfig.cmake.in ├── LICENSE ├── README ├── TODO ├── include └── tcg │ ├── exec.h │ ├── helper-gen.h │ ├── helper-head.h │ ├── helper-proto.h │ ├── helper-tcg.h │ ├── helper.h │ ├── i386 │ ├── tcg-target.h │ └── tcg-target.opc.h │ ├── ops_sse_header.h │ ├── regs.h │ ├── tb.h │ ├── tcg-llvm.h │ ├── tcg-mo.h │ ├── tcg-op.h │ ├── tcg-opc.h │ ├── tcg-runtime.h │ ├── tcg.h │ └── utils │ ├── atomic.h │ ├── bitmap.h │ ├── bitops.h │ ├── cutils.h │ ├── host-utils.h │ ├── log.h │ ├── mutex.h │ ├── osdep.h │ └── rounding.h └── src ├── CMakeLists.txt ├── cutils.c ├── elf.h ├── i386 └── tcg-target.inc.c ├── optimize.c ├── tcg-common.c ├── tcg-gvec-desc.h ├── tcg-ldst.inc.c ├── tcg-llvm.cpp ├── tcg-op-gvec.c ├── tcg-op-gvec.h ├── tcg-op-vec.c ├── tcg-op.c ├── tcg-pool.inc.c ├── tcg-runtime-gvec.c ├── tcg-runtime.c └── tcg.c /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017 Cyberhaven 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy 4 | # of this software and associated documentation files (the "Software"), to deal 5 | # in the Software without restriction, including without limitation the rights 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | # copies of the Software, and to permit persons to whom the Software is 8 | # furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in all 11 | # copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | # SOFTWARE. 20 | 21 | cmake_minimum_required(VERSION 3.4.3) 22 | 23 | project(LIBTCG) 24 | set(LIBTCG_VERSION_MAJOR 4) 25 | set(LIBTCG_VERSION_MINOR 0) 26 | set(LIBTCG_VERSION_PATCH 0) 27 | set(LIBTCG_PACKAGE_VERSION 28 | "${LIBTCG_VERSION_MAJOR}.${LIBTCG_VERSION_MINOR}.${LIBTCG_VERSION_PATCH}") 29 | 30 | include(CMakePackageConfigHelpers) 31 | set(CMAKE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Version.cmake") 32 | write_basic_package_version_file(${CMAKE_VERSION_FILE} 33 | VERSION ${LIBTCG_PACKAGE_VERSION} 34 | COMPATIBILITY AnyNewerVersion) 35 | 36 | set(CMAKE_CONFIG_FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake") 37 | set(LIBTCG_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/include") 38 | set(LIBTCG_LIBRARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/src") 39 | configure_file(LIBTCGConfig.cmake.in ${CMAKE_CONFIG_FILE} @ONLY) 40 | 41 | find_package(PkgConfig REQUIRED) 42 | pkg_check_modules(GLIB_PKG glib-2.0) 43 | 44 | find_package(LIBQ REQUIRED) 45 | message(STATUS "Found libq ${LIBQ_PACKAGE_VERSION}") 46 | 47 | ##### LLVM ##### 48 | find_package(LLVM REQUIRED) 49 | message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") 50 | 51 | add_definitions(${LLVM_DEFINITIONS}) 52 | 53 | include_directories("include" 54 | ${LLVM_INCLUDE_DIRS}) 55 | 56 | llvm_map_components_to_libnames(LLVM_LIBS core) 57 | 58 | set(LLVM_CONFIG "${LLVM_TOOLS_BINARY_DIR}/llvm-config" 59 | CACHE PATH "Path to llvm-config") 60 | execute_process(COMMAND ${LLVM_CONFIG} "--cxxflags" 61 | RESULT_VARIABLE LLVM_CONFIG_RESULT 62 | OUTPUT_VARIABLE LLVM_CXXFLAGS 63 | OUTPUT_STRIP_TRAILING_WHITESPACE) 64 | 65 | ################## 66 | 67 | option(WITH_GUEST "Type of guest target to support") 68 | 69 | if(NOT WITH_GUEST) 70 | message(FATAL_ERROR "Please specify guest target type") 71 | endif() 72 | 73 | message(STATUS "WITH_GUEST: ${WITH_GUEST}") 74 | 75 | if(WITH_GUEST MATCHES "i386") 76 | set(TARGET_LONG_BITS "32") 77 | set(TARGET_INSN_START_EXTRA_WORDS "1") 78 | elseif(WITH_GUEST MATCHES "x86_64") 79 | set(TARGET_LONG_BITS "64") 80 | set(TARGET_INSN_START_EXTRA_WORDS "1") 81 | set(TARGET_X86_64 "1") 82 | else() 83 | message(FATAL_ERROR "Incorrect target ${WITH_GUEST}") 84 | endif() 85 | 86 | if(WITH_GUEST MATCHES "s2e") 87 | set(WITH_SYMBEX ON) 88 | if(NOT (WITH_GUEST MATCHES "s2e_sp")) 89 | set(WITH_SYMBEX_MP ON) 90 | endif() 91 | endif() 92 | 93 | include_directories(${GLIB_PKG_INCLUDE_DIRS} ${LIBTCG_INCLUDE_DIR} ${LIBQ_INCLUDE_DIR}) 94 | add_subdirectory(src) 95 | -------------------------------------------------------------------------------- /LIBTCGConfig.cmake.in: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017 Cyberhaven 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy 4 | # of this software and associated documentation files (the "Software"), to deal 5 | # in the Software without restriction, including without limitation the rights 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | # copies of the Software, and to permit persons to whom the Software is 8 | # furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in all 11 | # copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | # SOFTWARE. 20 | 21 | set(LIBTCG_VERSION_MAJOR @LIBTCG_VERSION_MAJOR@) 22 | set(LIBTCG_VERSION_MINOR @LIBTCG_VERSION_MINOR@) 23 | set(LIBTCG_VERSION_PATCH @LIBTCG_VERSION_PATCH@) 24 | set(LIBTCG_PACKAGE_VERSION @LIBTCG_PACKAGE_VERSION@) 25 | 26 | set(LIBTCG_INCLUDE_DIR "@LIBTCG_INCLUDE_DIR@") 27 | set(LIBTCG_LIBRARY_DIR "@LIBTCG_LIBRARY_DIR@") 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | All the files in this directory and subdirectories are released under 2 | an MIT/BSD-like license (see header in each file). No other license is 3 | accepted. 4 | 5 | ====== 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Tiny Code Generator - Fabrice Bellard. 2 | 3 | 1) Introduction 4 | 5 | TCG (Tiny Code Generator) began as a generic backend for a C 6 | compiler. It was simplified to be used in QEMU. It also has its roots 7 | in the QOP code generator written by Paul Brook. 8 | 9 | 2) Definitions 10 | 11 | The TCG "target" is the architecture for which we generate the 12 | code. It is of course not the same as the "target" of QEMU which is 13 | the emulated architecture. As TCG started as a generic C backend used 14 | for cross compiling, it is assumed that the TCG target is different 15 | from the host, although it is never the case for QEMU. 16 | 17 | A TCG "function" corresponds to a QEMU Translated Block (TB). 18 | 19 | A TCG "temporary" is a variable only live in a basic 20 | block. Temporaries are allocated explicitly in each function. 21 | 22 | A TCG "local temporary" is a variable only live in a function. Local 23 | temporaries are allocated explicitly in each function. 24 | 25 | A TCG "global" is a variable which is live in all the functions 26 | (equivalent of a C global variable). They are defined before the 27 | functions defined. A TCG global can be a memory location (e.g. a QEMU 28 | CPU register), a fixed host register (e.g. the QEMU CPU state pointer) 29 | or a memory location which is stored in a register outside QEMU TBs 30 | (not implemented yet). 31 | 32 | A TCG "basic block" corresponds to a list of instructions terminated 33 | by a branch instruction. 34 | 35 | 3) Intermediate representation 36 | 37 | 3.1) Introduction 38 | 39 | TCG instructions operate on variables which are temporaries, local 40 | temporaries or globals. TCG instructions and variables are strongly 41 | typed. Two types are supported: 32 bit integers and 64 bit 42 | integers. Pointers are defined as an alias to 32 bit or 64 bit 43 | integers depending on the TCG target word size. 44 | 45 | Each instruction has a fixed number of output variable operands, input 46 | variable operands and always constant operands. 47 | 48 | The notable exception is the call instruction which has a variable 49 | number of outputs and inputs. 50 | 51 | In the textual form, output operands usually come first, followed by 52 | input operands, followed by constant operands. The output type is 53 | included in the instruction name. Constants are prefixed with a '$'. 54 | 55 | add_i32 t0, t1, t2 (t0 <- t1 + t2) 56 | 57 | 3.2) Assumptions 58 | 59 | * Basic blocks 60 | 61 | - Basic blocks end after branches (e.g. brcond_i32 instruction), 62 | goto_tb and exit_tb instructions. 63 | - Basic blocks start after the end of a previous basic block, or at a 64 | set_label instruction. 65 | 66 | After the end of a basic block, the content of temporaries is 67 | destroyed, but local temporaries and globals are preserved. 68 | 69 | * Floating point types are not supported yet 70 | 71 | * Pointers: depending on the TCG target, pointer size is 32 bit or 64 72 | bit. The type TCG_TYPE_PTR is an alias to TCG_TYPE_I32 or 73 | TCG_TYPE_I64. 74 | 75 | * Helpers: 76 | 77 | Using the tcg_gen_helper_x_y it is possible to call any function 78 | taking i32, i64 or pointer types. By default, before calling a helper, 79 | all globals are stored at their canonical location and it is assumed 80 | that the function can modify them. This can be overridden by the 81 | TCG_CALL_CONST function modifier. By default, the helper is allowed to 82 | modify the CPU state or raise an exception. This can be overridden by 83 | the TCG_CALL_PURE function modifier, in which case the call to the 84 | function is removed if the return value is not used. 85 | 86 | On some TCG targets (e.g. x86), several calling conventions are 87 | supported. 88 | 89 | * Branches: 90 | 91 | Use the instruction 'br' to jump to a label. Use 'jmp' to jump to an 92 | explicit address. Conditional branches can only jump to labels. 93 | 94 | 3.3) Code Optimizations 95 | 96 | When generating instructions, you can count on at least the following 97 | optimizations: 98 | 99 | - Single instructions are simplified, e.g. 100 | 101 | and_i32 t0, t0, $0xffffffff 102 | 103 | is suppressed. 104 | 105 | - A liveness analysis is done at the basic block level. The 106 | information is used to suppress moves from a dead variable to 107 | another one. It is also used to remove instructions which compute 108 | dead results. The later is especially useful for condition code 109 | optimization in QEMU. 110 | 111 | In the following example: 112 | 113 | add_i32 t0, t1, t2 114 | add_i32 t0, t0, $1 115 | mov_i32 t0, $1 116 | 117 | only the last instruction is kept. 118 | 119 | 3.4) Instruction Reference 120 | 121 | ********* Function call 122 | 123 | * call ptr 124 | 125 | call function 'ptr' (pointer type) 126 | 127 | optional 32 bit or 64 bit return value 128 | optional 32 bit or 64 bit parameters 129 | 130 | ********* Jumps/Labels 131 | 132 | * jmp t0 133 | 134 | Absolute jump to address t0 (pointer type). 135 | 136 | * set_label $label 137 | 138 | Define label 'label' at the current program point. 139 | 140 | * br $label 141 | 142 | Jump to label. 143 | 144 | * brcond_i32/i64 cond, t0, t1, label 145 | 146 | Conditional jump if t0 cond t1 is true. cond can be: 147 | TCG_COND_EQ 148 | TCG_COND_NE 149 | TCG_COND_LT /* signed */ 150 | TCG_COND_GE /* signed */ 151 | TCG_COND_LE /* signed */ 152 | TCG_COND_GT /* signed */ 153 | TCG_COND_LTU /* unsigned */ 154 | TCG_COND_GEU /* unsigned */ 155 | TCG_COND_LEU /* unsigned */ 156 | TCG_COND_GTU /* unsigned */ 157 | 158 | ********* Arithmetic 159 | 160 | * add_i32/i64 t0, t1, t2 161 | 162 | t0=t1+t2 163 | 164 | * sub_i32/i64 t0, t1, t2 165 | 166 | t0=t1-t2 167 | 168 | * neg_i32/i64 t0, t1 169 | 170 | t0=-t1 (two's complement) 171 | 172 | * mul_i32/i64 t0, t1, t2 173 | 174 | t0=t1*t2 175 | 176 | * div_i32/i64 t0, t1, t2 177 | 178 | t0=t1/t2 (signed). Undefined behavior if division by zero or overflow. 179 | 180 | * divu_i32/i64 t0, t1, t2 181 | 182 | t0=t1/t2 (unsigned). Undefined behavior if division by zero. 183 | 184 | * rem_i32/i64 t0, t1, t2 185 | 186 | t0=t1%t2 (signed). Undefined behavior if division by zero or overflow. 187 | 188 | * remu_i32/i64 t0, t1, t2 189 | 190 | t0=t1%t2 (unsigned). Undefined behavior if division by zero. 191 | 192 | ********* Logical 193 | 194 | * and_i32/i64 t0, t1, t2 195 | 196 | t0=t1&t2 197 | 198 | * or_i32/i64 t0, t1, t2 199 | 200 | t0=t1|t2 201 | 202 | * xor_i32/i64 t0, t1, t2 203 | 204 | t0=t1^t2 205 | 206 | * not_i32/i64 t0, t1 207 | 208 | t0=~t1 209 | 210 | * andc_i32/i64 t0, t1, t2 211 | 212 | t0=t1&~t2 213 | 214 | * eqv_i32/i64 t0, t1, t2 215 | 216 | t0=~(t1^t2), or equivalently, t0=t1^~t2 217 | 218 | * nand_i32/i64 t0, t1, t2 219 | 220 | t0=~(t1&t2) 221 | 222 | * nor_i32/i64 t0, t1, t2 223 | 224 | t0=~(t1|t2) 225 | 226 | * orc_i32/i64 t0, t1, t2 227 | 228 | t0=t1|~t2 229 | 230 | ********* Shifts/Rotates 231 | 232 | * shl_i32/i64 t0, t1, t2 233 | 234 | t0=t1 << t2. Undefined behavior if t2 < 0 or t2 >= 32 (resp 64) 235 | 236 | * shr_i32/i64 t0, t1, t2 237 | 238 | t0=t1 >> t2 (unsigned). Undefined behavior if t2 < 0 or t2 >= 32 (resp 64) 239 | 240 | * sar_i32/i64 t0, t1, t2 241 | 242 | t0=t1 >> t2 (signed). Undefined behavior if t2 < 0 or t2 >= 32 (resp 64) 243 | 244 | * rotl_i32/i64 t0, t1, t2 245 | 246 | Rotation of t2 bits to the left. Undefined behavior if t2 < 0 or t2 >= 32 (resp 64) 247 | 248 | * rotr_i32/i64 t0, t1, t2 249 | 250 | Rotation of t2 bits to the right. Undefined behavior if t2 < 0 or t2 >= 32 (resp 64) 251 | 252 | ********* Misc 253 | 254 | * mov_i32/i64 t0, t1 255 | 256 | t0 = t1 257 | 258 | Move t1 to t0 (both operands must have the same type). 259 | 260 | * ext8s_i32/i64 t0, t1 261 | ext8u_i32/i64 t0, t1 262 | ext16s_i32/i64 t0, t1 263 | ext16u_i32/i64 t0, t1 264 | ext32s_i64 t0, t1 265 | ext32u_i64 t0, t1 266 | 267 | 8, 16 or 32 bit sign/zero extension (both operands must have the same type) 268 | 269 | * bswap16_i32/i64 t0, t1 270 | 271 | 16 bit byte swap on a 32/64 bit value. It assumes that the two/six high order 272 | bytes are set to zero. 273 | 274 | * bswap32_i32/i64 t0, t1 275 | 276 | 32 bit byte swap on a 32/64 bit value. With a 64 bit value, it assumes that 277 | the four high order bytes are set to zero. 278 | 279 | * bswap64_i64 t0, t1 280 | 281 | 64 bit byte swap 282 | 283 | * discard_i32/i64 t0 284 | 285 | Indicate that the value of t0 won't be used later. It is useful to 286 | force dead code elimination. 287 | 288 | * deposit_i32/i64 dest, t1, t2, pos, len 289 | 290 | Deposit T2 as a bitfield into T1, placing the result in DEST. 291 | The bitfield is described by POS/LEN, which are immediate values: 292 | 293 | LEN - the length of the bitfield 294 | POS - the position of the first bit, counting from the LSB 295 | 296 | For example, pos=8, len=4 indicates a 4-bit field at bit 8. 297 | This operation would be equivalent to 298 | 299 | dest = (t1 & ~0x0f00) | ((t2 << 8) & 0x0f00) 300 | 301 | 302 | ********* Conditional moves 303 | 304 | * setcond_i32/i64 cond, dest, t1, t2 305 | 306 | dest = (t1 cond t2) 307 | 308 | Set DEST to 1 if (T1 cond T2) is true, otherwise set to 0. 309 | 310 | ********* Type conversions 311 | 312 | * ext_i32_i64 t0, t1 313 | Convert t1 (32 bit) to t0 (64 bit) and does sign extension 314 | 315 | * extu_i32_i64 t0, t1 316 | Convert t1 (32 bit) to t0 (64 bit) and does zero extension 317 | 318 | * trunc_i64_i32 t0, t1 319 | Truncate t1 (64 bit) to t0 (32 bit) 320 | 321 | * concat_i32_i64 t0, t1, t2 322 | Construct t0 (64-bit) taking the low half from t1 (32 bit) and the high half 323 | from t2 (32 bit). 324 | 325 | * concat32_i64 t0, t1, t2 326 | Construct t0 (64-bit) taking the low half from t1 (64 bit) and the high half 327 | from t2 (64 bit). 328 | 329 | ********* Load/Store 330 | 331 | * ld_i32/i64 t0, t1, offset 332 | ld8s_i32/i64 t0, t1, offset 333 | ld8u_i32/i64 t0, t1, offset 334 | ld16s_i32/i64 t0, t1, offset 335 | ld16u_i32/i64 t0, t1, offset 336 | ld32s_i64 t0, t1, offset 337 | ld32u_i64 t0, t1, offset 338 | 339 | t0 = read(t1 + offset) 340 | Load 8, 16, 32 or 64 bits with or without sign extension from host memory. 341 | offset must be a constant. 342 | 343 | * st_i32/i64 t0, t1, offset 344 | st8_i32/i64 t0, t1, offset 345 | st16_i32/i64 t0, t1, offset 346 | st32_i64 t0, t1, offset 347 | 348 | write(t0, t1 + offset) 349 | Write 8, 16, 32 or 64 bits to host memory. 350 | 351 | ********* 64-bit target on 32-bit host support 352 | 353 | The following opcodes are internal to TCG. Thus they are to be implemented by 354 | 32-bit host code generators, but are not to be emitted by guest translators. 355 | They are emitted as needed by inline functions within "tcg-op.h". 356 | 357 | * brcond2_i32 cond, t0_low, t0_high, t1_low, t1_high, label 358 | 359 | Similar to brcond, except that the 64-bit values T0 and T1 360 | are formed from two 32-bit arguments. 361 | 362 | * add2_i32 t0_low, t0_high, t1_low, t1_high, t2_low, t2_high 363 | * sub2_i32 t0_low, t0_high, t1_low, t1_high, t2_low, t2_high 364 | 365 | Similar to add/sub, except that the 64-bit inputs T1 and T2 are 366 | formed from two 32-bit arguments, and the 64-bit output T0 367 | is returned in two 32-bit outputs. 368 | 369 | * mulu2_i32 t0_low, t0_high, t1, t2 370 | 371 | Similar to mul, except two 32-bit (unsigned) inputs T1 and T2 yielding 372 | the full 64-bit product T0. The later is returned in two 32-bit outputs. 373 | 374 | * setcond2_i32 cond, dest, t1_low, t1_high, t2_low, t2_high 375 | 376 | Similar to setcond, except that the 64-bit values T1 and T2 are 377 | formed from two 32-bit arguments. The result is a 32-bit value. 378 | 379 | ********* QEMU specific operations 380 | 381 | * exit_tb t0 382 | 383 | Exit the current TB and return the value t0 (word type). 384 | 385 | * goto_tb index 386 | 387 | Exit the current TB and jump to the TB index 'index' (constant) if the 388 | current TB was linked to this TB. Otherwise execute the next 389 | instructions. 390 | 391 | * qemu_ld8u t0, t1, flags 392 | qemu_ld8s t0, t1, flags 393 | qemu_ld16u t0, t1, flags 394 | qemu_ld16s t0, t1, flags 395 | qemu_ld32 t0, t1, flags 396 | qemu_ld32u t0, t1, flags 397 | qemu_ld32s t0, t1, flags 398 | qemu_ld64 t0, t1, flags 399 | 400 | Load data at the QEMU CPU address t1 into t0. t1 has the QEMU CPU address 401 | type. 'flags' contains the QEMU memory index (selects user or kernel access) 402 | for example. 403 | 404 | Note that "qemu_ld32" implies a 32-bit result, while "qemu_ld32u" and 405 | "qemu_ld32s" imply a 64-bit result appropriately extended from 32 bits. 406 | 407 | * qemu_st8 t0, t1, flags 408 | qemu_st16 t0, t1, flags 409 | qemu_st32 t0, t1, flags 410 | qemu_st64 t0, t1, flags 411 | 412 | Store the data t0 at the QEMU CPU Address t1. t1 has the QEMU CPU 413 | address type. 'flags' contains the QEMU memory index (selects user or 414 | kernel access) for example. 415 | 416 | Note 1: Some shortcuts are defined when the last operand is known to be 417 | a constant (e.g. addi for add, movi for mov). 418 | 419 | Note 2: When using TCG, the opcodes must never be generated directly 420 | as some of them may not be available as "real" opcodes. Always use the 421 | function tcg_gen_xxx(args). 422 | 423 | 4) Backend 424 | 425 | tcg-target.h contains the target specific definitions. tcg-target.c 426 | contains the target specific code. 427 | 428 | 4.1) Assumptions 429 | 430 | The target word size (TCG_TARGET_REG_BITS) is expected to be 32 bit or 431 | 64 bit. It is expected that the pointer has the same size as the word. 432 | 433 | On a 32 bit target, all 64 bit operations are converted to 32 bits. A 434 | few specific operations must be implemented to allow it (see add2_i32, 435 | sub2_i32, brcond2_i32). 436 | 437 | Floating point operations are not supported in this version. A 438 | previous incarnation of the code generator had full support of them, 439 | but it is better to concentrate on integer operations first. 440 | 441 | On a 64 bit target, no assumption is made in TCG about the storage of 442 | the 32 bit values in 64 bit registers. 443 | 444 | 4.2) Constraints 445 | 446 | GCC like constraints are used to define the constraints of every 447 | instruction. Memory constraints are not supported in this 448 | version. Aliases are specified in the input operands as for GCC. 449 | 450 | The same register may be used for both an input and an output, even when 451 | they are not explicitly aliased. If an op expands to multiple target 452 | instructions then care must be taken to avoid clobbering input values. 453 | GCC style "early clobber" outputs are not currently supported. 454 | 455 | A target can define specific register or constant constraints. If an 456 | operation uses a constant input constraint which does not allow all 457 | constants, it must also accept registers in order to have a fallback. 458 | 459 | The movi_i32 and movi_i64 operations must accept any constants. 460 | 461 | The mov_i32 and mov_i64 operations must accept any registers of the 462 | same type. 463 | 464 | The ld/st instructions must accept signed 32 bit constant offsets. It 465 | can be implemented by reserving a specific register to compute the 466 | address if the offset is too big. 467 | 468 | The ld/st instructions must accept any destination (ld) or source (st) 469 | register. 470 | 471 | 4.3) Function call assumptions 472 | 473 | - The only supported types for parameters and return value are: 32 and 474 | 64 bit integers and pointer. 475 | - The stack grows downwards. 476 | - The first N parameters are passed in registers. 477 | - The next parameters are passed on the stack by storing them as words. 478 | - Some registers are clobbered during the call. 479 | - The function can return 0 or 1 value in registers. On a 32 bit 480 | target, functions must be able to return 2 values in registers for 481 | 64 bit return type. 482 | 483 | 5) Recommended coding rules for best performance 484 | 485 | - Use globals to represent the parts of the QEMU CPU state which are 486 | often modified, e.g. the integer registers and the condition 487 | codes. TCG will be able to use host registers to store them. 488 | 489 | - Avoid globals stored in fixed registers. They must be used only to 490 | store the pointer to the CPU state and possibly to store a pointer 491 | to a register window. 492 | 493 | - Use temporaries. Use local temporaries only when really needed, 494 | e.g. when you need to use a value after a jump. Local temporaries 495 | introduce a performance hit in the current TCG implementation: their 496 | content is saved to memory at end of each basic block. 497 | 498 | - Free temporaries and local temporaries when they are no longer used 499 | (tcg_temp_free). Since tcg_const_x() also creates a temporary, you 500 | should free it after it is used. Freeing temporaries does not yield 501 | a better generated code, but it reduces the memory usage of TCG and 502 | the speed of the translation. 503 | 504 | - Don't hesitate to use helpers for complicated or seldom used target 505 | instructions. There is little performance advantage in using TCG to 506 | implement target instructions taking more than about twenty TCG 507 | instructions. Note that this rule of thumb is more applicable to 508 | helpers doing complex logic or arithmetic, where the C compiler has 509 | scope to do a good job of optimisation; it is less relevant where 510 | the instruction is mostly doing loads and stores, and in those cases 511 | inline TCG may still be faster for longer sequences. 512 | 513 | - The hard limit on the number of TCG instructions you can generate 514 | per target instruction is set by MAX_OP_PER_INSTR in exec-all.h -- 515 | you cannot exceed this without risking a buffer overrun. 516 | 517 | - Use the 'discard' instruction if you know that TCG won't be able to 518 | prove that a given global is "dead" at a given program point. The 519 | x86 target uses it to improve the condition codes optimisation. 520 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | - Add new instructions such as: clz, ctz, popcnt. 2 | 3 | - See if it is worth exporting mul2, mulu2, div2, divu2. 4 | 5 | - Support of globals saved in fixed registers between TBs. 6 | 7 | Ideas: 8 | 9 | - Move the slow part of the qemu_ld/st ops after the end of the TB. 10 | 11 | - Change exception syntax to get closer to QOP system (exception 12 | parameters given with a specific instruction). 13 | 14 | - Add float and vector support. 15 | -------------------------------------------------------------------------------- /include/tcg/exec.h: -------------------------------------------------------------------------------- 1 | /* 2 | * internal execution defines for qemu 3 | * 4 | * Copyright (c) 2003 Fabrice Bellard 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | #ifndef EXEC_ALL_H 21 | #define EXEC_ALL_H 22 | 23 | #include 24 | 25 | /* 26 | * Translation Cache-related fields of a TB. 27 | * This struct exists just for convenience; we keep track of TB's in a binary 28 | * search tree, and the only fields needed to compare TB's in the tree are 29 | * @ptr and @size. 30 | * Note: the address of search data can be obtained by adding @size to @ptr. 31 | */ 32 | struct tb_tc { 33 | void *ptr; /* pointer to the translated code */ 34 | size_t size; 35 | }; 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /include/tcg/helper-gen.h: -------------------------------------------------------------------------------- 1 | /* Helper file for declaring TCG helper functions. 2 | This one expands generation functions for tcg opcodes. */ 3 | 4 | #ifndef HELPER_GEN_H 5 | #define HELPER_GEN_H 6 | 7 | #include "helper-head.h" 8 | 9 | #define DEF_HELPER_FLAGS_0(name, flags, ret) \ 10 | static inline void glue(gen_helper_, name)(dh_retvar_decl0(ret)) { \ 11 | tcg_gen_callN((void *) HELPER(name), dh_retvar(ret), 0, NULL); \ 12 | } 13 | 14 | #define DEF_HELPER_FLAGS_1(name, flags, ret, t1) \ 15 | static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) dh_arg_decl(t1, 1)) { \ 16 | TCGTemp *args[1] = {dh_arg(t1, 1)}; \ 17 | tcg_gen_callN((void *) HELPER(name), dh_retvar(ret), 1, args); \ 18 | } 19 | 20 | #define DEF_HELPER_FLAGS_2(name, flags, ret, t1, t2) \ 21 | static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) dh_arg_decl(t1, 1), dh_arg_decl(t2, 2)) { \ 22 | TCGTemp *args[2] = {dh_arg(t1, 1), dh_arg(t2, 2)}; \ 23 | tcg_gen_callN((void *) HELPER(name), dh_retvar(ret), 2, args); \ 24 | } 25 | 26 | #define DEF_HELPER_FLAGS_3(name, flags, ret, t1, t2, t3) \ 27 | static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), \ 28 | dh_arg_decl(t3, 3)) { \ 29 | TCGTemp *args[3] = {dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3)}; \ 30 | tcg_gen_callN((void *) HELPER(name), dh_retvar(ret), 3, args); \ 31 | } 32 | 33 | #define DEF_HELPER_FLAGS_4(name, flags, ret, t1, t2, t3, t4) \ 34 | static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), \ 35 | dh_arg_decl(t3, 3), dh_arg_decl(t4, 4)) { \ 36 | TCGTemp *args[4] = {dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3), dh_arg(t4, 4)}; \ 37 | tcg_gen_callN((void *) HELPER(name), dh_retvar(ret), 4, args); \ 38 | } 39 | 40 | #define DEF_HELPER_FLAGS_5(name, flags, ret, t1, t2, t3, t4, t5) \ 41 | static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), \ 42 | dh_arg_decl(t3, 3), dh_arg_decl(t4, 4), dh_arg_decl(t5, 5)) { \ 43 | TCGTemp *args[5] = {dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3), dh_arg(t4, 4), dh_arg(t5, 5)}; \ 44 | tcg_gen_callN((void *) HELPER(name), dh_retvar(ret), 5, args); \ 45 | } 46 | 47 | #define DEF_HELPER_FLAGS_6(name, flags, ret, t1, t2, t3, t4, t5, t6) \ 48 | static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), \ 49 | dh_arg_decl(t3, 3), dh_arg_decl(t4, 4), dh_arg_decl(t5, 5), \ 50 | dh_arg_decl(t6, 6)) { \ 51 | TCGTemp *args[6] = {dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3), dh_arg(t4, 4), dh_arg(t5, 5), dh_arg(t6, 6)}; \ 52 | tcg_gen_callN((void *) HELPER(name), dh_retvar(ret), 6, args); \ 53 | } 54 | 55 | #include "helper.h" 56 | // #include "trace/generated-helpers.h" 57 | #include "tcg-runtime.h" 58 | // #include "trace/generated-helpers-wrappers.h" 59 | 60 | #undef DEF_HELPER_FLAGS_0 61 | #undef DEF_HELPER_FLAGS_1 62 | #undef DEF_HELPER_FLAGS_2 63 | #undef DEF_HELPER_FLAGS_3 64 | #undef DEF_HELPER_FLAGS_4 65 | #undef DEF_HELPER_FLAGS_5 66 | #undef DEF_HELPER_FLAGS_6 67 | #undef GEN_HELPER 68 | 69 | #endif /* HELPER_GEN_H */ 70 | -------------------------------------------------------------------------------- /include/tcg/helper-head.h: -------------------------------------------------------------------------------- 1 | /* Helper file for declaring TCG helper functions. 2 | Used by other helper files. 3 | 4 | Targets should use DEF_HELPER_N and DEF_HELPER_FLAGS_N to declare helper 5 | functions. Names should be specified without the helper_ prefix, and 6 | the return and argument types specified. 3 basic types are understood 7 | (i32, i64 and ptr). Additional aliases are provided for convenience and 8 | to match the types used by the C helper implementation. 9 | 10 | The target helper.h should be included in all files that use/define 11 | helper functions. THis will ensure that function prototypes are 12 | consistent. In addition it should be included an extra two times for 13 | helper.c, defining: 14 | GEN_HELPER 1 to produce op generation functions (gen_helper_*) 15 | GEN_HELPER 2 to do runtime registration helper functions. 16 | */ 17 | 18 | #ifndef EXEC_HELPER_HEAD_H 19 | #define EXEC_HELPER_HEAD_H 20 | 21 | #define HELPER(name) glue(helper_, name) 22 | 23 | /* Some types that make sense in C, but not for TCG. */ 24 | #define dh_alias_i32 i32 25 | #define dh_alias_s32 i32 26 | #define dh_alias_int i32 27 | #define dh_alias_i64 i64 28 | #define dh_alias_s64 i64 29 | #define dh_alias_f16 i32 30 | #define dh_alias_f32 i32 31 | #define dh_alias_f64 i64 32 | #define dh_alias_ptr ptr 33 | #define dh_alias_cptr ptr 34 | #define dh_alias_void void 35 | #define dh_alias_noreturn noreturn 36 | #define dh_alias(t) glue(dh_alias_, t) 37 | 38 | #define dh_ctype_i32 uint32_t 39 | #define dh_ctype_s32 int32_t 40 | #define dh_ctype_int int 41 | #define dh_ctype_i64 uint64_t 42 | #define dh_ctype_s64 int64_t 43 | #define dh_ctype_f16 uint32_t 44 | #define dh_ctype_f32 float32 45 | #define dh_ctype_f64 float64 46 | #define dh_ctype_ptr void * 47 | #define dh_ctype_cptr const void * 48 | #define dh_ctype_void void 49 | #define dh_ctype_noreturn void QEMU_NORETURN 50 | #define dh_ctype(t) dh_ctype_##t 51 | 52 | //#ifdef NEED_CPU_H 53 | #ifdef TARGET_LONG_BITS 54 | #if TARGET_LONG_BITS == 32 55 | #define dh_alias_tl i32 56 | #else 57 | #define dh_alias_tl i64 58 | #endif 59 | #endif 60 | #define dh_alias_env ptr 61 | #define dh_ctype_tl target_ulong 62 | #define dh_ctype_env CPUArchState * 63 | //#endif 64 | 65 | /* We can't use glue() here because it falls foul of C preprocessor 66 | recursive expansion rules. */ 67 | #define dh_retvar_decl0_void void 68 | #define dh_retvar_decl0_noreturn void 69 | #define dh_retvar_decl0_i32 TCGv_i32 retval 70 | #define dh_retvar_decl0_i64 TCGv_i64 retval 71 | #define dh_retvar_decl0_ptr TCGv_ptr retval 72 | #define dh_retvar_decl0(t) glue(dh_retvar_decl0_, dh_alias(t)) 73 | 74 | #define dh_retvar_decl_void 75 | #define dh_retvar_decl_noreturn 76 | #define dh_retvar_decl_i32 TCGv_i32 retval, 77 | #define dh_retvar_decl_i64 TCGv_i64 retval, 78 | #define dh_retvar_decl_ptr TCGv_ptr retval, 79 | #define dh_retvar_decl(t) glue(dh_retvar_decl_, dh_alias(t)) 80 | 81 | #define dh_retvar_void NULL 82 | #define dh_retvar_noreturn NULL 83 | #define dh_retvar_i32 tcgv_i32_temp(retval) 84 | #define dh_retvar_i64 tcgv_i64_temp(retval) 85 | #define dh_retvar_ptr tcgv_ptr_temp(retval) 86 | #define dh_retvar(t) glue(dh_retvar_, dh_alias(t)) 87 | 88 | #define dh_is_64bit_void 0 89 | #define dh_is_64bit_noreturn 0 90 | #define dh_is_64bit_i32 0 91 | #define dh_is_64bit_i64 1 92 | #define dh_is_64bit_ptr (sizeof(void *) == 8) 93 | #define dh_is_64bit_cptr dh_is_64bit_ptr 94 | #define dh_is_64bit(t) glue(dh_is_64bit_, dh_alias(t)) 95 | 96 | #define dh_is_signed_void 0 97 | #define dh_is_signed_noreturn 0 98 | #define dh_is_signed_i32 0 99 | #define dh_is_signed_s32 1 100 | #define dh_is_signed_i64 0 101 | #define dh_is_signed_s64 1 102 | #define dh_is_signed_f16 0 103 | #define dh_is_signed_f32 0 104 | #define dh_is_signed_f64 0 105 | #define dh_is_signed_tl 0 106 | #define dh_is_signed_int 1 107 | /* ??? This is highly specific to the host cpu. There are even special 108 | extension instructions that may be required, e.g. ia64's addp4. But 109 | for now we don't support any 64-bit targets with 32-bit pointers. */ 110 | #define dh_is_signed_ptr 0 111 | #define dh_is_signed_cptr dh_is_signed_ptr 112 | #define dh_is_signed_env dh_is_signed_ptr 113 | #define dh_is_signed(t) dh_is_signed_##t 114 | 115 | #define dh_callflag_i32 0 116 | #define dh_callflag_s32 0 117 | #define dh_callflag_int 0 118 | #define dh_callflag_i64 0 119 | #define dh_callflag_s64 0 120 | #define dh_callflag_f16 0 121 | #define dh_callflag_f32 0 122 | #define dh_callflag_f64 0 123 | #define dh_callflag_ptr 0 124 | #define dh_callflag_cptr dh_callflag_ptr 125 | #define dh_callflag_void 0 126 | #define dh_callflag_noreturn TCG_CALL_NO_RETURN 127 | #define dh_callflag(t) glue(dh_callflag_, dh_alias(t)) 128 | 129 | #define dh_sizemask(t, n) ((dh_is_64bit(t) << (n * 2)) | (dh_is_signed(t) << (n * 2 + 1))) 130 | 131 | #define dh_arg(t, n) glue(glue(tcgv_, dh_alias(t)), _temp)(glue(arg, n)) 132 | 133 | #define dh_arg_decl(t, n) glue(TCGv_, dh_alias(t)) glue(arg, n) 134 | 135 | #define DEF_HELPER_0(name, ret) DEF_HELPER_FLAGS_0(name, 0, ret) 136 | #define DEF_HELPER_1(name, ret, t1) DEF_HELPER_FLAGS_1(name, 0, ret, t1) 137 | #define DEF_HELPER_2(name, ret, t1, t2) DEF_HELPER_FLAGS_2(name, 0, ret, t1, t2) 138 | #define DEF_HELPER_3(name, ret, t1, t2, t3) DEF_HELPER_FLAGS_3(name, 0, ret, t1, t2, t3) 139 | #define DEF_HELPER_4(name, ret, t1, t2, t3, t4) DEF_HELPER_FLAGS_4(name, 0, ret, t1, t2, t3, t4) 140 | #define DEF_HELPER_5(name, ret, t1, t2, t3, t4, t5) DEF_HELPER_FLAGS_5(name, 0, ret, t1, t2, t3, t4, t5) 141 | #define DEF_HELPER_6(name, ret, t1, t2, t3, t4, t5, t6) DEF_HELPER_FLAGS_6(name, 0, ret, t1, t2, t3, t4, t5, t6) 142 | 143 | /* MAX_OPC_PARAM_IARGS must be set to n if last entry is DEF_HELPER_FLAGS_n. */ 144 | 145 | #endif /* EXEC_HELPER_HEAD_H */ 146 | -------------------------------------------------------------------------------- /include/tcg/helper-proto.h: -------------------------------------------------------------------------------- 1 | /* Helper file for declaring TCG helper functions. 2 | This one expands prototypes for the helper functions. */ 3 | 4 | #ifndef HELPER_PROTO_H 5 | #define HELPER_PROTO_H 6 | 7 | #include "helper-head.h" 8 | 9 | #define DEF_HELPER_FLAGS_0(name, flags, ret) dh_ctype(ret) HELPER(name)(void); 10 | 11 | #define DEF_HELPER_FLAGS_1(name, flags, ret, t1) dh_ctype(ret) HELPER(name)(dh_ctype(t1)); 12 | 13 | #define DEF_HELPER_FLAGS_2(name, flags, ret, t1, t2) dh_ctype(ret) HELPER(name)(dh_ctype(t1), dh_ctype(t2)); 14 | 15 | #define DEF_HELPER_FLAGS_3(name, flags, ret, t1, t2, t3) \ 16 | dh_ctype(ret) HELPER(name)(dh_ctype(t1), dh_ctype(t2), dh_ctype(t3)); 17 | 18 | #define DEF_HELPER_FLAGS_4(name, flags, ret, t1, t2, t3, t4) \ 19 | dh_ctype(ret) HELPER(name)(dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), dh_ctype(t4)); 20 | 21 | #define DEF_HELPER_FLAGS_5(name, flags, ret, t1, t2, t3, t4, t5) \ 22 | dh_ctype(ret) HELPER(name)(dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), dh_ctype(t4), dh_ctype(t5)); 23 | 24 | #define DEF_HELPER_FLAGS_6(name, flags, ret, t1, t2, t3, t4, t5, t6) \ 25 | dh_ctype(ret) HELPER(name)(dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), dh_ctype(t4), dh_ctype(t5), dh_ctype(t6)); 26 | 27 | #include "helper.h" 28 | // #include "trace/generated-helpers.h" 29 | #include "tcg-runtime.h" 30 | 31 | #undef DEF_HELPER_FLAGS_0 32 | #undef DEF_HELPER_FLAGS_1 33 | #undef DEF_HELPER_FLAGS_2 34 | #undef DEF_HELPER_FLAGS_3 35 | #undef DEF_HELPER_FLAGS_4 36 | #undef DEF_HELPER_FLAGS_5 37 | #undef DEF_HELPER_FLAGS_6 38 | 39 | #endif /* HELPER_PROTO_H */ 40 | -------------------------------------------------------------------------------- /include/tcg/helper-tcg.h: -------------------------------------------------------------------------------- 1 | /* Helper file for declaring TCG helper functions. 2 | This one defines data structures private to tcg.c. */ 3 | 4 | #ifndef HELPER_TCG_H 5 | #define HELPER_TCG_H 6 | 7 | #include "helper-head.h" 8 | 9 | /* Need one more level of indirection before stringification 10 | to get all the macros expanded first. */ 11 | #define str(s) #s 12 | 13 | #define DEF_HELPER_FLAGS_0(NAME, FLAGS, ret) \ 14 | {.func = HELPER(NAME), .name = str(NAME), .flags = FLAGS | dh_callflag(ret), .sizemask = dh_sizemask(ret, 0)}, 15 | 16 | #define DEF_HELPER_FLAGS_1(NAME, FLAGS, ret, t1) \ 17 | {.func = HELPER(NAME), \ 18 | .name = str(NAME), \ 19 | .flags = FLAGS | dh_callflag(ret), \ 20 | .sizemask = dh_sizemask(ret, 0) | dh_sizemask(t1, 1)}, 21 | 22 | #define DEF_HELPER_FLAGS_2(NAME, FLAGS, ret, t1, t2) \ 23 | {.func = HELPER(NAME), \ 24 | .name = str(NAME), \ 25 | .flags = FLAGS | dh_callflag(ret), \ 26 | .sizemask = dh_sizemask(ret, 0) | dh_sizemask(t1, 1) | dh_sizemask(t2, 2)}, 27 | 28 | #define DEF_HELPER_FLAGS_3(NAME, FLAGS, ret, t1, t2, t3) \ 29 | {.func = HELPER(NAME), \ 30 | .name = str(NAME), \ 31 | .flags = FLAGS | dh_callflag(ret), \ 32 | .sizemask = dh_sizemask(ret, 0) | dh_sizemask(t1, 1) | dh_sizemask(t2, 2) | dh_sizemask(t3, 3)}, 33 | 34 | #define DEF_HELPER_FLAGS_4(NAME, FLAGS, ret, t1, t2, t3, t4) \ 35 | {.func = HELPER(NAME), \ 36 | .name = str(NAME), \ 37 | .flags = FLAGS | dh_callflag(ret), \ 38 | .sizemask = \ 39 | dh_sizemask(ret, 0) | dh_sizemask(t1, 1) | dh_sizemask(t2, 2) | dh_sizemask(t3, 3) | dh_sizemask(t4, 4)}, 40 | 41 | #define DEF_HELPER_FLAGS_5(NAME, FLAGS, ret, t1, t2, t3, t4, t5) \ 42 | {.func = HELPER(NAME), \ 43 | .name = str(NAME), \ 44 | .flags = FLAGS | dh_callflag(ret), \ 45 | .sizemask = dh_sizemask(ret, 0) | dh_sizemask(t1, 1) | dh_sizemask(t2, 2) | dh_sizemask(t3, 3) | \ 46 | dh_sizemask(t4, 4) | dh_sizemask(t5, 5)}, 47 | 48 | #define DEF_HELPER_FLAGS_6(NAME, FLAGS, ret, t1, t2, t3, t4, t5, t6) \ 49 | {.func = HELPER(NAME), \ 50 | .name = str(NAME), \ 51 | .flags = FLAGS | dh_callflag(ret), \ 52 | .sizemask = dh_sizemask(ret, 0) | dh_sizemask(t1, 1) | dh_sizemask(t2, 2) | dh_sizemask(t3, 3) | \ 53 | dh_sizemask(t4, 4) | dh_sizemask(t5, 5) | dh_sizemask(t6, 6)}, 54 | 55 | #include 56 | // #include 57 | 58 | #undef str 59 | #undef DEF_HELPER_FLAGS_0 60 | #undef DEF_HELPER_FLAGS_1 61 | #undef DEF_HELPER_FLAGS_2 62 | #undef DEF_HELPER_FLAGS_3 63 | #undef DEF_HELPER_FLAGS_4 64 | #undef DEF_HELPER_FLAGS_5 65 | #undef DEF_HELPER_FLAGS_6 66 | 67 | #endif /* HELPER_TCG_H */ 68 | -------------------------------------------------------------------------------- /include/tcg/helper.h: -------------------------------------------------------------------------------- 1 | DEF_HELPER_1(cc_compute_all, i32, int) 2 | DEF_HELPER_1(cc_compute_c, i32, int) 3 | 4 | DEF_HELPER_0(lock, void) 5 | DEF_HELPER_0(unlock, void) 6 | DEF_HELPER_2(write_eflags, void, tl, i32) 7 | DEF_HELPER_0(read_eflags, tl) 8 | DEF_HELPER_1(divb_AL, void, tl) 9 | DEF_HELPER_1(idivb_AL, void, tl) 10 | DEF_HELPER_1(divw_AX, void, tl) 11 | DEF_HELPER_1(idivw_AX, void, tl) 12 | DEF_HELPER_1(divl_EAX, void, tl) 13 | DEF_HELPER_1(idivl_EAX, void, tl) 14 | #ifdef TARGET_X86_64 15 | DEF_HELPER_1(mulq_EAX_T0, void, tl) 16 | DEF_HELPER_1(imulq_EAX_T0, void, tl) 17 | DEF_HELPER_2(imulq_T0_T1, tl, tl, tl) 18 | DEF_HELPER_1(divq_EAX, void, tl) 19 | DEF_HELPER_1(idivq_EAX, void, tl) 20 | #endif 21 | 22 | DEF_HELPER_1(aam, void, int) 23 | DEF_HELPER_1(aad, void, int) 24 | DEF_HELPER_0(aaa, void) 25 | DEF_HELPER_0(aas, void) 26 | DEF_HELPER_0(daa, void) 27 | DEF_HELPER_0(das, void) 28 | 29 | /* NOTE: segment-related instructions access memory, but the value 30 | will be concretized anyway because it is stored in 31 | always-concrete part of the CPUState */ 32 | DEF_HELPER_1(lsl, tl, tl) 33 | DEF_HELPER_1(lar, tl, tl) 34 | DEF_HELPER_1(verr, void, tl) 35 | DEF_HELPER_1(verw, void, tl) 36 | DEF_HELPER_1(lldt, void, int) 37 | DEF_HELPER_1(ltr, void, int) 38 | DEF_HELPER_2(load_seg, void, int, int) 39 | DEF_HELPER_3(ljmp_protected, void, int, tl, int) 40 | DEF_HELPER_4(lcall_real, void, int, tl, int, int) 41 | DEF_HELPER_4(lcall_protected, void, int, tl, int, int) 42 | DEF_HELPER_1(iret_real, void, int) 43 | DEF_HELPER_2(iret_protected, void, int, int) 44 | DEF_HELPER_2(lret_protected, void, int, int) 45 | DEF_HELPER_1(read_crN, tl, int) 46 | DEF_HELPER_2(write_crN, void, int, tl) 47 | DEF_HELPER_1(lmsw, void, tl) 48 | DEF_HELPER_0(clts, void) 49 | DEF_HELPER_2(movl_drN_T0, void, int, tl) 50 | DEF_HELPER_1(invlpg, void, tl) 51 | 52 | DEF_HELPER_3(enter_level, void, int, int, tl) 53 | #ifdef TARGET_X86_64 54 | DEF_HELPER_3(enter64_level, void, int, int, tl) 55 | #endif 56 | DEF_HELPER_0(sysenter, void) 57 | DEF_HELPER_1(sysexit, void, int) 58 | #ifdef TARGET_X86_64 59 | DEF_HELPER_1(syscall, void, int) 60 | DEF_HELPER_1(sysret, void, int) 61 | #endif 62 | DEF_HELPER_1(hlt, void, int) 63 | DEF_HELPER_1(monitor, void, tl) 64 | DEF_HELPER_1(mwait, void, int) 65 | DEF_HELPER_0(debug, void) 66 | DEF_HELPER_0(reset_rf, void) 67 | DEF_HELPER_2(raise_interrupt, void, int, int) 68 | DEF_HELPER_1(raise_exception, void, int) 69 | DEF_HELPER_0(cli, void) 70 | DEF_HELPER_0(sti, void) 71 | DEF_HELPER_0(set_inhibit_irq, void) 72 | DEF_HELPER_0(reset_inhibit_irq, void) 73 | DEF_HELPER_2(boundw, void, tl, int) 74 | DEF_HELPER_2(boundl, void, tl, int) 75 | DEF_HELPER_0(rsm, void) 76 | DEF_HELPER_1(into, void, int) 77 | DEF_HELPER_1(cmpxchg8b, void, tl) 78 | #ifdef TARGET_X86_64 79 | DEF_HELPER_1(cmpxchg16b, void, tl) 80 | #endif 81 | DEF_HELPER_0(single_step, void) 82 | DEF_HELPER_0(cpuid, void) 83 | DEF_HELPER_0(rdtsc, void) 84 | DEF_HELPER_0(rdtscp, void) 85 | DEF_HELPER_0(rdpmc, void) 86 | DEF_HELPER_0(rdmsr, void) 87 | DEF_HELPER_0(wrmsr, void) 88 | 89 | DEF_HELPER_1(check_iob, void, i32) 90 | DEF_HELPER_1(check_iow, void, i32) 91 | DEF_HELPER_1(check_iol, void, i32) 92 | DEF_HELPER_2(outb, void, i32, i32) 93 | DEF_HELPER_1(inb, tl, i32) 94 | DEF_HELPER_2(outw, void, i32, i32) 95 | DEF_HELPER_1(inw, tl, i32) 96 | DEF_HELPER_2(outl, void, i32, i32) 97 | DEF_HELPER_1(inl, tl, i32) 98 | 99 | DEF_HELPER_2(svm_check_intercept_param, void, i32, i64) 100 | DEF_HELPER_2(vmexit, void, i32, i64) 101 | DEF_HELPER_3(svm_check_io, void, i32, i32, i32) 102 | DEF_HELPER_2(vmrun, void, int, int) 103 | DEF_HELPER_0(vmmcall, void) 104 | DEF_HELPER_1(vmload, void, int) 105 | DEF_HELPER_1(vmsave, void, int) 106 | DEF_HELPER_0(stgi, void) 107 | DEF_HELPER_0(clgi, void) 108 | DEF_HELPER_0(skinit, void) 109 | DEF_HELPER_1(invlpga, void, int) 110 | 111 | /* x86 FPU */ 112 | 113 | DEF_HELPER_1(flds_FT0, void, i32) 114 | DEF_HELPER_1(fldl_FT0, void, i64) 115 | DEF_HELPER_1(fildl_FT0, void, s32) 116 | DEF_HELPER_1(flds_ST0, void, i32) 117 | DEF_HELPER_1(fldl_ST0, void, i64) 118 | DEF_HELPER_1(fildl_ST0, void, s32) 119 | DEF_HELPER_1(fildll_ST0, void, s64) 120 | DEF_HELPER_0(fsts_ST0, i32) 121 | DEF_HELPER_0(fstl_ST0, i64) 122 | DEF_HELPER_0(fist_ST0, s32) 123 | DEF_HELPER_0(fistl_ST0, s32) 124 | DEF_HELPER_0(fistll_ST0, s64) 125 | DEF_HELPER_0(fistt_ST0, s32) 126 | DEF_HELPER_0(fisttl_ST0, s32) 127 | DEF_HELPER_0(fisttll_ST0, s64) 128 | DEF_HELPER_1(fldt_ST0, void, tl) 129 | DEF_HELPER_1(fstt_ST0, void, tl) 130 | DEF_HELPER_0(fpush, void) 131 | DEF_HELPER_0(fpop, void) 132 | DEF_HELPER_0(fdecstp, void) 133 | DEF_HELPER_0(fincstp, void) 134 | DEF_HELPER_1(ffree_STN, void, int) 135 | DEF_HELPER_0(fmov_ST0_FT0, void) 136 | DEF_HELPER_1(fmov_FT0_STN, void, int) 137 | DEF_HELPER_1(fmov_ST0_STN, void, int) 138 | DEF_HELPER_1(fmov_STN_ST0, void, int) 139 | DEF_HELPER_1(fxchg_ST0_STN, void, int) 140 | DEF_HELPER_0(fcom_ST0_FT0, void) 141 | DEF_HELPER_0(fucom_ST0_FT0, void) 142 | DEF_HELPER_0(fcomi_ST0_FT0, void) 143 | DEF_HELPER_0(fucomi_ST0_FT0, void) 144 | DEF_HELPER_0(fadd_ST0_FT0, void) 145 | DEF_HELPER_0(fmul_ST0_FT0, void) 146 | DEF_HELPER_0(fsub_ST0_FT0, void) 147 | DEF_HELPER_0(fsubr_ST0_FT0, void) 148 | DEF_HELPER_0(fdiv_ST0_FT0, void) 149 | DEF_HELPER_0(fdivr_ST0_FT0, void) 150 | DEF_HELPER_1(fadd_STN_ST0, void, int) 151 | DEF_HELPER_1(fmul_STN_ST0, void, int) 152 | DEF_HELPER_1(fsub_STN_ST0, void, int) 153 | DEF_HELPER_1(fsubr_STN_ST0, void, int) 154 | DEF_HELPER_1(fdiv_STN_ST0, void, int) 155 | DEF_HELPER_1(fdivr_STN_ST0, void, int) 156 | DEF_HELPER_0(fchs_ST0, void) 157 | DEF_HELPER_0(fabs_ST0, void) 158 | DEF_HELPER_0(fxam_ST0, void) 159 | DEF_HELPER_0(fld1_ST0, void) 160 | DEF_HELPER_0(fldl2t_ST0, void) 161 | DEF_HELPER_0(fldl2e_ST0, void) 162 | DEF_HELPER_0(fldpi_ST0, void) 163 | DEF_HELPER_0(fldlg2_ST0, void) 164 | DEF_HELPER_0(fldln2_ST0, void) 165 | DEF_HELPER_0(fldz_ST0, void) 166 | DEF_HELPER_0(fldz_FT0, void) 167 | DEF_HELPER_0(fnstsw, i32) 168 | DEF_HELPER_0(fnstcw, i32) 169 | DEF_HELPER_1(fldcw, void, i32) 170 | DEF_HELPER_0(fclex, void) 171 | DEF_HELPER_0(fwait, void) 172 | DEF_HELPER_0(fninit, void) 173 | DEF_HELPER_1(fbld_ST0, void, tl) 174 | DEF_HELPER_1(fbst_ST0, void, tl) 175 | DEF_HELPER_0(f2xm1, void) 176 | DEF_HELPER_0(fyl2x, void) 177 | DEF_HELPER_0(fptan, void) 178 | DEF_HELPER_0(fpatan, void) 179 | DEF_HELPER_0(fxtract, void) 180 | DEF_HELPER_0(fprem1, void) 181 | DEF_HELPER_0(fprem, void) 182 | DEF_HELPER_0(fyl2xp1, void) 183 | DEF_HELPER_0(fsqrt, void) 184 | DEF_HELPER_0(fsincos, void) 185 | DEF_HELPER_0(frndint, void) 186 | DEF_HELPER_0(fscale, void) 187 | DEF_HELPER_0(fsin, void) 188 | DEF_HELPER_0(fcos, void) 189 | DEF_HELPER_2(fstenv, void, tl, int) 190 | DEF_HELPER_2(fldenv, void, tl, int) 191 | DEF_HELPER_2(fsave, void, tl, int) 192 | DEF_HELPER_2(frstor, void, tl, int) 193 | DEF_HELPER_2(fxsave, void, tl, int) 194 | DEF_HELPER_2(fxrstor, void, tl, int) 195 | 196 | DEF_HELPER_1(bsf, tl, tl) 197 | DEF_HELPER_1(bsr, tl, tl) 198 | DEF_HELPER_2(lzcnt, tl, tl, int) 199 | 200 | /* MMX/SSE */ 201 | DEF_HELPER_1(ldmxcsr, void, i32) 202 | DEF_HELPER_0(enter_mmx, void) 203 | DEF_HELPER_0(emms, void) 204 | DEF_HELPER_2(movq, void, ptr, ptr) 205 | 206 | #define SHIFT 0 207 | #include "ops_sse_header.h" 208 | #define SHIFT 1 209 | #include "ops_sse_header.h" 210 | 211 | DEF_HELPER_2(rclb, tl, tl, tl) 212 | DEF_HELPER_2(rclw, tl, tl, tl) 213 | DEF_HELPER_2(rcll, tl, tl, tl) 214 | DEF_HELPER_2(rcrb, tl, tl, tl) 215 | DEF_HELPER_2(rcrw, tl, tl, tl) 216 | DEF_HELPER_2(rcrl, tl, tl, tl) 217 | #ifdef TARGET_X86_64 218 | DEF_HELPER_2(rclq, tl, tl, tl) 219 | DEF_HELPER_2(rcrq, tl, tl, tl) 220 | #endif 221 | 222 | #if !defined(CONFIG_SYMBEX) 223 | DEF_HELPER_1(se_opcode, void, i64) 224 | #endif 225 | 226 | #if defined(CONFIG_SYMBEX) 227 | DEF_HELPER_1(se_call, void, tl) 228 | DEF_HELPER_1(se_ret, void, tl) 229 | #endif 230 | 231 | DEF_HELPER_FLAGS_3(gvec_mov, TCG_CALL_NO_RWG, void, ptr, ptr, i32) 232 | 233 | DEF_HELPER_FLAGS_3(gvec_dup8, TCG_CALL_NO_RWG, void, ptr, i32, i32) 234 | DEF_HELPER_FLAGS_3(gvec_dup16, TCG_CALL_NO_RWG, void, ptr, i32, i32) 235 | DEF_HELPER_FLAGS_3(gvec_dup32, TCG_CALL_NO_RWG, void, ptr, i32, i32) 236 | DEF_HELPER_FLAGS_3(gvec_dup64, TCG_CALL_NO_RWG, void, ptr, i32, i64) 237 | 238 | DEF_HELPER_FLAGS_4(gvec_add8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 239 | DEF_HELPER_FLAGS_4(gvec_add16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 240 | DEF_HELPER_FLAGS_4(gvec_add32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 241 | DEF_HELPER_FLAGS_4(gvec_add64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 242 | 243 | DEF_HELPER_FLAGS_4(gvec_adds8, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32) 244 | DEF_HELPER_FLAGS_4(gvec_adds16, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32) 245 | DEF_HELPER_FLAGS_4(gvec_adds32, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32) 246 | DEF_HELPER_FLAGS_4(gvec_adds64, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32) 247 | 248 | DEF_HELPER_FLAGS_4(gvec_sub8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 249 | DEF_HELPER_FLAGS_4(gvec_sub16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 250 | DEF_HELPER_FLAGS_4(gvec_sub32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 251 | DEF_HELPER_FLAGS_4(gvec_sub64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 252 | 253 | DEF_HELPER_FLAGS_4(gvec_subs8, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32) 254 | DEF_HELPER_FLAGS_4(gvec_subs16, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32) 255 | DEF_HELPER_FLAGS_4(gvec_subs32, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32) 256 | DEF_HELPER_FLAGS_4(gvec_subs64, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32) 257 | 258 | DEF_HELPER_FLAGS_4(gvec_mul8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 259 | DEF_HELPER_FLAGS_4(gvec_mul16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 260 | DEF_HELPER_FLAGS_4(gvec_mul32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 261 | DEF_HELPER_FLAGS_4(gvec_mul64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 262 | 263 | DEF_HELPER_FLAGS_4(gvec_muls8, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32) 264 | DEF_HELPER_FLAGS_4(gvec_muls16, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32) 265 | DEF_HELPER_FLAGS_4(gvec_muls32, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32) 266 | DEF_HELPER_FLAGS_4(gvec_muls64, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32) 267 | 268 | DEF_HELPER_FLAGS_4(gvec_ssadd8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 269 | DEF_HELPER_FLAGS_4(gvec_ssadd16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 270 | DEF_HELPER_FLAGS_4(gvec_ssadd32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 271 | DEF_HELPER_FLAGS_4(gvec_ssadd64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 272 | 273 | DEF_HELPER_FLAGS_4(gvec_sssub8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 274 | DEF_HELPER_FLAGS_4(gvec_sssub16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 275 | DEF_HELPER_FLAGS_4(gvec_sssub32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 276 | DEF_HELPER_FLAGS_4(gvec_sssub64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 277 | 278 | DEF_HELPER_FLAGS_4(gvec_usadd8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 279 | DEF_HELPER_FLAGS_4(gvec_usadd16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 280 | DEF_HELPER_FLAGS_4(gvec_usadd32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 281 | DEF_HELPER_FLAGS_4(gvec_usadd64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 282 | 283 | DEF_HELPER_FLAGS_4(gvec_ussub8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 284 | DEF_HELPER_FLAGS_4(gvec_ussub16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 285 | DEF_HELPER_FLAGS_4(gvec_ussub32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 286 | DEF_HELPER_FLAGS_4(gvec_ussub64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 287 | 288 | DEF_HELPER_FLAGS_4(gvec_smin8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 289 | DEF_HELPER_FLAGS_4(gvec_smin16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 290 | DEF_HELPER_FLAGS_4(gvec_smin32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 291 | DEF_HELPER_FLAGS_4(gvec_smin64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 292 | 293 | DEF_HELPER_FLAGS_4(gvec_smax8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 294 | DEF_HELPER_FLAGS_4(gvec_smax16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 295 | DEF_HELPER_FLAGS_4(gvec_smax32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 296 | DEF_HELPER_FLAGS_4(gvec_smax64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 297 | 298 | DEF_HELPER_FLAGS_4(gvec_umin8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 299 | DEF_HELPER_FLAGS_4(gvec_umin16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 300 | DEF_HELPER_FLAGS_4(gvec_umin32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 301 | DEF_HELPER_FLAGS_4(gvec_umin64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 302 | 303 | DEF_HELPER_FLAGS_4(gvec_umax8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 304 | DEF_HELPER_FLAGS_4(gvec_umax16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 305 | DEF_HELPER_FLAGS_4(gvec_umax32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 306 | DEF_HELPER_FLAGS_4(gvec_umax64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 307 | 308 | DEF_HELPER_FLAGS_3(gvec_neg8, TCG_CALL_NO_RWG, void, ptr, ptr, i32) 309 | DEF_HELPER_FLAGS_3(gvec_neg16, TCG_CALL_NO_RWG, void, ptr, ptr, i32) 310 | DEF_HELPER_FLAGS_3(gvec_neg32, TCG_CALL_NO_RWG, void, ptr, ptr, i32) 311 | DEF_HELPER_FLAGS_3(gvec_neg64, TCG_CALL_NO_RWG, void, ptr, ptr, i32) 312 | 313 | DEF_HELPER_FLAGS_3(gvec_not, TCG_CALL_NO_RWG, void, ptr, ptr, i32) 314 | DEF_HELPER_FLAGS_4(gvec_and, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 315 | DEF_HELPER_FLAGS_4(gvec_or, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 316 | DEF_HELPER_FLAGS_4(gvec_xor, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 317 | DEF_HELPER_FLAGS_4(gvec_andc, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 318 | DEF_HELPER_FLAGS_4(gvec_orc, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 319 | DEF_HELPER_FLAGS_4(gvec_nand, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 320 | DEF_HELPER_FLAGS_4(gvec_nor, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 321 | DEF_HELPER_FLAGS_4(gvec_eqv, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 322 | 323 | DEF_HELPER_FLAGS_4(gvec_ands, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32) 324 | DEF_HELPER_FLAGS_4(gvec_xors, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32) 325 | DEF_HELPER_FLAGS_4(gvec_ors, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32) 326 | 327 | DEF_HELPER_FLAGS_3(gvec_shl8i, TCG_CALL_NO_RWG, void, ptr, ptr, i32) 328 | DEF_HELPER_FLAGS_3(gvec_shl16i, TCG_CALL_NO_RWG, void, ptr, ptr, i32) 329 | DEF_HELPER_FLAGS_3(gvec_shl32i, TCG_CALL_NO_RWG, void, ptr, ptr, i32) 330 | DEF_HELPER_FLAGS_3(gvec_shl64i, TCG_CALL_NO_RWG, void, ptr, ptr, i32) 331 | 332 | DEF_HELPER_FLAGS_3(gvec_shr8i, TCG_CALL_NO_RWG, void, ptr, ptr, i32) 333 | DEF_HELPER_FLAGS_3(gvec_shr16i, TCG_CALL_NO_RWG, void, ptr, ptr, i32) 334 | DEF_HELPER_FLAGS_3(gvec_shr32i, TCG_CALL_NO_RWG, void, ptr, ptr, i32) 335 | DEF_HELPER_FLAGS_3(gvec_shr64i, TCG_CALL_NO_RWG, void, ptr, ptr, i32) 336 | 337 | DEF_HELPER_FLAGS_3(gvec_sar8i, TCG_CALL_NO_RWG, void, ptr, ptr, i32) 338 | DEF_HELPER_FLAGS_3(gvec_sar16i, TCG_CALL_NO_RWG, void, ptr, ptr, i32) 339 | DEF_HELPER_FLAGS_3(gvec_sar32i, TCG_CALL_NO_RWG, void, ptr, ptr, i32) 340 | DEF_HELPER_FLAGS_3(gvec_sar64i, TCG_CALL_NO_RWG, void, ptr, ptr, i32) 341 | 342 | DEF_HELPER_FLAGS_4(gvec_eq8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 343 | DEF_HELPER_FLAGS_4(gvec_eq16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 344 | DEF_HELPER_FLAGS_4(gvec_eq32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 345 | DEF_HELPER_FLAGS_4(gvec_eq64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 346 | 347 | DEF_HELPER_FLAGS_4(gvec_ne8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 348 | DEF_HELPER_FLAGS_4(gvec_ne16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 349 | DEF_HELPER_FLAGS_4(gvec_ne32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 350 | DEF_HELPER_FLAGS_4(gvec_ne64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 351 | 352 | DEF_HELPER_FLAGS_4(gvec_lt8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 353 | DEF_HELPER_FLAGS_4(gvec_lt16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 354 | DEF_HELPER_FLAGS_4(gvec_lt32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 355 | DEF_HELPER_FLAGS_4(gvec_lt64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 356 | 357 | DEF_HELPER_FLAGS_4(gvec_le8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 358 | DEF_HELPER_FLAGS_4(gvec_le16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 359 | DEF_HELPER_FLAGS_4(gvec_le32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 360 | DEF_HELPER_FLAGS_4(gvec_le64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 361 | 362 | DEF_HELPER_FLAGS_4(gvec_ltu8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 363 | DEF_HELPER_FLAGS_4(gvec_ltu16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 364 | DEF_HELPER_FLAGS_4(gvec_ltu32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 365 | DEF_HELPER_FLAGS_4(gvec_ltu64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 366 | 367 | DEF_HELPER_FLAGS_4(gvec_leu8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 368 | DEF_HELPER_FLAGS_4(gvec_leu16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 369 | DEF_HELPER_FLAGS_4(gvec_leu32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 370 | DEF_HELPER_FLAGS_4(gvec_leu64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) 371 | -------------------------------------------------------------------------------- /include/tcg/i386/tcg-target.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Tiny Code Generator for QEMU 3 | * 4 | * Copyright (c) 2008 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef I386_TCG_TARGET_H 26 | #define I386_TCG_TARGET_H 27 | 28 | #define TCG_TARGET_INSN_UNIT_SIZE 1 29 | #define TCG_TARGET_TLB_DISPLACEMENT_BITS 31 30 | 31 | #ifdef __x86_64__ 32 | #define TCG_TARGET_REG_BITS 64 33 | #define TCG_TARGET_NB_REGS 32 34 | #else 35 | #define TCG_TARGET_REG_BITS 32 36 | #define TCG_TARGET_NB_REGS 24 37 | #endif 38 | 39 | typedef enum { 40 | TCG_REG_EAX = 0, 41 | TCG_REG_ECX, 42 | TCG_REG_EDX, 43 | TCG_REG_EBX, 44 | TCG_REG_ESP, 45 | TCG_REG_EBP, 46 | TCG_REG_ESI, 47 | TCG_REG_EDI, 48 | 49 | /* 64-bit registers; always define the symbols to avoid 50 | too much if-deffing. */ 51 | TCG_REG_R8, 52 | TCG_REG_R9, 53 | TCG_REG_R10, 54 | TCG_REG_R11, 55 | TCG_REG_R12, 56 | TCG_REG_R13, 57 | TCG_REG_R14, 58 | TCG_REG_R15, 59 | 60 | TCG_REG_XMM0, 61 | TCG_REG_XMM1, 62 | TCG_REG_XMM2, 63 | TCG_REG_XMM3, 64 | TCG_REG_XMM4, 65 | TCG_REG_XMM5, 66 | TCG_REG_XMM6, 67 | TCG_REG_XMM7, 68 | 69 | /* 64-bit registers; likewise always define. */ 70 | TCG_REG_XMM8, 71 | TCG_REG_XMM9, 72 | TCG_REG_XMM10, 73 | TCG_REG_XMM11, 74 | TCG_REG_XMM12, 75 | TCG_REG_XMM13, 76 | TCG_REG_XMM14, 77 | TCG_REG_XMM15, 78 | 79 | TCG_REG_RAX = TCG_REG_EAX, 80 | TCG_REG_RCX = TCG_REG_ECX, 81 | TCG_REG_RDX = TCG_REG_EDX, 82 | TCG_REG_RBX = TCG_REG_EBX, 83 | TCG_REG_RSP = TCG_REG_ESP, 84 | TCG_REG_RBP = TCG_REG_EBP, 85 | TCG_REG_RSI = TCG_REG_ESI, 86 | TCG_REG_RDI = TCG_REG_EDI, 87 | 88 | TCG_AREG0 = TCG_REG_EBP, 89 | TCG_REG_CALL_STACK = TCG_REG_ESP 90 | } TCGReg; 91 | 92 | /* used for function call generation */ 93 | #define TCG_TARGET_STACK_ALIGN 16 94 | #if defined(_WIN64) 95 | #define TCG_TARGET_CALL_STACK_OFFSET 32 96 | #else 97 | #define TCG_TARGET_CALL_STACK_OFFSET 0 98 | #endif 99 | 100 | extern bool have_bmi1; 101 | extern bool have_popcnt; 102 | extern bool have_avx1; 103 | extern bool have_avx2; 104 | 105 | /* optional instructions */ 106 | #define TCG_TARGET_HAS_div2_i32 1 107 | #define TCG_TARGET_HAS_rot_i32 1 108 | #define TCG_TARGET_HAS_ext8s_i32 1 109 | #define TCG_TARGET_HAS_ext16s_i32 1 110 | #define TCG_TARGET_HAS_ext8u_i32 1 111 | #define TCG_TARGET_HAS_ext16u_i32 1 112 | #define TCG_TARGET_HAS_bswap16_i32 1 113 | #define TCG_TARGET_HAS_bswap32_i32 1 114 | #define TCG_TARGET_HAS_neg_i32 1 115 | #define TCG_TARGET_HAS_not_i32 1 116 | #define TCG_TARGET_HAS_andc_i32 have_bmi1 117 | #define TCG_TARGET_HAS_orc_i32 0 118 | #define TCG_TARGET_HAS_eqv_i32 0 119 | #define TCG_TARGET_HAS_nand_i32 0 120 | #define TCG_TARGET_HAS_nor_i32 0 121 | #define TCG_TARGET_HAS_clz_i32 1 122 | #define TCG_TARGET_HAS_ctz_i32 1 123 | #define TCG_TARGET_HAS_ctpop_i32 have_popcnt 124 | #define TCG_TARGET_HAS_deposit_i32 1 125 | #define TCG_TARGET_HAS_extract_i32 1 126 | #define TCG_TARGET_HAS_sextract_i32 1 127 | #define TCG_TARGET_HAS_movcond_i32 1 128 | #define TCG_TARGET_HAS_add2_i32 1 129 | #define TCG_TARGET_HAS_sub2_i32 1 130 | #define TCG_TARGET_HAS_mulu2_i32 1 131 | #define TCG_TARGET_HAS_muls2_i32 1 132 | #define TCG_TARGET_HAS_muluh_i32 0 133 | #define TCG_TARGET_HAS_mulsh_i32 0 134 | #define TCG_TARGET_HAS_goto_ptr 1 135 | #define TCG_TARGET_HAS_direct_jump 1 136 | 137 | #if TCG_TARGET_REG_BITS == 64 138 | /* Keep target addresses zero-extended in a register. */ 139 | #define TCG_TARGET_HAS_extrl_i64_i32 (TARGET_LONG_BITS == 32) 140 | #define TCG_TARGET_HAS_extrh_i64_i32 (TARGET_LONG_BITS == 32) 141 | #define TCG_TARGET_HAS_div2_i64 1 142 | #define TCG_TARGET_HAS_rot_i64 1 143 | #define TCG_TARGET_HAS_ext8s_i64 1 144 | #define TCG_TARGET_HAS_ext16s_i64 1 145 | #define TCG_TARGET_HAS_ext32s_i64 1 146 | #define TCG_TARGET_HAS_ext8u_i64 1 147 | #define TCG_TARGET_HAS_ext16u_i64 1 148 | #define TCG_TARGET_HAS_ext32u_i64 1 149 | #define TCG_TARGET_HAS_bswap16_i64 1 150 | #define TCG_TARGET_HAS_bswap32_i64 1 151 | #define TCG_TARGET_HAS_bswap64_i64 1 152 | #define TCG_TARGET_HAS_neg_i64 1 153 | #define TCG_TARGET_HAS_not_i64 1 154 | #define TCG_TARGET_HAS_andc_i64 have_bmi1 155 | #define TCG_TARGET_HAS_orc_i64 0 156 | #define TCG_TARGET_HAS_eqv_i64 0 157 | #define TCG_TARGET_HAS_nand_i64 0 158 | #define TCG_TARGET_HAS_nor_i64 0 159 | #define TCG_TARGET_HAS_clz_i64 1 160 | #define TCG_TARGET_HAS_ctz_i64 1 161 | #define TCG_TARGET_HAS_ctpop_i64 have_popcnt 162 | #define TCG_TARGET_HAS_deposit_i64 1 163 | #define TCG_TARGET_HAS_extract_i64 1 164 | #define TCG_TARGET_HAS_sextract_i64 0 165 | #define TCG_TARGET_HAS_movcond_i64 1 166 | #define TCG_TARGET_HAS_add2_i64 1 167 | #define TCG_TARGET_HAS_sub2_i64 1 168 | #define TCG_TARGET_HAS_mulu2_i64 1 169 | #define TCG_TARGET_HAS_muls2_i64 1 170 | #define TCG_TARGET_HAS_muluh_i64 0 171 | #define TCG_TARGET_HAS_mulsh_i64 0 172 | #endif 173 | 174 | /* We do not support older SSE systems, only beginning with AVX1. */ 175 | #define TCG_TARGET_HAS_v64 have_avx1 176 | #define TCG_TARGET_HAS_v128 have_avx1 177 | #define TCG_TARGET_HAS_v256 have_avx2 178 | 179 | #define TCG_TARGET_HAS_andc_vec 1 180 | #define TCG_TARGET_HAS_orc_vec 0 181 | #define TCG_TARGET_HAS_not_vec 0 182 | #define TCG_TARGET_HAS_neg_vec 0 183 | #define TCG_TARGET_HAS_shi_vec 1 184 | #define TCG_TARGET_HAS_shs_vec 0 185 | #define TCG_TARGET_HAS_shv_vec 0 186 | #define TCG_TARGET_HAS_cmp_vec 1 187 | #define TCG_TARGET_HAS_mul_vec 1 188 | #define TCG_TARGET_HAS_sat_vec 1 189 | #define TCG_TARGET_HAS_minmax_vec 1 190 | 191 | #define TCG_TARGET_deposit_i32_valid(ofs, len) \ 192 | (((ofs) == 0 && (len) == 8) || ((ofs) == 8 && (len) == 8) || ((ofs) == 0 && (len) == 16)) 193 | #define TCG_TARGET_deposit_i64_valid TCG_TARGET_deposit_i32_valid 194 | 195 | /* Check for the possibility of high-byte extraction and, for 64-bit, 196 | zero-extending 32-bit right-shift. */ 197 | #define TCG_TARGET_extract_i32_valid(ofs, len) ((ofs) == 8 && (len) == 8) 198 | #define TCG_TARGET_extract_i64_valid(ofs, len) (((ofs) == 8 && (len) == 8) || ((ofs) + (len)) == 32) 199 | 200 | static inline void flush_icache_range(uintptr_t start, uintptr_t stop) { 201 | } 202 | 203 | static inline void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_addr, uintptr_t addr) { 204 | /* patch the branch destination */ 205 | atomic_set((int32_t *) jmp_addr, addr - (jmp_addr + 4)); 206 | /* no need to flush icache explicitly */ 207 | } 208 | 209 | /* This defines the natural memory order supported by this 210 | * architecture before guarantees made by various barrier 211 | * instructions. 212 | * 213 | * The x86 has a pretty strong memory ordering which only really 214 | * allows for some stores to be re-ordered after loads. 215 | */ 216 | #include "../tcg-mo.h" 217 | 218 | #define TCG_TARGET_DEFAULT_MO (TCG_MO_ALL & ~TCG_MO_ST_LD) 219 | 220 | #define TCG_TARGET_HAS_MEMORY_BSWAP 1 221 | 222 | #ifdef CONFIG_SOFTMMU 223 | #define TCG_TARGET_NEED_LDST_LABELS 224 | #endif 225 | #define TCG_TARGET_NEED_POOL_LABELS 226 | 227 | #endif 228 | -------------------------------------------------------------------------------- /include/tcg/i386/tcg-target.opc.h: -------------------------------------------------------------------------------- 1 | /* Target-specific opcodes for host vector expansion. These will be 2 | emitted by tcg_expand_vec_op. For those familiar with GCC internals, 3 | consider these to be UNSPEC with names. */ 4 | 5 | DEF(x86_shufps_vec, 1, 2, 1, IMPLVEC) 6 | DEF(x86_vpblendvb_vec, 1, 3, 0, IMPLVEC) 7 | DEF(x86_blend_vec, 1, 2, 1, IMPLVEC) 8 | DEF(x86_packss_vec, 1, 2, 0, IMPLVEC) 9 | DEF(x86_packus_vec, 1, 2, 0, IMPLVEC) 10 | DEF(x86_psrldq_vec, 1, 1, 1, IMPLVEC) 11 | DEF(x86_vperm2i128_vec, 1, 2, 1, IMPLVEC) 12 | DEF(x86_punpckl_vec, 1, 2, 0, IMPLVEC) 13 | DEF(x86_punpckh_vec, 1, 2, 0, IMPLVEC) 14 | -------------------------------------------------------------------------------- /include/tcg/ops_sse_header.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4/PNI support 3 | * 4 | * Copyright (c) 2005 Fabrice Bellard 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | #include 21 | 22 | #if SHIFT == 0 23 | #define Reg MMXReg 24 | #define SUFFIX _mmx 25 | #else 26 | #define Reg XMMReg 27 | #define SUFFIX _xmm 28 | #endif 29 | 30 | #define dh_alias_Reg ptr 31 | #define dh_alias_XMMReg ptr 32 | #define dh_alias_MMXReg ptr 33 | #define dh_ctype_Reg Reg * 34 | #define dh_ctype_XMMReg XMMReg * 35 | #define dh_ctype_MMXReg MMXReg * 36 | #define dh_is_signed_Reg dh_is_signed_ptr 37 | #define dh_is_signed_XMMReg dh_is_signed_ptr 38 | #define dh_is_signed_MMXReg dh_is_signed_ptr 39 | 40 | DEF_HELPER_2(glue(psrlw, SUFFIX), void, Reg, Reg) 41 | DEF_HELPER_2(glue(psraw, SUFFIX), void, Reg, Reg) 42 | DEF_HELPER_2(glue(psllw, SUFFIX), void, Reg, Reg) 43 | DEF_HELPER_2(glue(psrld, SUFFIX), void, Reg, Reg) 44 | DEF_HELPER_2(glue(psrad, SUFFIX), void, Reg, Reg) 45 | DEF_HELPER_2(glue(pslld, SUFFIX), void, Reg, Reg) 46 | DEF_HELPER_2(glue(psrlq, SUFFIX), void, Reg, Reg) 47 | DEF_HELPER_2(glue(psllq, SUFFIX), void, Reg, Reg) 48 | 49 | #if SHIFT == 1 50 | DEF_HELPER_2(glue(psrldq, SUFFIX), void, Reg, Reg) 51 | DEF_HELPER_2(glue(pslldq, SUFFIX), void, Reg, Reg) 52 | #endif 53 | 54 | #define SSE_HELPER_B(name, F) DEF_HELPER_2(glue(name, SUFFIX), void, Reg, Reg) 55 | 56 | #define SSE_HELPER_W(name, F) DEF_HELPER_2(glue(name, SUFFIX), void, Reg, Reg) 57 | 58 | #define SSE_HELPER_L(name, F) DEF_HELPER_2(glue(name, SUFFIX), void, Reg, Reg) 59 | 60 | #define SSE_HELPER_Q(name, F) DEF_HELPER_2(glue(name, SUFFIX), void, Reg, Reg) 61 | 62 | SSE_HELPER_B(paddb, FADD) 63 | SSE_HELPER_W(paddw, FADD) 64 | SSE_HELPER_L(paddl, FADD) 65 | SSE_HELPER_Q(paddq, FADD) 66 | 67 | SSE_HELPER_B(psubb, FSUB) 68 | SSE_HELPER_W(psubw, FSUB) 69 | SSE_HELPER_L(psubl, FSUB) 70 | SSE_HELPER_Q(psubq, FSUB) 71 | 72 | SSE_HELPER_B(paddusb, FADDUB) 73 | SSE_HELPER_B(paddsb, FADDSB) 74 | SSE_HELPER_B(psubusb, FSUBUB) 75 | SSE_HELPER_B(psubsb, FSUBSB) 76 | 77 | SSE_HELPER_W(paddusw, FADDUW) 78 | SSE_HELPER_W(paddsw, FADDSW) 79 | SSE_HELPER_W(psubusw, FSUBUW) 80 | SSE_HELPER_W(psubsw, FSUBSW) 81 | 82 | SSE_HELPER_B(pminub, FMINUB) 83 | SSE_HELPER_B(pmaxub, FMAXUB) 84 | 85 | SSE_HELPER_W(pminsw, FMINSW) 86 | SSE_HELPER_W(pmaxsw, FMAXSW) 87 | 88 | SSE_HELPER_Q(pand, FAND) 89 | SSE_HELPER_Q(pandn, FANDN) 90 | SSE_HELPER_Q(por, FOR) 91 | SSE_HELPER_Q(pxor, FXOR) 92 | 93 | SSE_HELPER_B(pcmpgtb, FCMPGTB) 94 | SSE_HELPER_W(pcmpgtw, FCMPGTW) 95 | SSE_HELPER_L(pcmpgtl, FCMPGTL) 96 | 97 | SSE_HELPER_B(pcmpeqb, FCMPEQ) 98 | SSE_HELPER_W(pcmpeqw, FCMPEQ) 99 | SSE_HELPER_L(pcmpeql, FCMPEQ) 100 | 101 | SSE_HELPER_W(pmullw, FMULLW) 102 | #if SHIFT == 0 103 | SSE_HELPER_W(pmulhrw, FMULHRW) 104 | #endif 105 | SSE_HELPER_W(pmulhuw, FMULHUW) 106 | SSE_HELPER_W(pmulhw, FMULHW) 107 | 108 | SSE_HELPER_B(pavgb, FAVG) 109 | SSE_HELPER_W(pavgw, FAVG) 110 | 111 | DEF_HELPER_2(glue(pmuludq, SUFFIX), void, Reg, Reg) 112 | DEF_HELPER_2(glue(pmaddwd, SUFFIX), void, Reg, Reg) 113 | 114 | DEF_HELPER_2(glue(psadbw, SUFFIX), void, Reg, Reg) 115 | DEF_HELPER_3(glue(maskmov, SUFFIX), void, Reg, Reg, tl) 116 | DEF_HELPER_2(glue(movl_mm_T0, SUFFIX), void, Reg, i32) 117 | #ifdef TARGET_X86_64 118 | DEF_HELPER_2(glue(movq_mm_T0, SUFFIX), void, Reg, i64) 119 | #endif 120 | 121 | #if SHIFT == 0 122 | DEF_HELPER_3(glue(pshufw, SUFFIX), void, Reg, Reg, int) 123 | #else 124 | DEF_HELPER_3(shufps, void, Reg, Reg, int) 125 | DEF_HELPER_3(shufpd, void, Reg, Reg, int) 126 | DEF_HELPER_3(glue(pshufd, SUFFIX), void, Reg, Reg, int) 127 | DEF_HELPER_3(glue(pshuflw, SUFFIX), void, Reg, Reg, int) 128 | DEF_HELPER_3(glue(pshufhw, SUFFIX), void, Reg, Reg, int) 129 | #endif 130 | 131 | #if SHIFT == 1 132 | /* FPU ops */ 133 | /* XXX: not accurate */ 134 | 135 | #define SSE_HELPER_S(name, F) \ 136 | DEF_HELPER_2(name##ps, void, Reg, Reg) \ 137 | DEF_HELPER_2(name##ss, void, Reg, Reg) \ 138 | DEF_HELPER_2(name##pd, void, Reg, Reg) \ 139 | DEF_HELPER_2(name##sd, void, Reg, Reg) 140 | 141 | SSE_HELPER_S(add, FPU_ADD) 142 | SSE_HELPER_S(sub, FPU_SUB) 143 | SSE_HELPER_S(mul, FPU_MUL) 144 | SSE_HELPER_S(div, FPU_DIV) 145 | SSE_HELPER_S(min, FPU_MIN) 146 | SSE_HELPER_S(max, FPU_MAX) 147 | SSE_HELPER_S(sqrt, FPU_SQRT) 148 | 149 | DEF_HELPER_2(cvtps2pd, void, Reg, Reg) 150 | DEF_HELPER_2(cvtpd2ps, void, Reg, Reg) 151 | DEF_HELPER_2(cvtss2sd, void, Reg, Reg) 152 | DEF_HELPER_2(cvtsd2ss, void, Reg, Reg) 153 | DEF_HELPER_2(cvtdq2ps, void, Reg, Reg) 154 | DEF_HELPER_2(cvtdq2pd, void, Reg, Reg) 155 | DEF_HELPER_2(cvtpi2ps, void, XMMReg, MMXReg) 156 | DEF_HELPER_2(cvtpi2pd, void, XMMReg, MMXReg) 157 | DEF_HELPER_2(cvtsi2ss, void, XMMReg, i32) 158 | DEF_HELPER_2(cvtsi2sd, void, XMMReg, i32) 159 | 160 | #ifdef TARGET_X86_64 161 | DEF_HELPER_2(cvtsq2ss, void, XMMReg, i64) 162 | DEF_HELPER_2(cvtsq2sd, void, XMMReg, i64) 163 | #endif 164 | 165 | DEF_HELPER_2(cvtps2dq, void, XMMReg, XMMReg) 166 | DEF_HELPER_2(cvtpd2dq, void, XMMReg, XMMReg) 167 | DEF_HELPER_2(cvtps2pi, void, MMXReg, XMMReg) 168 | DEF_HELPER_2(cvtpd2pi, void, MMXReg, XMMReg) 169 | DEF_HELPER_1(cvtss2si, s32, XMMReg) 170 | DEF_HELPER_1(cvtsd2si, s32, XMMReg) 171 | #ifdef TARGET_X86_64 172 | DEF_HELPER_1(cvtss2sq, s64, XMMReg) 173 | DEF_HELPER_1(cvtsd2sq, s64, XMMReg) 174 | #endif 175 | 176 | DEF_HELPER_2(cvttps2dq, void, XMMReg, XMMReg) 177 | DEF_HELPER_2(cvttpd2dq, void, XMMReg, XMMReg) 178 | DEF_HELPER_2(cvttps2pi, void, MMXReg, XMMReg) 179 | DEF_HELPER_2(cvttpd2pi, void, MMXReg, XMMReg) 180 | DEF_HELPER_1(cvttss2si, s32, XMMReg) 181 | DEF_HELPER_1(cvttsd2si, s32, XMMReg) 182 | #ifdef TARGET_X86_64 183 | DEF_HELPER_1(cvttss2sq, s64, XMMReg) 184 | DEF_HELPER_1(cvttsd2sq, s64, XMMReg) 185 | #endif 186 | 187 | DEF_HELPER_2(rsqrtps, void, XMMReg, XMMReg) 188 | DEF_HELPER_2(rsqrtss, void, XMMReg, XMMReg) 189 | DEF_HELPER_2(rcpps, void, XMMReg, XMMReg) 190 | DEF_HELPER_2(rcpss, void, XMMReg, XMMReg) 191 | DEF_HELPER_2(extrq_r, void, XMMReg, XMMReg) 192 | DEF_HELPER_3(extrq_i, void, XMMReg, int, int) 193 | DEF_HELPER_2(insertq_r, void, XMMReg, XMMReg) 194 | DEF_HELPER_3(insertq_i, void, XMMReg, int, int) 195 | DEF_HELPER_2(haddps, void, XMMReg, XMMReg) 196 | DEF_HELPER_2(haddpd, void, XMMReg, XMMReg) 197 | DEF_HELPER_2(hsubps, void, XMMReg, XMMReg) 198 | DEF_HELPER_2(hsubpd, void, XMMReg, XMMReg) 199 | DEF_HELPER_2(addsubps, void, XMMReg, XMMReg) 200 | DEF_HELPER_2(addsubpd, void, XMMReg, XMMReg) 201 | 202 | #define SSE_HELPER_CMP(name, F) \ 203 | DEF_HELPER_2(name##ps, void, Reg, Reg) \ 204 | DEF_HELPER_2(name##ss, void, Reg, Reg) \ 205 | DEF_HELPER_2(name##pd, void, Reg, Reg) \ 206 | DEF_HELPER_2(name##sd, void, Reg, Reg) 207 | 208 | SSE_HELPER_CMP(cmpeq, FPU_CMPEQ) 209 | SSE_HELPER_CMP(cmplt, FPU_CMPLT) 210 | SSE_HELPER_CMP(cmple, FPU_CMPLE) 211 | SSE_HELPER_CMP(cmpunord, FPU_CMPUNORD) 212 | SSE_HELPER_CMP(cmpneq, FPU_CMPNEQ) 213 | SSE_HELPER_CMP(cmpnlt, FPU_CMPNLT) 214 | SSE_HELPER_CMP(cmpnle, FPU_CMPNLE) 215 | SSE_HELPER_CMP(cmpord, FPU_CMPORD) 216 | 217 | DEF_HELPER_2(ucomiss, void, Reg, Reg) 218 | DEF_HELPER_2(comiss, void, Reg, Reg) 219 | DEF_HELPER_2(ucomisd, void, Reg, Reg) 220 | DEF_HELPER_2(comisd, void, Reg, Reg) 221 | DEF_HELPER_1(movmskps, i32, Reg) 222 | DEF_HELPER_1(movmskpd, i32, Reg) 223 | #endif 224 | 225 | DEF_HELPER_1(glue(pmovmskb, SUFFIX), i32, Reg) 226 | DEF_HELPER_2(glue(packsswb, SUFFIX), void, Reg, Reg) 227 | DEF_HELPER_2(glue(packuswb, SUFFIX), void, Reg, Reg) 228 | DEF_HELPER_2(glue(packssdw, SUFFIX), void, Reg, Reg) 229 | #define UNPCK_OP(base_name, base) \ 230 | DEF_HELPER_2(glue(punpck##base_name##bw, SUFFIX), void, Reg, Reg) \ 231 | DEF_HELPER_2(glue(punpck##base_name##wd, SUFFIX), void, Reg, Reg) \ 232 | DEF_HELPER_2(glue(punpck##base_name##dq, SUFFIX), void, Reg, Reg) 233 | 234 | UNPCK_OP(l, 0) 235 | UNPCK_OP(h, 1) 236 | 237 | #if SHIFT == 1 238 | DEF_HELPER_2(glue(punpcklqdq, SUFFIX), void, Reg, Reg) 239 | DEF_HELPER_2(glue(punpckhqdq, SUFFIX), void, Reg, Reg) 240 | #endif 241 | 242 | /* 3DNow! float ops */ 243 | #if SHIFT == 0 244 | DEF_HELPER_2(pi2fd, void, MMXReg, MMXReg) 245 | DEF_HELPER_2(pi2fw, void, MMXReg, MMXReg) 246 | DEF_HELPER_2(pf2id, void, MMXReg, MMXReg) 247 | DEF_HELPER_2(pf2iw, void, MMXReg, MMXReg) 248 | DEF_HELPER_2(pfacc, void, MMXReg, MMXReg) 249 | DEF_HELPER_2(pfadd, void, MMXReg, MMXReg) 250 | DEF_HELPER_2(pfcmpeq, void, MMXReg, MMXReg) 251 | DEF_HELPER_2(pfcmpge, void, MMXReg, MMXReg) 252 | DEF_HELPER_2(pfcmpgt, void, MMXReg, MMXReg) 253 | DEF_HELPER_2(pfmax, void, MMXReg, MMXReg) 254 | DEF_HELPER_2(pfmin, void, MMXReg, MMXReg) 255 | DEF_HELPER_2(pfmul, void, MMXReg, MMXReg) 256 | DEF_HELPER_2(pfnacc, void, MMXReg, MMXReg) 257 | DEF_HELPER_2(pfpnacc, void, MMXReg, MMXReg) 258 | DEF_HELPER_2(pfrcp, void, MMXReg, MMXReg) 259 | DEF_HELPER_2(pfrsqrt, void, MMXReg, MMXReg) 260 | DEF_HELPER_2(pfsub, void, MMXReg, MMXReg) 261 | DEF_HELPER_2(pfsubr, void, MMXReg, MMXReg) 262 | DEF_HELPER_2(pswapd, void, MMXReg, MMXReg) 263 | #endif 264 | 265 | /* SSSE3 op helpers */ 266 | DEF_HELPER_2(glue(phaddw, SUFFIX), void, Reg, Reg) 267 | DEF_HELPER_2(glue(phaddd, SUFFIX), void, Reg, Reg) 268 | DEF_HELPER_2(glue(phaddsw, SUFFIX), void, Reg, Reg) 269 | DEF_HELPER_2(glue(phsubw, SUFFIX), void, Reg, Reg) 270 | DEF_HELPER_2(glue(phsubd, SUFFIX), void, Reg, Reg) 271 | DEF_HELPER_2(glue(phsubsw, SUFFIX), void, Reg, Reg) 272 | DEF_HELPER_2(glue(pabsb, SUFFIX), void, Reg, Reg) 273 | DEF_HELPER_2(glue(pabsw, SUFFIX), void, Reg, Reg) 274 | DEF_HELPER_2(glue(pabsd, SUFFIX), void, Reg, Reg) 275 | DEF_HELPER_2(glue(pmaddubsw, SUFFIX), void, Reg, Reg) 276 | DEF_HELPER_2(glue(pmulhrsw, SUFFIX), void, Reg, Reg) 277 | DEF_HELPER_2(glue(pshufb, SUFFIX), void, Reg, Reg) 278 | DEF_HELPER_2(glue(psignb, SUFFIX), void, Reg, Reg) 279 | DEF_HELPER_2(glue(psignw, SUFFIX), void, Reg, Reg) 280 | DEF_HELPER_2(glue(psignd, SUFFIX), void, Reg, Reg) 281 | DEF_HELPER_3(glue(palignr, SUFFIX), void, Reg, Reg, s32) 282 | 283 | /* SSE4.1 op helpers */ 284 | #if SHIFT == 1 285 | DEF_HELPER_2(glue(pblendvb, SUFFIX), void, Reg, Reg) 286 | DEF_HELPER_2(glue(blendvps, SUFFIX), void, Reg, Reg) 287 | DEF_HELPER_2(glue(blendvpd, SUFFIX), void, Reg, Reg) 288 | DEF_HELPER_2(glue(ptest, SUFFIX), void, Reg, Reg) 289 | DEF_HELPER_2(glue(pmovsxbw, SUFFIX), void, Reg, Reg) 290 | DEF_HELPER_2(glue(pmovsxbd, SUFFIX), void, Reg, Reg) 291 | DEF_HELPER_2(glue(pmovsxbq, SUFFIX), void, Reg, Reg) 292 | DEF_HELPER_2(glue(pmovsxwd, SUFFIX), void, Reg, Reg) 293 | DEF_HELPER_2(glue(pmovsxwq, SUFFIX), void, Reg, Reg) 294 | DEF_HELPER_2(glue(pmovsxdq, SUFFIX), void, Reg, Reg) 295 | DEF_HELPER_2(glue(pmovzxbw, SUFFIX), void, Reg, Reg) 296 | DEF_HELPER_2(glue(pmovzxbd, SUFFIX), void, Reg, Reg) 297 | DEF_HELPER_2(glue(pmovzxbq, SUFFIX), void, Reg, Reg) 298 | DEF_HELPER_2(glue(pmovzxwd, SUFFIX), void, Reg, Reg) 299 | DEF_HELPER_2(glue(pmovzxwq, SUFFIX), void, Reg, Reg) 300 | DEF_HELPER_2(glue(pmovzxdq, SUFFIX), void, Reg, Reg) 301 | DEF_HELPER_2(glue(pmuldq, SUFFIX), void, Reg, Reg) 302 | DEF_HELPER_2(glue(pcmpeqq, SUFFIX), void, Reg, Reg) 303 | DEF_HELPER_2(glue(packusdw, SUFFIX), void, Reg, Reg) 304 | DEF_HELPER_2(glue(pminsb, SUFFIX), void, Reg, Reg) 305 | DEF_HELPER_2(glue(pminsd, SUFFIX), void, Reg, Reg) 306 | DEF_HELPER_2(glue(pminuw, SUFFIX), void, Reg, Reg) 307 | DEF_HELPER_2(glue(pminud, SUFFIX), void, Reg, Reg) 308 | DEF_HELPER_2(glue(pmaxsb, SUFFIX), void, Reg, Reg) 309 | DEF_HELPER_2(glue(pmaxsd, SUFFIX), void, Reg, Reg) 310 | DEF_HELPER_2(glue(pmaxuw, SUFFIX), void, Reg, Reg) 311 | DEF_HELPER_2(glue(pmaxud, SUFFIX), void, Reg, Reg) 312 | DEF_HELPER_2(glue(pmulld, SUFFIX), void, Reg, Reg) 313 | DEF_HELPER_2(glue(phminposuw, SUFFIX), void, Reg, Reg) 314 | DEF_HELPER_3(glue(roundps, SUFFIX), void, Reg, Reg, i32) 315 | DEF_HELPER_3(glue(roundpd, SUFFIX), void, Reg, Reg, i32) 316 | DEF_HELPER_3(glue(roundss, SUFFIX), void, Reg, Reg, i32) 317 | DEF_HELPER_3(glue(roundsd, SUFFIX), void, Reg, Reg, i32) 318 | DEF_HELPER_3(glue(blendps, SUFFIX), void, Reg, Reg, i32) 319 | DEF_HELPER_3(glue(blendpd, SUFFIX), void, Reg, Reg, i32) 320 | DEF_HELPER_3(glue(pblendw, SUFFIX), void, Reg, Reg, i32) 321 | DEF_HELPER_3(glue(dpps, SUFFIX), void, Reg, Reg, i32) 322 | DEF_HELPER_3(glue(dppd, SUFFIX), void, Reg, Reg, i32) 323 | DEF_HELPER_3(glue(mpsadbw, SUFFIX), void, Reg, Reg, i32) 324 | #endif 325 | 326 | /* SSE4.2 op helpers */ 327 | #if SHIFT == 1 328 | DEF_HELPER_2(glue(pcmpgtq, SUFFIX), void, Reg, Reg) 329 | DEF_HELPER_3(glue(pcmpestri, SUFFIX), void, Reg, Reg, i32) 330 | DEF_HELPER_3(glue(pcmpestrm, SUFFIX), void, Reg, Reg, i32) 331 | DEF_HELPER_3(glue(pcmpistri, SUFFIX), void, Reg, Reg, i32) 332 | DEF_HELPER_3(glue(pcmpistrm, SUFFIX), void, Reg, Reg, i32) 333 | DEF_HELPER_3(crc32, tl, i32, tl, i32) 334 | DEF_HELPER_2(popcnt, tl, tl, i32) 335 | #endif 336 | 337 | #undef SHIFT 338 | #undef Reg 339 | #undef SUFFIX 340 | 341 | #undef SSE_HELPER_B 342 | #undef SSE_HELPER_W 343 | #undef SSE_HELPER_L 344 | #undef SSE_HELPER_Q 345 | #undef SSE_HELPER_S 346 | #undef SSE_HELPER_CMP 347 | #undef UNPCK_OP 348 | -------------------------------------------------------------------------------- /include/tcg/regs.h: -------------------------------------------------------------------------------- 1 | #ifndef _TCG_REGS_H_ 2 | 3 | #define _TCG_REGS_H_ 4 | 5 | #include 6 | 7 | // XXX: this is in softfloat. 8 | typedef uint32_t float32; 9 | typedef uint64_t float64; 10 | 11 | typedef union { 12 | uint8_t _b[8]; 13 | uint16_t _w[4]; 14 | uint32_t _l[2]; 15 | float32 _s[2]; 16 | uint64_t q; 17 | } MMXReg; 18 | 19 | typedef union { 20 | uint8_t _b[16]; 21 | uint16_t _w[8]; 22 | uint32_t _l[4]; 23 | uint64_t _q[2]; 24 | float32 _s[4]; 25 | float64 _d[2]; 26 | } XMMReg; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /include/tcg/tb.h: -------------------------------------------------------------------------------- 1 | /// Copyright (C) 2003 Fabrice Bellard 2 | /// Copyright (C) 2010 Dependable Systems Laboratory, EPFL 3 | /// Copyright (C) 2016-2019 Cyberhaven 4 | /// Copyrights of all contributions belong to their respective owners. 5 | /// 6 | /// This library is free software; you can redistribute it and/or 7 | /// modify it under the terms of the GNU Library General Public 8 | /// License as published by the Free Software Foundation; either 9 | /// version 2 of the License, or (at your option) any later version. 10 | /// 11 | /// This library is distributed in the hope that it will be useful, 12 | /// but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | /// Library General Public License for more details. 15 | /// 16 | /// You should have received a copy of the GNU Library General Public 17 | /// License along with this library; if not, see . 18 | 19 | #ifndef _TCG_TB_H_ 20 | 21 | #define _TCG_TB_H_ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | enum ETranslationBlockType { 32 | TB_DEFAULT = 0, 33 | TB_JMP, 34 | TB_JMP_IND, 35 | TB_COND_JMP, 36 | TB_COND_JMP_IND, 37 | TB_CALL, 38 | TB_CALL_IND, 39 | TB_REP, 40 | TB_RET, 41 | TB_IRET, 42 | TB_EXCP, 43 | TB_SYSENTER, 44 | TB_INTERRUPT 45 | }; 46 | 47 | #ifdef CONFIG_SYMBEX 48 | enum JumpType { JT_RET, JT_LRET }; 49 | #endif 50 | 51 | // XXX 52 | typedef uintptr_t tb_page_addr_t; 53 | 54 | #if defined(_ARCH_PPC) || defined(__x86_64__) || defined(__arm__) || defined(__i386__) 55 | #define USE_DIRECT_JUMP 56 | #elif defined(CONFIG_TCG_INTERPRETER) 57 | #define USE_DIRECT_JUMP 58 | #endif 59 | 60 | // XXX 61 | typedef int spinlock_t; 62 | 63 | struct TranslationBlock { 64 | target_ulong pc; /* simulated PC corresponding to this block (EIP + CS base) */ 65 | target_ulong cs_base; /* CS base for this block */ 66 | uint64_t flags; /* flags defining in which context the code was generated */ 67 | uint16_t size; /* size of target code for this block (1 <= 68 | size <= TARGET_PAGE_SIZE) */ 69 | 70 | #define CF_COUNT_MASK 0x00007fff 71 | #define CF_NOCACHE 0x00010000 /* To be freed after execution */ 72 | #define CF_HAS_INTERRUPT_EXIT 0x00020000 /* The TB has a prologue to handle quick CPU loop exit */ 73 | #define CF_INVALID 0x00040000 /* TB is stale. Set with @jmp_lock held */ 74 | #define CF_PARALLEL 0x00080000 /* Generate code for a parallel context */ 75 | 76 | uint32_t cflags; /* compile flags */ 77 | 78 | // uint8_t *tc_ptr; /* pointer to the translated code */ 79 | // unsigned tc_size; /* size of the translated code */ 80 | struct tb_tc tc; 81 | 82 | /* next matching tb for physical address. */ 83 | struct TranslationBlock *phys_hash_next; 84 | /* first and second physical page containing code. The lower bit 85 | of the pointer tells the index in page_next[] */ 86 | struct TranslationBlock *page_next[2]; 87 | tb_page_addr_t page_addr[2]; 88 | 89 | /* jmp_lock placed here to fill a 4-byte hole. Its documentation is below */ 90 | spinlock_t jmp_lock; 91 | 92 | /* The following data are used to directly call another TB from 93 | * the code of this one. This can be done either by emitting direct or 94 | * indirect native jump instructions. These jumps are reset so that the TB 95 | * just continues its execution. The TB can be linked to another one by 96 | * setting one of the jump targets (or patching the jump instruction). Only 97 | * two of such jumps are supported. 98 | */ 99 | uint16_t jmp_reset_offset[2]; /* offset of original jump target */ 100 | #define TB_JMP_RESET_OFFSET_INVALID 0xffff /* indicates no jump generated */ 101 | uintptr_t jmp_target_arg[2]; /* target address or offset */ 102 | 103 | /* 104 | * Each TB has a NULL-terminated list (jmp_list_head) of incoming jumps. 105 | * Each TB can have two outgoing jumps, and therefore can participate 106 | * in two lists. The list entries are kept in jmp_list_next[2]. The least 107 | * significant bit (LSB) of the pointers in these lists is used to encode 108 | * which of the two list entries is to be used in the pointed TB. 109 | * 110 | * List traversals are protected by jmp_lock. The destination TB of each 111 | * outgoing jump is kept in jmp_dest[] so that the appropriate jmp_lock 112 | * can be acquired from any origin TB. 113 | * 114 | * jmp_dest[] are tagged pointers as well. The LSB is set when the TB is 115 | * being invalidated, so that no further outgoing jumps from it can be set. 116 | * 117 | * jmp_lock also protects the CF_INVALID cflag; a jump must not be chained 118 | * to a destination TB that has CF_INVALID set. 119 | */ 120 | uintptr_t jmp_list_head; 121 | uintptr_t jmp_list_next[2]; 122 | uintptr_t jmp_dest[2]; 123 | 124 | uint32_t icount; 125 | 126 | #ifdef CONFIG_SYMBEX 127 | /* pointer to LLVM translated code */ 128 | void *llvm_function; 129 | #endif 130 | 131 | #ifdef CONFIG_SYMBEX 132 | enum ETranslationBlockType se_tb_type; 133 | uint64_t se_tb_call_eip; 134 | void *se_tb; 135 | uint64_t pcOfLastInstr; /* XXX: hack for call instructions */ 136 | 137 | /* Indicates whether there are execution handlers attached */ 138 | int instrumented; 139 | 140 | #ifdef STATIC_TRANSLATOR 141 | /* pc after which to stop the translation */ 142 | target_ulong last_pc; 143 | #endif 144 | #endif 145 | }; 146 | 147 | typedef struct TranslationBlock TranslationBlock; 148 | 149 | /* Hide the atomic_read to make code a little easier on the eyes */ 150 | static inline uint32_t tb_cflags(const TranslationBlock *tb) { 151 | return atomic_read(&tb->cflags); 152 | } 153 | 154 | #ifdef __cplusplus 155 | } 156 | #endif 157 | 158 | #endif 159 | -------------------------------------------------------------------------------- /include/tcg/tcg-llvm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Tiny Code Generator for QEMU 3 | * 4 | * Copyright (c) 2017, Cyberhaven 5 | * Copyright (c) 2010, Dependable Systems Laboratory, EPFL 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #ifndef TCG_LLVM_H 27 | #define TCG_LLVM_H 28 | 29 | #include 30 | #include 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif 35 | 36 | // Functions for QEMU C code 37 | extern void *tcg_llvm_translator; 38 | 39 | void tcg_llvm_close(void *l); 40 | void *tcg_llvm_gen_code(void *llvmTranslator, struct TCGContext *s, struct TranslationBlock *tb); 41 | 42 | #ifdef __cplusplus 43 | } 44 | #endif 45 | 46 | #ifdef __cplusplus 47 | 48 | #include 49 | 50 | // External interface for C++ code 51 | 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | 67 | #ifdef STATIC_TRANSLATOR 68 | #include 69 | 70 | struct TCGLLVMTBInfo { 71 | /* Return instructions */ 72 | llvm::SmallVector returnInstructions; 73 | 74 | /* Instructions that assign a value to the program counter */ 75 | llvm::SmallVector pcAssignments; 76 | 77 | llvm::SmallVector staticBranchTargets; 78 | 79 | void clear() { 80 | returnInstructions.clear(); 81 | pcAssignments.clear(); 82 | staticBranchTargets.clear(); 83 | } 84 | }; 85 | #endif 86 | 87 | class TCGLLVMTranslator { 88 | private: 89 | const std::string m_bitcodeLibraryPath; 90 | std::unique_ptr m_module; 91 | 92 | llvm::IRBuilder<> m_builder; 93 | 94 | /* Function pass manager (used for optimizing the code) */ 95 | llvm::legacy::FunctionPassManager *m_functionPassManager; 96 | 97 | #ifdef CONFIG_SYMBEX 98 | /* Declaration of a wrapper function for helpers */ 99 | llvm::Function *m_helperForkAndConcretize; 100 | llvm::Function *m_qemu_ld_helpers[5]; 101 | llvm::Function *m_qemu_st_helpers[5]; 102 | #endif 103 | 104 | #ifdef STATIC_TRANSLATOR 105 | TCGLLVMTBInfo m_info; 106 | #endif 107 | 108 | /* Count of generated translation blocks */ 109 | int m_tbCount; 110 | 111 | /* XXX: The following members are "local" to generateCode method */ 112 | 113 | /* TCGContext for current translation block */ 114 | TCGContext *m_tcgContext; 115 | 116 | TranslationBlock *m_tb; 117 | 118 | /* Function for current translation block */ 119 | llvm::Function *m_tbFunction; 120 | 121 | /* Current temp m_values */ 122 | llvm::Value *m_values[TCG_MAX_TEMPS]; 123 | 124 | /* Pointers to in-memory versions of globals or local temps */ 125 | llvm::Value *m_memValuesPtr[TCG_MAX_TEMPS]; 126 | 127 | /* For reg-based globals, store argument number, 128 | * for mem-based globals, store base value index */ 129 | int m_globalsIdx[TCG_MAX_TEMPS]; 130 | 131 | std::unordered_map m_labels; 132 | 133 | llvm::FunctionType *m_tbType; 134 | llvm::Type *m_cpuType; 135 | llvm::Value *m_cpuState; 136 | // Represents CPU state pointer cast to an int 137 | llvm::Instruction *m_cpuStateInt; 138 | 139 | // This instruction is a no-op in the entry block, we use it 140 | // in order to simplify instruction insertion. 141 | llvm::Instruction *m_noop; 142 | llvm::Value *m_eip; 143 | llvm::Value *m_ccop; 144 | 145 | static unsigned m_eip_last_gep_index; 146 | 147 | typedef llvm::DenseMap, llvm::Instruction *> GepMap; 148 | GepMap m_registers; 149 | 150 | std::string generateName(); 151 | 152 | TCGLLVMTranslator(const std::string &bitcodeLibraryPath, std::unique_ptr module); 153 | 154 | #ifdef CONFIG_SYMBEX 155 | void initializeNativeCpuState(); 156 | void initializeHelpers(); 157 | #endif 158 | 159 | public: 160 | ~TCGLLVMTranslator(); 161 | 162 | static TCGLLVMTranslator *create(const std::string &bitcodeLibraryPath); 163 | 164 | llvm::LLVMContext &getContext() const { 165 | return m_module->getContext(); 166 | } 167 | 168 | llvm::Module *getModule() const { 169 | return m_module.get(); 170 | } 171 | 172 | const std::string &getBitcodeLibraryPath() const { 173 | return m_bitcodeLibraryPath; 174 | } 175 | 176 | llvm::legacy::FunctionPassManager *getFunctionPassManager() const { 177 | return m_functionPassManager; 178 | } 179 | 180 | bool isInstrumented(llvm::Function *tb); 181 | 182 | /* Shortcuts */ 183 | llvm::Type *intType(int w) { 184 | return llvm::IntegerType::get(getContext(), w); 185 | } 186 | llvm::Type *intPtrType(int w) { 187 | return llvm::PointerType::get(intType(w), 0); 188 | } 189 | llvm::Type *wordType() { 190 | return intType(TCG_TARGET_REG_BITS); 191 | } 192 | llvm::Type *wordType(int bits) { 193 | return intType(bits); 194 | } 195 | llvm::Type *wordPtrType() { 196 | return intPtrType(TCG_TARGET_REG_BITS); 197 | } 198 | llvm::FunctionType *tbType(); 199 | 200 | void adjustTypeSize(unsigned target, llvm::Value **v1); 201 | 202 | llvm::Value *generateCpuStatePtr(uint64_t arg, unsigned sizeInBytes); 203 | void generateQemuCpuLoad(const TCGArg *args, unsigned memBits, unsigned regBits, bool signExtend); 204 | void generateQemuCpuStore(const TCGArg *args, unsigned memBits, llvm::Value *valueToStore); 205 | 206 | #ifdef STATIC_TRANSLATOR 207 | uint64_t m_currentPc; 208 | void attachPcMetadata(llvm::Instruction *instr, uint64_t pc); 209 | #endif 210 | llvm::Value *attachCurrentPc(llvm::Value *value); 211 | 212 | // This handles the special case of symbolic values 213 | // assigned to the program counter register 214 | llvm::Value *handleSymbolicPcAssignment(llvm::Value *orig); 215 | 216 | #ifdef STATIC_TRANSLATOR 217 | bool isPcAssignment(llvm::Value *v) { 218 | return v == m_eip; 219 | } 220 | 221 | const TCGLLVMTBInfo &getTbInfo() const { 222 | return m_info; 223 | } 224 | 225 | void computeStaticBranchTargets(); 226 | #endif 227 | 228 | void adjustTypeSize(unsigned target, llvm::Value **v1, llvm::Value **v2) { 229 | adjustTypeSize(target, v1); 230 | adjustTypeSize(target, v2); 231 | } 232 | 233 | llvm::Type *tcgType(int type) { 234 | return type == TCG_TYPE_I64 ? intType(64) : intType(32); 235 | } 236 | 237 | llvm::Type *tcgPtrType(int type) { 238 | return type == TCG_TYPE_I64 ? intPtrType(64) : intPtrType(32); 239 | } 240 | 241 | /* Helpers */ 242 | llvm::Value *getValue(TCGArg arg); 243 | void setValue(TCGArg arg, llvm::Value *v); 244 | void delValue(int idx); 245 | 246 | llvm::Value *getPtrForValue(int idx); 247 | void delPtrForValue(int idx); 248 | void initGlobalsAndLocalTemps(); 249 | void loadNativeCpuState(llvm::Function *f); 250 | unsigned getValueBits(int idx); 251 | 252 | void invalidateCachedMemory(); 253 | 254 | uint64_t toInteger(llvm::Value *v) const; 255 | 256 | llvm::BasicBlock *getLabel(TCGArg i); 257 | void startNewBasicBlock(llvm::BasicBlock *bb = NULL); 258 | 259 | /* Code generation */ 260 | llvm::Value *generateQemuMemOp(bool ld, llvm::Value *value, llvm::Value *addr, int mem_index, int bits); 261 | 262 | int generateOperation(const TCGOp *op); 263 | 264 | llvm::Function *createTbFunction(const std::string &name); 265 | llvm::Function *generateCode(TCGContext *s, TranslationBlock *tb); 266 | void removeInterruptExit(); 267 | 268 | bool getCpuFieldGepIndexes(unsigned offset, unsigned sizeInBytes, llvm::SmallVector &gepIndexes); 269 | static bool GetStaticBranchTarget(const llvm::BasicBlock *bb, uint64_t *target); 270 | }; 271 | 272 | #endif 273 | 274 | #endif 275 | -------------------------------------------------------------------------------- /include/tcg/tcg-mo.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Tiny Code Generator for QEMU 3 | * 4 | * Copyright (c) 2008 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef TCG_MO_H 26 | #define TCG_MO_H 27 | 28 | typedef enum { 29 | /* Used to indicate the type of accesses on which ordering 30 | is to be ensured. Modeled after SPARC barriers. 31 | 32 | This is of the form TCG_MO_A_B where A is before B in program order. 33 | */ 34 | TCG_MO_LD_LD = 0x01, 35 | TCG_MO_ST_LD = 0x02, 36 | TCG_MO_LD_ST = 0x04, 37 | TCG_MO_ST_ST = 0x08, 38 | TCG_MO_ALL = 0x0F, /* OR of the above */ 39 | 40 | /* Used to indicate the kind of ordering which is to be ensured by the 41 | instruction. These types are derived from x86/aarch64 instructions. 42 | It should be noted that these are different from C11 semantics. */ 43 | TCG_BAR_LDAQ = 0x10, /* Following ops will not come forward */ 44 | TCG_BAR_STRL = 0x20, /* Previous ops will not be delayed */ 45 | TCG_BAR_SC = 0x30, /* No ops cross barrier; OR of the above */ 46 | } TCGBar; 47 | 48 | #endif /* TCG_MO_H */ 49 | -------------------------------------------------------------------------------- /include/tcg/tcg-opc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Tiny Code Generator for QEMU 3 | * 4 | * Copyright (c) 2008 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | /* 26 | * DEF(name, oargs, iargs, cargs, flags) 27 | */ 28 | 29 | /* predefined ops */ 30 | DEF(discard, 1, 0, 0, TCG_OPF_NOT_PRESENT) 31 | DEF(set_label, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_NOT_PRESENT) 32 | 33 | /* variable number of parameters */ 34 | DEF(call, 0, 0, 3, TCG_OPF_CALL_CLOBBER | TCG_OPF_NOT_PRESENT) 35 | 36 | DEF(br, 0, 0, 1, TCG_OPF_BB_END) 37 | 38 | #define IMPL(X) (__builtin_constant_p(X) && !(X) ? TCG_OPF_NOT_PRESENT : 0) 39 | #if TCG_TARGET_REG_BITS == 32 40 | #define IMPL64 TCG_OPF_64BIT | TCG_OPF_NOT_PRESENT 41 | #else 42 | #define IMPL64 TCG_OPF_64BIT 43 | #endif 44 | 45 | DEF(mb, 0, 0, 1, 0) 46 | 47 | DEF(mov_i32, 1, 1, 0, TCG_OPF_NOT_PRESENT) 48 | DEF(movi_i32, 1, 0, 1, TCG_OPF_NOT_PRESENT) 49 | DEF(setcond_i32, 1, 2, 1, 0) 50 | DEF(movcond_i32, 1, 4, 1, IMPL(TCG_TARGET_HAS_movcond_i32)) 51 | /* load/store */ 52 | DEF(ld8u_i32, 1, 1, 1, 0) 53 | DEF(ld8s_i32, 1, 1, 1, 0) 54 | DEF(ld16u_i32, 1, 1, 1, 0) 55 | DEF(ld16s_i32, 1, 1, 1, 0) 56 | DEF(ld_i32, 1, 1, 1, 0) 57 | DEF(st8_i32, 0, 2, 1, 0) 58 | DEF(st16_i32, 0, 2, 1, 0) 59 | DEF(st_i32, 0, 2, 1, 0) 60 | /* arith */ 61 | DEF(add_i32, 1, 2, 0, 0) 62 | DEF(sub_i32, 1, 2, 0, 0) 63 | DEF(mul_i32, 1, 2, 0, 0) 64 | DEF(div_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_div_i32)) 65 | DEF(divu_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_div_i32)) 66 | DEF(rem_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_rem_i32)) 67 | DEF(remu_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_rem_i32)) 68 | DEF(div2_i32, 2, 3, 0, IMPL(TCG_TARGET_HAS_div2_i32)) 69 | DEF(divu2_i32, 2, 3, 0, IMPL(TCG_TARGET_HAS_div2_i32)) 70 | DEF(and_i32, 1, 2, 0, 0) 71 | DEF(or_i32, 1, 2, 0, 0) 72 | DEF(xor_i32, 1, 2, 0, 0) 73 | /* shifts/rotates */ 74 | DEF(shl_i32, 1, 2, 0, 0) 75 | DEF(shr_i32, 1, 2, 0, 0) 76 | DEF(sar_i32, 1, 2, 0, 0) 77 | DEF(rotl_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_rot_i32)) 78 | DEF(rotr_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_rot_i32)) 79 | DEF(deposit_i32, 1, 2, 2, IMPL(TCG_TARGET_HAS_deposit_i32)) 80 | DEF(extract_i32, 1, 1, 2, IMPL(TCG_TARGET_HAS_extract_i32)) 81 | DEF(sextract_i32, 1, 1, 2, IMPL(TCG_TARGET_HAS_sextract_i32)) 82 | 83 | DEF(brcond_i32, 0, 2, 2, TCG_OPF_BB_END) 84 | 85 | DEF(add2_i32, 2, 4, 0, IMPL(TCG_TARGET_HAS_add2_i32)) 86 | DEF(sub2_i32, 2, 4, 0, IMPL(TCG_TARGET_HAS_sub2_i32)) 87 | DEF(mulu2_i32, 2, 2, 0, IMPL(TCG_TARGET_HAS_mulu2_i32)) 88 | DEF(muls2_i32, 2, 2, 0, IMPL(TCG_TARGET_HAS_muls2_i32)) 89 | DEF(muluh_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_muluh_i32)) 90 | DEF(mulsh_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_mulsh_i32)) 91 | DEF(brcond2_i32, 0, 4, 2, TCG_OPF_BB_END | IMPL(TCG_TARGET_REG_BITS == 32)) 92 | DEF(setcond2_i32, 1, 4, 1, IMPL(TCG_TARGET_REG_BITS == 32)) 93 | 94 | DEF(ext8s_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_ext8s_i32)) 95 | DEF(ext16s_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_ext16s_i32)) 96 | DEF(ext8u_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_ext8u_i32)) 97 | DEF(ext16u_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_ext16u_i32)) 98 | DEF(bswap16_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_bswap16_i32)) 99 | DEF(bswap32_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_bswap32_i32)) 100 | DEF(not_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_not_i32)) 101 | DEF(neg_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_neg_i32)) 102 | DEF(andc_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_andc_i32)) 103 | DEF(orc_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_orc_i32)) 104 | DEF(eqv_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_eqv_i32)) 105 | DEF(nand_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_nand_i32)) 106 | DEF(nor_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_nor_i32)) 107 | DEF(clz_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_clz_i32)) 108 | DEF(ctz_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_ctz_i32)) 109 | DEF(ctpop_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_ctpop_i32)) 110 | 111 | DEF(mov_i64, 1, 1, 0, TCG_OPF_64BIT | TCG_OPF_NOT_PRESENT) 112 | DEF(movi_i64, 1, 0, 1, TCG_OPF_64BIT | TCG_OPF_NOT_PRESENT) 113 | DEF(setcond_i64, 1, 2, 1, IMPL64) 114 | DEF(movcond_i64, 1, 4, 1, IMPL64 | IMPL(TCG_TARGET_HAS_movcond_i64)) 115 | /* load/store */ 116 | DEF(ld8u_i64, 1, 1, 1, IMPL64) 117 | DEF(ld8s_i64, 1, 1, 1, IMPL64) 118 | DEF(ld16u_i64, 1, 1, 1, IMPL64) 119 | DEF(ld16s_i64, 1, 1, 1, IMPL64) 120 | DEF(ld32u_i64, 1, 1, 1, IMPL64) 121 | DEF(ld32s_i64, 1, 1, 1, IMPL64) 122 | DEF(ld_i64, 1, 1, 1, IMPL64) 123 | DEF(st8_i64, 0, 2, 1, IMPL64) 124 | DEF(st16_i64, 0, 2, 1, IMPL64) 125 | DEF(st32_i64, 0, 2, 1, IMPL64) 126 | DEF(st_i64, 0, 2, 1, IMPL64) 127 | /* arith */ 128 | DEF(add_i64, 1, 2, 0, IMPL64) 129 | DEF(sub_i64, 1, 2, 0, IMPL64) 130 | DEF(mul_i64, 1, 2, 0, IMPL64) 131 | DEF(div_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div_i64)) 132 | DEF(divu_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div_i64)) 133 | DEF(rem_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_rem_i64)) 134 | DEF(remu_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_rem_i64)) 135 | DEF(div2_i64, 2, 3, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div2_i64)) 136 | DEF(divu2_i64, 2, 3, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div2_i64)) 137 | DEF(and_i64, 1, 2, 0, IMPL64) 138 | DEF(or_i64, 1, 2, 0, IMPL64) 139 | DEF(xor_i64, 1, 2, 0, IMPL64) 140 | /* shifts/rotates */ 141 | DEF(shl_i64, 1, 2, 0, IMPL64) 142 | DEF(shr_i64, 1, 2, 0, IMPL64) 143 | DEF(sar_i64, 1, 2, 0, IMPL64) 144 | DEF(rotl_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_rot_i64)) 145 | DEF(rotr_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_rot_i64)) 146 | DEF(deposit_i64, 1, 2, 2, IMPL64 | IMPL(TCG_TARGET_HAS_deposit_i64)) 147 | DEF(extract_i64, 1, 1, 2, IMPL64 | IMPL(TCG_TARGET_HAS_extract_i64)) 148 | DEF(sextract_i64, 1, 1, 2, IMPL64 | IMPL(TCG_TARGET_HAS_sextract_i64)) 149 | 150 | /* size changing ops */ 151 | DEF(ext_i32_i64, 1, 1, 0, IMPL64) 152 | DEF(extu_i32_i64, 1, 1, 0, IMPL64) 153 | DEF(extrl_i64_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_extrl_i64_i32) | (TCG_TARGET_REG_BITS == 32 ? TCG_OPF_NOT_PRESENT : 0)) 154 | DEF(extrh_i64_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_extrh_i64_i32) | (TCG_TARGET_REG_BITS == 32 ? TCG_OPF_NOT_PRESENT : 0)) 155 | 156 | DEF(brcond_i64, 0, 2, 2, TCG_OPF_BB_END | IMPL64) 157 | DEF(ext8s_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext8s_i64)) 158 | DEF(ext16s_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext16s_i64)) 159 | DEF(ext32s_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext32s_i64)) 160 | DEF(ext8u_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext8u_i64)) 161 | DEF(ext16u_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext16u_i64)) 162 | DEF(ext32u_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext32u_i64)) 163 | DEF(bswap16_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_bswap16_i64)) 164 | DEF(bswap32_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_bswap32_i64)) 165 | DEF(bswap64_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_bswap64_i64)) 166 | DEF(not_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_not_i64)) 167 | DEF(neg_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_neg_i64)) 168 | DEF(andc_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_andc_i64)) 169 | DEF(orc_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_orc_i64)) 170 | DEF(eqv_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_eqv_i64)) 171 | DEF(nand_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_nand_i64)) 172 | DEF(nor_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_nor_i64)) 173 | DEF(clz_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_clz_i64)) 174 | DEF(ctz_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ctz_i64)) 175 | DEF(ctpop_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ctpop_i64)) 176 | 177 | DEF(add2_i64, 2, 4, 0, IMPL64 | IMPL(TCG_TARGET_HAS_add2_i64)) 178 | DEF(sub2_i64, 2, 4, 0, IMPL64 | IMPL(TCG_TARGET_HAS_sub2_i64)) 179 | DEF(mulu2_i64, 2, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_mulu2_i64)) 180 | DEF(muls2_i64, 2, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_muls2_i64)) 181 | DEF(muluh_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_muluh_i64)) 182 | DEF(mulsh_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_mulsh_i64)) 183 | 184 | #define TLADDR_ARGS (TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? 1 : 2) 185 | #define DATA64_ARGS (TCG_TARGET_REG_BITS == 64 ? 1 : 2) 186 | 187 | /* QEMU specific */ 188 | DEF(insn_start, 0, 0, TLADDR_ARGS *TARGET_INSN_START_WORDS, TCG_OPF_NOT_PRESENT) 189 | DEF(exit_tb, 0, 0, 1, TCG_OPF_BB_EXIT | TCG_OPF_BB_END) 190 | DEF(goto_tb, 0, 0, 1, TCG_OPF_BB_EXIT | TCG_OPF_BB_END) 191 | DEF(goto_ptr, 0, 1, 0, TCG_OPF_BB_EXIT | TCG_OPF_BB_END | IMPL(TCG_TARGET_HAS_goto_ptr)) 192 | 193 | DEF(qemu_ld_i32, 1, TLADDR_ARGS, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 194 | DEF(qemu_st_i32, 0, TLADDR_ARGS + 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 195 | DEF(qemu_ld_i64, DATA64_ARGS, TLADDR_ARGS, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS | TCG_OPF_64BIT) 196 | DEF(qemu_st_i64, 0, TLADDR_ARGS + DATA64_ARGS, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS | TCG_OPF_64BIT) 197 | 198 | /* Host vector support. */ 199 | 200 | #define IMPLVEC TCG_OPF_VECTOR | IMPL(TCG_TARGET_MAYBE_vec) 201 | 202 | DEF(mov_vec, 1, 1, 0, TCG_OPF_VECTOR | TCG_OPF_NOT_PRESENT) 203 | DEF(dupi_vec, 1, 0, 1, TCG_OPF_VECTOR | TCG_OPF_NOT_PRESENT) 204 | 205 | DEF(dup_vec, 1, 1, 0, IMPLVEC) 206 | DEF(dup2_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_REG_BITS == 32)) 207 | 208 | DEF(ld_vec, 1, 1, 1, IMPLVEC) 209 | DEF(st_vec, 0, 2, 1, IMPLVEC) 210 | 211 | DEF(add_vec, 1, 2, 0, IMPLVEC) 212 | DEF(sub_vec, 1, 2, 0, IMPLVEC) 213 | DEF(mul_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_mul_vec)) 214 | DEF(neg_vec, 1, 1, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_neg_vec)) 215 | DEF(ssadd_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_sat_vec)) 216 | DEF(usadd_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_sat_vec)) 217 | DEF(sssub_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_sat_vec)) 218 | DEF(ussub_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_sat_vec)) 219 | DEF(smin_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_minmax_vec)) 220 | DEF(umin_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_minmax_vec)) 221 | DEF(smax_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_minmax_vec)) 222 | DEF(umax_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_minmax_vec)) 223 | 224 | DEF(and_vec, 1, 2, 0, IMPLVEC) 225 | DEF(or_vec, 1, 2, 0, IMPLVEC) 226 | DEF(xor_vec, 1, 2, 0, IMPLVEC) 227 | DEF(andc_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_andc_vec)) 228 | DEF(orc_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_orc_vec)) 229 | DEF(not_vec, 1, 1, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_not_vec)) 230 | 231 | DEF(shli_vec, 1, 1, 1, IMPLVEC | IMPL(TCG_TARGET_HAS_shi_vec)) 232 | DEF(shri_vec, 1, 1, 1, IMPLVEC | IMPL(TCG_TARGET_HAS_shi_vec)) 233 | DEF(sari_vec, 1, 1, 1, IMPLVEC | IMPL(TCG_TARGET_HAS_shi_vec)) 234 | 235 | DEF(shls_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_shs_vec)) 236 | DEF(shrs_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_shs_vec)) 237 | DEF(sars_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_shs_vec)) 238 | 239 | DEF(shlv_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_shv_vec)) 240 | DEF(shrv_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_shv_vec)) 241 | DEF(sarv_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_shv_vec)) 242 | 243 | DEF(cmp_vec, 1, 2, 1, IMPLVEC) 244 | 245 | DEF(last_generic, 0, 0, 0, TCG_OPF_NOT_PRESENT) 246 | 247 | #if TCG_TARGET_MAYBE_vec 248 | #include "i386/tcg-target.opc.h" 249 | #endif 250 | 251 | #undef TLADDR_ARGS 252 | #undef DATA64_ARGS 253 | #undef IMPL 254 | #undef IMPL64 255 | #undef IMPLVEC 256 | #undef DEF 257 | -------------------------------------------------------------------------------- /include/tcg/tcg-runtime.h: -------------------------------------------------------------------------------- 1 | 2 | DEF_HELPER_FLAGS_2(div_i32, TCG_CALL_NO_RWG_SE, s32, s32, s32) 3 | DEF_HELPER_FLAGS_2(rem_i32, TCG_CALL_NO_RWG_SE, s32, s32, s32) 4 | DEF_HELPER_FLAGS_2(divu_i32, TCG_CALL_NO_RWG_SE, i32, i32, i32) 5 | DEF_HELPER_FLAGS_2(remu_i32, TCG_CALL_NO_RWG_SE, i32, i32, i32) 6 | 7 | DEF_HELPER_FLAGS_2(div_i64, TCG_CALL_NO_RWG_SE, s64, s64, s64) 8 | DEF_HELPER_FLAGS_2(rem_i64, TCG_CALL_NO_RWG_SE, s64, s64, s64) 9 | DEF_HELPER_FLAGS_2(divu_i64, TCG_CALL_NO_RWG_SE, i64, i64, i64) 10 | DEF_HELPER_FLAGS_2(remu_i64, TCG_CALL_NO_RWG_SE, i64, i64, i64) 11 | 12 | DEF_HELPER_FLAGS_2(shl_i64, TCG_CALL_NO_RWG_SE, i64, i64, i64) 13 | DEF_HELPER_FLAGS_2(shr_i64, TCG_CALL_NO_RWG_SE, i64, i64, i64) 14 | DEF_HELPER_FLAGS_2(sar_i64, TCG_CALL_NO_RWG_SE, s64, s64, s64) 15 | 16 | DEF_HELPER_FLAGS_2(mulsh_i64, TCG_CALL_NO_RWG_SE, s64, s64, s64) 17 | DEF_HELPER_FLAGS_2(muluh_i64, TCG_CALL_NO_RWG_SE, i64, i64, i64) 18 | 19 | DEF_HELPER_FLAGS_2(clz_i32, TCG_CALL_NO_RWG_SE, i32, i32, i32) 20 | DEF_HELPER_FLAGS_2(ctz_i32, TCG_CALL_NO_RWG_SE, i32, i32, i32) 21 | DEF_HELPER_FLAGS_2(clz_i64, TCG_CALL_NO_RWG_SE, i64, i64, i64) 22 | DEF_HELPER_FLAGS_2(ctz_i64, TCG_CALL_NO_RWG_SE, i64, i64, i64) 23 | DEF_HELPER_FLAGS_1(clrsb_i32, TCG_CALL_NO_RWG_SE, i32, i32) 24 | DEF_HELPER_FLAGS_1(clrsb_i64, TCG_CALL_NO_RWG_SE, i64, i64) 25 | DEF_HELPER_FLAGS_1(ctpop_i32, TCG_CALL_NO_RWG_SE, i32, i32) 26 | DEF_HELPER_FLAGS_1(ctpop_i64, TCG_CALL_NO_RWG_SE, i64, i64) 27 | 28 | DEF_HELPER_FLAGS_1(lookup_tb_ptr, TCG_CALL_NO_WG_SE, ptr, env) 29 | 30 | DEF_HELPER_FLAGS_1(exit_atomic, TCG_CALL_NO_WG, noreturn, env) 31 | 32 | #ifdef CONFIG_SOFTMMU 33 | 34 | DEF_HELPER_FLAGS_5(atomic_cmpxchgb, TCG_CALL_NO_WG, i32, env, tl, i32, i32, i32) 35 | DEF_HELPER_FLAGS_5(atomic_cmpxchgw_be, TCG_CALL_NO_WG, i32, env, tl, i32, i32, i32) 36 | DEF_HELPER_FLAGS_5(atomic_cmpxchgw_le, TCG_CALL_NO_WG, i32, env, tl, i32, i32, i32) 37 | DEF_HELPER_FLAGS_5(atomic_cmpxchgl_be, TCG_CALL_NO_WG, i32, env, tl, i32, i32, i32) 38 | DEF_HELPER_FLAGS_5(atomic_cmpxchgl_le, TCG_CALL_NO_WG, i32, env, tl, i32, i32, i32) 39 | #ifdef CONFIG_ATOMIC64 40 | DEF_HELPER_FLAGS_5(atomic_cmpxchgq_be, TCG_CALL_NO_WG, i64, env, tl, i64, i64, i32) 41 | DEF_HELPER_FLAGS_5(atomic_cmpxchgq_le, TCG_CALL_NO_WG, i64, env, tl, i64, i64, i32) 42 | #endif 43 | 44 | #ifdef CONFIG_ATOMIC64 45 | #define GEN_ATOMIC_HELPERS(NAME) \ 46 | DEF_HELPER_FLAGS_4(glue(glue(atomic_, NAME), b), TCG_CALL_NO_WG, i32, env, tl, i32, i32) \ 47 | DEF_HELPER_FLAGS_4(glue(glue(atomic_, NAME), w_le), TCG_CALL_NO_WG, i32, env, tl, i32, i32) \ 48 | DEF_HELPER_FLAGS_4(glue(glue(atomic_, NAME), w_be), TCG_CALL_NO_WG, i32, env, tl, i32, i32) \ 49 | DEF_HELPER_FLAGS_4(glue(glue(atomic_, NAME), l_le), TCG_CALL_NO_WG, i32, env, tl, i32, i32) \ 50 | DEF_HELPER_FLAGS_4(glue(glue(atomic_, NAME), l_be), TCG_CALL_NO_WG, i32, env, tl, i32, i32) \ 51 | DEF_HELPER_FLAGS_4(glue(glue(atomic_, NAME), q_le), TCG_CALL_NO_WG, i64, env, tl, i64, i32) \ 52 | DEF_HELPER_FLAGS_4(glue(glue(atomic_, NAME), q_be), TCG_CALL_NO_WG, i64, env, tl, i64, i32) 53 | #else 54 | #define GEN_ATOMIC_HELPERS(NAME) \ 55 | DEF_HELPER_FLAGS_4(glue(glue(atomic_, NAME), b), TCG_CALL_NO_WG, i32, env, tl, i32, i32) \ 56 | DEF_HELPER_FLAGS_4(glue(glue(atomic_, NAME), w_le), TCG_CALL_NO_WG, i32, env, tl, i32, i32) \ 57 | DEF_HELPER_FLAGS_4(glue(glue(atomic_, NAME), w_be), TCG_CALL_NO_WG, i32, env, tl, i32, i32) \ 58 | DEF_HELPER_FLAGS_4(glue(glue(atomic_, NAME), l_le), TCG_CALL_NO_WG, i32, env, tl, i32, i32) \ 59 | DEF_HELPER_FLAGS_4(glue(glue(atomic_, NAME), l_be), TCG_CALL_NO_WG, i32, env, tl, i32, i32) 60 | #endif /* CONFIG_ATOMIC64 */ 61 | 62 | #else 63 | 64 | DEF_HELPER_FLAGS_4(atomic_cmpxchgb, TCG_CALL_NO_WG, i32, env, tl, i32, i32) 65 | DEF_HELPER_FLAGS_4(atomic_cmpxchgw_be, TCG_CALL_NO_WG, i32, env, tl, i32, i32) 66 | DEF_HELPER_FLAGS_4(atomic_cmpxchgw_le, TCG_CALL_NO_WG, i32, env, tl, i32, i32) 67 | DEF_HELPER_FLAGS_4(atomic_cmpxchgl_be, TCG_CALL_NO_WG, i32, env, tl, i32, i32) 68 | DEF_HELPER_FLAGS_4(atomic_cmpxchgl_le, TCG_CALL_NO_WG, i32, env, tl, i32, i32) 69 | #ifdef CONFIG_ATOMIC64 70 | DEF_HELPER_FLAGS_4(atomic_cmpxchgq_be, TCG_CALL_NO_WG, i64, env, tl, i64, i64) 71 | DEF_HELPER_FLAGS_4(atomic_cmpxchgq_le, TCG_CALL_NO_WG, i64, env, tl, i64, i64) 72 | #endif 73 | 74 | #ifdef CONFIG_ATOMIC64 75 | #define GEN_ATOMIC_HELPERS(NAME) \ 76 | DEF_HELPER_FLAGS_3(glue(glue(atomic_, NAME), b), TCG_CALL_NO_WG, i32, env, tl, i32) \ 77 | DEF_HELPER_FLAGS_3(glue(glue(atomic_, NAME), w_le), TCG_CALL_NO_WG, i32, env, tl, i32) \ 78 | DEF_HELPER_FLAGS_3(glue(glue(atomic_, NAME), w_be), TCG_CALL_NO_WG, i32, env, tl, i32) \ 79 | DEF_HELPER_FLAGS_3(glue(glue(atomic_, NAME), l_le), TCG_CALL_NO_WG, i32, env, tl, i32) \ 80 | DEF_HELPER_FLAGS_3(glue(glue(atomic_, NAME), l_be), TCG_CALL_NO_WG, i32, env, tl, i32) \ 81 | DEF_HELPER_FLAGS_3(glue(glue(atomic_, NAME), q_le), TCG_CALL_NO_WG, i64, env, tl, i64) \ 82 | DEF_HELPER_FLAGS_3(glue(glue(atomic_, NAME), q_be), TCG_CALL_NO_WG, i64, env, tl, i64) 83 | #else 84 | #define GEN_ATOMIC_HELPERS(NAME) \ 85 | DEF_HELPER_FLAGS_3(glue(glue(atomic_, NAME), b), TCG_CALL_NO_WG, i32, env, tl, i32) \ 86 | DEF_HELPER_FLAGS_3(glue(glue(atomic_, NAME), w_le), TCG_CALL_NO_WG, i32, env, tl, i32) \ 87 | DEF_HELPER_FLAGS_3(glue(glue(atomic_, NAME), w_be), TCG_CALL_NO_WG, i32, env, tl, i32) \ 88 | DEF_HELPER_FLAGS_3(glue(glue(atomic_, NAME), l_le), TCG_CALL_NO_WG, i32, env, tl, i32) \ 89 | DEF_HELPER_FLAGS_3(glue(glue(atomic_, NAME), l_be), TCG_CALL_NO_WG, i32, env, tl, i32) 90 | #endif /* CONFIG_ATOMIC64 */ 91 | 92 | #endif /* CONFIG_SOFTMMU */ 93 | 94 | GEN_ATOMIC_HELPERS(fetch_add) 95 | GEN_ATOMIC_HELPERS(fetch_and) 96 | GEN_ATOMIC_HELPERS(fetch_or) 97 | GEN_ATOMIC_HELPERS(fetch_xor) 98 | GEN_ATOMIC_HELPERS(fetch_smin) 99 | GEN_ATOMIC_HELPERS(fetch_umin) 100 | GEN_ATOMIC_HELPERS(fetch_smax) 101 | GEN_ATOMIC_HELPERS(fetch_umax) 102 | 103 | GEN_ATOMIC_HELPERS(add_fetch) 104 | GEN_ATOMIC_HELPERS(and_fetch) 105 | GEN_ATOMIC_HELPERS(or_fetch) 106 | GEN_ATOMIC_HELPERS(xor_fetch) 107 | GEN_ATOMIC_HELPERS(smin_fetch) 108 | GEN_ATOMIC_HELPERS(umin_fetch) 109 | GEN_ATOMIC_HELPERS(smax_fetch) 110 | GEN_ATOMIC_HELPERS(umax_fetch) 111 | 112 | GEN_ATOMIC_HELPERS(xchg) 113 | 114 | #undef GEN_ATOMIC_HELPERS 115 | -------------------------------------------------------------------------------- /include/tcg/utils/atomic.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 Cyberhaven 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #ifndef TCG_ATOMIC_H 22 | #define TCG_ATOMIC_H 23 | 24 | #define atomic_read(p) __atomic_load_n(p, __ATOMIC_RELAXED) 25 | #define atomic_set(p, i) __atomic_store_n(p, i, __ATOMIC_RELAXED) 26 | #define atomic_fetch_inc(p) __atomic_fetch_add(p, 1, __ATOMIC_SEQ_CST) 27 | #define atomic_or(p, n) ((void) __sync_fetch_and_or(p, n)) 28 | #define atomic_or_fetch(p, n) __atomic_or_fetch(p, n, __ATOMIC_SEQ_CST) 29 | #define atomic_and(p, n) ((void) __atomic_fetch_and(p, n, __ATOMIC_SEQ_CST)) 30 | #define atomic_cmpxchg(p, old, new) __sync_val_compare_and_swap(p, old, new) 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /include/tcg/utils/bitmap.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 Cyberhaven 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #ifndef TCG_BITMAP_H 22 | 23 | #define TCG_BITMAP_H 24 | 25 | #include 26 | #include "bitops.h" 27 | 28 | static inline void bitmap_zero(unsigned long *bitmap, long bits) { 29 | long length = BITS_TO_LONGS(bits) * sizeof(unsigned long); 30 | memset(bitmap, 0, length); 31 | } 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /include/tcg/utils/bitops.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Bitops Module 3 | * 4 | * Copyright (C) 2010 Corentin Chary 5 | * 6 | * Mostly inspired by (stolen from) linux/bitmap.h and linux/bitops.h 7 | * 8 | * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. 9 | * See the COPYING.LIB file in the top-level directory. 10 | */ 11 | 12 | #ifndef BITOPS_H 13 | #define BITOPS_H 14 | 15 | #include "atomic.h" 16 | #include "host-utils.h" 17 | #include "rounding.h" 18 | 19 | #define BITS_PER_BYTE CHAR_BIT 20 | #define BITS_PER_LONG (sizeof(unsigned long) * BITS_PER_BYTE) 21 | 22 | #if !defined(BIT) 23 | #define BIT(nr) (1UL << (nr)) 24 | #endif 25 | 26 | #define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) 27 | #define BIT_WORD(nr) ((nr) / BITS_PER_LONG) 28 | #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) 29 | 30 | #define MAKE_64BIT_MASK(shift, length) (((~0ULL) >> (64 - (length))) << (shift)) 31 | 32 | /** 33 | * set_bit - Set a bit in memory 34 | * @nr: the bit to set 35 | * @addr: the address to start counting from 36 | */ 37 | static inline void set_bit(long nr, unsigned long *addr) { 38 | unsigned long mask = BIT_MASK(nr); 39 | unsigned long *p = addr + BIT_WORD(nr); 40 | 41 | *p |= mask; 42 | } 43 | 44 | /** 45 | * set_bit_atomic - Set a bit in memory atomically 46 | * @nr: the bit to set 47 | * @addr: the address to start counting from 48 | */ 49 | static inline void set_bit_atomic(long nr, unsigned long *addr) { 50 | unsigned long mask = BIT_MASK(nr); 51 | unsigned long *p = addr + BIT_WORD(nr); 52 | 53 | atomic_or(p, mask); 54 | } 55 | 56 | /** 57 | * clear_bit - Clears a bit in memory 58 | * @nr: Bit to clear 59 | * @addr: Address to start counting from 60 | */ 61 | static inline void clear_bit(long nr, unsigned long *addr) { 62 | unsigned long mask = BIT_MASK(nr); 63 | unsigned long *p = addr + BIT_WORD(nr); 64 | 65 | *p &= ~mask; 66 | } 67 | 68 | /** 69 | * change_bit - Toggle a bit in memory 70 | * @nr: Bit to change 71 | * @addr: Address to start counting from 72 | */ 73 | static inline void change_bit(long nr, unsigned long *addr) { 74 | unsigned long mask = BIT_MASK(nr); 75 | unsigned long *p = addr + BIT_WORD(nr); 76 | 77 | *p ^= mask; 78 | } 79 | 80 | /** 81 | * test_and_set_bit - Set a bit and return its old value 82 | * @nr: Bit to set 83 | * @addr: Address to count from 84 | */ 85 | static inline int test_and_set_bit(long nr, unsigned long *addr) { 86 | unsigned long mask = BIT_MASK(nr); 87 | unsigned long *p = addr + BIT_WORD(nr); 88 | unsigned long old = *p; 89 | 90 | *p = old | mask; 91 | return (old & mask) != 0; 92 | } 93 | 94 | /** 95 | * test_and_clear_bit - Clear a bit and return its old value 96 | * @nr: Bit to clear 97 | * @addr: Address to count from 98 | */ 99 | static inline int test_and_clear_bit(long nr, unsigned long *addr) { 100 | unsigned long mask = BIT_MASK(nr); 101 | unsigned long *p = addr + BIT_WORD(nr); 102 | unsigned long old = *p; 103 | 104 | *p = old & ~mask; 105 | return (old & mask) != 0; 106 | } 107 | 108 | /** 109 | * test_and_change_bit - Change a bit and return its old value 110 | * @nr: Bit to change 111 | * @addr: Address to count from 112 | */ 113 | static inline int test_and_change_bit(long nr, unsigned long *addr) { 114 | unsigned long mask = BIT_MASK(nr); 115 | unsigned long *p = addr + BIT_WORD(nr); 116 | unsigned long old = *p; 117 | 118 | *p = old ^ mask; 119 | return (old & mask) != 0; 120 | } 121 | 122 | /** 123 | * test_bit - Determine whether a bit is set 124 | * @nr: bit number to test 125 | * @addr: Address to start counting from 126 | */ 127 | static inline int test_bit(long nr, const unsigned long *addr) { 128 | return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG - 1))); 129 | } 130 | 131 | /** 132 | * find_first_bit - find the first set bit in a memory region 133 | * @addr: The address to start the search at 134 | * @size: The maximum size to search 135 | * 136 | * Returns the bit number of the first set bit. 137 | */ 138 | static inline unsigned long find_first_bit(const unsigned long *addr, unsigned long size) { 139 | unsigned long result, tmp; 140 | 141 | for (result = 0; result < size; result += BITS_PER_LONG) { 142 | tmp = *addr++; 143 | if (tmp) { 144 | result += ctzl(tmp); 145 | return result < size ? result : size; 146 | } 147 | } 148 | /* Not found */ 149 | return size; 150 | } 151 | 152 | /** 153 | * rol8 - rotate an 8-bit value left 154 | * @word: value to rotate 155 | * @shift: bits to roll 156 | */ 157 | static inline uint8_t rol8(uint8_t word, unsigned int shift) { 158 | return (word << shift) | (word >> ((8 - shift) & 7)); 159 | } 160 | 161 | /** 162 | * ror8 - rotate an 8-bit value right 163 | * @word: value to rotate 164 | * @shift: bits to roll 165 | */ 166 | static inline uint8_t ror8(uint8_t word, unsigned int shift) { 167 | return (word >> shift) | (word << ((8 - shift) & 7)); 168 | } 169 | 170 | /** 171 | * rol16 - rotate a 16-bit value left 172 | * @word: value to rotate 173 | * @shift: bits to roll 174 | */ 175 | static inline uint16_t rol16(uint16_t word, unsigned int shift) { 176 | return (word << shift) | (word >> ((16 - shift) & 15)); 177 | } 178 | 179 | /** 180 | * ror16 - rotate a 16-bit value right 181 | * @word: value to rotate 182 | * @shift: bits to roll 183 | */ 184 | static inline uint16_t ror16(uint16_t word, unsigned int shift) { 185 | return (word >> shift) | (word << ((16 - shift) & 15)); 186 | } 187 | 188 | /** 189 | * rol32 - rotate a 32-bit value left 190 | * @word: value to rotate 191 | * @shift: bits to roll 192 | */ 193 | static inline uint32_t rol32(uint32_t word, unsigned int shift) { 194 | return (word << shift) | (word >> ((32 - shift) & 31)); 195 | } 196 | 197 | /** 198 | * ror32 - rotate a 32-bit value right 199 | * @word: value to rotate 200 | * @shift: bits to roll 201 | */ 202 | static inline uint32_t ror32(uint32_t word, unsigned int shift) { 203 | return (word >> shift) | (word << ((32 - shift) & 31)); 204 | } 205 | 206 | /** 207 | * rol64 - rotate a 64-bit value left 208 | * @word: value to rotate 209 | * @shift: bits to roll 210 | */ 211 | static inline uint64_t rol64(uint64_t word, unsigned int shift) { 212 | return (word << shift) | (word >> ((64 - shift) & 63)); 213 | } 214 | 215 | /** 216 | * ror64 - rotate a 64-bit value right 217 | * @word: value to rotate 218 | * @shift: bits to roll 219 | */ 220 | static inline uint64_t ror64(uint64_t word, unsigned int shift) { 221 | return (word >> shift) | (word << ((64 - shift) & 63)); 222 | } 223 | 224 | /** 225 | * extract32: 226 | * @value: the value to extract the bit field from 227 | * @start: the lowest bit in the bit field (numbered from 0) 228 | * @length: the length of the bit field 229 | * 230 | * Extract from the 32 bit input @value the bit field specified by the 231 | * @start and @length parameters, and return it. The bit field must 232 | * lie entirely within the 32 bit word. It is valid to request that 233 | * all 32 bits are returned (ie @length 32 and @start 0). 234 | * 235 | * Returns: the value of the bit field extracted from the input value. 236 | */ 237 | static inline uint32_t extract32(uint32_t value, int start, int length) { 238 | assert(start >= 0 && length > 0 && length <= 32 - start); 239 | return (value >> start) & (~0U >> (32 - length)); 240 | } 241 | 242 | /** 243 | * extract64: 244 | * @value: the value to extract the bit field from 245 | * @start: the lowest bit in the bit field (numbered from 0) 246 | * @length: the length of the bit field 247 | * 248 | * Extract from the 64 bit input @value the bit field specified by the 249 | * @start and @length parameters, and return it. The bit field must 250 | * lie entirely within the 64 bit word. It is valid to request that 251 | * all 64 bits are returned (ie @length 64 and @start 0). 252 | * 253 | * Returns: the value of the bit field extracted from the input value. 254 | */ 255 | static inline uint64_t extract64(uint64_t value, int start, int length) { 256 | assert(start >= 0 && length > 0 && length <= 64 - start); 257 | return (value >> start) & (~0ULL >> (64 - length)); 258 | } 259 | 260 | /** 261 | * sextract32: 262 | * @value: the value to extract the bit field from 263 | * @start: the lowest bit in the bit field (numbered from 0) 264 | * @length: the length of the bit field 265 | * 266 | * Extract from the 32 bit input @value the bit field specified by the 267 | * @start and @length parameters, and return it, sign extended to 268 | * an int32_t (ie with the most significant bit of the field propagated 269 | * to all the upper bits of the return value). The bit field must lie 270 | * entirely within the 32 bit word. It is valid to request that 271 | * all 32 bits are returned (ie @length 32 and @start 0). 272 | * 273 | * Returns: the sign extended value of the bit field extracted from the 274 | * input value. 275 | */ 276 | static inline int32_t sextract32(uint32_t value, int start, int length) { 277 | assert(start >= 0 && length > 0 && length <= 32 - start); 278 | /* Note that this implementation relies on right shift of signed 279 | * integers being an arithmetic shift. 280 | */ 281 | return ((int32_t)(value << (32 - length - start))) >> (32 - length); 282 | } 283 | 284 | /** 285 | * sextract64: 286 | * @value: the value to extract the bit field from 287 | * @start: the lowest bit in the bit field (numbered from 0) 288 | * @length: the length of the bit field 289 | * 290 | * Extract from the 64 bit input @value the bit field specified by the 291 | * @start and @length parameters, and return it, sign extended to 292 | * an int64_t (ie with the most significant bit of the field propagated 293 | * to all the upper bits of the return value). The bit field must lie 294 | * entirely within the 64 bit word. It is valid to request that 295 | * all 64 bits are returned (ie @length 64 and @start 0). 296 | * 297 | * Returns: the sign extended value of the bit field extracted from the 298 | * input value. 299 | */ 300 | static inline int64_t sextract64(uint64_t value, int start, int length) { 301 | assert(start >= 0 && length > 0 && length <= 64 - start); 302 | /* Note that this implementation relies on right shift of signed 303 | * integers being an arithmetic shift. 304 | */ 305 | return ((int64_t)(value << (64 - length - start))) >> (64 - length); 306 | } 307 | 308 | /** 309 | * deposit32: 310 | * @value: initial value to insert bit field into 311 | * @start: the lowest bit in the bit field (numbered from 0) 312 | * @length: the length of the bit field 313 | * @fieldval: the value to insert into the bit field 314 | * 315 | * Deposit @fieldval into the 32 bit @value at the bit field specified 316 | * by the @start and @length parameters, and return the modified 317 | * @value. Bits of @value outside the bit field are not modified. 318 | * Bits of @fieldval above the least significant @length bits are 319 | * ignored. The bit field must lie entirely within the 32 bit word. 320 | * It is valid to request that all 32 bits are modified (ie @length 321 | * 32 and @start 0). 322 | * 323 | * Returns: the modified @value. 324 | */ 325 | static inline uint32_t deposit32(uint32_t value, int start, int length, uint32_t fieldval) { 326 | uint32_t mask; 327 | assert(start >= 0 && length > 0 && length <= 32 - start); 328 | mask = (~0U >> (32 - length)) << start; 329 | return (value & ~mask) | ((fieldval << start) & mask); 330 | } 331 | 332 | /** 333 | * deposit64: 334 | * @value: initial value to insert bit field into 335 | * @start: the lowest bit in the bit field (numbered from 0) 336 | * @length: the length of the bit field 337 | * @fieldval: the value to insert into the bit field 338 | * 339 | * Deposit @fieldval into the 64 bit @value at the bit field specified 340 | * by the @start and @length parameters, and return the modified 341 | * @value. Bits of @value outside the bit field are not modified. 342 | * Bits of @fieldval above the least significant @length bits are 343 | * ignored. The bit field must lie entirely within the 64 bit word. 344 | * It is valid to request that all 64 bits are modified (ie @length 345 | * 64 and @start 0). 346 | * 347 | * Returns: the modified @value. 348 | */ 349 | static inline uint64_t deposit64(uint64_t value, int start, int length, uint64_t fieldval) { 350 | uint64_t mask; 351 | assert(start >= 0 && length > 0 && length <= 64 - start); 352 | mask = (~0ULL >> (64 - length)) << start; 353 | return (value & ~mask) | ((fieldval << start) & mask); 354 | } 355 | 356 | #endif 357 | -------------------------------------------------------------------------------- /include/tcg/utils/cutils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Simple C functions to supplement the C library 3 | * 4 | * Copyright (c) 2006 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef _LIBTCG_CUTILS_H_ 26 | 27 | #define _LIBTCG_CUTILS_H_ 28 | 29 | #include 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | // strtosz() suffixes used to specify the default treatment of an 36 | // argument passed to strtosz() without an explicit suffix. 37 | // These should be defined using upper case characters in the range 38 | // A-Z, as strtosz() will use qemu_toupper() on the given argument 39 | // prior to comparison. 40 | #define STRTOSZ_DEFSUFFIX_TB 'T' 41 | #define STRTOSZ_DEFSUFFIX_GB 'G' 42 | #define STRTOSZ_DEFSUFFIX_MB 'M' 43 | #define STRTOSZ_DEFSUFFIX_KB 'K' 44 | #define STRTOSZ_DEFSUFFIX_B 'B' 45 | 46 | int64_t strtosz_suffix_unit(const char *nptr, char **end, const char default_suffix, int64_t unit); 47 | 48 | int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix); 49 | int64_t strtosz(const char *nptr, char **end); 50 | 51 | void pstrcpy(char *buf, int buf_size, const char *str); 52 | char *pstrcat(char *buf, int buf_size, const char *s); 53 | 54 | #ifdef __cplusplus 55 | } 56 | #endif 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /include/tcg/utils/host-utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Utility compute operations used by translated code. 3 | * 4 | * Copyright (c) 2007 Thiemo Seufer 5 | * Copyright (c) 2007 Jocelyn Mayer 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #ifndef HOST_UTILS_H 27 | #define HOST_UTILS_H 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #if defined(__x86_64__) 35 | static inline void mulu64(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b) { 36 | __uint128_t r = (__uint128_t) a * b; 37 | *plow = r; 38 | *phigh = r >> 64; 39 | } 40 | 41 | static inline void muls64(uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b) { 42 | __int128_t r = (__int128_t) a * b; 43 | *plow = r; 44 | *phigh = r >> 64; 45 | } 46 | 47 | /* compute with 96 bit intermediate result: (a*b)/c */ 48 | static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c) { 49 | return (__int128_t) a * b / c; 50 | } 51 | 52 | static inline int divu128(uint64_t *plow, uint64_t *phigh, uint64_t divisor) { 53 | if (divisor == 0) { 54 | return 1; 55 | } else { 56 | __uint128_t dividend = ((__uint128_t) *phigh << 64) | *plow; 57 | __uint128_t result = dividend / divisor; 58 | *plow = result; 59 | *phigh = dividend % divisor; 60 | return result > UINT64_MAX; 61 | } 62 | } 63 | 64 | static inline int divs128(int64_t *plow, int64_t *phigh, int64_t divisor) { 65 | if (divisor == 0) { 66 | return 1; 67 | } else { 68 | __int128_t dividend = ((__int128_t) *phigh << 64) | *plow; 69 | __int128_t result = dividend / divisor; 70 | *plow = result; 71 | *phigh = dividend % divisor; 72 | return result != *plow; 73 | } 74 | } 75 | #else 76 | /* Long integer helpers */ 77 | static inline void mul64(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b) { 78 | typedef union { 79 | uint64_t ll; 80 | struct { 81 | #ifdef HOST_WORDS_BIGENDIAN 82 | uint32_t high, low; 83 | #else 84 | uint32_t low, high; 85 | #endif 86 | } l; 87 | } LL; 88 | LL rl, rm, rn, rh, a0, b0; 89 | uint64_t c; 90 | 91 | a0.ll = a; 92 | b0.ll = b; 93 | 94 | rl.ll = (uint64_t) a0.l.low * b0.l.low; 95 | rm.ll = (uint64_t) a0.l.low * b0.l.high; 96 | rn.ll = (uint64_t) a0.l.high * b0.l.low; 97 | rh.ll = (uint64_t) a0.l.high * b0.l.high; 98 | 99 | c = (uint64_t) rl.l.high + rm.l.low + rn.l.low; 100 | rl.l.high = c; 101 | c >>= 32; 102 | c = c + rm.l.high + rn.l.high + rh.l.low; 103 | rh.l.low = c; 104 | rh.l.high += (uint32_t)(c >> 32); 105 | 106 | *plow = rl.ll; 107 | *phigh = rh.ll; 108 | } 109 | 110 | static void mulu64(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b) { 111 | mul64(plow, phigh, a, b); 112 | } 113 | 114 | static void muls64(uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b) { 115 | uint64_t rh; 116 | 117 | mul64(plow, &rh, a, b); 118 | 119 | /* Adjust for signs. */ 120 | if (b < 0) { 121 | rh -= a; 122 | } 123 | if (a < 0) { 124 | rh -= b; 125 | } 126 | *phigh = rh; 127 | } 128 | 129 | static int divu128(uint64_t *plow, uint64_t *phigh, uint64_t divisor) { 130 | uint64_t dhi = *phigh; 131 | uint64_t dlo = *plow; 132 | unsigned i; 133 | uint64_t carry = 0; 134 | 135 | if (divisor == 0) { 136 | return 1; 137 | } else if (dhi == 0) { 138 | *plow = dlo / divisor; 139 | *phigh = dlo % divisor; 140 | return 0; 141 | } else if (dhi > divisor) { 142 | return 1; 143 | } else { 144 | 145 | for (i = 0; i < 64; i++) { 146 | carry = dhi >> 63; 147 | dhi = (dhi << 1) | (dlo >> 63); 148 | if (carry || (dhi >= divisor)) { 149 | dhi -= divisor; 150 | carry = 1; 151 | } else { 152 | carry = 0; 153 | } 154 | dlo = (dlo << 1) | carry; 155 | } 156 | 157 | *plow = dlo; 158 | *phigh = dhi; 159 | return 0; 160 | } 161 | } 162 | 163 | static int divs128(int64_t *plow, int64_t *phigh, int64_t divisor) { 164 | int sgn_dvdnd = *phigh < 0; 165 | int sgn_divsr = divisor < 0; 166 | int overflow = 0; 167 | 168 | if (sgn_dvdnd) { 169 | *plow = ~(*plow); 170 | *phigh = ~(*phigh); 171 | if (*plow == (int64_t) -1) { 172 | *plow = 0; 173 | (*phigh)++; 174 | } else { 175 | (*plow)++; 176 | } 177 | } 178 | 179 | if (sgn_divsr) { 180 | divisor = 0 - divisor; 181 | } 182 | 183 | overflow = divu128((uint64_t *) plow, (uint64_t *) phigh, (uint64_t) divisor); 184 | 185 | if (sgn_dvdnd ^ sgn_divsr) { 186 | *plow = 0 - *plow; 187 | } 188 | 189 | if (!overflow) { 190 | if ((*plow < 0) ^ (sgn_dvdnd ^ sgn_divsr)) { 191 | overflow = 1; 192 | } 193 | } 194 | 195 | return overflow; 196 | } 197 | 198 | static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c) { 199 | union { 200 | uint64_t ll; 201 | struct { 202 | #ifdef HOST_WORDS_BIGENDIAN 203 | uint32_t high, low; 204 | #else 205 | uint32_t low, high; 206 | #endif 207 | } l; 208 | } u, res; 209 | uint64_t rl, rh; 210 | 211 | u.ll = a; 212 | rl = (uint64_t) u.l.low * (uint64_t) b; 213 | rh = (uint64_t) u.l.high * (uint64_t) b; 214 | rh += (rl >> 32); 215 | res.l.high = rh / c; 216 | res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c; 217 | return res.ll; 218 | } 219 | 220 | #endif 221 | 222 | /** 223 | * clz32 - count leading zeros in a 32-bit value. 224 | * @val: The value to search 225 | * 226 | * Returns 32 if the value is zero. Note that the GCC builtin is 227 | * undefined if the value is zero. 228 | */ 229 | static inline int clz32(uint32_t val) { 230 | return val ? __builtin_clz(val) : 32; 231 | } 232 | 233 | /** 234 | * clo32 - count leading ones in a 32-bit value. 235 | * @val: The value to search 236 | * 237 | * Returns 32 if the value is -1. 238 | */ 239 | static inline int clo32(uint32_t val) { 240 | return clz32(~val); 241 | } 242 | 243 | /** 244 | * clz64 - count leading zeros in a 64-bit value. 245 | * @val: The value to search 246 | * 247 | * Returns 64 if the value is zero. Note that the GCC builtin is 248 | * undefined if the value is zero. 249 | */ 250 | static inline int clz64(uint64_t val) { 251 | return val ? __builtin_clzll(val) : 64; 252 | } 253 | 254 | /** 255 | * clo64 - count leading ones in a 64-bit value. 256 | * @val: The value to search 257 | * 258 | * Returns 64 if the value is -1. 259 | */ 260 | static inline int clo64(uint64_t val) { 261 | return clz64(~val); 262 | } 263 | 264 | /** 265 | * ctz32 - count trailing zeros in a 32-bit value. 266 | * @val: The value to search 267 | * 268 | * Returns 32 if the value is zero. Note that the GCC builtin is 269 | * undefined if the value is zero. 270 | */ 271 | static inline int ctz32(uint32_t val) { 272 | return val ? __builtin_ctz(val) : 32; 273 | } 274 | 275 | /** 276 | * cto32 - count trailing ones in a 32-bit value. 277 | * @val: The value to search 278 | * 279 | * Returns 32 if the value is -1. 280 | */ 281 | static inline int cto32(uint32_t val) { 282 | return ctz32(~val); 283 | } 284 | 285 | /** 286 | * ctz64 - count trailing zeros in a 64-bit value. 287 | * @val: The value to search 288 | * 289 | * Returns 64 if the value is zero. Note that the GCC builtin is 290 | * undefined if the value is zero. 291 | */ 292 | static inline int ctz64(uint64_t val) { 293 | return val ? __builtin_ctzll(val) : 64; 294 | } 295 | 296 | /** 297 | * cto64 - count trailing ones in a 64-bit value. 298 | * @val: The value to search 299 | * 300 | * Returns 64 if the value is -1. 301 | */ 302 | static inline int cto64(uint64_t val) { 303 | return ctz64(~val); 304 | } 305 | 306 | /** 307 | * clrsb32 - count leading redundant sign bits in a 32-bit value. 308 | * @val: The value to search 309 | * 310 | * Returns the number of bits following the sign bit that are equal to it. 311 | * No special cases; output range is [0-31]. 312 | */ 313 | static inline int clrsb32(uint32_t val) { 314 | #if __has_builtin(__builtin_clrsb) || !defined(__clang__) 315 | return __builtin_clrsb(val); 316 | #else 317 | return clz32(val ^ ((int32_t) val >> 1)) - 1; 318 | #endif 319 | } 320 | 321 | /** 322 | * clrsb64 - count leading redundant sign bits in a 64-bit value. 323 | * @val: The value to search 324 | * 325 | * Returns the number of bits following the sign bit that are equal to it. 326 | * No special cases; output range is [0-63]. 327 | */ 328 | static inline int clrsb64(uint64_t val) { 329 | #if __has_builtin(__builtin_clrsbll) || !defined(__clang__) 330 | return __builtin_clrsbll(val); 331 | #else 332 | return clz64(val ^ ((int64_t) val >> 1)) - 1; 333 | #endif 334 | } 335 | 336 | /** 337 | * ctpop8 - count the population of one bits in an 8-bit value. 338 | * @val: The value to search 339 | */ 340 | static inline int ctpop8(uint8_t val) { 341 | return __builtin_popcount(val); 342 | } 343 | 344 | /** 345 | * ctpop16 - count the population of one bits in a 16-bit value. 346 | * @val: The value to search 347 | */ 348 | static inline int ctpop16(uint16_t val) { 349 | return __builtin_popcount(val); 350 | } 351 | 352 | /** 353 | * ctpop32 - count the population of one bits in a 32-bit value. 354 | * @val: The value to search 355 | */ 356 | static inline int ctpop32(uint32_t val) { 357 | return __builtin_popcount(val); 358 | } 359 | 360 | /** 361 | * ctpop64 - count the population of one bits in a 64-bit value. 362 | * @val: The value to search 363 | */ 364 | static inline int ctpop64(uint64_t val) { 365 | return __builtin_popcountll(val); 366 | } 367 | 368 | /** 369 | * revbit8 - reverse the bits in an 8-bit value. 370 | * @x: The value to modify. 371 | */ 372 | static inline uint8_t revbit8(uint8_t x) { 373 | /* Assign the correct nibble position. */ 374 | x = ((x & 0xf0) >> 4) | ((x & 0x0f) << 4); 375 | /* Assign the correct bit position. */ 376 | x = ((x & 0x88) >> 3) | ((x & 0x44) >> 1) | ((x & 0x22) << 1) | ((x & 0x11) << 3); 377 | return x; 378 | } 379 | 380 | /* Host type specific sizes of these routines. */ 381 | 382 | #if ULONG_MAX == UINT32_MAX 383 | #define clzl clz32 384 | #define ctzl ctz32 385 | #define clol clo32 386 | #define ctol cto32 387 | #define ctpopl ctpop32 388 | #define revbitl revbit32 389 | #elif ULONG_MAX == UINT64_MAX 390 | #define clzl clz64 391 | #define ctzl ctz64 392 | #define clol clo64 393 | #define ctol cto64 394 | #define ctpopl ctpop64 395 | #define revbitl revbit64 396 | #else 397 | #error Unknown sizeof long 398 | #endif 399 | 400 | static inline bool is_power_of_2(uint64_t value) { 401 | if (!value) { 402 | return false; 403 | } 404 | 405 | return !(value & (value - 1)); 406 | } 407 | 408 | /** 409 | * Return @value rounded down to the nearest power of two or zero. 410 | */ 411 | static inline uint64_t pow2floor(uint64_t value) { 412 | if (!value) { 413 | /* Avoid undefined shift by 64 */ 414 | return 0; 415 | } 416 | return 0x8000000000000000ull >> clz64(value); 417 | } 418 | 419 | /* 420 | * Return @value rounded up to the nearest power of two modulo 2^64. 421 | * This is *zero* for @value > 2^63, so be careful. 422 | */ 423 | static inline uint64_t pow2ceil(uint64_t value) { 424 | int n = clz64(value - 1); 425 | 426 | if (!n) { 427 | /* 428 | * @value - 1 has no leading zeroes, thus @value - 1 >= 2^63 429 | * Therefore, either @value == 0 or @value > 2^63. 430 | * If it's 0, return 1, else return 0. 431 | */ 432 | return !value; 433 | } 434 | return 0x8000000000000000ull >> (n - 1); 435 | } 436 | 437 | static inline uint32_t pow2roundup32(uint32_t x) { 438 | x |= (x >> 1); 439 | x |= (x >> 2); 440 | x |= (x >> 4); 441 | x |= (x >> 8); 442 | x |= (x >> 16); 443 | return x + 1; 444 | } 445 | 446 | /** 447 | * urshift - 128-bit Unsigned Right Shift. 448 | * @plow: in/out - lower 64-bit integer. 449 | * @phigh: in/out - higher 64-bit integer. 450 | * @shift: in - bytes to shift, between 0 and 127. 451 | * 452 | * Result is zero-extended and stored in plow/phigh, which are 453 | * input/output variables. Shift values outside the range will 454 | * be mod to 128. In other words, the caller is responsible to 455 | * verify/assert both the shift range and plow/phigh pointers. 456 | */ 457 | void urshift(uint64_t *plow, uint64_t *phigh, int32_t shift); 458 | 459 | /** 460 | * ulshift - 128-bit Unsigned Left Shift. 461 | * @plow: in/out - lower 64-bit integer. 462 | * @phigh: in/out - higher 64-bit integer. 463 | * @shift: in - bytes to shift, between 0 and 127. 464 | * @overflow: out - true if any 1-bit is shifted out. 465 | * 466 | * Result is zero-extended and stored in plow/phigh, which are 467 | * input/output variables. Shift values outside the range will 468 | * be mod to 128. In other words, the caller is responsible to 469 | * verify/assert both the shift range and plow/phigh pointers. 470 | */ 471 | void ulshift(uint64_t *plow, uint64_t *phigh, int32_t shift, bool *overflow); 472 | 473 | #endif 474 | -------------------------------------------------------------------------------- /include/tcg/utils/log.h: -------------------------------------------------------------------------------- 1 | /// Copyright (C) 2003 Fabrice Bellard 2 | /// Copyright (C) 2016-2019 Cyberhaven 3 | /// Copyrights of all contributions belong to their respective owners. 4 | /// 5 | /// This library is free software; you can redistribute it and/or 6 | /// modify it under the terms of the GNU Library General Public 7 | /// License as published by the Free Software Foundation; either 8 | /// version 2 of the License, or (at your option) any later version. 9 | /// 10 | /// This library is distributed in the hope that it will be useful, 11 | /// but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | /// Library General Public License for more details. 14 | /// 15 | /// You should have received a copy of the GNU Library General Public 16 | /// License along with this library; if not, see . 17 | 18 | #ifndef TCG_LOG_H 19 | 20 | #define TCG_LOG_H 21 | 22 | #include 23 | 24 | typedef int (*fprintf_function)(FILE *f, const char *fmt, ...); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /include/tcg/utils/mutex.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 Cyberhaven 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #ifndef _TCG_MUTEX_H_ 22 | 23 | #define _TCG_MUTEX_H_ 24 | 25 | #include 26 | 27 | typedef struct _mutex_t { pthread_mutex_t mutex; } mutex_t; 28 | 29 | static inline void mutex_init(mutex_t *m) { 30 | int ret = pthread_mutex_init(&m->mutex, NULL); 31 | if (ret < 0) { 32 | abort(); 33 | } 34 | } 35 | 36 | static inline void mutex_lock(mutex_t *m) { 37 | pthread_mutex_lock(&m->mutex); 38 | } 39 | 40 | static inline void mutex_unlock(mutex_t *m) { 41 | pthread_mutex_unlock(&m->mutex); 42 | } 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /include/tcg/utils/osdep.h: -------------------------------------------------------------------------------- 1 | /// Copyright (C) 2003 Fabrice Bellard 2 | /// Copyright (C) 2016 Cyberhaven 3 | /// Copyrights of all contributions belong to their respective owners. 4 | /// 5 | /// This library is free software; you can redistribute it and/or 6 | /// modify it under the terms of the GNU Library General Public 7 | /// License as published by the Free Software Foundation; either 8 | /// version 2 of the License, or (at your option) any later version. 9 | /// 10 | /// This library is distributed in the hope that it will be useful, 11 | /// but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | /// Library General Public License for more details. 14 | /// 15 | /// You should have received a copy of the GNU Library General Public 16 | /// License along with this library; if not, see . 17 | 18 | #ifndef TCG_OSDEP_H 19 | #define TCG_OSDEP_H 20 | 21 | #include 22 | #include 23 | #ifdef __OpenBSD__ 24 | #include 25 | #include 26 | #endif 27 | 28 | #include 29 | 30 | #ifndef glue 31 | #define xglue(x, y) x##y 32 | #define glue(x, y) xglue(x, y) 33 | #define stringify(s) tostring(s) 34 | #define tostring(s) #s 35 | #endif 36 | 37 | #ifndef container_of 38 | #define container_of(ptr, type, member) \ 39 | ({ \ 40 | const typeof(((type *) 0)->member) *__mptr = (ptr); \ 41 | (type *) ((char *) __mptr - offsetof(type, member)); \ 42 | }) 43 | #endif 44 | 45 | /* Convert from a base type to a parent type, with compile time checking. */ 46 | #ifdef __GNUC__ 47 | #define DO_UPCAST(type, field, dev) \ 48 | (__extension__({ \ 49 | char __attribute__((unused)) offset_must_be_zero[-offsetof(type, field)]; \ 50 | container_of(dev, type, field); \ 51 | })) 52 | #else 53 | #define DO_UPCAST(type, field, dev) container_of(dev, type, field) 54 | #endif 55 | 56 | #define typeof_field(type, field) typeof(((type *) 0)->field) 57 | #define type_check(t1, t2) ((t1 *) 0 - (t2 *) 0) 58 | 59 | #ifndef MIN 60 | #define MIN(a, b) (((a) < (b)) ? (a) : (b)) 61 | #endif 62 | #ifndef MAX 63 | #define MAX(a, b) (((a) > (b)) ? (a) : (b)) 64 | #endif 65 | 66 | #ifndef ARRAY_SIZE 67 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 68 | #endif 69 | 70 | #define likely(x) __builtin_expect(!!(x), 1) 71 | #define unlikely(x) __builtin_expect(!!(x), 0) 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /include/tcg/utils/rounding.h: -------------------------------------------------------------------------------- 1 | // Helper macros for pointer arithmetic. 2 | // 3 | // Contains code derived from these sources: 4 | // https://github.com/lattera/glibc/blob/master/include/libc-pointer-arith.h 5 | 6 | // Copyright (C) 2012-2019 Free Software Foundation, Inc. 7 | // This file is part of the GNU C Library. 8 | // 9 | // The GNU C Library is free software; you can redistribute it and/or 10 | // modify it under the terms of the GNU Lesser General Public 11 | // License as published by the Free Software Foundation; either 12 | // version 2.1 of the License, or (at your option) any later version. 13 | // The GNU C 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 GNU C Library; if not, see 20 | // . 21 | 22 | #ifndef LIBTCG_ROUNDING 23 | 24 | #define LIBTCG_ROUNDING 25 | 26 | // Round number down to multiple 27 | #define ALIGN_DOWN(base, size) ((base) / (size) * (size)) 28 | 29 | // Align a value by rounding up to closest size. 30 | // E.g. Using size of 4096, we get this behavior: 31 | // {4095, 4096, 4097} = {4096, 4096, 8192}. 32 | // Note: The size argument has side effects (expanded multiple times). 33 | #define ALIGN_UP(base, size) ALIGN_DOWN((base) + (size) -1, (base)) 34 | 35 | // Same as ALIGN_DOWN(), but automatically casts when base is a pointer 36 | #define ALIGN_PTR_DOWN(base, size) ((typeof(base)) ALIGN_DOWN((uintptr_t)(base), (size))) 37 | 38 | // Same as ALIGN_UP(), but automatically casts when base is a pointer 39 | #define ALIGN_PTR_UP(base, size) ((typeof(base)) ALIGN_UP((uintptr_t)(base), (size))) 40 | 41 | // Round number up to multiple. 42 | // Requires that size be a power of 2. 43 | #ifndef ROUND_UP 44 | #define ROUND_UP(base, size) (((base) + (size) -1) & -(size)) 45 | #endif 46 | 47 | #ifndef DIV_ROUND_UP 48 | #define DIV_ROUND_UP(base, size) (((base) + (size) -1) / (size)) 49 | #endif 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017 Cyberhaven 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy 4 | # of this software and associated documentation files (the "Software"), to deal 5 | # in the Software without restriction, including without limitation the rights 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | # copies of the Software, and to permit persons to whom the Software is 8 | # furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in all 11 | # copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | # SOFTWARE. 20 | 21 | set (TCG_SOURCES) 22 | list (APPEND TCG_SOURCES cutils.c tcg.c tcg-common.c tcg-op.c optimize.c tcg-op-gvec.c tcg-runtime-gvec.c tcg-op-vec.c) 23 | 24 | if (WITH_SYMBEX) 25 | list(APPEND TCG_SOURCES tcg-llvm.cpp) 26 | endif (WITH_SYMBEX) 27 | 28 | add_library(tcg ${TCG_SOURCES}) 29 | 30 | set (COMMON_FLAGS "-Wall -fPIC -Werror -Wno-zero-length-array -Wno-mismatched-tags -Wno-initializer-overrides") 31 | set (COMMON_FLAGS "${COMMON_FLAGS} -DCONFIG_SOFTMMU -DCPU_TEMP_BUF_NLONGS=128") 32 | 33 | if (WITH_SYMBEX) 34 | set (COMMON_FLAGS "${COMMON_FLAGS} -DCONFIG_SYMBEX -DTCG_ENABLE_MEM_TRACING") 35 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 36 | endif (WITH_SYMBEX) 37 | 38 | if (WITH_SYMBEX_MP) 39 | set (COMMON_FLAGS "${COMMON_FLAGS} -DCONFIG_SYMBEX_MP") 40 | endif (WITH_SYMBEX_MP) 41 | 42 | if (TARGET_X86_64) 43 | set (COMMON_FLAGS "${COMMON_FLAGS} -DTARGET_X86_64") 44 | endif (TARGET_X86_64) 45 | 46 | if (TARGET_LONG_BITS) 47 | set (COMMON_FLAGS "${COMMON_FLAGS} -DTARGET_LONG_BITS=${TARGET_LONG_BITS}") 48 | else (TARGET_LONG_BITS) 49 | MESSAGE (FATAL_ERROR "Please specify -DTARGET_LONG_BITS") 50 | endif (TARGET_LONG_BITS) 51 | 52 | if (TARGET_INSN_START_EXTRA_WORDS) 53 | set (COMMON_FLAGS "${COMMON_FLAGS} -DTARGET_INSN_START_EXTRA_WORDS=${TARGET_INSN_START_EXTRA_WORDS}") 54 | else (TARGET_INSN_START_EXTRA_WORDS) 55 | MESSAGE (FATAL_ERROR "Please specify -DTARGET_INSN_START_EXTRA_WORDS") 56 | endif (TARGET_INSN_START_EXTRA_WORDS) 57 | 58 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COMMON_FLAGS}") 59 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMMON_FLAGS}") 60 | 61 | MESSAGE( STATUS "CMAKE_C_FLAGS: " ${CMAKE_C_FLAGS} ) 62 | MESSAGE( STATUS "WITH_SYMBEX: " ${WITH_SYMBEX} ) 63 | MESSAGE( STATUS "WITH_SYMBEX_MP: " ${WITH_SYMBEX_MP} ) 64 | -------------------------------------------------------------------------------- /src/cutils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Simple C functions to supplement the C library 3 | * 4 | * Copyright (c) 2006 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | 35 | static int64_t suffix_mul(char suffix, int64_t unit) { 36 | switch (toupper(suffix)) { 37 | case STRTOSZ_DEFSUFFIX_B: 38 | return 1; 39 | case STRTOSZ_DEFSUFFIX_KB: 40 | return unit; 41 | case STRTOSZ_DEFSUFFIX_MB: 42 | return unit * unit; 43 | case STRTOSZ_DEFSUFFIX_GB: 44 | return unit * unit * unit; 45 | case STRTOSZ_DEFSUFFIX_TB: 46 | return unit * unit * unit * unit; 47 | } 48 | return -1; 49 | } 50 | 51 | /// 52 | /// \brief strtosz_suffix_unit Convert string to bytes, allowing either B/b for bytes, K/k for KB, 53 | /// M/m for MB, G/g for GB or T/t for TB. End pointer will be returned 54 | /// in *end, if not NULL. 55 | /// 56 | /// \param nptr 57 | /// \param end 58 | /// \param default_suffix 59 | /// \param unit 60 | /// \return -1 on error 61 | /// 62 | int64_t strtosz_suffix_unit(const char *nptr, char **end, const char default_suffix, int64_t unit) { 63 | int64_t retval = -1; 64 | char *endptr; 65 | unsigned char c; 66 | int mul_required = 0; 67 | double val, mul, integral, fraction; 68 | 69 | errno = 0; 70 | val = strtod(nptr, &endptr); 71 | if (__builtin_isnan(val) || endptr == nptr || errno != 0) { 72 | goto fail; 73 | } 74 | fraction = modf(val, &integral); 75 | if (fraction != 0) { 76 | mul_required = 1; 77 | } 78 | c = *endptr; 79 | mul = suffix_mul(c, unit); 80 | if (mul >= 0) { 81 | endptr++; 82 | } else { 83 | mul = suffix_mul(default_suffix, unit); 84 | assert(mul >= 0); 85 | } 86 | if (mul == 1 && mul_required) { 87 | goto fail; 88 | } 89 | if ((val * mul >= INT64_MAX) || val < 0) { 90 | goto fail; 91 | } 92 | retval = val * mul; 93 | 94 | fail: 95 | if (end) { 96 | *end = endptr; 97 | } 98 | 99 | return retval; 100 | } 101 | 102 | int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix) { 103 | return strtosz_suffix_unit(nptr, end, default_suffix, 1024); 104 | } 105 | 106 | int64_t strtosz(const char *nptr, char **end) { 107 | return strtosz_suffix(nptr, end, STRTOSZ_DEFSUFFIX_MB); 108 | } 109 | 110 | void pstrcpy(char *buf, int buf_size, const char *str) { 111 | int c; 112 | char *q = buf; 113 | 114 | if (buf_size <= 0) 115 | return; 116 | 117 | for (;;) { 118 | c = *str++; 119 | if (c == 0 || q >= buf + buf_size - 1) 120 | break; 121 | *q++ = c; 122 | } 123 | *q = '\0'; 124 | } 125 | 126 | /* strcat and truncate. */ 127 | char *pstrcat(char *buf, int buf_size, const char *s) { 128 | int len; 129 | len = strlen(buf); 130 | if (len < buf_size) 131 | pstrcpy(buf + len, buf_size - len, s); 132 | return buf; 133 | } 134 | -------------------------------------------------------------------------------- /src/tcg-common.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Tiny Code Generator for QEMU 3 | * 4 | * Copyright (c) 2008 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #include 26 | #include 27 | 28 | #if defined(CONFIG_TCG_INTERPRETER) 29 | uintptr_t tci_tb_ptr; 30 | #endif 31 | 32 | TCGOpDef tcg_op_defs[] = { 33 | #define DEF(s, oargs, iargs, cargs, flags) {#s, oargs, iargs, cargs, iargs + oargs + cargs, flags}, 34 | #include 35 | #undef DEF 36 | }; 37 | const size_t tcg_op_defs_max = ARRAY_SIZE(tcg_op_defs); 38 | -------------------------------------------------------------------------------- /src/tcg-gvec-desc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Generic vector operation descriptor 3 | * 4 | * Copyright (c) 2018 Linaro 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | /* ??? These bit widths are set for ARM SVE, maxing out at 256 byte vectors. */ 21 | #define SIMD_OPRSZ_SHIFT 0 22 | #define SIMD_OPRSZ_BITS 5 23 | 24 | #define SIMD_MAXSZ_SHIFT (SIMD_OPRSZ_SHIFT + SIMD_OPRSZ_BITS) 25 | #define SIMD_MAXSZ_BITS 5 26 | 27 | #define SIMD_DATA_SHIFT (SIMD_MAXSZ_SHIFT + SIMD_MAXSZ_BITS) 28 | #define SIMD_DATA_BITS (32 - SIMD_DATA_SHIFT) 29 | 30 | /* Create a descriptor from components. */ 31 | uint32_t simd_desc(uint32_t oprsz, uint32_t maxsz, int32_t data); 32 | 33 | /* Extract the operation size from a descriptor. */ 34 | static inline intptr_t simd_oprsz(uint32_t desc) { 35 | return (extract32(desc, SIMD_OPRSZ_SHIFT, SIMD_OPRSZ_BITS) + 1) * 8; 36 | } 37 | 38 | /* Extract the max vector size from a descriptor. */ 39 | static inline intptr_t simd_maxsz(uint32_t desc) { 40 | return (extract32(desc, SIMD_MAXSZ_SHIFT, SIMD_MAXSZ_BITS) + 1) * 8; 41 | } 42 | 43 | /* Extract the operation-specific data from a descriptor. */ 44 | static inline int32_t simd_data(uint32_t desc) { 45 | return sextract32(desc, SIMD_DATA_SHIFT, SIMD_DATA_BITS); 46 | } 47 | -------------------------------------------------------------------------------- /src/tcg-ldst.inc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * TCG Backend Data: load-store optimization only. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | typedef struct TCGLabelQemuLdst { 24 | bool is_ld; /* qemu_ld: true, qemu_st: false */ 25 | TCGMemOpIdx oi; 26 | TCGType type; /* result type of a load */ 27 | TCGReg addrlo_reg; /* reg index for low word of guest virtual addr */ 28 | TCGReg addrhi_reg; /* reg index for high word of guest virtual addr */ 29 | TCGReg datalo_reg; /* reg index for low word to be loaded or stored */ 30 | TCGReg datahi_reg; /* reg index for high word to be loaded or stored */ 31 | tcg_insn_unit *raddr; /* gen code addr of the next IR of qemu_ld/st IR */ 32 | tcg_insn_unit *label_ptr[2]; /* label pointers to be updated */ 33 | QSIMPLEQ_ENTRY(TCGLabelQemuLdst) next; 34 | } TCGLabelQemuLdst; 35 | 36 | /* 37 | * Generate TB finalization at the end of block 38 | */ 39 | 40 | static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l); 41 | static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l); 42 | 43 | static bool tcg_out_ldst_finalize(TCGContext *s) { 44 | TCGLabelQemuLdst *lb; 45 | 46 | /* qemu_ld/st slow paths */ 47 | QSIMPLEQ_FOREACH(lb, &s->ldst_labels, next) { 48 | if (lb->is_ld) { 49 | tcg_out_qemu_ld_slow_path(s, lb); 50 | } else { 51 | tcg_out_qemu_st_slow_path(s, lb); 52 | } 53 | 54 | /* Test for (pending) buffer overflow. The assumption is that any 55 | one operation beginning below the high water mark cannot overrun 56 | the buffer completely. Thus we can test for overflow after 57 | generating code without having to check during generation. */ 58 | if (unlikely((void *) s->code_ptr > s->code_gen_highwater)) { 59 | return false; 60 | } 61 | } 62 | return true; 63 | } 64 | 65 | /* 66 | * Allocate a new TCGLabelQemuLdst entry. 67 | */ 68 | 69 | static inline TCGLabelQemuLdst *new_ldst_label(TCGContext *s) { 70 | TCGLabelQemuLdst *l = tcg_malloc(sizeof(*l)); 71 | 72 | QSIMPLEQ_INSERT_TAIL(&s->ldst_labels, l, next); 73 | 74 | return l; 75 | } 76 | -------------------------------------------------------------------------------- /src/tcg-op-gvec.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Generic vector operation expansion 3 | * 4 | * Copyright (c) 2018 Linaro 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | /* 21 | * "Generic" vectors. All operands are given as offsets from ENV, 22 | * and therefore cannot also be allocated via tcg_global_mem_new_*. 23 | * OPRSZ is the byte size of the vector upon which the operation is performed. 24 | * MAXSZ is the byte size of the full vector; bytes beyond OPSZ are cleared. 25 | * 26 | * All sizes must be 8 or any multiple of 16. 27 | * When OPRSZ is 8, the alignment may be 8, otherwise must be 16. 28 | * Operands may completely, but not partially, overlap. 29 | */ 30 | 31 | /* Expand a call to a gvec-style helper, with pointers to two vector 32 | operands, and a descriptor (see tcg-gvec-desc.h). */ 33 | typedef void gen_helper_gvec_2(TCGv_ptr, TCGv_ptr, TCGv_i32); 34 | void tcg_gen_gvec_2_ool(uint32_t dofs, uint32_t aofs, uint32_t oprsz, uint32_t maxsz, int32_t data, 35 | gen_helper_gvec_2 *fn); 36 | 37 | /* Similarly, passing an extra data value. */ 38 | typedef void gen_helper_gvec_2i(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv_i32); 39 | void tcg_gen_gvec_2i_ool(uint32_t dofs, uint32_t aofs, TCGv_i64 c, uint32_t oprsz, uint32_t maxsz, int32_t data, 40 | gen_helper_gvec_2i *fn); 41 | 42 | /* Similarly, passing an extra pointer (e.g. env or float_status). */ 43 | typedef void gen_helper_gvec_2_ptr(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32); 44 | void tcg_gen_gvec_2_ptr(uint32_t dofs, uint32_t aofs, TCGv_ptr ptr, uint32_t oprsz, uint32_t maxsz, int32_t data, 45 | gen_helper_gvec_2_ptr *fn); 46 | 47 | /* Similarly, with three vector operands. */ 48 | typedef void gen_helper_gvec_3(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32); 49 | void tcg_gen_gvec_3_ool(uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t oprsz, uint32_t maxsz, int32_t data, 50 | gen_helper_gvec_3 *fn); 51 | 52 | /* Similarly, with four vector operands. */ 53 | typedef void gen_helper_gvec_4(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32); 54 | void tcg_gen_gvec_4_ool(uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t cofs, uint32_t oprsz, uint32_t maxsz, 55 | int32_t data, gen_helper_gvec_4 *fn); 56 | 57 | /* Similarly, with five vector operands. */ 58 | typedef void gen_helper_gvec_5(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32); 59 | void tcg_gen_gvec_5_ool(uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t cofs, uint32_t xofs, uint32_t oprsz, 60 | uint32_t maxsz, int32_t data, gen_helper_gvec_5 *fn); 61 | 62 | typedef void gen_helper_gvec_3_ptr(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32); 63 | void tcg_gen_gvec_3_ptr(uint32_t dofs, uint32_t aofs, uint32_t bofs, TCGv_ptr ptr, uint32_t oprsz, uint32_t maxsz, 64 | int32_t data, gen_helper_gvec_3_ptr *fn); 65 | 66 | typedef void gen_helper_gvec_4_ptr(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32); 67 | void tcg_gen_gvec_4_ptr(uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t cofs, TCGv_ptr ptr, uint32_t oprsz, 68 | uint32_t maxsz, int32_t data, gen_helper_gvec_4_ptr *fn); 69 | 70 | /* Expand a gvec operation. Either inline or out-of-line depending on 71 | the actual vector size and the operations supported by the host. */ 72 | typedef struct { 73 | /* Expand inline as a 64-bit or 32-bit integer. 74 | Only one of these will be non-NULL. */ 75 | void (*fni8)(TCGv_i64, TCGv_i64); 76 | void (*fni4)(TCGv_i32, TCGv_i32); 77 | /* Expand inline with a host vector type. */ 78 | void (*fniv)(unsigned, TCGv_vec, TCGv_vec); 79 | /* Expand out-of-line helper w/descriptor. */ 80 | gen_helper_gvec_2 *fno; 81 | /* The opcode, if any, to which this corresponds. */ 82 | TCGOpcode opc; 83 | /* The data argument to the out-of-line helper. */ 84 | int32_t data; 85 | /* The vector element size, if applicable. */ 86 | uint8_t vece; 87 | /* Prefer i64 to v64. */ 88 | bool prefer_i64; 89 | } GVecGen2; 90 | 91 | typedef struct { 92 | /* Expand inline as a 64-bit or 32-bit integer. 93 | Only one of these will be non-NULL. */ 94 | void (*fni8)(TCGv_i64, TCGv_i64, int64_t); 95 | void (*fni4)(TCGv_i32, TCGv_i32, int32_t); 96 | /* Expand inline with a host vector type. */ 97 | void (*fniv)(unsigned, TCGv_vec, TCGv_vec, int64_t); 98 | /* Expand out-of-line helper w/descriptor, data in descriptor. */ 99 | gen_helper_gvec_2 *fno; 100 | /* Expand out-of-line helper w/descriptor, data as argument. */ 101 | gen_helper_gvec_2i *fnoi; 102 | /* The opcode, if any, to which this corresponds. */ 103 | TCGOpcode opc; 104 | /* The vector element size, if applicable. */ 105 | uint8_t vece; 106 | /* Prefer i64 to v64. */ 107 | bool prefer_i64; 108 | /* Load dest as a 3rd source operand. */ 109 | bool load_dest; 110 | } GVecGen2i; 111 | 112 | typedef struct { 113 | /* Expand inline as a 64-bit or 32-bit integer. 114 | Only one of these will be non-NULL. */ 115 | void (*fni8)(TCGv_i64, TCGv_i64, TCGv_i64); 116 | void (*fni4)(TCGv_i32, TCGv_i32, TCGv_i32); 117 | /* Expand inline with a host vector type. */ 118 | void (*fniv)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec); 119 | /* Expand out-of-line helper w/descriptor. */ 120 | gen_helper_gvec_2i *fno; 121 | /* The opcode, if any, to which this corresponds. */ 122 | TCGOpcode opc; 123 | /* The data argument to the out-of-line helper. */ 124 | uint32_t data; 125 | /* The vector element size, if applicable. */ 126 | uint8_t vece; 127 | /* Prefer i64 to v64. */ 128 | bool prefer_i64; 129 | /* Load scalar as 1st source operand. */ 130 | bool scalar_first; 131 | } GVecGen2s; 132 | 133 | typedef struct { 134 | /* Expand inline as a 64-bit or 32-bit integer. 135 | Only one of these will be non-NULL. */ 136 | void (*fni8)(TCGv_i64, TCGv_i64, TCGv_i64); 137 | void (*fni4)(TCGv_i32, TCGv_i32, TCGv_i32); 138 | /* Expand inline with a host vector type. */ 139 | void (*fniv)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec); 140 | /* Expand out-of-line helper w/descriptor. */ 141 | gen_helper_gvec_3 *fno; 142 | /* The opcode, if any, to which this corresponds. */ 143 | TCGOpcode opc; 144 | /* The data argument to the out-of-line helper. */ 145 | int32_t data; 146 | /* The vector element size, if applicable. */ 147 | uint8_t vece; 148 | /* Prefer i64 to v64. */ 149 | bool prefer_i64; 150 | /* Load dest as a 3rd source operand. */ 151 | bool load_dest; 152 | } GVecGen3; 153 | 154 | typedef struct { 155 | /* Expand inline as a 64-bit or 32-bit integer. 156 | Only one of these will be non-NULL. */ 157 | void (*fni8)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64); 158 | void (*fni4)(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32); 159 | /* Expand inline with a host vector type. */ 160 | void (*fniv)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec, TCGv_vec); 161 | /* Expand out-of-line helper w/descriptor. */ 162 | gen_helper_gvec_4 *fno; 163 | /* The opcode, if any, to which this corresponds. */ 164 | TCGOpcode opc; 165 | /* The data argument to the out-of-line helper. */ 166 | int32_t data; 167 | /* The vector element size, if applicable. */ 168 | uint8_t vece; 169 | /* Prefer i64 to v64. */ 170 | bool prefer_i64; 171 | /* Write aofs as a 2nd dest operand. */ 172 | bool write_aofs; 173 | } GVecGen4; 174 | 175 | void tcg_gen_gvec_2(uint32_t dofs, uint32_t aofs, uint32_t oprsz, uint32_t maxsz, const GVecGen2 *); 176 | void tcg_gen_gvec_2i(uint32_t dofs, uint32_t aofs, uint32_t oprsz, uint32_t maxsz, int64_t c, const GVecGen2i *); 177 | void tcg_gen_gvec_2s(uint32_t dofs, uint32_t aofs, uint32_t oprsz, uint32_t maxsz, TCGv_i64 c, const GVecGen2s *); 178 | void tcg_gen_gvec_3(uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t oprsz, uint32_t maxsz, const GVecGen3 *); 179 | void tcg_gen_gvec_4(uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t cofs, uint32_t oprsz, uint32_t maxsz, 180 | const GVecGen4 *); 181 | 182 | /* Expand a specific vector operation. */ 183 | 184 | void tcg_gen_gvec_mov(unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t oprsz, uint32_t maxsz); 185 | void tcg_gen_gvec_not(unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t oprsz, uint32_t maxsz); 186 | void tcg_gen_gvec_neg(unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t oprsz, uint32_t maxsz); 187 | 188 | void tcg_gen_gvec_add(unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t oprsz, uint32_t maxsz); 189 | void tcg_gen_gvec_sub(unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t oprsz, uint32_t maxsz); 190 | void tcg_gen_gvec_mul(unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t oprsz, uint32_t maxsz); 191 | 192 | void tcg_gen_gvec_addi(unsigned vece, uint32_t dofs, uint32_t aofs, int64_t c, uint32_t oprsz, uint32_t maxsz); 193 | void tcg_gen_gvec_muli(unsigned vece, uint32_t dofs, uint32_t aofs, int64_t c, uint32_t oprsz, uint32_t maxsz); 194 | 195 | void tcg_gen_gvec_adds(unsigned vece, uint32_t dofs, uint32_t aofs, TCGv_i64 c, uint32_t oprsz, uint32_t maxsz); 196 | void tcg_gen_gvec_subs(unsigned vece, uint32_t dofs, uint32_t aofs, TCGv_i64 c, uint32_t oprsz, uint32_t maxsz); 197 | void tcg_gen_gvec_muls(unsigned vece, uint32_t dofs, uint32_t aofs, TCGv_i64 c, uint32_t oprsz, uint32_t maxsz); 198 | 199 | /* Saturated arithmetic. */ 200 | void tcg_gen_gvec_ssadd(unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t oprsz, uint32_t maxsz); 201 | void tcg_gen_gvec_sssub(unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t oprsz, uint32_t maxsz); 202 | void tcg_gen_gvec_usadd(unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t oprsz, uint32_t maxsz); 203 | void tcg_gen_gvec_ussub(unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t oprsz, uint32_t maxsz); 204 | 205 | /* Min/max. */ 206 | void tcg_gen_gvec_smin(unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t oprsz, uint32_t maxsz); 207 | void tcg_gen_gvec_umin(unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t oprsz, uint32_t maxsz); 208 | void tcg_gen_gvec_smax(unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t oprsz, uint32_t maxsz); 209 | void tcg_gen_gvec_umax(unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t oprsz, uint32_t maxsz); 210 | 211 | void tcg_gen_gvec_and(unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t oprsz, uint32_t maxsz); 212 | void tcg_gen_gvec_or(unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t oprsz, uint32_t maxsz); 213 | void tcg_gen_gvec_xor(unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t oprsz, uint32_t maxsz); 214 | void tcg_gen_gvec_andc(unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t oprsz, uint32_t maxsz); 215 | void tcg_gen_gvec_orc(unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t oprsz, uint32_t maxsz); 216 | void tcg_gen_gvec_nand(unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t oprsz, uint32_t maxsz); 217 | void tcg_gen_gvec_nor(unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t oprsz, uint32_t maxsz); 218 | void tcg_gen_gvec_eqv(unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t oprsz, uint32_t maxsz); 219 | 220 | void tcg_gen_gvec_andi(unsigned vece, uint32_t dofs, uint32_t aofs, int64_t c, uint32_t oprsz, uint32_t maxsz); 221 | void tcg_gen_gvec_xori(unsigned vece, uint32_t dofs, uint32_t aofs, int64_t c, uint32_t oprsz, uint32_t maxsz); 222 | void tcg_gen_gvec_ori(unsigned vece, uint32_t dofs, uint32_t aofs, int64_t c, uint32_t oprsz, uint32_t maxsz); 223 | 224 | void tcg_gen_gvec_ands(unsigned vece, uint32_t dofs, uint32_t aofs, TCGv_i64 c, uint32_t oprsz, uint32_t maxsz); 225 | void tcg_gen_gvec_xors(unsigned vece, uint32_t dofs, uint32_t aofs, TCGv_i64 c, uint32_t oprsz, uint32_t maxsz); 226 | void tcg_gen_gvec_ors(unsigned vece, uint32_t dofs, uint32_t aofs, TCGv_i64 c, uint32_t oprsz, uint32_t maxsz); 227 | 228 | void tcg_gen_gvec_dup_mem(unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t s, uint32_t m); 229 | void tcg_gen_gvec_dup_i32(unsigned vece, uint32_t dofs, uint32_t s, uint32_t m, TCGv_i32); 230 | void tcg_gen_gvec_dup_i64(unsigned vece, uint32_t dofs, uint32_t s, uint32_t m, TCGv_i64); 231 | 232 | void tcg_gen_gvec_dup8i(uint32_t dofs, uint32_t s, uint32_t m, uint8_t x); 233 | void tcg_gen_gvec_dup16i(uint32_t dofs, uint32_t s, uint32_t m, uint16_t x); 234 | void tcg_gen_gvec_dup32i(uint32_t dofs, uint32_t s, uint32_t m, uint32_t x); 235 | void tcg_gen_gvec_dup64i(uint32_t dofs, uint32_t s, uint32_t m, uint64_t x); 236 | 237 | void tcg_gen_gvec_shli(unsigned vece, uint32_t dofs, uint32_t aofs, int64_t shift, uint32_t oprsz, uint32_t maxsz); 238 | void tcg_gen_gvec_shri(unsigned vece, uint32_t dofs, uint32_t aofs, int64_t shift, uint32_t oprsz, uint32_t maxsz); 239 | void tcg_gen_gvec_sari(unsigned vece, uint32_t dofs, uint32_t aofs, int64_t shift, uint32_t oprsz, uint32_t maxsz); 240 | 241 | void tcg_gen_gvec_cmp(TCGCond cond, unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t oprsz, 242 | uint32_t maxsz); 243 | 244 | /* 245 | * 64-bit vector operations. Use these when the register has been allocated 246 | * with tcg_global_mem_new_i64, and so we cannot also address it via pointer. 247 | * OPRSZ = MAXSZ = 8. 248 | */ 249 | 250 | void tcg_gen_vec_neg8_i64(TCGv_i64 d, TCGv_i64 a); 251 | void tcg_gen_vec_neg16_i64(TCGv_i64 d, TCGv_i64 a); 252 | void tcg_gen_vec_neg32_i64(TCGv_i64 d, TCGv_i64 a); 253 | 254 | void tcg_gen_vec_add8_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b); 255 | void tcg_gen_vec_add16_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b); 256 | void tcg_gen_vec_add32_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b); 257 | 258 | void tcg_gen_vec_sub8_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b); 259 | void tcg_gen_vec_sub16_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b); 260 | void tcg_gen_vec_sub32_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b); 261 | 262 | void tcg_gen_vec_shl8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t); 263 | void tcg_gen_vec_shl16i_i64(TCGv_i64 d, TCGv_i64 a, int64_t); 264 | void tcg_gen_vec_shr8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t); 265 | void tcg_gen_vec_shr16i_i64(TCGv_i64 d, TCGv_i64 a, int64_t); 266 | void tcg_gen_vec_sar8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t); 267 | void tcg_gen_vec_sar16i_i64(TCGv_i64 d, TCGv_i64 a, int64_t); 268 | -------------------------------------------------------------------------------- /src/tcg-op-vec.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Tiny Code Generator for QEMU 3 | * 4 | * Copyright (c) 2018 Linaro, Inc. 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | /* Reduce the number of ifdefs below. This assumes that all uses of 25 | TCGV_HIGH and TCGV_LOW are properly protected by a conditional that 26 | the compiler can eliminate. */ 27 | #if TCG_TARGET_REG_BITS == 64 28 | extern TCGv_i32 TCGV_LOW_link_error(TCGv_i64); 29 | extern TCGv_i32 TCGV_HIGH_link_error(TCGv_i64); 30 | #define TCGV_LOW TCGV_LOW_link_error 31 | #define TCGV_HIGH TCGV_HIGH_link_error 32 | #endif 33 | 34 | void vec_gen_2(TCGOpcode opc, TCGType type, unsigned vece, TCGArg r, TCGArg a) { 35 | TCGOp *op = tcg_emit_op(opc); 36 | TCGOP_VECL(op) = type - TCG_TYPE_V64; 37 | TCGOP_VECE(op) = vece; 38 | op->args[0] = r; 39 | op->args[1] = a; 40 | } 41 | 42 | void vec_gen_3(TCGOpcode opc, TCGType type, unsigned vece, TCGArg r, TCGArg a, TCGArg b) { 43 | TCGOp *op = tcg_emit_op(opc); 44 | TCGOP_VECL(op) = type - TCG_TYPE_V64; 45 | TCGOP_VECE(op) = vece; 46 | op->args[0] = r; 47 | op->args[1] = a; 48 | op->args[2] = b; 49 | } 50 | 51 | void vec_gen_4(TCGOpcode opc, TCGType type, unsigned vece, TCGArg r, TCGArg a, TCGArg b, TCGArg c) { 52 | TCGOp *op = tcg_emit_op(opc); 53 | TCGOP_VECL(op) = type - TCG_TYPE_V64; 54 | TCGOP_VECE(op) = vece; 55 | op->args[0] = r; 56 | op->args[1] = a; 57 | op->args[2] = b; 58 | op->args[3] = c; 59 | } 60 | 61 | static void vec_gen_op2(TCGOpcode opc, unsigned vece, TCGv_vec r, TCGv_vec a) { 62 | TCGTemp *rt = tcgv_vec_temp(r); 63 | TCGTemp *at = tcgv_vec_temp(a); 64 | TCGType type = rt->base_type; 65 | 66 | /* Must enough inputs for the output. */ 67 | tcg_debug_assert(at->base_type >= type); 68 | vec_gen_2(opc, type, vece, temp_arg(rt), temp_arg(at)); 69 | } 70 | 71 | static void vec_gen_op3(TCGOpcode opc, unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b) { 72 | TCGTemp *rt = tcgv_vec_temp(r); 73 | TCGTemp *at = tcgv_vec_temp(a); 74 | TCGTemp *bt = tcgv_vec_temp(b); 75 | TCGType type = rt->base_type; 76 | 77 | /* Must enough inputs for the output. */ 78 | tcg_debug_assert(at->base_type >= type); 79 | tcg_debug_assert(bt->base_type >= type); 80 | vec_gen_3(opc, type, vece, temp_arg(rt), temp_arg(at), temp_arg(bt)); 81 | } 82 | 83 | void tcg_gen_mov_vec(TCGv_vec r, TCGv_vec a) { 84 | if (r != a) { 85 | vec_gen_op2(INDEX_op_mov_vec, 0, r, a); 86 | } 87 | } 88 | 89 | #define MO_REG (TCG_TARGET_REG_BITS == 64 ? MO_64 : MO_32) 90 | 91 | static void do_dupi_vec(TCGv_vec r, unsigned vece, TCGArg a) { 92 | TCGTemp *rt = tcgv_vec_temp(r); 93 | vec_gen_2(INDEX_op_dupi_vec, rt->base_type, vece, temp_arg(rt), a); 94 | } 95 | 96 | TCGv_vec tcg_const_zeros_vec(TCGType type) { 97 | TCGv_vec ret = tcg_temp_new_vec(type); 98 | do_dupi_vec(ret, MO_REG, 0); 99 | return ret; 100 | } 101 | 102 | TCGv_vec tcg_const_ones_vec(TCGType type) { 103 | TCGv_vec ret = tcg_temp_new_vec(type); 104 | do_dupi_vec(ret, MO_REG, -1); 105 | return ret; 106 | } 107 | 108 | TCGv_vec tcg_const_zeros_vec_matching(TCGv_vec m) { 109 | TCGTemp *t = tcgv_vec_temp(m); 110 | return tcg_const_zeros_vec(t->base_type); 111 | } 112 | 113 | TCGv_vec tcg_const_ones_vec_matching(TCGv_vec m) { 114 | TCGTemp *t = tcgv_vec_temp(m); 115 | return tcg_const_ones_vec(t->base_type); 116 | } 117 | 118 | void tcg_gen_dup64i_vec(TCGv_vec r, uint64_t a) { 119 | if (TCG_TARGET_REG_BITS == 32 && a == deposit64(a, 32, 32, a)) { 120 | do_dupi_vec(r, MO_32, a); 121 | } else if (TCG_TARGET_REG_BITS == 64 || a == (uint64_t)(int32_t) a) { 122 | do_dupi_vec(r, MO_64, a); 123 | } else { 124 | TCGv_i64 c = tcg_const_i64(a); 125 | tcg_gen_dup_i64_vec(MO_64, r, c); 126 | tcg_temp_free_i64(c); 127 | } 128 | } 129 | 130 | void tcg_gen_dup32i_vec(TCGv_vec r, uint32_t a) { 131 | do_dupi_vec(r, MO_REG, dup_const(MO_32, a)); 132 | } 133 | 134 | void tcg_gen_dup16i_vec(TCGv_vec r, uint32_t a) { 135 | do_dupi_vec(r, MO_REG, dup_const(MO_16, a)); 136 | } 137 | 138 | void tcg_gen_dup8i_vec(TCGv_vec r, uint32_t a) { 139 | do_dupi_vec(r, MO_REG, dup_const(MO_8, a)); 140 | } 141 | 142 | void tcg_gen_dupi_vec(unsigned vece, TCGv_vec r, uint64_t a) { 143 | do_dupi_vec(r, MO_REG, dup_const(vece, a)); 144 | } 145 | 146 | void tcg_gen_dup_i64_vec(unsigned vece, TCGv_vec r, TCGv_i64 a) { 147 | TCGArg ri = tcgv_vec_arg(r); 148 | TCGTemp *rt = arg_temp(ri); 149 | TCGType type = rt->base_type; 150 | 151 | if (TCG_TARGET_REG_BITS == 64) { 152 | TCGArg ai = tcgv_i64_arg(a); 153 | vec_gen_2(INDEX_op_dup_vec, type, vece, ri, ai); 154 | } else if (vece == MO_64) { 155 | TCGArg al = tcgv_i32_arg(TCGV_LOW(a)); 156 | TCGArg ah = tcgv_i32_arg(TCGV_HIGH(a)); 157 | vec_gen_3(INDEX_op_dup2_vec, type, MO_64, ri, al, ah); 158 | } else { 159 | TCGArg ai = tcgv_i32_arg(TCGV_LOW(a)); 160 | vec_gen_2(INDEX_op_dup_vec, type, vece, ri, ai); 161 | } 162 | } 163 | 164 | void tcg_gen_dup_i32_vec(unsigned vece, TCGv_vec r, TCGv_i32 a) { 165 | TCGArg ri = tcgv_vec_arg(r); 166 | TCGArg ai = tcgv_i32_arg(a); 167 | TCGTemp *rt = arg_temp(ri); 168 | TCGType type = rt->base_type; 169 | 170 | vec_gen_2(INDEX_op_dup_vec, type, vece, ri, ai); 171 | } 172 | 173 | static void vec_gen_ldst(TCGOpcode opc, TCGv_vec r, TCGv_ptr b, TCGArg o) { 174 | TCGArg ri = tcgv_vec_arg(r); 175 | TCGArg bi = tcgv_ptr_arg(b); 176 | TCGTemp *rt = arg_temp(ri); 177 | TCGType type = rt->base_type; 178 | 179 | vec_gen_3(opc, type, 0, ri, bi, o); 180 | } 181 | 182 | void tcg_gen_ld_vec(TCGv_vec r, TCGv_ptr b, TCGArg o) { 183 | vec_gen_ldst(INDEX_op_ld_vec, r, b, o); 184 | } 185 | 186 | void tcg_gen_st_vec(TCGv_vec r, TCGv_ptr b, TCGArg o) { 187 | vec_gen_ldst(INDEX_op_st_vec, r, b, o); 188 | } 189 | 190 | void tcg_gen_stl_vec(TCGv_vec r, TCGv_ptr b, TCGArg o, TCGType low_type) { 191 | TCGArg ri = tcgv_vec_arg(r); 192 | TCGArg bi = tcgv_ptr_arg(b); 193 | TCGTemp *rt = arg_temp(ri); 194 | TCGType type = rt->base_type; 195 | 196 | tcg_debug_assert(low_type >= TCG_TYPE_V64); 197 | tcg_debug_assert(low_type <= type); 198 | vec_gen_3(INDEX_op_st_vec, low_type, 0, ri, bi, o); 199 | } 200 | 201 | void tcg_gen_add_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b) { 202 | vec_gen_op3(INDEX_op_add_vec, vece, r, a, b); 203 | } 204 | 205 | void tcg_gen_sub_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b) { 206 | vec_gen_op3(INDEX_op_sub_vec, vece, r, a, b); 207 | } 208 | 209 | void tcg_gen_and_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b) { 210 | vec_gen_op3(INDEX_op_and_vec, 0, r, a, b); 211 | } 212 | 213 | void tcg_gen_or_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b) { 214 | vec_gen_op3(INDEX_op_or_vec, 0, r, a, b); 215 | } 216 | 217 | void tcg_gen_xor_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b) { 218 | vec_gen_op3(INDEX_op_xor_vec, 0, r, a, b); 219 | } 220 | 221 | void tcg_gen_andc_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b) { 222 | if (TCG_TARGET_HAS_andc_vec) { 223 | vec_gen_op3(INDEX_op_andc_vec, 0, r, a, b); 224 | } else { 225 | TCGv_vec t = tcg_temp_new_vec_matching(r); 226 | tcg_gen_not_vec(0, t, b); 227 | tcg_gen_and_vec(0, r, a, t); 228 | tcg_temp_free_vec(t); 229 | } 230 | } 231 | 232 | void tcg_gen_orc_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b) { 233 | if (TCG_TARGET_HAS_orc_vec) { 234 | vec_gen_op3(INDEX_op_orc_vec, 0, r, a, b); 235 | } else { 236 | TCGv_vec t = tcg_temp_new_vec_matching(r); 237 | tcg_gen_not_vec(0, t, b); 238 | tcg_gen_or_vec(0, r, a, t); 239 | tcg_temp_free_vec(t); 240 | } 241 | } 242 | 243 | void tcg_gen_nand_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b) { 244 | /* TODO: Add TCG_TARGET_HAS_nand_vec when adding a backend supports it. */ 245 | tcg_gen_and_vec(0, r, a, b); 246 | tcg_gen_not_vec(0, r, r); 247 | } 248 | 249 | void tcg_gen_nor_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b) { 250 | /* TODO: Add TCG_TARGET_HAS_nor_vec when adding a backend supports it. */ 251 | tcg_gen_or_vec(0, r, a, b); 252 | tcg_gen_not_vec(0, r, r); 253 | } 254 | 255 | void tcg_gen_eqv_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b) { 256 | /* TODO: Add TCG_TARGET_HAS_eqv_vec when adding a backend supports it. */ 257 | tcg_gen_xor_vec(0, r, a, b); 258 | tcg_gen_not_vec(0, r, r); 259 | } 260 | 261 | void tcg_gen_not_vec(unsigned vece, TCGv_vec r, TCGv_vec a) { 262 | if (TCG_TARGET_HAS_not_vec) { 263 | vec_gen_op2(INDEX_op_not_vec, 0, r, a); 264 | } else { 265 | TCGv_vec t = tcg_const_ones_vec_matching(r); 266 | tcg_gen_xor_vec(0, r, a, t); 267 | tcg_temp_free_vec(t); 268 | } 269 | } 270 | 271 | void tcg_gen_neg_vec(unsigned vece, TCGv_vec r, TCGv_vec a) { 272 | if (TCG_TARGET_HAS_neg_vec) { 273 | vec_gen_op2(INDEX_op_neg_vec, vece, r, a); 274 | } else { 275 | TCGv_vec t = tcg_const_zeros_vec_matching(r); 276 | tcg_gen_sub_vec(vece, r, t, a); 277 | tcg_temp_free_vec(t); 278 | } 279 | } 280 | 281 | static void do_shifti(TCGOpcode opc, unsigned vece, TCGv_vec r, TCGv_vec a, int64_t i) { 282 | TCGTemp *rt = tcgv_vec_temp(r); 283 | TCGTemp *at = tcgv_vec_temp(a); 284 | TCGArg ri = temp_arg(rt); 285 | TCGArg ai = temp_arg(at); 286 | TCGType type = rt->base_type; 287 | int can; 288 | 289 | tcg_debug_assert(at->base_type == type); 290 | tcg_debug_assert(i >= 0 && i < (8 << vece)); 291 | 292 | if (i == 0) { 293 | tcg_gen_mov_vec(r, a); 294 | return; 295 | } 296 | 297 | can = tcg_can_emit_vec_op(opc, type, vece); 298 | if (can > 0) { 299 | vec_gen_3(opc, type, vece, ri, ai, i); 300 | } else { 301 | /* We leave the choice of expansion via scalar or vector shift 302 | to the target. Often, but not always, dupi can feed a vector 303 | shift easier than a scalar. */ 304 | tcg_debug_assert(can < 0); 305 | tcg_expand_vec_op(opc, type, vece, ri, ai, i); 306 | } 307 | } 308 | 309 | void tcg_gen_shli_vec(unsigned vece, TCGv_vec r, TCGv_vec a, int64_t i) { 310 | do_shifti(INDEX_op_shli_vec, vece, r, a, i); 311 | } 312 | 313 | void tcg_gen_shri_vec(unsigned vece, TCGv_vec r, TCGv_vec a, int64_t i) { 314 | do_shifti(INDEX_op_shri_vec, vece, r, a, i); 315 | } 316 | 317 | void tcg_gen_sari_vec(unsigned vece, TCGv_vec r, TCGv_vec a, int64_t i) { 318 | do_shifti(INDEX_op_sari_vec, vece, r, a, i); 319 | } 320 | 321 | void tcg_gen_cmp_vec(TCGCond cond, unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b) { 322 | TCGTemp *rt = tcgv_vec_temp(r); 323 | TCGTemp *at = tcgv_vec_temp(a); 324 | TCGTemp *bt = tcgv_vec_temp(b); 325 | TCGArg ri = temp_arg(rt); 326 | TCGArg ai = temp_arg(at); 327 | TCGArg bi = temp_arg(bt); 328 | TCGType type = rt->base_type; 329 | int can; 330 | 331 | tcg_debug_assert(at->base_type >= type); 332 | tcg_debug_assert(bt->base_type >= type); 333 | can = tcg_can_emit_vec_op(INDEX_op_cmp_vec, type, vece); 334 | if (can > 0) { 335 | vec_gen_4(INDEX_op_cmp_vec, type, vece, ri, ai, bi, cond); 336 | } else { 337 | tcg_debug_assert(can < 0); 338 | tcg_expand_vec_op(INDEX_op_cmp_vec, type, vece, ri, ai, bi, cond); 339 | } 340 | } 341 | 342 | static void do_op3(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b, TCGOpcode opc) { 343 | TCGTemp *rt = tcgv_vec_temp(r); 344 | TCGTemp *at = tcgv_vec_temp(a); 345 | TCGTemp *bt = tcgv_vec_temp(b); 346 | TCGArg ri = temp_arg(rt); 347 | TCGArg ai = temp_arg(at); 348 | TCGArg bi = temp_arg(bt); 349 | TCGType type = rt->base_type; 350 | int can; 351 | 352 | tcg_debug_assert(at->base_type >= type); 353 | tcg_debug_assert(bt->base_type >= type); 354 | can = tcg_can_emit_vec_op(opc, type, vece); 355 | if (can > 0) { 356 | vec_gen_3(opc, type, vece, ri, ai, bi); 357 | } else { 358 | tcg_debug_assert(can < 0); 359 | tcg_expand_vec_op(opc, type, vece, ri, ai, bi); 360 | } 361 | } 362 | 363 | void tcg_gen_mul_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b) { 364 | do_op3(vece, r, a, b, INDEX_op_mul_vec); 365 | } 366 | 367 | void tcg_gen_ssadd_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b) { 368 | do_op3(vece, r, a, b, INDEX_op_ssadd_vec); 369 | } 370 | 371 | void tcg_gen_usadd_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b) { 372 | do_op3(vece, r, a, b, INDEX_op_usadd_vec); 373 | } 374 | 375 | void tcg_gen_sssub_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b) { 376 | do_op3(vece, r, a, b, INDEX_op_sssub_vec); 377 | } 378 | 379 | void tcg_gen_ussub_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b) { 380 | do_op3(vece, r, a, b, INDEX_op_ussub_vec); 381 | } 382 | 383 | void tcg_gen_smin_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b) { 384 | do_op3(vece, r, a, b, INDEX_op_smin_vec); 385 | } 386 | 387 | void tcg_gen_umin_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b) { 388 | do_op3(vece, r, a, b, INDEX_op_umin_vec); 389 | } 390 | 391 | void tcg_gen_smax_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b) { 392 | do_op3(vece, r, a, b, INDEX_op_smax_vec); 393 | } 394 | 395 | void tcg_gen_umax_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b) { 396 | do_op3(vece, r, a, b, INDEX_op_umax_vec); 397 | } 398 | -------------------------------------------------------------------------------- /src/tcg-pool.inc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * TCG Backend Data: constant pool. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | typedef struct TCGLabelPoolData { 24 | struct TCGLabelPoolData *next; 25 | tcg_insn_unit *label; 26 | intptr_t addend; 27 | int rtype; 28 | unsigned nlong; 29 | tcg_target_ulong data[]; 30 | } TCGLabelPoolData; 31 | 32 | static TCGLabelPoolData *new_pool_alloc(TCGContext *s, int nlong, int rtype, tcg_insn_unit *label, intptr_t addend) { 33 | TCGLabelPoolData *n = tcg_malloc(sizeof(TCGLabelPoolData) + sizeof(tcg_target_ulong) * nlong); 34 | 35 | n->label = label; 36 | n->addend = addend; 37 | n->rtype = rtype; 38 | n->nlong = nlong; 39 | return n; 40 | } 41 | 42 | static void new_pool_insert(TCGContext *s, TCGLabelPoolData *n) { 43 | TCGLabelPoolData *i, **pp; 44 | int nlong = n->nlong; 45 | 46 | /* Insertion sort on the pool. */ 47 | for (pp = &s->pool_labels; (i = *pp) != NULL; pp = &i->next) { 48 | if (nlong > i->nlong) { 49 | break; 50 | } 51 | if (nlong < i->nlong) { 52 | continue; 53 | } 54 | if (memcmp(n->data, i->data, sizeof(tcg_target_ulong) * nlong) >= 0) { 55 | break; 56 | } 57 | } 58 | n->next = *pp; 59 | *pp = n; 60 | } 61 | 62 | /* The "usual" for generic integer code. */ 63 | static inline void new_pool_label(TCGContext *s, tcg_target_ulong d, int rtype, tcg_insn_unit *label, intptr_t addend) { 64 | TCGLabelPoolData *n = new_pool_alloc(s, 1, rtype, label, addend); 65 | n->data[0] = d; 66 | new_pool_insert(s, n); 67 | } 68 | 69 | /* For v64 or v128, depending on the host. */ 70 | static inline void new_pool_l2(TCGContext *s, int rtype, tcg_insn_unit *label, intptr_t addend, tcg_target_ulong d0, 71 | tcg_target_ulong d1) { 72 | TCGLabelPoolData *n = new_pool_alloc(s, 2, rtype, label, addend); 73 | n->data[0] = d0; 74 | n->data[1] = d1; 75 | new_pool_insert(s, n); 76 | } 77 | 78 | /* For v128 or v256, depending on the host. */ 79 | static inline void new_pool_l4(TCGContext *s, int rtype, tcg_insn_unit *label, intptr_t addend, tcg_target_ulong d0, 80 | tcg_target_ulong d1, tcg_target_ulong d2, tcg_target_ulong d3) { 81 | TCGLabelPoolData *n = new_pool_alloc(s, 4, rtype, label, addend); 82 | n->data[0] = d0; 83 | n->data[1] = d1; 84 | n->data[2] = d2; 85 | n->data[3] = d3; 86 | new_pool_insert(s, n); 87 | } 88 | 89 | /* For v256, for 32-bit host. */ 90 | static inline void new_pool_l8(TCGContext *s, int rtype, tcg_insn_unit *label, intptr_t addend, tcg_target_ulong d0, 91 | tcg_target_ulong d1, tcg_target_ulong d2, tcg_target_ulong d3, tcg_target_ulong d4, 92 | tcg_target_ulong d5, tcg_target_ulong d6, tcg_target_ulong d7) { 93 | TCGLabelPoolData *n = new_pool_alloc(s, 8, rtype, label, addend); 94 | n->data[0] = d0; 95 | n->data[1] = d1; 96 | n->data[2] = d2; 97 | n->data[3] = d3; 98 | n->data[4] = d4; 99 | n->data[5] = d5; 100 | n->data[6] = d6; 101 | n->data[7] = d7; 102 | new_pool_insert(s, n); 103 | } 104 | 105 | /* To be provided by cpu/tcg-target.inc.c. */ 106 | static void tcg_out_nop_fill(tcg_insn_unit *p, int count); 107 | 108 | static bool tcg_out_pool_finalize(TCGContext *s) { 109 | TCGLabelPoolData *p = s->pool_labels; 110 | TCGLabelPoolData *l = NULL; 111 | void *a; 112 | 113 | if (p == NULL) { 114 | return true; 115 | } 116 | 117 | /* ??? Round up to qemu_icache_linesize, but then do not round 118 | again when allocating the next TranslationBlock structure. */ 119 | a = (void *) ROUND_UP((uintptr_t) s->code_ptr, sizeof(tcg_target_ulong) * p->nlong); 120 | tcg_out_nop_fill(s->code_ptr, (tcg_insn_unit *) a - s->code_ptr); 121 | s->data_gen_ptr = a; 122 | 123 | for (; p != NULL; p = p->next) { 124 | size_t size = sizeof(tcg_target_ulong) * p->nlong; 125 | if (!l || l->nlong != p->nlong || memcmp(l->data, p->data, size)) { 126 | if (unlikely(a > s->code_gen_highwater)) { 127 | return false; 128 | } 129 | memcpy(a, p->data, size); 130 | a += size; 131 | l = p; 132 | } 133 | patch_reloc(p->label, p->rtype, (intptr_t) a - size, p->addend); 134 | } 135 | 136 | s->code_ptr = a; 137 | return true; 138 | } 139 | -------------------------------------------------------------------------------- /src/tcg-runtime.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Tiny Code Generator for QEMU 3 | * 4 | * Copyright (c) 2008 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | // XXX: clean this up 31 | #define HELPER(x) helper_##x 32 | 33 | /* 32-bit helpers */ 34 | 35 | int32_t HELPER(div_i32)(int32_t arg1, int32_t arg2) { 36 | return arg1 / arg2; 37 | } 38 | 39 | int32_t HELPER(rem_i32)(int32_t arg1, int32_t arg2) { 40 | return arg1 % arg2; 41 | } 42 | 43 | uint32_t HELPER(divu_i32)(uint32_t arg1, uint32_t arg2) { 44 | return arg1 / arg2; 45 | } 46 | 47 | uint32_t HELPER(remu_i32)(uint32_t arg1, uint32_t arg2) { 48 | return arg1 % arg2; 49 | } 50 | 51 | /* 64-bit helpers */ 52 | 53 | uint64_t HELPER(shl_i64)(uint64_t arg1, uint64_t arg2) { 54 | return arg1 << arg2; 55 | } 56 | 57 | uint64_t HELPER(shr_i64)(uint64_t arg1, uint64_t arg2) { 58 | return arg1 >> arg2; 59 | } 60 | 61 | int64_t HELPER(sar_i64)(int64_t arg1, int64_t arg2) { 62 | return arg1 >> arg2; 63 | } 64 | 65 | int64_t HELPER(div_i64)(int64_t arg1, int64_t arg2) { 66 | return arg1 / arg2; 67 | } 68 | 69 | int64_t HELPER(rem_i64)(int64_t arg1, int64_t arg2) { 70 | return arg1 % arg2; 71 | } 72 | 73 | uint64_t HELPER(divu_i64)(uint64_t arg1, uint64_t arg2) { 74 | return arg1 / arg2; 75 | } 76 | 77 | uint64_t HELPER(remu_i64)(uint64_t arg1, uint64_t arg2) { 78 | return arg1 % arg2; 79 | } 80 | 81 | uint64_t HELPER(muluh_i64)(uint64_t arg1, uint64_t arg2) { 82 | uint64_t l, h; 83 | mulu64(&l, &h, arg1, arg2); 84 | return h; 85 | } 86 | 87 | int64_t HELPER(mulsh_i64)(int64_t arg1, int64_t arg2) { 88 | uint64_t l, h; 89 | muls64(&l, &h, arg1, arg2); 90 | return h; 91 | } 92 | 93 | uint32_t HELPER(clz_i32)(uint32_t arg, uint32_t zero_val) { 94 | return arg ? clz32(arg) : zero_val; 95 | } 96 | 97 | uint32_t HELPER(ctz_i32)(uint32_t arg, uint32_t zero_val) { 98 | return arg ? ctz32(arg) : zero_val; 99 | } 100 | 101 | uint64_t HELPER(clz_i64)(uint64_t arg, uint64_t zero_val) { 102 | return arg ? clz64(arg) : zero_val; 103 | } 104 | 105 | uint64_t HELPER(ctz_i64)(uint64_t arg, uint64_t zero_val) { 106 | return arg ? ctz64(arg) : zero_val; 107 | } 108 | 109 | uint32_t HELPER(clrsb_i32)(uint32_t arg) { 110 | return clrsb32(arg); 111 | } 112 | 113 | uint64_t HELPER(clrsb_i64)(uint64_t arg) { 114 | return clrsb64(arg); 115 | } 116 | 117 | uint32_t HELPER(ctpop_i32)(uint32_t arg) { 118 | return ctpop32(arg); 119 | } 120 | 121 | uint64_t HELPER(ctpop_i64)(uint64_t arg) { 122 | return ctpop64(arg); 123 | } 124 | --------------------------------------------------------------------------------