Rizin
unix-like reverse engineering framework and cli tools
armass64.c File Reference
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <rz_util.h>
#include "armass64_const.h"

Go to the source code of this file.

Classes

struct  operand_t
 
struct  Opcode_t
 

Macros

#define MAX_OPERANDS   7
 
#define check_cond(cond)
 
#define COND_CASE(a, b)   case (ut16)(a) << 8 | (ut16)(b)
 

Typedefs

typedef enum optype_t OpType
 
typedef enum regtype_t RegType
 
typedef enum shifttype_t ShiftType
 
typedef enum logicalop_t LogicalOp
 
typedef struct operand_t Operand
 
typedef struct Opcode_t ArmOp
 

Enumerations

enum  optype_t {
  ARM_NOTYPE = -1 , ARM_GPR = 1 , ARM_CONSTANT = 2 , ARM_FP = 4 ,
  ARM_MEM_OPT = 8 , ARM_SHIFT = 16 , ARM_EXTEND = 32
}
 
enum  regtype_t {
  ARM_UNDEFINED = -1 , ARM_REG64 = 1 , ARM_REG32 = 2 , ARM_SP = 4 ,
  ARM_PC = 8 , ARM_SIMD = 16
}
 
enum  shifttype_t {
  ARM_LSL = 0 , ARM_LSR = 1 , ARM_ASR = 2 , ARM_ROR = 3 ,
  ARM_UXTB , ARM_UXTH , ARM_UXTW , ARM_UXTX ,
  ARM_SXTB , ARM_SXTH , ARM_SXTW , ARM_SXTX
}
 
enum  logicalop_t { ARM_AND = 0 , ARM_ORR = 1 , ARM_EOR = 2 , ARM_ANDS = 3 }
 

Functions

static int get_mem_option (char *token)
 
static int countLeadingZeros (ut64 x)
 
static int countTrailingZeros (ut64 x)
 
static int calcNegOffset (int n, int shift)
 
static int countLeadingOnes (ut64 x)
 
static int countTrailingOnes (ut64 x)
 
static bool isMask (ut64 value)
 
static bool isShiftedMask (ut64 value)
 
static ut32 encodeBitMasksWithSize (ut64 imm, ut32 reg_size)
 
static ut32 encode1reg (ArmOp *op)
 
static ut32 encode2regs (ArmOp *op)
 
static ut32 encodeImm9 (ut32 n)
 
static ut32 mov (ArmOp *op)
 
static ut32 cb (ArmOp *op)
 
static ut32 cmp (ArmOp *op)
 
static ut32 regsluop (ArmOp *op, int k)
 
static ut32 reglsop (ArmOp *op, int k)
 
static ut32 lsop (ArmOp *op, int k, ut64 addr)
 
static ut32 branch (ArmOp *op, ut64 addr, int k)
 
static ut32 bdot (ArmOp *op, ut64 addr, int k)
 
static ut8 parse_cond (const char *str)
 
static ut32 parse_bdot (const char *str, ArmOp *op, ut64 addr)
 
static ut32 mem_barrier (ArmOp *op, ut64 addr, int k)
 
static ut32 msr (ArmOp *op, int w)
 
static ut32 logical (ArmOp *op, bool invert, LogicalOp opc)
 
static ut32 adrp (ArmOp *op, ut64 addr, ut32 k)
 
static ut32 adr (ArmOp *op, int addr)
 
static ut32 stp (ArmOp *op, int k)
 
static ut32 exception (ArmOp *op, ut32 k)
 
static ut32 arithmetic (ArmOp *op, int k)
 
static ut32 neg (ArmOp *op)
 
static ut32 bitfield (ArmOp *op, int k)
 
static bool parseOperands (char *str, ArmOp *op)
 
static bool parseOpcode (const char *str, ArmOp *op)
 
static bool handlePAC (ut32 *op, const char *str)
 
bool arm64ass (const char *str, ut64 addr, ut32 *op)
 

Macro Definition Documentation

◆ check_cond

#define check_cond (   cond)
Value:
if (!(cond)) { \
return data; \
}
#define cond(bop, top, mask, flags)

Definition at line 87 of file armass64.c.

◆ COND_CASE

#define COND_CASE (   a,
  b 
)    case (ut16)(a) << 8 | (ut16)(b)

◆ MAX_OPERANDS

#define MAX_OPERANDS   7

Definition at line 75 of file armass64.c.

Typedef Documentation

◆ ArmOp

typedef struct Opcode_t ArmOp

◆ LogicalOp

typedef enum logicalop_t LogicalOp

◆ Operand

typedef struct operand_t Operand

◆ OpType

typedef enum optype_t OpType

◆ RegType

typedef enum regtype_t RegType

◆ ShiftType

typedef enum shifttype_t ShiftType

Enumeration Type Documentation

◆ logicalop_t

Enumerator
ARM_AND 
ARM_ORR 
ARM_EOR 
ARM_ANDS 

Definition at line 44 of file armass64.c.

44  {
45  ARM_AND = 0,
46  ARM_ORR = 1,
47  ARM_EOR = 2,
48  ARM_ANDS = 3
49 } LogicalOp;
@ ARM_AND
Definition: armass64.c:45
@ ARM_EOR
Definition: armass64.c:47
@ ARM_ANDS
Definition: armass64.c:48
@ ARM_ORR
Definition: armass64.c:46
enum logicalop_t LogicalOp

◆ optype_t

enum optype_t
Enumerator
ARM_NOTYPE 
ARM_GPR 
ARM_CONSTANT 
ARM_FP 
ARM_MEM_OPT 
ARM_SHIFT 
ARM_EXTEND 

Definition at line 10 of file armass64.c.

10  {
11  ARM_NOTYPE = -1,
12  ARM_GPR = 1,
13  ARM_CONSTANT = 2,
14  ARM_FP = 4,
15  ARM_MEM_OPT = 8,
16  ARM_SHIFT = 16,
17  ARM_EXTEND = 32
18 } OpType;
@ ARM_CONSTANT
Definition: armass64.c:13
@ ARM_GPR
Definition: armass64.c:12
@ ARM_FP
Definition: armass64.c:14
@ ARM_MEM_OPT
Definition: armass64.c:15
@ ARM_NOTYPE
Definition: armass64.c:11
@ ARM_SHIFT
Definition: armass64.c:16
@ ARM_EXTEND
Definition: armass64.c:17
enum optype_t OpType

◆ regtype_t

enum regtype_t
Enumerator
ARM_UNDEFINED 
ARM_REG64 
ARM_REG32 
ARM_SP 
ARM_PC 
ARM_SIMD 

Definition at line 20 of file armass64.c.

20  {
21  ARM_UNDEFINED = -1,
22  ARM_REG64 = 1,
23  ARM_REG32 = 2,
24  ARM_SP = 4,
25  ARM_PC = 8,
26  ARM_SIMD = 16
27 } RegType;
@ ARM_UNDEFINED
Definition: armass64.c:21
@ ARM_PC
Definition: armass64.c:25
@ ARM_REG32
Definition: armass64.c:23
@ ARM_SP
Definition: armass64.c:24
@ ARM_REG64
Definition: armass64.c:22
@ ARM_SIMD
Definition: armass64.c:26
enum regtype_t RegType

◆ shifttype_t

Enumerator
ARM_LSL 
ARM_LSR 
ARM_ASR 
ARM_ROR 
ARM_UXTB 
ARM_UXTH 
ARM_UXTW 
ARM_UXTX 
ARM_SXTB 
ARM_SXTH 
ARM_SXTW 
ARM_SXTX 

Definition at line 29 of file armass64.c.

29  {
30  ARM_LSL = 0,
31  ARM_LSR = 1,
32  ARM_ASR = 2,
33  ARM_ROR = 3,
34  ARM_UXTB,
35  ARM_UXTH,
36  ARM_UXTW,
37  ARM_UXTX,
38  ARM_SXTB,
39  ARM_SXTH,
40  ARM_SXTW,
41  ARM_SXTX
42 } ShiftType;
enum shifttype_t ShiftType
@ ARM_UXTH
Definition: armass64.c:35
@ ARM_SXTB
Definition: armass64.c:38
@ ARM_LSL
Definition: armass64.c:30
@ ARM_ASR
Definition: armass64.c:32
@ ARM_UXTB
Definition: armass64.c:34
@ ARM_SXTX
Definition: armass64.c:41
@ ARM_LSR
Definition: armass64.c:31
@ ARM_ROR
Definition: armass64.c:33
@ ARM_UXTW
Definition: armass64.c:36
@ ARM_UXTX
Definition: armass64.c:37
@ ARM_SXTH
Definition: armass64.c:39
@ ARM_SXTW
Definition: armass64.c:40

Function Documentation

◆ adr()

static ut32 adr ( ArmOp op,
int  addr 
)
static

Definition at line 884 of file armass64.c.

884  {
885  ut32 data = UT32_MAX;
886  ut64 at = 0LL;
887 
888  if (op->operands[1].type & ARM_CONSTANT) {
889  // XXX what about negative values?
890  at = op->operands[1].immediate - addr;
891  at /= 4;
892  }
893  data = 0x00000030;
894  data |= encode1reg(op);
895  ut8 b0 = at;
896  ut8 b1 = (at >> 3) & 0xff;
897  ut8 b2 = (at >> (8 + 7)) & 0xff;
898  data += b0 << 29;
899  data += b1 << 16;
900  data += b2 << 24;
901  return data;
902 }
static ut32 encode1reg(ArmOp *op)
Definition: armass64.c:211
uint32_t ut32
uint8_t ut8
Definition: lh5801.h:11
#define UT32_MAX
Definition: rz_types_base.h:99
Definition: dis.c:32
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58

