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

Go to the source code of this file.

Classes

struct  ArmOpcode
 
struct  ArmOp
 

Typedefs

typedef int(* AssembleFunction) (ArmOpcode *, ut64, const char *)
 

Enumerations

enum  {
  TYPE_MOV = 1 , TYPE_TST = 2 , TYPE_SWI = 3 , TYPE_HLT = 4 ,
  TYPE_BRA = 5 , TYPE_BRR = 6 , TYPE_ARI = 7 , TYPE_IMM = 8 ,
  TYPE_MEM = 9 , TYPE_BKP = 10 , TYPE_SWP = 11 , TYPE_MOVW = 12 ,
  TYPE_MOVT = 13 , TYPE_UDF = 14 , TYPE_SHFT = 15 , TYPE_COPROC = 16 ,
  TYPE_ENDIAN = 17 , TYPE_MUL = 18 , TYPE_CLZ = 19 , TYPE_REV = 20 ,
  TYPE_NEG = 21 , TYPE_BFC = 22 , TYPE_BFI = 23
}
 

Functions

static int strcmpnull (const char *a, const char *b)
 
static char * parse_hints (char *input)
 
static st8 iflag (char *input)
 
static ut64 cqcheck (char **input)
 
static ut64 opmask (char *input, char *opcode, ut64 allowed_mask)
 
static ut32 itmask (char *input)
 
static ut64 getnum (const char *str)
 
static ut64 getnumbang (const char *str)
 
static ut32 getimmed8 (const char *str)
 
static st32 firstsigdigit (ut32 num)
 
static ut32 getthbimmed (st32 number)
 
static ut32 getthzeroimmed12 (ut32 number)
 
static ut32 getthzeroimmed16 (ut32 number)
 
static ut32 getthimmed12 (const char *str)
 
static char * getrange (char *s)
 
static int getreg (const char *str)
 
static st32 getlistmask (char *input)
 
static st32 getregmemstart (const char *input)
 
static st32 getregmemstartend (const char *input)
 
static st32 getregmemend (const char *input)
 
static st32 getreglist (const char *input)
 
static st32 getnummemend (const char *input)
 
static st32 getnummemendbang (const char *input)
 
static st32 getregmembang (const char *input)
 
static int getcoproc (const char *str)
 
static int getcoprocreg (const char *str)
 
static ut8 interpret_msrbank (char *str, ut8 *spsr)
 
static ut32 thumb_getshift (const char *str)
 
static st32 getshiftmemend (const char *input)
 
static ut64 thumb_selector (char *args[])
 
static ut32 getshift (const char *str)
 
static void arm_opcode_parse (ArmOpcode *ao, const char *str)
 
static int arm_opcode_cond (ArmOpcode *ao, int delta)
 
static st32 thumb_getoffset (char *label, ut64 cur)
 
static st8 std_16bit_2reg (ArmOpcode *ao, ut64 m)
 
static st8 mem_16bit_2reg (ArmOpcode *ao, ut64 m)
 
static st8 std_32bit_2reg (ArmOpcode *ao, ut64 m, bool shift)
 
static st8 mem_32bit_2reg (ArmOpcode *ao, ut64 m)
 
static st8 std_32bit_3reg (ArmOpcode *ao, ut64 m, bool shift)
 
static void std_opt_2 (ArmOpcode *ao)
 
static void std_opt_3 (ArmOpcode *ao)
 
static int thumb_assemble (ArmOpcode *ao, ut64 off, const char *str)
 
static int findyz (int x, int *y, int *z)
 
static int arm_assemble (ArmOpcode *ao, ut64 off, const char *str)
 
ut32 armass_assemble (const char *str, ut64 off, int thumb)
 

Variables

static ArmOp ops []
 
static const ut64 M_BIT = 0x1
 
static const ut64 S_BIT = 0x2
 
static const ut64 C_BITS = 0x3c
 
static const ut64 DOTN_BIT = 0x40
 
static const ut64 DOTW_BIT = 0x80
 
static const ut64 L_BIT = 0x100
 
static const ut64 X_BIT = 0x200
 
static const ut64 TWO_BIT = 0x400
 
static const ut64 IE_BIT = 0x800
 
static const ut64 ID_BIT = 0x1000
 
static const ut64 EA_BIT = 0x2000
 
static const ut64 FD_BIT = 0x4000
 
static const ut64 T_BIT = 0x8000
 
static const ut64 B_BIT = 0x10000
 
static const ut64 H_BIT = 0x20000
 
static const ut64 D_BIT = 0x40000
 
static const ut64 W_BIT = 0x80000
 
static const ut64 EIGHT_BIT = 0x100000
 
static const ut64 SIXTEEN_BIT = 0x200000
 
static const ut64 BB_BIT = 0x400000
 
static const ut64 BT_BIT = 0x800000
 
static const ut64 TB_BIT = 0x1000000
 
static const ut64 TT_BIT = 0x2000000
 
static const ut64 RZ_BIT = 0x4000000
 
static const ut64 IA_BIT = 0x8000000
 
static const ut64 DB_BIT = 0x10000000
 
static const ut64 SH_BIT = 0x20000000
 
static const ut64 WB_BIT = 0x40000000
 
static const ut64 WT_BIT = 0x80000000
 
static const ut64 C_MATCH_BIT = 0x100000000
 
static bool err
 
static AssembleFunction assemble [2] = { &arm_assemble, &thumb_assemble }
 

Typedef Documentation

◆ AssembleFunction

typedef int(* AssembleFunction) (ArmOpcode *, ut64, const char *)

Definition at line 6206 of file armass.c.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
TYPE_MOV 
TYPE_TST 
TYPE_SWI 
TYPE_HLT 
TYPE_BRA 
TYPE_BRR 
TYPE_ARI 
TYPE_IMM 
TYPE_MEM 
TYPE_BKP 
TYPE_SWP 
TYPE_MOVW 
TYPE_MOVT 
TYPE_UDF 
TYPE_SHFT 
TYPE_COPROC 
TYPE_ENDIAN 
TYPE_MUL 
TYPE_CLZ 
TYPE_REV 
TYPE_NEG 
TYPE_BFC 
TYPE_BFI 

Definition at line 27 of file armass.c.

27  {
28  TYPE_MOV = 1,
29  TYPE_TST = 2,
30  TYPE_SWI = 3,
31  TYPE_HLT = 4,
32  TYPE_BRA = 5,
33  TYPE_BRR = 6,
34  TYPE_ARI = 7,
35  TYPE_IMM = 8,
36  TYPE_MEM = 9,
37  TYPE_BKP = 10,
38  TYPE_SWP = 11,
39  TYPE_MOVW = 12,
40  TYPE_MOVT = 13,
41  TYPE_UDF = 14,
42  TYPE_SHFT = 15,
43  TYPE_COPROC = 16,
44  TYPE_ENDIAN = 17,
45  TYPE_MUL = 18,
46  TYPE_CLZ = 19,
47  TYPE_REV = 20,
48  TYPE_NEG = 21,
49  TYPE_BFC = 22,
50  TYPE_BFI = 23
51 };
@ TYPE_BFC
Definition: armass.c:49
@ TYPE_IMM
Definition: armass.c:35
@ TYPE_BRR
Definition: armass.c:33
@ TYPE_SWI
Definition: armass.c:30
@ TYPE_REV
Definition: armass.c:47
@ TYPE_SHFT
Definition: armass.c:42
@ TYPE_MOVT
Definition: armass.c:40
@ TYPE_BFI
Definition: armass.c:50
@ TYPE_BKP
Definition: armass.c:37
@ TYPE_MUL
Definition: armass.c:45
@ TYPE_HLT
Definition: armass.c:31
@ TYPE_TST
Definition: armass.c:29
@ TYPE_CLZ
Definition: armass.c:46
@ TYPE_COPROC
Definition: armass.c:43
@ TYPE_BRA
Definition: armass.c:32
@ TYPE_SWP
Definition: armass.c:38
@ TYPE_MOV
Definition: armass.c:28
@ TYPE_MOVW
Definition: armass.c:39
@ TYPE_MEM
Definition: armass.c:36
@ TYPE_NEG
Definition: armass.c:48
@ TYPE_UDF
Definition: armass.c:41
@ TYPE_ARI
Definition: armass.c:34
@ TYPE_ENDIAN
Definition: armass.c:44

Function Documentation

◆ arm_assemble()

static int arm_assemble ( ArmOpcode ao,
ut64  off,
const char *  str 
)
static

Definition at line 5684 of file armass.c.

5684  {
5685  int i, j, ret, reg, a, b;
5686  int coproc, opc;
5687  bool rex = false;
5688  int shift, low, high;
5689  for (i = 0; ops[i].name; i++) {
5690  if (!strncmp(ao->op, ops[i].name, strlen(ops[i].name))) {
5691  ao->o = ops[i].code;
5692  arm_opcode_cond(ao, strlen(ops[i].name));
5693  int type = ops[i].type;
5694  if (ao->a[0] || type == TYPE_BKP) {
5695  switch (type) {
5696  case TYPE_MEM:
5697  if (!strncmp(ops[i].name, "strex", 5)) {
5698  rex = 1;
5699  }
5700  if (!strcmp(ops[i].name, "str") || !strcmp(ops[i].name, "ldr")) {
5701  if (!ao->a[2]) {
5702  ao->a[2] = "0";
5703  }
5704  }
5705  getrange(ao->a[0]);
5706  getrange(ao->a[1]);
5707  getrange(ao->a[2]);
5708  if (ao->a[0] && ao->a[1]) {
5709  char rn[8];
5710  strncpy(rn, ao->a[1], 7);
5711  int r0 = getreg(ao->a[0]);
5712  int r1 = getreg(ao->a[1]);
5713  if ((r0 < 0 || r0 > 15) || (r1 > 15 || r1 < 0)) {
5714  return 0;
5715  }
5716  ao->o |= r0 << 20;
5717  if (!strcmp(ops[i].name, "strd")) {
5718  r1 = getreg(ao->a[2]);
5719  if (r1 == -1) {
5720  break;
5721  }
5722  ao->o |= r1 << 8;
5723  if (ao->a[3]) {
5724  char *bracket = strchr(ao->a[3], ']');
5725  if (bracket) {
5726  *bracket = '\0';
5727  }
5728  int num = getnum(ao->a[3]);
5729  ao->o |= (num & 0x0f) << 24;
5730  ao->o |= ((num >> 4) & 0x0f) << 16;
5731  }
5732  break;
5733  }
5734  if (!strcmp(ops[i].name, "strh")) {
5735  ao->o |= r1 << 8;
5736  if (ao->a[2]) {
5737  reg = getreg(ao->a[2]);
5738  if (reg != -1) {
5739  ao->o |= reg << 24;
5740  } else {
5741  ao->o |= 1 << 14;
5742  ao->o |= getnum(ao->a[2]) << 24;
5743  }
5744  } else {
5745  ao->o |= 1 << 14;
5746  }
5747  break;
5748  }
5749  if (rex) {
5750  ao->o |= r1 << 24;
5751  } else {
5752  ao->o |= r1 << 8; // delta
5753  }
5754  } else {
5755  return 0;
5756  }
5757 
5758  ret = getreg(ao->a[2]);
5759  if (ret != -1) {
5760  if (rex) {
5761  ao->o |= 1;
5762  ao->o |= (ret & 0x0f) << 8;
5763  } else {
5764  ao->o |= (strstr(str, "],")) ? 6 : 7;
5765  ao->o |= (ret & 0x0f) << 24;
5766  }
5767  if (ao->a[3]) {
5768  shift = getshift(ao->a[3]);
5769  low = shift & 0xFF;
5770  high = shift & 0xFF00;
5771  ao->o |= low << 24;
5772  ao->o |= high << 8;
5773  }
5774  } else {
5775  int num = getnum(ao->a[2]) & 0xfff;
5776  if (err) {
5777  break;
5778  }
5779  if (rex) {
5780  ao->o |= 1;
5781  } else {
5782  ao->o |= (strstr(str, "],")) ? 4 : 5;
5783  }
5784  ao->o |= 1;
5785  ao->o |= (num & 0xff) << 24;
5786  ao->o |= ((num >> 8) & 0xf) << 16;
5787  }
5788 
5789  break;
5790  case TYPE_IMM:
5791  if (*ao->a[0] == '{') {
5792  st32 reg = getreglist(ao->a[0]);
5793  for (j = 0; j < 16; j++) {
5794  if (reg & (1 << j)) {
5795  if (j < 8) {
5796  ao->o |= 1 << (24 + j);
5797  } else {
5798  ao->o |= 1 << (8 + j);
5799  }
5800  }
5801  }
5802  } else {
5803  ao->o |= getnum(ao->a[0]) << 24; // ???
5804  }
5805  break;
5806  case TYPE_BRA:
5807  if (getreg(ao->a[0]) == -1) {
5808  // TODO: control if branch out of range
5809  ret = (getnum(ao->a[0]) - (int)ao->off - 8) / 4;
5810  if (ret >= 0x00800000 || ret < (int)0xff800000) {
5811  RZ_LOG_ERROR("assembler: arm: %s: invalid branch address (out of range).\n", ops[i].name);
5812  return 0;
5813  }
5814  ao->o |= ((ret >> 16) & 0xff) << 8;
5815  ao->o |= ((ret >> 8) & 0xff) << 16;
5816  ao->o |= ((ret)&0xff) << 24;
5817  } else {
5818  RZ_LOG_ERROR("assembler: arm: %s: instruction does not accept a register as argument\n", ops[i].name);
5819  return 0;
5820  }
5821  break;
5822  case TYPE_BKP:
5823  ao->o |= 0x70 << 24;
5824  if (ao->a[0]) {
5825  int n = getnum(ao->a[0]);
5826  ao->o |= ((n & 0xf) << 24);
5827  ao->o |= (((n >> 4) & 0xff) << 16);
5828  }
5829  break;
5830  case TYPE_BRR:
5831  if (getreg(ao->a[0]) == -1) {
5832  ut32 dst = getnum(ao->a[0]);
5833  dst -= (ao->off + 8);
5834  if (dst & 0x2) {
5835  ao->o = 0xfb;
5836  } else {
5837  ao->o = 0xfa;
5838  }
5839  dst /= 4;
5840  ao->o |= ((dst >> 16) & 0xff) << 8;
5841  ao->o |= ((dst >> 8) & 0xff) << 16;
5842  ao->o |= ((dst)&0xff) << 24;
5843  return 4;
5844  } else {
5845  ao->o |= (getreg(ao->a[0]) << 24);
5846  }
5847  break;
5848  case TYPE_HLT: {
5849  ut32 o = 0, n = getnum(ao->a[0]);
5850  o |= ((n >> 12) & 0xf) << 8;
5851  o |= ((n >> 8) & 0xf) << 20;
5852  o |= ((n >> 4) & 0xf) << 16;
5853  o |= ((n)&0xf) << 24;
5854  ao->o |= o;
5855  } break;
5856  case TYPE_SWI:
5857  ao->o |= (getnum(ao->a[0]) & 0xff) << 24;
5858  ao->o |= ((getnum(ao->a[0]) >> 8) & 0xff) << 16;
5859  ao->o |= ((getnum(ao->a[0]) >> 16) & 0xff) << 8;
5860  break;
5861  case TYPE_UDF: {
5862  // e7f000f0 = udf 0
5863  // e7ffffff = udf 0xffff
5864  ut32 n = getnum(ao->a[0]);
5865  ao->o |= 0xe7;
5866  ao->o |= (n & 0xf) << 24;
5867  ao->o |= ((n >> 4) & 0xff) << 16;
5868  ao->o |= ((n >> 12) & 0xf) << 8;
5869  } break;
5870  case TYPE_ARI:
5871  if (!ao->a[2]) {
5872  ao->a[2] = ao->a[1];
5873  ao->a[1] = ao->a[0];
5874  }
5875  reg = getreg(ao->a[0]);
5876  if (reg == -1) {
5877  return 0;
5878  }
5879  ao->o |= reg << 20;
5880 
5881  reg = getreg(ao->a[1]);
5882  if (reg == -1) {
5883  return 0;
5884  }
5885  ao->o |= reg << 8;
5886  reg = getreg(ao->a[2]);
5887  if (reg == -1) {
5888  int imm = getnum(ao->a[2]);
5889  if (imm && !(imm & (imm - 1)) && imm > 255) {
5890  int r;
5891  for (r = 0; r != 32; r += 2) {
5892  if (!(imm & ~0xff)) {
5893  ao->o |= (r << 15) | (imm << 24) | 2;
5894  break;
5895  }
5896  imm = (imm << 2) | (imm >> 30);
5897  }
5898  } else {
5899  ao->o |= (imm << 24) | 2;
5900  }
5901  } else {
5902  ao->o |= reg << 24;
5903  }
5904  if (ao->a[3]) {
5905  ao->o |= getshift(ao->a[3]);
5906  }
5907  break;
5908  case TYPE_SWP: {
5909  int a1 = getreg(ao->a[1]);
5910  if (a1) {
5911  ao->o = 0xe1;
5912  ao->o |= (getreg(ao->a[0]) << 4) << 16;
5913  ao->o |= (0x90 + a1) << 24;
5914  if (ao->a[2]) {
5915  ao->o |= (getreg(ao->a[2] + 1)) << 8;
5916  } else {
5917  return 0;
5918  }
5919  }
5920  if (0xff == ((ao->o >> 16) & 0xff)) {
5921  return 0;
5922  }
5923  } break;
5924  case TYPE_MOV:
5925  if (!strcmpnull(ao->op, "movs")) {
5926  ao->o = 0xb0e1;
5927  }
5928  ao->o |= getreg(ao->a[0]) << 20;
5929  ret = getreg(ao->a[1]);
5930  if (ret != -1) {
5931  ao->o |= ret << 24;
5932  } else {
5933  int immed = getimmed8(ao->a[1]);
5934  if (err) {
5935  return 0;
5936  }
5937  ao->o |= 0xa003 | (immed & 0xff) << 24 | (immed >> 8) << 16;
5938  }
5939  break;
5940  case TYPE_MOVW:
5941  reg = getreg(ao->a[0]);
5942  if (reg == -1) {
5943  return 0;
5944  }
5945  ao->o |= getreg(ao->a[0]) << 20;
5946  ret = getnum(ao->a[1]);
5947 
5948  ao->o |= 0x3 | ret << 24;
5949  ao->o |= (ret & 0xf000) >> 4;
5950  ao->o |= (ret & 0xf00) << 8;
5951  break;
5952  case TYPE_MOVT:
5953  ao->o |= getreg(ao->a[0]) << 20;
5954  ret = getnum(ao->a[1]);
5955 
5956  ao->o |= 0x4003 | ret << 24;
5957  ao->o |= (ret & 0xf000) >> 4;
5958  ao->o |= (ret & 0xf00) << 8;
5959  break;
5960  case TYPE_MUL:
5961  if (!strcmpnull(ao->op, "mul")) {
5962  ret = getreg(ao->a[0]);
5963  a = getreg(ao->a[1]);
5964  b = getreg(ao->a[2]);
5965  if (b == -1) {
5966  b = a;
5967  a = ret;
5968  }
5969  if (ret == -1 || a == -1) {
5970  return 0;
5971  }
5972  ao->o |= ret << 8;
5973  ao->o |= a << 24;
5974  ao->o |= b << 16;
5975  } else {
5976  low = getreg(ao->a[0]);
5977  high = getreg(ao->a[1]);
5978  a = getreg(ao->a[2]);
5979  b = getreg(ao->a[3]);
5980  if (low == -1 || high == -1 || a == -1 || b == -1) {
5981  return 0;
5982  }
5983  if (!strcmpnull(ao->op, "smlal")) {
5984  ao->o |= low << 20;
5985  ao->o |= high << 8;
5986  ao->o |= a << 24;
5987  ao->o |= b << 16;
5988  } else if (!strncmp(ao->op, "smla", 4)) {
5989  if (low > 14 || high > 14 || a > 14) {
5990  return 0;
5991  }
5992  ao->o |= low << 8;
5993  ao->o |= high << 24;
5994  ao->o |= a << 16;
5995  ao->o |= b << 20;
5996  break;
5997  } else {
5998  ao->o |= low << 20;
5999  ao->o |= high << 8;
6000  ao->o |= a << 24;
6001  ao->o |= b << 16;
6002  }
6003  }
6004  break;
6005  case TYPE_TST:
6006  a = getreg(ao->a[0]);
6007  b = getreg(ao->a[1]);
6008  if (b == -1) {
6009  int y, z;
6010  b = getnum(ao->a[1]);
6011  if (b >= 0 && b <= 0xff) {
6012  ao->o = 0x50e3;
6013  // TODO: if (b>255) -> automatic multiplier
6014  ao->o |= (a << 8);
6015  ao->o |= ((b & 0xff) << 24);
6016  } else if (findyz(b, &y, &z)) {
6017  ao->o = 0x50e3;
6018  ao->o |= (y << 24);
6019  ao->o |= (z << 16);
6020  } else {
6021  RZ_LOG_ERROR("assembler: arm: %s: parameter %d is out of range (0-255)\n", ops[i].name, b);
6022  return 0;
6023  }
6024  } else {
6025  ao->o |= (a << 8);
6026  ao->o |= (b << 24);
6027  if (ao->a[2]) {
6028  ao->o |= getshift(ao->a[2]);
6029  }
6030  }
6031  if (ao->a[2]) {
6032  int n = getnum(ao->a[2]);
6033  if (n & 1) {
6034  RZ_LOG_ERROR("assembler: arm: %s: multiplier argument is not pair\n", ops[i].name);
6035  return 0;
6036  }
6037  ao->o |= (n >> 1) << 16;
6038  }
6039  break;
6040  case TYPE_SHFT:
6041  reg = getreg(ao->a[2]);
6042  if (reg == -1 || reg > 14) {
6043  return 0;
6044  }
6045  ao->o |= reg << 16;
6046 
6047  reg = getreg(ao->a[0]);
6048  if (reg == -1 || reg > 14) {
6049  return 0;
6050  }
6051  ao->o |= reg << 20;
6052 
6053  reg = getreg(ao->a[1]);
6054  if (reg == -1 || reg > 14) {
6055  return 0;
6056  }
6057  ao->o |= reg << 24;
6058  break;
6059  case TYPE_REV:
6060  reg = getreg(ao->a[0]);
6061  if (reg == -1 || reg > 14) {
6062  return 0;
6063  }
6064  ao->o |= reg << 20;
6065 
6066  reg = getreg(ao->a[1]);
6067  if (reg == -1 || reg > 14) {
6068  return 0;
6069  }
6070  ao->o |= reg << 24;
6071 
6072  break;
6073  case TYPE_ENDIAN:
6074  if (!strcmp(ao->a[0], "le")) {
6075  ao->o |= 0;
6076  } else if (!strcmp(ao->a[0], "be")) {
6077  ao->o |= 0x20000;
6078  } else {
6079  return 0;
6080  }
6081  break;
6082  case TYPE_COPROC:
6083  // printf ("%s %s %s %s %s\n", ao->a[0], ao->a[1], ao->a[2], ao->a[3], ao->a[4] );
6084  if (ao->a[0]) {
6085  coproc = getnum(ao->a[0] + 1);
6086  if (coproc == -1 || coproc > 9) {
6087  return 0;
6088  }
6089  ao->o |= coproc << 16;
6090  }
6091 
6092  opc = getnum(ao->a[1]);
6093  if (opc == -1 || opc > 7) {
6094  return 0;
6095  }
6096  ao->o |= opc << 13;
6097 
6098  reg = getreg(ao->a[2]);
6099  if (reg == -1 || reg > 14) {
6100  return 0;
6101  }
6102  ao->o |= reg << 20;
6103 
6104  // coproc register 1
6105  const char *a3 = ao->a[3];
6106  if (a3) {
6107  coproc = getnum(a3 + 1);
6108  if (coproc == -1 || coproc > 15) {
6109  return 0;
6110  }
6111  ao->o |= coproc << 8;
6112  }
6113 
6114  const char *a4 = ao->a[4];
6115  if (a4) {
6116  coproc = getnum(ao->a[4] + 1);
6117  if (coproc == -1 || coproc > 15) {
6118  return 0;
6119  }
6120  ao->o |= coproc << 24;
6121  }
6122 
6123  coproc = getnum(ao->a[5]);
6124  if (coproc > -1) {
6125  if (coproc > 7) {
6126  return 0;
6127  }
6128  // optional opcode
6129  ao->o |= coproc << 29;
6130  }
6131 
6132  break;
6133  case TYPE_CLZ:
6134  ao->o |= 1 << 28;
6135 
6136  reg = getreg(ao->a[0]);
6137  if (reg == -1 || reg > 14) {
6138  return 0;
6139  }
6140  ao->o |= reg << 20;
6141 
6142  reg = getreg(ao->a[1]);
6143  if (reg == -1 || reg > 14) {
6144  return 0;
6145  }
6146  ao->o |= reg << 24;
6147 
6148  break;
6149  case TYPE_NEG:
6150  if (!ao->a[0] || !ao->a[1]) {
6151  return 0;
6152  }
6153  ao->a[2] = "0";
6154  int len = strlen(ao->a[1]) + 1;
6155  memmove(ao->a[0] + 1, ao->a[0], ao->a[1] - ao->a[0] + len);
6156  ao->a[0]++;
6157  ao->a[1]++;
6158  strncpy(ao->op, "rsbs", 5);
6159  arm_assemble(ao, off, str); // rsbs reg0, reg1, #0
6160  break;
6161  case TYPE_BFC:
6162  case TYPE_BFI: {
6163  size_t argoff = 0;
6164  if (type == TYPE_BFI) {
6165  ut32 rn = getreg(ao->a[1]);
6166  if (rn >= 0xf) {
6167  return 0;
6168  }
6169  ao->o |= rn << 24;
6170  argoff = 1;
6171  }
6172  if (!ao->a[0] || !ao->a[argoff + 1] || !ao->a[argoff + 2]) {
6173  return 0;
6174  }
6175  reg = getreg(ao->a[0]);
6176  if (reg == -1 || reg > 15) {
6177  return 0;
6178  }
6179  ut64 lsb = getnum(ao->a[argoff + 1]);
6180  if (lsb > 0x1f) {
6181  RZ_LOG_ERROR("assembler: arm: %s: lsb out of bounds\n", ops[i].name);
6182  return 0;
6183  }
6184  ut64 width = getnum(ao->a[argoff + 2]);
6185  ut64 msb = lsb + width - 1;
6186  if (width < 1 || width > 0x20 || msb > 0x1f) {
6187  RZ_LOG_ERROR("assembler: arm: %s: lsb + width out of bounds\n", ops[i].name);
6188  return 0;
6189  }
6190  ut32 tmp;
6191  rz_mem_swapendian((ut8 *)(void *)&tmp, (const ut8 *)(void *)&ao->o, sizeof(tmp));
6192  tmp |= lsb << 7;
6193  tmp |= msb << 16;
6194  tmp |= reg << 12;
6195  rz_mem_swapendian((ut8 *)(void *)&ao->o, (const ut8 *)(void *)&tmp, sizeof(tmp));
6196  break;
6197  }
6198  }
6199  }
6200  return 1;
6201  }
6202  }
6203  return 0;
6204 }
size_t len
Definition: 6502dis.c:15
#define imm
lzma_index ** i
Definition: index.h:629
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 ut64 getnum(const char *str)
Definition: armass.c:437
static ut32 getimmed8(const char *str)
Definition: armass.c:474
static ArmOp ops[]
Definition: armass.c:59
static char * getrange(char *s)
Definition: armass.c:598
static int arm_opcode_cond(ArmOpcode *ao, int delta)
Definition: armass.c:1140
static st32 getreglist(const char *input)
Definition: armass.c:748
static int strcmpnull(const char *a, const char *b)
Definition: armass.c:53
static bool err
Definition: armass.c:435
static int arm_assemble(ArmOpcode *ao, ut64 off, const char *str)
Definition: armass.c:5684
static ut32 getshift(const char *str)
Definition: armass.c:1042
static int getreg(const char *str)
Definition: armass.c:620
static int findyz(int x, int *y, int *z)
Definition: armass.c:5666
#define r
Definition: crypto_rc6.c:12
uint32_t ut32
static ut64 opc
Definition: desil.c:33
#define reg(n)
uint8_t ut8
Definition: lh5801.h:11
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char static mode static oldfd struct tms static buf static getgid static geteuid const char static filename static arg static mask struct ustat static ubuf static getppid static setsid static egid sigset_t static set struct timeval struct timezone static tz fd_set fd_set fd_set struct timeval static timeout const char char static bufsiz const char static swapflags void static offset const char static length static mode static who const char struct statfs static buf unsigned unsigned num
Definition: sflib.h:126
char * dst
Definition: lz4.h:724
int n
Definition: mipsasm.c:19
int type
Definition: mipsasm.c:17
int off
Definition: pal.c:13
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API void rz_mem_swapendian(ut8 *dest, const ut8 *orig, int size)
Definition: mem.c:202
#define st32
Definition: rz_types_base.h:12
static int
Definition: sfsocketcall.h:114
#define b(i)
Definition: sha256.c:42
#define a(i)
Definition: sha256.c:41
int type
Definition: armass.c:24
int code
Definition: armass.c:23
const char * name
Definition: armass.c:22
char * a[16]
Definition: armass.c:18
char op[128]
Definition: armass.c:16
ut64 off
Definition: armass.c:14
ut32 o
the assembled instruction
Definition: armass.c:15
Definition: z80asm.h:102
int width
Definition: main.c:10
ut64(WINAPI *w32_GetEnabledXStateFeatures)()

References a, ArmOpcode::a, arm_opcode_cond(), b, ArmOp::code, dst, err, findyz(), getimmed8(), getnum(), getrange(), getreg(), getreglist(), getshift(), i, imm, int, len, n, ArmOp::name, num, ArmOpcode::o, ArmOpcode::off, off, ArmOpcode::op, opc, ops, r, r0, r1, reg, RZ_LOG_ERROR, rz_mem_swapendian(), shift(), st32, cmd_descs_generate::str, strcmpnull(), autogen_x86imm::tmp, ArmOp::type, type, TYPE_ARI, TYPE_BFC, TYPE_BFI, TYPE_BKP, TYPE_BRA, TYPE_BRR, TYPE_CLZ, TYPE_COPROC, TYPE_ENDIAN, TYPE_HLT, TYPE_IMM, TYPE_MEM, TYPE_MOV, TYPE_MOVT, TYPE_MOVW, TYPE_MUL, TYPE_NEG, TYPE_REV, TYPE_SHFT, TYPE_SWI, TYPE_SWP, TYPE_TST, TYPE_UDF, ut64(), and width.

◆ arm_opcode_cond()

static int arm_opcode_cond ( ArmOpcode ao,
int  delta 
)
inlinestatic

Definition at line 1140 of file armass.c.

1140  {
1141  const char *conds[] = {
1142  "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
1143  "hi", "ls", "ge", "lt", "gt", "le", "al", "nv", 0
1144  };
1145  int i, cond = 14; // 'always' is default
1146  char *c = ao->op + delta;
1147  for (i = 0; conds[i]; i++) {
1148  if (!strcmpnull(c, conds[i])) {
1149  cond = i;
1150  break;
1151  }
1152  }
1153  ao->o |= cond << 4;
1154  return cond;
1155 }
#define c(i)
Definition: sha256.c:43
#define cond(bop, top, mask, flags)
static const char * conds[]
Definition: v810_disas.c:93
static st64 delta
Definition: vmenus.c:2425

References c, cond, conds, delta, i, ArmOpcode::o, ArmOpcode::op, and strcmpnull().

Referenced by arm_assemble().

◆ arm_opcode_parse()

static void arm_opcode_parse ( ArmOpcode ao,
const char *  str 
)
static

Definition at line 1099 of file armass.c.

1099  {
1100  memset(ao, 0, sizeof(ArmOpcode));
1101  if (strlen(str) + 1 >= sizeof(ao->op)) {
1102  return;
1103  }
1104  strncpy(ao->op, str, sizeof(ao->op) - 1);
1105  strcpy(ao->opstr, ao->op);
1106  char *c = strchr(ao->op, ' ');
1107  if (!c) {
1108  return;
1109  }
1110  for (size_t i = 0; i < 16; i++) {
1111  while (*c == ' ') {
1112  *c++ = '\0';
1113  }
1114  if (!*c) {
1115  break;
1116  }
1117  // found start of new argument
1118  ao->a[i] = c;
1119  // find end of new argument
1120  while (*c && *c != ',') {
1121  if (*c == '{') {
1122  // reglists like "{r0, r1, r2}" should be a single arg
1123  c = strchr(c, '}');
1124  if (!c) {
1125  return;
1126  }
1127  }
1128  c++;
1129  }
1130  if (!*c) {
1131  rz_str_trim_tail(ao->a[i]);
1132  break;
1133  }
1134  *c = '\0';
1135  rz_str_trim_tail(ao->a[i]);
1136  c++;
1137  }
1138 }
return memset(p, 0, total)
RZ_API RZ_BORROW char * rz_str_trim_tail(RZ_NONNULL char *str)
Removes whitespace characters (space, tab, newline etc.) from the end of a string and replaces them w...
Definition: str_trim.c:125
char opstr[128]
Definition: armass.c:17

