static int do_alignment_ldrhstrh(unsigned long addr, unsigned long instr, struct pt_regs *regs) { unsigned int rd = RD_BITS(instr); if ((instr & 0x01f00ff0) == 0x01000090) goto swp; if ((instr & 0x90) != 0x90 || (instr & 0x60) == 0) goto bad; ai_half += 1; if (LDST_L_BIT(instr)) { unsigned long val; get16_unaligned_check(val, addr); /* signed half-word? */ if (instr & 0x40) val = (signed long)((signed short) val); regs->uregs[rd] = val; } else put16_unaligned_check(regs->uregs[rd], addr); return TYPE_LDST; swp: printk(KERN_ERR "Alignment trap: not handling swp instruction\n"); bad: return TYPE_ERROR; fault: return TYPE_FAULT; }
static void fixup_load(struct disasm_state *state, struct pt_regs *regs, struct callee_regs *cregs) { int val; /* register write back */ if ((state->aa == 1) || (state->aa == 2)) { set_reg(state->wb_reg, state->src1 + state->src2, regs, cregs); if (state->aa == 2) state->src2 = 0; } if (state->zz == 0) { get32_unaligned_check(val, state->src1 + state->src2); } else { get16_unaligned_check(val, state->src1 + state->src2); if (state->x) val = (val << 16) >> 16; } if (state->pref == 0) set_reg(state->dest, val, regs, cregs); return; fault: state->fault = 1; }
static int do_alignment_ldrhstrh(unsigned long addr, unsigned long instr, struct pt_regs *regs) { unsigned int rd = RD_BITS(instr); if ((instr & 0x4b003fe0) == 0x40000120) /* old value 0x40002120, can't judge swap instr correctly */ goto swp; ai_half += 1; if (LDST_L_BIT(instr)) { unsigned long val; get16_unaligned_check(val, addr); /* signed half-word? */ if (instr & 0x80) val = (signed long)((signed short) val); regs->uregs[rd] = val; } else put16_unaligned_check(regs->uregs[rd], addr); return TYPE_LDST; swp: /* only handle swap word, for swap byte should not active this alignment exception */ get32_unaligned_check(regs->uregs[RD_BITS(instr)], addr); put32_unaligned_check(regs->uregs[RM_BITS(instr)], addr); return TYPE_SWAP; fault: return TYPE_FAULT; }
static int do_alignment_ldrhstrh(unsigned long addr, unsigned long instr, struct pt_regs *regs) { unsigned int rd = RD_BITS(instr); ai_half += 1; if (user_mode(regs)) goto user; if (LDST_L_BIT(instr)) { unsigned long val; get16_unaligned_check(val, addr); /* signed half-word? */ if (instr & 0x40) val = (signed long)((signed short) val); regs->uregs[rd] = val; } else put16_unaligned_check(regs->uregs[rd], addr); return TYPE_LDST; user: if (LDST_L_BIT(instr)) { unsigned long val; unsigned int __ua_flags = uaccess_save_and_enable(); get16t_unaligned_check(val, addr); uaccess_restore(__ua_flags); /* signed half-word? */ if (instr & 0x40) val = (signed long)((signed short) val); regs->uregs[rd] = val; } else { unsigned int __ua_flags = uaccess_save_and_enable(); put16t_unaligned_check(regs->uregs[rd], addr); uaccess_restore(__ua_flags); } return TYPE_LDST; fault: return TYPE_FAULT; }
static int do_alignment_ldrhstrh(unsigned long addr, unsigned long instr, struct pt_regs *regs) { unsigned int rd = RD_BITS(instr); ai_half += 1; if (user_mode(regs)) goto user; if (LDST_L_BIT(instr)) { unsigned long val; get16_unaligned_check(val, addr); if (instr & 0x40) val = (signed long)((signed short) val); regs->uregs[rd] = val; } else put16_unaligned_check(regs->uregs[rd], addr); return TYPE_LDST; user: if (LDST_L_BIT(instr)) { unsigned long val; get16t_unaligned_check(val, addr); if (instr & 0x40) val = (signed long)((signed short) val); regs->uregs[rd] = val; } else put16t_unaligned_check(regs->uregs[rd], addr); return TYPE_LDST; fault: return TYPE_FAULT; }