References addr, ARM_CONSTANT, b1, b2, encode1reg(), UT32_MAX, and ut64().

Referenced by arm64ass().

◆ adrp()

static ut32 adrp ( ArmOp op,
ut64  addr,
ut32  k 
)
static

Definition at line 853 of file armass64.c.

853  { //, int reg, ut64 dst) {
854  ut64 at = 0LL;
855  ut32 data = k;
856  if (op->operands[0].type == ARM_GPR) {
857  data |= encode1reg(op);
858  } else {
859  RZ_LOG_ERROR("assembler: arm64: adrp: invalid assembly. valid usage: adrp x0, addr\n");
860  return UT32_MAX;
861  }
862  if (op->operands[1].type == ARM_CONSTANT) {
863  // XXX what about negative values?
864  at = op->operands[1].immediate - addr;
865  at /= 4;
866  } else {
867  RZ_LOG_ERROR("assembler: arm64: adrp: invalid assembly. valid usage: adrp x0, addr\n");
868  return UT32_MAX;
869  }
870  ut8 b0 = at;
871  ut8 b1 = (at >> 3) & 0xff;
872 
873 #if 0
874  ut8 b2 = (at >> (8 + 7)) & 0xff;
875  data += b0 << 29;
876  data += b1 << 16;
877  data += b2 << 24;
878 #endif
879  data += b0 << 16;
880  data += b1 << 8;
881  return data;
882 }
const char * k
Definition: dsignal.c:11
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58

References addr, ARM_CONSTANT, ARM_GPR, b1, b2, encode1reg(), k, RZ_LOG_ERROR, UT32_MAX, and ut64().

Referenced by arm64ass(), and extract_addr_from_code().

◆ arithmetic()

static ut32 arithmetic ( ArmOp op,
int  k 
)
static

Definition at line 933 of file armass64.c.

933  {
934  ut32 data = UT32_MAX;
935  if (op->operands_count < 3) {
936  return data;
937  }
938 
939  if (!(op->operands[0].type & ARM_GPR &&
940  op->operands[1].type & ARM_GPR)) {
941  return data;
942  }
943  if (op->operands[2].type & ARM_GPR) {
944  k -= 6;
945  }
946  data = k;
947  data += encode1reg(op);
948  data += (op->operands[1].reg & 7) << (24 + 5);
949  data += (op->operands[1].reg >> 3) << 16;
950  if (op->operands[2].type & ARM_GPR) {
951  data += op->operands[2].reg << 8;
952  } else {
953  data += (op->operands[2].reg & 0x3f) << 18;
954  data += (op->operands[2].reg >> 6) << 8;
955  }
956 
957  if (op->operands[2].type & ARM_CONSTANT && op->operands[3].type & ARM_SHIFT) {
958  if ((op->operands[3].shift == ARM_LSL) && (op->operands[3].shift_amount == 12)) {
959  data |= (0x4000);
960  }
961  }
962 
963  if (op->operands[2].type & ARM_GPR && op->operands[3].type & ARM_SHIFT) {
964  switch (op->operands[3].shift) {
965  case ARM_LSL:
966  data |= (0x00040000 * op->operands[3].shift_amount);
967  break;
968  case ARM_LSR:
969  data |= (0x00040000 * op->operands[3].shift_amount) | (0x4000);
970  break;
971  case ARM_ASR:
972  data |= (0x00040000 * op->operands[3].shift_amount) | (0x8000);
973  break;
974  default:
975  return data;
976  }
977  }
978  return data;
979 }

References ARM_ASR, ARM_CONSTANT, ARM_GPR, ARM_LSL, ARM_LSR, ARM_SHIFT, encode1reg(), k, and UT32_MAX.

Referenced by arm64ass(), neg(), rop_classify_arithmetic(), and rop_classify_arithmetic_const().

◆ arm64ass()

bool arm64ass ( const char *  str,
ut64  addr,
ut32 op 
)

Definition at line 1348 of file armass64.c.

1348  {
1349  *op = UT32_MAX;
1350  ArmOp ops = { 0 };
1351  if (!parseOpcode(str, &ops)) {
1352  free(ops.mnemonic);
1353  return false;
1354  }
1355  /* TODO: write tests for this and move out the regsize logic into the mov */
1356  if (!strncmp(str, "mov", 3)) {
1357  *op = mov(&ops);
1358  } else if (!strncmp(str, "cb", 2)) {
1359  *op = cb(&ops);
1360  } else if (!strncmp(str, "cmp", 3)) {
1361  *op = cmp(&ops);
1362  } else if (!strncmp(str, "ldrb", 4)) {
1363  *op = lsop(&ops, 0x00004038, -1);
1364  } else if (!strncmp(str, "ldrh", 4)) {
1365  *op = lsop(&ops, 0x00004078, -1);
1366  } else if (!strncmp(str, "ldrsh", 5)) {
1367  *op = lsop(&ops, 0x00008078, -1);
1368  } else if (!strncmp(str, "ldrsw", 5)) {
1369  *op = lsop(&ops, 0x00000098, addr);
1370  } else if (!strncmp(str, "ldrsb", 5)) {
1371  *op = lsop(&ops, 0x00008038, -1);
1372  } else if (!strncmp(str, "strb", 4)) {
1373  *op = lsop(&ops, 0x00000038, -1);
1374  } else if (!strncmp(str, "strh", 4)) {
1375  *op = lsop(&ops, 0x00000078, -1);
1376  } else if (!strncmp(str, "ldr", 3)) {
1377  *op = reglsop(&ops, 0x000040f8);
1378  } else if (!strncmp(str, "stur", 4)) {
1379  *op = regsluop(&ops, 0x000000f8);
1380  } else if (!strncmp(str, "ldur", 4)) {
1381  *op = regsluop(&ops, 0x000040f8);
1382  } else if (!strncmp(str, "str", 3)) {
1383  *op = reglsop(&ops, 0x000000f8);
1384  } else if (!strncmp(str, "stp", 3)) {
1385  *op = stp(&ops, 0x000000a9);
1386  } else if (!strncmp(str, "ldp", 3)) {
1387  *op = stp(&ops, 0x000040a9);
1388  } else if (!strncmp(str, "sub", 3)) { // w
1389  *op = arithmetic(&ops, 0xd1);
1390  } else if (!strncmp(str, "add x", 5)) {
1391  *op = arithmetic(&ops, 0x91);
1392  } else if (!strncmp(str, "add w", 5)) {
1393  *op = arithmetic(&ops, 0x11);
1394  } else if (!strncmp(str, "adr x", 5)) { // w
1395  *op = adr(&ops, addr);
1396  } else if (!strncmp(str, "adrp x", 6)) {
1397  *op = adrp(&ops, addr, 0x00000090);
1398  } else if (!strncmp(str, "neg", 3)) {
1399  *op = neg(&ops);
1400  } else if (!strcmp(str, "isb")) {
1401  *op = 0xdf3f03d5;
1402  } else if (handlePAC(op, str)) { // PAC
1403  free(ops.mnemonic);
1404  return true;
1405  } else if (!strcmp(str, "nop")) {
1406  *op = 0x1f2003d5;
1407  } else if (!strcmp(str, "ret")) {
1408  *op = 0xc0035fd6;
1409  } else if (!strncmp(str, "msr ", 4)) {
1410  *op = msr(&ops, 0);
1411  } else if (!strncmp(str, "mrs ", 4)) {
1412  *op = msr(&ops, 1);
1413  } else if (!strncmp(str, "ands ", 5)) {
1414  *op = logical(&ops, false, ARM_ANDS);
1415  } else if (!strncmp(str, "and ", 4)) {
1416  *op = logical(&ops, false, ARM_AND);
1417  } else if (!strncmp(str, "bics ", 5)) {
1418  *op = logical(&ops, true, ARM_ANDS);
1419  } else if (!strncmp(str, "bic ", 4)) {
1420  *op = logical(&ops, true, ARM_AND);
1421  } else if (!strncmp(str, "eon ", 4)) {
1422  *op = logical(&ops, true, ARM_EOR);
1423  } else if (!strncmp(str, "eor ", 4)) {
1424  *op = logical(&ops, false, ARM_EOR);
1425  } else if (!strncmp(str, "orn ", 4)) {
1426  *op = logical(&ops, true, ARM_ORR);
1427  } else if (!strncmp(str, "orr ", 4)) {
1428  *op = logical(&ops, false, ARM_ORR);
1429  } else if (!strncmp(str, "svc ", 4)) { // system level exception
1430  *op = exception(&ops, 0x010000d4);
1431  } else if (!strncmp(str, "hvc ", 4)) { // hypervisor level exception
1432  *op = exception(&ops, 0x020000d4);
1433  } else if (!strncmp(str, "smc ", 4)) { // secure monitor exception
1434  *op = exception(&ops, 0x030000d4);
1435  } else if (!strncmp(str, "brk ", 4)) { // breakpoint
1436  *op = exception(&ops, 0x000020d4);
1437  } else if (!strncmp(str, "hlt ", 4)) { // halt
1438  *op = exception(&ops, 0x000040d4);
1439  } else if (!strncmp(str, "b ", 2)) {
1440  *op = branch(&ops, addr, 0x14);
1441  } else if (!strncmp(str, "b.", 2)) {
1442  *op = parse_bdot(str + 2, &ops, addr);
1443  } else if (!strncmp(str, "bl ", 3)) {
1444  *op = branch(&ops, addr, 0x94);
1445  } else if (!strncmp(str, "br x", 4)) {
1446  *op = branch(&ops, addr, 0x1fd6);
1447  } else if (!strncmp(str, "blr x", 5)) {
1448  *op = branch(&ops, addr, 0x3fd6);
1449  } else if (!strncmp(str, "dmb ", 4)) {
1450  *op = mem_barrier(&ops, addr, 0xbf3003d5);
1451  } else if (!strncmp(str, "dsb ", 4)) {
1452  *op = mem_barrier(&ops, addr, 0x9f3003d5);
1453  } else if (!strncmp(str, "isb", 3)) {
1454  *op = mem_barrier(&ops, addr, 0xdf3f03d5);
1455  } else if (!strncmp(str, "sbfiz ", 6) || !strncmp(str, "sbfm ", 5) || !strncmp(str, "sbfx ", 5)) {
1456  *op = bitfield(&ops, 0x00000013);
1457  } else if (!strncmp(str, "ubfiz ", 6) || !strncmp(str, "ubfm ", 5) || !strncmp(str, "ubfx ", 5)) {
1458  *op = bitfield(&ops, 0x00000053);
1459  }
1460  free(ops.mnemonic);
1461  return *op != UT32_MAX;
1462 }
static struct @29 ops[]
static ut32 parse_bdot(const char *str, ArmOp *op, ut64 addr)
Definition: armass64.c:673
static ut32 branch(ArmOp *op, ut64 addr, int k)
Definition: armass64.c:571
static ut32 bitfield(ArmOp *op, int k)
Definition: armass64.c:992
static ut32 logical(ArmOp *op, bool invert, LogicalOp opc)
Definition: armass64.c:786
static ut32 neg(ArmOp *op)
Definition: armass64.c:981
static ut32 cb(ArmOp *op)
Definition: armass64.c:310
static ut32 exception(ArmOp *op, ut32 k)
Definition: armass64.c:921
static ut32 adrp(ArmOp *op, ut64 addr, ut32 k)
Definition: armass64.c:853
static ut32 mov(ArmOp *op)
Definition: armass64.c:223
static ut32 arithmetic(ArmOp *op, int k)
Definition: armass64.c:933
static ut32 reglsop(ArmOp *op, int k)
Definition: armass64.c:405
static bool handlePAC(ut32 *op, const char *str)
Definition: armass64.c:1308
static bool parseOpcode(const char *str, ArmOp *op)
Definition: armass64.c:1293
static ut32 mem_barrier(ArmOp *op, ut64 addr, int k)
Definition: armass64.c:686
static ut32 lsop(ArmOp *op, int k, ut64 addr)
Definition: armass64.c:462
static ut32 cmp(ArmOp *op)
Definition: armass64.c:340
static ut32 regsluop(ArmOp *op, int k)
Definition: armass64.c:362
static ut32 adr(ArmOp *op, int addr)
Definition: armass64.c:884
static ut32 msr(ArmOp *op, int w)
Definition: armass64.c:706
static ut32 stp(ArmOp *op, int k)
Definition: armass64.c:904
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
Definition: armass.c:21