References ArmOpcode::a, c, i, memset(), ArmOpcode::op, ArmOpcode::opstr, rz_str_trim_tail(), and cmd_descs_generate::str.

Referenced by armass_assemble().

◆ armass_assemble()

ut32 armass_assemble ( const char *  str,
ut64  off,
int  thumb 
)

Definition at line 6209 of file armass.c.

6209  {
6210  int i, j;
6211  char buf[128];
6212  ArmOpcode aop = { .off = off };
6213  for (i = j = 0; i < sizeof(buf) - 1 && str[j]; i++, j++) {
6214  if (str[j] == '#') {
6215  i--;
6216  continue;
6217  }
6218  buf[i] = tolower((const ut8)str[j]);
6219  }
6220  buf[i] = 0;
6221  arm_opcode_parse(&aop, buf);
6222  aop.off = off;
6223  if (thumb < 0 || thumb > 1) {
6224  return -1;
6225  }
6226  if (assemble[thumb](&aop, off, buf) <= 0) {
6227  // RZ_LOG_ERROR("armass: Unknown opcode (%s)\n", buf);
6228  return -1;
6229  }
6230  return aop.o;
6231 }
static AssembleFunction assemble[2]
Definition: armass.c:6207
static void arm_opcode_parse(ArmOpcode *ao, const char *str)
Definition: armass.c:1099
voidpf void * buf
Definition: ioapi.h:138
#define tolower(c)
Definition: safe-ctype.h:149

References arm_opcode_parse(), assemble, i, ArmOpcode::o, ArmOpcode::off, off, cmd_descs_generate::str, and tolower.

Referenced by assemble().

◆ cqcheck()

static ut64 cqcheck ( char **  input)
static

Definition at line 230 of file armass.c.

230  {
231  ut64 res = 0;
232  int i;
233  ut8 offset = 0;
234 
235  const char *conds[] = {
236  "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
237  "hi", "ls", "ge", "lt", "gt", "le", "al", "nv", 0
238  };
239  for (i = 0; conds[i]; i++) {
240  if (rz_str_startswith(*input, conds[i])) {
241  res |= C_MATCH_BIT;
242  res |= i << 2;
243  *input += 2;
244  offset += 2;
245  break;
246  }
247  }
248  if (rz_str_startswith(*input, ".n")) {
249  res |= DOTN_BIT;
250  *input += 2;
251  offset += 2;
252  } else if (rz_str_startswith(*input, ".w")) {
253  res |= DOTW_BIT;
254  *input += 2;
255  offset += 2;
256  }
257 
258  if (**input == '\0') {
259  return res;
260  }
261  *input -= offset;
262  return 0;
263 }
static const ut64 C_MATCH_BIT
Definition: armass.c:190
static const ut64 DOTN_BIT
Definition: armass.c:164
static const ut64 DOTW_BIT
Definition: armass.c:165
voidpf uLong offset
Definition: ioapi.h:144
RZ_API bool rz_str_startswith(RZ_NONNULL const char *str, RZ_NONNULL const char *needle)
Checks if a string starts with a specifc sequence of characters (case sensitive)
Definition: str.c:3286
static bool input(void *ud, zip_uint8_t *data, zip_uint64_t length)

References C_MATCH_BIT, conds, DOTN_BIT, DOTW_BIT, i, input(), rz_str_startswith(), and ut64().

Referenced by opmask().

◆ findyz()

static int findyz ( int  x,
int y,
int z 
)
static

Definition at line 5666 of file armass.c.

5666  {
5667  int i, j;
5668  for (i = 0; i < 0xff; i++) {
5669  for (j = 0; j < 0xf; j++) {
5670  int v = i << j;
5671  if (v > x) {
5672  continue;
5673  }
5674  if (v == x) {
5675  *y = i;
5676  *z = 16 - (j / 2);
5677  return 1;
5678  }
5679  }
5680  }
5681  return 0;
5682 }
const char * v
Definition: dsignal.c:12
int x
Definition: mipsasm.c:20

References i, v, and x.

Referenced by arm_assemble().

◆ firstsigdigit()

static st32 firstsigdigit ( ut32  num)
static

Definition at line 495 of file armass.c.

495  {
496  st32 f = -1;
497  st32 b = -1;
498  ut32 forwardmask = 0x80000000;
499  ut32 backwardmask = 0x1;
500  ut32 i;
501  for (i = 0; i < 32; i++) {
502  if ((forwardmask & num) && (f == -1)) {
503  f = i;
504  }
505  if ((backwardmask & num) && (b == -1)) {
506  b = 32 - i;
507  }
508  forwardmask >>= 1;
509  backwardmask <<= 1;
510  }
511 
512  if ((b - f) < 9) {
513  return f;
514  }
515  return -1;
516 }
#define f(i)
Definition: sha256.c:46

References b, f, i, num, and st32.

Referenced by getthimmed12().

◆ getcoproc()

static int getcoproc ( const char *  str)
static

Definition at line 814 of file armass.c.

814  {
815  char *ep;
816  if (!str || !*str) {
817  return -1;
818  }
819  if (*str == 'p') {
820  int coproc = strtol(str + 1, &ep, 10);
821  if ((ep[0] != '\0') || (str[1] == '\0')) {
822  return -1;
823  }
824  if (coproc < 16 && coproc >= 0) {
825  return coproc;
826  }
827  }
828  return -1;
829 }

References cmd_descs_generate::str.

Referenced by thumb_assemble(), and thumb_selector().

◆ getcoprocreg()

static int getcoprocreg ( const char *  str)
static

Definition at line 831 of file armass.c.

831  {
832  char *ep;
833 
834  if (!str || !*str) {
835  return -1;
836  }
837  if (rz_str_startswith(str, "c")) {
838  int reg = strtol(str + 1, &ep, 10);
839  if ((ep[0] != '\0') || (str[1] == '\0')) {
840  return -1;
841  }
842  if (reg < 16 && reg >= 0) {
843  return reg;
844  }
845  }
846  return -1;
847 }

References reg, rz_str_startswith(), and cmd_descs_generate::str.

Referenced by thumb_assemble(), and thumb_selector().

◆ getimmed8()

static ut32 getimmed8 ( const char *  str)
static

Definition at line 474 of file armass.c.

474  {
475  ut32 num = getnum(str);
476  if (err) {
477  return 0;
478  }
479  ut32 rotate;
480  if (num <= 0xff) {
481  return num;
482  } else {
483  for (rotate = 1; rotate < 16; rotate++) {
484  // rol 2
485  num = ((num << 2) | (num >> 30));
486  if (num == (num & 0xff)) {
487  return (num | (rotate << 8));
488  }
489  }
490  err = 1;
491  return 0;
492  }
493 }
void rotate(unsigned char *list, unsigned len, unsigned rot)
Definition: gzappend.c:123

References err, getnum(), num, rotate(), and cmd_descs_generate::str.

Referenced by arm_assemble().

◆ getlistmask()

static st32 getlistmask ( char *  input)
static

Definition at line 644 of file armass.c.

644  {
645  st32 tempres, res = 0;
646  int i, j, start, end;
647  char *temp = NULL;
648  char *otemp = NULL;
649  char *temp2 = malloc(strlen(input) + 1);
650  if (!temp2) {
651  res = -1;
652  goto end;
653  }
654  temp = (char *)malloc(strlen(input) + 1);
655  if (!temp) {
656  res = -1;
657  goto end;
658  }
659  otemp = temp;
660  while (*input != '\0') {
661  for (; *input == ' '; input++) {
662  ;
663  }
664  for (i = 0; input[i] != ',' && input[i] != '\0'; i++) {
665  ;
666  }
667  rz_str_ncpy(temp, input, i + 1);
668 
669  input += i;
670  if (*input != '\0') {
671  input++;
672  }
673 
674  for (i = 0; temp[i] != '-' && temp[i] != '\0'; i++) {
675  ;
676  }
677  if (i == strlen(temp)) {
678  tempres = getreg(temp);
679  if (tempres == -1 || tempres > 15) {
680  res = -1;
681  goto end;
682  }
683  res |= 1 << tempres;
684  } else {
685  strncpy(temp2, temp, i);
686  temp2[i] = 0;
687  temp += i + 1;
688  start = getreg(temp2);
689  if (start == -1 || start > 15) {
690  res = -1;
691  goto end;
692  }
693  end = getreg(temp);
694  if (end == -1 || end > 15) {
695  res = -1;
696  goto end;
697  }
698 
699  for (j = start; j <= end; j++) {
700  res |= 1 << j;
701  }
702  }
703  }
704 end:
705  free(otemp);
706  free(temp2);
707  return res;
708 }
#define NULL
Definition: cris-opc.c:27
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 static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void start
Definition: sflib.h:133
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
void * malloc(size_t size)
Definition: malloc.c:123
RZ_API size_t rz_str_ncpy(char *dst, const char *src, size_t n)
Secure string copy with null terminator.
Definition: str.c:923

References test_evm::end, free(), getreg(), i, input(), malloc(), NULL, rz_str_ncpy(), st32, and start.

Referenced by getreglist().

◆ getnum()

static ut64 getnum ( const char *  str)
static

Definition at line 437 of file armass.c.

437  {
438  char *endptr;
439  err = false;
440  ut64 val;
441 
442  if (!str) {
443  err = true;
444  return 0;
445  }
446  while (*str == '$' || *str == '#') {
447  str++;
448  }
449  val = strtoll(str, &endptr, 0);
450  if (str != endptr && *endptr == '\0') {
451  return val;
452  }
453  err = true;
454  return 0;
455 }
ut16 val
Definition: armass64_const.h:6

References err, cmd_descs_generate::str, ut64(), and val.

Referenced by arm_assemble(), getimmed8(), getnumbang(), getnummemend(), getnummemendbang(), getthimmed12(), thumb_assemble(), thumb_getshift(), and thumb_selector().

◆ getnumbang()

static ut64 getnumbang ( const char *  str)
static

Definition at line 457 of file armass.c.

457  {
458  ut64 res;
459 
460  if (!str || !*str || !rz_str_endswith(str, "!")) {
461  err = true;
462  return 0;
463  }
464  char *temp = rz_str_ndup(str, strlen(str) - 1);
465  if (!temp) {
466  return -1;
467  }
468  err = false;
469  res = getnum(temp);
470  free(temp);
471  return res; // err propagates
472 }
RZ_API char * rz_str_ndup(RZ_NULLABLE const char *ptr, int len)
Create new copy of string ptr limited to size len.
Definition: str.c:1006
RZ_API bool rz_str_endswith(RZ_NONNULL const char *str, RZ_NONNULL const char *needle)
Checks if a string ends with a specifc sequence of characters (case sensitive)
Definition: str.c:3329

References err, free(), getnum(), rz_str_endswith(), rz_str_ndup(), cmd_descs_generate::str, and ut64().

Referenced by thumb_selector().

◆ getnummemend()

static st32 getnummemend ( const char *  input)
static

Definition at line 766 of file armass.c.

766  {
767  st32 res;
768  err = false;
769  if (!input || !*input || !rz_str_endswith(input, "]")) {
770  err = true;
771  return -1;
772  }
773  char *temp = rz_str_ndup(input, strlen(input) - 1);
774  if (!temp) {
775  err = true;
776  return -1;
777  }
778  res = getnum(temp);
779  free(temp);
780  return res;
781 }

References err, free(), getnum(), input(), rz_str_endswith(), rz_str_ndup(), and st32.

Referenced by thumb_assemble(), and thumb_selector().

◆ getnummemendbang()

static st32 getnummemendbang ( const char *  input)
static

Definition at line 783 of file armass.c.

783  {
784  st32 res;
785  err = false;
786  if (!input || (strlen(input) < 2) || (input[strlen(input) - 2] != ']' || !rz_str_endswith(input, "!"))) {
787  err = true;
788  return 0;
789  }
790  char *temp = rz_str_ndup(input, strlen(input) - 2);
791  if (!temp) {
792  err = true;
793  return 0;
794  }
795  res = getnum(temp);
796  free(temp);
797  return res;
798 }

References err, free(), getnum(), input(), rz_str_endswith(), rz_str_ndup(), and st32.

Referenced by thumb_assemble(), and thumb_selector().

◆ getrange()

static char* getrange ( char *  s)
static

Definition at line 598 of file armass.c.

598  {
599  char *p = NULL;
600  while (s && *s) {
601  if (*s == ',') {
602  p = s + 1;
603  *p = 0;
604  }
605  if (*s == '[' || *s == ']') {
606  memmove(s, s + 1, strlen(s + 1) + 1);
607  }
608  if (*s == '}') {
609  *s = 0;
610  }
611  s++;
612  }
613  while (p && *p == ' ') {
614  p++;
615  }
616  return p;
617 }
void * p
Definition: libc.cpp:67
static RzSocket * s
Definition: rtr.c:28

References NULL, p, and s.

Referenced by arm_assemble().

◆ getreg()

static int getreg ( const char *  str)
static

Definition at line 620 of file armass.c.

620  {
621  int i;
622  char *ep;
623  const char *aliases[] = { "sb", "sl", "fp", "ip", "sp", "lr", "pc", NULL };
624  if (!str || !*str) {
625  return -1;
626  }
627  if (*str == 'r') {
628  int reg = strtol(str + 1, &ep, 10);
629  if ((ep[0] != '\0') || (str[1] == '\0')) {
630  return -1;
631  }
632  if (reg < 16 && reg >= 0) {
633  return reg;
634  }
635  }
636  for (i = 0; aliases[i]; i++) {
637  if (!strcmpnull(str, aliases[i])) {
638  return 9 + i;
639  }
640  }
641  return -1;
642 }

References i, NULL, reg, cmd_descs_generate::str, and strcmpnull().

Referenced by arm_assemble(), getlistmask(), getregmembang(), getregmemend(), getregmemstart(), getregmemstartend(), getshift(), mem_16bit_2reg(), mem_32bit_2reg(), std_16bit_2reg(), std_32bit_2reg(), std_32bit_3reg(), thumb_assemble(), and thumb_selector().

◆ getreglist()

static st32 getreglist ( const char *  input)
static

Definition at line 748 of file armass.c.

748  {
749  st32 res;
750 
751  if (!input || (strlen(input) < 2) || (*input != '{') || !rz_str_endswith(input, "}")) {
752  return -1;
753  }
754  if (*input) {
755  input++;
756  }
757  char *temp = rz_str_ndup(input, strlen(input) - 1);
758  if (!temp) {
759  return -1;
760  }
761  res = getlistmask(temp);
762  free(temp);
763  return res;
764 }
static st32 getlistmask(char *input)
Definition: armass.c:644

References free(), getlistmask(), input(), rz_str_endswith(), rz_str_ndup(), and st32.

Referenced by arm_assemble(), thumb_assemble(), and thumb_selector().

◆ getregmembang()

static st32 getregmembang ( const char *  input)
static

Definition at line 800 of file armass.c.

800  {
801  st32 res;
802  if (!input || !*input || !rz_str_endswith(input, "!")) {
803  return -1;
804  }
805  char *temp = rz_str_ndup(input, strlen(input) - 1);
806  if (!temp) {
807  return -1;
808  }
809  res = getreg(temp);
810  free(temp);
811  return res;
812 }

References free(), getreg(), input(), rz_str_endswith(), rz_str_ndup(), and st32.

Referenced by thumb_assemble(), and thumb_selector().

◆ getregmemend()

static st32 getregmemend ( const char *  input)
static

Definition at line 733 of file armass.c.

733  {
734  st32 res;
735  if (!input || !*input || !rz_str_endswith(input, "]")) {
736  return -1;
737  }
738 
739  char *temp = rz_str_ndup(input, strlen(input) - 1);
740  if (!temp) {
741  return -1;
742  }
743  res = getreg(temp);
744  free(temp);
745  return res;
746 }

References free(), getreg(), input(), rz_str_endswith(), rz_str_ndup(), and st32.

Referenced by thumb_assemble(), and thumb_selector().

◆ getregmemstart()

static st32 getregmemstart ( const char *  input)
static

Definition at line 710 of file armass.c.

710  {
711  if ((strlen(input) < 1) || (!(*input == '['))) {
712  return -1;
713  }
714  input++;
715  return getreg(input);
716 }

References getreg(), and input().

Referenced by mem_16bit_2reg(), mem_32bit_2reg(), thumb_assemble(), and thumb_selector().

◆ getregmemstartend()

static st32 getregmemstartend ( const char *  input)
static

Definition at line 718 of file armass.c.

718  {
719  st32 res;
720  if (!input || (strlen(input) < 2) || (*input != '[') || !rz_str_endswith(input, "]")) {
721  return -1;
722  }
723  input++;
724  char *temp = rz_str_ndup(input, strlen(input) - 1);
725  if (!temp) {
726  return -1;
727  }
728  res = getreg(temp);
729  free(temp);
730  return res;
731 }

References free(), getreg(), input(), rz_str_endswith(), rz_str_ndup(), and st32.

Referenced by thumb_assemble(), and thumb_selector().

◆ getshift()

static ut32 getshift ( const char *  str)
static

Definition at line 1042 of file armass.c.

1042  {
1043  char type[128];
1044  char arg[128];
1045  char *space;
1046  ut32 i = 0, shift = 0;
1047  const char *shifts[] = {
1048  "LSL", "LSR", "ASR", "ROR",
1049  0, "RRX" // alias for ROR #0
1050  };
1051 
1052  strncpy(type, str, sizeof(type) - 1);
1053  // XXX strcaecmp is probably unportable
1054  if (rz_str_casecmp(type, shifts[5])) {
1055  space = strchr(type, ' ');
1056  if (!space) {
1057  return 0;
1058  }
1059  *space = 0;
1060  strncpy(arg, ++space, sizeof(arg) - 1);
1061 
1062  for (i = 0; shifts[i]; i++) {
1063  if (!rz_str_casecmp(type, shifts[i])) {
1064  shift = 1;
1065  break;
1066  }
1067  }
1068  if (!shift) {
1069  return 0;
1070  }
1071  shift = i * 2;
1072  if ((i = getreg(arg)) != -1) {
1073  i <<= 8; // set reg
1074  // i|=1; // use reg
1075  i |= (1 << 4); // bitshift
1076  i |= shift << 4; // set shift mode
1077  if (shift == 6) {
1078  i |= (1 << 20);
1079  }
1080  } else {
1081  char *bracket = strchr(arg, ']');
1082  if (bracket) {
1083  *bracket = '\0';
1084  }
1085  // ensure only the bottom 5 bits are used
1086  i &= 0x1f;
1087  if (!i) {
1088  i = 32;
1089  }
1090  i = (i * 8);
1091  i |= shift; // lsl, ror, ...
1092  i = i << 4;
1093  }
1094  }
1095 
1096  return i;
1097 }
RZ_API int rz_str_casecmp(const char *dst, const char *orig)
Definition: str.c:121

References getreg(), i, rz_str_casecmp(), shift(), cmd_descs_generate::str, and type.

Referenced by arm_assemble().

◆ getshiftmemend()

static st32 getshiftmemend ( const char *  input)
static

Definition at line 948 of file armass.c.

948  {
949  st32 res;
950  if (!input || !*input || !rz_str_endswith(input, "]")) {
951  return -1;
952  }
953 
954  char *temp = rz_str_ndup(input, strlen(input) - 1);
955  if (!temp) {
956  return -1;
957  }
958  res = thumb_getshift(temp);
959  free(temp);
960  return res;
961 }
static ut32 thumb_getshift(const char *str)
Definition: armass.c:887

References free(), input(), rz_str_endswith(), rz_str_ndup(), st32, and thumb_getshift().

Referenced by thumb_assemble(), and thumb_selector().

◆ getthbimmed()

static ut32 getthbimmed ( st32  number)
static

Definition at line 518 of file armass.c.

518  {
519  ut32 res = 0;
520  if (number < 0) {
521  res |= 1 << 18;
522  }
523  number >>= 1;
524  res |= ((number & 0xff) << 8);
525  number >>= 8;
526  res |= (number & 0x07);
527  number >>= 3;
528  res |= ((number & 0xff) << 24);
529  number >>= 8;
530  res |= ((number & 0x3) << 16);
531  number >>= 2;
532  if (number < 0) {
533  res |= ((number & 0x1) << 3);
534  number >>= 1;
535  res |= ((number & 0x1) << 5);
536  } else {
537  res |= ((!(number & 0x1)) << 3);
538  number >>= 1;
539  res |= ((!(number & 0x1)) << 5);
540  }
541  return res;
542 }

Referenced by thumb_assemble().

◆ getthimmed12()

static ut32 getthimmed12 ( const char *  str)
static

Definition at line 561 of file armass.c.

561  {
562  ut64 num = getnum(str);
563  if (err) {
564  return 0;
565  }
566 
567  st32 FSD = 0;
568  ut64 result = 0;
569  if (num <= 0xff) {
570  return num << 8;
571  } else if (((num & 0xff00ff00) == 0) && ((num & 0x00ff0000) == ((num & 0x000000ff) << 16))) {
572  result |= (num & 0x000000ff) << 8;
573  result |= 0x00000010;
574  return result;
575  } else if (((num & 0x00ff00ff) == 0) && ((num & 0xff000000) == ((num & 0x0000ff00) << 16))) {
576  result |= num & 0x0000ff00;
577  result |= 0x00000020;
578  return result;
579  } else if (((num & 0xff000000) == ((num & 0x00ff0000) << 8)) && ((num & 0xff000000) == ((num & 0x0000ff00) << 16)) && ((num & 0xff000000) == ((num & 0x000000ff) << 24))) {
580  result |= num & 0x0000ff00;
581  result |= 0x00000030;
582  return result;
583  } else {
584  FSD = firstsigdigit(num);
585  if (FSD != -1) {
586  result |= ((num >> (24 - FSD)) & 0x0000007f) << 8;
587  result |= ((8 + FSD) & 0x1) << 15;
588  result |= ((8 + FSD) & 0xe) << 3;
589  result |= ((8 + FSD) & 0x10) << 14;
590  return result;
591  } else {
592  err = true;
593  return 0;
594  }
595  }
596 }
static st32 firstsigdigit(ut32 num)
Definition: armass.c:495

References err, firstsigdigit(), getnum(), num, st32, cmd_descs_generate::str, and ut64().

Referenced by thumb_assemble().

◆ getthzeroimmed12()

static ut32 getthzeroimmed12 ( ut32  number)
static

Definition at line 544 of file armass.c.

544  {
545  ut32 res = 0;
546  res |= (number & 0x800) << 7;
547  res |= (number & 0x700) >> 4;
548  res |= (number & 0x0ff) << 8;
549  return res;
550 }

Referenced by thumb_assemble().

◆ getthzeroimmed16()

static ut32 getthzeroimmed16 ( ut32  number)
static

Definition at line 552 of file armass.c.

552  {
553  ut32 res = 0;
554  res |= (number & 0xf000) << 12;
555  res |= (number & 0x0800) << 7;
556  res |= (number & 0x0700) >> 4;
557  res |= (number & 0x00ff) << 8;
558  return res;
559 }

Referenced by thumb_assemble().

◆ iflag()

static st8 iflag ( char *  input)
static

Definition at line 208 of file armass.c.

208  {
209  st8 res = 0;
210  rz_str_case(input, false);
211 
212  for (; *input; input++) {
213  switch (*input) {
214  case 'a':
215  res |= 0x4;
216  break;
217  case 'i':
218  res |= 0x2;
219  break;
220  case 'f':
221  res |= 0x1;
222  break;
223  default:
224  return -1;
225  }
226  }
227  return res;
228 }
RZ_API void rz_str_case(char *str, bool up)
Definition: str.c:341
#define st8
Definition: rz_types_base.h:16

References input(), rz_str_case(), and st8.

Referenced by thumb_assemble().

◆ interpret_msrbank()

static ut8 interpret_msrbank ( char *  str,
ut8 spsr 
)
static

Definition at line 849 of file armass.c.

849  {
850  const char fields[] = { 'c', 'x', 's', 'f', 0 };
851  int res = 0;
852  int i, j;
853  if (rz_str_startswith(str, "spsr_")) {
854  *spsr = 1;
855  } else {
856  *spsr = 0;
857  }
858 
859  if (rz_str_startswith(str, "apsr_")) {
860  if (!(strcmp(str + 5, "g"))) {
861  return 0x4;
862  }
863  if (!(strcmp(str + 5, "nzcvq"))) {
864  return 0x8;
865  }
866  if (!(strcmp(str + 5, "nzcvqg"))) {
867  return 0xc;
868  }
869  }
870  if (rz_str_startswith(str, "cpsr_") || rz_str_startswith(str, "spsr_")) {
871  for (i = 0; str[5 + i]; i++) {
872  for (j = 0; fields[j]; j++) {
873  if (str[5 + i] == fields[j]) {
874  break;
875  }
876  }
877  if (!(fields[j])) {
878  return 0;
879  }
880  res |= 1 << j;
881  }
882  return res;
883  }
884  return 0;
885 }
const aarch64_field fields[]
Definition: aarch64-opc.c:205

References fields, i, rz_str_startswith(), spsr, and cmd_descs_generate::str.

Referenced by thumb_assemble().

◆ itmask()

static ut32 itmask ( char *  input)
static

Definition at line 405 of file armass.c.

405  {
406  ut32 res = 0;
407  ut32 i, length;
408  rz_str_case(input, false);
409  if (2 > strlen(input)) {
410  return 0;
411  }
412  if (rz_str_startswith(input, "it")) {
413  input += 2;
414  res |= 1; // matched
415  if (strlen(input) > 3) {
416  return 0;
417  }
418  res |= (strlen(input) & 0x3) << 4;
419  length = strlen(input);
420  for (i = 0; i < length; i++, input++) {
421  if (*input == 'e') {
422  res |= 1 << (3 - i);
423  continue;
424  }
425  if (*input == 't') {
426  continue;
427  }
428  return 0;
429  }
430  return res;
431  }
432  return 0;
433 }
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 static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void length
Definition: sflib.h:133

References i, input(), length, rz_str_case(), and rz_str_startswith().

Referenced by thumb_assemble().

◆ mem_16bit_2reg()

static st8 mem_16bit_2reg ( ArmOpcode ao,
ut64  m 
)
static

Definition at line 1176 of file armass.c.

1176  {
1177  ut8 rd = getreg(ao->a[0]);
1178  ut8 rn = getregmemstart(ao->a[1]);
1179  if ((rd < 8) && (rn < 8) && !(m & DOTW_BIT)) {
1180  ao->o |= rd << 8;
1181  ao->o |= rn << 11;
1182  return 2;
1183  }
1184  return 0;
1185 }
#define rd()
static st32 getregmemstart(const char *input)
Definition: armass.c:710

References ArmOpcode::a, DOTW_BIT, getreg(), getregmemstart(), regress::m, ArmOpcode::o, and rd.

Referenced by thumb_assemble().

◆ mem_32bit_2reg()

static st8 mem_32bit_2reg ( ArmOpcode ao,
ut64  m 
)
static

Definition at line 1212 of file armass.c.

1212  {
1213  ut8 rd = getreg(ao->a[0]);
1214  ut8 rn = getregmemstart(ao->a[1]);
1215  if ((rd > 15) || (rn > 15) || (m & DOTN_BIT)) {
1216  return -1;
1217  }
1218  ao->o |= rd << 4;
1219  ao->o |= rn << 24;
1220  return 4;
1221 }

References ArmOpcode::a, DOTN_BIT, getreg(), getregmemstart(), regress::m, ArmOpcode::o, and rd.

Referenced by thumb_assemble().

◆ opmask()

static ut64 opmask ( char *  input,
char *  opcode,
ut64  allowed_mask 
)
static

Definition at line 265 of file armass.c.

265  {
266  ut64 res = 0;
267 
268  rz_str_case(input, false);
269  if (strlen(opcode) > strlen(input)) {
270  return 0;
271  }
272  if (rz_str_startswith(input, opcode)) {
273  input += strlen(opcode);
274  res |= M_BIT;
275  res |= cqcheck(&input);
276 
277  if ((*input == 's') && (S_BIT & allowed_mask)) {
278  res |= S_BIT;
279  input++;
280  }
281  res |= cqcheck(&input);
282 
283  if ((rz_str_startswith(input, "wb")) && (WB_BIT & allowed_mask)) {
284  res |= WB_BIT;
285  input += 2;
286  }
287  if ((rz_str_startswith(input, "wt")) && (WT_BIT & allowed_mask)) {
288  res |= WT_BIT;
289  input += 2;
290  }
291  res |= cqcheck(&input);
292  if ((rz_str_startswith(input, "db")) && (DB_BIT & allowed_mask)) {
293  res |= DB_BIT;
294  input += 2;
295  }
296  if ((rz_str_startswith(input, "ea")) && (EA_BIT & allowed_mask)) {
297  res |= EA_BIT;
298  input += 2;
299  }
300  if ((rz_str_startswith(input, "ia")) && (IA_BIT & allowed_mask)) {
301  res |= IA_BIT;
302  input += 2;
303  }
304  if ((rz_str_startswith(input, "fd")) && (FD_BIT & allowed_mask)) {
305  res |= FD_BIT;
306  input += 2;
307  }
308  res |= cqcheck(&input);
309  if ((*input == 'l') && (L_BIT & allowed_mask)) {
310  res |= L_BIT;
311  input++;
312  }
313  res |= cqcheck(&input);
314  if ((rz_str_startswith(input, "bb")) && (BB_BIT & allowed_mask)) {
315  res |= BB_BIT;
316  input += 2;
317  }
318  if ((rz_str_startswith(input, "tt")) && (TT_BIT & allowed_mask)) {
319  res |= TT_BIT;
320  input += 2;
321  }
322  if ((rz_str_startswith(input, "bt")) && (BT_BIT & allowed_mask)) {
323  res |= BT_BIT;
324  input += 2;
325  }
326  if ((rz_str_startswith(input, "tb")) && (TB_BIT & allowed_mask)) {
327  res |= TB_BIT;
328  input += 2;
329  }
330  res |= cqcheck(&input);
331  if ((*input == 'w') && (W_BIT & allowed_mask)) {
332  res |= W_BIT;
333  input++;
334  }
335  if ((*input == 'b') && (B_BIT & allowed_mask)) {
336  res |= B_BIT;
337  input++;
338  } else if ((*input == 'h') && (H_BIT & allowed_mask)) {
339  res |= H_BIT;
340  input++;
341  } else if ((*input == 'd') && (D_BIT & allowed_mask)) {
342  res |= D_BIT;
343  input++;
344  }
345  if ((*input == 't') && (T_BIT & allowed_mask)) {
346  res |= T_BIT;
347  input++;
348  }
349  if ((*input == 's') && (S_BIT & allowed_mask)) {
350  res |= S_BIT;
351  input++;
352  }
353  res |= cqcheck(&input);
354  if ((*input == 'r') && (RZ_BIT & allowed_mask)) {
355  res |= RZ_BIT;
356  input++;
357  }
358  res |= cqcheck(&input);
359  if ((*input == '2') && (TWO_BIT & allowed_mask)) {
360  res |= TWO_BIT;
361  input++;
362  }
363  if ((*input == '8') && (EIGHT_BIT & allowed_mask)) {
364  res |= EIGHT_BIT;
365  input++;
366  }
367  if ((rz_str_startswith(input, "16")) && (SIXTEEN_BIT & allowed_mask)) {
368  res |= SIXTEEN_BIT;
369  input += 2;
370  }
371  res |= cqcheck(&input);
372  if ((*input == 'l') && (L_BIT & allowed_mask)) {
373  res |= L_BIT;
374  input++;
375  }
376  if ((*input == 'x') && (X_BIT & allowed_mask)) {
377  res |= X_BIT;
378  input++;
379  }
380  res |= cqcheck(&input);
381  if ((rz_str_startswith(input, "id")) && (ID_BIT & allowed_mask)) {
382  res |= ID_BIT;
383  input += 2;
384  }
385  if ((rz_str_startswith(input, "ie")) && (IE_BIT & allowed_mask)) {
386  res |= IE_BIT;
387  input += 2;
388  }
389  res |= cqcheck(&input);
390  if ((rz_str_startswith(input, "sh")) && (SH_BIT & allowed_mask)) {
391  res |= SH_BIT;
392  input += 2;
393  }
394  res |= cqcheck(&input);
395  if (!(res & C_MATCH_BIT)) {
396  res |= 15 << 2; // nv is the default condition
397  }
398  if (*input == 0) {
399  return res;
400  }
401  }
402  return 0;
403 }
static const ut64 W_BIT
Definition: armass.c:177
static const ut64 TB_BIT
Definition: armass.c:182
static const ut64 IE_BIT
Definition: armass.c:169
static const ut64 RZ_BIT
Definition: armass.c:184
static const ut64 EA_BIT
Definition: armass.c:171
static const ut64 BB_BIT
Definition: armass.c:180
static const ut64 H_BIT
Definition: armass.c:175
static const ut64 X_BIT
Definition: armass.c:167
static const ut64 S_BIT
Definition: armass.c:162
static const ut64 L_BIT
Definition: armass.c:166
static ut64 cqcheck(char **input)
Definition: armass.c:230
static const ut64 B_BIT
Definition: armass.c:174
static const ut64 SH_BIT
Definition: armass.c:187
static const ut64 TT_BIT
Definition: armass.c:183
static const ut64 D_BIT
Definition: armass.c:176
static const ut64 ID_BIT
Definition: armass.c:170
static const ut64 WT_BIT
Definition: armass.c:189
static const ut64 FD_BIT
Definition: armass.c:172
static const ut64 WB_BIT
Definition: armass.c:188
static const ut64 DB_BIT
Definition: armass.c:186
static const ut64 IA_BIT
Definition: armass.c:185
static const ut64 T_BIT
Definition: armass.c:173
static const ut64 BT_BIT
Definition: armass.c:181
static const ut64 SIXTEEN_BIT
Definition: armass.c:179
static const ut64 TWO_BIT
Definition: armass.c:168
static const ut64 M_BIT
Definition: armass.c:161
static const ut64 EIGHT_BIT
Definition: armass.c:178

