1fca08f32SWang Nan /* 2fca08f32SWang Nan * arch/arm/probes/decode.c 3fca08f32SWang Nan * 4fca08f32SWang Nan * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. 5fca08f32SWang Nan * 6fca08f32SWang Nan * Some contents moved here from arch/arm/include/asm/kprobes-arm.c which is 7fca08f32SWang Nan * Copyright (C) 2006, 2007 Motorola Inc. 8fca08f32SWang Nan * 9fca08f32SWang Nan * This program is free software; you can redistribute it and/or modify 10fca08f32SWang Nan * it under the terms of the GNU General Public License version 2 as 11fca08f32SWang Nan * published by the Free Software Foundation. 12fca08f32SWang Nan */ 13fca08f32SWang Nan 14fca08f32SWang Nan #include <linux/kernel.h> 15fca08f32SWang Nan #include <linux/types.h> 16fca08f32SWang Nan #include <asm/system_info.h> 17fca08f32SWang Nan #include <asm/ptrace.h> 18fca08f32SWang Nan #include <linux/bug.h> 19fca08f32SWang Nan 20fca08f32SWang Nan #include "decode.h" 21fca08f32SWang Nan 22fca08f32SWang Nan 23fca08f32SWang Nan #ifndef find_str_pc_offset 24fca08f32SWang Nan 25fca08f32SWang Nan /* 26fca08f32SWang Nan * For STR and STM instructions, an ARM core may choose to use either 27fca08f32SWang Nan * a +8 or a +12 displacement from the current instruction's address. 28fca08f32SWang Nan * Whichever value is chosen for a given core, it must be the same for 29fca08f32SWang Nan * both instructions and may not change. This function measures it. 30fca08f32SWang Nan */ 31fca08f32SWang Nan 32fca08f32SWang Nan int str_pc_offset; 33fca08f32SWang Nan 34fca08f32SWang Nan void __init find_str_pc_offset(void) 35fca08f32SWang Nan { 36fca08f32SWang Nan int addr, scratch, ret; 37fca08f32SWang Nan 38fca08f32SWang Nan __asm__ ( 39fca08f32SWang Nan "sub %[ret], pc, #4 \n\t" 40fca08f32SWang Nan "str pc, %[addr] \n\t" 41fca08f32SWang Nan "ldr %[scr], %[addr] \n\t" 42fca08f32SWang Nan "sub %[ret], %[scr], %[ret] \n\t" 43fca08f32SWang Nan : [ret] "=r" (ret), [scr] "=r" (scratch), [addr] "+m" (addr)); 44fca08f32SWang Nan 45fca08f32SWang Nan str_pc_offset = ret; 46fca08f32SWang Nan } 47fca08f32SWang Nan 48fca08f32SWang Nan #endif /* !find_str_pc_offset */ 49fca08f32SWang Nan 50fca08f32SWang Nan 51fca08f32SWang Nan #ifndef test_load_write_pc_interworking 52fca08f32SWang Nan 53fca08f32SWang Nan bool load_write_pc_interworks; 54fca08f32SWang Nan 55fca08f32SWang Nan void __init test_load_write_pc_interworking(void) 56fca08f32SWang Nan { 57fca08f32SWang Nan int arch = cpu_architecture(); 58fca08f32SWang Nan BUG_ON(arch == CPU_ARCH_UNKNOWN); 59fca08f32SWang Nan load_write_pc_interworks = arch >= CPU_ARCH_ARMv5T; 60fca08f32SWang Nan } 61fca08f32SWang Nan 62fca08f32SWang Nan #endif /* !test_load_write_pc_interworking */ 63fca08f32SWang Nan 64fca08f32SWang Nan 65fca08f32SWang Nan #ifndef test_alu_write_pc_interworking 66fca08f32SWang Nan 67fca08f32SWang Nan bool alu_write_pc_interworks; 68fca08f32SWang Nan 69fca08f32SWang Nan void __init test_alu_write_pc_interworking(void) 70fca08f32SWang Nan { 71fca08f32SWang Nan int arch = cpu_architecture(); 72fca08f32SWang Nan BUG_ON(arch == CPU_ARCH_UNKNOWN); 73fca08f32SWang Nan alu_write_pc_interworks = arch >= CPU_ARCH_ARMv7; 74fca08f32SWang Nan } 75fca08f32SWang Nan 76fca08f32SWang Nan #endif /* !test_alu_write_pc_interworking */ 77fca08f32SWang Nan 78fca08f32SWang Nan 79fca08f32SWang Nan void __init arm_probes_decode_init(void) 80fca08f32SWang Nan { 81fca08f32SWang Nan find_str_pc_offset(); 82fca08f32SWang Nan test_load_write_pc_interworking(); 83fca08f32SWang Nan test_alu_write_pc_interworking(); 84fca08f32SWang Nan } 85fca08f32SWang Nan 86fca08f32SWang Nan 87fca08f32SWang Nan static unsigned long __kprobes __check_eq(unsigned long cpsr) 88fca08f32SWang Nan { 89fca08f32SWang Nan return cpsr & PSR_Z_BIT; 90fca08f32SWang Nan } 91fca08f32SWang Nan 92fca08f32SWang Nan static unsigned long __kprobes __check_ne(unsigned long cpsr) 93fca08f32SWang Nan { 94fca08f32SWang Nan return (~cpsr) & PSR_Z_BIT; 95fca08f32SWang Nan } 96fca08f32SWang Nan 97fca08f32SWang Nan static unsigned long __kprobes __check_cs(unsigned long cpsr) 98fca08f32SWang Nan { 99fca08f32SWang Nan return cpsr & PSR_C_BIT; 100fca08f32SWang Nan } 101fca08f32SWang Nan 102fca08f32SWang Nan static unsigned long __kprobes __check_cc(unsigned long cpsr) 103fca08f32SWang Nan { 104fca08f32SWang Nan return (~cpsr) & PSR_C_BIT; 105fca08f32SWang Nan } 106fca08f32SWang Nan 107fca08f32SWang Nan static unsigned long __kprobes __check_mi(unsigned long cpsr) 108fca08f32SWang Nan { 109fca08f32SWang Nan return cpsr & PSR_N_BIT; 110fca08f32SWang Nan } 111fca08f32SWang Nan 112fca08f32SWang Nan static unsigned long __kprobes __check_pl(unsigned long cpsr) 113fca08f32SWang Nan { 114fca08f32SWang Nan return (~cpsr) & PSR_N_BIT; 115fca08f32SWang Nan } 116fca08f32SWang Nan 117fca08f32SWang Nan static unsigned long __kprobes __check_vs(unsigned long cpsr) 118fca08f32SWang Nan { 119fca08f32SWang Nan return cpsr & PSR_V_BIT; 120fca08f32SWang Nan } 121fca08f32SWang Nan 122fca08f32SWang Nan static unsigned long __kprobes __check_vc(unsigned long cpsr) 123fca08f32SWang Nan { 124fca08f32SWang Nan return (~cpsr) & PSR_V_BIT; 125fca08f32SWang Nan } 126fca08f32SWang Nan 127fca08f32SWang Nan static unsigned long __kprobes __check_hi(unsigned long cpsr) 128fca08f32SWang Nan { 129fca08f32SWang Nan cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */ 130fca08f32SWang Nan return cpsr & PSR_C_BIT; 131fca08f32SWang Nan } 132fca08f32SWang Nan 133fca08f32SWang Nan static unsigned long __kprobes __check_ls(unsigned long cpsr) 134fca08f32SWang Nan { 135fca08f32SWang Nan cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */ 136fca08f32SWang Nan return (~cpsr) & PSR_C_BIT; 137fca08f32SWang Nan } 138fca08f32SWang Nan 139fca08f32SWang Nan static unsigned long __kprobes __check_ge(unsigned long cpsr) 140fca08f32SWang Nan { 141fca08f32SWang Nan cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ 142fca08f32SWang Nan return (~cpsr) & PSR_N_BIT; 143fca08f32SWang Nan } 144fca08f32SWang Nan 145fca08f32SWang Nan static unsigned long __kprobes __check_lt(unsigned long cpsr) 146fca08f32SWang Nan { 147fca08f32SWang Nan cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ 148fca08f32SWang Nan return cpsr & PSR_N_BIT; 149fca08f32SWang Nan } 150fca08f32SWang Nan 151fca08f32SWang Nan static unsigned long __kprobes __check_gt(unsigned long cpsr) 152fca08f32SWang Nan { 153fca08f32SWang Nan unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ 154fca08f32SWang Nan temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */ 155fca08f32SWang Nan return (~temp) & PSR_N_BIT; 156fca08f32SWang Nan } 157fca08f32SWang Nan 158fca08f32SWang Nan static unsigned long __kprobes __check_le(unsigned long cpsr) 159fca08f32SWang Nan { 160fca08f32SWang Nan unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ 161fca08f32SWang Nan temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */ 162fca08f32SWang Nan return temp & PSR_N_BIT; 163fca08f32SWang Nan } 164fca08f32SWang Nan 165fca08f32SWang Nan static unsigned long __kprobes __check_al(unsigned long cpsr) 166fca08f32SWang Nan { 167fca08f32SWang Nan return true; 168fca08f32SWang Nan } 169fca08f32SWang Nan 170fca08f32SWang Nan probes_check_cc * const probes_condition_checks[16] = { 171fca08f32SWang Nan &__check_eq, &__check_ne, &__check_cs, &__check_cc, 172fca08f32SWang Nan &__check_mi, &__check_pl, &__check_vs, &__check_vc, 173fca08f32SWang Nan &__check_hi, &__check_ls, &__check_ge, &__check_lt, 174fca08f32SWang Nan &__check_gt, &__check_le, &__check_al, &__check_al 175fca08f32SWang Nan }; 176fca08f32SWang Nan 177fca08f32SWang Nan 178fca08f32SWang Nan void __kprobes probes_simulate_nop(probes_opcode_t opcode, 179fca08f32SWang Nan struct arch_probes_insn *asi, 180fca08f32SWang Nan struct pt_regs *regs) 181fca08f32SWang Nan { 182fca08f32SWang Nan } 183fca08f32SWang Nan 184fca08f32SWang Nan void __kprobes probes_emulate_none(probes_opcode_t opcode, 185fca08f32SWang Nan struct arch_probes_insn *asi, 186fca08f32SWang Nan struct pt_regs *regs) 187fca08f32SWang Nan { 188fca08f32SWang Nan asi->insn_fn(); 189fca08f32SWang Nan } 190fca08f32SWang Nan 191fca08f32SWang Nan /* 192fca08f32SWang Nan * Prepare an instruction slot to receive an instruction for emulating. 193fca08f32SWang Nan * This is done by placing a subroutine return after the location where the 194fca08f32SWang Nan * instruction will be placed. We also modify ARM instructions to be 195fca08f32SWang Nan * unconditional as the condition code will already be checked before any 196fca08f32SWang Nan * emulation handler is called. 197fca08f32SWang Nan */ 198fca08f32SWang Nan static probes_opcode_t __kprobes 199fca08f32SWang Nan prepare_emulated_insn(probes_opcode_t insn, struct arch_probes_insn *asi, 200fca08f32SWang Nan bool thumb) 201fca08f32SWang Nan { 202fca08f32SWang Nan #ifdef CONFIG_THUMB2_KERNEL 203fca08f32SWang Nan if (thumb) { 204fca08f32SWang Nan u16 *thumb_insn = (u16 *)asi->insn; 205fca08f32SWang Nan /* Thumb bx lr */ 206fca08f32SWang Nan thumb_insn[1] = __opcode_to_mem_thumb16(0x4770); 207fca08f32SWang Nan thumb_insn[2] = __opcode_to_mem_thumb16(0x4770); 208fca08f32SWang Nan return insn; 209fca08f32SWang Nan } 210fca08f32SWang Nan asi->insn[1] = __opcode_to_mem_arm(0xe12fff1e); /* ARM bx lr */ 211fca08f32SWang Nan #else 212fca08f32SWang Nan asi->insn[1] = __opcode_to_mem_arm(0xe1a0f00e); /* mov pc, lr */ 213fca08f32SWang Nan #endif 214fca08f32SWang Nan /* Make an ARM instruction unconditional */ 215fca08f32SWang Nan if (insn < 0xe0000000) 216fca08f32SWang Nan insn = (insn | 0xe0000000) & ~0x10000000; 217fca08f32SWang Nan return insn; 218fca08f32SWang Nan } 219fca08f32SWang Nan 220fca08f32SWang Nan /* 221fca08f32SWang Nan * Write a (probably modified) instruction into the slot previously prepared by 222fca08f32SWang Nan * prepare_emulated_insn 223fca08f32SWang Nan */ 224fca08f32SWang Nan static void __kprobes 225fca08f32SWang Nan set_emulated_insn(probes_opcode_t insn, struct arch_probes_insn *asi, 226fca08f32SWang Nan bool thumb) 227fca08f32SWang Nan { 228fca08f32SWang Nan #ifdef CONFIG_THUMB2_KERNEL 229fca08f32SWang Nan if (thumb) { 230fca08f32SWang Nan u16 *ip = (u16 *)asi->insn; 231fca08f32SWang Nan if (is_wide_instruction(insn)) 232fca08f32SWang Nan *ip++ = __opcode_to_mem_thumb16(insn >> 16); 233fca08f32SWang Nan *ip++ = __opcode_to_mem_thumb16(insn); 234fca08f32SWang Nan return; 235fca08f32SWang Nan } 236fca08f32SWang Nan #endif 237fca08f32SWang Nan asi->insn[0] = __opcode_to_mem_arm(insn); 238fca08f32SWang Nan } 239fca08f32SWang Nan 240fca08f32SWang Nan /* 241fca08f32SWang Nan * When we modify the register numbers encoded in an instruction to be emulated, 242fca08f32SWang Nan * the new values come from this define. For ARM and 32-bit Thumb instructions 243fca08f32SWang Nan * this gives... 244fca08f32SWang Nan * 245fca08f32SWang Nan * bit position 16 12 8 4 0 246fca08f32SWang Nan * ---------------+---+---+---+---+---+ 247fca08f32SWang Nan * register r2 r0 r1 -- r3 248fca08f32SWang Nan */ 249fca08f32SWang Nan #define INSN_NEW_BITS 0x00020103 250fca08f32SWang Nan 251fca08f32SWang Nan /* Each nibble has same value as that at INSN_NEW_BITS bit 16 */ 252fca08f32SWang Nan #define INSN_SAMEAS16_BITS 0x22222222 253fca08f32SWang Nan 254fca08f32SWang Nan /* 255fca08f32SWang Nan * Validate and modify each of the registers encoded in an instruction. 256fca08f32SWang Nan * 257fca08f32SWang Nan * Each nibble in regs contains a value from enum decode_reg_type. For each 258fca08f32SWang Nan * non-zero value, the corresponding nibble in pinsn is validated and modified 259fca08f32SWang Nan * according to the type. 260fca08f32SWang Nan */ 261fca08f32SWang Nan static bool __kprobes decode_regs(probes_opcode_t *pinsn, u32 regs, bool modify) 262fca08f32SWang Nan { 263fca08f32SWang Nan probes_opcode_t insn = *pinsn; 264fca08f32SWang Nan probes_opcode_t mask = 0xf; /* Start at least significant nibble */ 265fca08f32SWang Nan 266fca08f32SWang Nan for (; regs != 0; regs >>= 4, mask <<= 4) { 267fca08f32SWang Nan 268fca08f32SWang Nan probes_opcode_t new_bits = INSN_NEW_BITS; 269fca08f32SWang Nan 270fca08f32SWang Nan switch (regs & 0xf) { 271fca08f32SWang Nan 272fca08f32SWang Nan case REG_TYPE_NONE: 273fca08f32SWang Nan /* Nibble not a register, skip to next */ 274fca08f32SWang Nan continue; 275fca08f32SWang Nan 276fca08f32SWang Nan case REG_TYPE_ANY: 277fca08f32SWang Nan /* Any register is allowed */ 278fca08f32SWang Nan break; 279fca08f32SWang Nan 280fca08f32SWang Nan case REG_TYPE_SAMEAS16: 281fca08f32SWang Nan /* Replace register with same as at bit position 16 */ 282fca08f32SWang Nan new_bits = INSN_SAMEAS16_BITS; 283fca08f32SWang Nan break; 284fca08f32SWang Nan 285fca08f32SWang Nan case REG_TYPE_SP: 286fca08f32SWang Nan /* Only allow SP (R13) */ 287fca08f32SWang Nan if ((insn ^ 0xdddddddd) & mask) 288fca08f32SWang Nan goto reject; 289fca08f32SWang Nan break; 290fca08f32SWang Nan 291fca08f32SWang Nan case REG_TYPE_PC: 292fca08f32SWang Nan /* Only allow PC (R15) */ 293fca08f32SWang Nan if ((insn ^ 0xffffffff) & mask) 294fca08f32SWang Nan goto reject; 295fca08f32SWang Nan break; 296fca08f32SWang Nan 297fca08f32SWang Nan case REG_TYPE_NOSP: 298fca08f32SWang Nan /* Reject SP (R13) */ 299fca08f32SWang Nan if (((insn ^ 0xdddddddd) & mask) == 0) 300fca08f32SWang Nan goto reject; 301fca08f32SWang Nan break; 302fca08f32SWang Nan 303fca08f32SWang Nan case REG_TYPE_NOSPPC: 304fca08f32SWang Nan case REG_TYPE_NOSPPCX: 305fca08f32SWang Nan /* Reject SP and PC (R13 and R15) */ 306fca08f32SWang Nan if (((insn ^ 0xdddddddd) & 0xdddddddd & mask) == 0) 307fca08f32SWang Nan goto reject; 308fca08f32SWang Nan break; 309fca08f32SWang Nan 310fca08f32SWang Nan case REG_TYPE_NOPCWB: 311fca08f32SWang Nan if (!is_writeback(insn)) 312fca08f32SWang Nan break; /* No writeback, so any register is OK */ 313fca08f32SWang Nan /* fall through... */ 314fca08f32SWang Nan case REG_TYPE_NOPC: 315fca08f32SWang Nan case REG_TYPE_NOPCX: 316fca08f32SWang Nan /* Reject PC (R15) */ 317fca08f32SWang Nan if (((insn ^ 0xffffffff) & mask) == 0) 318fca08f32SWang Nan goto reject; 319fca08f32SWang Nan break; 320fca08f32SWang Nan } 321fca08f32SWang Nan 322fca08f32SWang Nan /* Replace value of nibble with new register number... */ 323fca08f32SWang Nan insn &= ~mask; 324fca08f32SWang Nan insn |= new_bits & mask; 325fca08f32SWang Nan } 326fca08f32SWang Nan 327fca08f32SWang Nan if (modify) 328fca08f32SWang Nan *pinsn = insn; 329fca08f32SWang Nan 330fca08f32SWang Nan return true; 331fca08f32SWang Nan 332fca08f32SWang Nan reject: 333fca08f32SWang Nan return false; 334fca08f32SWang Nan } 335fca08f32SWang Nan 336fca08f32SWang Nan static const int decode_struct_sizes[NUM_DECODE_TYPES] = { 337fca08f32SWang Nan [DECODE_TYPE_TABLE] = sizeof(struct decode_table), 338fca08f32SWang Nan [DECODE_TYPE_CUSTOM] = sizeof(struct decode_custom), 339fca08f32SWang Nan [DECODE_TYPE_SIMULATE] = sizeof(struct decode_simulate), 340fca08f32SWang Nan [DECODE_TYPE_EMULATE] = sizeof(struct decode_emulate), 341fca08f32SWang Nan [DECODE_TYPE_OR] = sizeof(struct decode_or), 342fca08f32SWang Nan [DECODE_TYPE_REJECT] = sizeof(struct decode_reject) 343fca08f32SWang Nan }; 344fca08f32SWang Nan 345*83803d97SWang Nan static int run_checkers(const struct decode_checker *checkers[], 346*83803d97SWang Nan int action, probes_opcode_t insn, 347*83803d97SWang Nan struct arch_probes_insn *asi, 348*83803d97SWang Nan const struct decode_header *h) 349*83803d97SWang Nan { 350*83803d97SWang Nan const struct decode_checker **p; 351*83803d97SWang Nan 352*83803d97SWang Nan if (!checkers) 353*83803d97SWang Nan return INSN_GOOD; 354*83803d97SWang Nan 355*83803d97SWang Nan p = checkers; 356*83803d97SWang Nan while (*p != NULL) { 357*83803d97SWang Nan int retval; 358*83803d97SWang Nan probes_check_t *checker_func = (*p)[action].checker; 359*83803d97SWang Nan 360*83803d97SWang Nan retval = INSN_GOOD; 361*83803d97SWang Nan if (checker_func) 362*83803d97SWang Nan retval = checker_func(insn, asi, h); 363*83803d97SWang Nan if (retval == INSN_REJECTED) 364*83803d97SWang Nan return retval; 365*83803d97SWang Nan p++; 366*83803d97SWang Nan } 367*83803d97SWang Nan return INSN_GOOD; 368*83803d97SWang Nan } 369*83803d97SWang Nan 370fca08f32SWang Nan /* 371fca08f32SWang Nan * probes_decode_insn operates on data tables in order to decode an ARM 372fca08f32SWang Nan * architecture instruction onto which a kprobe has been placed. 373fca08f32SWang Nan * 374fca08f32SWang Nan * These instruction decoding tables are a concatenation of entries each 375fca08f32SWang Nan * of which consist of one of the following structs: 376fca08f32SWang Nan * 377fca08f32SWang Nan * decode_table 378fca08f32SWang Nan * decode_custom 379fca08f32SWang Nan * decode_simulate 380fca08f32SWang Nan * decode_emulate 381fca08f32SWang Nan * decode_or 382fca08f32SWang Nan * decode_reject 383fca08f32SWang Nan * 384fca08f32SWang Nan * Each of these starts with a struct decode_header which has the following 385fca08f32SWang Nan * fields: 386fca08f32SWang Nan * 387fca08f32SWang Nan * type_regs 388fca08f32SWang Nan * mask 389fca08f32SWang Nan * value 390fca08f32SWang Nan * 391fca08f32SWang Nan * The least significant DECODE_TYPE_BITS of type_regs contains a value 392fca08f32SWang Nan * from enum decode_type, this indicates which of the decode_* structs 393fca08f32SWang Nan * the entry contains. The value DECODE_TYPE_END indicates the end of the 394fca08f32SWang Nan * table. 395fca08f32SWang Nan * 396fca08f32SWang Nan * When the table is parsed, each entry is checked in turn to see if it 397fca08f32SWang Nan * matches the instruction to be decoded using the test: 398fca08f32SWang Nan * 399fca08f32SWang Nan * (insn & mask) == value 400fca08f32SWang Nan * 401fca08f32SWang Nan * If no match is found before the end of the table is reached then decoding 402fca08f32SWang Nan * fails with INSN_REJECTED. 403fca08f32SWang Nan * 404fca08f32SWang Nan * When a match is found, decode_regs() is called to validate and modify each 405fca08f32SWang Nan * of the registers encoded in the instruction; the data it uses to do this 406fca08f32SWang Nan * is (type_regs >> DECODE_TYPE_BITS). A validation failure will cause decoding 407fca08f32SWang Nan * to fail with INSN_REJECTED. 408fca08f32SWang Nan * 409fca08f32SWang Nan * Once the instruction has passed the above tests, further processing 410fca08f32SWang Nan * depends on the type of the table entry's decode struct. 411fca08f32SWang Nan * 412fca08f32SWang Nan */ 413fca08f32SWang Nan int __kprobes 414fca08f32SWang Nan probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, 415fca08f32SWang Nan const union decode_item *table, bool thumb, 416*83803d97SWang Nan bool emulate, const union decode_action *actions, 417*83803d97SWang Nan const struct decode_checker *checkers[]) 418fca08f32SWang Nan { 419fca08f32SWang Nan const struct decode_header *h = (struct decode_header *)table; 420fca08f32SWang Nan const struct decode_header *next; 421fca08f32SWang Nan bool matched = false; 422*83803d97SWang Nan /* 423*83803d97SWang Nan * @insn can be modified by decode_regs. Save its original 424*83803d97SWang Nan * value for checkers. 425*83803d97SWang Nan */ 426*83803d97SWang Nan probes_opcode_t origin_insn = insn; 427fca08f32SWang Nan 428fca08f32SWang Nan if (emulate) 429fca08f32SWang Nan insn = prepare_emulated_insn(insn, asi, thumb); 430fca08f32SWang Nan 431fca08f32SWang Nan for (;; h = next) { 432fca08f32SWang Nan enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK; 433fca08f32SWang Nan u32 regs = h->type_regs.bits >> DECODE_TYPE_BITS; 434fca08f32SWang Nan 435fca08f32SWang Nan if (type == DECODE_TYPE_END) 436fca08f32SWang Nan return INSN_REJECTED; 437fca08f32SWang Nan 438fca08f32SWang Nan next = (struct decode_header *) 439fca08f32SWang Nan ((uintptr_t)h + decode_struct_sizes[type]); 440fca08f32SWang Nan 441fca08f32SWang Nan if (!matched && (insn & h->mask.bits) != h->value.bits) 442fca08f32SWang Nan continue; 443fca08f32SWang Nan 444fca08f32SWang Nan if (!decode_regs(&insn, regs, emulate)) 445fca08f32SWang Nan return INSN_REJECTED; 446fca08f32SWang Nan 447fca08f32SWang Nan switch (type) { 448fca08f32SWang Nan 449fca08f32SWang Nan case DECODE_TYPE_TABLE: { 450fca08f32SWang Nan struct decode_table *d = (struct decode_table *)h; 451fca08f32SWang Nan next = (struct decode_header *)d->table.table; 452fca08f32SWang Nan break; 453fca08f32SWang Nan } 454fca08f32SWang Nan 455fca08f32SWang Nan case DECODE_TYPE_CUSTOM: { 456*83803d97SWang Nan int err; 457fca08f32SWang Nan struct decode_custom *d = (struct decode_custom *)h; 458*83803d97SWang Nan int action = d->decoder.action; 459*83803d97SWang Nan 460*83803d97SWang Nan err = run_checkers(checkers, action, origin_insn, asi, h); 461*83803d97SWang Nan if (err == INSN_REJECTED) 462*83803d97SWang Nan return INSN_REJECTED; 463*83803d97SWang Nan return actions[action].decoder(insn, asi, h); 464fca08f32SWang Nan } 465fca08f32SWang Nan 466fca08f32SWang Nan case DECODE_TYPE_SIMULATE: { 467*83803d97SWang Nan int err; 468fca08f32SWang Nan struct decode_simulate *d = (struct decode_simulate *)h; 469*83803d97SWang Nan int action = d->handler.action; 470*83803d97SWang Nan 471*83803d97SWang Nan err = run_checkers(checkers, action, origin_insn, asi, h); 472*83803d97SWang Nan if (err == INSN_REJECTED) 473*83803d97SWang Nan return INSN_REJECTED; 474*83803d97SWang Nan asi->insn_handler = actions[action].handler; 475fca08f32SWang Nan return INSN_GOOD_NO_SLOT; 476fca08f32SWang Nan } 477fca08f32SWang Nan 478fca08f32SWang Nan case DECODE_TYPE_EMULATE: { 479*83803d97SWang Nan int err; 480fca08f32SWang Nan struct decode_emulate *d = (struct decode_emulate *)h; 481*83803d97SWang Nan int action = d->handler.action; 482*83803d97SWang Nan 483*83803d97SWang Nan err = run_checkers(checkers, action, origin_insn, asi, h); 484*83803d97SWang Nan if (err == INSN_REJECTED) 485*83803d97SWang Nan return INSN_REJECTED; 486fca08f32SWang Nan 487fca08f32SWang Nan if (!emulate) 488*83803d97SWang Nan return actions[action].decoder(insn, asi, h); 489fca08f32SWang Nan 490*83803d97SWang Nan asi->insn_handler = actions[action].handler; 491fca08f32SWang Nan set_emulated_insn(insn, asi, thumb); 492fca08f32SWang Nan return INSN_GOOD; 493fca08f32SWang Nan } 494fca08f32SWang Nan 495fca08f32SWang Nan case DECODE_TYPE_OR: 496fca08f32SWang Nan matched = true; 497fca08f32SWang Nan break; 498fca08f32SWang Nan 499fca08f32SWang Nan case DECODE_TYPE_REJECT: 500fca08f32SWang Nan default: 501fca08f32SWang Nan return INSN_REJECTED; 502fca08f32SWang Nan } 503fca08f32SWang Nan } 504fca08f32SWang Nan } 505