References addr, adr(), adrp(), arithmetic(), ARM_AND, ARM_ANDS, ARM_EOR, ARM_ORR, bitfield(), branch(), cb(), cmp(), exception(), free(), handlePAC(), logical(), lsop(), mem_barrier(), mov(), msr(), neg(), ops, parse_bdot(), parseOpcode(), reglsop(), regsluop(), stp(), cmd_descs_generate::str, and UT32_MAX.

Referenced by assemble().

◆ bdot()

static ut32 bdot ( ArmOp op,
ut64  addr,
int  k 
)
static

Definition at line 610 of file armass64.c.

610  {
611  ut32 data = UT32_MAX;
612  int n = 0;
613  int a = 0;
614  n = op->operands[0].immediate;
615  // I am sure there's a logical way to do negative offsets,
616  // but I was unable to find any sensible docs so I did my best
617  if (!(n & 0x3 || n > 0x7ffffff)) {
618  n -= addr;
619  data = k;
620  if (n < 0) {
621  n *= -1;
622  a = (n << 3) - 1;
623  data |= (0xff - a) << 24;
624 
625  a = calcNegOffset(n, 5);
626  data |= a << 16;
627 
628  a = calcNegOffset(n, 13);
629  data |= a << 8;
630  } else {
631  data |= (n & 31) << 27;
632  data |= (0xff & (n >> 5)) << 16;
633  data |= (0xff & (n >> 13)) << 8;
634  }
635  }
636 
637  return data;
638 }
static int calcNegOffset(int n, int shift)
Definition: armass64.c:125
int n
Definition: mipsasm.c:19
#define a(i)
Definition: sha256.c:41

References a, addr, calcNegOffset(), k, n, and UT32_MAX.

Referenced by parse_bdot().

◆ bitfield()

static ut32 bitfield ( ArmOp op,
int  k 
)
static

Definition at line 992 of file armass64.c.

992  {
993  ut32 data = UT32_MAX;
994  check_cond(op->operands_count == 4);
995  check_cond(op->operands[0].type == ARM_GPR);
996  check_cond(op->operands[1].type == ARM_GPR);
997  check_cond(op->operands[0].reg_type == op->operands[1].reg_type);
998  check_cond(op->operands[2].type == ARM_CONSTANT);
999  check_cond(op->operands[3].type == ARM_CONSTANT);
1000  int bits = (op->operands[0].reg_type & ARM_REG64) ? 64 : 32;
1001  // unalias
1002  if (!strcmp(op->mnemonic, "sbfx") || !strcmp(op->mnemonic, "ubfx")) {
1003  op->operands[3].immediate += op->operands[2].immediate - 1;
1004  } else if (!strcmp(op->mnemonic, "sbfiz") || !strcmp(op->mnemonic, "ubfiz")) {
1005  check_cond(op->operands[2].immediate < bits);
1006  int temp = bits - op->operands[2].immediate;
1007  check_cond(op->operands[3].immediate <= temp);
1008  op->operands[2].immediate = temp & (bits - 1);
1009  op->operands[3].immediate--;
1010  }
1011  check_cond(op->operands[2].immediate < bits);
1012  check_cond(op->operands[3].immediate < bits);
1013  if (bits == 64) {
1014  k |= 0x00004080;
1015  }
1016  k |= op->operands[2].immediate << 8 | op->operands[3].immediate << 18;
1017  data = k | encode2regs(op);
1018  return data;
1019 }
#define check_cond(cond)
Definition: armass64.c:87
static ut32 encode2regs(ArmOp *op)
Definition: armass64.c:215
int bits(struct state *s, int need)
Definition: blast.c:72

References ARM_CONSTANT, ARM_GPR, ARM_REG64, bits(), check_cond, encode2regs(), k, and UT32_MAX.

Referenced by arm64ass().

◆ branch()

static ut32 branch ( ArmOp op,
ut64  addr,
int  k 
)
static

Definition at line 571 of file armass64.c.

571  {
572  ut32 data = UT32_MAX;
573  ut64 n = 0;
574  if (op->operands[0].type & ARM_CONSTANT) {
575  n = op->operands[0].immediate;
576  if (!(n & 0x3)) {
577  if (n >= addr) {
578  n -= addr;
579  } else {
580  n -= addr;
581  n = n & 0xfffffff;
582  k |= 3;
583  }
584  n = n >> 2;
585  int t = (n & 0xff000000) >> 24;
586  int h = (n & 0xff0000) >> 16;
587  int m = (n & 0xff00) >> 8;
588  n &= 0xff;
589  data = k;
590  data |= n << 24;
591  data |= m << 16;
592  data |= h << 8;
593  data |= t;
594  }
595  } else {
596  n = op->operands[0].reg;
597  if (n >= 31) {
598  return -1;
599  }
600  n = n << 5;
601  int h = n >> 8;
602  n &= 0xff;
603  data = k;
604  data |= n << 24;
605  data |= h << 16;
606  }
607  return data;
608 }
#define h(i)
Definition: sha256.c:48

References addr, ARM_CONSTANT, h, k, regress::m, n, UT32_MAX, and ut64().

Referenced by arm64ass().

◆ calcNegOffset()

static int calcNegOffset ( int  n,
int  shift 
)
static

Definition at line 125 of file armass64.c.

125  {
126  int a = n >> shift;
127  if (a == 0) {
128  return 0xff;
129  }
130  // find first set bit then invert it and all
131  // bits below it
132  int t = 0x400;
133  while (!(t & a) && a != 0 && t != 0) {
134  t = t >> 1;
135  }
136  t = t & (t - 1);
137  a = a ^ t;
138  // If bits below 32 are set
139  if (countTrailingZeros(n) > shift) {
140  a--;
141  }
142  return 0xff & (0xff - a);
143 }
static RZ_NULLABLE RzILOpBitVector * shift(RzILOpBitVector *val, RZ_NULLABLE RzILOpBool **carry_out, arm_shifter type, RZ_OWN RzILOpBitVector *dist)
Definition: arm_il32.c:190
static int countTrailingZeros(ut64 x)
Definition: armass64.c:116

References a, countTrailingZeros(), n, and shift().

Referenced by bdot().

◆ cb()

static ut32 cb ( ArmOp op)
static

Definition at line 310 of file armass64.c.