References B_BIT, BB_BIT, BT_BIT, C_MATCH_BIT, cqcheck(), D_BIT, DB_BIT, EA_BIT, EIGHT_BIT, FD_BIT, H_BIT, IA_BIT, ID_BIT, IE_BIT, input(), L_BIT, M_BIT, RZ_BIT, rz_str_case(), rz_str_startswith(), S_BIT, SH_BIT, SIXTEEN_BIT, T_BIT, TB_BIT, TT_BIT, TWO_BIT, ut64(), W_BIT, WB_BIT, WT_BIT, and X_BIT.

Referenced by thumb_assemble().

◆ parse_hints()

static char* parse_hints ( char *  input)
static

Definition at line 192 of file armass.c.

192  {
193  if (!strcmpnull(input, "unst")) {
194  return "6";
195  }
196  if (!strcmpnull(input, "un")) {
197  return "7";
198  }
199  if (!strcmpnull(input, "st")) {
200  return "14";
201  }
202  if (!strcmpnull(input, "sy")) {
203  return "15";
204  }
205  return "-1";
206 }

References input(), and strcmpnull().

Referenced by thumb_assemble().

◆ std_16bit_2reg()

static st8 std_16bit_2reg ( ArmOpcode ao,
ut64  m 
)
static

Definition at line 1165 of file armass.c.

1165  {
1166  ut8 rd = getreg(ao->a[0]);
1167  ut8 rn = getreg(ao->a[1]);
1168  if ((rd < 8) && (rn < 8) && !(m & DOTW_BIT)) {
1169  ao->o |= rd << 8;
1170  ao->o |= rn << 11;
1171  return 2;
1172  }
1173  return 0;
1174 }

References ArmOpcode::a, DOTW_BIT, getreg(), regress::m, ArmOpcode::o, and rd.

Referenced by thumb_assemble().

◆ std_32bit_2reg()

static st8 std_32bit_2reg ( ArmOpcode ao,
ut64  m,
bool  shift 
)
static

Definition at line 1187 of file armass.c.

1187  {
1188  ut8 rd = getreg(ao->a[0]);
1189  ut8 rn = getreg(ao->a[1]);
1190  if ((rd > 15) || (rn > 15) || (m & DOTN_BIT)) {
1191  return -1;
1192  }
1193  if (m & S_BIT) {
1194  ao->o |= 1 << 28;
1195  }
1196  if (shift) {
1197  err = false;
1198  ut32 shiftnum = thumb_getshift(ao->a[2]);
1199  if (err) {
1200  return -1;
1201  }
1202  ao->o |= shiftnum;
1203  ao->o |= rd << 24;
1204  ao->o |= rn << 8;
1205  } else {
1206  ao->o |= rd;
1207  ao->o |= rn << 24;
1208  }
1209  return 4;
1210 }

References ArmOpcode::a, DOTN_BIT, err, getreg(), regress::m, ArmOpcode::o, rd, S_BIT, shift(), and thumb_getshift().

Referenced by thumb_assemble().

◆ std_32bit_3reg()

static st8 std_32bit_3reg ( ArmOpcode ao,
ut64  m,
bool  shift 
)
static

Definition at line 1223 of file armass.c.

1223  {
1224  ut8 rd = getreg(ao->a[0]);
1225  ut8 rn = getreg(ao->a[1]);
1226  ut8 rm = getreg(ao->a[2]);
1227  if ((rd > 15) || (rn > 15) || (rm > 15) || (m & DOTN_BIT)) {
1228  return -1;
1229  }
1230  ao->o |= rd;
1231  ao->o |= rn << 24;
1232  ao->o |= rm << 8;
1233  if (shift) {
1234  err = false;
1235  ut32 shiftnum = thumb_getshift(ao->a[3]);
1236  if (err) {
1237  return -1;
1238  }
1239  ao->o |= shiftnum;
1240  }
1241  if (m & S_BIT) {
1242  ao->o |= 1 << 28;
1243  }
1244  return 4;
1245 }

References ArmOpcode::a, DOTN_BIT, err, getreg(), regress::m, ArmOpcode::o, rd, S_BIT, shift(), and thumb_getshift().

Referenced by thumb_assemble().

◆ std_opt_2()

static void std_opt_2 ( ArmOpcode ao)
static

Definition at line 1247 of file armass.c.

1247  {
1248  ao->a[2] = ao->a[1];
1249  ao->a[1] = ao->a[0];
1250 }

References ArmOpcode::a.

Referenced by thumb_assemble().

◆ std_opt_3()

static void std_opt_3 ( ArmOpcode ao)
static

Definition at line 1252 of file armass.c.

1252  {
1253  ao->a[3] = ao->a[2];
1254  ao->a[2] = ao->a[1];
1255  ao->a[1] = ao->a[0];
1256 }

References ArmOpcode::a.

Referenced by thumb_assemble().

◆ strcmpnull()

static int strcmpnull ( const char *  a,
const char *  b 
)
static

Definition at line 53 of file armass.c.

53  {
54  return (a && b) ? strcmp(a, b) : -1;
55 }

References a, and b.

Referenced by arm_assemble(), arm_opcode_cond(), getreg(), parse_hints(), and thumb_assemble().

◆ thumb_assemble()

static int thumb_assemble ( ArmOpcode ao,
ut64  off,
const char *  str 
)
static

Definition at line 1259 of file armass.c.

