* Apply two patches from flux (thanks!)

- Implement barrel shifter for the ARM assembler
  - fix type of bitwide ops (and, eor, ...)
This commit is contained in:
pancake 2012-02-01 16:51:59 +01:00
parent 0c5a3834f4
commit b909e43976

View File

@ -3,6 +3,7 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <r_util.h>
// TODO: only lo registers accessible in thumb arm
@ -74,12 +75,12 @@ static ArmOp ops[] = {
{ "mvn", 0, TYPE_MOV },
{ "svc", 0xf, TYPE_SWI }, // ???
{ "and", 0x0, TYPE_TST },
{ "ands", 0x1000, TYPE_TST },
{ "eor", 0x2000, TYPE_TST },
{ "eors", 0x3000, TYPE_TST },
{ "orr", 0x0, TYPE_TST },
{ "bic", 0x0, TYPE_TST },
{ "and", 0x0000, TYPE_ARI },
{ "ands", 0x1000, TYPE_ARI },
{ "eor", 0x2000, TYPE_ARI },
{ "eors", 0x3000, TYPE_ARI },
{ "orr", 0x0, TYPE_ARI },
{ "bic", 0x0, TYPE_ARI },
{ "cmp", 0x4001, TYPE_TST },
{ "cmn", 0x0, TYPE_TST },
@ -148,11 +149,61 @@ static int getlist(char *op) {
return list;
}
static int getshift(const char *str) {
if (!str) return 0;
while (str && *str && !atoi (str))
str++;
return atoi (str)>>1;
static ut32 getshift(const char *str) {
char type[128];
char arg[128];
char *space;
ut32 i=0, shift=0;
const char *shifts[] = {
"LSL", "LSR", "ASR", "ROR",
0,
"RRX" // alias for ROR #0
};
strncpy (type, str, sizeof(type)-1);
// handle RRX alias case
if (!strcasecmp (type, shifts[5])) {
shift = 6;
}
// all other shift types
else {
// split the string into type and arg
space = strchr(type, ' ');
if (!space)
return 0;
*space = 0;
strncpy (arg, ++space, sizeof(arg)-1);
for (i=0; shifts[i]; i++) {
if (!strcasecmp (type, shifts[i])) {
shift = 1;
break;
}
}
if (!shift)
return 0;
shift = (i*2);
if ((i = getreg(arg)) != -1) {
shift |= 1;
i = i<<4;
}
else {
i = getnum (arg);
// ensure only the bottom 5 bits are used
i &= 0x1f;
if (!i)
i = 32;
i = (i*8);
}
}
i += shift;
i = i << 4;
r_mem_copyendian(&shift, &i, sizeof(ut32), 0);
return shift;
}
static void arm_opcode_parse(ArmOpcode *ao, const char *str) {
@ -493,6 +544,8 @@ static int arm_assemble(ArmOpcode *ao, const char *str) {
ao->o |= getreg (ao->a[1])<<8;
ret = getreg (ao->a[2]);
ao->o |= (ret!=-1)? ret<<24 : 2 | getnum(ao->a[2])<<24;
if (ao->a[3])
ao->o |= getshift (ao->a[3]);
break;
case TYPE_MOV:
ao->o |= getreg (ao->a[0])<<20;
@ -504,7 +557,8 @@ static int arm_assemble(ArmOpcode *ao, const char *str) {
//ao->o |= getreg(ao->a[0])<<20; // ???
ao->o |= getreg (ao->a[0])<<8;
ao->o |= getreg (ao->a[1])<<24;
ao->o |= getshift (ao->a[2])<<16; // shift
if (ao->a[2])
ao->o |= getshift (ao->a[2]);
break;
}
return 1;