310  {
311  ut32 data = UT32_MAX;
312  int k = 0;
313  if (!strncmp(op->mnemonic, "cbnz", 4)) {
314  if (op->operands[0].reg_type & ARM_REG64) {
315  k = 0x000000b5;
316  } else if (op->operands[0].reg_type & ARM_REG32) {
317  k = 0x00000035;
318  } else {
319  return UT32_MAX;
320  }
321  } else if (!strncmp(op->mnemonic, "cbz", 3)) {
322  if (op->operands[0].reg_type & ARM_REG64) {
323  k = 0x000000b4;
324  } else if (op->operands[0].reg_type & ARM_REG32) {
325  k = 0x00000034;
326  } else {
327  return UT32_MAX;
328  }
329  } else {
330  return UT32_MAX;
331  }
332  // printf ("%s %d, %llu\n", op->mnemonic, op->operands[0].reg, op->operands[1].immediate);
333  ut32 imm = op->operands[1].immediate;
334  data = k | encode1reg(op) | ((imm & 0x1c) << 27) | ((imm & 0x1fe0) << 11);
335  data = data | ((imm & 0x1fe000) >> 5);
336 
337  return data;
338 }
#define imm

References ARM_REG32, ARM_REG64, encode1reg(), imm, k, and UT32_MAX.

Referenced by arm64ass().

◆ cmp()

static ut32 cmp ( ArmOp op)
static

Definition at line 340 of file armass64.c.

340  {
341  ut32 data = UT32_MAX;
342  int k = 0;
343  if (op->operands[0].reg_type & ARM_REG64 && op->operands[1].reg_type & ARM_REG64) {
344  k = 0x1f0000eb;
345  } else if (op->operands[0].reg_type & ARM_REG32 && op->operands[1].reg_type & ARM_REG32) {
346  if (op->operands[2].shift_amount > 31) {
347  return UT32_MAX;
348  }
349  k = 0x1f00006b;
350  } else {
351  return UT32_MAX;
352  }
353 
354  data = k | (op->operands[0].reg & 0x18) << 13 | op->operands[0].reg << 29 | op->operands[1].reg << 8;
355 
356  if (op->operands[2].type != ARM_SHIFT) {
357  data |= op->operands[2].shift_amount << 18 | op->operands[2].shift << 14;
358  }
359  return data;
360 }
if(dbg->bits==RZ_SYS_BITS_64)
Definition: windows-arm64.h:4

References ARM_REG32, ARM_REG64, ARM_SHIFT, if(), k, and UT32_MAX.

Referenced by arm64ass().

◆ countLeadingOnes()

static int countLeadingOnes ( ut64  x)
static

Definition at line 145 of file armass64.c.

145  {
146  return countLeadingZeros(~x);
147 }
static int countLeadingZeros(ut64 x)
Definition: armass64.c:107
int x
Definition: mipsasm.c:20

References countLeadingZeros(), and x.

Referenced by encodeBitMasksWithSize().

◆ countLeadingZeros()

static int countLeadingZeros ( ut64  x)
static

Definition at line 107 of file armass64.c.

107  {
108  int count = 64;
109  while (x) {
110  x >>= 1;
111  --count;
112  }
113  return count;
114 }
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98

References count, and x.

Referenced by AArch64_AM_decodeLogicalImmediate(), AArch64_AM_isValidDecodeLogicalImmediate(), and countLeadingOnes().

◆ countTrailingOnes()

static int countTrailingOnes ( ut64  x)
static

Definition at line 149 of file armass64.c.

149  {
150  return countTrailingZeros(~x);
151 }

References countTrailingZeros(), and x.

Referenced by encodeBitMasksWithSize().

◆ countTrailingZeros()

static int countTrailingZeros ( ut64  x)
static

Definition at line 116 of file armass64.c.

116  {
117  int count = 0;
118  while (x && !(x & 1)) {
119  count++;
120  x >>= 1;
121  }
122  return count;
123 }

References count, and x.

Referenced by calcNegOffset(), countTrailingOnes(), encodeBitMasksWithSize(), reglsop(), and regsluop().

◆ encode1reg()

static ut32 encode1reg ( ArmOp op)
inlinestatic

Definition at line 211 of file armass64.c.

211  {
212  return op->operands[0].reg << 24;
213 }

Referenced by adr(), adrp(), arithmetic(), cb(), encode2regs(), lsop(), and mov().

◆ encode2regs()

static ut32 encode2regs ( ArmOp op)
inlinestatic

Definition at line 215 of file armass64.c.

215  {
216  return (op->operands[1].reg & 0x7) << 29 | (op->operands[1].reg & 0x18) << 13 | encode1reg(op);
217 }

References encode1reg().

Referenced by bitfield(), lsop(), mov(), reglsop(), regsluop(), and stp().

◆ encodeBitMasksWithSize()

static ut32 encodeBitMasksWithSize ( ut64  imm,
ut32  reg_size 
)
static

Definition at line 162 of file armass64.c.

162  {
163  if (imm == 0 || imm == UT64_MAX || (reg_size != 64 && (imm >> reg_size != 0 || imm == (~0ULL >> (64 - reg_size))))) {
164  return UT32_MAX;
165  }
166  // get element size
167  ut32 size = reg_size;
168  do {
169  size >>= 1;
170  ut64 mask = (1ull << size) - 1;
171  if ((imm & mask) != ((imm >> size) & mask)) {
172  size <<= 1;
173  break;
174  }
175  } while (size > 2);
176  // determine rot to make element be 0^m 1^n
177  ut32 cto, i;
178  ut64 mask = UT64_MAX >> (64 - size);
179  imm &= mask;
180 
181  if (isShiftedMask(imm)) {
183  cto = countTrailingOnes(imm >> i);
184  } else {
185  imm |= ~mask;
186  if (!isShiftedMask(~imm)) {
187  return UT32_MAX;
188  }
189 
190  ut32 clo = countLeadingOnes(imm);
191  i = 64 - clo;
192  cto = clo + countTrailingOnes(imm) - (64 - size);
193  }
194 
195  // Encode in Immr the number of RORs it would take to get *from* 0^m 1^n
196  // to our target value, where I is the number of RORs to go the opposite
197  // direction
198  ut32 immr = (size - i) & (size - 1);
199  // If size has a 1 in the n'th bit, create a value that has zeroes in
200  // bits [0, n] and ones above that.
201  ut64 nimms = ~(size - 1) << 1;
202  // Or the cto value into the low bits, which must be below the Nth bit
203  // bit mentioned above.
204  nimms |= (cto - 1);
205  // Extract and toggle seventh bit to make N field.
206  ut32 n = ((nimms >> 6) & 1) ^ 1;
207  ut32 encoding = (n << 12) | (immr << 6) | (nimms & 0x3f);
208  return encoding;
209 }
#define mask()
lzma_index ** i
Definition: index.h:629
static int countLeadingOnes(ut64 x)
Definition: armass64.c:145
static bool isShiftedMask(ut64 value)
Definition: armass64.c:157
static int countTrailingOnes(ut64 x)
Definition: armass64.c:149
voidpf void uLong size
Definition: ioapi.h:138
#define UT64_MAX
Definition: rz_types_base.h:86

References countLeadingOnes(), countTrailingOnes(), countTrailingZeros(), cmd_descs_generate::encoding, i, imm, isShiftedMask(), mask, n, UT32_MAX, ut64(), and UT64_MAX.

Referenced by logical(), and mov().

◆ encodeImm9()

static ut32 encodeImm9 ( ut32  n)
inlinestatic

Definition at line 219 of file armass64.c.

219  {
220  return (n & 0x1f0) << 4 | (n & 0xf) << 20;
221 }

References n.

Referenced by lsop().

◆ exception()

static ut32 exception ( ArmOp op,
ut32  k 
)
static

Definition at line 921 of file armass64.c.

921  {
922  ut32 data = UT32_MAX;
923 
924  if (op->operands[0].type == ARM_CONSTANT) {
925  int n = op->operands[0].immediate;
926  data = k;
927  data += (((n / 8) & 0xff) << 16);
928  data += n << 29; //((n >> 8) << 8);
929  }
930  return data;
931 }

References ARM_CONSTANT, k, n, and UT32_MAX.

Referenced by arm64ass().

◆ get_mem_option()

static int get_mem_option ( char *  token)
static

Definition at line 92 of file armass64.c.

92  {
93  // values 4, 8, 12, are unused. XXX to adjust
94  const char *options[] = { "sy", "st", "ld", "xxx", "ish", "ishst",
95  "ishld", "xxx", "nsh", "nshst", "nshld",
96  "xxx", "osh", "oshst", "oshld", NULL };
97  int i = 0;
98  while (options[i]) {
99  if (!rz_str_casecmp(token, options[i])) {
100  return 15 - i;
101  }
102  i++;
103  }
104  return -1;
105 }
#define NULL
Definition: cris-opc.c:27
static const char struct stat static buf struct stat static buf static vhangup int options
Definition: sflib.h:145
RZ_API int rz_str_casecmp(const char *dst, const char *orig)
Definition: str.c:121

References i, NULL, options, and rz_str_casecmp().

Referenced by parseOperands().

◆ handlePAC()

static bool handlePAC ( ut32 op,
const char *  str 
)
static

Definition at line 1308 of file armass64.c.