1259  {
1260  ut64 m;
1261  ao->o = UT32_MAX;
1262  if (!strcmpnull(ao->op, "udf")) {
1263  ao->o = 0xde;
1264  ao->o |= getnum(ao->a[0]) << 8;
1265  return 2;
1266  } else if ((m = opmask(ao->op, "add", S_BIT | W_BIT))) {
1267  ut64 argt = thumb_selector(ao->a);
1268  switch (argt) {
1269  case THUMB_REG_CONST: {
1270  std_opt_2(ao);
1271  }
1272  // intentional fallthrough
1273  case THUMB_REG_REG_CONST: {
1274  ut8 reg1 = getreg(ao->a[0]);
1275  ut8 reg2 = getreg(ao->a[1]);
1276  ut32 num = getnum(ao->a[2]);
1277 
1278  if ((reg1 > 15) || (reg2 > 15)) {
1279  return -1;
1280  }
1281 
1282  if (reg2 == 13) {
1283  if ((reg1 < 8) && (num < 1024) && (num % 4 == 0) && (!(m & DOTW_BIT)) && (!(m & W_BIT))) {
1284  ao->o = 0x00a8;
1285  ao->o |= reg1;
1286  ao->o |= (num >> 2) << 8;
1287  return 2;
1288  }
1289 
1290  if ((reg1 == 13) && (num < 512) && (num % 4 == 0) && (!(m & DOTW_BIT)) && (!(m & W_BIT))) {
1291  ao->o = 0x00b0;
1292  ao->o |= (num >> 2) << 8;
1293  return 2;
1294  }
1295 
1296  err = false;
1297  ut32 thnum = getthimmed12(ao->a[2]);
1298  if (!err && (!(m & W_BIT))) {
1299  ao->o = 0x0df10000;
1300  ao->o |= reg1;
1301  ao->o |= thnum;
1302  if (m & S_BIT) {
1303  ao->o |= 1 << 28;
1304  }
1305  return 4;
1306  }
1307 
1308  if (num > 4095) {
1309  return -1;
1310  }
1311 
1312  ao->o = 0x0df20000;
1313  ao->o |= reg1;
1314  ao->o |= getthzeroimmed12(num);
1315  return 4;
1316  }
1317 
1318  if (num < 8) {
1319  ao->o = 0x001c;
1320  ao->o |= (num & 0x3) << 14;
1321  ao->o |= (num >> 2);
1322  if (std_16bit_2reg(ao, m)) {
1323  return 2;
1324  }
1325  }
1326 
1327  if ((reg1 < 8) && (reg1 == reg2) && (num < 256)) {
1328  ao->o = 0x0030;
1329  ao->o |= reg1;
1330  ao->o |= num << 8;
1331  return 2;
1332  }
1333 
1334  err = false;
1335  ut32 thnum = getthimmed12(ao->a[2]);
1336  if (!err && (!(m & W_BIT))) {
1337  ao->o = 0x00f10000;
1338  ao->o |= thnum;
1339  return std_32bit_2reg(ao, m, false);
1340  }
1341 
1342  if (num > 4095) {
1343  return -1;
1344  }
1345 
1346  ao->o = 0x00f20000;
1347  ao->o |= getthzeroimmed12(num);
1348  return std_32bit_2reg(ao, m, false);
1349  } break;
1350  case THUMB_REG_REG: {
1351  std_opt_2(ao);
1352  }
1353  // intentional fallthrough
1354  case THUMB_REG_REG_REG: {
1355  ao->a[3] = "lsl 0";
1356  }
1357  // intentional fallthrough
1358  case THUMB_REG_REG_SHIFT: {
1359  if (ao->a[3] == NULL) { // double fallthrough
1360  std_opt_3(ao);
1361  }
1362  }
1363  // intentional fallthrough
1364  case THUMB_REG_REG_REG_SHIFT: {
1365  ut8 reg1 = getreg(ao->a[0]);
1366  ut8 reg2 = getreg(ao->a[1]);
1367  ut8 reg3 = getreg(ao->a[2]);
1368  ut32 shift = thumb_getshift(ao->a[3]);
1369 
1370  if ((reg1 > 15) || (reg2 > 15) || (reg3 > 15)) {
1371  return -1;
1372  }
1373 
1374  if (reg2 == 13) {
1375  if ((reg1 == reg3) && (!(m & DOTW_BIT)) && (shift == 0)) {
1376  ao->o = 0x6844;
1377  ao->o |= (reg1 & 0x7) << 8;
1378  ao->o |= (reg1 >> 3) << 15;
1379  return 2;
1380  }
1381 
1382  if ((reg1 == 13) && (!(m & DOTW_BIT)) && (shift == 0)) {
1383  ao->o = 0x8544;
1384  ao->o |= reg3 << 11;
1385  return 2;
1386  }
1387 
1388  ao->o = 0x0deb0000;
1389  ao->o |= reg1;
1390  ao->o |= reg3 << 8;
1391  ao->o |= shift;
1392  if (m & S_BIT) {
1393  ao->o |= 1 << 28;
1394  }
1395  return 4;
1396  }
1397 
1398  if ((reg3 < 8) && (!(m & DOTW_BIT)) && (shift == 0)) {
1399  ao->o = 0x0018;
1400  ao->o |= (reg3 >> 2);
1401  ao->o |= (reg3 & 0x3) << 14;
1402  if (std_16bit_2reg(ao, m)) {
1403  return 2;
1404  }
1405  }
1406 
1407  if ((reg1 == reg2) && (!(m & DOTW_BIT)) && (shift == 0)) {
1408  ao->o = 0x0044;
1409  ao->o |= (reg1 & 0x7) << 8;
1410  ao->o |= (reg1 >> 3) << 15;
1411  ao->o |= reg3 << 11;
1412  return 2;
1413  }
1414 
1415  ao->o = 0x00eb0000;
1416  return std_32bit_3reg(ao, m, true);
1417  } break;
1418  default:
1419  return -1;
1420  }
1421  } else if ((m = opmask(ao->op, "adc", S_BIT))) {
1422  ut64 argt = thumb_selector(ao->a);
1423  switch (argt) {
1424  case THUMB_REG_CONST: {
1425  std_opt_2(ao);
1426  }
1427  // intentional fallthrough
1428  case THUMB_REG_REG_CONST: {
1429  ao->o = 0x40f10000;
1430  ao->o |= getthimmed12(ao->a[2]);
1431  return std_32bit_2reg(ao, m, false);
1432  } break;
1433  case THUMB_REG_REG: {
1434  ao->o = 0x4041;
1435  if (std_16bit_2reg(ao, m)) {
1436  return 2;
1437  }
1438  std_opt_2(ao);
1439  }
1440  // intentional fallthrough
1441  case THUMB_REG_REG_REG: {
1442  ao->o = 0x40eb0000;
1443  return std_32bit_3reg(ao, m, false);
1444  } break;
1445  case THUMB_REG_REG_SHIFT: {
1446  std_opt_3(ao);
1447  }
1448  // intentional fallthrough
1449  // a bit naughty, perhaps?
1450  case THUMB_REG_REG_REG_SHIFT: {
1451  ao->o = 0x40eb0000;
1452  return std_32bit_3reg(ao, m, true);
1453  } break;
1454  default:
1455  return -1;
1456  }
1457  } else if ((m = opmask(ao->op, "adr", 0))) {
1458  ut64 argt = thumb_selector(ao->a);
1459  switch (argt) {
1460  case THUMB_REG_CONST: {
1461  ut8 reg = getreg(ao->a[0]);
1462  st32 label = getnum(ao->a[1]);
1463  if (!(m & DOTW_BIT) && (reg < 8) && (label < 1024) && (label >= 0) && (label % 4 == 0)) {
1464  ao->o = 0x00a0;
1465  ao->o |= reg;
1466  ao->o |= (label / 4) << 8;
1467  return 2;
1468  } else if ((label < 0) && (label > -4096)) {
1469  if (m & DOTN_BIT) {
1470  // this is explicitly an error
1471  return -1;
1472  }
1473  ao->o = 0xaff20000;
1474  ao->o |= reg;
1475  ao->o |= getthzeroimmed12(-label);
1476  return 4;
1477  } else if ((label > 0) && (label < 4096)) {
1478  if (m & DOTN_BIT) {
1479  // this is explicitly an error
1480  return -1;
1481  }
1482  ao->o = 0x0ff20000;
1483  ao->o |= reg;
1484  ao->o |= getthzeroimmed12(label);
1485  return 4;
1486  }
1487  return -1;
1488  } break;
1489  default:
1490  return -1;
1491  }
1492  } else if ((m = opmask(ao->op, "and", S_BIT))) {
1493  ut64 argt = thumb_selector(ao->a);
1494  switch (argt) {
1495  case THUMB_REG_REG: {
1496  ao->o = 0x0040;
1497  if (std_16bit_2reg(ao, m)) {
1498  return 2;
1499  }
1500  std_opt_2(ao);
1501  }
1502  // intentional fallthrough
1503  case THUMB_REG_REG_REG: {
1504  ao->o = 0x00ea0000;
1505  return std_32bit_3reg(ao, m, false);
1506  } break;
1507  case THUMB_REG_CONST: {
1508  std_opt_2(ao);
1509  }
1510  // intentional fallthrough
1511  case THUMB_REG_REG_CONST: {
1512  ut32 imm = getthimmed12(ao->a[2]);
1513  ao->o = 0x00f00000;
1514  ao->o |= imm;
1515  return std_32bit_2reg(ao, m, false);
1516  } break;
1517  case THUMB_REG_REG_SHIFT: {
1518  std_opt_3(ao);
1519  }
1520  // intentional fallthrough
1521  case THUMB_REG_REG_REG_SHIFT: {
1522  ao->o = 0x00ea0000;
1523  return std_32bit_3reg(ao, m, true);
1524  } break;
1525  default:
1526  return -1;
1527  }
1528  } else if ((m = opmask(ao->op, "asr", S_BIT))) {
1529  ut64 argt = thumb_selector(ao->a);
1530  switch (argt) {
1531  case THUMB_REG_REG_CONST: {
1532  ut8 reg1 = getreg(ao->a[0]);
1533  ut8 reg2 = getreg(ao->a[1]);
1534  ut32 imm = getnum(ao->a[2]);
1535  if (((int)imm < 1) && ((int)imm > 32)) {
1536  return -1;
1537  }
1538  ao->o = 0x0010;
1539  ao->o |= (imm & 0x3) << 14;
1540  ao->o |= (imm & 0x1c) >> 2;
1541  if (std_16bit_2reg(ao, m)) {
1542  return 2;
1543  }
1544  ao->o = 0x4fea2000;
1545  ao->o |= reg1;
1546  ao->o |= reg2 << 8;
1547  ao->o |= (imm & 0x3) << 14;
1548  ao->o |= (imm & 0x1c) << 2;
1549  if (m & S_BIT) {
1550  ao->o |= 1 << 28;
1551  }
1552  return 4;
1553  } break;
1554  case THUMB_REG_REG: {
1555  ao->o = 0x0041;
1556  if (std_16bit_2reg(ao, m)) {
1557  return 2;
1558  }
1559  std_opt_2(ao);
1560  }
1561  // intentional fallthrough
1562  case THUMB_REG_REG_REG: {
1563  ao->o = 0x40fa00f0;
1564  return std_32bit_3reg(ao, m, false);
1565  } break;
1566  default:
1567  return -1;
1568  }
1569  } else if ((m = opmask(ao->op, "b", 0))) {
1570  ut64 argt = thumb_selector(ao->a);
1571  switch (argt) {
1572  case THUMB_CONST: {
1573  st32 offset = thumb_getoffset(ao->a[0], off);
1574  if (offset % 2 != 0) {
1575  return -1;
1576  }
1577 
1578  if ((m & C_BITS) == C_BITS) {
1579  if ((offset >= -2048) && (offset <= 2046) && (!(m & DOTW_BIT))) {
1580  ao->o = 0x00e0;
1581  ao->o |= ((offset / 2 & 0xff) << 8);
1582  ao->o |= ((offset / 2 & 0x700) >> 8);
1583  return 2;
1584  }
1585  if ((offset < -16777216) || (offset > 16777214) || (offset % 2 != 0)) {
1586  return -1;
1587  }
1588  ao->o = 0x00f00090;
1589  ao->o |= getthbimmed(offset);
1590  return 4;
1591  } else {
1592  if ((offset >= -256) && (offset <= 254) && (!(m & DOTW_BIT))) {
1593  ao->o = 0x00d0;
1594  ao->o |= (ut16)((offset / 2) << 8);
1595  ao->o |= ((m & C_BITS) >> 2);
1596  return 2;
1597  }
1598  if ((offset < -1048576) || (offset > 1048574) || (offset % 2 != 0)) {
1599  return -1;
1600  }
1601 
1602  ao->o = 0x00f00080;
1603  ao->o |= (ut32)(offset & 0x80000) >> 16;
1604  ao->o |= (ut32)(offset & 0x40000) >> 13;
1605  ao->o |= (ut32)(offset & 0x3f000) << 12;
1606  ao->o |= (ut32)(offset & 0xe00) >> 9;
1607  ao->o |= (ut32)(offset & 0x1fe) << 7;
1608  if (offset < 0) {
1609  ao->o |= 1 << 18;
1610  }
1611  ao->o |= (((m & C_BITS) & 0xc) << 28);
1612  ao->o |= (((m & C_BITS) & 0x30) << 12);
1613  return 4;
1614  }
1615  } break;
1616  default:
1617  return -1;
1618  }
1619  } else if (opmask(ao->op, "bl", 0)) {
1620  ut64 argt = thumb_selector(ao->a);
1621  switch (argt) {
1622  case THUMB_CONST: {
1623  st32 offset = thumb_getoffset(ao->a[0], off);
1624  ao->o = 0x00f000d0;
1625  if ((offset > 16777214) || (offset < -16777216) || (offset % 2 != 0)) {
1626  return -1;
1627  }
1628  ao->o |= getthbimmed(offset);
1629  return 4;
1630  } break;
1631  default:
1632  return -1;
1633  }
1634  } else if (opmask(ao->op, "bx", 0)) {
1635  ut64 argt = thumb_selector(ao->a);
1636  switch (argt) {
1637  case THUMB_REG: {
1638  ut32 reg1 = getreg(ao->a[0]);
1639  ao->o = 0x0047;
1640  ao->o |= reg1 << 11;
1641  return 2;
1642  } break;
1643  default:
1644  return -1;
1645  }
1646  } else if (opmask(ao->op, "blx", 0)) {
1647  ut64 argt = thumb_selector(ao->a);
1648  switch (argt) {
1649  case THUMB_REG: {
1650  ut32 reg1 = getreg(ao->a[0]);
1651  ao->o = 0x8047;
1652  ao->o |= reg1 << 11;
1653  return 2;
1654  } break;
1655  case THUMB_CONST: {
1656  st32 offset = thumb_getoffset(ao->a[0], off);
1657  ao->o = 0x00f000c0;
1658  if ((offset > 16777214) || (offset < -16777216) || (offset % 2 != 0)) {
1659  return -1;
1660  }
1661  offset += off & 0x2; // (Align(PC,4)
1662  ao->o |= getthbimmed(offset);
1663  return 4;
1664  } break;
1665  default:
1666  return -1;
1667  }
1668  } else if ((m = opmask(ao->op, "bfc", 0))) {
1669  ut64 argt = thumb_selector(ao->a);
1670  switch (argt) {
1671  case THUMB_REG_CONST_CONST: {
1672  if (m & DOTN_BIT) {
1673  // this is explicitly an error
1674  return -1;
1675  }
1676  ut8 reg1 = getreg(ao->a[0]);
1677  ut32 lsb = getnum(ao->a[1]);
1678  ut32 width = getnum(ao->a[2]);
1679  ut32 msb = lsb + width - 1;
1680  if ((lsb > 31) || (msb > 31)) {
1681  return -1;
1682  }
1683  ao->o = 0x6ff30000;
1684  ao->o |= reg1;
1685  ao->o |= ((lsb & 0x1c) << 2);
1686  ao->o |= ((lsb & 0x3) << 14);
1687  ao->o |= (msb << 8);
1688  return 4;
1689  } break;
1690  default:
1691  return -1;
1692  }
1693  } else if ((m = opmask(ao->op, "bfi", 0))) {
1694  ut64 argt = thumb_selector(ao->a);
1695  switch (argt) {
1697  ut32 lsb = getnum(ao->a[2]);
1698  ut32 width = getnum(ao->a[3]);
1699  ut32 msb = lsb + width - 1;
1700  if ((lsb > 31) || (msb > 31)) {
1701  return -1;
1702  }
1703  ao->o = 0x60f30000;
1704  ao->o |= ((lsb & 0x1c) << 2);
1705  ao->o |= ((lsb & 0x3) << 14);
1706  ao->o |= (msb << 8);
1707  return std_32bit_2reg(ao, m, false);
1708  } break;
1709  default:
1710  return -1;
1711  }
1712  } else if ((m = opmask(ao->op, "bic", S_BIT))) {
1713  ut64 argt = thumb_selector(ao->a);
1714  switch (argt) {
1715  case THUMB_REG_REG: {
1716  ao->o = 0x8043;
1717  if (std_16bit_2reg(ao, m)) {
1718  return 2;
1719  }
1720  std_opt_2(ao);
1721  }
1722  // intentional fallthrough
1723  case THUMB_REG_REG_REG: {
1724  ao->o = 0x20ea0000;
1725  return std_32bit_3reg(ao, m, false);
1726  } break;
1727  case THUMB_REG_CONST: {
1728  std_opt_2(ao);
1729  }
1730  // intentional fallthrough
1731  case THUMB_REG_REG_CONST: {
1732  ao->o = 0x20f00000;
1733  ao->o |= getthimmed12(ao->a[2]);
1734  return std_32bit_2reg(ao, m, false);
1735  } break;
1736  case THUMB_REG_REG_SHIFT: {
1737  std_opt_3(ao);
1738  }
1739  // intentional fallthrough
1740  case THUMB_REG_REG_REG_SHIFT: {
1741  ao->o = 0x20ea0000;
1742  return std_32bit_3reg(ao, m, true);
1743  } break;
1744  default:
1745  return -1;
1746  }
1747  } else if (opmask(ao->op, "bkpt", 0)) {
1748  ut64 argt = thumb_selector(ao->a);
1749  switch (argt) {
1750  case THUMB_CONST: {
1751  ut32 num = getnum(ao->a[0]);
1752  if (num > 255) {
1753  return -1;
1754  }
1755  ao->o = 0x00be;
1756  ao->o |= num << 8;
1757  return 2;
1758  } break;
1759  default:
1760  return -1;
1761  }
1762  } else if (opmask(ao->op, "cbnz", 0)) {
1763  ut64 argt = thumb_selector(ao->a);
1764  switch (argt) {
1765  case THUMB_REG_CONST: {
1766  ut8 reg1 = getreg(ao->a[0]);
1767  st32 offset = thumb_getoffset(ao->a[1], off);
1768  if ((reg1 > 7) || (offset > 127) || (offset % 2 != 0)) {
1769  return -1;
1770  }
1771  ao->o = 0x00b9;
1772  ao->o |= reg1 << 8;
1773  ao->o |= (offset & 0x3e) << 10;
1774  ao->o |= (offset & 0x40) >> 5;
1775  return 2;
1776  } break;
1777  default:
1778  return -1;
1779  }
1780  } else if (opmask(ao->op, "cbz", 0)) {
1781  ut64 argt = thumb_selector(ao->a);
1782  switch (argt) {
1783  case THUMB_REG_CONST: {
1784  ut8 reg1 = getreg(ao->a[0]);
1785  st32 offset = thumb_getoffset(ao->a[1], off);
1786  if ((reg1 > 7) || (offset > 127) || (offset % 2 != 0)) {
1787  return -1;
1788  }
1789  ao->o = 0x00b1;
1790  ao->o |= reg1 << 8;
1791  ao->o |= (offset & 0x3e) << 10;
1792  ao->o |= (offset & 0x40) >> 5;
1793  return 2;
1794  } break;
1795  default:
1796  return -1;
1797  }
1798  } else if ((m = opmask(ao->op, "cdp", TWO_BIT))) {
1799  ut64 argt = thumb_selector(ao->a);
1800  switch (argt) {
1802  ao->a[5] = "0";
1803  }
1804  // intentional fallthrough
1806  ut32 coproc = getcoproc(ao->a[0]);
1807  ut32 opc1 = getnum(ao->a[1]);
1808  ut8 reg1 = getcoprocreg(ao->a[2]);
1809  ut8 reg2 = getcoprocreg(ao->a[3]);
1810  ut8 reg3 = getcoprocreg(ao->a[4]);
1811  ut32 opc2 = getnum(ao->a[5]);
1812  if ((coproc > 15) || (opc1 > 15) || (opc2 > 7)) {
1813  return -1;
1814  }
1815  ao->o = 0x00ee0000;
1816  if (m & TWO_BIT) {
1817  ao->o |= 1 << 20;
1818  }
1819  ao->o |= coproc;
1820  ao->o |= opc1 << 28;
1821  ao->o |= reg1 << 4;
1822  ao->o |= reg2 << 24;
1823  ao->o |= reg3 << 8;
1824  ao->o |= opc2 << 13;
1825  return 4;
1826  } break;
1827  default:
1828  return -1;
1829  }
1830  } else if (opmask(ao->op, "clrex", 0)) {
1831  ut64 argt = thumb_selector(ao->a);
1832  switch (argt) {
1833  case THUMB_NONE: {
1834  ao->o = 0xbff32f8f;
1835  return 4;
1836  } break;
1837  default:
1838  return -1;
1839  }
1840  } else if ((m = opmask(ao->op, "clz", 0))) {
1841  ut64 argt = thumb_selector(ao->a);
1842  switch (argt) {
1843  case THUMB_REG_REG: {
1844  ao->o = 0xb0fa80f0;
1845  ao->a[2] = ao->a[1];
1846  return std_32bit_3reg(ao, m, false);
1847  } break;
1848  default:
1849  return -1;
1850  }
1851  } else if ((m = opmask(ao->op, "cmn", 0))) {
1852  ut64 argt = thumb_selector(ao->a);
1853  switch (argt) {
1854  case THUMB_REG_CONST: {
1855  ut8 reg1 = getreg(ao->a[0]);
1856  ut32 num = getthimmed12(ao->a[1]);
1857  ao->o = 0x10f1000f;
1858  ao->o |= reg1 << 24;
1859  ao->o |= num;
1860  return 4;
1861  } break;
1862  case THUMB_REG_REG: {
1863  ao->o = 0xc042;
1864  if (std_16bit_2reg(ao, m)) {
1865  return 2;
1866  }
1867  ao->a[2] = "lsl 0";
1868  }
1869  // intentional fallthrough
1870  case THUMB_REG_REG_SHIFT: {
1871  ao->o = 0x10eb000f;
1872  return std_32bit_2reg(ao, m, true);
1873  } break;
1874  default:
1875  return -1;
1876  }
1877  } else if ((m = opmask(ao->op, "cmp", 0))) {
1878  ut64 argt = thumb_selector(ao->a);
1879  switch (argt) {
1880  case THUMB_REG_CONST: {
1881  ut8 reg1 = getreg(ao->a[0]);
1882  ut32 num = getnum(ao->a[1]);
1883  if ((num < 256) && (!(m & DOTW_BIT))) {
1884  ao->o = 0x0028;
1885  ao->o |= reg1;
1886  ao->o |= num << 8;
1887  return 2;
1888  }
1889  num = getthimmed12(ao->a[1]);
1890  ao->o = 0xb0f1000f;
1891  ao->o |= reg1 << 24;
1892  ao->o |= num;
1893  return 4;
1894  } break;
1895  case THUMB_REG_REG: {
1896  ut8 reg1 = getreg(ao->a[0]);
1897  ut8 reg2 = getreg(ao->a[1]);
1898  ao->o = 0x8042;
1899  if (std_16bit_2reg(ao, m)) {
1900  return 2;
1901  }
1902  if (!(m & DOTW_BIT)) {
1903  ao->o = 0x0045;
1904  ao->o |= ((reg1 & 0x7) << 8);
1905  ao->o |= ((reg1 & 0x8) << 12);
1906  ao->o |= reg2 << 11;
1907  return 2;
1908  }
1909  ao->a[2] = "lsl 0";
1910  }
1911  // intentional fallthrough
1912  case THUMB_REG_REG_SHIFT: {
1913  ut8 reg1 = getreg(ao->a[0]);
1914  ut8 reg2 = getreg(ao->a[1]);
1915  ut32 shift = thumb_getshift(ao->a[2]);
1916  ao->o = 0xb0eb000f;
1917  ao->o |= reg1 << 24;
1918  ao->o |= reg2 << 8;
1919  ao->o |= shift;
1920  return 4;
1921  } break;
1922  default:
1923  return -1;
1924  }
1925  } else if ((m = opmask(ao->op, "cps", ID_BIT | IE_BIT))) {
1926  ut64 argt = thumb_selector(ao->a);
1927  switch (argt) {
1928  case THUMB_OTHER: {
1929  st8 aif = iflag(ao->a[0]);
1930  if (aif == -1) {
1931  return -1;
1932  }
1933  if (!(m & DOTW_BIT)) {
1934  ao->o = 0x60b6;
1935  ao->o |= aif << 8;
1936  if (m & ID_BIT) {
1937  ao->o |= 1 << 12;
1938  }
1939  return 2;
1940  }
1941  ao->a[1] = "0";
1942  }
1943  // intentional fallthrough
1944  case THUMB_OTHER_CONST: {
1945  st8 aif = iflag(ao->a[0]);
1946  ut8 mode = getnum(ao->a[1]);
1947  if ((mode > 31) || (aif == -1)) {
1948  return -1;
1949  }
1950  ao->o = 0xaff30085;
1951  ao->o |= mode << 8;
1952  ao->o |= aif << 13;
1953  if (m & ID_BIT) {
1954  ao->o |= 1 << 1;
1955  }
1956  return 4;
1957  } break;
1958  case THUMB_CONST: {
1959  ut8 mode = getnum(ao->a[0]);
1960  if ((m & ID_BIT) || (m & IE_BIT) || (mode > 31)) {
1961  return -1;
1962  }
1963  ao->o = 0xaff30081;
1964  ao->o |= mode << 8;
1965  return 4;
1966  } break;
1967  default:
1968  return -1;
1969  }
1970  } else if (opmask(ao->op, "dbg", 0)) {
1971  ut64 argt = thumb_selector(ao->a);
1972  switch (argt) {
1973  case THUMB_CONST: {
1974  ut32 option = getnum(ao->a[0]);
1975  if (option > 15) {
1976  return -1;
1977  }
1978  ao->o = 0xaff3f080;
1979  ao->o |= option << 8;
1980  return 4;
1981  }
1982  default:
1983  return -1;
1984  }
1985  } else if (opmask(ao->op, "dmb", 0)) {
1986  ut64 argt = thumb_selector(ao->a);
1987  switch (argt) {
1988  case THUMB_NONE: {
1989  ao->o = 0xbff35f8f;
1990  return 4;
1991  } break;
1992  case THUMB_OTHER: {
1993  rz_str_case(ao->a[0], false);
1994  if (strcmpnull(ao->a[0], "sy")) {
1995  return -1;
1996  }
1997  ao->a[0] = "15";
1998  }
1999  // intentional fallthrough
2000  case THUMB_CONST: {
2001  ut32 option = getnum(ao->a[0]);
2002  if (option != 15) {
2003  return -1;
2004  }
2005  ao->o = 0xbff3508f;
2006  ao->o |= option << 8;
2007  return 4;
2008  } break;
2009  default:
2010  return -1;
2011  }
2012  } else if (opmask(ao->op, "dsb", 0)) {
2013  ut64 argt = thumb_selector(ao->a);
2014  switch (argt) {
2015  case THUMB_NONE: {
2016  ao->o = 0xbff34f8f;
2017  return 4;
2018  }
2019  // intentional fallthrough
2020  case THUMB_OTHER: {
2021  rz_str_case(ao->a[0], false);
2022  if (!strcmpnull((ao->a[0] = parse_hints(ao->a[0])), "-1")) {
2023  return -1;
2024  }
2025  }
2026  // intentional fallthrough
2027  case THUMB_CONST: {
2028  ut32 option = getnum(ao->a[0]);
2029  if ((option != 6) && (option != 7) && (option != 14) && (option != 15)) {
2030  return -1;
2031  }
2032  ao->o = 0xbff3408f;
2033  ao->o |= option << 8;
2034  return 4;
2035  } break;
2036  default:
2037  return -1;
2038  }
2039  } else if ((m = opmask(ao->op, "eor", S_BIT))) {
2040  ut64 argt = thumb_selector(ao->a);
2041  switch (argt) {
2042  case THUMB_REG_CONST:
2043  std_opt_2(ao);
2044  // intentional fallthrough
2045  case THUMB_REG_REG_CONST: {
2046  err = false;
2047  ut32 imm = getthimmed12(ao->a[2]);
2048  if (err) {
2049  return -1;
2050  }
2051  ao->o = 0x80f00000;
2052  ao->o |= imm;
2053  return std_32bit_2reg(ao, m, false);
2054  } break;
2055  case THUMB_REG_REG: {
2056  ao->o = 0x4040;
2057  if (std_16bit_2reg(ao, m)) {
2058  return 2;
2059  }
2060  std_opt_2(ao);
2061  }
2062  // intentional fallthrough
2063  case THUMB_REG_REG_REG:
2064  ao->a[3] = "lsl 0";
2065  // intentional fallthrough
2066  case THUMB_REG_REG_REG_SHIFT: {
2067  ao->o = 0x80ea0000;
2068  return std_32bit_3reg(ao, m, true);
2069  } break;
2070  default:
2071  return -1;
2072  }
2073  } else if (opmask(ao->op, "isb", 0)) {
2074  ut64 argt = thumb_selector(ao->a);
2075  switch (argt) {
2076  case THUMB_NONE: {
2077  ao->o = 0xbff36f8f;
2078  return 4;
2079  }
2080  // intentional fallthrough
2081  case THUMB_OTHER: {
2082  rz_str_case(ao->a[0], false);
2083  if (strcmpnull(ao->a[0], "sy")) {
2084  return -1;
2085  }
2086  ao->a[0] = "15";
2087  }
2088  // intentional fallthrough
2089  case THUMB_CONST: {
2090  ut32 option = getnum(ao->a[0]);
2091  if (option != 15) {
2092  return -1;
2093  }
2094  ao->o = 0xbff3608f;
2095  ao->o |= option << 8;
2096  return 4;
2097  } break;
2098  default:
2099  return -1;
2100  }
2101  } else if ((m = itmask(ao->op))) {
2102  ut64 argt = thumb_selector(ao->a);
2103  switch (argt) {
2104  case THUMB_OTHER: {
2105  ut16 cond = 0;
2106  ut16 i;
2107 
2108  const char *conds[] = {
2109  "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
2110  "hi", "ls", "ge", "lt", "gt", "le", "al", "nv", 0
2111  };
2112  rz_str_case(ao->a[0], false);
2113  for (i = 0; conds[i]; i++) {
2114  if (!(strcmpnull(ao->a[0], conds[i]))) {
2115  cond = i;
2116  break;
2117  }
2118  }
2119 
2120  if (i == 16) {
2121  return -1;
2122  }
2123  ao->o = 0x00bf;
2124  ao->o |= cond << 12;
2125 
2126  ut8 nrcs = (m & 0x30) >> 4;
2127  ut8 thiset = 0;
2128 
2129  for (i = 0; i < nrcs; i++) {
2130  thiset = ((m & (1 << (3 - i))) >> (3 - i));
2131  ao->o |= ((cond & 0x1) ^ thiset) << (11 - i);
2132  }
2133  ao->o |= 1 << (11 - i);
2134  return 2;
2135  } break;
2136  default:
2137  return -1;
2138  }
2139  } else if ((m = opmask(ao->op, "ldc", TWO_BIT | L_BIT))) {
2140  ut64 argt = thumb_selector(ao->a);
2141  switch (argt) {
2143  ut8 proc = getcoproc(ao->a[0]);
2144  ut8 reg1 = getcoprocreg(ao->a[1]);
2145  ut8 reg2 = getregmemstart(ao->a[2]);
2146  st32 imm = getnummemend(ao->a[3]);
2147  ao->o = 0x10ed0000;
2148  if (m & L_BIT) {
2149  ao->o |= 1 << 30;
2150  }
2151  if (m & TWO_BIT) {
2152  ao->o |= 1 << 20;
2153  }
2154  if (imm < 0) {
2155  imm = -imm;
2156  } else {
2157  ao->o |= 1 << 31;
2158  }
2159  if ((proc > 15) || (reg1 > 15) || (reg2 > 15) || (imm > 1024) || (imm % 4 != 0)) {
2160  return -1;
2161  }
2162  ao->o |= proc;
2163  ao->o |= reg1 << 4;
2164  ao->o |= (imm >> 2) << 8;
2165  ao->o |= reg2 << 24;
2166  return 4;
2167  } break;
2169  ao->a[3] = "0";
2170  // intentional fallthrough
2172  ut8 proc = getcoproc(ao->a[0]);
2173  ut8 reg1 = getcoprocreg(ao->a[1]);
2174  ut8 reg2 = getregmemstartend(ao->a[2]);
2175  st32 imm = getnum(ao->a[3]);
2176  ao->o = 0x30ec0000;
2177  if (m & L_BIT) {
2178  ao->o |= 1 << 30;
2179  }
2180  if (m & TWO_BIT) {
2181  ao->o |= 1 << 20;
2182  }
2183  if (imm < 0) {
2184  imm = -imm;
2185  } else {
2186  ao->o |= 1 << 31;
2187  }
2188  if ((proc > 15) || (reg1 > 15) || (reg2 > 15) || (imm > 1024) || (imm % 4 != 0)) {
2189  return -1;
2190  }
2191  ao->o |= proc;
2192  ao->o |= reg1 << 4;
2193  ao->o |= (imm >> 2) << 8;
2194  ao->o |= reg2 << 24;
2195  return 4;
2196  } break;
2198  ut8 proc = getcoproc(ao->a[0]);
2199  ut8 reg1 = getcoprocreg(ao->a[1]);
2200  ut8 reg2 = getregmemstart(ao->a[2]);
2201  st32 imm = getnummemendbang(ao->a[3]);
2202  ao->o = 0x30ed0000;
2203  if (m & L_BIT) {
2204  ao->o |= 1 << 30;
2205  }
2206  if (m & TWO_BIT) {
2207  ao->o |= 1 << 20;
2208  }
2209  if (imm < 0) {
2210  imm = -imm;
2211  } else {
2212  ao->o |= 1 << 31;
2213  }
2214  if ((proc > 15) || (reg1 > 15) || (reg2 > 15) || (imm > 1024) || (imm % 4 != 0)) {
2215  return -1;
2216  }
2217  ao->o |= proc;
2218  ao->o |= reg1 << 4;
2219  ao->o |= (imm >> 2) << 8;
2220  ao->o |= reg2 << 24;
2221  return 4;
2222  } break;
2223  default:
2224  return -1;
2225  }
2226  } else if ((m = opmask(ao->op, "ldm", DB_BIT | EA_BIT | IA_BIT | FD_BIT))) {
2227  ut64 argt = thumb_selector(ao->a);
2228  switch (argt) {
2229  case THUMB_REGBANG_LIST: {
2230  ut8 reg1 = getregmembang(ao->a[0]);
2231  ut32 list = getreglist(ao->a[1]);
2232  if (!((m & DB_BIT) || (m & EA_BIT)) && !(list & 0xff00) && (reg1 < 8) && !(m & DOTW_BIT)) {
2233  ao->o = 0x00c8;
2234  ao->o |= reg1;
2235  if (list & (1 << reg1)) {
2236  list ^= 1 << (reg1);
2237  }
2238  ao->o |= (list & 0xff) << 8;
2239 
2240  return 2;
2241  }
2242  if (list & 0x2000) {
2243  return -1;
2244  }
2245  if ((m & DB_BIT) || (m & EA_BIT)) {
2246  ao->o = 0x30e90000;
2247  } else {
2248  // ldmia is the default!
2249  ao->o = 0xb0e80000;
2250  }
2251 
2252  ao->o |= reg1 << 24;
2253  ao->o |= (list & 0xff) << 8;
2254  ao->o |= (list & 0xff00) >> 8;
2255  return 4;
2256  } break;
2257  case THUMB_REG_LIST: {
2258  ut8 reg1 = getreg(ao->a[0]);
2259  ut32 list = getreglist(ao->a[1]);
2260  if (!((m & DB_BIT) || (m & EA_BIT)) && !(list & 0xff00) && (reg1 < 8) && !(m & DOTW_BIT)) {
2261  ao->o = 0x00c8;
2262  ao->o |= reg1;
2263  ao->o |= 1 << (reg1 + 8);
2264  ao->o |= (list & 0xff) << 8;
2265  return 2;
2266  }
2267  if (list & 0x2000) {
2268  return -1;
2269  }
2270 
2271  if ((m & DB_BIT) || (m & EA_BIT)) {
2272  ao->o = 0x10e90000;
2273  } else {
2274  ao->o = 0x90e80000;
2275  }
2276 
2277  ao->o |= reg1 << 24;
2278  ao->o |= (list & 0xff) << 8;
2279  ao->o |= (list & 0xff00) >> 8;
2280  return 4;
2281  } break;
2282  default:
2283  return -1;
2284  }
2285  } else if ((m = opmask(ao->op, "ldr", B_BIT | H_BIT | D_BIT | T_BIT | S_BIT))) {
2286  ut64 argt = thumb_selector(ao->a);
2287  ut32 ldrsel = m & (B_BIT | H_BIT | D_BIT);
2288  if ((m & S_BIT) && !(m & (B_BIT | H_BIT))) {
2289  return -1;
2290  }
2291  switch (argt) {
2292  case THUMB_REG_CONST:
2293  ao->a[2] = ao->a[1];
2294  strcat(ao->a[2], "]");
2295  ao->a[1] = "[r15";
2296  // intentional fallthrough
2298  if (ao->a[2] == NULL) { // double fallthrough
2299  ao->a[1][strlen(ao->a[1]) - 1] = '\0';
2300  ao->a[2] = "0]";
2301  }
2302  // intentional fallthrough
2304  ut8 reg1 = getreg(ao->a[0]);
2305  ut8 reg2 = getregmemstart(ao->a[1]);
2306  st32 num = getnummemend(ao->a[2]);
2307  if (ldrsel == 0) {
2308  if (m & T_BIT) {
2309  if ((num < 0) || (num > 255)) {
2310  return -1;
2311  }
2312  ao->o = 0x50f8000e;
2313  ao->o |= num << 8;
2314  return mem_32bit_2reg(ao, m);
2315  }
2316  if (reg2 == 15) {
2317  if ((num > 4095) || (num < -4095)) {
2318  return -1;
2319  }
2320  if ((reg1 < 8) && (num < 1024) && (num % 4 == 0)) {
2321  ao->o = 0x0048;
2322  ao->o |= reg1;
2323  ao->o |= (num >> 2) << 8;
2324  return 2;
2325  }
2326  ao->o = 0x5ff80000;
2327  if (num < 0) {
2328  num = -num;
2329  } else {
2330  ao->o |= 1 << 31;
2331  }
2332  ao->o |= reg1 << 4;
2333  ao->o |= (num & 0xff) << 8;
2334  ao->o |= (num & 0x0f00) >> 8;
2335  return 4;
2336  }
2337  if ((reg2 == 13) && (reg1 < 8) && (num >= 0) && (num < 1024) && (num % 4 == 0) && (!(m & DOTW_BIT))) {
2338  ao->o = 0x0098;
2339  ao->o |= reg1;
2340  ao->o |= (num >> 2) << 8;
2341  return 2;
2342  }
2343  if ((num >= 0) && (num < 128) && (num % 4 == 0)) {
2344  ao->o = 0x0068;
2345  ao->o |= (num >> 4);
2346  ao->o |= ((num >> 2) & 0x3) << 14;
2347  if (mem_16bit_2reg(ao, m)) {
2348  return 2;
2349  }
2350  }
2351  if ((num > 4095) || (num < -1023)) {
2352  return -1;
2353  }
2354  if (num >= 0) {
2355  ao->o = 0xd0f80000;
2356  ao->o |= (num & 0xff) << 8;
2357  ao->o |= (num & 0xf00) >> 8;
2358  return mem_32bit_2reg(ao, m);
2359  }
2360  ao->o = 0x50f8000c;
2361  ao->o |= (-num & 0xff) << 8;
2362  return mem_32bit_2reg(ao, m);
2363  } else if (ldrsel == B_BIT) {
2364  if (m & T_BIT) {
2365  if ((num < 0) || (num > 255)) {
2366  return -1;
2367  }
2368  ao->o = 0x10f8000e;
2369  if (m & S_BIT) {
2370  ao->o |= 1 << 16;
2371  }
2372  ao->o |= num << 8;
2373  return mem_32bit_2reg(ao, m);
2374  }
2375  if (reg2 == 15) {
2376  if ((num > 4095) || (num < -4095)) {
2377  return -1;
2378  }
2379  ao->o = 0x1ff80000;
2380  if (m & S_BIT) {
2381  ao->o |= 1 << 16;
2382  }
2383  if (num < 0) {
2384  num = -num;
2385  } else {
2386  ao->o |= 1 << 31;
2387  }
2388  ao->o |= reg1 << 4;
2389  ao->o |= (num & 0xff) << 8;
2390  ao->o |= (num & 0x0f00) >> 8;
2391  return 4;
2392  }
2393  if ((num >= 0) && (num < 32) && (!(m & S_BIT))) {
2394  ao->o = 0x0078;
2395  ao->o |= (num >> 2);
2396  ao->o |= (num & 0x3) << 14;
2397  if (mem_16bit_2reg(ao, m)) {
2398  return 2;
2399  }
2400  }
2401  if ((num > 4095) || (num < -255)) {
2402  return -1;
2403  }
2404  if (num >= 0) {
2405  ao->o = 0x90f80000;
2406  if (m & S_BIT) {
2407  ao->o |= 1 << 16;
2408  }
2409  ao->o |= (num & 0xff) << 8;
2410  ao->o |= (num & 0xf00) >> 8;
2411  return mem_32bit_2reg(ao, m);
2412  }
2413  ao->o = 0x10f8000c;
2414  if (m & S_BIT) {
2415  ao->o |= 1 << 16;
2416  }
2417  ao->o |= -num << 8;
2418  return mem_32bit_2reg(ao, m);
2419  } else if (ldrsel == H_BIT) {
2420  if (m & T_BIT) {
2421  if ((num < 0) || (num > 255)) {
2422  return -1;
2423  }
2424  ao->o = 0x30f8000e;
2425  if (m & S_BIT) {
2426  ao->o |= 1 << 16;
2427  }
2428  ao->o |= num << 8;
2429  return mem_32bit_2reg(ao, m);
2430  }
2431  if (reg2 == 15) {
2432  if ((num > 4095) || (num < -4095)) {
2433  return -1;
2434  }
2435  ao->o = 0x3ff80000;
2436  if (m & S_BIT) {
2437  ao->o |= 1 << 16;
2438  }
2439  if (num < 0) {
2440  num = -num;
2441  } else {
2442  ao->o |= 1 << 31;
2443  }
2444  ao->o |= reg1 << 4;
2445  ao->o |= (num & 0xff) << 8;
2446  ao->o |= (num & 0x0f00) >> 8;
2447  return 4;
2448  }
2449  if ((num >= 0) && (num < 64) && (num % 2 == 0) && (!(m & S_BIT))) {
2450  ao->o = 0x0088;
2451  ao->o |= (num >> 3);
2452  ao->o |= ((num >> 1) & 0x3) << 14;
2453  if (mem_16bit_2reg(ao, m)) {
2454  return 2;
2455  }
2456  }
2457  if ((num > 4095) || (num < -255)) {
2458  return -1;
2459  }
2460  if (num >= 0) {
2461  ao->o = 0xb0f80000;
2462  if (m & S_BIT) {
2463  ao->o |= 1 << 16;
2464  }
2465  ao->o |= (num & 0xff) << 8;
2466  ao->o |= (num & 0xf00) >> 8;
2467  return mem_32bit_2reg(ao, m);
2468  }
2469  ao->o = 0x30f8000c;
2470  if (m & S_BIT) {
2471  ao->o |= 1 << 16;
2472  }
2473  ao->o |= -num << 8;
2474  return mem_32bit_2reg(ao, m);
2475  } else {
2476  return -1;
2477  }
2478  } break;
2480  ut8 reg1 = getreg(ao->a[0]);
2481  ut8 reg2 = getregmemstartend(ao->a[1]);
2482  st32 num = getnum(ao->a[2]);
2483  if ((num < -255) || (num > 255)) {
2484  return -1;
2485  }
2486  if (ldrsel == 0) {
2487  ao->o = 0x50f80009;
2488  } else if (ldrsel == B_BIT) {
2489  ao->o = 0x10f80009;
2490  } else if (ldrsel == H_BIT) {
2491  ao->o = 0x30f80009;
2492  } else {
2493  return -1;
2494  }
2495  if (m & S_BIT) {
2496  ao->o |= 1 << 16;
2497  }
2498  if (num < 0) {
2499  num = -num;
2500  } else {
2501  ao->o |= 1 << 1;
2502  }
2503  ao->o |= num << 8;
2504  ao->o |= reg1 << 4;
2505  ao->o |= reg2 << 24;
2506  return 4;
2507  } break;
2509  st32 num = getnummemendbang(ao->a[2]);
2510  if ((num < -255) || (num > 255)) {
2511  return -1;
2512  }
2513  if (ldrsel == 0) {
2514  ao->o = 0x50f8000d;
2515  } else if (ldrsel == B_BIT) {
2516  ao->o = 0x10f8000d;
2517  } else if (ldrsel == H_BIT) {
2518  ao->o = 0x30f8000d;
2519  } else {
2520  return -1;
2521  }
2522  if (m & S_BIT) {
2523  ao->o |= 1 << 16;
2524  }
2525  if (num < 0) {
2526  num = -num;
2527  } else {
2528  ao->o |= 1 << 1;
2529  }
2530  ao->o |= num << 8;
2531  return mem_32bit_2reg(ao, m);
2532  } break;
2534  ut8 reg3 = getregmemend(ao->a[2]);
2535  if (reg3 < 8) {
2536  if (ldrsel == 0) {
2537  ao->o = 0x0058;
2538  } else if (ldrsel == B_BIT) {
2539  if (m & S_BIT) {
2540  ao->o = 0x0056;
2541  } else {
2542  ao->o = 0x005c;
2543  }
2544  } else if (ldrsel == H_BIT) {
2545  if (m & S_BIT) {
2546  ao->o = 0x005e;
2547  } else {
2548  ao->o = 0x005a;
2549  }
2550  } else {
2551  return -1;
2552  }
2553  ao->o |= (reg3 & 0x3) << 14;
2554  ao->o |= (reg3 & 0x4) >> 2;
2555  if (mem_16bit_2reg(ao, m)) {
2556  return 2;
2557  }
2558  }
2559  ao->a[2][strlen(ao->a[2]) - 1] = '\0';
2560  ao->a[3] = "lsl 0]";
2561  }
2562  // intentional fallthrough
2564  ut8 reg3 = getreg(ao->a[2]);
2565  ut32 shift = getshiftmemend(ao->a[3]);
2566 
2567  shift >>= 2;
2568  if (shift & 0xffffcfff) {
2569  return -1;
2570  }
2571 
2572  if (ldrsel == 0) {
2573  ao->o = 0x50f80000;
2574  } else if (ldrsel == B_BIT) {
2575  ao->o = 0x10f80000;
2576  } else if (ldrsel == H_BIT) {
2577  ao->o = 0x30f80000;
2578  } else {
2579  return -1;
2580  }
2581  if (m & S_BIT) {
2582  ao->o |= 1 << 16;
2583  }
2584  ao->o |= reg3 << 8;
2585  ao->o |= shift;
2586  return mem_32bit_2reg(ao, m);
2587  } break;
2589  ao->a[2][strlen(ao->a[2]) - 1] = '\0';
2590  ao->a[3] = "0]";
2591  }
2592  // intentional fallthrough
2594  ut8 reg1 = getreg(ao->a[0]);
2595  ut8 reg2 = getreg(ao->a[1]);
2596  ut8 reg3 = getregmemstart(ao->a[2]);
2597  st32 num = getnummemend(ao->a[3]);
2598 
2599  if ((num > 1020) || (num < -1020) || (num % 4 != 0) || (ldrsel != D_BIT)) {
2600  return -1;
2601  }
2602  ao->o = 0x50e90000;
2603  if (num < 0) {
2604  num = -num;
2605  } else {
2606  ao->o |= 1 << 31;
2607  }
2608  ao->o |= reg1 << 4;
2609  ao->o |= reg2;
2610  ao->o |= reg3 << 24;
2611  ao->o |= (num >> 2) << 8;
2612  return 4;
2613  } break;
2615  ut8 reg1 = getreg(ao->a[0]);
2616  ut8 reg2 = getreg(ao->a[1]);
2617  ut8 reg3 = getregmemstartend(ao->a[2]);
2618  st32 num = getnum(ao->a[3]);
2619  if ((num > 1020) || (num < -1020) || (num % 4 != 0) || (ldrsel != D_BIT)) {
2620  return -1;
2621  }
2622  ao->o = 0x70e80000;
2623  if (num < 0) {
2624  num = -num;
2625  } else {
2626  ao->o |= 1 << 31;
2627  }
2628  ao->o |= reg1 << 4;
2629  ao->o |= reg2;
2630  ao->o |= reg3 << 24;
2631  ao->o |= (num >> 2) << 8;
2632  return 4;
2633  } break;
2635  ut8 reg1 = getreg(ao->a[0]);
2636  ut8 reg2 = getreg(ao->a[1]);
2637  ut8 reg3 = getregmemstart(ao->a[2]);
2638  st32 num = getnummemendbang(ao->a[3]);
2639  if ((num > 1020) || (num < -1020) || (num % 4 != 0) || (ldrsel != D_BIT)) {
2640  return -1;
2641  }
2642  ao->o = 0x70e90000;
2643  if (num < 0) {
2644  num = -num;
2645  } else {
2646  ao->o |= 1 << 31;
2647  }
2648  ao->o |= reg1 << 4;
2649  ao->o |= reg2;
2650  ao->o |= reg3 << 24;
2651  ao->o |= (num >> 2) << 8;
2652  return 4;
2653  } break;
2654  default:
2655  return -1;
2656  }
2657  } else if ((m = opmask(ao->op, "ldrex", B_BIT | H_BIT | D_BIT))) {
2658  ut64 argt = thumb_selector(ao->a);
2659  ut32 ldrsel = m & (B_BIT | H_BIT | D_BIT);
2660  switch (argt) {
2661  case THUMB_REG_BRACKREGBRACK: {
2662  ut8 reg1 = getreg(ao->a[0]);
2663  ut8 reg2 = getregmemstartend(ao->a[1]);
2664 
2665  if (ldrsel == B_BIT) {
2666  ao->o = 0xd0e84f0f;
2667  ao->o |= reg1 << 4;
2668  ao->o |= reg2 << 24;
2669  return 4;
2670  } else if (ldrsel == H_BIT) {
2671  ao->o = 0xd0e85f0f;
2672  ao->o |= reg1 << 4;
2673  ao->o |= reg2 << 24;
2674  return 4;
2675  } else if (ldrsel == 0) {
2676  ao->a[1][strlen(ao->a[1]) - 1] = '\0';
2677  ao->a[2] = "0]";
2678  } else {
2679  return -1;
2680  }
2681  }
2682  // intentional fallthrough
2684  st32 num = getnummemend(ao->a[2]);
2685  if ((ldrsel != 0) || (num < 0) || (num > 1020) || (num % 4 != 0)) {
2686  return -1;
2687  }
2688  ao->o = 0x50e8000f;
2689  ao->o |= (num >> 2) << 8;
2690  return mem_32bit_2reg(ao, m);
2691  } break;
2693  ut8 reg1 = getreg(ao->a[0]);
2694  ut8 reg2 = getreg(ao->a[1]);
2695  ut8 reg3 = getregmemstartend(ao->a[2]);
2696  if (!(ldrsel & D_BIT)) {
2697  return -1;
2698  }
2699  ao->o = 0xd0e87f00;
2700  ao->o |= reg1 << 4;
2701  ao->o |= reg2;
2702  ao->o |= reg3 << 24;
2703  return 4;
2704  } break;
2705  default:
2706  return -1;
2707  }
2708  } else if ((m = opmask(ao->op, "lsl", S_BIT))) {
2709  ut64 argt = thumb_selector(ao->a);
2710  switch (argt) {
2711  case THUMB_REG_REG_CONST: {
2712  ut8 reg1 = getreg(ao->a[0]);
2713  ut8 reg2 = getreg(ao->a[1]);
2714  ut32 num = getnum(ao->a[2]);
2715  if (num > 32) {
2716  return -1;
2717  }
2718  ao->o = 0x0000;
2719  if (std_16bit_2reg(ao, m)) {
2720  ao->o |= (num & 0x03) << 14;
2721  ao->o |= num >> 2;
2722  return 2;
2723  }
2724  ao->o = 0x4fea0000;
2725  ao->o |= reg1;
2726  ao->o |= reg2 << 8;
2727  ao->o |= (num >> 2) << 4;
2728  ao->o |= (num & 0x3) << 14;
2729  if (m & S_BIT) {
2730  ao->o |= 1 << 28;
2731  }
2732  return 4;
2733  } break;
2734  case THUMB_REG_REG: {
2735  ao->o = 0x8040;
2736  if (std_16bit_2reg(ao, m)) {
2737  return 2;
2738  }
2739  std_opt_2(ao);
2740  }
2741  // intentional fallthrough
2742  case THUMB_REG_REG_REG: {
2743  ao->o = 0x00fa00f0;
2744  return std_32bit_3reg(ao, m, false);
2745  } break;
2746  default:
2747  return -1;
2748  }
2749  } else if ((m = opmask(ao->op, "lsr", S_BIT))) {
2750  ut64 argt = thumb_selector(ao->a);
2751  switch (argt) {
2752  case THUMB_REG_REG_CONST: {
2753  ut8 reg1 = getreg(ao->a[0]);
2754  ut8 reg2 = getreg(ao->a[1]);
2755  ut32 num = getnum(ao->a[2]);
2756  if (num > 32) {
2757  return -1;
2758  }
2759  ao->o = 0x0008;
2760  if (std_16bit_2reg(ao, m)) {
2761  ao->o |= (num & 0x03) << 14;
2762  ao->o |= num >> 2;
2763  return 2;
2764  }
2765  ao->o = 0x4fea1000;
2766  ao->o |= reg1;
2767  ao->o |= reg2 << 8;
2768  ao->o |= (num >> 2) << 4;
2769  ao->o |= (num & 0x3) << 14;
2770  if (m & S_BIT) {
2771  ao->o |= 1 << 28;
2772  }
2773  return 4;
2774  } break;
2775  case THUMB_REG_REG: {
2776  ao->o = 0xc040;
2777  if (std_16bit_2reg(ao, m)) {
2778  return 2;
2779  }
2780  std_opt_2(ao);
2781  }
2782  // intentional fallthrough
2783  case THUMB_REG_REG_REG: {
2784  ao->o = 0x20fa00f0;
2785  return std_32bit_3reg(ao, m, false);
2786  } break;
2787  default:
2788  return -1;
2789  }
2790  } else if ((m = opmask(ao->op, "mcr", RZ_BIT | TWO_BIT))) {
2791  ut64 argt = thumb_selector(ao->a);
2792  switch (argt) {
2794  ao->a[5] = "0";
2795  }
2796  // intentional fallthrough
2798  ut32 coproc = getcoproc(ao->a[0]);
2799  ut32 opc1 = getnum(ao->a[1]);
2800  ut32 reg1 = getreg(ao->a[2]);
2801  ut32 coreg1 = getcoprocreg(ao->a[3]);
2802  ut32 coreg2 = getcoprocreg(ao->a[4]);
2803  ut32 opc2 = getnum(ao->a[5]);
2804 
2805  if ((coproc > 15) || (opc1 > 7) || (reg1 > 15) || (coreg1 > 15) || (coreg2 > 15) || (opc2 > 7) || (m & RZ_BIT)) {
2806  return -1;
2807  }
2808 
2809  ao->o = 0x00ee1000;
2810  if (m & TWO_BIT) {
2811  ao->o |= 1 << 20;
2812  }
2813  ao->o |= coproc;
2814  ao->o |= opc1 << 29;
2815  ao->o |= reg1 << 4;
2816  ao->o |= coreg1 << 24;
2817  ao->o |= coreg2 << 8;
2818  ao->o |= opc2 << 13;
2819  return 4;
2820  } break;
2822  ut32 coproc = getcoproc(ao->a[0]);
2823  ut32 opc = getnum(ao->a[1]);
2824  ut32 reg1 = getreg(ao->a[2]);
2825  ut32 reg2 = getreg(ao->a[3]);
2826  ut32 coreg = getcoprocreg(ao->a[4]);
2827 
2828  if ((coproc > 15) || (opc > 15) || (reg1 > 15) || (reg2 > 15) || (coreg > 15) || (!(m & RZ_BIT))) {
2829  return -1;
2830  }
2831 
2832  ao->o = 0x40ec0000;
2833  if (m & TWO_BIT) {
2834  ao->o |= 1 << 20;
2835  }
2836  ao->o |= coproc;
2837  ao->o |= opc << 12;
2838  ao->o |= reg1 << 4;
2839  ao->o |= reg2 << 24;
2840  ao->o |= coreg << 8;
2841  return 4;
2842  } break;
2843  default:
2844  return -1;
2845  }
2846  } else if ((m = opmask(ao->op, "mla", 0))) {
2847  ut64 argt = thumb_selector(ao->a);
2848  switch (argt) {
2849  case THUMB_REG_REG_REG_REG: {
2850  ut32 reg4 = getreg(ao->a[3]);
2851  if (reg4 > 15) {
2852  return -1;
2853  }
2854  ao->o = 0x00fb0000;
2855  ao->o |= reg4 << 4;
2856 
2857  return std_32bit_3reg(ao, m, false);
2858  } break;
2859  default:
2860  return -1;
2861  }
2862  } else if ((m = opmask(ao->op, "mls", 0))) {
2863  ut64 argt = thumb_selector(ao->a);
2864  switch (argt) {
2865  case THUMB_REG_REG_REG_REG: {
2866  ut32 reg4 = getreg(ao->a[3]);
2867  if (reg4 > 15) {
2868  return -1;
2869  }
2870  ao->o = 0x00fb1000;
2871  ao->o |= reg4 << 4;
2872 
2873  return std_32bit_3reg(ao, m, false);
2874  } break;
2875  default:
2876  return -1;
2877  }
2878  } else if ((m = opmask(ao->op, "mov", S_BIT | W_BIT | T_BIT))) {
2879  ut64 argt = thumb_selector(ao->a);
2880  switch (argt) {
2881  case THUMB_REG_CONST: {
2882  ut32 reg1 = getreg(ao->a[0]);
2883  err = false;
2884  ut32 num = getnum(ao->a[1]);
2885 
2886  if (reg1 > 15) {
2887  return -1;
2888  }
2889 
2890  if ((m & W_BIT) || (m & T_BIT)) {
2891  ut32 wnum = getnum(ao->a[1]);
2892  if (wnum > 65535) {
2893  return -1;
2894  }
2895  ao->o = 0x40f20000;
2896  if (m & T_BIT) {
2897  ao->o |= 1 << 31;
2898  }
2899  ao->o |= reg1;
2900  ao->o |= getthzeroimmed16(wnum);
2901  return 4;
2902  }
2903 
2904  if (err) {
2905  return -1;
2906  }
2907 
2908  if ((num < 256) && (reg1 < 8) && (!(m & DOTW_BIT))) {
2909  ao->o = 0x0020;
2910  ao->o |= reg1;
2911  ao->o |= num << 8;
2912  return 2;
2913  }
2914 
2915  ao->o = 0x4ff00000;
2916  ao->o |= reg1;
2917  ao->o |= getthimmed12(ao->a[1]);
2918  if (m & S_BIT) {
2919  ao->o |= 1 << 28;
2920  }
2921  return 4;
2922  } break;
2923  case THUMB_REG_REG: {
2924  ut32 reg1 = getreg(ao->a[0]);
2925  ut32 reg2 = getreg(ao->a[1]);
2926 
2927  if ((reg1 > 15) || (reg2 > 15)) {
2928  return -1;
2929  }
2930 
2931  if ((!(m & S_BIT)) && (!(m & DOTW_BIT))) {
2932  ao->o = 0x0046;
2933  ao->o |= (reg1 & 0x7) << 8;
2934  ao->o |= (reg1 & 0x8) << 12;
2935  ao->o |= reg2 << 11;
2936  return 2;
2937  }
2938 
2939  if ((reg1 < 8) && (reg2 < 8) && (!(m & DOTW_BIT))) {
2940  ao->o = 0;
2941  ao->o |= reg1 << 8;
2942  ao->o |= reg2 << 11;
2943  return 2;
2944  }
2945 
2946  ao->o = 0x4fea0000;
2947  ao->o |= reg1;
2948  ao->o |= reg2 << 8;
2949  if (m & S_BIT) {
2950  ao->o |= 1 << 28;
2951  }
2952  return 4;
2953  } break;
2954  default:
2955  return -1;
2956  }
2957  } else if ((m = opmask(ao->op, "mrc", TWO_BIT))) {
2958  ut64 argt = thumb_selector(ao->a);
2959  switch (argt) {
2961  ao->a[5] = "0";
2962  }
2963  // intentional fallthrough
2965  ut32 coproc = getcoproc(ao->a[0]);
2966  ut32 opc1 = getnum(ao->a[1]);
2967  ut32 reg1 = getreg(ao->a[2]);
2968  ut32 coreg1 = getcoprocreg(ao->a[3]);
2969  ut32 coreg2 = getcoprocreg(ao->a[4]);
2970  ut32 opc2 = getnum(ao->a[5]);
2971 
2972  if ((coproc > 15) || (opc1 > 7) || (reg1 > 15) || (coreg1 > 15) || (coreg2 > 15) || (opc2 > 7)) {
2973  return -1;
2974  }
2975 
2976  ao->o = 0x10ee1000;
2977  if (m & TWO_BIT) {
2978  ao->o |= 1 << 20;
2979  }
2980  ao->o |= coproc;
2981  ao->o |= opc1 << 29;
2982  ao->o |= reg1 << 4;
2983  ao->o |= coreg1 << 24;
2984  ao->o |= coreg2 << 8;
2985  ao->o |= opc2 << 13;
2986  return 4;
2987  } break;
2988  default:
2989  return -1;
2990  }
2991  } else if ((m = opmask(ao->op, "mrrc", TWO_BIT))) {
2992  ut64 argt = thumb_selector(ao->a);
2993  switch (argt) {
2995  ut32 coproc = getcoproc(ao->a[0]);
2996  ut32 opc = getnum(ao->a[1]);
2997  ut32 reg1 = getreg(ao->a[2]);
2998  ut32 reg2 = getreg(ao->a[3]);
2999  ut32 coreg = getcoprocreg(ao->a[4]);
3000 
3001  if ((coproc > 15) || (opc > 15) || (reg1 > 15) || (reg2 > 15) || (coreg > 15)) {
3002  return -1;
3003  }
3004 
3005  ao->o = 0x50ec0000;
3006  if (m & TWO_BIT) {
3007  ao->o |= 1 << 20;
3008  }
3009  ao->o |= coproc;
3010  ao->o |= opc << 12;
3011  ao->o |= reg1 << 4;
3012  ao->o |= reg2 << 24;
3013  ao->o |= coreg << 8;
3014  return 4;
3015  } break;
3016  default:
3017  return -1;
3018  }
3019  } else if (opmask(ao->op, "mrs", 0)) {
3020  ut64 argt = thumb_selector(ao->a);
3021  switch (argt) {
3022  case THUMB_REG_OTHER: {
3023  ut32 reg1 = getreg(ao->a[0]);
3024  rz_str_case(ao->a[1], false);
3025 
3026  if (reg1 > 15) {
3027  return -1;
3028  }
3029 
3030  if ((!strcmp(ao->a[1], "cpsr")) || (!strcmp(ao->a[1], "apsr"))) {
3031  ao->o = 0xeff30080;
3032  ao->o |= reg1;
3033  return 4;
3034  }
3035 
3036  if (!strcmp(ao->a[1], "spsr")) {
3037  ao->o = 0xfff30080;
3038  ao->o |= reg1;
3039  return 4;
3040  }
3041 
3042  return -1;
3043  } break;
3044  default:
3045  return -1;
3046  }
3047  } else if (opmask(ao->op, "msr", 0)) {
3048  ut64 argt = thumb_selector(ao->a);
3049  switch (argt) {
3050  case THUMB_OTHER_REG: {
3051  rz_str_case(ao->a[0], false);
3052  ut8 spsr = 0;
3053  ut8 bank = interpret_msrbank(ao->a[0], &spsr);
3054  ut32 reg1 = getreg(ao->a[1]);
3055 
3056  if ((bank == 0) || (reg1 > 15)) {
3057  return -1;
3058  }
3059 
3060  ao->o = 0x80f30080;
3061  ao->o |= reg1 << 24;
3062  ao->o |= bank;
3063  if (spsr != 0) {
3064  ao->o |= 1 << 28;
3065  }
3066  return 4;
3067  } break;
3068  default:
3069  return -1;
3070  }
3071  } else if ((m = opmask(ao->op, "mul", 0))) {
3072  ut64 argt = thumb_selector(ao->a);
3073  switch (argt) {
3074  case THUMB_REG_REG: {
3075  std_opt_2(ao);
3076  }
3077  // intentional fallthrough
3078  case THUMB_REG_REG_REG: {
3079  ut8 reg1 = getreg(ao->a[0]);
3080  ut8 reg3 = getreg(ao->a[2]);
3081 
3082  ao->o = 0x4043;
3083  if ((reg1 == reg3) && (std_16bit_2reg(ao, m))) {
3084  return 2;
3085  }
3086 
3087  ao->o = 0x00fb00f0;
3088  return std_32bit_3reg(ao, m, false);
3089  } break;
3090  default:
3091  return -1;
3092  }
3093  } else if ((m = opmask(ao->op, "mvn", S_BIT))) {
3094  ut64 argt = thumb_selector(ao->a);
3095  switch (argt) {
3096  case THUMB_REG_CONST: {
3097  ut8 reg1 = getreg(ao->a[0]);
3098  err = false;
3099  ut32 num = getthimmed12(ao->a[1]);
3100 
3101  if ((reg1 > 15) || err) {
3102  return -1;
3103  }
3104 
3105  ao->o = 0x6ff00000;
3106  ao->o |= reg1;
3107  ao->o |= num;
3108  if (m & S_BIT) {
3109  ao->o |= 1 << 28;
3110  }
3111  return 4;
3112  } break;
3113  case THUMB_REG_REG: {
3114  ao->a[2] = "lsl 0";
3115  }
3116  // intentional fallthrough
3117  case THUMB_REG_REG_SHIFT: {
3118  ut8 reg1 = getreg(ao->a[0]);
3119  ut8 reg2 = getreg(ao->a[1]);
3120  ut32 shift = thumb_getshift(ao->a[2]);
3121 
3122  if ((reg1 > 15) || (reg2 > 15)) {
3123  return -1;
3124  }
3125 
3126  ao->o = 0xc043;
3127  if ((shift == 0) && (std_16bit_2reg(ao, m))) {
3128  return 2;
3129  }
3130 
3131  ao->o = 0x6fea0000;
3132  ao->o |= reg1;
3133  ao->o |= reg2 << 8;
3134  ao->o |= shift;
3135  if (m & S_BIT) {
3136  ao->o |= 1 << 28;
3137  }
3138  return 4;
3139  } break;
3140  default:
3141  return -1;
3142  }
3143  } else if ((m = opmask(ao->op, "nop", 0))) {
3144  ut64 argt = thumb_selector(ao->a);
3145  switch (argt) {
3146  case THUMB_NONE: {
3147  if (m & DOTW_BIT) {
3148  ao->o = 0xaff30080;
3149  return 4;
3150  }
3151  ao->o = 0x00bf;
3152  return 2;
3153  } break;
3154  default:
3155  return -1;
3156  }
3157  } else if ((m = opmask(ao->op, "orn", S_BIT))) {
3158  ut64 argt = thumb_selector(ao->a);
3159  switch (argt) {
3160  case THUMB_REG_CONST: {
3161  std_opt_2(ao);
3162  }
3163  // intentional fallthrough
3164  case THUMB_REG_REG_CONST: {
3165  err = false;
3166  ut32 num = getthimmed12(ao->a[2]);
3167 
3168  if (err) {
3169  return -1;
3170  }
3171 
3172  ao->o = 0x60f00000;
3173  ao->o |= num;
3174  return (std_32bit_2reg(ao, m, false));
3175  } break;
3176  case THUMB_REG_REG: {
3177  std_opt_2(ao);
3178  }
3179  // intentional fallthrough
3180  case THUMB_REG_REG_REG: {
3181  ao->a[3] = "lsl 0";
3182  }
3183  // intentional fallthrough
3184  case THUMB_REG_REG_SHIFT: {
3185  if (ao->a[3] == NULL) { // double fallthrough
3186  std_opt_3(ao);
3187  }
3188  }
3189  // intentional fallthrough
3190  case THUMB_REG_REG_REG_SHIFT: {
3191  ao->o = 0x60ea0000;
3192  return std_32bit_3reg(ao, m, true);
3193  } break;
3194  default:
3195  return -1;
3196  }
3197  } else if ((m = opmask(ao->op, "orr", S_BIT))) {
3198  ut64 argt = thumb_selector(ao->a);
3199  switch (argt) {
3200  case THUMB_REG_CONST: {
3201  std_opt_2(ao);
3202  }
3203  // intentional fallthrough
3204  case THUMB_REG_REG_CONST: {
3205  err = false;
3206  ut32 num = getthimmed12(ao->a[2]);
3207 
3208  if (err) {
3209  return -1;
3210  }
3211 
3212  ao->o = 0x40f00000;
3213  ao->o |= num;
3214  return std_32bit_2reg(ao, m, false);
3215  } break;
3216  case THUMB_REG_REG: {
3217  ao->o = 0x0043;
3218  if (std_16bit_2reg(ao, m)) {
3219  return 2;
3220  }
3221  std_opt_2(ao);
3222  }
3223  // intentional fallthrough
3224  case THUMB_REG_REG_REG: {
3225  ao->a[3] = "lsl 0";
3226  }
3227  // intentional fallthrough
3228  case THUMB_REG_REG_SHIFT: {
3229  if (ao->a[3] == NULL) { // double fallthrough
3230  std_opt_3(ao);
3231  }
3232  }
3233  // intentional fallthrough
3234  case THUMB_REG_REG_REG_SHIFT: {
3235  ao->o = 0x40ea0000;
3236  return (std_32bit_3reg(ao, m, true));
3237  } break;
3238  default:
3239  return -1;
3240  }
3241  } else if ((m = opmask(ao->op, "pkh", BT_BIT | TB_BIT))) {
3242  ut64 argt = thumb_selector(ao->a);
3243  switch (argt) {
3244  case THUMB_REG_REG: {
3245  std_opt_2(ao);
3246  }
3247  // intentional fallthrough
3248  case THUMB_REG_REG_REG: {
3249  if (m & TB_BIT) {
3250  ao->a[3] = "asr 0";
3251  } else if (m & BT_BIT) {
3252  ao->a[3] = "lsl 0";
3253  } else {
3254  return -1;
3255  }
3256  }
3257  // intentional fallthrough
3258  case THUMB_REG_REG_SHIFT: {
3259  if (ao->a[3] == NULL) { // double fallthrough
3260  std_opt_3(ao);
3261  }
3262  }
3263  // intentional fallthrough
3264  case THUMB_REG_REG_REG_SHIFT: {
3265  ut32 shift = thumb_getshift(ao->a[3]);
3266 
3267  if (((m & TB_BIT) && ((shift & 0x00003000) != 0x00002000)) || ((m & BT_BIT) && ((shift & 0x00003000) != 0)) || ((m & (TB_BIT | BT_BIT)) == 0)) {
3268  return -1;
3269  }
3270 
3271  ao->o = 0xc0ea0000;
3272  return (std_32bit_3reg(ao, m, true));
3273  } break;
3274  default:
3275  return -1;
3276  }
3277  } else if (opmask(ao->op, "pld", 0)) {
3278  ut64 argt = thumb_selector(ao->a);
3279  switch (argt) {
3281  ut8 reg1 = getregmemstart(ao->a[0]);
3282  st32 num = getnummemend(ao->a[1]);
3283 
3284  if (reg1 == 15) {
3285  if ((num < -4095) || (num > 4095)) {
3286  return -1;
3287  }
3288  ao->o = 0x1ff800f0;
3289  if (num > 0) {
3290  ao->o |= 1 << 31;
3291  } else {
3292  num = -num;
3293  }
3294  ao->o |= (num & 0x0ff) << 8;
3295  ao->o |= (num & 0xf00) >> 8;
3296  return 4;
3297  }
3298 
3299  if ((reg1 > 15) || (num < -255) || (num > 4095)) {
3300  return -1;
3301  }
3302 
3303  if (num > 0) {
3304  ao->o = 0x90f800f0;
3305  ao->o |= (num & 0x0ff) << 8;
3306  ao->o |= (num & 0xf00) >> 8;
3307  ao->o |= reg1 << 24;
3308  return 4;
3309  }
3310  num = -num;
3311  ao->o = 0x10f800fc;
3312  ao->o |= num << 8;
3313  ao->o |= reg1 << 24;
3314  return 4;
3315  } break;
3316  case THUMB_BRACKREG_REGBRACK: {
3317  ao->a[1][strlen(ao->a[1]) - 1] = '\0';
3318  ao->a[2] = "lsl 0]";
3319  }
3320  // intentional fallthrough
3322  ut8 reg1 = getregmemstart(ao->a[0]);
3323  ut8 reg2 = getreg(ao->a[1]);
3324  ut32 shift = getshiftmemend(ao->a[2]) >> 2;
3325 
3326  if ((reg1 > 15) || (reg2 > 15) || ((shift & 0xffffcfff) != 0)) {
3327  return -1;
3328  }
3329 
3330  ao->o = 0x10f800f0;
3331  ao->o |= reg1 << 24;
3332  ao->o |= reg2 << 8;
3333  ao->o |= shift;
3334  return 4;
3335  } break;
3336  default:
3337  return -1;
3338  }
3339  } else if (opmask(ao->op, "pli", 0)) {
3340  ut64 argt = thumb_selector(ao->a);
3341  switch (argt) {
3343  ut8 reg1 = getregmemstart(ao->a[0]);
3344  st32 num = getnummemend(ao->a[1]);
3345 
3346  if (reg1 == 15) {
3347  if ((num < -4095) || (num > 4095)) {
3348  return -1;
3349  }
3350  ao->o = 0x1ff900f0;
3351  if (num > 0) {
3352  ao->o |= 1 << 31;
3353  } else {
3354  num = -num;
3355  }
3356  ao->o |= (num & 0x0ff) << 8;
3357  ao->o |= (num & 0xf00) >> 8;
3358  return 4;
3359  }
3360 
3361  if ((reg1 > 15) || (num < -255) || (num > 4095)) {
3362  return -1;
3363  }
3364 
3365  if (num > 0) {
3366  ao->o = 0x90f900f0;
3367  ao->o |= (num & 0x0ff) << 8;
3368  ao->o |= (num & 0xf00) >> 8;
3369  ao->o |= reg1 << 24;
3370  return 4;
3371  }
3372  num = -num;
3373  ao->o = 0x10f900fc;
3374  ao->o |= num << 8;
3375  ao->o |= reg1 << 24;
3376  return 4;
3377  } break;
3378  case THUMB_BRACKREG_REGBRACK: {
3379  ao->a[1][strlen(ao->a[1]) - 1] = '\0';
3380  ao->a[2] = "lsl 0]";
3381  }
3382  // intentional fallthrough
3384  ut8 reg1 = getregmemstart(ao->a[0]);
3385  ut8 reg2 = getreg(ao->a[1]);
3386  ut32 shift = getshiftmemend(ao->a[2]) >> 2;
3387 
3388  if ((reg1 > 15) || (reg2 > 15) || ((shift & 0xffffcfff) != 0)) {
3389  return -1;
3390  }
3391 
3392  ao->o = 0x10f900f0;
3393  ao->o |= reg1 << 24;
3394  ao->o |= reg2 << 8;
3395  ao->o |= shift;
3396  return 4;
3397  } break;
3398  default:
3399  return -1;
3400  }
3401  } else if ((m = opmask(ao->op, "pop", 0))) {
3402  ut64 argt = thumb_selector(ao->a);
3403  switch (argt) {
3404  case THUMB_LIST: {
3405  st32 list = getreglist(ao->a[0]);
3406  if ((list <= 0) || ((list & (1 << 13)) != 0)) {
3407  return -1;
3408  }
3409  if ((!(m & DOTW_BIT)) && ((list & 0x00007f00) == 0)) {
3410  ao->o = 0x00bc;
3411  ao->o |= (list & 0x8000) >> 15;
3412  ao->o |= (list & 0xff) << 8;
3413  return 2;
3414  }
3415  ao->o = 0xbde80000;
3416  ao->o |= (list & 0xff00) >> 8;
3417  ao->o |= (list & 0xff) << 8;
3418  return 4;
3419  } break;
3420  default:
3421  return -1;
3422  }
3423  } else if ((m = opmask(ao->op, "push", 0))) {
3424  ut64 argt = thumb_selector(ao->a);
3425  switch (argt) {
3426  case THUMB_LIST: {
3427  st32 list = getreglist(ao->a[0]);
3428  if ((list <= 0) || ((list & 0x0000a000) != 0)) {
3429  return -1;
3430  }
3431  if ((!(m & DOTW_BIT)) && ((list & 0x00001f00) == 0)) {
3432  ao->o = 0x00b4;
3433  ao->o |= (list & 0x4000) >> 14;
3434  ao->o |= (list & 0xff) << 8;
3435  return 2;
3436  }
3437  ao->o = 0x2de90000;
3438  ao->o |= (list & 0xff00) >> 8;
3439  ao->o |= (list & 0xff) << 8;
3440  return 4;
3441  } break;
3442  default:
3443  return -1;
3444  }
3445  } else if ((m = opmask(ao->op, "qadd", EIGHT_BIT | SIXTEEN_BIT))) {
3446  ut64 argt = thumb_selector(ao->a);
3447  switch (argt) {
3448  case THUMB_REG_REG: {
3449  std_opt_2(ao);
3450  }
3451  // intentional fallthrough
3452  case THUMB_REG_REG_REG: {
3453  if (m & SIXTEEN_BIT) {
3454  ao->o = 0x90fa10f0;
3455  } else if (m & EIGHT_BIT) {
3456  ao->o = 0x80fa10f0;
3457  } else {
3458  ao->o = 0x80fa80f0;
3459  }
3460 
3461  return std_32bit_3reg(ao, m, false);
3462  } break;
3463  default:
3464  return -1;
3465  }
3466  } else if ((m = opmask(ao->op, "qasx", 0))) {
3467  ut64 argt = thumb_selector(ao->a);
3468  switch (argt) {
3469  case THUMB_REG_REG: {
3470  std_opt_2(ao);
3471  }
3472  // intentional fallthrough
3473  case THUMB_REG_REG_REG: {
3474  ao->o = 0xa0fa10f0;
3475  return std_32bit_3reg(ao, m, false);
3476  } break;
3477  default:
3478  return -1;
3479  }
3480  } else if ((m = opmask(ao->op, "qdadd", 0))) {
3481  ut64 argt = thumb_selector(ao->a);
3482  switch (argt) {
3483  case THUMB_REG_REG: {
3484  std_opt_2(ao);
3485  }
3486  // intentional fallthrough
3487  case THUMB_REG_REG_REG: {
3488  ao->o = 0x80fa90f0;
3489  return std_32bit_3reg(ao, m, false);
3490  } break;
3491  default:
3492  return -1;
3493  }
3494  } else if ((m = opmask(ao->op, "qdsub", 0))) {
3495  ut64 argt = thumb_selector(ao->a);
3496  switch (argt) {
3497  case THUMB_REG_REG: {
3498  std_opt_2(ao);
3499  }
3500  // intentional fallthrough
3501  case THUMB_REG_REG_REG: {
3502  ao->o = 0x80fab0f0;
3503  return std_32bit_3reg(ao, m, false);
3504  } break;
3505  default:
3506  return -1;
3507  }
3508  } else if ((m = opmask(ao->op, "qsax", 0))) {
3509  ut64 argt = thumb_selector(ao->a);
3510  switch (argt) {
3511  case THUMB_REG_REG: {
3512  std_opt_2(ao);
3513  }
3514  // intentional fallthrough
3515  case THUMB_REG_REG_REG: {
3516  ao->o = 0xe0fa10f0;
3517  return std_32bit_3reg(ao, m, false);
3518  } break;
3519  default:
3520  return -1;
3521  }
3522  } else if ((m = opmask(ao->op, "qsub", EIGHT_BIT | SIXTEEN_BIT))) {
3523  ut64 argt = thumb_selector(ao->a);
3524  switch (argt) {
3525  case THUMB_REG_REG: {
3526  std_opt_2(ao);
3527  }
3528  // intentional fallthrough
3529  case THUMB_REG_REG_REG: {
3530  if (m & SIXTEEN_BIT) {
3531  ao->o = 0xd0fa10f0;
3532  } else if (m & EIGHT_BIT) {
3533  ao->o = 0xc0fa10f0;
3534  } else {
3535  ao->o = 0x80faa0f0;
3536  }
3537  return std_32bit_3reg(ao, m, false);
3538  } break;
3539  default:
3540  return -1;
3541  }
3542  } else if ((m = opmask(ao->op, "rbit", 0))) {
3543  ut64 argt = thumb_selector(ao->a);
3544  switch (argt) {
3545  case THUMB_REG_REG: {
3546  ao->a[2] = ao->a[1];
3547  ao->o = 0x90faa0f0;
3548  return std_32bit_3reg(ao, m, false);
3549  } break;
3550  default:
3551  return -1;
3552  }
3553  } else if ((m = opmask(ao->op, "rev", SIXTEEN_BIT | SH_BIT))) {
3554  ut64 argt = thumb_selector(ao->a);
3555  switch (argt) {
3556  case THUMB_REG_REG: {
3557  if (m & SIXTEEN_BIT) {
3558  ao->o = 0x40ba;
3559  } else if (m & SH_BIT) {
3560  ao->o = 0xc0ba;
3561  } else {
3562  ao->o = 0x00ba;
3563  }
3564 
3565  if (std_16bit_2reg(ao, m)) {
3566  return 2;
3567  }
3568 
3569  if (m & SIXTEEN_BIT) {
3570  ao->o = 0x90fa90f0;
3571  } else if (m & SH_BIT) {
3572  ao->o = 0x90fab0f0;
3573  } else {
3574  ao->o = 0x90fa80f0;
3575  }
3576  ao->a[2] = ao->a[1];
3577  return std_32bit_3reg(ao, m, false);
3578  } break;
3579  default:
3580  return -1;
3581  }
3582  } else if ((m = opmask(ao->op, "rfe", IA_BIT | FD_BIT | DB_BIT | EA_BIT))) {
3583  ut64 argt = thumb_selector(ao->a);
3584  ut32 wb = 0;
3585  switch (argt) {
3586  case THUMB_REGBANG: {
3587  ao->a[0][strlen(ao->a[0]) - 1] = '\0';
3588  wb = 0x20000000;
3589  }
3590  // intentional fallthrough
3591  case THUMB_REG: {
3592  ut8 reg1 = getreg(ao->a[0]);
3593 
3594  if (reg1 > 15) {
3595  return -1;
3596  }
3597 
3598  if ((m & DB_BIT) || (m & EA_BIT)) {
3599  ao->o = 0x10e800c0;
3600  } else {
3601  ao->o = 0x90e900c0;
3602  }
3603 
3604  ao->o |= reg1 << 24;
3605  ao->o |= wb;
3606  return 4;
3607  } break;
3608  default:
3609  return -1;
3610  }
3611  } else if ((m = opmask(ao->op, "ror", S_BIT))) {
3612  ut64 argt = thumb_selector(ao->a);
3613  switch (argt) {
3614  case THUMB_REG_REG_CONST: {
3615  ut8 reg1 = getreg(ao->a[0]);
3616  ut8 reg2 = getreg(ao->a[1]);
3617  ut32 num = getnum(ao->a[2]);
3618 
3619  if ((reg1 > 15) || (reg2 > 15) || (num > 31) || (num < 1)) {
3620  return -1;
3621  }
3622 
3623  ao->o = 0x4fea3000;
3624  ao->o |= reg1;
3625  ao->o |= reg2 << 8;
3626  ao->o |= (num & 0x3) << 14;
3627  ao->o |= (num & 0x1c) << 2;
3628  if (m & S_BIT) {
3629  ao->o |= 1 << 28;
3630  }
3631  return 4;
3632  } break;
3633  case THUMB_REG_REG: {
3634  ao->o = 0xc041;
3635  if (std_16bit_2reg(ao, m)) {
3636  return 2;
3637  }
3638  std_opt_2(ao);
3639  }
3640  // intentional fallthrough
3641  case THUMB_REG_REG_REG: {
3642  ao->o = 0x60fa00f0;
3643  return (std_32bit_3reg(ao, m, false));
3644  } break;
3645  default:
3646  return -1;
3647  }
3648  } else if ((m = opmask(ao->op, "rrx", S_BIT))) {
3649  ut64 argt = thumb_selector(ao->a);
3650  switch (argt) {
3651  case THUMB_REG_REG: {
3652  ut8 reg1 = getreg(ao->a[0]);
3653  ut8 reg2 = getreg(ao->a[1]);
3654 
3655  if ((reg1 > 15) || (reg2 > 15)) {
3656  return -1;
3657  }
3658 
3659  ao->o = 0x4fea3000;
3660  ao->o |= reg1;
3661  ao->o |= reg2 << 8;
3662  if (m & S_BIT) {
3663  ao->o |= 1 << 28;
3664  }
3665  return 4;
3666  } break;
3667  default:
3668  return -1;
3669  }
3670  } else if ((m = opmask(ao->op, "rsb", S_BIT))) {
3671  ut64 argt = thumb_selector(ao->a);
3672  switch (argt) {
3673  case THUMB_REG_CONST: {
3674  std_opt_2(ao);
3675  }
3676  // intentional fallthrough
3677  case THUMB_REG_REG_CONST: {
3678  err = false;
3679  ut32 num = getthimmed12(ao->a[2]);
3680 
3681  if (err) {
3682  return -1;
3683  }
3684 
3685  ao->o = 0x4042;
3686  if ((num == 0) && std_16bit_2reg(ao, m)) {
3687  return 2;
3688  }
3689 
3690  ao->o = 0xc0f10000;
3691  ao->o |= num;
3692  return (std_32bit_2reg(ao, m, false));
3693  } break;
3694  case THUMB_REG_REG: {
3695  std_opt_2(ao);
3696  }
3697  // intentional fallthrough
3698  case THUMB_REG_REG_REG: {
3699  ao->a[3] = "lsl 0";
3700  }
3701  // intentional fallthrough
3702  case THUMB_REG_REG_SHIFT: {
3703  if (ao->a[3] == NULL) { // double fallthrough
3704  std_opt_3(ao);
3705  }
3706  }
3707  // intentional fallthrough
3708  case THUMB_REG_REG_REG_SHIFT: {
3709  ao->o = 0xc0eb0000;
3710  return (std_32bit_3reg(ao, m, true));
3711  } break;
3712  default:
3713  return -1;
3714  }
3715  } else if ((m = opmask(ao->op, "sadd", EIGHT_BIT | SIXTEEN_BIT))) {
3716  ut64 argt = thumb_selector(ao->a);
3717  switch (argt) {
3718  case THUMB_REG_REG: {
3719  std_opt_2(ao);
3720  }
3721  // intentional fallthrough
3722  case THUMB_REG_REG_REG: {
3723  if (m & SIXTEEN_BIT) {
3724  ao->o = 0x90fa00f0;
3725  } else if (m & EIGHT_BIT) {
3726  ao->o = 0x80fa00f0;
3727  } else {
3728  return -1;
3729  }
3730  return std_32bit_3reg(ao, m, false);
3731  } break;
3732  default:
3733  return -1;
3734  }
3735  } else if ((m = opmask(ao->op, "sasx", 0))) {
3736  ut64 argt = thumb_selector(ao->a);
3737  switch (argt) {
3738  case THUMB_REG_REG: {
3739  std_opt_2(ao);
3740  }
3741  // intentional fallthrough
3742  case THUMB_REG_REG_REG: {
3743  ao->o = 0xa0fa00f0;
3744  return std_32bit_3reg(ao, m, false);
3745  } break;
3746  default:
3747  return -1;
3748  }
3749  } else if ((m = opmask(ao->op, "sbc", S_BIT))) {
3750  ut64 argt = thumb_selector(ao->a);
3751  switch (argt) {
3752  case THUMB_REG_REG: {
3753  ao->o = 0x8041;
3754  if (std_16bit_2reg(ao, m)) {
3755  return 2;
3756  }
3757  std_opt_2(ao);
3758  }
3759  // intentional fallthrough
3760  case THUMB_REG_REG_REG: {
3761  ao->a[3] = "lsl 0";
3762  }
3763  // intentional fallthrough
3764  case THUMB_REG_REG_SHIFT: {
3765  if (ao->a[3] == NULL) { // double fallthrough
3766  std_opt_3(ao);
3767  }
3768  }
3769  // intentional fallthrough
3770  case THUMB_REG_REG_REG_SHIFT: {
3771  ao->o = 0x60eb0000;
3772  return std_32bit_3reg(ao, m, true);
3773  } break;
3774  case THUMB_REG_CONST: {
3775  std_opt_2(ao);
3776  }
3777  // intentional fallthrough
3778  case THUMB_REG_REG_CONST: {
3779  ao->o = 0x60f10000;
3780  err = false;
3781  ut32 num = getthimmed12(ao->a[2]);
3782 
3783  if (err) {
3784  return -1;
3785  }
3786  ao->o |= num;
3787 
3788  return std_32bit_2reg(ao, m, false);
3789  } break;
3790  default:
3791  return -1;
3792  }
3793  } else if ((m = opmask(ao->op, "sbfx", 0))) {
3794  ut64 argt = thumb_selector(ao->a);
3795  switch (argt) {
3797  ut32 lsb = getnum(ao->a[2]);
3798  ut32 width = getnum(ao->a[3]);
3799  ut32 msb = lsb + width - 1;
3800  if ((lsb > 31) || (msb > 31)) {
3801  return -1;
3802  }
3803  ao->o = 0x40f30000;
3804  ao->o |= ((lsb & 0x1c) << 2);
3805  ao->o |= ((lsb & 0x3) << 14);
3806  ao->o |= ((width - 1) << 8);
3807  return std_32bit_2reg(ao, m, false);
3808  } break;
3809  default:
3810  return -1;
3811  }
3812  } else if ((m = opmask(ao->op, "sdiv", 0))) {
3813  ut64 argt = thumb_selector(ao->a);
3814  switch (argt) {
3815  case THUMB_REG_REG: {
3816  std_opt_2(ao);
3817  }
3818  // intentional fallthrough
3819  case THUMB_REG_REG_REG: {
3820  ao->o = 0x90fbf0f0;
3821  return std_32bit_3reg(ao, m, false);
3822  } break;
3823  default:
3824  return -1;
3825  }
3826  } else if ((m = opmask(ao->op, "sel", 0))) {
3827  ut64 argt = thumb_selector(ao->a);
3828  switch (argt) {
3829  case THUMB_REG_REG: {
3830  std_opt_2(ao);
3831  }
3832  // intentional fallthrough
3833  case THUMB_REG_REG_REG: {
3834  ao->o = 0xa0fa80f0;
3835  return std_32bit_3reg(ao, m, false);
3836  } break;
3837  default:
3838  return -1;
3839  }
3840  } else if (opmask(ao->op, "setend", 0)) {
3841  ut64 argt = thumb_selector(ao->a);
3842  switch (argt) {
3843  case THUMB_OTHER: {
3844  rz_str_case(ao->a[0], false);
3845  ao->o = 0x50b6;
3846  if (!(strcmpnull(ao->a[0], "be"))) {
3847  ao->o |= 1 << 11;
3848  return 2;
3849  } else if (!(strcmpnull(ao->a[0], "le"))) {
3850  return 2;
3851  } else {
3852  return -1;
3853  }
3854  break;
3855  }
3856  default:
3857  return -1;
3858  }
3859  } else if ((m = opmask(ao->op, "sev", 0))) {
3860  ut64 argt = thumb_selector(ao->a);
3861  switch (argt) {
3862  case THUMB_NONE:
3863  if (m & DOTW_BIT) {
3864  ao->o = 0xaff30480;
3865  return 4;
3866  } else {
3867  ao->o = 0x40bf;
3868  return 2;
3869  }
3870  break;
3871  default:
3872  return -1;
3873  }
3874  } else if ((m = opmask(ao->op, "shadd", EIGHT_BIT | SIXTEEN_BIT))) {
3875  ut64 argt = thumb_selector(ao->a);
3876  switch (argt) {
3877  case THUMB_REG_REG: {
3878  std_opt_2(ao);
3879  }
3880  // intentional fallthrough
3881  case THUMB_REG_REG_REG: {
3882  if (m & SIXTEEN_BIT) {
3883  ao->o = 0x90fa20f0;
3884  } else if (m & EIGHT_BIT) {
3885  ao->o = 0x80fa20f0;
3886  } else {
3887  return -1;
3888  }
3889  return std_32bit_3reg(ao, m, false);
3890  } break;
3891  default:
3892  return -1;
3893  }
3894  } else if ((m = opmask(ao->op, "shasx", 0))) {
3895  ut64 argt = thumb_selector(ao->a);
3896  switch (argt) {
3897  case THUMB_REG_REG: {
3898  std_opt_2(ao);
3899  }
3900  // intentional fallthrough
3901  case THUMB_REG_REG_REG: {
3902  ao->o = 0xa0fa20f0;
3903  return std_32bit_3reg(ao, m, false);
3904  } break;
3905  default:
3906  return -1;
3907  }
3908  } else if ((m = opmask(ao->op, "shsax", 0))) {
3909  ut64 argt = thumb_selector(ao->a);
3910  switch (argt) {
3911  case THUMB_REG_REG: {
3912  std_opt_2(ao);
3913  }
3914  // intentional fallthrough
3915  case THUMB_REG_REG_REG: {
3916  ao->o = 0xe0fa20f0;
3917  return std_32bit_3reg(ao, m, false);
3918  } break;
3919  default:
3920  return -1;
3921  }
3922  } else if ((m = opmask(ao->op, "shsub", EIGHT_BIT | SIXTEEN_BIT))) {
3923  ut64 argt = thumb_selector(ao->a);
3924  switch (argt) {
3925  case THUMB_REG_REG: {
3926  std_opt_2(ao);
3927  }
3928  // intentional fallthrough
3929  case THUMB_REG_REG_REG: {
3930  if (m & SIXTEEN_BIT) {
3931  ao->o = 0xd0fa20f0;
3932  } else if (m & EIGHT_BIT) {
3933  ao->o = 0xc0fa20f0;
3934  } else {
3935  return -1;
3936  }
3937  return std_32bit_3reg(ao, m, false);
3938  } break;
3939  default:
3940  return -1;
3941  }
3942  } else if (opmask(ao->op, "smc", 0)) {
3943  ut64 argt = thumb_selector(ao->a);
3944  switch (argt) {
3945  case THUMB_CONST: {
3946  err = false;
3947  ut32 num = getnum(ao->a[0]);
3948 
3949  if (err || (num > 15)) {
3950  return -1;
3951  }
3952 
3953  ao->o = 0xf0f70080;
3954  ao->o |= num << 24;
3955  return 4;
3956  } break;
3957  default:
3958  return -1;
3959  }
3960  } else if ((m = opmask(ao->op, "smla", BB_BIT | BT_BIT | TB_BIT | TT_BIT | WB_BIT | WT_BIT | L_BIT | D_BIT | X_BIT))) {
3961  ut64 argt = thumb_selector(ao->a);
3962  switch (argt) {
3963  case THUMB_REG_REG_REG_REG: {
3964  ut8 reg1 = getreg(ao->a[0]);
3965  ut8 reg2 = getreg(ao->a[1]);
3966  ut8 reg3 = getreg(ao->a[2]);
3967  ut8 reg4 = getreg(ao->a[3]);
3968 
3969  if ((reg1 > 15) || (reg2 > 15) || (reg3 > 15) || (reg4 > 15) || (m & DOTN_BIT)) {
3970  return -1;
3971  }
3972  if (m & L_BIT) {
3973  if (m & BB_BIT) {
3974  ao->o = 0xc0fb8000;
3975  } else if (m & BT_BIT) {
3976  ao->o = 0xc0fb9000;
3977  } else if (m & TB_BIT) {
3978  ao->o = 0xc0fba000;
3979  } else if (m & TT_BIT) {
3980  ao->o = 0xc0fbb000;
3981  } else if (m & D_BIT) {
3982  ao->o = 0xc0fbc000;
3983  if (m & X_BIT) {
3984  ao->o |= 1 << 12;
3985  }
3986  } else {
3987  ao->o = 0xc0fb0000;
3988  }
3989  ao->o |= reg1 << 4;
3990  ao->o |= reg2;
3991  ao->o |= reg3 << 24;
3992  ao->o |= reg4 << 8;
3993  return 4;
3994  }
3995  if (m & BB_BIT) {
3996  ao->o = 0x10fb0000;
3997  ao->o |= reg4 << 4;
3998  return std_32bit_3reg(ao, m, false);
3999  }
4000  if (m & BT_BIT) {
4001  ao->o = 0x10fb1000;
4002  ao->o |= reg4 << 4;
4003  return std_32bit_3reg(ao, m, false);
4004  }
4005  if (m & TB_BIT) {
4006  ao->o = 0x10fb2000;
4007  ao->o |= reg4 << 4;
4008  return std_32bit_3reg(ao, m, false);
4009  }
4010  if (m & TT_BIT) {
4011  ao->o = 0x10fb3000;
4012  ao->o |= reg4 << 4;
4013  return std_32bit_3reg(ao, m, false);
4014  }
4015  if (m & D_BIT) {
4016  ao->o = 0x20fb0000;
4017  if (m & X_BIT) {
4018  ao->o |= 1 << 12;
4019  }
4020  ao->o |= reg4 << 4;
4021  return std_32bit_3reg(ao, m, false);
4022  }
4023  if (m & WB_BIT) {
4024  ao->o = 0x30fb0000;
4025  ao->o |= reg4 << 4;
4026  return std_32bit_3reg(ao, m, false);
4027  }
4028  if (m & WT_BIT) {
4029  ao->o = 0x30fb1000;
4030  ao->o |= reg4 << 4;
4031  return std_32bit_3reg(ao, m, false);
4032  }
4033  return -1;
4034  } break;
4035  default:
4036  return -1;
4037  }
4038  } else if ((m = opmask(ao->op, "smlsd", X_BIT))) {
4039  ut64 argt = thumb_selector(ao->a);
4040  switch (argt) {
4041  case THUMB_REG_REG_REG_REG: {
4042  ut8 reg4 = getreg(ao->a[3]);
4043 
4044  if (reg4 > 15) {
4045  return -1;
4046  }
4047  ao->o = 0x40fb0000;
4048  if (m & X_BIT) {
4049  ao->o |= 1 << 12;
4050  }
4051  ao->o |= reg4 << 4;
4052  return std_32bit_3reg(ao, m, false);
4053  } break;
4054  default:
4055  return -1;
4056  }
4057  } else if ((m = opmask(ao->op, "smlsld", X_BIT))) {
4058  ut64 argt = thumb_selector(ao->a);
4059  switch (argt) {
4060  case THUMB_REG_REG_REG_REG: {
4061  ut8 reg1 = getreg(ao->a[0]);
4062  ut8 reg2 = getreg(ao->a[1]);
4063  ut8 reg3 = getreg(ao->a[2]);
4064  ut8 reg4 = getreg(ao->a[3]);
4065 
4066  if ((reg1 > 15) || (reg2 > 15) || (reg3 > 15) || (reg4 > 15) || (m & DOTN_BIT)) {
4067  return -1;
4068  }
4069  ao->o = 0xd0fbc000;
4070 
4071  if (m & X_BIT) {
4072  ao->o |= 1 << 12;
4073  }
4074 
4075  ao->o |= reg1 << 4;
4076  ao->o |= reg2;
4077  ao->o |= reg3 << 24;
4078  ao->o |= reg4 << 8;
4079  return 4;
4080  } break;
4081  default:
4082  return -1;
4083  }
4084  } else if ((m = opmask(ao->op, "smmla", RZ_BIT))) {
4085  ut64 argt = thumb_selector(ao->a);
4086  switch (argt) {
4087  case THUMB_REG_REG_REG_REG: {
4088  ut8 reg4 = getreg(ao->a[3]);
4089 
4090  if (reg4 > 15) {
4091  return -1;
4092  }
4093  ao->o = 0x50fb0000;
4094  if (m & RZ_BIT) {
4095  ao->o |= 1 << 12;
4096  }
4097  ao->o |= reg4 << 4;
4098  return std_32bit_3reg(ao, m, false);
4099  } break;
4100  default:
4101  return -1;
4102  }
4103  } else if ((m = opmask(ao->op, "smmls", RZ_BIT))) {
4104  ut64 argt = thumb_selector(ao->a);
4105  switch (argt) {
4106  case THUMB_REG_REG_REG_REG: {
4107  ut8 reg4 = getreg(ao->a[3]);
4108 
4109  if (reg4 > 15) {
4110  return -1;
4111  }
4112  ao->o = 0x60fb0000;
4113  if (m & RZ_BIT) {
4114  ao->o |= 1 << 12;
4115  }
4116  ao->o |= reg4 << 4;
4117  return std_32bit_3reg(ao, m, false);
4118  } break;
4119  default:
4120  return -1;
4121  }
4122  } else if ((m = opmask(ao->op, "smmul", RZ_BIT))) {
4123  ut64 argt = thumb_selector(ao->a);
4124  switch (argt) {
4125  case THUMB_REG_REG: {
4126  std_opt_2(ao);
4127  }
4128  // intentional fallthrough
4129  case THUMB_REG_REG_REG: {
4130  ao->o = 0x50fb00f0;
4131  if (m & RZ_BIT) {
4132  ao->o |= 1 << 12;
4133  }
4134  return std_32bit_3reg(ao, m, false);
4135  } break;
4136  default:
4137  return -1;
4138  }
4139  } else if ((m = opmask(ao->op, "smuad", X_BIT))) {
4140  ut64 argt = thumb_selector(ao->a);
4141  switch (argt) {
4142  case THUMB_REG_REG: {
4143  std_opt_2(ao);
4144  }
4145  // intentional fallthrough
4146  case THUMB_REG_REG_REG: {
4147  ao->o = 0x20fb00f0;
4148  if (m & X_BIT) {
4149  ao->o |= 1 << 12;
4150  }
4151  return std_32bit_3reg(ao, m, false);
4152  } break;
4153  default:
4154  return -1;
4155  }
4156  } else if ((m = opmask(ao->op, "smul", BB_BIT | BT_BIT | TB_BIT | TT_BIT | WB_BIT | WT_BIT | L_BIT))) {
4157  ut64 argt = thumb_selector(ao->a);
4158  switch (argt) {
4159  case THUMB_REG_REG: {
4160  std_opt_2(ao);
4161  }
4162  // intentional fallthrough
4163  case THUMB_REG_REG_REG: {
4164  if (m & BB_BIT) {
4165  ao->o = 0x10fb00f0;
4166  } else if (m & BT_BIT) {
4167  ao->o = 0x10fb10f0;
4168  } else if (m & TB_BIT) {
4169  ao->o = 0x10fb20f0;
4170  } else if (m & TT_BIT) {
4171  ao->o = 0x10fb30f0;
4172  } else if (m & WB_BIT) {
4173  ao->o = 0x30fb00f0;
4174  } else if (m & WT_BIT) {
4175  ao->o = 0x30fb10f0;
4176  } else {
4177  return -1;
4178  }
4179  return std_32bit_3reg(ao, m, false);
4180  } break;
4181  case THUMB_REG_REG_REG_REG: {
4182  ut8 reg1 = getreg(ao->a[0]);
4183  ut8 reg2 = getreg(ao->a[1]);
4184  ut8 reg3 = getreg(ao->a[2]);
4185  ut8 reg4 = getreg(ao->a[3]);
4186 
4187  if ((reg1 > 15) || (reg2 > 15) || (reg3 > 15) || (reg4 > 15) || (m & DOTN_BIT) || (!(m & L_BIT))) {
4188  return -1;
4189  }
4190 
4191  ao->o = 0x80fb0000;
4192  ao->o |= reg1 << 4;
4193  ao->o |= reg2;
4194  ao->o |= reg3 << 24;
4195  ao->o |= reg4 << 8;
4196  return 4;
4197  } break;
4198  default:
4199  return -1;
4200  }
4201  } else if ((m = opmask(ao->op, "smusd", X_BIT))) {
4202  ut64 argt = thumb_selector(ao->a);
4203  switch (argt) {
4204  case THUMB_REG_REG: {
4205  std_opt_2(ao);
4206  }
4207  // intentional fallthrough
4208  case THUMB_REG_REG_REG: {
4209  ao->o = 0x40fb00f0;
4210  if (m & X_BIT) {
4211  ao->o |= 1 << 12;
4212  }
4213  return std_32bit_3reg(ao, m, false);
4214  } break;
4215  default:
4216  return -1;
4217  }
4218  } else if ((m = opmask(ao->op, "srs", DB_BIT | FD_BIT | IA_BIT | EA_BIT))) {
4219  ut32 w = 0;
4220  ut64 argt = thumb_selector(ao->a);
4221  switch (argt) {
4222  case THUMB_CONSTBANG: {
4223  ao->a[0][strlen(ao->a[0]) - 1] = '\0';
4224  w = 1;
4225  }
4226  // intentional fallthrough
4227  case THUMB_CONST: {
4228  ut32 num = getnum(ao->a[0]);
4229  if (num > 31) {
4230  return -1;
4231  }
4232  if ((m & DB_BIT) || (m & FD_BIT)) {
4233  ao->o = 0x0de800c0;
4234  } else {
4235  ao->o = 0x8de900c0;
4236  }
4237  ao->o |= num << 8;
4238  ao->o |= w << 29;
4239  return 4;
4240  } break;
4241  default:
4242  return -1;
4243  }
4244  } else if ((m = opmask(ao->op, "ssat", SIXTEEN_BIT))) {
4245  ut64 argt = thumb_selector(ao->a);
4246  switch (argt) {
4247  case THUMB_REG_CONST_REG: {
4248  ao->a[3] = "lsl 0";
4249  }
4250  // intentional fallthrough
4252  ut8 reg1 = getreg(ao->a[0]);
4253  ut32 num = getnum(ao->a[1]) - 1;
4254  ut8 reg2 = getreg(ao->a[2]);
4255  ut32 shift = thumb_getshift(ao->a[3]);
4256 
4257  if (err || (reg1 > 15) || (reg2 > 15) || (num > 31) || (shift & 0x00001000) || ((m & SIXTEEN_BIT) && shift)) {
4258  return -1;
4259  }
4260 
4261  if (shift & 0x00002000) {
4262  shift |= 0x20000000;
4263  shift &= 0xffffdfff;
4264  }
4265 
4266  if (m & SIXTEEN_BIT) {
4267  ao->o = 0x20f30000;
4268  } else {
4269  ao->o = 0x00f30000;
4270  }
4271 
4272  ao->o |= reg1;
4273  ao->o |= reg2 << 24;
4274  ao->o |= num << 8;
4275  ao->o |= shift;
4276  return 4;
4277  } break;
4278  default:
4279  return -1;
4280  }
4281  } else if ((m = opmask(ao->op, "ssax", 0))) {
4282  ut64 argt = thumb_selector(ao->a);
4283  switch (argt) {
4284  case THUMB_REG_REG: {
4285  std_opt_2(ao);
4286  }
4287  // intentional fallthrough
4288  case THUMB_REG_REG_REG: {
4289  ao->o = 0xe0fa00f0;
4290  return std_32bit_3reg(ao, m, false);
4291  } break;
4292  default:
4293  return -1;
4294  }
4295  } else if ((m = opmask(ao->op, "ssub", EIGHT_BIT | SIXTEEN_BIT))) {
4296  ut64 argt = thumb_selector(ao->a);
4297  switch (argt) {
4298  case THUMB_REG_REG: {
4299  std_opt_2(ao);
4300  }
4301  // intentional fallthrough
4302  case THUMB_REG_REG_REG: {
4303  if (m & EIGHT_BIT) {
4304  ao->o = 0xc0fa00f0;
4305  } else if (m & SIXTEEN_BIT) {
4306  ao->o = 0xd0fa00f0;
4307  } else {
4308  return -1;
4309  }
4310  return std_32bit_3reg(ao, m, false);
4311  } break;
4312  default:
4313  return -1;
4314  }
4315  } else if ((m = opmask(ao->op, "stc", L_BIT | TWO_BIT))) {
4316  ut64 argt = thumb_selector(ao->a);
4317  switch (argt) {
4319  ao->a[2][strlen(ao->a[2]) - 1] = '\0';
4320  ao->a[3] = "0]";
4321  }
4322  // intentional fallthrough
4324  ut8 coproc = getcoproc(ao->a[0]);
4325  ut8 coreg = getcoprocreg(ao->a[1]);
4326  ut8 reg = getregmemstart(ao->a[2]);
4327  st32 num = getnummemend(ao->a[3]);
4328 
4329  if ((coproc > 15) || (coreg > 15) || (reg > 15) || (num > 4092) || (num < -4092) || (num % 4 != 0)) {
4330  return -1;
4331  }
4332 
4333  ao->o = 0x00ed0000;
4334  if (m & L_BIT) {
4335  ao->o |= 1 << 30;
4336  }
4337  if (m & TWO_BIT) {
4338  ao->o |= 1 << 20;
4339  }
4340  if (num < 0) {
4341  num = -num;
4342  } else {
4343  ao->o |= 1 << 31;
4344  }
4345  ao->o |= coproc;
4346  ao->o |= coreg << 4;
4347  ao->o |= reg << 24;
4348  ao->o |= (num >> 2) << 8;
4349  return 4;
4350  } break;
4352  ut8 coproc = getcoproc(ao->a[0]);
4353  ut8 coreg = getcoprocreg(ao->a[1]);
4354  ut8 reg = getregmemstartend(ao->a[2]);
4355  st32 num = getnum(ao->a[3]);
4356 
4357  if ((coproc > 15) || (coreg > 15) || (reg > 15) || (num > 4092) || (num < -4092) || (num % 4 != 0)) {
4358  return -1;
4359  }
4360 
4361  ao->o = 0x20ec0000;
4362  if (m & L_BIT) {
4363  ao->o |= 1 << 30;
4364  }
4365  if (m & TWO_BIT) {
4366  ao->o |= 1 << 20;
4367  }
4368  if (num < 0) {
4369  num = -num;
4370  } else {
4371  ao->o |= 1 << 31;
4372  }
4373  ao->o |= coproc;
4374  ao->o |= coreg << 4;
4375  ao->o |= reg << 24;
4376  ao->o |= (num >> 2) << 8;
4377  return 4;
4378  } break;
4380  ut8 coproc = getcoproc(ao->a[0]);
4381  ut8 coreg = getcoprocreg(ao->a[1]);
4382  ut8 reg = getregmemstart(ao->a[2]);
4383  st32 num = getnummemendbang(ao->a[3]);
4384 
4385  if ((coproc > 15) || (coreg > 15) || (reg > 15) || (num > 4092) || (num < -4092) || (num % 4 != 0)) {
4386  return -1;
4387  }
4388 
4389  ao->o = 0x20ed0000;
4390  if (m & L_BIT) {
4391  ao->o |= 1 << 30;
4392  }
4393  if (m & TWO_BIT) {
4394  ao->o |= 1 << 20;
4395  }
4396  if (num < 0) {
4397  num = -num;
4398  } else {
4399  ao->o |= 1 << 31;
4400  }
4401  ao->o |= coproc;
4402  ao->o |= coreg << 4;
4403  ao->o |= reg << 24;
4404  ao->o |= (num >> 2) << 8;
4405  return 4;
4406  } break;
4407  default:
4408  return -1;
4409  }
4410  } else if ((m = opmask(ao->op, "stm", FD_BIT | DB_BIT | IA_BIT | EA_BIT))) {
4411  ut64 argt = thumb_selector(ao->a);
4412  bool wb = false;
4413  switch (argt) {
4414  case THUMB_REGBANG_LIST: {
4415  wb = true;
4416  ao->a[0][strlen(ao->a[0]) - 1] = '\0';
4417  }
4418  // intentional fallthrough
4419  case THUMB_REG_LIST: {
4420  ut8 reg = getreg(ao->a[0]);
4421  st32 list = getreglist(ao->a[1]);
4422  if ((list <= 0) || ((list & 0x0000a000) != 0)) {
4423  return -1;
4424  }
4425 
4426  if ((!(m & DOTW_BIT)) && ((list & 0x0000ff00) == 0) && (!(m & (FD_BIT | DB_BIT))) && wb) {
4427  ao->o = 0x00c0;
4428  ao->o |= (list & 0x000000ff) << 8;
4429  ao->o |= reg;
4430  return 2;
4431  }
4432 
4433  if ((m & (FD_BIT | DB_BIT | IA_BIT | EA_BIT)) == 0) {
4434  return -1;
4435  }
4436 
4437  if (m & (FD_BIT | DB_BIT)) {
4438  ao->o = 0x00e90000;
4439  } else {
4440  ao->o = 0x80e80000;
4441  }
4442 
4443  if (wb) {
4444  ao->o |= 1 << 29;
4445  }
4446 
4447  ao->o |= reg << 24;
4448  ao->o |= (list & 0x000000ff) << 8;
4449  ao->o |= (list & 0x0000ff00) >> 8;
4450  return 4;
4451  } break;
4452  default:
4453  return -1;
4454  }
4455  } else if ((m = opmask(ao->op, "str", B_BIT | T_BIT | D_BIT | H_BIT))) {
4456  ut64 argt = thumb_selector(ao->a);
4457  ut32 strsel = m & (B_BIT | H_BIT | D_BIT);
4458  switch (argt) {
4460  if (ao->a[2] == NULL) { // double fallthrough
4461  ao->a[1][strlen(ao->a[1]) - 1] = '\0';
4462  ao->a[2] = "0]";
4463  }
4464  // intentional fallthrough
4466  ut8 reg1 = getreg(ao->a[0]);
4467  ut8 reg2 = getregmemstart(ao->a[1]);
4468  st32 num = getnummemend(ao->a[2]);
4469  if (m & T_BIT) {
4470  if ((num < 0) || (num > 255)) {
4471  return -1;
4472  }
4473  if (strsel == 0) {
4474  ao->o = 0x40f8000e;
4475  } else if (strsel == H_BIT) {
4476  ao->o = 0x20f8000e;
4477  } else if (strsel == B_BIT) {
4478  ao->o = 0x00f8000e;
4479  } else {
4480  return -1;
4481  }
4482  ao->o |= num << 8;
4483  return mem_32bit_2reg(ao, m);
4484  }
4485 
4486  if ((strsel == 0) && (reg2 == 13) && (num >= 0) && (num < 1024) && ((num % 4) == 0) && (reg1 < 8) & (!(m & DOTW_BIT))) {
4487  ao->o = 0x0090;
4488  ao->o |= reg1;
4489  ao->o |= (num >> 2) << 8;
4490  return 2;
4491  }
4492 
4493  bool t1form = false;
4494  if ((strsel == 0) && (num < 128) && (num >= 0) && (num % 4 == 0)) {
4495  ao->o = 0x0060;
4496  ao->o |= (num >> 4);
4497  ao->o |= ((num >> 2) & 0x3) << 14;
4498  t1form = true;
4499  }
4500  if ((strsel == B_BIT) && (num < 32) && (num >= 0)) {
4501  ao->o = 0x0070;
4502  ao->o |= (num >> 2);
4503  ao->o |= (num & 0x3) << 14;
4504  t1form = true;
4505  }
4506  if ((strsel == H_BIT) && (num < 64) && (num >= 0) && (num % 2 == 0)) {
4507  ao->o = 0x0080;
4508  ao->o |= (num >> 3);
4509  ao->o |= ((num >> 1) & 0x3) << 14;
4510  t1form = true;
4511  }
4512  if (t1form) {
4513  if (mem_16bit_2reg(ao, m)) {
4514  return 2;
4515  }
4516  }
4517 
4518  if ((num > 4095) || (num < -255)) {
4519  return -1;
4520  }
4521  if (num >= 0) {
4522  if (strsel == 0) {
4523  ao->o = 0xc0f80000;
4524  } else if (strsel == B_BIT) {
4525  ao->o = 0x80f80000;
4526  } else if (strsel == H_BIT) {
4527  ao->o = 0xa0f80000;
4528  } else {
4529  return -1;
4530  }
4531  ao->o |= (num >> 8);
4532  ao->o |= (num & 0x000000ff) << 8;
4533  return mem_32bit_2reg(ao, m);
4534  }
4535  if (strsel == 0) {
4536  ao->o = 0x40f8000c;
4537  } else if (strsel == B_BIT) {
4538  ao->o = 0x00f8000c;
4539  } else if (strsel == H_BIT) {
4540  ao->o = 0x20f8000c;
4541  } else {
4542  return -1;
4543  }
4544  ao->o |= -num << 8;
4545  return mem_32bit_2reg(ao, m);
4546  } break;
4548  ut8 reg1 = getreg(ao->a[0]);
4549  ut8 reg2 = getregmemstartend(ao->a[1]);
4550  st32 num = getnum(ao->a[2]);
4551 
4552  if ((num > 255) || (num < -255)) {
4553  return -1;
4554  }
4555 
4556  if (strsel == 0) {
4557  ao->o = 0x40f80009;
4558  } else if (strsel == B_BIT) {
4559  ao->o = 0x00f80009;
4560  } else if (strsel == H_BIT) {
4561  ao->o = 0x20f80009;
4562  } else {
4563  return -1;
4564  }
4565 
4566  if (num < 0) {
4567  num = -num;
4568  } else {
4569  ao->o |= 1 << 1;
4570  }
4571  ao->o |= num << 8;
4572  ao->o |= reg1 << 4;
4573  ao->o |= reg2 << 24;
4574  return 4;
4575  } break;
4577  st32 num = getnummemendbang(ao->a[2]);
4578 
4579  if ((num > 255) || (num < -255)) {
4580  return -1;
4581  }
4582 
4583  if (strsel == 0) {
4584  ao->o = 0x40f8000d;
4585  } else if (strsel == B_BIT) {
4586  ao->o = 0x00f8000d;
4587  } else if (strsel == H_BIT) {
4588  ao->o = 0x20f8000d;
4589  } else {
4590  return -1;
4591  }
4592 
4593  if (num < 0) {
4594  num = -num;
4595  } else {
4596  ao->o |= 1 << 1;
4597  }
4598  ao->o |= num << 8;
4599  return mem_32bit_2reg(ao, m);
4600  } break;
4602  ut8 reg1 = getreg(ao->a[0]);
4603  ut8 reg2 = getregmemstart(ao->a[1]);
4604  ut8 reg3 = getregmemend(ao->a[2]);
4605  if ((reg1 < 8) && (reg2 < 8) && (reg3 < 8) && (!(m & DOTW_BIT))) {
4606  if (strsel == 0) {
4607  ao->o = 0x0050;
4608  } else if (strsel == B_BIT) {
4609  ao->o = 0x0054;
4610  } else if (strsel == H_BIT) {
4611  ao->o = 0x0052;
4612  } else {
4613  return -1;
4614  }
4615  ao->o |= reg1 << 8;
4616  ao->o |= reg2 << 11;
4617  ao->o |= (reg3 & 0x3) << 14;
4618  ao->o |= (reg3 >> 2);
4619  return 2;
4620  }
4621  ao->a[2][strlen(ao->a[2]) - 1] = '\0';
4622  ao->a[3] = "lsl 0]";
4623  }
4624  // intentional fallthrough
4626  ut8 reg1 = getreg(ao->a[0]);
4627  ut8 reg2 = getregmemstart(ao->a[1]);
4628  ut8 reg3 = getreg(ao->a[2]);
4629  ut32 shift = getshiftmemend(ao->a[3]) >> 2;
4630 
4631  if (((shift & 0xffffcfff) != 0) || (reg1 > 15) || (reg2 > 15) || (reg3 > 15)) {
4632  return -1;
4633  }
4634 
4635  if (strsel == 0) {
4636  ao->o = 0x40f80000;
4637  } else if (strsel == B_BIT) {
4638  ao->o = 0x00f80000;
4639  } else if (strsel == H_BIT) {
4640  ao->o = 0x20f80000;
4641  } else {
4642  return -1;
4643  }
4644 
4645  ao->o |= reg1 << 4;
4646  ao->o |= reg2 << 24;
4647  ao->o |= reg3 << 8;
4648  ao->o |= shift;
4649  return 4;
4650  } break;
4652  ao->a[2][strlen(ao->a[2]) - 1] = '\0';
4653  ao->a[3] = "0]";
4654  }
4655  // intentional fallthrough
4657  ut8 reg1 = getreg(ao->a[0]);
4658  ut8 reg2 = getreg(ao->a[1]);
4659  ut8 reg3 = getregmemstart(ao->a[2]);
4660  st32 num = getnummemend(ao->a[3]);
4661 
4662  if ((reg1 > 15) || (reg2 > 15) || (reg3 > 15) || (strsel != D_BIT) || (num > 1023) || (num < -1023) || ((num % 4) != 0)) {
4663  return -1;
4664  }
4665 
4666  ao->o = 0x40e90000;
4667 
4668  if (num < 0) {
4669  num = -num;
4670  } else {
4671  ao->o |= 1 << 31;
4672  }
4673  ao->o |= reg1 << 4;
4674  ao->o |= reg2;
4675  ao->o |= reg3 << 24;
4676  ao->o |= (num >> 2) << 8;
4677  return 4;
4678  } break;
4680  ut8 reg1 = getreg(ao->a[0]);
4681  ut8 reg2 = getreg(ao->a[1]);
4682  ut8 reg3 = getregmemstart(ao->a[2]);
4683  st32 num = getnummemendbang(ao->a[3]);
4684 
4685  if ((reg1 > 15) || (reg2 > 15) || (reg3 > 15) || (strsel != D_BIT) || (num > 1023) || (num < -1023) || ((num % 4) != 0)) {
4686  return -1;
4687  }
4688 
4689  ao->o = 0x60e90000;
4690 
4691  if (num < 0) {
4692  num = -num;
4693  } else {
4694  ao->o |= 1 << 31;
4695  }
4696  ao->o |= reg1 << 4;
4697  ao->o |= reg2;
4698  ao->o |= reg3 << 24;
4699  ao->o |= (num >> 2) << 8;
4700  return 4;
4701  } break;
4703  ut8 reg1 = getreg(ao->a[0]);
4704  ut8 reg2 = getreg(ao->a[1]);
4705  ut8 reg3 = getregmemstartend(ao->a[2]);
4706  st32 num = getnum(ao->a[3]);
4707 
4708  if ((reg1 > 15) || (reg2 > 15) || (reg3 > 15) || (strsel != D_BIT) || (num > 1023) || (num < -1023) || ((num % 4) != 0)) {
4709  return -1;
4710  }
4711 
4712  ao->o = 0x60e80000;
4713 
4714  if (num < 0) {
4715  num = -num;
4716  } else {
4717  ao->o |= 1 << 31;
4718  }
4719  ao->o |= reg1 << 4;
4720  ao->o |= reg2;
4721  ao->o |= reg3 << 24;
4722  ao->o |= (num >> 2) << 8;
4723  return 4;
4724  } break;
4725  default:
4726  return -1;
4727  }
4728  } else if ((m = opmask(ao->op, "strex", B_BIT | D_BIT | H_BIT))) {
4729  ut64 argt = thumb_selector(ao->a);
4730  ut32 strsel = m & (B_BIT | H_BIT | D_BIT);
4731  switch (argt) {
4733  ut8 reg1 = getreg(ao->a[0]);
4734  ut8 reg2 = getreg(ao->a[1]);
4735  ut8 reg3 = getregmemstartend(ao->a[2]);
4736 
4737  if ((strsel == D_BIT) || (reg1 > 15) || (reg2 > 15) || (reg3 > 15)) {
4738  return -1;
4739  }
4740  if (strsel == B_BIT) {
4741  ao->o = 0xc0e8400f;
4742  ao->o |= reg1 << 8;
4743  ao->o |= reg2 << 4;
4744  ao->o |= reg3 << 24;
4745  return 4;
4746  } else if (strsel == H_BIT) {
4747  ao->o = 0xc0e8500f;
4748  ao->o |= reg1 << 8;
4749  ao->o |= reg2 << 4;
4750  ao->o |= reg3 << 24;
4751  return 4;
4752  }
4753 
4754  ao->a[2][strlen(ao->a[2]) - 1] = '\0';
4755  ao->a[3] = "0]";
4756  }
4757  // intentional fallthrough
4759  ut8 reg1 = getreg(ao->a[0]);
4760  ut8 reg2 = getreg(ao->a[1]);
4761  ut8 reg3 = getregmemstart(ao->a[2]);
4762  st32 num = getnummemend(ao->a[3]);
4763 
4764  if ((strsel != 0) || (reg1 > 15) || (reg2 > 15) || (reg3 > 15) || (num < 0) || (num > 1023) || ((num % 4) != 0)) {
4765  return -1;
4766  }
4767 
4768  ao->o = 0x40e80000;
4769  ao->o |= reg1;
4770  ao->o |= reg2 << 4;
4771  ao->o |= reg3 << 24;
4772  ao->o |= (num >> 2) << 8;
4773  return 4;
4774  } break;
4776  ut8 reg1 = getreg(ao->a[0]);
4777  ut8 reg2 = getreg(ao->a[1]);
4778  ut8 reg3 = getreg(ao->a[2]);
4779  ut8 reg4 = getregmemstartend(ao->a[3]);
4780 
4781  if ((strsel != D_BIT) || (reg1 > 15) || (reg2 > 15) || (reg3 > 15) || (reg4 > 15)) {
4782  return -1;
4783  }
4784 
4785  ao->o = 0xc0e87000;
4786  ao->o |= reg1 << 8;
4787  ao->o |= reg2 << 4;
4788  ao->o |= reg3;
4789  ao->o |= reg4 << 24;
4790  return 4;
4791  } break;
4792  }
4793  } else if ((m = opmask(ao->op, "sub", S_BIT | W_BIT))) {
4794  ut64 argt = thumb_selector(ao->a);
4795  switch (argt) {
4796  case THUMB_REG_CONST: {
4797  std_opt_2(ao);
4798  }
4799  // intentional fallthrough
4800  case THUMB_REG_REG_CONST: {
4801  ut8 reg1 = getreg(ao->a[0]);
4802  ut8 reg2 = getreg(ao->a[1]);
4803  ut32 num = getnum(ao->a[2]);
4804 
4805  if ((reg1 > 15) || (reg2 > 15)) {
4806  return -1;
4807  }
4808 
4809  if ((reg1 == 15) && (reg2 == 14) && (num < 256)) {
4810  ao->o = 0xdef3008f;
4811  ao->o |= num << 8;
4812  return 4;
4813  }
4814  if (reg2 == 13) {
4815  if ((reg1 == 13) && (!(m & DOTW_BIT)) && (!(m & W_BIT)) && (num <= 4096) && (num % 4 == 0)) {
4816  ao->o = 0x80b0;
4817  ao->o |= (num >> 2) << 8;
4818  return 2;
4819  }
4820  err = false;
4821  ut32 thnum = getthimmed12(ao->a[2]);
4822 
4823  if (!err && (!(m & W_BIT))) {
4824  ao->o = 0xadf10000;
4825  ao->o |= thnum;
4826  ao->o |= reg1;
4827  if (m & S_BIT) {
4828  ao->o |= 1 << 28;
4829  }
4830  return 4;
4831  }
4832 
4833  if (num > 4096) {
4834  return -1;
4835  }
4836 
4837  ao->o = 0xadf20000;
4838  ao->o |= getthzeroimmed12(num);
4839  ao->o |= reg1;
4840  return 4;
4841  }
4842 
4843  if ((reg1 < 8) && (reg2 < 8) && (!(m & DOTW_BIT)) && (!(m & W_BIT)) && (num < 8)) {
4844  ao->o = 0x001e;
4845  ao->o |= reg1 << 8;
4846  ao->o |= reg2 << 11;
4847  ao->o |= (num & 0x3) << 14;
4848  ao->o |= (num >> 2);
4849  return 2;
4850  }
4851 
4852  if ((reg1 < 8) && (reg1 == reg2) && (!(m & DOTW_BIT)) && (!(m & W_BIT)) && (num < 256)) {
4853  ao->o = 0x0038;
4854  ao->o |= reg1;
4855  ao->o |= num << 8;
4856  return 2;
4857  }
4858 
4859  err = false;
4860  ut32 thnum = getthimmed12(ao->a[2]);
4861 
4862  if (!err && (!(m & W_BIT))) {
4863  ao->o = 0xa0f10000;
4864  ao->o |= thnum;
4865  return std_32bit_2reg(ao, m, false);
4866  }
4867 
4868  if (num > 4096) {
4869  return -1;
4870  }
4871 
4872  ao->o = 0xa0f20000;
4873  ao->o |= reg1;
4874  ao->o |= reg2 << 24;
4875  ao->o |= getthzeroimmed12(num);
4876  return 4;
4877  } break;
4878  case THUMB_REG_REG: {
4879  std_opt_2(ao);
4880  }
4881  // intentional fallthrough
4882  case THUMB_REG_REG_REG: {
4883  ao->a[3] = "lsl 0";
4884  }
4885  // intentional fallthrough
4886  case THUMB_REG_REG_SHIFT:
4887  if (ao->a[3] == NULL) { // double fallthrough
4888  std_opt_3(ao);
4889  }
4890  // intentional fallthrough
4891  case THUMB_REG_REG_REG_SHIFT: {
4892  ut8 reg1 = getreg(ao->a[0]);
4893  ut8 reg2 = getreg(ao->a[1]);
4894  ut8 reg3 = getreg(ao->a[2]);
4895  ut32 shift = thumb_getshift(ao->a[3]);
4896 
4897  if (reg2 == 13) {
4898  ao->o = 0xadeb0000;
4899  ao->o |= reg1;
4900  ao->o |= reg3 << 8;
4901  ao->o |= shift;
4902  if (m & S_BIT) {
4903  ao->o |= 1 << 28;
4904  }
4905  return 4;
4906  }
4907 
4908  if ((shift == 0) && (reg1 < 8) && (reg2 < 8) && (reg3 < 8) && (!(m & DOTW_BIT))) {
4909  ao->o = 0x001a;
4910  ao->o |= reg1 << 8;
4911  ao->o |= reg2 << 11;
4912  ao->o |= (reg3 & 0x3) << 14;
4913  ao->o |= (reg3 >> 2);
4914  return 2;
4915  }
4916 
4917  ao->o = 0xa0eb0000;
4918  return std_32bit_3reg(ao, m, true);
4919  } break;
4920  default:
4921  return -1;
4922  }
4923  } else if (opmask(ao->op, "svc", 0)) {
4924  ut64 argt = thumb_selector(ao->a);
4925  switch (argt) {
4926  case THUMB_CONST: {
4927  ut32 num = getnum(ao->a[0]);
4928  if (num > 255) {
4929  return -1;
4930  }
4931  ao->o = 0x00df;
4932  ao->o |= num << 8;
4933  return 2;
4934  } break;
4935  default:
4936  return -1;
4937  }
4938  } else if ((m = opmask(ao->op, "sxta", B_BIT | H_BIT | SIXTEEN_BIT))) {
4939  ut64 argt = thumb_selector(ao->a);
4940  switch (argt) {
4941  case THUMB_REG_REG: {
4942  std_opt_2(ao);
4943  }
4944  // intentional fallthrough
4945  case THUMB_REG_REG_REG: {
4946  ao->a[3] = "lsl 0";
4947  }
4948  // intentional fallthrough
4949  case THUMB_REG_REG_SHIFT: {
4950  if (ao->a[3] == NULL) { // double fallthrough
4951  std_opt_3(ao);
4952  }
4953  }
4954  // intentional fallthrough
4955  case THUMB_REG_REG_REG_SHIFT: {
4956  ut32 shift = thumb_getshift(ao->a[3]);
4957 
4958  if ((shift != 0) && ((shift & 0x0000f010) != 0x00003000)) {
4959  return -1;
4960  }
4961 
4962  ut64 sufsel = m & (B_BIT | H_BIT | SIXTEEN_BIT);
4963 
4964  if (sufsel == B_BIT) {
4965  ao->o = 0x40fa80f0;
4966  } else if (sufsel == (B_BIT | SIXTEEN_BIT)) {
4967  ao->o = 0x20fa80f0;
4968  } else if (sufsel == H_BIT) {
4969  ao->o = 0x00fa80f0;
4970  } else {
4971  return -1;
4972  }
4973 
4974  ao->o |= (shift & 0x00000060) << 7;
4975  return std_32bit_3reg(ao, m, false);
4976  } break;
4977  }
4978  } else if ((m = opmask(ao->op, "sxt", B_BIT | H_BIT | SIXTEEN_BIT))) {
4979  ut64 sufsel = m & (B_BIT | H_BIT | SIXTEEN_BIT);
4980  ut64 argt = thumb_selector(ao->a);
4981  switch (argt) {
4982  case THUMB_REG_REG: {
4983  ao->a[2] = "lsl 0";
4984  }
4985  // intentional fallthrough
4986  case THUMB_REG_REG_SHIFT: {
4987  ut8 reg1 = getreg(ao->a[0]);
4988  ut8 reg2 = getreg(ao->a[1]);
4989  ut32 shift = thumb_getshift(ao->a[2]);
4990 
4991  if ((reg1 > 15) && (reg2 > 15) && (shift != 0) && ((shift & 0x0000f010) != 0x00003000)) {
4992  return -1;
4993  }
4994 
4995  if (sufsel == B_BIT) {
4996  ao->o = 0x40b2;
4997  if ((shift == 0) && std_16bit_2reg(ao, m)) {
4998  return 2;
4999  }
5000  ao->o = 0x4ffa80f0;
5001  } else if (sufsel == (B_BIT | SIXTEEN_BIT)) {
5002  ao->o = 0x2ffa80f0;
5003  } else if (sufsel == H_BIT) {
5004  ao->o = 0x00b2;
5005  if ((shift == 0) && std_16bit_2reg(ao, m)) {
5006  return 2;
5007  }
5008  ao->o = 0x0ffa80f0;
5009  } else {
5010  return -1;
5011  }
5012 
5013  ao->o |= (shift & 0x00000060) << 7;
5014  ao->o |= reg1;
5015  ao->o |= reg2 << 8;
5016  return 4;
5017  } break;
5018  }
5019  } else if ((m = opmask(ao->op, "tb", B_BIT | H_BIT))) {
5020  ut64 argt = thumb_selector(ao->a);
5021  ut64 sufsel = m & (B_BIT | H_BIT);
5022  switch (argt) {
5023  case THUMB_BRACKREG_REGBRACK: {
5024  ut8 reg1 = getregmemstart(ao->a[0]);
5025  ut8 reg2 = getregmemend(ao->a[1]);
5026 
5027  if ((reg1 > 15) || (reg2 > 15)) {
5028  return -1;
5029  }
5030 
5031  if (sufsel == B_BIT) {
5032  ao->o = 0xd0e800f0;
5033  ao->o |= reg1 << 24;
5034  ao->o |= reg2 << 8;
5035  return 4;
5036  }
5037  ao->a[1][strlen(ao->a[1]) - 1] = '\0';
5038  ao->a[2] = "lsl 1]";
5039  }
5040  // intentional fallthrough
5042  ut8 reg1 = getregmemstart(ao->a[0]);
5043  ut8 reg2 = getreg(ao->a[1]);
5044  ut32 shift = getshiftmemend(ao->a[2]);
5045 
5046  if ((reg1 > 15) || (reg2 > 15) || (shift != 0x00004000) || (sufsel != H_BIT)) {
5047  return -1;
5048  }
5049 
5050  ao->o = 0xd0e810f0;
5051  ao->o |= reg1 << 24;
5052  ao->o |= reg2 << 8;
5053  return 4;
5054  } break;
5055  default:
5056  return -1;
5057  }
5058  } else if ((m = opmask(ao->op, "teq", 0))) {
5059  ut64 argt = thumb_selector(ao->a);
5060  switch (argt) {
5061  case THUMB_REG_CONST: {
5062  ut8 reg = getreg(ao->a[0]);
5063  err = false;
5064  ut32 num = getthimmed12(ao->a[1]);
5065 
5066  if (err || (reg > 15)) {
5067  return -1;
5068  }
5069 
5070  ao->o = 0x90f0000f;
5071  ao->o |= reg << 24;
5072  ao->o |= num;
5073  return 4;
5074  } break;
5075  case THUMB_REG_REG: {
5076  ao->a[2] = "lsl 0";
5077  }
5078  // intentional fallthrough
5079  case THUMB_REG_REG_SHIFT: {
5080  ao->o = 0x90ea000f;
5081  return std_32bit_2reg(ao, m, true);
5082  } break;
5083  default:
5084  return -1;
5085  }
5086  } else if ((m = opmask(ao->op, "tst", 0))) {
5087  ut64 argt = thumb_selector(ao->a);
5088  switch (argt) {
5089  case THUMB_REG_CONST: {
5090  ut8 reg1 = getreg(ao->a[0]);
5091  err = false;
5092  ut32 num = getthimmed12(ao->a[1]);
5093 
5094  if (err || (reg1 > 15)) {
5095  return -1;
5096  }
5097 
5098  ao->o = 0x10f0000f;
5099  ao->o |= reg1 << 24;
5100  ao->o |= num;
5101  return 4;
5102  } break;
5103  case THUMB_REG_REG: {
5104  ao->o = 0x0042;
5105 
5106  if (std_16bit_2reg(ao, m)) {
5107  return 2;
5108  }
5109 
5110  ao->a[2] = "lsl 0";
5111  }
5112  // intentional fallthrough
5113  case THUMB_REG_REG_SHIFT: {
5114  ao->o = 0x10ea000f;
5115  return std_32bit_2reg(ao, m, true);
5116  } break;
5117  default:
5118  return -1;
5119  }
5120  } else if ((m = opmask(ao->op, "uadd", EIGHT_BIT | SIXTEEN_BIT))) {
5121  ut64 argt = thumb_selector(ao->a);
5122  switch (argt) {
5123  case THUMB_REG_REG: {
5124  std_opt_2(ao);
5125  }
5126  // intentional fallthrough
5127  case THUMB_REG_REG_REG: {
5128  if (m & EIGHT_BIT) {
5129  ao->o = 0x80fa40f0;
5130  } else if (m & SIXTEEN_BIT) {
5131  ao->o = 0x90fa40f0;
5132  } else {
5133  return -1;
5134  }
5135 
5136  return std_32bit_3reg(ao, m, false);
5137  } break;
5138  default:
5139  return -1;
5140  }
5141  } else if ((m = opmask(ao->op, "uasx", 0))) {
5142  ut64 argt = thumb_selector(ao->a);
5143  switch (argt) {
5144  case THUMB_REG_REG: {
5145  std_opt_2(ao);
5146  }
5147  // intentional fallthrough
5148  case THUMB_REG_REG_REG: {
5149  ao->o = 0xa0fa40f0;
5150  return std_32bit_3reg(ao, m, false);
5151  } break;
5152  default:
5153  return -1;
5154  }
5155  } else if (opmask(ao->op, "ubfx", 0)) {
5156  ut64 argt = thumb_selector(ao->a);
5157  switch (argt) {
5159  ut8 reg1 = getreg(ao->a[0]);
5160  ut8 reg2 = getreg(ao->a[1]);
5161  ut32 lsb = getnum(ao->a[2]);
5162  ut32 widthm1 = getnum(ao->a[3]) - 1;
5163 
5164  if ((reg1 > 15) || (reg2 > 15) || (lsb > 31) || ((31 - lsb) <= widthm1)) {
5165  return -1;
5166  }
5167 
5168  ao->o = 0xc0f30000;
5169  ao->o |= reg1;
5170  ao->o |= reg2 << 24;
5171  ao->o |= (lsb & 0x1c) << 2;
5172  ao->o |= (lsb & 0x3) << 14;
5173  ao->o |= widthm1 << 8;
5174  return 4;
5175  } break;
5176  default:
5177  return -1;
5178  }
5179  } else if ((m = opmask(ao->op, "udiv", 0))) {
5180  ut64 argt = thumb_selector(ao->a);
5181  switch (argt) {
5182  case THUMB_REG_REG: {
5183  std_opt_2(ao);
5184  }
5185  // intentional fallthrough
5186  case THUMB_REG_REG_REG: {
5187  ao->o = 0xb0fbf0f0;
5188  return std_32bit_3reg(ao, m, false);
5189  } break;
5190  default:
5191  return -1;
5192  }
5193  } else if ((m = opmask(ao->op, "uhadd", EIGHT_BIT | SIXTEEN_BIT))) {
5194  ut64 argt = thumb_selector(ao->a);
5195  ut64 sufsel = m & (EIGHT_BIT | SIXTEEN_BIT);
5196  switch (argt) {
5197  case THUMB_REG_REG: {
5198  std_opt_2(ao);
5199  }
5200  // intentional fallthrough
5201  case THUMB_REG_REG_REG: {
5202  if (sufsel == EIGHT_BIT) {
5203  ao->o = 0x80fa60f0;
5204  } else if (sufsel == SIXTEEN_BIT) {
5205  ao->o = 0x90fa60f0;
5206  } else {
5207  return -1;
5208  }
5209 
5210  return std_32bit_3reg(ao, m, false);
5211  } break;
5212  default:
5213  return -1;
5214  }
5215  } else if ((m = opmask(ao->op, "uhasx", 0))) {
5216  ut64 argt = thumb_selector(ao->a);
5217  switch (argt) {
5218  case THUMB_REG_REG: {
5219  std_opt_2(ao);
5220  }
5221  // intentional fallthrough
5222  case THUMB_REG_REG_REG: {
5223  ao->o = 0xa0fa60f0;
5224 
5225  return std_32bit_3reg(ao, m, false);
5226 
5227  } break;
5228  default:
5229  return -1;
5230  }
5231  } else if ((m = opmask(ao->op, "uhsax", 0))) {
5232  ut64 argt = thumb_selector(ao->a);
5233  switch (argt) {
5234  case THUMB_REG_REG: {
5235  std_opt_2(ao);
5236  }
5237  // intentional fallthrough
5238  case THUMB_REG_REG_REG: {
5239  ao->o = 0xe0fa60f0;
5240 
5241  return std_32bit_3reg(ao, m, false);
5242  } break;
5243  default:
5244  return -1;
5245  }
5246  } else if ((m = opmask(ao->op, "uhsub", EIGHT_BIT | SIXTEEN_BIT))) {
5247  ut64 argt = thumb_selector(ao->a);
5248  ut64 sufsel = m & (EIGHT_BIT | SIXTEEN_BIT);
5249  switch (argt) {
5250  case THUMB_REG_REG: {
5251  std_opt_2(ao);
5252  }
5253  // intentional fallthrough
5254  case THUMB_REG_REG_REG: {
5255  if (sufsel == EIGHT_BIT) {
5256  ao->o = 0xc0fa60f0;
5257  } else if (sufsel == SIXTEEN_BIT) {
5258  ao->o = 0xd0fa60f0;
5259  } else {
5260  return -1;
5261  }
5262 
5263  return std_32bit_3reg(ao, m, false);
5264  } break;
5265  default:
5266  return -1;
5267  }
5268  } else if (opmask(ao->op, "umaal", 0)) {
5269  ut64 argt = thumb_selector(ao->a);
5270  switch (argt) {
5271  case THUMB_REG_REG_REG_REG: {
5272  ut8 reg1 = getreg(ao->a[0]);
5273  ut8 reg2 = getreg(ao->a[1]);
5274  ut8 reg3 = getreg(ao->a[2]);
5275  ut8 reg4 = getreg(ao->a[3]);
5276 
5277  if ((reg1 > 15) || (reg2 > 15) || (reg3 > 15) || (reg4 > 15)) {
5278  return -1;
5279  }
5280 
5281  ao->o = 0xe0fb6000;
5282  ao->o |= reg1 << 4;
5283  ao->o |= reg2;
5284  ao->o |= reg3 << 24;
5285  ao->o |= reg4 << 8;
5286  return 4;
5287  } break;
5288  default:
5289  return -1;
5290  }
5291  } else if (opmask(ao->op, "umlal", 0)) {
5292  ut64 argt = thumb_selector(ao->a);
5293  switch (argt) {
5294  case THUMB_REG_REG_REG_REG: {
5295  ut8 reg1 = getreg(ao->a[0]);
5296  ut8 reg2 = getreg(ao->a[1]);
5297  ut8 reg3 = getreg(ao->a[2]);
5298  ut8 reg4 = getreg(ao->a[3]);
5299 
5300  if ((reg1 > 15) || (reg2 > 15) || (reg3 > 15) || (reg4 > 15)) {
5301  return -1;
5302  }
5303 
5304  ao->o = 0xe0fb0000;
5305  ao->o |= reg1 << 4;
5306  ao->o |= reg2;
5307  ao->o |= reg3 << 24;
5308  ao->o |= reg4 << 8;
5309  return 4;
5310  } break;
5311  default:
5312  return -1;
5313  }
5314  } else if (opmask(ao->op, "umull", 0)) {
5315  ut64 argt = thumb_selector(ao->a);
5316  switch (argt) {
5317  case THUMB_REG_REG_REG_REG: {
5318  ut8 reg1 = getreg(ao->a[0]);
5319  ut8 reg2 = getreg(ao->a[1]);
5320  ut8 reg3 = getreg(ao->a[2]);
5321  ut8 reg4 = getreg(ao->a[3]);
5322 
5323  if ((reg1 > 15) || (reg2 > 15) || (reg3 > 15) || (reg4 > 15)) {
5324  return -1;
5325  }
5326 
5327  ao->o = 0xa0fb0000;
5328  ao->o |= reg1 << 4;
5329  ao->o |= reg2;
5330  ao->o |= reg3 << 24;
5331  ao->o |= reg4 << 8;
5332  return 4;
5333  } break;
5334  default:
5335  return -1;
5336  }
5337  } else if ((m = opmask(ao->op, "uqadd", EIGHT_BIT | SIXTEEN_BIT))) {
5338  ut64 argt = thumb_selector(ao->a);
5339  ut64 sufsel = m & (EIGHT_BIT | SIXTEEN_BIT);
5340  switch (argt) {
5341  case THUMB_REG_REG: {
5342  std_opt_2(ao);
5343  }
5344  // intentional fallthrough
5345  case THUMB_REG_REG_REG: {
5346  if (sufsel == EIGHT_BIT) {
5347  ao->o = 0x80fa50f0;
5348  } else if (sufsel == SIXTEEN_BIT) {
5349  ao->o = 0x90fa50f0;
5350  } else {
5351  return -1;
5352  }
5353 
5354  return std_32bit_3reg(ao, m, false);
5355  } break;
5356  default:
5357  return -1;
5358  }
5359  } else if ((m = opmask(ao->op, "uqasx", 0))) {
5360  ut64 argt = thumb_selector(ao->a);
5361  switch (argt) {
5362  case THUMB_REG_REG: {
5363  std_opt_2(ao);
5364  }
5365  // intentional fallthrough
5366  case THUMB_REG_REG_REG: {
5367  ao->o = 0xa0fa50f0;
5368 
5369  return std_32bit_3reg(ao, m, false);
5370  } break;
5371  default:
5372  return -1;
5373  }
5374  } else if ((m = opmask(ao->op, "uqsax", 0))) {
5375  ut64 argt = thumb_selector(ao->a);
5376  switch (argt) {
5377  case THUMB_REG_REG: {
5378  std_opt_2(ao);
5379  }
5380  // intentional fallthrough
5381  case THUMB_REG_REG_REG: {
5382  ao->o = 0xe0fa50f0;
5383 
5384  return std_32bit_3reg(ao, m, false);
5385  } break;
5386  default:
5387  return -1;
5388  }
5389  } else if ((m = opmask(ao->op, "uqsub", EIGHT_BIT | SIXTEEN_BIT))) {
5390  ut64 argt = thumb_selector(ao->a);
5391  ut64 sufsel = m & (EIGHT_BIT | SIXTEEN_BIT);
5392  switch (argt) {
5393  case THUMB_REG_REG: {
5394  std_opt_2(ao);
5395  }
5396  // intentional fallthrough
5397  case THUMB_REG_REG_REG: {
5398  if (sufsel == EIGHT_BIT) {
5399  ao->o = 0xc0fa50f0;
5400  } else if (sufsel == SIXTEEN_BIT) {
5401  ao->o = 0xd0fa50f0;
5402  } else {
5403  return -1;
5404  }
5405 
5406  return std_32bit_3reg(ao, m, false);
5407  } break;
5408  default:
5409  return -1;
5410  }
5411  } else if ((m = opmask(ao->op, "usad8", 0))) {
5412  ut64 argt = thumb_selector(ao->a);
5413  switch (argt) {
5414  case THUMB_REG_REG: {
5415  std_opt_2(ao);
5416  }
5417  // intentional fallthrough
5418  case THUMB_REG_REG_REG: {
5419  ao->o = 0x70fb00f0;
5420 
5421  return std_32bit_3reg(ao, m, false);
5422  } break;
5423  default:
5424  return -1;
5425  }
5426  } else if (opmask(ao->op, "usada8", 0)) {
5427  ut64 argt = thumb_selector(ao->a);
5428  switch (argt) {
5429  case THUMB_REG_REG_REG_REG: {
5430  ut8 reg1 = getreg(ao->a[0]);
5431  ut8 reg2 = getreg(ao->a[1]);
5432  ut8 reg3 = getreg(ao->a[2]);
5433  ut8 reg4 = getreg(ao->a[3]);
5434 
5435  if ((reg1 > 15) || (reg2 > 15) || (reg3 > 15) || (reg4 > 15)) {
5436  return -1;
5437  }
5438 
5439  ao->o = 0x70fb0000;
5440  ao->o |= reg1;
5441  ao->o |= reg2 << 24;
5442  ao->o |= reg3 << 8;
5443  ao->o |= reg4 << 4;
5444  return 4;
5445  } break;
5446  default:
5447  return -1;
5448  }
5449  } else if ((m = opmask(ao->op, "usat", SIXTEEN_BIT))) {
5450  ut64 argt = thumb_selector(ao->a);
5451  switch (argt) {
5452  case THUMB_REG_CONST_REG: {
5453  if (m & SIXTEEN_BIT) {
5454  ut8 reg1 = getreg(ao->a[0]);
5455  ut32 num = getnum(ao->a[1]);
5456  ut8 reg2 = getreg(ao->a[2]);
5457 
5458  if ((reg1 > 15) || (num > 15) || (reg2 > 15)) {
5459  return -1;
5460  }
5461 
5462  ao->o = 0xa0f30000;
5463  ao->o |= reg1;
5464  ao->o |= reg2 << 24;
5465  ao->o |= num << 8;
5466  return 4;
5467  }
5468 
5469  ao->a[3] = "lsl 0";
5470  }
5471  // intentional fallthrough
5473  ut8 reg1 = getreg(ao->a[0]);
5474  ut32 num = getnum(ao->a[1]);
5475  ut8 reg2 = getreg(ao->a[2]);
5476  ut32 shift = thumb_getshift(ao->a[3]);
5477 
5478  if ((reg1 > 15) || (num > 31) || (reg2 > 15) || (m & SIXTEEN_BIT) || ((shift & 0x00001000) != 0)) {
5479  return -1;
5480  }
5481 
5482  ao->o = 0x80f30000;
5483  ao->o |= reg1;
5484  ao->o |= (num & 0xf) << 8;
5485  ao->o |= (num >> 4) << 12;
5486  ao->o |= reg2 << 24;
5487  ao->o |= (shift & 0x00002000) << 16;
5488  ao->o |= (shift & 0x0000c070);
5489  return 4;
5490  } break;
5491  default:
5492  return -1;
5493  }
5494  } else if ((m = opmask(ao->op, "usax", 0))) {
5495  ut64 argt = thumb_selector(ao->a);
5496  switch (argt) {
5497  case THUMB_REG_REG: {
5498  std_opt_2(ao);
5499  }
5500  // intentional fallthrough
5501  case THUMB_REG_REG_REG: {
5502  ao->o = 0xe0fa40f0;
5503 
5504  return std_32bit_3reg(ao, m, false);
5505  } break;
5506  default:
5507  return -1;
5508  }
5509  } else if ((m = opmask(ao->op, "usub", EIGHT_BIT | SIXTEEN_BIT))) {
5510  ut64 argt = thumb_selector(ao->a);
5511  ut64 sufsel = m & (EIGHT_BIT | SIXTEEN_BIT);
5512  switch (argt) {
5513  case THUMB_REG_REG: {
5514  std_opt_2(ao);
5515  }
5516  // intentional fallthrough
5517  case THUMB_REG_REG_REG: {
5518  if (sufsel == EIGHT_BIT) {
5519  ao->o = 0xc0fa40f0;
5520  } else if (sufsel == SIXTEEN_BIT) {
5521  ao->o = 0xd0fa40f0;
5522  } else {
5523  return -1;
5524  }
5525 
5526  return std_32bit_3reg(ao, m, false);
5527  } break;
5528  default:
5529  return -1;
5530  }
5531  } else if ((m = opmask(ao->op, "uxta", B_BIT | H_BIT | SIXTEEN_BIT))) {
5532  ut64 argt = thumb_selector(ao->a);
5533  ut64 sufsel = m & (B_BIT | H_BIT | SIXTEEN_BIT);
5534  switch (argt) {
5535  case THUMB_REG_REG: {
5536  std_opt_2(ao);
5537  }
5538  // intentional fallthrough
5539  case THUMB_REG_REG_REG: {
5540  ao->a[3] = "lsl 0";
5541  }
5542  // intentional fallthrough
5543  case THUMB_REG_REG_SHIFT: {
5544  if (ao->a[3] == NULL) { // double fallthrough
5545  std_opt_3(ao);
5546  }
5547  }
5548  // intentional fallthrough
5549  case THUMB_REG_REG_REG_SHIFT: {
5550  ut32 shift = thumb_getshift(ao->a[3]);
5551 
5552  if (shift && ((shift & 0x0000f010) != 0x00003000)) {
5553  return -1;
5554  }
5555 
5556  if (sufsel == B_BIT) {
5557  ao->o = 0x50fa80f0;
5558  } else if (sufsel == (B_BIT | SIXTEEN_BIT)) {
5559  ao->o = 0x30fa80f0;
5560  } else if (sufsel == H_BIT) {
5561  ao->o = 0x10fa80f0;
5562  } else {
5563  return -1;
5564  }
5565 
5566  ao->o |= (shift & 0x00000060) << 7;
5567  return (std_32bit_3reg(ao, m, false));
5568  } break;
5569  default:
5570  return -1;
5571  }
5572  } else if ((m = opmask(ao->op, "uxt", B_BIT | H_BIT | SIXTEEN_BIT))) {
5573  ut64 argt = thumb_selector(ao->a);
5574  ut64 sufsel = m & (B_BIT | H_BIT | SIXTEEN_BIT);
5575  switch (argt) {
5576  case THUMB_REG_REG: {
5577  if ((sufsel == B_BIT) || (sufsel == H_BIT)) {
5578  if (sufsel == B_BIT) {
5579  ao->o = 0xc0b2;
5580  } else {
5581  ao->o = 0x80b2;
5582  }
5583  if (std_16bit_2reg(ao, m)) {
5584  return 2;
5585  }
5586  }
5587  ao->a[2] = "lsl 0";
5588  }
5589  // intentional fallthrough
5590  case THUMB_REG_REG_SHIFT: {
5591  ut8 reg1 = getreg(ao->a[0]);
5592  ut8 reg2 = getreg(ao->a[1]);
5593  ut32 shift = thumb_getshift(ao->a[2]);
5594 
5595  if ((reg1 > 15) || (reg2 > 15) || (shift && ((shift & 0x0000f010) != 0x00003000))) {
5596  return -1;
5597  }
5598 
5599  if (sufsel == B_BIT) {
5600  ao->o = 0x5ffa80f0;
5601  } else if (sufsel == (B_BIT | SIXTEEN_BIT)) {
5602  ao->o = 0x3ffa80f0;
5603  } else if (sufsel == H_BIT) {
5604  ao->o = 0x1ffa80f0;
5605  } else {
5606  return -1;
5607  }
5608 
5609  ao->o |= (shift & 0x00000060) << 7;
5610  ao->o |= reg1;
5611  ao->o |= reg2 << 8;
5612  return 4;
5613  } break;
5614  default:
5615  return -1;
5616  }
5617  } else if ((m = opmask(ao->op, "wfe", 0))) {
5618  ut64 argt = thumb_selector(ao->a);
5619  switch (argt) {
5620  case THUMB_NONE: {
5621  if (m & DOTW_BIT) {
5622  ao->o = 0xaff30280;
5623  return 4;
5624  } else {
5625  ao->o = 0x20bf;
5626  return 2;
5627  }
5628  } break;
5629  default:
5630  return -1;
5631  }
5632  } else if ((m = opmask(ao->op, "wfi", 0))) {
5633  ut64 argt = thumb_selector(ao->a);
5634  switch (argt) {
5635  case THUMB_NONE: {
5636  if (m & DOTW_BIT) {
5637  ao->o = 0xaff30380;
5638  return 4;
5639  } else {
5640  ao->o = 0x30bf;
5641  return 2;
5642  }
5643  } break;
5644  default:
5645  return -1;
5646  }
5647  } else if ((m = opmask(ao->op, "yield", 0))) {
5648  ut64 argt = thumb_selector(ao->a);
5649  switch (argt) {
5650  case THUMB_NONE: {
5651  if (m & DOTW_BIT) {
5652  ao->o = 0xaff30180;
5653  return 4;
5654  } else {
5655  ao->o = 0x10bf;
5656  return 2;
5657  }
5658  } break;
5659  default:
5660  return -1;
5661  }
5662  }
5663  return 0;
5664 }
#define THUMB_REG_REG_REG
#define THUMB_COPROC_COREG_BRACKREGBRACK_CONST
#define THUMB_REG_REG_BRACKREGBRACK
#define THUMB_REG_REG_REG_SHIFT
#define THUMB_REG_BRACKREG_CONSTBRACK
#define THUMB_REG_REG_BRACKREGBRACK_CONST
#define THUMB_REG_REG
Definition: armass16_const.h:8
#define THUMB_COPROC_COREG_BRACKREG_CONSTBRACK
#define THUMB_OTHER
Definition: armass16_const.h:7
#define THUMB_REG_REG_BRACKREG_CONSTBRACK
#define THUMB_NONE
Definition: armass16_const.h:4
#define THUMB_REG_CONST
Definition: armass16_const.h:9
#define THUMB_REG_REG_REG_BRACKREGBRACK
#define THUMB_OTHER_CONST
#define THUMB_REGBANG_LIST
#define THUMB_REG_REG_BRACKREG_CONSTBRACKBANG
#define THUMB_OTHER_REG
#define THUMB_REG_CONST_CONST
#define THUMB_CONSTBANG
#define THUMB_COPROC_CONST_COREG_COREG_COREG_CONST
#define THUMB_COPROC_COREG_BRACKREG_CONSTBRACKBANG
#define THUMB_COPROC_CONST_REG_REG_COREG
#define THUMB_COPROC_CONST_COREG_COREG_COREG
#define THUMB_REG_CONST_REG_SHIFT
#define THUMB_REGBANG
#define THUMB_REG
Definition: armass16_const.h:5
#define THUMB_COPROC_CONST_REG_COREG_COREG_CONST
#define THUMB_REG_REG_CONST_CONST
#define THUMB_REG_LIST
#define THUMB_REG_BRACKREGBRACK
#define THUMB_LIST
#define THUMB_REG_REG_CONST
#define THUMB_REG_BRACKREG_REG_SHIFTBRACK
#define THUMB_REG_CONST_REG
#define THUMB_REG_REG_SHIFT
#define THUMB_REG_OTHER
#define THUMB_REG_REG_REG_REG
#define THUMB_BRACKREG_REGBRACK
#define THUMB_BRACKREG_REG_SHIFTBRACK
#define THUMB_REG_BRACKREG_REGBRACK
#define THUMB_COPROC_CONST_REG_COREG_COREG
#define THUMB_COPROC_COREG_BRACKREGBRACK
#define THUMB_REG_BRACKREG_CONSTBRACKBANG
#define THUMB_REG_BRACKREGBRACK_CONST
#define THUMB_BRACKREG_CONSTBRACK
#define THUMB_CONST
Definition: armass16_const.h:6
static st32 getnummemend(const char *input)
Definition: armass.c:766
static st32 getregmemstartend(const char *input)
Definition: armass.c:718
static st32 getnummemendbang(const char *input)
Definition: armass.c:783
static ut64 opmask(char *input, char *opcode, ut64 allowed_mask)
Definition: armass.c:265
static ut32 getthbimmed(st32 number)
Definition: armass.c:518
static st8 mem_32bit_2reg(ArmOpcode *ao, ut64 m)
Definition: armass.c:1212
static char * parse_hints(char *input)
Definition: armass.c:192
static ut32 itmask(char *input)
Definition: armass.c:405
static int getcoproc(const char *str)
Definition: armass.c:814
static st32 getregmembang(const char *input)
Definition: armass.c:800
static const ut64 C_BITS
Definition: armass.c:163
static ut8 interpret_msrbank(char *str, ut8 *spsr)
Definition: armass.c:849
static int getcoprocreg(const char *str)
Definition: armass.c:831
static ut32 getthzeroimmed16(ut32 number)
Definition: armass.c:552
static st32 thumb_getoffset(char *label, ut64 cur)
Definition: armass.c:1157
static st8 std_32bit_3reg(ArmOpcode *ao, ut64 m, bool shift)
Definition: armass.c:1223
static ut32 getthimmed12(const char *str)
Definition: armass.c:561
static st32 getregmemend(const char *input)
Definition: armass.c:733
static st8 std_16bit_2reg(ArmOpcode *ao, ut64 m)
Definition: armass.c:1165
static void std_opt_2(ArmOpcode *ao)
Definition: armass.c:1247
static st8 iflag(char *input)
Definition: armass.c:208
static void std_opt_3(ArmOpcode *ao)
Definition: armass.c:1252
static st32 getshiftmemend(const char *input)
Definition: armass.c:948
static ut64 thumb_selector(char *args[])
Definition: armass.c:963
static st8 std_32bit_2reg(ArmOpcode *ao, ut64 m, bool shift)
Definition: armass.c:1187
static ut32 getthzeroimmed12(ut32 number)
Definition: armass.c:544
static st8 mem_16bit_2reg(ArmOpcode *ao, ut64 m)
Definition: armass.c:1176
#define w
Definition: crypto_rc6.c:13
uint16_t ut16
const char int mode
Definition: ioapi.h:137
static void list(RzEgg *egg)
Definition: rz-gg.c:52
#define UT32_MAX
Definition: rz_types_base.h:99
Definition: dis.h:35
Definition: getopt.h:84
struct Proc * proc

