Enscript Output

extractedLnx/linux-2.6.38/arch/powerpc/lib/sstep.c_emulate_step.c

int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
{
	unsigned int opcode, ra, rb, rd, spr, u;
	unsigned long int imm;
	unsigned long int val, val2;
	unsigned long int ea;
	unsigned int cr, mb, me, sh;
	int err;
	unsigned long old_ra;
	long ival;

	opcode = instr >> 26;
	switch (opcode) {
	case 16:	/* bc */
		imm = (signed short)(instr & 0xfffc);
		if ((instr & 2) == 0)
			imm += regs->nip;
		regs->nip += 4;
		if ((regs->msr & MSR_SF) == 0)
			regs->nip &= 0xffffffffUL;
		if (instr & 1)
			regs->link = regs->nip;
		if (branch_taken(instr, regs))
			regs->nip = imm;
		return 1;
#ifdef CONFIG_PPC64
	case 17:	/* sc */
		/*
		 * N.B. this uses knowledge about how the syscall
		 * entry code works.  If that is changed, this will
		 * need to be changed also.
		 */
		if (regs->gpr[0] == 0x1ebe &&
		    cpu_has_feature(CPU_FTR_REAL_LE)) {
			regs->msr ^= MSR_LE;
			goto instr_done;
		}
		regs->gpr[9] = regs->gpr[13];
		regs->gpr[10] = MSR_KERNEL;
		regs->gpr[11] = regs->nip + 4;
		regs->gpr[12] = regs->msr & MSR_MASK;
		regs->gpr[13] = (unsigned long) get_paca();
		regs->nip = (unsigned long) &system_call_common;
		regs->msr = MSR_KERNEL;
		return 1;
#endif
	case 18:	/* b */
		imm = instr & 0x03fffffc;
		if (imm & 0x02000000)
			imm -= 0x04000000;
		if ((instr & 2) == 0)
			imm += regs->nip;
		if (instr & 1) {
			regs->link = regs->nip + 4;
			if ((regs->msr & MSR_SF) == 0)
				regs->link &= 0xffffffffUL;
		}
		if ((regs->msr & MSR_SF) == 0)
			imm &= 0xffffffffUL;
		regs->nip = imm;
		return 1;
	case 19:
		switch ((instr >> 1) & 0x3ff) {
		case 16:	/* bclr */
		case 528:	/* bcctr */
			imm = (instr & 0x400)? regs->ctr: regs->link;
			regs->nip += 4;
			if ((regs->msr & MSR_SF) == 0) {
				regs->nip &= 0xffffffffUL;
				imm &= 0xffffffffUL;
			}
			if (instr & 1)
				regs->link = regs->nip;
			if (branch_taken(instr, regs))
				regs->nip = imm;
			return 1;

		case 18:	/* rfid, scary */
			return -1;

		case 150:	/* isync */
			isync();
			goto instr_done;

		case 33:	/* crnor */
		case 129:	/* crandc */
		case 193:	/* crxor */
		case 225:	/* crnand */
		case 257:	/* crand */
		case 289:	/* creqv */
		case 417:	/* crorc */
		case 449:	/* cror */
			ra = (instr >> 16) & 0x1f;
			rb = (instr >> 11) & 0x1f;
			rd = (instr >> 21) & 0x1f;
			ra = (regs->ccr >> (31 - ra)) & 1;
			rb = (regs->ccr >> (31 - rb)) & 1;
			val = (instr >> (6 + ra * 2 + rb)) & 1;
			regs->ccr = (regs->ccr & ~(1UL << (31 - rd))) |
				(val << (31 - rd));
			goto instr_done;
		}
		break;
	case 31:
		switch ((instr >> 1) & 0x3ff) {
		case 598:	/* sync */
#ifdef __powerpc64__
			switch ((instr >> 21) & 3) {
			case 1:		/* lwsync */
				asm volatile("lwsync" : : : "memory");
				goto instr_done;
			case 2:		/* ptesync */
				asm volatile("ptesync" : : : "memory");
				goto instr_done;
			}
#endif
			mb();
			goto instr_done;

		case 854:	/* eieio */
			eieio();
			goto instr_done;
		}
		break;
	}

	/* Following cases refer to regs->gpr[], so we need all regs */
	if (!FULL_REGS(regs))
		return 0;

	rd = (instr >> 21) & 0x1f;
	ra = (instr >> 16) & 0x1f;
	rb = (instr >> 11) & 0x1f;

	switch (opcode) {
	case 7:		/* mulli */
		regs->gpr[rd] = regs->gpr[ra] * (short) instr;
		goto instr_done;

	case 8:		/* subfic */
		imm = (short) instr;
		add_with_carry(regs, rd, ~regs->gpr[ra], imm, 1);
		goto instr_done;

	case 10:	/* cmpli */
		imm = (unsigned short) instr;
		val = regs->gpr[ra];
#ifdef __powerpc64__
		if ((rd & 1) == 0)
			val = (unsigned int) val;
#endif
		do_cmp_unsigned(regs, val, imm, rd >> 2);
		goto instr_done;

	case 11:	/* cmpi */
		imm = (short) instr;
		val = regs->gpr[ra];
#ifdef __powerpc64__
		if ((rd & 1) == 0)
			val = (int) val;
#endif
		do_cmp_signed(regs, val, imm, rd >> 2);
		goto instr_done;

	case 12:	/* addic */
		imm = (short) instr;
		add_with_carry(regs, rd, regs->gpr[ra], imm, 0);
		goto instr_done;

	case 13:	/* addic. */
		imm = (short) instr;
		add_with_carry(regs, rd, regs->gpr[ra], imm, 0);
		set_cr0(regs, rd);
		goto instr_done;

	case 14:	/* addi */
		imm = (short) instr;
		if (ra)
			imm += regs->gpr[ra];
		regs->gpr[rd] = imm;
		goto instr_done;

	case 15:	/* addis */
		imm = ((short) instr) << 16;
		if (ra)
			imm += regs->gpr[ra];
		regs->gpr[rd] = imm;
		goto instr_done;

	case 20:	/* rlwimi */
		mb = (instr >> 6) & 0x1f;
		me = (instr >> 1) & 0x1f;
		val = DATA32(regs->gpr[rd]);
		imm = MASK32(mb, me);
		regs->gpr[ra] = (regs->gpr[ra] & ~imm) | (ROTATE(val, rb) & imm);
		goto logical_done;

	case 21:	/* rlwinm */
		mb = (instr >> 6) & 0x1f;
		me = (instr >> 1) & 0x1f;
		val = DATA32(regs->gpr[rd]);
		regs->gpr[ra] = ROTATE(val, rb) & MASK32(mb, me);
		goto logical_done;

	case 23:	/* rlwnm */
		mb = (instr >> 6) & 0x1f;
		me = (instr >> 1) & 0x1f;
		rb = regs->gpr[rb] & 0x1f;
		val = DATA32(regs->gpr[rd]);
		regs->gpr[ra] = ROTATE(val, rb) & MASK32(mb, me);
		goto logical_done;

	case 24:	/* ori */
		imm = (unsigned short) instr;
		regs->gpr[ra] = regs->gpr[rd] | imm;
		goto instr_done;

	case 25:	/* oris */
		imm = (unsigned short) instr;
		regs->gpr[ra] = regs->gpr[rd] | (imm << 16);
		goto instr_done;

	case 26:	/* xori */
		imm = (unsigned short) instr;
		regs->gpr[ra] = regs->gpr[rd] ^ imm;
		goto instr_done;

	case 27:	/* xoris */
		imm = (unsigned short) instr;
		regs->gpr[ra] = regs->gpr[rd] ^ (imm << 16);
		goto instr_done;

	case 28:	/* andi. */
		imm = (unsigned short) instr;
		regs->gpr[ra] = regs->gpr[rd] & imm;
		set_cr0(regs, ra);
		goto instr_done;

	case 29:	/* andis. */
		imm = (unsigned short) instr;
		regs->gpr[ra] = regs->gpr[rd] & (imm << 16);
		set_cr0(regs, ra);
		goto instr_done;

#ifdef __powerpc64__
	case 30:	/* rld* */
		mb = ((instr >> 6) & 0x1f) | (instr & 0x20);
		val = regs->gpr[rd];
		if ((instr & 0x10) == 0) {
			sh = rb | ((instr & 2) << 4);
			val = ROTATE(val, sh);
			switch ((instr >> 2) & 3) {
			case 0:		/* rldicl */
				regs->gpr[ra] = val & MASK64_L(mb);
				goto logical_done;
			case 1:		/* rldicr */
				regs->gpr[ra] = val & MASK64_R(mb);
				goto logical_done;
			case 2:		/* rldic */
				regs->gpr[ra] = val & MASK64(mb, 63 - sh);
				goto logical_done;
			case 3:		/* rldimi */
				imm = MASK64(mb, 63 - sh);
				regs->gpr[ra] = (regs->gpr[ra] & ~imm) |
					(val & imm);
				goto logical_done;
			}
		} else {
			sh = regs->gpr[rb] & 0x3f;
			val = ROTATE(val, sh);
			switch ((instr >> 1) & 7) {
			case 0:		/* rldcl */
				regs->gpr[ra] = val & MASK64_L(mb);
				goto logical_done;
			case 1:		/* rldcr */
				regs->gpr[ra] = val & MASK64_R(mb);
				goto logical_done;
			}
		}
#endif

	case 31:
		switch ((instr >> 1) & 0x3ff) {
		case 83:	/* mfmsr */
			if (regs->msr & MSR_PR)
				break;
			regs->gpr[rd] = regs->msr & MSR_MASK;
			goto instr_done;
		case 146:	/* mtmsr */
			if (regs->msr & MSR_PR)
				break;
			imm = regs->gpr[rd];
			if ((imm & MSR_RI) == 0)
				/* can't step mtmsr that would clear MSR_RI */
				return -1;
			regs->msr = imm;
			goto instr_done;
#ifdef CONFIG_PPC64
		case 178:	/* mtmsrd */
			/* only MSR_EE and MSR_RI get changed if bit 15 set */
			/* mtmsrd doesn't change MSR_HV and MSR_ME */
			if (regs->msr & MSR_PR)
				break;
			imm = (instr & 0x10000)? 0x8002: 0xefffffffffffefffUL;
			imm = (regs->msr & MSR_MASK & ~imm)
				| (regs->gpr[rd] & imm);
			if ((imm & MSR_RI) == 0)
				/* can't step mtmsrd that would clear MSR_RI */
				return -1;
			regs->msr = imm;
			goto instr_done;
#endif
		case 19:	/* mfcr */
			regs->gpr[rd] = regs->ccr;
			regs->gpr[rd] &= 0xffffffffUL;
			goto instr_done;

		case 144:	/* mtcrf */
			imm = 0xf0000000UL;
			val = regs->gpr[rd];
			for (sh = 0; sh < 8; ++sh) {
				if (instr & (0x80000 >> sh))
					regs->ccr = (regs->ccr & ~imm) |
						(val & imm);
				imm >>= 4;
			}
			goto instr_done;

		case 339:	/* mfspr */
			spr = (instr >> 11) & 0x3ff;
			switch (spr) {
			case 0x20:	/* mfxer */
				regs->gpr[rd] = regs->xer;
				regs->gpr[rd] &= 0xffffffffUL;
				goto instr_done;
			case 0x100:	/* mflr */
				regs->gpr[rd] = regs->link;
				goto instr_done;
			case 0x120:	/* mfctr */
				regs->gpr[rd] = regs->ctr;
				goto instr_done;
			}
			break;

		case 467:	/* mtspr */
			spr = (instr >> 11) & 0x3ff;
			switch (spr) {
			case 0x20:	/* mtxer */
				regs->xer = (regs->gpr[rd] & 0xffffffffUL);
				goto instr_done;
			case 0x100:	/* mtlr */
				regs->link = regs->gpr[rd];
				goto instr_done;
			case 0x120:	/* mtctr */
				regs->ctr = regs->gpr[rd];
				goto instr_done;
			}
			break;

/*
 * Compare instructions
 */
		case 0:	/* cmp */
			val = regs->gpr[ra];
			val2 = regs->gpr[rb];
#ifdef __powerpc64__
			if ((rd & 1) == 0) {
				/* word (32-bit) compare */
				val = (int) val;
				val2 = (int) val2;
			}
#endif
			do_cmp_signed(regs, val, val2, rd >> 2);
			goto instr_done;

		case 32:	/* cmpl */
			val = regs->gpr[ra];
			val2 = regs->gpr[rb];
#ifdef __powerpc64__
			if ((rd & 1) == 0) {
				/* word (32-bit) compare */
				val = (unsigned int) val;
				val2 = (unsigned int) val2;
			}
#endif
			do_cmp_unsigned(regs, val, val2, rd >> 2);
			goto instr_done;

/*
 * Arithmetic instructions
 */
		case 8:	/* subfc */
			add_with_carry(regs, rd, ~regs->gpr[ra],
				       regs->gpr[rb], 1);
			goto arith_done;
#ifdef __powerpc64__
		case 9:	/* mulhdu */
			asm("mulhdu %0,%1,%2" : "=r" (regs->gpr[rd]) :
			    "r" (regs->gpr[ra]), "r" (regs->gpr[rb]));
			goto arith_done;
#endif
		case 10:	/* addc */
			add_with_carry(regs, rd, regs->gpr[ra],
				       regs->gpr[rb], 0);
			goto arith_done;

		case 11:	/* mulhwu */
			asm("mulhwu %0,%1,%2" : "=r" (regs->gpr[rd]) :
			    "r" (regs->gpr[ra]), "r" (regs->gpr[rb]));
			goto arith_done;

		case 40:	/* subf */
			regs->gpr[rd] = regs->gpr[rb] - regs->gpr[ra];
			goto arith_done;
#ifdef __powerpc64__
		case 73:	/* mulhd */
			asm("mulhd %0,%1,%2" : "=r" (regs->gpr[rd]) :
			    "r" (regs->gpr[ra]), "r" (regs->gpr[rb]));
			goto arith_done;
#endif
		case 75:	/* mulhw */
			asm("mulhw %0,%1,%2" : "=r" (regs->gpr[rd]) :
			    "r" (regs->gpr[ra]), "r" (regs->gpr[rb]));
			goto arith_done;

		case 104:	/* neg */
			regs->gpr[rd] = -regs->gpr[ra];
			goto arith_done;

		case 136:	/* subfe */
			add_with_carry(regs, rd, ~regs->gpr[ra], regs->gpr[rb],
				       regs->xer & XER_CA);
			goto arith_done;

		case 138:	/* adde */
			add_with_carry(regs, rd, regs->gpr[ra], regs->gpr[rb],
				       regs->xer & XER_CA);
			goto arith_done;

		case 200:	/* subfze */
			add_with_carry(regs, rd, ~regs->gpr[ra], 0L,
				       regs->xer & XER_CA);
			goto arith_done;

		case 202:	/* addze */
			add_with_carry(regs, rd, regs->gpr[ra], 0L,
				       regs->xer & XER_CA);
			goto arith_done;

		case 232:	/* subfme */
			add_with_carry(regs, rd, ~regs->gpr[ra], -1L,
				       regs->xer & XER_CA);
			goto arith_done;
#ifdef __powerpc64__
		case 233:	/* mulld */
			regs->gpr[rd] = regs->gpr[ra] * regs->gpr[rb];
			goto arith_done;
#endif
		case 234:	/* addme */
			add_with_carry(regs, rd, regs->gpr[ra], -1L,
				       regs->xer & XER_CA);
			goto arith_done;

		case 235:	/* mullw */
			regs->gpr[rd] = (unsigned int) regs->gpr[ra] *
				(unsigned int) regs->gpr[rb];
			goto arith_done;

		case 266:	/* add */
			regs->gpr[rd] = regs->gpr[ra] + regs->gpr[rb];
			goto arith_done;
#ifdef __powerpc64__
		case 457:	/* divdu */
			regs->gpr[rd] = regs->gpr[ra] / regs->gpr[rb];
			goto arith_done;
#endif
		case 459:	/* divwu */
			regs->gpr[rd] = (unsigned int) regs->gpr[ra] /
				(unsigned int) regs->gpr[rb];
			goto arith_done;
#ifdef __powerpc64__
		case 489:	/* divd */
			regs->gpr[rd] = (long int) regs->gpr[ra] /
				(long int) regs->gpr[rb];
			goto arith_done;
#endif
		case 491:	/* divw */
			regs->gpr[rd] = (int) regs->gpr[ra] /
				(int) regs->gpr[rb];
			goto arith_done;


/*
 * Logical instructions
 */
		case 26:	/* cntlzw */
			asm("cntlzw %0,%1" : "=r" (regs->gpr[ra]) :
			    "r" (regs->gpr[rd]));
			goto logical_done;
#ifdef __powerpc64__
		case 58:	/* cntlzd */
			asm("cntlzd %0,%1" : "=r" (regs->gpr[ra]) :
			    "r" (regs->gpr[rd]));
			goto logical_done;
#endif
		case 28:	/* and */
			regs->gpr[ra] = regs->gpr[rd] & regs->gpr[rb];
			goto logical_done;

		case 60:	/* andc */
			regs->gpr[ra] = regs->gpr[rd] & ~regs->gpr[rb];
			goto logical_done;

		case 124:	/* nor */
			regs->gpr[ra] = ~(regs->gpr[rd] | regs->gpr[rb]);
			goto logical_done;

		case 284:	/* xor */
			regs->gpr[ra] = ~(regs->gpr[rd] ^ regs->gpr[rb]);
			goto logical_done;

		case 316:	/* xor */
			regs->gpr[ra] = regs->gpr[rd] ^ regs->gpr[rb];
			goto logical_done;

		case 412:	/* orc */
			regs->gpr[ra] = regs->gpr[rd] | ~regs->gpr[rb];
			goto logical_done;

		case 444:	/* or */
			regs->gpr[ra] = regs->gpr[rd] | regs->gpr[rb];
			goto logical_done;

		case 476:	/* nand */
			regs->gpr[ra] = ~(regs->gpr[rd] & regs->gpr[rb]);
			goto logical_done;

		case 922:	/* extsh */
			regs->gpr[ra] = (signed short) regs->gpr[rd];
			goto logical_done;

		case 954:	/* extsb */
			regs->gpr[ra] = (signed char) regs->gpr[rd];
			goto logical_done;
#ifdef __powerpc64__
		case 986:	/* extsw */
			regs->gpr[ra] = (signed int) regs->gpr[rd];
			goto logical_done;
#endif

/*
 * Shift instructions
 */
		case 24:	/* slw */
			sh = regs->gpr[rb] & 0x3f;
			if (sh < 32)
				regs->gpr[ra] = (regs->gpr[rd] << sh) & 0xffffffffUL;
			else
				regs->gpr[ra] = 0;
			goto logical_done;

		case 536:	/* srw */
			sh = regs->gpr[rb] & 0x3f;
			if (sh < 32)
				regs->gpr[ra] = (regs->gpr[rd] & 0xffffffffUL) >> sh;
			else
				regs->gpr[ra] = 0;
			goto logical_done;

		case 792:	/* sraw */
			sh = regs->gpr[rb] & 0x3f;
			ival = (signed int) regs->gpr[rd];
			regs->gpr[ra] = ival >> (sh < 32 ? sh : 31);
			if (ival < 0 && (sh >= 32 || (ival & ((1 << sh) - 1)) != 0))
				regs->xer |= XER_CA;
			else
				regs->xer &= ~XER_CA;
			goto logical_done;

		case 824:	/* srawi */
			sh = rb;
			ival = (signed int) regs->gpr[rd];
			regs->gpr[ra] = ival >> sh;
			if (ival < 0 && (ival & ((1 << sh) - 1)) != 0)
				regs->xer |= XER_CA;
			else
				regs->xer &= ~XER_CA;
			goto logical_done;

#ifdef __powerpc64__
		case 27:	/* sld */
			sh = regs->gpr[rd] & 0x7f;
			if (sh < 64)
				regs->gpr[ra] = regs->gpr[rd] << sh;
			else
				regs->gpr[ra] = 0;
			goto logical_done;

		case 539:	/* srd */
			sh = regs->gpr[rb] & 0x7f;
			if (sh < 64)
				regs->gpr[ra] = regs->gpr[rd] >> sh;
			else
				regs->gpr[ra] = 0;
			goto logical_done;

		case 794:	/* srad */
			sh = regs->gpr[rb] & 0x7f;
			ival = (signed long int) regs->gpr[rd];
			regs->gpr[ra] = ival >> (sh < 64 ? sh : 63);
			if (ival < 0 && (sh >= 64 || (ival & ((1 << sh) - 1)) != 0))
				regs->xer |= XER_CA;
			else
				regs->xer &= ~XER_CA;
			goto logical_done;

		case 826:	/* sradi with sh_5 = 0 */
		case 827:	/* sradi with sh_5 = 1 */
			sh = rb | ((instr & 2) << 4);
			ival = (signed long int) regs->gpr[rd];
			regs->gpr[ra] = ival >> sh;
			if (ival < 0 && (ival & ((1 << sh) - 1)) != 0)
				regs->xer |= XER_CA;
			else
				regs->xer &= ~XER_CA;
			goto logical_done;
#endif /* __powerpc64__ */

/*
 * Cache instructions
 */
		case 54:	/* dcbst */
			ea = xform_ea(instr, regs, 0);
			if (!address_ok(regs, ea, 8))
				return 0;
			err = 0;
			__cacheop_user_asmx(ea, err, "dcbst");
			if (err)
				return 0;
			goto instr_done;

		case 86:	/* dcbf */
			ea = xform_ea(instr, regs, 0);
			if (!address_ok(regs, ea, 8))
				return 0;
			err = 0;
			__cacheop_user_asmx(ea, err, "dcbf");
			if (err)
				return 0;
			goto instr_done;

		case 246:	/* dcbtst */
			if (rd == 0) {
				ea = xform_ea(instr, regs, 0);
				prefetchw((void *) ea);
			}
			goto instr_done;

		case 278:	/* dcbt */
			if (rd == 0) {
				ea = xform_ea(instr, regs, 0);
				prefetch((void *) ea);
			}
			goto instr_done;

		}
		break;
	}

	/*
	 * Following cases are for loads and stores, so bail out
	 * if we're in little-endian mode.
	 */
	if (regs->msr & MSR_LE)
		return 0;

	/*
	 * Save register RA in case it's an update form load or store
	 * and the access faults.
	 */
	old_ra = regs->gpr[ra];

	switch (opcode) {
	case 31:
		u = instr & 0x40;
		switch ((instr >> 1) & 0x3ff) {
		case 20:	/* lwarx */
			ea = xform_ea(instr, regs, 0);
			if (ea & 3)
				break;		/* can't handle misaligned */
			err = -EFAULT;
			if (!address_ok(regs, ea, 4))
				goto ldst_done;
			err = 0;
			__get_user_asmx(val, ea, err, "lwarx");
			if (!err)
				regs->gpr[rd] = val;
			goto ldst_done;

		case 150:	/* stwcx. */
			ea = xform_ea(instr, regs, 0);
			if (ea & 3)
				break;		/* can't handle misaligned */
			err = -EFAULT;
			if (!address_ok(regs, ea, 4))
				goto ldst_done;
			err = 0;
			__put_user_asmx(regs->gpr[rd], ea, err, "stwcx.", cr);
			if (!err)
				regs->ccr = (regs->ccr & 0x0fffffff) |
					(cr & 0xe0000000) |
					((regs->xer >> 3) & 0x10000000);
			goto ldst_done;

#ifdef __powerpc64__
		case 84:	/* ldarx */
			ea = xform_ea(instr, regs, 0);
			if (ea & 7)
				break;		/* can't handle misaligned */
			err = -EFAULT;
			if (!address_ok(regs, ea, 8))
				goto ldst_done;
			err = 0;
			__get_user_asmx(val, ea, err, "ldarx");
			if (!err)
				regs->gpr[rd] = val;
			goto ldst_done;

		case 214:	/* stdcx. */
			ea = xform_ea(instr, regs, 0);
			if (ea & 7)
				break;		/* can't handle misaligned */
			err = -EFAULT;
			if (!address_ok(regs, ea, 8))
				goto ldst_done;
			err = 0;
			__put_user_asmx(regs->gpr[rd], ea, err, "stdcx.", cr);
			if (!err)
				regs->ccr = (regs->ccr & 0x0fffffff) |
					(cr & 0xe0000000) |
					((regs->xer >> 3) & 0x10000000);
			goto ldst_done;

		case 21:	/* ldx */
		case 53:	/* ldux */
			err = read_mem(&regs->gpr[rd], xform_ea(instr, regs, u),
				       8, regs);
			goto ldst_done;
#endif

		case 23:	/* lwzx */
		case 55:	/* lwzux */
			err = read_mem(&regs->gpr[rd], xform_ea(instr, regs, u),
				       4, regs);
			goto ldst_done;

		case 87:	/* lbzx */
		case 119:	/* lbzux */
			err = read_mem(&regs->gpr[rd], xform_ea(instr, regs, u),
				       1, regs);
			goto ldst_done;

#ifdef CONFIG_ALTIVEC
		case 103:	/* lvx */
		case 359:	/* lvxl */
			if (!(regs->msr & MSR_VEC))
				break;
			ea = xform_ea(instr, regs, 0);
			err = do_vec_load(rd, do_lvx, ea, regs);
			goto ldst_done;

		case 231:	/* stvx */
		case 487:	/* stvxl */
			if (!(regs->msr & MSR_VEC))
				break;
			ea = xform_ea(instr, regs, 0);
			err = do_vec_store(rd, do_stvx, ea, regs);
			goto ldst_done;
#endif /* CONFIG_ALTIVEC */

#ifdef __powerpc64__
		case 149:	/* stdx */
		case 181:	/* stdux */
			val = regs->gpr[rd];
			err = write_mem(val, xform_ea(instr, regs, u), 8, regs);
			goto ldst_done;
#endif

		case 151:	/* stwx */
		case 183:	/* stwux */
			val = regs->gpr[rd];
			err = write_mem(val, xform_ea(instr, regs, u), 4, regs);
			goto ldst_done;

		case 215:	/* stbx */
		case 247:	/* stbux */
			val = regs->gpr[rd];
			err = write_mem(val, xform_ea(instr, regs, u), 1, regs);
			goto ldst_done;

		case 279:	/* lhzx */
		case 311:	/* lhzux */
			err = read_mem(&regs->gpr[rd], xform_ea(instr, regs, u),
				       2, regs);
			goto ldst_done;

#ifdef __powerpc64__
		case 341:	/* lwax */
		case 373:	/* lwaux */
			err = read_mem(&regs->gpr[rd], xform_ea(instr, regs, u),
				       4, regs);
			if (!err)
				regs->gpr[rd] = (signed int) regs->gpr[rd];
			goto ldst_done;
#endif

		case 343:	/* lhax */
		case 375:	/* lhaux */
			err = read_mem(&regs->gpr[rd], xform_ea(instr, regs, u),
				       2, regs);
			if (!err)
				regs->gpr[rd] = (signed short) regs->gpr[rd];
			goto ldst_done;

		case 407:	/* sthx */
		case 439:	/* sthux */
			val = regs->gpr[rd];
			err = write_mem(val, xform_ea(instr, regs, u), 2, regs);
			goto ldst_done;

#ifdef __powerpc64__
		case 532:	/* ldbrx */
			err = read_mem(&val, xform_ea(instr, regs, 0), 8, regs);
			if (!err)
				regs->gpr[rd] = byterev_8(val);
			goto ldst_done;

#endif

		case 534:	/* lwbrx */
			err = read_mem(&val, xform_ea(instr, regs, 0), 4, regs);
			if (!err)
				regs->gpr[rd] = byterev_4(val);
			goto ldst_done;

#ifdef CONFIG_PPC_CPU
		case 535:	/* lfsx */
		case 567:	/* lfsux */
			if (!(regs->msr & MSR_FP))
				break;
			ea = xform_ea(instr, regs, u);
			err = do_fp_load(rd, do_lfs, ea, 4, regs);
			goto ldst_done;

		case 599:	/* lfdx */
		case 631:	/* lfdux */
			if (!(regs->msr & MSR_FP))
				break;
			ea = xform_ea(instr, regs, u);
			err = do_fp_load(rd, do_lfd, ea, 8, regs);
			goto ldst_done;

		case 663:	/* stfsx */
		case 695:	/* stfsux */
			if (!(regs->msr & MSR_FP))
				break;
			ea = xform_ea(instr, regs, u);
			err = do_fp_store(rd, do_stfs, ea, 4, regs);
			goto ldst_done;

		case 727:	/* stfdx */
		case 759:	/* stfdux */
			if (!(regs->msr & MSR_FP))
				break;
			ea = xform_ea(instr, regs, u);
			err = do_fp_store(rd, do_stfd, ea, 8, regs);
			goto ldst_done;
#endif

#ifdef __powerpc64__
		case 660:	/* stdbrx */
			val = byterev_8(regs->gpr[rd]);
			err = write_mem(val, xform_ea(instr, regs, 0), 8, regs);
			goto ldst_done;

#endif
		case 662:	/* stwbrx */
			val = byterev_4(regs->gpr[rd]);
			err = write_mem(val, xform_ea(instr, regs, 0), 4, regs);
			goto ldst_done;

		case 790:	/* lhbrx */
			err = read_mem(&val, xform_ea(instr, regs, 0), 2, regs);
			if (!err)
				regs->gpr[rd] = byterev_2(val);
			goto ldst_done;

		case 918:	/* sthbrx */
			val = byterev_2(regs->gpr[rd]);
			err = write_mem(val, xform_ea(instr, regs, 0), 2, regs);
			goto ldst_done;

#ifdef CONFIG_VSX
		case 844:	/* lxvd2x */
		case 876:	/* lxvd2ux */
			if (!(regs->msr & MSR_VSX))
				break;
			rd |= (instr & 1) << 5;
			ea = xform_ea(instr, regs, u);
			err = do_vsx_load(rd, do_lxvd2x, ea, regs);
			goto ldst_done;

		case 972:	/* stxvd2x */
		case 1004:	/* stxvd2ux */
			if (!(regs->msr & MSR_VSX))
				break;
			rd |= (instr & 1) << 5;
			ea = xform_ea(instr, regs, u);
			err = do_vsx_store(rd, do_stxvd2x, ea, regs);
			goto ldst_done;

#endif /* CONFIG_VSX */
		}
		break;

	case 32:	/* lwz */
	case 33:	/* lwzu */
		err = read_mem(&regs->gpr[rd], dform_ea(instr, regs), 4, regs);
		goto ldst_done;

	case 34:	/* lbz */
	case 35:	/* lbzu */
		err = read_mem(&regs->gpr[rd], dform_ea(instr, regs), 1, regs);
		goto ldst_done;

	case 36:	/* stw */
	case 37:	/* stwu */
		val = regs->gpr[rd];
		err = write_mem(val, dform_ea(instr, regs), 4, regs);
		goto ldst_done;

	case 38:	/* stb */
	case 39:	/* stbu */
		val = regs->gpr[rd];
		err = write_mem(val, dform_ea(instr, regs), 1, regs);
		goto ldst_done;

	case 40:	/* lhz */
	case 41:	/* lhzu */
		err = read_mem(&regs->gpr[rd], dform_ea(instr, regs), 2, regs);
		goto ldst_done;

	case 42:	/* lha */
	case 43:	/* lhau */
		err = read_mem(&regs->gpr[rd], dform_ea(instr, regs), 2, regs);
		if (!err)
			regs->gpr[rd] = (signed short) regs->gpr[rd];
		goto ldst_done;

	case 44:	/* sth */
	case 45:	/* sthu */
		val = regs->gpr[rd];
		err = write_mem(val, dform_ea(instr, regs), 2, regs);
		goto ldst_done;

	case 46:	/* lmw */
		ra = (instr >> 16) & 0x1f;
		if (ra >= rd)
			break;		/* invalid form, ra in range to load */
		ea = dform_ea(instr, regs);
		do {
			err = read_mem(&regs->gpr[rd], ea, 4, regs);
			if (err)
				return 0;
			ea += 4;
		} while (++rd < 32);
		goto instr_done;

	case 47:	/* stmw */
		ea = dform_ea(instr, regs);
		do {
			err = write_mem(regs->gpr[rd], ea, 4, regs);
			if (err)
				return 0;
			ea += 4;
		} while (++rd < 32);
		goto instr_done;

#ifdef CONFIG_PPC_FPU
	case 48:	/* lfs */
	case 49:	/* lfsu */
		if (!(regs->msr & MSR_FP))
			break;
		ea = dform_ea(instr, regs);
		err = do_fp_load(rd, do_lfs, ea, 4, regs);
		goto ldst_done;

	case 50:	/* lfd */
	case 51:	/* lfdu */
		if (!(regs->msr & MSR_FP))
			break;
		ea = dform_ea(instr, regs);
		err = do_fp_load(rd, do_lfd, ea, 8, regs);
		goto ldst_done;

	case 52:	/* stfs */
	case 53:	/* stfsu */
		if (!(regs->msr & MSR_FP))
			break;
		ea = dform_ea(instr, regs);
		err = do_fp_store(rd, do_stfs, ea, 4, regs);
		goto ldst_done;

	case 54:	/* stfd */
	case 55:	/* stfdu */
		if (!(regs->msr & MSR_FP))
			break;
		ea = dform_ea(instr, regs);
		err = do_fp_store(rd, do_stfd, ea, 8, regs);
		goto ldst_done;
#endif

#ifdef __powerpc64__
	case 58:	/* ld[u], lwa */
		switch (instr & 3) {
		case 0:		/* ld */
			err = read_mem(&regs->gpr[rd], dsform_ea(instr, regs),
				       8, regs);
			goto ldst_done;
		case 1:		/* ldu */
			err = read_mem(&regs->gpr[rd], dsform_ea(instr, regs),
				       8, regs);
			goto ldst_done;
		case 2:		/* lwa */
			err = read_mem(&regs->gpr[rd], dsform_ea(instr, regs),
				       4, regs);
			if (!err)
				regs->gpr[rd] = (signed int) regs->gpr[rd];
			goto ldst_done;
		}
		break;

	case 62:	/* std[u] */
		val = regs->gpr[rd];
		switch (instr & 3) {
		case 0:		/* std */
			err = write_mem(val, dsform_ea(instr, regs), 8, regs);
			goto ldst_done;
		case 1:		/* stdu */
			err = write_mem(val, dsform_ea(instr, regs), 8, regs);
			goto ldst_done;
		}
		break;
#endif /* __powerpc64__ */

	}
	err = -EINVAL;

 ldst_done:
	if (err) {
		regs->gpr[ra] = old_ra;
		return 0;	/* invoke DSI if -EFAULT? */
	}
 instr_done:
	regs->nip += 4;
#ifdef __powerpc64__
	if ((regs->msr & MSR_SF) == 0)
		regs->nip &= 0xffffffffUL;
#endif
	return 1;

 logical_done:
	if (instr & 1)
		set_cr0(regs, ra);
	goto instr_done;

 arith_done:
	if (instr & 1)
		set_cr0(regs, rd);
	goto instr_done;
}

Generated by GNU enscript 1.6.4.