1308  {
1309  if (!strcmp(str, "autiasp")) {
1310  *op = 0xbf2303d5;
1311  return true;
1312  }
1313  if (!strcmp(str, "autiaz")) {
1314  *op = 0x9f2303d5;
1315  return true;
1316  }
1317  if (!strcmp(str, "autibsp")) {
1318  *op = 0xff2303d5;
1319  return true;
1320  }
1321  if (!strcmp(str, "autibz")) {
1322  *op = 0xdf2303d5;
1323  return true;
1324  }
1325  if (!strcmp(str, "paciaz")) {
1326  *op = 0x1f2303d5;
1327  return true;
1328  }
1329  if (!strcmp(str, "pacibz")) {
1330  *op = 0x5f2303d5;
1331  return true;
1332  }
1333  if (!strcmp(str, "paciasp")) {
1334  *op = 0x3f2303d5;
1335  return true;
1336  }
1337  if (!strcmp(str, "pacibsp")) {
1338  *op = 0x7f2303d5;
1339  return true;
1340  }
1341  if (!strcmp(str, "retab")) {
1342  *op = 0xff0f5fd6;
1343  return true;
1344  }
1345  return false;
1346 }

References cmd_descs_generate::str.

Referenced by arm64ass().

◆ isMask()

static bool isMask ( ut64  value)
static

Definition at line 153 of file armass64.c.

153  {
154  return value && ((value + 1) & value) == 0;
155 }
static int value
Definition: cmd_api.c:93

References value.

Referenced by isShiftedMask().

◆ isShiftedMask()

static bool isShiftedMask ( ut64  value)
static

Definition at line 157 of file armass64.c.

157  {
158  return value && isMask((value - 1) | value);
159 }
static bool isMask(ut64 value)
Definition: armass64.c:153

References isMask(), and value.

Referenced by encodeBitMasksWithSize().

◆ logical()

static ut32 logical ( ArmOp op,
bool  invert,
LogicalOp  opc 
)
static

Definition at line 786 of file armass64.c.

786  {
787  ut32 data = UT32_MAX;
788  RegType reg_type = op->operands[0].reg_type;
789 
790  // Reg types need to match
791  if (!(reg_type == op->operands[1].reg_type)) {
792  return data;
793  }
794 
795  OpType op2_type = op->operands[2].type;
796  if (op2_type == ARM_CONSTANT) {
797  if (invert) {
798  /* there aren't inverted immediates in arm64 */
799  return UT32_MAX;
800  }
801  if (reg_type & ARM_REG64) {
802  data = 0x92000000;
803  } else if (reg_type & ARM_REG32) {
804  data = 0x12000000;
805  } else {
806  return UT32_MAX;
807  }
808 
809  bool is64bit = reg_type & ARM_REG64;
810 
811  data |= op->operands[0].reg;
812  data |= op->operands[1].reg << 5;
813  data |= (opc & 3) << 29;
814 
815  ut32 imm_orig = op->operands[2].immediate;
816  ut32 imm_mask = encodeBitMasksWithSize(invert ? ~imm_orig : imm_orig, is64bit ? 64 : 32);
817  if (imm_mask == UT32_MAX) {
818  return UT32_MAX;
819  }
820  data |= (imm_mask & 0x1fff) << 10;
821  } else if (op2_type == ARM_GPR) {
822  if (reg_type & ARM_REG64) {
823  data = 0x8a000000;
824  } else if (reg_type & ARM_REG32) {
825  data = 0x0a000000;
826  } else {
827  return UT32_MAX;
828  }
829 
830  data |= op->operands[0].reg;
831  data |= op->operands[1].reg << 5;
832  data |= op->operands[2].reg << 16;
833  data |= (opc & 3) << 29;
834 
835  if (op->operands_count == 4) {
836  Operand shift_op = op->operands[3];
837  if (shift_op.type == ARM_SHIFT) {
838  data |= (shift_op.shift_amount & 0x3f) << 10;
839  data |= (shift_op.shift & 0x3) << 22;
840  }
841  }
842 
843  if (invert) {
844  data |= 1 << 21;
845  }
846  } else {
847  return UT32_MAX;
848  }
849 
850  return rz_read_be32(&data);
851 }
static unsigned invert(unsigned x)
Definition: aesdata.c:73
static ut32 encodeBitMasksWithSize(ut64 imm, ut32 reg_size)
Definition: armass64.c:162
static ut64 opc
Definition: desil.c:33
static ut32 rz_read_be32(const void *src)
Definition: rz_endian.h:87
ut64 shift_amount
Definition: armass64.c:65
OpType type
Definition: armass64.c:52
ShiftType shift
Definition: armass64.c:66

References ARM_CONSTANT, ARM_GPR, ARM_REG32, ARM_REG64, ARM_SHIFT, encodeBitMasksWithSize(), invert(), opc, rz_read_be32(), operand_t::shift, operand_t::shift_amount, operand_t::type, and UT32_MAX.

Referenced by arm64ass().

◆ lsop()

static ut32 lsop ( ArmOp op,
int  k,
ut64  addr 
)
static

Definition at line 462 of file armass64.c.

462  {
463  ut32 data = UT32_MAX;
464  int op_count = op->operands_count;
465  if (k == 0x00000098) { // ldrsw
466  if (op->operands[0].type & ARM_GPR && op->operands[1].type & ARM_CONSTANT) { // (literal)
467  st64 offset = op->operands[1].immediate - addr;
468  check_cond(op->operands[0].reg_type & ARM_REG64);
469  check_cond(!(offset & 0x3));
470  check_cond(-0x100000 <= offset && offset < 0x100000);
471  offset >>= 2;
472  data = k | (offset & 0x7f800) >> 3 | (offset & 0x7f8) << 13 | (offset & 0x7) << 29 | encode1reg(op);
473  return data;
474  }
475  k = 0x000080b8;
476  }
477  check_cond(op->operands[0].type == ARM_GPR);
478  check_cond(op->operands[1].type == ARM_GPR);
479  check_cond(op->operands[1].reg_type & ARM_REG64);
480  k |= encode2regs(op);
481  if (!strcmp(op->mnemonic, "ldrb") || !strcmp(op->mnemonic, "ldrh") || !strcmp(op->mnemonic, "strb") || !strcmp(op->mnemonic, "strh")) {
482  check_cond(op->operands[0].reg_type & ARM_REG32);
483  } else if (!strcmp(op->mnemonic, "ldrsw")) {
484  check_cond(op->operands[0].reg_type & ARM_REG64);
485  } else { // ldrsh, ldrsb
486  if (op->operands[0].reg_type & ARM_REG32) {
487  k |= 0x00004000;
488  }
489  }
490  char width = op->mnemonic[strlen(op->mnemonic) - 1];
491  if (op->operands[2].type & ARM_GPR) {
492  k |= 0x00482000;
493  if (op->operands[3].type == ARM_EXTEND) {
494  switch (op->operands[3].shift) {
495  case ARM_SXTW:
496  k |= 0x00800000;
497  // fall through
498  case ARM_UXTW:
499  check_cond(op->operands[2].reg_type & ARM_REG32);
500  break;
501  case ARM_SXTX:
502  k |= 0x00a00000;
503  check_cond(op->operands[2].reg_type & ARM_REG64);
504  break;
505  default:
506  return data;
507  }
508  } else if (op->operands[3].type == ARM_SHIFT) {
509  check_cond(op->operands[3].shift == ARM_LSL);
510  check_cond(op->operands[2].reg_type & ARM_REG64);
511  k |= 0x00200000;
512  }
513  if (op->operands[3].type == ARM_EXTEND || op->operands[3].type == ARM_SHIFT) {
514  if (width == 'b') {
515  check_cond(op->operands[3].shift_amount == 0);
516  if (op->operands[3].amount_present) {
517  k |= 0x00100000;
518  }
519  } else if (width == 'h') {
520  switch (op->operands[3].shift_amount) {
521  case 1:
522  k |= 0x00100000;
523  // fall through
524  case 0:
525  break;
526  default:
527  return data;
528  }
529  } else { // w
530  switch (op->operands[3].shift_amount) {
531  case 2:
532  k |= 0x00100000;
533  // fall through
534  case 0:
535  break;
536  default:
537  return data;
538  }
539  }
540  } else { // lsl 0 by default
541  check_cond(op->operands[2].reg_type & ARM_REG64);
542  k |= 0x00200000;
543  }
544  data = k | op->operands[2].reg << 8;
545  return data;
546  }
547  check_cond(op_count == 2 || op->operands[2].type == ARM_CONSTANT);
548  check_cond(!op->writeback || op->operands[2].preindex);
549  int n = op_count == 2 ? 0 : op->operands[2].immediate;
550  if (!op->writeback && (op_count == 2 || op->operands[2].preindex)) { // unsigned offset
551  check_cond(n >= 0);
552  if (width == 'b') {
553  check_cond(n <= 0xfff);
554  } else if (width == 'h') {
555  check_cond(n <= 0x1ffe && !(n & 1))
556  n >>= 1;
557  } else { // w
558  check_cond(n <= 0x3ffc && !(n & 3));
559  n >>= 2;
560  }
561  data = k | (n & 0x3f) << 18 | (n & 0xfc0) << 2 | 1;
562  return data;
563  }
564  check_cond(-0x100 <= n && n < 0x100) if (op->operands[2].preindex) {
565  k |= 0x00080000;
566  }
567  data = k | encodeImm9(n) | 0x00040000;
568  return data;
569 }
static ut32 encodeImm9(ut32 n)
Definition: armass64.c:219
voidpf uLong offset
Definition: ioapi.h:144
#define st64
Definition: rz_types_base.h:10
int width
Definition: main.c:10