References ArmOpcode::a, B_BIT, BB_BIT, BT_BIT, C_BITS, cond, conds, D_BIT, DB_BIT, DOTN_BIT, DOTW_BIT, EA_BIT, EIGHT_BIT, err, FD_BIT, getcoproc(), getcoprocreg(), getnum(), getnummemend(), getnummemendbang(), getreg(), getreglist(), getregmembang(), getregmemend(), getregmemstart(), getregmemstartend(), getshiftmemend(), getthbimmed(), getthimmed12(), getthzeroimmed12(), getthzeroimmed16(), H_BIT, i, IA_BIT, ID_BIT, IE_BIT, iflag(), imm, interpret_msrbank(), itmask(), L_BIT, list(), regress::m, mem_16bit_2reg(), mem_32bit_2reg(), NULL, num, ArmOpcode::o, off, ArmOpcode::op, opc, opmask(), parse_hints(), proc, reg, RZ_BIT, rz_str_case(), S_BIT, SH_BIT, shift(), SIXTEEN_BIT, spsr, st32, st8, std_16bit_2reg(), std_32bit_2reg(), std_32bit_3reg(), std_opt_2(), std_opt_3(), strcmpnull(), T_BIT, TB_BIT, THUMB_BRACKREG_CONSTBRACK, THUMB_BRACKREG_REG_SHIFTBRACK, THUMB_BRACKREG_REGBRACK, THUMB_CONST, THUMB_CONSTBANG, THUMB_COPROC_CONST_COREG_COREG_COREG, THUMB_COPROC_CONST_COREG_COREG_COREG_CONST, THUMB_COPROC_CONST_REG_COREG_COREG, THUMB_COPROC_CONST_REG_COREG_COREG_CONST, THUMB_COPROC_CONST_REG_REG_COREG, THUMB_COPROC_COREG_BRACKREG_CONSTBRACK, THUMB_COPROC_COREG_BRACKREG_CONSTBRACKBANG, THUMB_COPROC_COREG_BRACKREGBRACK, THUMB_COPROC_COREG_BRACKREGBRACK_CONST, thumb_getoffset(), thumb_getshift(), THUMB_LIST, THUMB_NONE, THUMB_OTHER, THUMB_OTHER_CONST, THUMB_OTHER_REG, THUMB_REG, THUMB_REG_BRACKREG_CONSTBRACK, THUMB_REG_BRACKREG_CONSTBRACKBANG, THUMB_REG_BRACKREG_REG_SHIFTBRACK, THUMB_REG_BRACKREG_REGBRACK, THUMB_REG_BRACKREGBRACK, THUMB_REG_BRACKREGBRACK_CONST, THUMB_REG_CONST, THUMB_REG_CONST_CONST, THUMB_REG_CONST_REG, THUMB_REG_CONST_REG_SHIFT, THUMB_REG_LIST, THUMB_REG_OTHER, THUMB_REG_REG, THUMB_REG_REG_BRACKREG_CONSTBRACK, THUMB_REG_REG_BRACKREG_CONSTBRACKBANG, THUMB_REG_REG_BRACKREGBRACK, THUMB_REG_REG_BRACKREGBRACK_CONST, THUMB_REG_REG_CONST, THUMB_REG_REG_CONST_CONST, THUMB_REG_REG_REG, THUMB_REG_REG_REG_BRACKREGBRACK, THUMB_REG_REG_REG_REG, THUMB_REG_REG_REG_SHIFT, THUMB_REG_REG_SHIFT, THUMB_REGBANG, THUMB_REGBANG_LIST, thumb_selector(), TT_BIT, TWO_BIT, UT32_MAX, ut64(), w, W_BIT, WB_BIT, width, WT_BIT, and X_BIT.

