1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2fca08f32SWang Nan /* 3fca08f32SWang Nan * arch/arm/probes/decode.c 4fca08f32SWang Nan * 5fca08f32SWang Nan * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. 6fca08f32SWang Nan * 7fca08f32SWang Nan * Some contents moved here from arch/arm/include/asm/kprobes-arm.c which is 8fca08f32SWang Nan * Copyright (C) 2006, 2007 Motorola Inc. 9fca08f32SWang Nan */ 10fca08f32SWang Nan 11fca08f32SWang Nan #include <linux/kernel.h> 12fca08f32SWang Nan #include <linux/types.h> 13fca08f32SWang Nan #include <asm/system_info.h> 14fca08f32SWang Nan #include <asm/ptrace.h> 15fca08f32SWang Nan #include <linux/bug.h> 16fca08f32SWang Nan 17fca08f32SWang Nan #include "decode.h" 18fca08f32SWang Nan 19fca08f32SWang Nan 20fca08f32SWang Nan #ifndef find_str_pc_offset 21fca08f32SWang Nan 22fca08f32SWang Nan /* 23fca08f32SWang Nan * For STR and STM instructions, an ARM core may choose to use either 24fca08f32SWang Nan * a +8 or a +12 displacement from the current instruction's address. 25fca08f32SWang Nan * Whichever value is chosen for a given core, it must be the same for 26fca08f32SWang Nan * both instructions and may not change. This function measures it. 27fca08f32SWang Nan */ 28fca08f32SWang Nan 29fca08f32SWang Nan int str_pc_offset; 30fca08f32SWang Nan 31fca08f32SWang Nan void __init find_str_pc_offset(void) 32fca08f32SWang Nan { 33fca08f32SWang Nan int addr, scratch, ret; 34fca08f32SWang Nan 35fca08f32SWang Nan __asm__ ( 36fca08f32SWang Nan "sub %[ret], pc, #4 \n\t" 37fca08f32SWang Nan "str pc, %[addr] \n\t" 38fca08f32SWang Nan "ldr %[scr], %[addr] \n\t" 39fca08f32SWang Nan "sub %[ret], %[scr], %[ret] \n\t" 40fca08f32SWang Nan : [ret] "=r" (ret), [scr] "=r" (scratch), [addr] "+m" (addr)); 41fca08f32SWang Nan 42fca08f32SWang Nan str_pc_offset = ret; 43fca08f32SWang Nan } 44fca08f32SWang Nan 45fca08f32SWang Nan #endif /* !find_str_pc_offset */ 46fca08f32SWang Nan 47fca08f32SWang Nan 48fca08f32SWang Nan #ifndef test_load_write_pc_interworking 49fca08f32SWang Nan 50fca08f32SWang Nan bool load_write_pc_interworks; 51fca08f32SWang Nan 52fca08f32SWang Nan void __init test_load_write_pc_interworking(void) 53fca08f32SWang Nan { 54fca08f32SWang Nan int arch = cpu_architecture(); 55fca08f32SWang Nan BUG_ON(arch == CPU_ARCH_UNKNOWN); 56fca08f32SWang Nan load_write_pc_interworks = arch >= CPU_ARCH_ARMv5T; 57fca08f32SWang Nan } 58fca08f32SWang Nan 59fca08f32SWang Nan #endif /* !test_load_write_pc_interworking */ 60fca08f32SWang Nan 61fca08f32SWang Nan 62fca08f32SWang Nan #ifndef test_alu_write_pc_interworking 63fca08f32SWang Nan 64fca08f32SWang Nan bool alu_write_pc_interworks; 65fca08f32SWang Nan 66fca08f32SWang Nan void __init test_alu_write_pc_interworking(void) 67fca08f32SWang Nan { 68fca08f32SWang Nan int arch = cpu_architecture(); 69fca08f32SWang Nan BUG_ON(arch == CPU_ARCH_UNKNOWN); 70fca08f32SWang Nan alu_write_pc_interworks = arch >= CPU_ARCH_ARMv7; 71fca08f32SWang Nan } 72fca08f32SWang Nan 73fca08f32SWang Nan #endif /* !test_alu_write_pc_interworking */ 74fca08f32SWang Nan 75fca08f32SWang Nan 76fca08f32SWang Nan void __init arm_probes_decode_init(void) 77fca08f32SWang Nan { 78fca08f32SWang Nan find_str_pc_offset(); 79fca08f32SWang Nan test_load_write_pc_interworking(); 80fca08f32SWang Nan test_alu_write_pc_interworking(); 81fca08f32SWang Nan } 82fca08f32SWang Nan 83fca08f32SWang Nan 84fca08f32SWang Nan static unsigned long __kprobes __check_eq(unsigned long cpsr) 85fca08f32SWang Nan { 86fca08f32SWang Nan return cpsr & PSR_Z_BIT; 87fca08f32SWang Nan } 88fca08f32SWang Nan 89fca08f32SWang Nan static unsigned long __kprobes __check_ne(unsigned long cpsr) 90fca08f32SWang Nan { 91fca08f32SWang Nan return (~cpsr) & PSR_Z_BIT; 92fca08f32SWang Nan } 93fca08f32SWang Nan 94fca08f32SWang Nan static unsigned long __kprobes __check_cs(unsigned long cpsr) 95fca08f32SWang Nan { 96fca08f32SWang Nan return cpsr & PSR_C_BIT; 97fca08f32SWang Nan } 98fca08f32SWang Nan 99fca08f32SWang Nan static unsigned long __kprobes __check_cc(unsigned long cpsr) 100fca08f32SWang Nan { 101fca08f32SWang Nan return (~cpsr) & PSR_C_BIT; 102fca08f32SWang Nan } 103fca08f32SWang Nan 104fca08f32SWang Nan static unsigned long __kprobes __check_mi(unsigned long cpsr) 105fca08f32SWang Nan { 106fca08f32SWang Nan return cpsr & PSR_N_BIT; 107fca08f32SWang Nan } 108fca08f32SWang Nan 109fca08f32SWang Nan static unsigned long __kprobes __check_pl(unsigned long cpsr) 110fca08f32SWang Nan { 111fca08f32SWang Nan return (~cpsr) & PSR_N_BIT; 112fca08f32SWang Nan } 113fca08f32SWang Nan 114fca08f32SWang Nan static unsigned long __kprobes __check_vs(unsigned long cpsr) 115fca08f32SWang Nan { 116fca08f32SWang Nan return cpsr & PSR_V_BIT; 117fca08f32SWang Nan } 118fca08f32SWang Nan 119fca08f32SWang Nan static unsigned long __kprobes __check_vc(unsigned long cpsr) 120fca08f32SWang Nan { 121fca08f32SWang Nan return (~cpsr) & PSR_V_BIT; 122fca08f32SWang Nan } 123fca08f32SWang Nan 124fca08f32SWang Nan static unsigned long __kprobes __check_hi(unsigned long cpsr) 125fca08f32SWang Nan { 126fca08f32SWang Nan cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */ 127fca08f32SWang Nan return cpsr & PSR_C_BIT; 128fca08f32SWang Nan } 129fca08f32SWang Nan 130fca08f32SWang Nan static unsigned long __kprobes __check_ls(unsigned long cpsr) 131fca08f32SWang Nan { 132fca08f32SWang Nan cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */ 133fca08f32SWang Nan return (~cpsr) & PSR_C_BIT; 134fca08f32SWang Nan } 135fca08f32SWang Nan 136fca08f32SWang Nan static unsigned long __kprobes __check_ge(unsigned long cpsr) 137fca08f32SWang Nan { 138fca08f32SWang Nan cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ 139fca08f32SWang Nan return (~cpsr) & PSR_N_BIT; 140fca08f32SWang Nan } 141fca08f32SWang Nan 142fca08f32SWang Nan static unsigned long __kprobes __check_lt(unsigned long cpsr) 143fca08f32SWang Nan { 144fca08f32SWang Nan cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ 145fca08f32SWang Nan return cpsr & PSR_N_BIT; 146fca08f32SWang Nan } 147fca08f32SWang Nan 148fca08f32SWang Nan static unsigned long __kprobes __check_gt(unsigned long cpsr) 149fca08f32SWang Nan { 150fca08f32SWang Nan unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ 151fca08f32SWang Nan temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */ 152fca08f32SWang Nan return (~temp) & PSR_N_BIT; 153fca08f32SWang Nan } 154fca08f32SWang Nan 155fca08f32SWang Nan static unsigned long __kprobes __check_le(unsigned long cpsr) 156fca08f32SWang Nan { 157fca08f32SWang Nan unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ 158fca08f32SWang Nan temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */ 159fca08f32SWang Nan return temp & PSR_N_BIT; 160fca08f32SWang Nan } 161fca08f32SWang Nan 162fca08f32SWang Nan static unsigned long __kprobes __check_al(unsigned long cpsr) 163fca08f32SWang Nan { 164fca08f32SWang Nan return true; 165fca08f32SWang Nan } 166fca08f32SWang Nan 167fca08f32SWang Nan probes_check_cc * const probes_condition_checks[16] = { 168fca08f32SWang Nan &__check_eq, &__check_ne, &__check_cs, &__check_cc, 169fca08f32SWang Nan &__check_mi, &__check_pl, &__check_vs, &__check_vc, 170fca08f32SWang Nan &__check_hi, &__check_ls, &__check_ge, &__check_lt, 171fca08f32SWang Nan &__check_gt, &__check_le, &__check_al, &__check_al 172fca08f32SWang Nan }; 173fca08f32SWang Nan 174fca08f32SWang Nan 175fca08f32SWang Nan void __kprobes probes_simulate_nop(probes_opcode_t opcode, 176fca08f32SWang Nan struct arch_probes_insn *asi, 177fca08f32SWang Nan struct pt_regs *regs) 178fca08f32SWang Nan { 179fca08f32SWang Nan } 180fca08f32SWang Nan 181fca08f32SWang Nan void __kprobes probes_emulate_none(probes_opcode_t opcode, 182fca08f32SWang Nan struct arch_probes_insn *asi, 183fca08f32SWang Nan struct pt_regs *regs) 184fca08f32SWang Nan { 185fca08f32SWang Nan asi->insn_fn(); 186fca08f32SWang Nan } 187fca08f32SWang Nan 188fca08f32SWang Nan /* 189fca08f32SWang Nan * Prepare an instruction slot to receive an instruction for emulating. 190fca08f32SWang Nan * This is done by placing a subroutine return after the location where the 191fca08f32SWang Nan * instruction will be placed. We also modify ARM instructions to be 192fca08f32SWang Nan * unconditional as the condition code will already be checked before any 193fca08f32SWang Nan * emulation handler is called. 194fca08f32SWang Nan */ 195fca08f32SWang Nan static probes_opcode_t __kprobes 196fca08f32SWang Nan prepare_emulated_insn(probes_opcode_t insn, struct arch_probes_insn *asi, 197fca08f32SWang Nan bool thumb) 198fca08f32SWang Nan { 199fca08f32SWang Nan #ifdef CONFIG_THUMB2_KERNEL 200fca08f32SWang Nan if (thumb) { 201fca08f32SWang Nan u16 *thumb_insn = (u16 *)asi->insn; 202fca08f32SWang Nan /* Thumb bx lr */ 203fca08f32SWang Nan thumb_insn[1] = __opcode_to_mem_thumb16(0x4770); 204fca08f32SWang Nan thumb_insn[2] = __opcode_to_mem_thumb16(0x4770); 205fca08f32SWang Nan return insn; 206fca08f32SWang Nan } 207fca08f32SWang Nan asi->insn[1] = __opcode_to_mem_arm(0xe12fff1e); /* ARM bx lr */ 208fca08f32SWang Nan #else 209fca08f32SWang Nan asi->insn[1] = __opcode_to_mem_arm(0xe1a0f00e); /* mov pc, lr */ 210fca08f32SWang Nan #endif 211fca08f32SWang Nan /* Make an ARM instruction unconditional */ 212fca08f32SWang Nan if (insn < 0xe0000000) 213fca08f32SWang Nan insn = (insn | 0xe0000000) & ~0x10000000; 214fca08f32SWang Nan return insn; 215fca08f32SWang Nan } 216fca08f32SWang Nan 217fca08f32SWang Nan /* 218fca08f32SWang Nan * Write a (probably modified) instruction into the slot previously prepared by 219fca08f32SWang Nan * prepare_emulated_insn 220fca08f32SWang Nan */ 221fca08f32SWang Nan static void __kprobes 222fca08f32SWang Nan set_emulated_insn(probes_opcode_t insn, struct arch_probes_insn *asi, 223fca08f32SWang Nan bool thumb) 224fca08f32SWang Nan { 225fca08f32SWang Nan #ifdef CONFIG_THUMB2_KERNEL 226fca08f32SWang Nan if (thumb) { 227fca08f32SWang Nan u16 *ip = (u16 *)asi->insn; 228fca08f32SWang Nan if (is_wide_instruction(insn)) 229fca08f32SWang Nan *ip++ = __opcode_to_mem_thumb16(insn >> 16); 230fca08f32SWang Nan *ip++ = __opcode_to_mem_thumb16(insn); 231fca08f32SWang Nan return; 232fca08f32SWang Nan } 233fca08f32SWang Nan #endif 234fca08f32SWang Nan asi->insn[0] = __opcode_to_mem_arm(insn); 235fca08f32SWang Nan } 236fca08f32SWang Nan 237fca08f32SWang Nan /* 238fca08f32SWang Nan * When we modify the register numbers encoded in an instruction to be emulated, 239fca08f32SWang Nan * the new values come from this define. For ARM and 32-bit Thumb instructions 240fca08f32SWang Nan * this gives... 241fca08f32SWang Nan * 242fca08f32SWang Nan * bit position 16 12 8 4 0 243fca08f32SWang Nan * ---------------+---+---+---+---+---+ 244fca08f32SWang Nan * register r2 r0 r1 -- r3 245fca08f32SWang Nan */ 246fca08f32SWang Nan #define INSN_NEW_BITS 0x00020103 247fca08f32SWang Nan 248fca08f32SWang Nan /* Each nibble has same value as that at INSN_NEW_BITS bit 16 */ 249fca08f32SWang Nan #define INSN_SAMEAS16_BITS 0x22222222 250fca08f32SWang Nan 251fca08f32SWang Nan /* 252fca08f32SWang Nan * Validate and modify each of the registers encoded in an instruction. 253fca08f32SWang Nan * 254fca08f32SWang Nan * Each nibble in regs contains a value from enum decode_reg_type. For each 255fca08f32SWang Nan * non-zero value, the corresponding nibble in pinsn is validated and modified 256fca08f32SWang Nan * according to the type. 257fca08f32SWang Nan */ 258fca08f32SWang Nan static bool __kprobes decode_regs(probes_opcode_t *pinsn, u32 regs, bool modify) 259fca08f32SWang Nan { 260fca08f32SWang Nan probes_opcode_t insn = *pinsn; 261fca08f32SWang Nan probes_opcode_t mask = 0xf; /* Start at least significant nibble */ 262fca08f32SWang Nan 263fca08f32SWang Nan for (; regs != 0; regs >>= 4, mask <<= 4) { 264fca08f32SWang Nan 265fca08f32SWang Nan probes_opcode_t new_bits = INSN_NEW_BITS; 266fca08f32SWang Nan 267fca08f32SWang Nan switch (regs & 0xf) { 268fca08f32SWang Nan 269fca08f32SWang Nan case REG_TYPE_NONE: 270fca08f32SWang Nan /* Nibble not a register, skip to next */ 271fca08f32SWang Nan continue; 272fca08f32SWang Nan 273fca08f32SWang Nan case REG_TYPE_ANY: 274fca08f32SWang Nan /* Any register is allowed */ 275fca08f32SWang Nan break; 276fca08f32SWang Nan 277fca08f32SWang Nan case REG_TYPE_SAMEAS16: 278fca08f32SWang Nan /* Replace register with same as at bit position 16 */ 279fca08f32SWang Nan new_bits = INSN_SAMEAS16_BITS; 280fca08f32SWang Nan break; 281fca08f32SWang Nan 282fca08f32SWang Nan case REG_TYPE_SP: 283fca08f32SWang Nan /* Only allow SP (R13) */ 284fca08f32SWang Nan if ((insn ^ 0xdddddddd) & mask) 285fca08f32SWang Nan goto reject; 286fca08f32SWang Nan break; 287fca08f32SWang Nan 288fca08f32SWang Nan case REG_TYPE_PC: 289fca08f32SWang Nan /* Only allow PC (R15) */ 290fca08f32SWang Nan if ((insn ^ 0xffffffff) & mask) 291fca08f32SWang Nan goto reject; 292fca08f32SWang Nan break; 293fca08f32SWang Nan 294fca08f32SWang Nan case REG_TYPE_NOSP: 295fca08f32SWang Nan /* Reject SP (R13) */ 296fca08f32SWang Nan if (((insn ^ 0xdddddddd) & mask) == 0) 297fca08f32SWang Nan goto reject; 298fca08f32SWang Nan break; 299fca08f32SWang Nan 300fca08f32SWang Nan case REG_TYPE_NOSPPC: 301fca08f32SWang Nan case REG_TYPE_NOSPPCX: 302fca08f32SWang Nan /* Reject SP and PC (R13 and R15) */ 303fca08f32SWang Nan if (((insn ^ 0xdddddddd) & 0xdddddddd & mask) == 0) 304fca08f32SWang Nan goto reject; 305fca08f32SWang Nan break; 306fca08f32SWang Nan 307fca08f32SWang Nan case REG_TYPE_NOPCWB: 308fca08f32SWang Nan if (!is_writeback(insn)) 309fca08f32SWang Nan break; /* No writeback, so any register is OK */ 310*df561f66SGustavo A. R. Silva fallthrough; 311fca08f32SWang Nan case REG_TYPE_NOPC: 312fca08f32SWang Nan case REG_TYPE_NOPCX: 313fca08f32SWang Nan /* Reject PC (R15) */ 314fca08f32SWang Nan if (((insn ^ 0xffffffff) & mask) == 0) 315fca08f32SWang Nan goto reject; 316fca08f32SWang Nan break; 317fca08f32SWang Nan } 318fca08f32SWang Nan 319fca08f32SWang Nan /* Replace value of nibble with new register number... */ 320fca08f32SWang Nan insn &= ~mask; 321fca08f32SWang Nan insn |= new_bits & mask; 322fca08f32SWang Nan } 323fca08f32SWang Nan 324fca08f32SWang Nan if (modify) 325fca08f32SWang Nan *pinsn = insn; 326fca08f32SWang Nan 327fca08f32SWang Nan return true; 328fca08f32SWang Nan 329fca08f32SWang Nan reject: 330fca08f32SWang Nan return false; 331fca08f32SWang Nan } 332fca08f32SWang Nan 333fca08f32SWang Nan static const int decode_struct_sizes[NUM_DECODE_TYPES] = { 334fca08f32SWang Nan [DECODE_TYPE_TABLE] = sizeof(struct decode_table), 335fca08f32SWang Nan [DECODE_TYPE_CUSTOM] = sizeof(struct decode_custom), 336fca08f32SWang Nan [DECODE_TYPE_SIMULATE] = sizeof(struct decode_simulate), 337fca08f32SWang Nan [DECODE_TYPE_EMULATE] = sizeof(struct decode_emulate), 338fca08f32SWang Nan [DECODE_TYPE_OR] = sizeof(struct decode_or), 339fca08f32SWang Nan [DECODE_TYPE_REJECT] = sizeof(struct decode_reject) 340fca08f32SWang Nan }; 341fca08f32SWang Nan 34283803d97SWang Nan static int run_checkers(const struct decode_checker *checkers[], 34383803d97SWang Nan int action, probes_opcode_t insn, 34483803d97SWang Nan struct arch_probes_insn *asi, 34583803d97SWang Nan const struct decode_header *h) 34683803d97SWang Nan { 34783803d97SWang Nan const struct decode_checker **p; 34883803d97SWang Nan 34983803d97SWang Nan if (!checkers) 35083803d97SWang Nan return INSN_GOOD; 35183803d97SWang Nan 35283803d97SWang Nan p = checkers; 35383803d97SWang Nan while (*p != NULL) { 35483803d97SWang Nan int retval; 35583803d97SWang Nan probes_check_t *checker_func = (*p)[action].checker; 35683803d97SWang Nan 35783803d97SWang Nan retval = INSN_GOOD; 35883803d97SWang Nan if (checker_func) 35983803d97SWang Nan retval = checker_func(insn, asi, h); 36083803d97SWang Nan if (retval == INSN_REJECTED) 36183803d97SWang Nan return retval; 36283803d97SWang Nan p++; 36383803d97SWang Nan } 36483803d97SWang Nan return INSN_GOOD; 36583803d97SWang Nan } 36683803d97SWang Nan 367fca08f32SWang Nan /* 368fca08f32SWang Nan * probes_decode_insn operates on data tables in order to decode an ARM 369fca08f32SWang Nan * architecture instruction onto which a kprobe has been placed. 370fca08f32SWang Nan * 371fca08f32SWang Nan * These instruction decoding tables are a concatenation of entries each 372fca08f32SWang Nan * of which consist of one of the following structs: 373fca08f32SWang Nan * 374fca08f32SWang Nan * decode_table 375fca08f32SWang Nan * decode_custom 376fca08f32SWang Nan * decode_simulate 377fca08f32SWang Nan * decode_emulate 378fca08f32SWang Nan * decode_or 379fca08f32SWang Nan * decode_reject 380fca08f32SWang Nan * 381fca08f32SWang Nan * Each of these starts with a struct decode_header which has the following 382fca08f32SWang Nan * fields: 383fca08f32SWang Nan * 384fca08f32SWang Nan * type_regs 385fca08f32SWang Nan * mask 386fca08f32SWang Nan * value 387fca08f32SWang Nan * 388fca08f32SWang Nan * The least significant DECODE_TYPE_BITS of type_regs contains a value 389fca08f32SWang Nan * from enum decode_type, this indicates which of the decode_* structs 390fca08f32SWang Nan * the entry contains. The value DECODE_TYPE_END indicates the end of the 391fca08f32SWang Nan * table. 392fca08f32SWang Nan * 393fca08f32SWang Nan * When the table is parsed, each entry is checked in turn to see if it 394fca08f32SWang Nan * matches the instruction to be decoded using the test: 395fca08f32SWang Nan * 396fca08f32SWang Nan * (insn & mask) == value 397fca08f32SWang Nan * 398fca08f32SWang Nan * If no match is found before the end of the table is reached then decoding 399fca08f32SWang Nan * fails with INSN_REJECTED. 400fca08f32SWang Nan * 401fca08f32SWang Nan * When a match is found, decode_regs() is called to validate and modify each 402fca08f32SWang Nan * of the registers encoded in the instruction; the data it uses to do this 403fca08f32SWang Nan * is (type_regs >> DECODE_TYPE_BITS). A validation failure will cause decoding 404fca08f32SWang Nan * to fail with INSN_REJECTED. 405fca08f32SWang Nan * 406fca08f32SWang Nan * Once the instruction has passed the above tests, further processing 407fca08f32SWang Nan * depends on the type of the table entry's decode struct. 408fca08f32SWang Nan * 409fca08f32SWang Nan */ 410fca08f32SWang Nan int __kprobes 411fca08f32SWang Nan probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, 412fca08f32SWang Nan const union decode_item *table, bool thumb, 41383803d97SWang Nan bool emulate, const union decode_action *actions, 41483803d97SWang Nan const struct decode_checker *checkers[]) 415fca08f32SWang Nan { 416fca08f32SWang Nan const struct decode_header *h = (struct decode_header *)table; 417fca08f32SWang Nan const struct decode_header *next; 418fca08f32SWang Nan bool matched = false; 41983803d97SWang Nan /* 42083803d97SWang Nan * @insn can be modified by decode_regs. Save its original 42183803d97SWang Nan * value for checkers. 42283803d97SWang Nan */ 42383803d97SWang Nan probes_opcode_t origin_insn = insn; 424fca08f32SWang Nan 4256624cf65SWang Nan /* 4266624cf65SWang Nan * stack_space is initialized to 0 here. Checker functions 4276624cf65SWang Nan * should update is value if they find this is a stack store 4286624cf65SWang Nan * instruction: positive value means bytes of stack usage, 4296624cf65SWang Nan * negitive value means unable to determine stack usage 4306624cf65SWang Nan * statically. For instruction doesn't store to stack, checker 4316624cf65SWang Nan * do nothing with it. 4326624cf65SWang Nan */ 4336624cf65SWang Nan asi->stack_space = 0; 4346624cf65SWang Nan 43528a1899dSWang Nan /* 43628a1899dSWang Nan * Similarly to stack_space, register_usage_flags is filled by 43728a1899dSWang Nan * checkers. Its default value is set to ~0, which is 'all 43828a1899dSWang Nan * registers are used', to prevent any potential optimization. 43928a1899dSWang Nan */ 44028a1899dSWang Nan asi->register_usage_flags = ~0UL; 44128a1899dSWang Nan 442fca08f32SWang Nan if (emulate) 443fca08f32SWang Nan insn = prepare_emulated_insn(insn, asi, thumb); 444fca08f32SWang Nan 445fca08f32SWang Nan for (;; h = next) { 446fca08f32SWang Nan enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK; 447fca08f32SWang Nan u32 regs = h->type_regs.bits >> DECODE_TYPE_BITS; 448fca08f32SWang Nan 449fca08f32SWang Nan if (type == DECODE_TYPE_END) 450fca08f32SWang Nan return INSN_REJECTED; 451fca08f32SWang Nan 452fca08f32SWang Nan next = (struct decode_header *) 453fca08f32SWang Nan ((uintptr_t)h + decode_struct_sizes[type]); 454fca08f32SWang Nan 455fca08f32SWang Nan if (!matched && (insn & h->mask.bits) != h->value.bits) 456fca08f32SWang Nan continue; 457fca08f32SWang Nan 458fca08f32SWang Nan if (!decode_regs(&insn, regs, emulate)) 459fca08f32SWang Nan return INSN_REJECTED; 460fca08f32SWang Nan 461fca08f32SWang Nan switch (type) { 462fca08f32SWang Nan 463fca08f32SWang Nan case DECODE_TYPE_TABLE: { 464fca08f32SWang Nan struct decode_table *d = (struct decode_table *)h; 465fca08f32SWang Nan next = (struct decode_header *)d->table.table; 466fca08f32SWang Nan break; 467fca08f32SWang Nan } 468fca08f32SWang Nan 469fca08f32SWang Nan case DECODE_TYPE_CUSTOM: { 47083803d97SWang Nan int err; 471fca08f32SWang Nan struct decode_custom *d = (struct decode_custom *)h; 47283803d97SWang Nan int action = d->decoder.action; 47383803d97SWang Nan 47483803d97SWang Nan err = run_checkers(checkers, action, origin_insn, asi, h); 47583803d97SWang Nan if (err == INSN_REJECTED) 47683803d97SWang Nan return INSN_REJECTED; 47783803d97SWang Nan return actions[action].decoder(insn, asi, h); 478fca08f32SWang Nan } 479fca08f32SWang Nan 480fca08f32SWang Nan case DECODE_TYPE_SIMULATE: { 48183803d97SWang Nan int err; 482fca08f32SWang Nan struct decode_simulate *d = (struct decode_simulate *)h; 48383803d97SWang Nan int action = d->handler.action; 48483803d97SWang Nan 48583803d97SWang Nan err = run_checkers(checkers, action, origin_insn, asi, h); 48683803d97SWang Nan if (err == INSN_REJECTED) 48783803d97SWang Nan return INSN_REJECTED; 48883803d97SWang Nan asi->insn_handler = actions[action].handler; 489fca08f32SWang Nan return INSN_GOOD_NO_SLOT; 490fca08f32SWang Nan } 491fca08f32SWang Nan 492fca08f32SWang Nan case DECODE_TYPE_EMULATE: { 49383803d97SWang Nan int err; 494fca08f32SWang Nan struct decode_emulate *d = (struct decode_emulate *)h; 49583803d97SWang Nan int action = d->handler.action; 49683803d97SWang Nan 49783803d97SWang Nan err = run_checkers(checkers, action, origin_insn, asi, h); 49883803d97SWang Nan if (err == INSN_REJECTED) 49983803d97SWang Nan return INSN_REJECTED; 500fca08f32SWang Nan 501fca08f32SWang Nan if (!emulate) 50283803d97SWang Nan return actions[action].decoder(insn, asi, h); 503fca08f32SWang Nan 50483803d97SWang Nan asi->insn_handler = actions[action].handler; 505fca08f32SWang Nan set_emulated_insn(insn, asi, thumb); 506fca08f32SWang Nan return INSN_GOOD; 507fca08f32SWang Nan } 508fca08f32SWang Nan 509fca08f32SWang Nan case DECODE_TYPE_OR: 510fca08f32SWang Nan matched = true; 511fca08f32SWang Nan break; 512fca08f32SWang Nan 513fca08f32SWang Nan case DECODE_TYPE_REJECT: 514fca08f32SWang Nan default: 515fca08f32SWang Nan return INSN_REJECTED; 516fca08f32SWang Nan } 517fca08f32SWang Nan } 518fca08f32SWang Nan } 519