References addr, ARM_CONSTANT, ARM_EXTEND, ARM_GPR, ARM_LSL, ARM_REG32, ARM_REG64, ARM_SHIFT, ARM_SXTW, ARM_SXTX, ARM_UXTW, check_cond, encode1reg(), encode2regs(), encodeImm9(), k, n, st64, UT32_MAX, and width.

Referenced by arm64ass().

◆ mem_barrier()

static ut32 mem_barrier ( ArmOp op,
ut64  addr,
int  k 
)
static

Definition at line 686 of file armass64.c.

686  {
687  ut32 data = UT32_MAX;
688  data = k;
689  if (!strncmp(op->mnemonic, "isb", 3)) {
690  if (op->operands[0].mem_option == 15 || op->operands[0].type == ARM_NOTYPE) {
691  return data;
692  } else {
693  return UT32_MAX;
694  }
695  }
696  if (op->operands[0].type == ARM_MEM_OPT) {
697  data |= op->operands[0].mem_option << 16;
698  } else if (op->operands_count == 1 && op->operands[0].type == ARM_CONSTANT) {
699  data |= (op->operands[0].immediate << 16);
700  }
701  return data;
702 }

References ARM_CONSTANT, ARM_MEM_OPT, ARM_NOTYPE, k, and UT32_MAX.

Referenced by arm64ass().

◆ mov()

static ut32 mov ( ArmOp op)
static

Definition at line 223 of file armass64.c.

223  {
224  ut32 k = 0;
225  ut32 data = UT32_MAX;
226  check_cond(op->operands_count >= 2);
227  check_cond(op->operands[0].type == ARM_GPR);
228  int bits = (op->operands[0].reg_type & ARM_REG64) ? 64 : 32;
229  if (bits == 64) {
230  k = 0x0080;
231  }
232  k |= encode1reg(op);
233  if (!strcmp(op->mnemonic, "mov")) {
234  check_cond(op->operands_count == 2);
235  if (op->operands[1].type == ARM_GPR) {
236  check_cond(bits == ((op->operands[1].reg_type & ARM_REG64) ? 64 : 32));
237  if (op->operands[0].reg_type & ARM_SP || op->operands[1].reg_type & ARM_SP) { // alias of add
238  k |= 0x0011;
239  data = k | encode2regs(op);
240  return data;
241  }
242  k |= 0xe003002a; // alias of orr
243  data = k | op->operands[1].reg << 8;
244  return data;
245  }
246  check_cond(op->operands[1].type & ARM_CONSTANT);
247  ut64 imm = op->operands[1].immediate;
248  ut64 imm_inverse = ~imm;
249  if (bits == 32) {
250  check_cond(imm <= 0xffffffff || imm_inverse <= 0xffffffff);
251  imm &= 0xffffffff;
252  imm_inverse &= 0xffffffff;
253  }
254  int shift;
255  ut64 mask = 0xffff;
256  for (shift = 0; shift < bits; shift += 16, mask <<= 16) {
257  if (imm == (imm & mask)) { // movz
258  data = k | 0x00008052;
259  imm >>= shift;
260  data |= (imm & 7) << 29 | (imm & 0x7f8) << 13 | (imm & 0xf800) >> 3;
261  data |= shift << 9;
262  return data;
263  }
264  }
265  mask = 0xffff;
266  for (shift = 0; shift < bits; shift += 16, mask <<= 16) {
267  if (imm_inverse == (imm_inverse & mask)) { // movn
268  data = k | 0x00008012;
269  imm_inverse >>= shift;
270  data |= (imm_inverse & 7) << 29 | (imm_inverse & 0x7f8) << 13 | (imm_inverse & 0xf800) >> 3;
271  data |= shift << 9;
272  return data;
273  }
274  }
275  ut32 bitmask = encodeBitMasksWithSize(op->operands[1].immediate, bits); // orr
276  check_cond(bitmask != UT32_MAX);
277  data = k | 0xe0030032;
278  data |= (bitmask & 0x3f) << 18 | (bitmask & 0x1fc0) << 2;
279  return data;
280  }
281  if (!strcmp(op->mnemonic, "movz")) {
282  k |= 0x8052;
283  } else if (!strcmp(op->mnemonic, "movk")) {
284  k |= 0x8072;
285  } else if (!strcmp(op->mnemonic, "movn")) {
286  k |= 0x8012;
287  } else {
288  return data;
289  }
290  check_cond(op->operands[1].type == ARM_CONSTANT);
291  ut64 imm = op->operands[1].immediate;
292  check_cond(imm <= 0xffff);
293  int shift = 0;
294  if (op->operands_count >= 3) {
295  check_cond(op->operands_count == 3);
296  check_cond(op->operands[2].type == ARM_SHIFT);
297  check_cond(op->operands[2].shift == ARM_LSL);
298  shift = op->operands[2].shift_amount;
299  check_cond(!(shift & 0xf));
300  check_cond(shift < bits);
301  }
302  data = k;
303  data |= (imm & 7) << 29; // arg(1)
304  data |= (imm & 0x7f8) << 13; // arg(1)
305  data |= (imm & 0xf800) >> 3; // arg(1)
306  data |= shift << 9; // arg(2)
307  return data;
308 }

References ARM_CONSTANT, ARM_GPR, ARM_LSL, ARM_REG64, ARM_SHIFT, ARM_SP, bits(), check_cond, encode1reg(), encode2regs(), encodeBitMasksWithSize(), imm, k, mask, shift(), UT32_MAX, and ut64().

Referenced by arm64ass().

◆ msr()

static ut32 msr ( ArmOp op,
int  w 
)
static

Definition at line 706 of file armass64.c.

706  {
707  ut32 data = UT32_MAX;
708  ut32 seq_data = UT32_MAX;
709  int is_immediate = 0;
710  int i;
711  ut32 r, b;
712  /* handle swapped args */
713  if (w) {
714  if (op->operands[1].reg_type != (ARM_REG64 | ARM_SP)) {
715  if (op->operands[1].type == ARM_CONSTANT) {
716  for (i = 0; msr_const[i].name; i++) {
717  if (op->operands[1].immediate == msr_const[i].val) {
718  op->operands[1].sp_val = msr_const[i].val;
719  op->operands[1].reg = op->operands[1].immediate;
720  break;
721  }
722  }
723  } else {
724  return data;
725  }
726  }
727  r = op->operands[0].reg;
728  b = op->operands[1].sp_val;
729  } else {
730  if (op->operands[0].reg_type != (ARM_REG64 | ARM_SP)) {
731  if (op->operands[0].type == ARM_CONSTANT) {
732  for (i = 0; msr_const[i].name; i++) {
733  if (op->operands[0].immediate == msr_const[i].val) {
734  op->operands[0].sp_val = msr_const[i].val;
735  op->operands[0].reg = op->operands[0].immediate;
736  break;
737  }
738  }
739  } else {
740  return data;
741  }
742  }
743  r = op->operands[1].reg;
744  if (op->operands[1].sp_val == 0xfffe) {
745  is_immediate = 1;
746  r = op->operands[1].immediate;
747  }
748  b = op->operands[0].sp_val;
749  }
750  data = 0x00000000;
751 
752  if (is_immediate) {
753  // only msr has immediate mode
754  data = 0xd500401f;
755  if (b == 0xc210) { // op0 is SPSel
756  b = 0x05; // set to immediate mode encoding
757  }
758 
759  data |= (b & 0xf0) << 12; // op1
760  data |= (b & 0x0f) << 5; // op2
761  data |= (r & 0xf) << 8; // CRm(#imm)
762 
763  } else {
764  if (w) {
765  /* mrs */
766  data |= 0xd5200000;
767  } else {
768  data |= 0xd5000000;
769  }
770  data |= b << 5;
771  data |= r;
772  }
773  seq_data = 0x00000000;
774  seq_data |= (data & 0xff) << 8 * 3;
775  seq_data |= (data & 0xff00) << 8 * 1;
776  seq_data |= (data & 0xff0000) >> 8 * 1;
777  seq_data |= (data & 0xff000000) >> 8 * 3;
778  /*
779 if (op->operands[1].reg_type == ARM_REG64) {
780  data |= op->operands[1].reg << 24;
781  }
782 */
783  return seq_data;
784 }
struct @60 msr_const[]
#define r
Definition: crypto_rc6.c:12
#define w
Definition: crypto_rc6.c:13
static int is_immediate(ut32 instr)
#define b(i)
Definition: sha256.c:42

References ARM_CONSTANT, ARM_REG64, ARM_SP, b, i, is_immediate(), msr_const, r, UT32_MAX, and w.

Referenced by arm64ass().

◆ neg()

static ut32 neg ( ArmOp op)
static

Definition at line 981 of file armass64.c.

981  {
982  if (op->operands_count < 2) {
983  return -1;
984  }
985  op->operands_count++;
986  op->operands[2] = op->operands[1];
987  op->operands[1].reg = 31; // xzr
988 
989  return arithmetic(op, 0xd1); // sub reg0, xzr, reg1
990 }

References arithmetic().

Referenced by arm64ass(), avr_il_neg(), esil_abs_neg(), get_long_object(), rz_il_handler_neg(), rz_il_op_new_neg(), rz_il_op_pure_dup(), rz_il_op_pure_free(), and subvar().

◆ parse_bdot()

static ut32 parse_bdot ( const char *  str,
ArmOp op,
ut64  addr 
)
static

Definition at line 673 of file armass64.c.