◆ thumb_getoffset()

static st32 thumb_getoffset ( char *  label,
ut64  cur 
)
static

Definition at line 1157 of file armass.c.

1157  {
1158  st32 res = rz_num_math(NULL, label);
1159  res -= 4;
1160  res -= cur; // possible integer underflow
1161  // printf("thumb_getoffset: %s, %lld, %lld\n", label, res, cur);
1162  return res;
1163 }
RZ_API ut64 rz_num_math(RzNum *num, const char *str)
Definition: unum.c:456

References NULL, rz_num_math(), and st32.

Referenced by thumb_assemble().

◆ thumb_getshift()

static ut32 thumb_getshift ( const char *  str)
static

Definition at line 887 of file armass.c.

887  {
888  // only immediate shifts are ever used by thumb-2. Bit positions are different from ARM.
889  const char *shifts[] = {
890  "LSL", "LSR", "ASR", "ROR", 0, "RRX"
891  };
892  char *type = strdup(str);
893  char *arg;
894  char *space;
895  ut32 res = 0;
896  ut32 shift = false;
897  err = false;
898  ut32 argn;
899  ut32 i;
900 
901  rz_str_case(type, true);
902 
903  if (!strcmp(type, shifts[5])) {
904  // handle RRX alias case
905  res |= 3 << 12;
906  free(type);
907  return res;
908  }
909 
910  space = strchr(type, ' ');
911  if (!space) {
912  free(type);
913  err = true;
914  return 0;
915  }
916  *space = 0;
917  arg = strdup(++space);
918 
919  for (i = 0; shifts[i]; i++) {
920  if (!strcmp(type, shifts[i])) {
921  shift = true;
922  break;
923  }
924  }
925  if (!shift) {
926  err = true;
927  free(type);
928  free(arg);
929  return 0;
930  }
931  res |= i << 12;
932 
933  argn = getnum(arg);
934  if (err || argn > 32) {
935  err = true;
936  free(type);
937  free(arg);
938  return 0;
939  }
940  res |= ((argn & 0x1c) << 2);
941  res |= ((argn & 0x3) << 14);
942 
943  free(type);
944  free(arg);
945  return res;
946 }
static const char * arg(RzAnalysis *a, csh *handle, cs_insn *insn, char *buf, int n)
Definition: arm_esil32.c:136
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 arg(), err, free(), getnum(), i, rz_str_case(), shift(), cmd_descs_generate::str, strdup(), and type.

