コード例 #1
0
ファイル: armass.c プロジェクト: Jo-Con-El/radare2
// TODO: group similar instructions like for non-thumb
static int thumb_assemble(ArmOpcode *ao, const char *str) {
	int reg, j;
	if (!strcmp (ao->op, "pop") && ao->a[0]) {
		ao->o = 0xbc;
		if (*ao->a[0]++=='{') {
			for (j=0; j<16; j++) {
				if (ao->a[j] && *ao->a[j]) {
					getrange (ao->a[j]); // XXX filter regname string
					reg = thumb_getreg (ao->a[j]);
					if (reg != -1) {
						if (reg<8)
							ao->o |= 1<<(8+reg);
						if (reg==8){
							ao->o |= 1;
						}
					//	else ignore...
					}
				}
			}
		} else ao->o |= getnum (ao->a[0])<<24; // ???
	} else
	if (!strcmp (ao->op, "push") && ao->a[0]) {
		ao->o = 0xb4;
		if (*ao->a[0]++=='{') {
			for (j=0; j<16; j++) {
				if (ao->a[j] && *ao->a[j]) {
					getrange (ao->a[j]); // XXX filter regname string
					reg = thumb_getreg (ao->a[j]);
					if (reg != -1) {
						if (reg<8)
							ao->o |= 1<<(8+reg);
						if (reg==8)
							ao->o |= 1;
					//	else ignore...
					}
				}
			}
		} else ao->o |= getnum (ao->a[0])<<24; // ???
	} else
	if (!strcmp (ao->op, "ldmia")) {
		ao->o = 0xc8 + getreg (ao->a[0]);
		ao->o |= getlist(ao->opstr) << 8;
	} else
	if (!strcmp (ao->op, "stmia")) {
		ao->o = 0xc0 + getreg (ao->a[0]);
		ao->o |= getlist(ao->opstr) << 8;
	} else
	if (!strcmp (ao->op, "nop")) {
		ao->o = 0xbf;
	} else
	if (!strcmp (ao->op, "yield")) {
		ao->o = 0x10bf;
	} else
	if (!strcmp (ao->op, "wfe")) {
		ao->o = 0x20bf;
	} else
	if (!strcmp (ao->op, "wfi")) {
		ao->o = 0x30bf;
	} else
	if (!strcmp (ao->op, "sev")) {
		ao->o = 0x40bf;
	} else
	if (!strcmp (ao->op, "bkpt")) {
		ao->o = 0xbe;
		ao->o |= (0xff & getnum (ao->a[0]))<<8;
	} else
	if (!strcmp (ao->op, "and")) {
		ao->o = 0x40;
		ao->o |= (0xff & getreg (ao->a[0])) << 8;
		ao->o |= (0xff & getreg (ao->a[1])) << 11;
	} else
	if (!strcmp (ao->op, "svc")) {
		ao->o = 0xdf;
		ao->o |= (0xff & getnum (ao->a[0])) << 8;
	} else
	if (!strcmp (ao->op, "b") || !strcmp (ao->op, "b.n")) {
		ao->o = 0xe0;
		ao->o |= getnum (ao->a[0])<<8;
	} else
	if (!strcmp (ao->op, "bx")) {
		ao->o = 0x47;
		ao->o |= getreg (ao->a[0])<<11;
	} else
	if (!strcmp (ao->op, "bl")) {
		ao->o = 0x47;
		ao->o |= getnum (ao->a[0])<<8;
		// XXX: length = 4
	} else
	if (*ao->op == 'b') { // conditional branch
		ao->o = 0xd0 | arm_opcode_cond (ao, 1);
		ao->o |= getnum (ao->a[0])<<8;
	} else
	if (!strcmp (ao->op, "mov")) {
		int reg = getreg (ao->a[1]);
		if (reg!=-1) {
			ao->o = 0x46;
			ao->o |= (getreg (ao->a[0]))<<8;
			ao->o |= reg<<11;
		} else {
			ao->o = 0x20;
			ao->o |= (getreg (ao->a[0]));
			ao->o |= (getnum (ao->a[1])&0xff)<<8;
		}
	} else
	if (!memcmp (ao->op, "ldr", 3)) {
		getrange (ao->a[1]);
		getrange (ao->a[2]);
		if (ao->op[3]=='h') {
			int a0 = getreg (ao->a[0]);
			int a1 = getreg (ao->a[1]);
			int a2 = getreg (ao->a[2]);
			if (a2 ==-1) {
				a2 = getnum (ao->a[2])/8;
				ao->o = 0x88; // | (8+(0xf & a0));
				ao->o |= (7&a0)<<8;
				ao->o |= (7&a1)<<11;
				ao->o += (7&a2);
			} else return 0;
		} else
		if (ao->op[3]=='b') {
			int a0 = getreg (ao->a[0]);
			int a1 = getreg (ao->a[1]);
			int a2 = getreg (ao->a[2]);
			if (a2 ==-1) {
				a2 = getnum (ao->a[2])/8;
				ao->o = 0x78; // | (8+(0xf & a0));
				ao->o |= (7&a0)<<8;
				ao->o |= (7&a1)<<11;
				ao->o |= (7&a2);
			} else return 0;
		} else {
			if (!strcmp (ao->a[1], "sp")) {
				// ldr r0, [sp, n] = a[r0-7][nn]
				if (getreg (ao->a[2]) == -1) {
					// ldr r0, [sp, n]
					ao->o = 0x98 + (0xf & getreg (ao->a[0]));
					ao->o |= (0xff & getnum (ao->a[2])/4)<<8;
				} else return 0;
			} else
			if (!strcmp (ao->a[1], "pc")) {
				// ldr r0, [pc, n] = 4[r0-8][nn*4]
				if (getreg (ao->a[2]) == -1) {
					ao->o = 0x40 | (8+(0xf & getreg (ao->a[0])));
					ao->o |= (0xff & getnum (ao->a[2])/4)<<8;
				} else return 0;
			} else {
				// ldr r0, [rN, rN] = 58[7bits:basereg + 7bits:destreg]
				int a0 = getreg (ao->a[0]);
				int a1 = getreg (ao->a[1]);
				int a2 = getreg (ao->a[2]);
				ao->o = 0x58; // | (8+(0xf & a0));
				ao->o |= (7&a0)<<8;
				ao->o |= (7&a1)<<11;
				ao->o |= (7&a2)<<14;
			}
		}
	} else
	if (!memcmp (ao->op, "str", 3)) {
		getrange (ao->a[1]);
		getrange (ao->a[2]);
		if (ao->op[3]=='h') {
			int a0 = getreg (ao->a[0]);
			int a1 = getreg (ao->a[1]);
			int a2 = getreg (ao->a[2]);
			if (a2 ==-1) {
				a2 = getnum (ao->a[2]);
				ao->o = 0x80; // | (8+(0xf & a0));
				ao->o |= (7&a0)<<8;
				ao->o |= (7&a1)<<11;
				ao->o |= (7&(a2>>1));
			} else return 0;
コード例 #2
0
ファイル: armass.c プロジェクト: albertogviana/radare2
// TODO: group similar instructions like for non-thumb
static int thumb_assemble(ArmOpcode *ao, const char *str) {
	int reg, j;
	ao->o = UT32_MAX;
	if (!strcmpnull (ao->op, "pop") && ao->a[0]) {
		ao->o = 0xbc;
		if (*ao->a[0]++=='{') {
			// XXX: inverse order?
			for (j=0; j<16; j++) {
				if (ao->a[j] && *ao->a[j]) {
					getrange (ao->a[j]); // XXX filter regname string
					reg = thumb_getreg (ao->a[j]);
					if (reg != -1) {
						if (reg<8)
							ao->o |= 1<<(8+reg);
						if (reg==8){
							ao->o |= 1;
						}
					//	else ignore...
					}
				}
			}
		} else ao->o |= getnum (ao->a[0])<<24; // ???
		return 2;
	} else
	if (!strcmpnull (ao->op, "push") && ao->a[0]) {
		ao->o = 0xb4;
		if (*ao->a[0]++=='{') {
			for (j=0; j<16; j++) {
				if (ao->a[j] && *ao->a[j]) {
					getrange (ao->a[j]); // XXX filter regname string
					reg = thumb_getreg (ao->a[j]);
					if (reg != -1) {
						if (reg<8)
							ao->o |= 1<<(8+reg);
						if (reg==8)
							ao->o |= 1;
					//	else ignore...
					}
				}
			}
		} else ao->o |= getnum (ao->a[0])<<24; // ???
		return 2;
	} else
	if (!strcmpnull (ao->op, "ldmia")) {
		ao->o = 0xc8 + getreg (ao->a[0]);
		ao->o |= getlist(ao->opstr) << 8;
		return 2;
	} else
	if (!strcmpnull (ao->op, "stmia")) {
		ao->o = 0xc0 + getreg (ao->a[0]);
		ao->o |= getlist(ao->opstr) << 8;
		return 2;
	} else
	if (!strcmpnull (ao->op, "nop")) {
		ao->o = 0xbf;
		return 2;
	} else
	if (!strcmpnull (ao->op, "yield")) {
		ao->o = 0x10bf;
		return 2;
	} else
	if (!strcmpnull (ao->op, "udf")) {
		ao->o = 0xde;
		ao->o |= getnum (ao->a[0])<<8;
		return 2;
	} else
	if (!strcmpnull (ao->op, "wfe")) {
		ao->o = 0x20bf;
		return 2;
	} else
	if (!strcmpnull (ao->op, "wfi")) {
		ao->o = 0x30bf;
		return 2;
	} else
	if (!strcmpnull (ao->op, "sev")) {
		ao->o = 0x40bf;
		return 2;
	} else
	if (!strcmpnull (ao->op, "bkpt")) {
		ao->o = 0xbe;
		ao->o |= (0xff & getnum (ao->a[0]))<<8;
		return 2;
	} else
#if 0
	if (!strcmpnull (ao->op, "and")) {
		ao->o = 0x40;
		ao->o |= (0xff & getreg (ao->a[0])) << 8;
		ao->o |= (0xff & getreg (ao->a[1])) << 11;
	} else
#endif
	if (!strcmpnull (ao->op, "svc")) {
		ao->o = 0xdf;
		ao->o |= (0xff & getnum (ao->a[0])) << 8;
		return 2;
	} else
	if (!strcmpnull (ao->op, "b") || !strcmpnull (ao->op, "b.n")) {
		//uncond branch : PC += 4 + (delta*2)
		int delta = getnum (ao->a[0]) - 4 - ao->off;
		if ((delta < -2048) || (delta > 2046) || (delta & 1)) {
			eprintf("branch out of range or not even\n");
			return 0;
		}
		ut16 opcode = 0xe000 | ((delta / 2) & 0x7ff);	//11bit offset>>1
		ao->o = opcode >>8;
		ao->o |= (opcode & 0xff)<<8;	// (ut32) ao->o holds the opcode in little-endian format !?
		return 2;
	} else