673  {
674  if (!str[0] || !str[1] || str[2] != ' ') {
675  inval:
676  RZ_LOG_ERROR("assembler: arm64: invalid condition\n");
677  return UT32_MAX;
678  }
679  ut8 cond = parse_cond(str);
680  if (cond == UT8_MAX) {
681  goto inval;
682  }
683  return bdot(op, addr, 0x00000054 | ((ut32)cond << 24));
684 }
static ut32 bdot(ArmOp *op, ut64 addr, int k)
Definition: armass64.c:610
static ut8 parse_cond(const char *str)
Definition: armass64.c:645
#define UT8_MAX

References addr, bdot(), cond, parse_cond(), RZ_LOG_ERROR, cmd_descs_generate::str, UT32_MAX, and UT8_MAX.

Referenced by arm64ass().

◆ parse_cond()

static ut8 parse_cond ( const char *  str)
static

Determine the 4-bit condition code for given string representation (e.g. "eq", "ne", ...) str string of at least 2 chars

Returns
the 4-bit condition or UT8_MAX if invalid

Definition at line 645 of file armass64.c.

645  {
646  // clang-format off
647  switch (((ut16)str[0] << 8 | (ut16)str[1])) {
648 #define COND_CASE(a, b) case (ut16)(a) << 8 | (ut16)(b)
649  COND_CASE('e', 'q'): return 0x0;
650  COND_CASE('n', 'e'): return 0x1;
651  COND_CASE('c', 's'): return 0x2;
652  COND_CASE('h', 's'): return 0x2;
653  COND_CASE('c', 'c'): return 0x3;
654  COND_CASE('l', 'o'): return 0x3;
655  COND_CASE('m', 'i'): return 0x4;
656  COND_CASE('p', 'l'): return 0x5;
657  COND_CASE('v', 's'): return 0x6;
658  COND_CASE('v', 'c'): return 0x7;
659  COND_CASE('h', 'i'): return 0x8;
660  COND_CASE('l', 's'): return 0x9;
661  COND_CASE('g', 'e'): return 0xa;
662  COND_CASE('l', 't'): return 0xb;
663  COND_CASE('g', 't'): return 0xc;
664  COND_CASE('l', 'e'): return 0xd;
665  COND_CASE('a', 'l'): return 0xe;
666  COND_CASE('n', 'v'): return 0xf;
667  default: return UT8_MAX;
668 #undef COND_CASE
669  }
670  // clang-format on
671 }
#define COND_CASE(a, b)
uint16_t ut16

References COND_CASE, cmd_descs_generate::str, and UT8_MAX.

Referenced by parse_bdot().

◆ parseOpcode()

static bool parseOpcode ( const char *  str,
ArmOp op 
)
static

Definition at line 1293 of file armass64.c.

1293  {
1294  char *in = strdup(str);
1295  char *space = strchr(in, ' ');
1296  if (!space) {
1297  op->operands[0].type = ARM_NOTYPE;
1298  op->mnemonic = in;
1299  return true;
1300  }
1301  space[0] = '\0';
1302  op->mnemonic = in;
1303  space++;
1304  op->writeback = strstr(space, "]!") != NULL;
1305  return parseOperands(space, op);
1306 }
static bool parseOperands(char *str, ArmOp *op)
Definition: armass64.c:1021
const lzma_allocator const uint8_t * in
Definition: block.h:527
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")

References ARM_NOTYPE, in, NULL, parseOperands(), cmd_descs_generate::str, and strdup().

Referenced by arm64ass().

◆ parseOperands()

static bool parseOperands ( char *  str,
ArmOp op 
)
static

Definition at line 1021 of file armass64.c.

1021  {
1022  char *t = strdup(str);
1023  int operand = 0;
1024  char *token = t;
1025  char *x;
1026  int imm_count = 0;
1027  int mem_opt = 0;
1028  int msr_op_index = 0;
1029  size_t index_bound = strcspn(t, "]");
1030  if (!token) {
1031  return false;
1032  }
1033 
1034  while (token) {
1035  char *next = strchr(token, ',');
1036  if (next) {
1037  // Change the ',' in token to null byte
1038  // essentialy split the token by commas
1039  *next++ = '\0';
1040  }
1041  while (token[0] == ' ') {
1042  token++;
1043  }
1044  if (operand >= MAX_OPERANDS) {
1045  RZ_LOG_ERROR("assembler: arm64: maximum number of operands reached.\n");
1046  return false;
1047  }
1048  op->operands[operand].type = ARM_NOTYPE;
1049  op->operands[operand].reg_type = ARM_UNDEFINED;
1050 
1051  // parse MSR (immediate) operand 1
1052  if (strcmp(op->mnemonic, "msr") == 0 && operand == 1) {
1053 
1054  // operand 1 must be a immediate
1055  if (token[0] == '#' || (token[0] >= '0' && token[0] <= '9')) {
1056  // immediate operand found.
1057  op->operands[operand].sp_val = 0xfffe; // not regiter, but a immediate
1058  op->operands[operand].immediate = rz_num_math(NULL, token[0] == '#' ? token + 1 : token);
1059  operand++;
1060  token = next;
1061  continue;
1062  }
1063  }
1064 
1065  // parse system registers
1066  if ((strcmp(op->mnemonic, "mrs") == 0 && operand == 1) || (strcmp(op->mnemonic, "msr") == 0 && operand == 0)) {
1067  for (msr_op_index = 0; msr_const[msr_op_index].name; msr_op_index++) {
1068  if (strcasecmp(token, msr_const[msr_op_index].name) == 0) {
1069  op->operands_count++;
1070  op->operands[operand].type = ARM_CONSTANT;
1071  op->operands[operand].immediate = msr_const[msr_op_index].val;
1072  imm_count++;
1073  break;
1074  }
1075  }
1076  if (msr_const[msr_op_index].name) {
1077  operand++;
1078  token = next;
1079  continue;
1080  }
1081  }
1082 
1083  while (token[0] == ' ' || token[0] == '[' || token[0] == ']') {
1084  token++;
1085  }
1086 
1087  if (!strncmp(token, "lsl", 3)) {
1088  op->operands[operand].type = ARM_SHIFT;
1089  op->operands[operand].shift = ARM_LSL;
1090  } else if (!strncmp(token, "lsr", 3)) {
1091  op->operands[operand].type = ARM_SHIFT;
1092  op->operands[operand].shift = ARM_LSR;
1093  } else if (!strncmp(token, "asr", 3)) {
1094  op->operands[operand].type = ARM_SHIFT;
1095  op->operands[operand].shift = ARM_ASR;
1096  } else if (!strncmp(token, "ror", 3)) {
1097  op->operands[operand].type = ARM_SHIFT;
1098  op->operands[operand].shift = ARM_ROR;
1099  } else if (!strncmp(token, "uxtb", 4)) {
1100  op->operands[operand].type = ARM_EXTEND;
1101  op->operands[operand].shift = ARM_UXTB;
1102  } else if (!strncmp(token, "uxth", 4)) {
1103  op->operands[operand].type = ARM_EXTEND;
1104  op->operands[operand].shift = ARM_UXTH;
1105  } else if (!strncmp(token, "uxtw", 4)) {
1106  op->operands[operand].type = ARM_EXTEND;
1107  op->operands[operand].shift = ARM_UXTW;
1108  } else if (!strncmp(token, "uxtx", 4)) {
1109  op->operands[operand].type = ARM_EXTEND;
1110  op->operands[operand].shift = ARM_UXTX;
1111  } else if (!strncmp(token, "sxtb", 4)) {
1112  op->operands[operand].type = ARM_EXTEND;
1113  op->operands[operand].shift = ARM_SXTB;
1114  } else if (!strncmp(token, "sxth", 4)) {
1115  op->operands[operand].type = ARM_EXTEND;
1116  op->operands[operand].shift = ARM_SXTH;
1117  } else if (!strncmp(token, "sxtw", 4)) {
1118  op->operands[operand].type = ARM_EXTEND;
1119  op->operands[operand].shift = ARM_SXTW;
1120  } else if (!strncmp(token, "sxtx", 4)) {
1121  op->operands[operand].type = ARM_EXTEND;
1122  op->operands[operand].shift = ARM_SXTX;
1123  }
1124  if (op->operands[operand].type == ARM_SHIFT) {
1125  op->operands_count++;
1126  token += 3;
1127  while (*token && *token == ' ') {
1128  token++;
1129  }
1130  if (*token == '#') {
1131  token++;
1132  }
1133  if (!*token || !isdigit(*token)) {
1134  return false;
1135  }
1136  op->operands[operand].shift_amount = rz_num_math(NULL, token);
1137  op->operands[operand].amount_present = true;
1138  if (op->operands[operand].shift_amount > 63) {
1139  free(t);
1140  return false;
1141  }
1142  operand++;
1143  token = next;
1144  continue;
1145  }
1146  if (op->operands[operand].type == ARM_EXTEND) {
1147  op->operands_count++;
1148  token += 4;
1149  while (*token && *token == ' ') {
1150  token++;
1151  }
1152  bool present = false;
1153  if (*token == '#') {
1154  present = true;
1155  ++token;
1156  }
1157  if (!*token || !isdigit(*token)) {
1158  if (present) {
1159  return false;
1160  }
1161  op->operands[operand].shift_amount = 0;
1162  op->operands[operand].amount_present = false;
1163  } else {
1164  op->operands[operand].shift_amount = rz_num_math(NULL, token);
1165  op->operands[operand].amount_present = true;
1166  }
1167  operand++;
1168  token = next;
1169  continue;
1170  }
1171 
1172  switch (token[0]) {
1173  case 'x':
1174  x = strchr(token, ',');
1175  if (x) {
1176  x[0] = '\0';
1177  }
1178  op->operands_count++;
1179  op->operands[operand].type = ARM_GPR;
1180  op->operands[operand].reg_type = ARM_REG64;
1181 
1182  if (!strncmp(token + 1, "zr", 2)) {
1183  // XZR
1184  op->operands[operand].reg = 31;
1185  } else {
1186  op->operands[operand].reg = rz_num_math(NULL, token + 1);
1187  }
1188 
1189  if (op->operands[operand].reg > 31) {
1190  free(t);
1191  return false;
1192  }
1193  break;
1194  case 'w':
1195  op->operands_count++;
1196  op->operands[operand].type = ARM_GPR;
1197  op->operands[operand].reg_type = ARM_REG32;
1198 
1199  if (!strncmp(token + 1, "zr", 2)) {
1200  // WZR
1201  op->operands[operand].reg = 31;
1202  } else if (!strncmp(token + 1, "sp", 2)) {
1203  // WSP
1204  op->operands[operand].reg = 31;
1205  op->operands[operand].reg_type |= ARM_SP;
1206  } else {
1207  op->operands[operand].reg = rz_num_math(NULL, token + 1);
1208  }
1209 
1210  if (op->operands[operand].reg > 31) {
1211  free(t);
1212  return false;
1213  }
1214  break;
1215  case 'v':
1216  op->operands_count++;
1217  op->operands[operand].type = ARM_FP;
1218  op->operands[operand].reg = rz_num_math(NULL, token + 1);
1219  break;
1220  case 's':
1221  case 'S':
1222  if (token[1] == 'P' || token[1] == 'p') {
1223  int i;
1224  for (i = 0; msr_const[i].name; i++) {
1225  if (!rz_str_ncasecmp(token, msr_const[i].name, strlen(msr_const[i].name))) {
1226  op->operands[operand].sp_val = msr_const[i].val;
1227  break;
1228  }
1229  }
1230  op->operands_count++;
1231  op->operands[operand].type = ARM_GPR;
1232  op->operands[operand].reg_type = ARM_SP | ARM_REG64;
1233  op->operands[operand].reg = 31;
1234  break;
1235  }
1236  mem_opt = get_mem_option(token);
1237  if (mem_opt != -1) {
1238  op->operands_count++;
1239  op->operands[operand].type = ARM_MEM_OPT;
1240  op->operands[operand].mem_option = mem_opt;
1241  }
1242  break;
1243  case 'L':
1244  case 'l':
1245  case 'I':
1246  case 'i':
1247  case 'N':
1248  case 'n':
1249  case 'O':
1250  case 'o':
1251  case 'p':
1252  case 'P':
1253  mem_opt = get_mem_option(token);
1254  if (mem_opt != -1) {
1255  op->operands_count++;
1256  op->operands[operand].type = ARM_MEM_OPT;
1257  op->operands[operand].mem_option = mem_opt;
1258  }
1259  break;
1260  case '#':
1261  if (token[1] == '-') {
1262  op->operands[operand].sign = -1;
1263  }
1264  op->operands_count++;
1265  op->operands[operand].type = ARM_CONSTANT;
1266  op->operands[operand].immediate = rz_num_math(NULL, token + 1);
1267  op->operands[operand].preindex = token - t < index_bound;
1268  imm_count++;
1269  break;
1270  case '-':
1271  op->operands[operand].sign = -1;
1272  // fallthrough
1273  default:
1274  op->operands_count++;
1275  op->operands[operand].type = ARM_CONSTANT;
1276  op->operands[operand].immediate = rz_num_math(NULL, token);
1277  op->operands[operand].preindex = token - t < index_bound;
1278  imm_count++;
1279  break;
1280  }
1281  token = next;
1282 
1283  operand++;
1284  if (operand > MAX_OPERANDS) {
1285  free(t);
1286  return false;
1287  }
1288  }
1289  free(t);
1290  return true;
1291 }
operand
Definition: arc-opc.c:39
#define MAX_OPERANDS
Definition: armass64.c:75
static int get_mem_option(char *token)
Definition: armass64.c:92
RZ_API ut64 rz_num_math(RzNum *num, const char *str)
Definition: unum.c:456
RZ_API int rz_str_ncasecmp(const char *dst, const char *orig, size_t n)
Definition: str.c:129
#define isdigit(c)
Definition: safe-ctype.h:131
Definition: z80asm.h:102