Referenced by getshiftmemend(), std_32bit_2reg(), std_32bit_3reg(), thumb_assemble(), and thumb_selector().

◆ thumb_selector()

static ut64 thumb_selector ( char *  args[])
static

Definition at line 963 of file armass.c.

963  {
964  ut64 res = 0;
965  ut8 i;
966  for (i = 0; i < 15; i++) {
967  if (args[i] == NULL) {
968  break;
969  }
970  if (getreg(args[i]) != -1) {
971  res |= 1 << (i * 4);
972  continue;
973  }
974  err = false;
975  getnum(args[i]);
976  if (!err) {
977  res |= 2 << (i * 4);
978  continue;
979  }
980  err = false;
982  if (!err) {
983  res |= 3 << (i * 4);
984  continue;
985  }
986  if (getcoproc(args[i]) != -1) {
987  res |= 4 << (i * 4);
988  continue;
989  }
990  if (getcoprocreg(args[i]) != -1) {
991  res |= 5 << (i * 4);
992  continue;
993  }
994  if (getregmemstart(args[i]) != -1) {
995  res |= 6 << (i * 4);
996  continue;
997  }
998  if (getregmemstartend(args[i]) != -1) {
999  res |= 7 << (i * 4);
1000  continue;
1001  }
1002  err = false;
1003  getnummemend(args[i]);
1004  if (!err) {
1005  res |= 8 << (i * 4);
1006  continue;
1007  }
1008  err = false;
1010  if (!err) {
1011  res |= 9 << (i * 4);
1012  continue;
1013  }
1014  if (getregmembang(args[i]) != -1) {
1015  res |= 0xa << (i * 4);
1016  continue;
1017  }
1018  if (getreglist(args[i]) != -1) {
1019  res |= 0xb << (i * 4);
1020  continue;
1021  }
1022  if (getregmemend(args[i]) != -1) {
1023  res |= 0xc << (i * 4);
1024  continue;
1025  }
1026  if (getshiftmemend(args[i]) != -1) {
1027  res |= 0xd << (i * 4);
1028  continue;
1029  }
1030  err = false;
1031  getnumbang(args[i]);
1032  if (!err) {
1033  res |= 0xe << (i * 4);
1034  continue;
1035  }
1036  res |= 0xf << (i * 4);
1037  }
1038  err = false;
1039  return res;
1040 }
static ut64 getnumbang(const char *str)
Definition: armass.c:457
int args
Definition: mipsasm.c:18

