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