References ARM_ASR, ARM_CONSTANT, ARM_EXTEND, ARM_FP, ARM_GPR, ARM_LSL, ARM_LSR, ARM_MEM_OPT, ARM_NOTYPE, ARM_REG32, ARM_REG64, ARM_ROR, ARM_SHIFT, ARM_SP, ARM_SXTB, ARM_SXTH, ARM_SXTW, ARM_SXTX, ARM_UNDEFINED, ARM_UXTB, ARM_UXTH, ARM_UXTW, ARM_UXTX, free(), get_mem_option(), i, isdigit, MAX_OPERANDS, msr_const, NULL, RZ_LOG_ERROR, rz_num_math(), rz_str_ncasecmp(), cmd_descs_generate::str, strdup(), and x.

Referenced by parseOpcode().

◆ reglsop()

static ut32 reglsop ( ArmOp op,
int  k 
)
static

Definition at line 405 of file armass64.c.

405  {
406  ut32 data = UT32_MAX;
407 
408  if (op->operands[1].reg_type & ARM_REG32) {
409  return data;
410  }
411  if (op->operands[0].reg_type & ARM_REG32) {
412  k -= 0x40;
413  }
414  if (op->operands[2].type & ARM_GPR) {
415  k += 0x00682000;
416  data = k | encode2regs(op);
417  data |= op->operands[2].reg << 8;
418  } else {
419  int n = op->operands[2].immediate;
420  if (n > 0x100 || n < -0x100) {
421  return UT32_MAX;
422  }
423 
424  if (n == 0 || (n > 0 && countTrailingZeros(n) >= 4)) {
425  k++;
426  }
427  data = k | encode2regs(op);
428 
429  if (n < 0) {
430  n *= -1;
431  data |= (0xf & (0xf - (n - 1))) << 20;
432  if (countTrailingZeros(n) > 3) {
433  data |= (0x1f - ((n >> 4) - 1)) << 8;
434  } else {
435  data |= (0x1f - (n >> 4)) << 8;
436  }
437  } else {
438  if (op->operands[0].reg_type & ARM_REG32) {
439  if (countTrailingZeros(n) < 2) {
440  data |= (0xf & (n & 63)) << 20;
441  data |= (n >> 4) << 8;
442  } else {
443  data++;
444  data |= (0xff & n) << 16;
445  }
446  data |= (n >> 8) << 8;
447  } else {
448  data |= (0xf & (n & 63)) << 20;
449  if (countTrailingZeros(n) < 4) {
450  data |= (n >> 4) << 8;
451  } else {
452  data |= (0xff & n) << 15;
453  }
454  data |= (n >> 8) << 23;
455  }
456  }
457  }
458  return data;
459 }

References ARM_GPR, ARM_REG32, countTrailingZeros(), encode2regs(), k, n, and UT32_MAX.

Referenced by arm64ass().

◆ regsluop()

static ut32 regsluop ( ArmOp op,
int  k 
)
static

Definition at line 362 of file armass64.c.

362  {
363  ut32 data = UT32_MAX;
364 
365  if (op->operands[1].reg_type & ARM_REG32) {
366  return data;
367  }
368  if (op->operands[0].reg_type & ARM_REG32) {
369  k -= 0x40;
370  }
371  if (op->operands[2].type & ARM_GPR) {
372  return data;
373  }
374 
375  int n = op->operands[2].immediate;
376  if (n > 0xff || n < -0x100) {
377  return data;
378  }
379 
380  data = k | encode2regs(op);
381 
382  if (n < 0) {
383  n *= -1;
384  data |= (0xf & (0xf - (n - 1))) << 20;
385 
386  if (countTrailingZeros(n) > 3) {
387  data |= (0x1f - ((n >> 4) - 1)) << 8;
388  } else {
389  data |= (0x1f - (n >> 4)) << 8;
390  }
391  } else {
392  data |= (0xf & (n & 63)) << 20;
393  if (countTrailingZeros(n) < 4) {
394  data |= (n >> 4) << 8;
395  } else {
396  data |= (0xff & n) << 4;
397  }
398  data |= (n >> 8) << 8;
399  }
400 
401  return data;
402 }

References ARM_GPR, ARM_REG32, countTrailingZeros(), encode2regs(), k, n, and UT32_MAX.

Referenced by arm64ass().

◆ stp()

static ut32 stp ( ArmOp op,
int  k 
)
static

Definition at line 904 of file armass64.c.

904  {
905  ut32 data = UT32_MAX;
906 
907  if (op->operands[3].immediate & 0x7) {
908  return data;
909  }
910  if (k == 0x000040a9 && (op->operands[0].reg == op->operands[1].reg)) {
911  return data;
912  }
913 
914  data = k;
915  data |= encode2regs(op);
916  data += (op->operands[3].immediate & 0x8) << 20;
917  data += (op->operands[3].immediate >> 4) << 8;
918  return data;
919 }

References encode2regs(), k, and UT32_MAX.

Referenced by arm64ass(), and dissect().