References args, err, getcoproc(), getcoprocreg(), getnum(), getnumbang(), getnummemend(), getnummemendbang(), getreg(), getreglist(), getregmembang(), getregmemend(), getregmemstart(), getregmemstartend(), getshiftmemend(), i, NULL, thumb_getshift(), and ut64().

Referenced by thumb_assemble().

Variable Documentation

◆ assemble

AssembleFunction assemble[2] = { &arm_assemble, &thumb_assemble }
static

Definition at line 6207 of file armass.c.

Referenced by armass_assemble().

◆ B_BIT

const ut64 B_BIT = 0x10000
static

Definition at line 174 of file armass.c.

Referenced by opmask(), and thumb_assemble().

◆ BB_BIT

const ut64 BB_BIT = 0x400000
static

Definition at line 180 of file armass.c.

Referenced by opmask(), and thumb_assemble().

◆ BT_BIT

const ut64 BT_BIT = 0x800000
static

Definition at line 181 of file armass.c.

Referenced by opmask(), and thumb_assemble().

◆ C_BITS

const ut64 C_BITS = 0x3c
static

Definition at line 163 of file armass.c.

Referenced by thumb_assemble().

◆ C_MATCH_BIT

const ut64 C_MATCH_BIT = 0x100000000
static

Definition at line 190 of file armass.c.

Referenced by cqcheck(), and opmask().

◆ D_BIT

const ut64 D_BIT = 0x40000
static

Definition at line 176 of file armass.c.

Referenced by opmask(), and thumb_assemble().

◆ DB_BIT

const ut64 DB_BIT = 0x10000000
static

Definition at line 186 of file armass.c.

Referenced by opmask(), and thumb_assemble().

◆ DOTN_BIT

const ut64 DOTN_BIT = 0x40
static

Definition at line 164 of file armass.c.

Referenced by cqcheck(), mem_32bit_2reg(), std_32bit_2reg(), std_32bit_3reg(), and thumb_assemble().

◆ DOTW_BIT

const ut64 DOTW_BIT = 0x80
static

Definition at line 165 of file armass.c.

Referenced by cqcheck(), mem_16bit_2reg(), std_16bit_2reg(), and thumb_assemble().

◆ EA_BIT

const ut64 EA_BIT = 0x2000
static

Definition at line 171 of file armass.c.

Referenced by opmask(), and thumb_assemble().

◆ EIGHT_BIT

const ut64 EIGHT_BIT = 0x100000
static

Definition at line 178 of file armass.c.

Referenced by opmask(), and thumb_assemble().

◆ err

bool err
static

Definition at line 435 of file armass.c.

Referenced by _zip_error_clear(), _zip_error_get(), _zip_error_set_from_source(), _zip_set_open_error(), DotZLib.Deflater::Add(), DotZLib.Inflater::Add(), add_from_zip(), arm_assemble(), autocmplt_cmd_arg_eval_full(), backedge_info(), bad_link(), blast(), bsd_info(), buf_move_back(), cabd_read_headers(), cat(), chmd_fast_find(), chmd_init_decomp(), class_base_error(), class_error(), class_method_error(), class_vtable_error(), clusterSaveConfig(), cmd_pCx(), compress2(), create_cmd_desc(), create_demangler(), cs_open(), DEFINE_HANDLE_TS_FCN(), DEFINE_HANDLE_TS_FCN_AND_SYMBOL(), deflateParams(), do_extract(), do_extract_currentfile(), do_iter_offsets(), do_iter_sections(), do_list(), do_read(), dynamic(), end(), DotZLib.Deflater::Finish(), DotZLib.Inflater::Finish(), flirt_pat_parse_line(), flirt_pat_parse_pattern_mask(), fs__read_filemap(), fs__statfs(), fs__symlink(), fs__write_filemap(), get_ibmi_physical_address(), get_template_params(), get_type_code_string(), getFileCrc(), GetHeapBlocks(), getimmed8(), getnum(), getnumbang(), getnummemend(), getnummemendbang(), GetSingleBlock(), GetSingleSegmentBlock(), getthimmed12(), guess_next_autocmplt_token(), gz_error(), gzclose_r(), gzip_normalize(), handle_redirection(), inet_ntop6(), inet_pton6(), init_demangler(), iter_dbt_commands(), lang_pipe_run(), list_zip(), LLVMFuzzerTestOneInput(), LoadCentralDirectoryRecord(), lzh_decompress(), lzh_read_lens(), main(), make_program_args(), make_program_env(), merge_zip(), microsoft_demangle(), mov(), mpca_lang(), mpca_lang_contents(), mpca_lang_file(), mpca_lang_pipe(), nanosleep(), new_socket(), ocaml_option(), parse_data_type(), parse_dbi_stream_ex_header(), parse_function(), parse_function_args(), parse_function_pointer(), parse_microsoft_mangled_name(), parse_microsoft_rtti_mangled_name(), parse_type_modifier(), pid_to_task(), print_result_diff(), puff(), read_from_file(), read_reset_table(), read_spaninfo(), rz_analysis_class_add_attr_unique(), rz_analysis_class_add_attr_unique_raw(), rz_analysis_class_add_handler(), rz_analysis_class_base_add_handler(), rz_analysis_class_base_del_handler(), rz_analysis_class_base_set(), rz_analysis_class_base_set_raw(), rz_analysis_class_create(), rz_analysis_class_delete_attr(), rz_analysis_class_method_add_handler(), rz_analysis_class_method_del_handler(), rz_analysis_class_method_delete(), rz_analysis_class_method_rename(), rz_analysis_class_method_rename_handler(), rz_analysis_class_method_set(), rz_analysis_class_rename(), rz_analysis_class_rename_handler(), rz_analysis_class_set_attr(), rz_analysis_class_vtable_add_handler(), rz_analysis_class_vtable_del_handler(), rz_analysis_class_vtable_delete(), rz_analysis_class_vtable_set(), rz_analysis_function_blocks_add_handler(), rz_asctime_r(), rz_bin_object_sections_mapping_list(), rz_bin_source_line_info_builder_build_and_fini(), rz_bp_add(), rz_cmd_get_help(), rz_cmd_parsed_args_setargs(), rz_cmd_search(), rz_cons_canvas_line_diagonal(), rz_core_analysis_function_set_signature(), rz_core_bin_sections_print(), rz_core_disasm_pdi_with_buf(), rz_core_project_load_for_cli(), rz_core_prompt_loop(), rz_core_seek_list(), rz_core_write_assembly(), rz_core_write_assembly_fill(), rz_core_write_base64_at(), rz_core_write_base64d_at(), rz_core_write_block(), rz_core_write_duplicate_at(), rz_core_write_hexpair(), rz_core_write_random_at(), rz_ctime_r(), rz_event_new(), rz_flag_set(), rz_gmtime_r(), rz_hash_bang_details_cb(), rz_il_reg_binding_derive(), rz_io_ar_open(), rz_lib_path(), rz_localtime_r(), rz_main_rz_bin(), rz_num_calc(), rz_num_math(), rz_open_malloc_handler(), rz_project_err_message(), rz_project_save_file(), rz_project_save_handler(), rz_str_unescape(), rz_sys_perror_str(), rz_time_stamp_to_str(), rz_write_from_file_handler(), rz_write_from_io_xchg_handler(), rz_write_from_socket_handler(), rzfind_open_file(), sdb_foreach_list_filter_cb(), sdb_ht_internal_insert(), SOCKOPT_SETTER(), std_32bit_2reg(), std_32bit_3reg(), strex(), tar(), test(), test_invalids(), test_valids(), thumb_assemble(), thumb_getshift(), thumb_selector(), ts_node_handle_arg_prargs(), uncompress2(), unz64local_CheckCurrentFileCoherencyHeader(), unz64local_getByte(), unz64local_GetCurrentFileInfoInternal(), unz64local_getLong(), unz64local_getLong64(), unz64local_getShort(), unzCloseCurrentFile(), unzGetCurrentFileInfo(), unzGetFilePos(), unzGoToFilePos64(), unzGoToFirstFile(), unzGoToNextFile(), unzLocateFile(), unzOpenCurrentFile3(), unzOpenInternal(), unzReadCurrentFile(), unzRepair(), unzSetOffset64(), uv__accept(), uv__async_start(), uv__cancel_read_console(), uv__create_stdio_pipe_pair(), uv__custom_sem_init(), uv__drain(), uv__dup2_cloexec(), uv__emfile_trick(), uv__fd_hash_init(), uv__fs_copyfile(), uv__get_cpu_speed(), uv__getaddrinfo_work(), uv__getnameinfo_work(), uv__inotify_fork(), uv__io_fork(), uv__io_poll(), uv__kill(), uv__make_socketpair(), uv__open_cloexec(), uv__pipe_getname(), uv__pipe_getsockpeername(), uv__pipe_read_ipc(), uv__pipe_write_data(), uv__pipe_write_ipc(), uv__platform_loop_init(), uv__process_child_init(), uv__process_open_stream(), uv__pthread_setname_np(), uv__pthread_sigmask(), uv__queue_done(), uv__read(), uv__server_io(), uv__set_process_title(), uv__signal_loop_once_init(), uv__signal_start(), uv__slow_poll_process_poll_req(), uv__socket(), uv__stdio_create(), uv__stream_init(), uv__stream_recv_cmsg(), uv__tcp_bind(), uv__tcp_connect(), uv__tcp_xfer_import(), uv__udp_bind(), uv__udp_connect(), uv__udp_disconnect(), uv__udp_init_ex(), uv__udp_recv_start(), uv__udp_send(), uv__udp_set_membership4(), uv__udp_set_membership6(), uv__udp_set_source_membership4(), uv__udp_set_source_membership6(), uv__udp_try_send(), uv__unknown_err_code(), uv__work_done(), uv__write(), uv_accept(), uv_async_init(), uv_barrier_init(), uv_cond_destroy(), uv_cond_init(), uv_cpu_info(), uv_err_name(), uv_err_name_r(), uv_exepath(), uv_fs_access(), uv_fs_chmod(), uv_fs_chown(), uv_fs_copyfile(), uv_fs_event_start(), uv_fs_lchown(), uv_fs_link(), uv_fs_lstat(), uv_fs_lutime(), uv_fs_mkdir(), uv_fs_mkdtemp(), uv_fs_mkstemp(), uv_fs_open(), uv_fs_opendir(), uv_fs_poll_start(), uv_fs_readlink(), uv_fs_realpath(), uv_fs_rename(), uv_fs_rmdir(), uv_fs_scandir(), uv_fs_stat(), uv_fs_statfs(), uv_fs_symlink(), uv_fs_unlink(), uv_fs_utime(), uv_getaddrinfo(), uv_kill(), uv_listen(), uv_loop_configure(), uv_loop_delete(), uv_loop_fork(), uv_loop_init(), uv_mutex_init(), uv_mutex_init_recursive(), uv_mutex_trylock(), uv_pipe_accept(), uv_pipe_bind(), uv_pipe_connect(), uv_pipe_endgame(), uv_pipe_open(), uv_pipe_zero_readfile_thread_proc(), uv_poll_init(), uv_process_fs_event_req(), uv_process_kill(), uv_process_pipe_connect_req(), uv_process_pipe_read_req(), uv_process_pipe_write_req(), uv_process_tcp_accept_req(), uv_process_tcp_connect_req(), uv_process_tcp_read_req(), uv_process_tcp_write_req(), uv_process_tty_write_req(), uv_process_udp_recv_req(), uv_process_udp_send_req(), uv_read_start(), uv_read_stop(), uv_resident_set_memory(), uv_rwlock_tryrdlock(), uv_rwlock_trywrlock(), uv_set_pipe_handle(), uv_set_process_title(), uv_signal_init(), uv_spawn(), uv_stdio_pipe_server(), uv_strerror(), uv_strerror_r(), uv_tcp_accept(), uv_tcp_endgame(), uv_tcp_init_ex(), uv_tcp_keepalive(), uv_tcp_listen(), uv_tcp_nodelay(), uv_tcp_open(), uv_tcp_set_socket(), uv_tcp_try_bind(), uv_tcp_try_connect(), uv_thread_create_ex(), uv_tty_get_winsize(), uv_tty_read_stop(), uv_tty_reset_mode(), uv_tty_set_mode(), uv_udp_maybe_bind(), uv_udp_open(), uv_udp_set_membership(), uv_udp_set_source_membership(), uv_write(), uv_write2(), wasm_dis(), Write_EndOfCentralDirectoryRecord(), Write_GlobalComment(), Write_LocalFileHeader(), Write_Zip64EndOfCentralDirectoryLocator(), Write_Zip64EndOfCentralDirectoryRecord(), zError(), zip64FlushWriteBuffer(), zip64local_getByte(), zip64local_getLong(), zip64local_getLong64(), zip64local_getShort(), zip_error_fini(), zip_error_init(), zip_error_set(), zip_error_strerror(), zipClose(), zipCloseFileInZipRaw64(), zipOpen3(), zipOpenNewFileInZip4_64(), and zipWriteInFileInZip().

◆ FD_BIT

const ut64 FD_BIT = 0x4000
static

Definition at line 172 of file armass.c.

Referenced by opmask(), and thumb_assemble().

◆ H_BIT

const ut64 H_BIT = 0x20000
static

Definition at line 175 of file armass.c.

Referenced by opmask(), and thumb_assemble().

◆ IA_BIT

const ut64 IA_BIT = 0x8000000
static

Definition at line 185 of file armass.c.

Referenced by opmask(), and thumb_assemble().

◆ ID_BIT

const ut64 ID_BIT = 0x1000
static

Definition at line 170 of file armass.c.

Referenced by opmask(), and thumb_assemble().

◆ IE_BIT

const ut64 IE_BIT = 0x800
static

Definition at line 169 of file armass.c.

Referenced by opmask(), and thumb_assemble().

◆ L_BIT

const ut64 L_BIT = 0x100
static

Definition at line 166 of file armass.c.

Referenced by opmask(), and thumb_assemble().

◆ M_BIT

const ut64 M_BIT = 0x1
static

Definition at line 161 of file armass.c.

Referenced by opmask().

◆ ops

ArmOp ops[]
static

Definition at line 59 of file armass.c.

Referenced by arm_assemble().

◆ RZ_BIT

const ut64 RZ_BIT = 0x4000000
static

Definition at line 184 of file armass.c.

Referenced by opmask(), and thumb_assemble().

◆ S_BIT

const ut64 S_BIT = 0x2
static

Definition at line 162 of file armass.c.

Referenced by opmask(), std_32bit_2reg(), std_32bit_3reg(), and thumb_assemble().

◆ SH_BIT

const ut64 SH_BIT = 0x20000000
static

Definition at line 187 of file armass.c.

Referenced by opmask(), and thumb_assemble().

◆ SIXTEEN_BIT

const ut64 SIXTEEN_BIT = 0x200000
static

Definition at line 179 of file armass.c.

Referenced by opmask(), and thumb_assemble().

◆ T_BIT

const ut64 T_BIT = 0x8000
static

Definition at line 173 of file armass.c.

Referenced by opmask(), and thumb_assemble().

◆ TB_BIT

const ut64 TB_BIT = 0x1000000
static

Definition at line 182 of file armass.c.

Referenced by opmask(), and thumb_assemble().

◆ TT_BIT

const ut64 TT_BIT = 0x2000000
static

Definition at line 183 of file armass.c.

Referenced by opmask(), and thumb_assemble().

◆ TWO_BIT

const ut64 TWO_BIT = 0x400
static

Definition at line 168 of file armass.c.

Referenced by opmask(), and thumb_assemble().

◆ W_BIT

const ut64 W_BIT = 0x80000
static

Definition at line 177 of file armass.c.

Referenced by opmask(), and thumb_assemble().

◆ WB_BIT

const ut64 WB_BIT = 0x40000000
static

Definition at line 188 of file armass.c.

Referenced by opmask(), and thumb_assemble().

◆ WT_BIT

const ut64 WT_BIT = 0x80000000
static

Definition at line 189 of file armass.c.

Referenced by opmask(), and thumb_assemble().

◆ X_BIT

const ut64 X_BIT = 0x200
static

Definition at line 167 of file armass.c.

Referenced by opmask(), and thumb_assemble().