Skip to content

Commit

Permalink
arm64: Adding literal load / stores.
Browse files Browse the repository at this point in the history
  • Loading branch information
mikeakohn committed Jan 21, 2024
1 parent 3150baf commit c4f9b62
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 27 deletions.
84 changes: 81 additions & 3 deletions asm/arm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -916,9 +916,11 @@ static int op_ld_st_imm_p(
if (operands[0].type == OPERAND_REG_SCALAR)
{
v = 1;
opcode &= 0x3fffffff;

size = operands[0].attribute & 0x3;
size = operands[0].attribute;
if (size == 4) { opc = 2; }
size = size & 0x3;
}

if (check_range(asm_context, "offset", offset, -256, 255) != 0)
Expand Down Expand Up @@ -979,9 +981,11 @@ static int op_ld_st_imm(
if (operands[0].type == OPERAND_REG_SCALAR)
{
v = 1;
opcode &= 0x3fffffff;

size = operands[0].attribute & 0x3;
size = operands[0].attribute;
if (size == 4) { opc = 2; }
size = size & 0x3;
shift = size;
}
else
Expand All @@ -1002,7 +1006,6 @@ static int op_ld_st_imm(

opcode |= (size << 30) |
(v << 26) |
(1 << 24) |
(opc << 22) |
(((offset >> shift) & 0xfff) << 10) |
(operands[1].value << 5) |
Expand All @@ -1013,6 +1016,74 @@ static int op_ld_st_imm(
return 4;
}

static int op_ld_literal(
AsmContext *asm_context,
struct _operand *operands,
int operand_count,
uint32_t opcode,
char *instr,
char reg_type)
{
if (operand_count != 2)
{
return -2;
}

if (operands[1].type != OPERAND_ADDRESS) { return -2; }

if (reg_type == 'x' && operands[0].type != OPERAND_REG_64)
{
return -2;
}

if (operands[0].type != OPERAND_REG_32 &&
operands[0].type != OPERAND_REG_64 &&
operands[0].type != OPERAND_REG_SCALAR)
{
return -2;
}

int offset = operands[1].value - asm_context->address;
int v = 0;
int size = 0;

if (operands[0].type == OPERAND_REG_SCALAR)
{
v = 1;

switch (operands[0].attribute)
{
case 2: size = 0; break;
case 3: size = 1; break;
case 4: size = 2; break;
default: return -2;
}
}

const int min = -(1 << 20);
const int max = (1 << 20) - 1;

if (check_range(asm_context, "offset", offset, min, max) != 0)
{
return -1;
}

if ((offset & 3) != 0)
{
print_error_align(asm_context, 4);
return -1;
}

opcode |= (size << 30) |
(v << 26) |
(((offset >> 2) & 0x7ffff) << 5) |
operands[0].value;

add_bin32(asm_context, opcode, IS_OPCODE);

return 4;
}

int parse_instruction_arm64(AsmContext *asm_context, char *instr)
{
char instr_case_mem[TOKENLEN];
Expand Down Expand Up @@ -1465,6 +1536,13 @@ int parse_instruction_arm64(AsmContext *asm_context, char *instr)
if (ret == -2) { continue; }
return ret;
}
case OP_LD_LITERAL:
{
ret = op_ld_literal(asm_context, operands, operand_count, table_arm64[n].opcode, instr, table_arm64[n].reg_type);

if (ret == -2) { continue; }
return ret;
}
default:
{
break;
Expand Down
29 changes: 25 additions & 4 deletions disasm/arm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -434,10 +434,9 @@ int disasm_arm64(
reg_name = scalar_size[size];
}

int imm = (opcode >> 12) & 0x1ff;
imm = (opcode >> 12) & 0x1ff;
imm = imm << 23;
imm = imm >> 23;
imm = imm << size;
imm = imm >> (23 - size);

if (index_type == 1)
{
Expand All @@ -462,7 +461,7 @@ int disasm_arm64(
}
case OP_LD_ST_IMM:
{
int imm = ((opcode >> 10) & 0xfff) << 1;
imm = ((opcode >> 10) & 0xfff) << 1;
char reg_name = (size & 1) == 0 ? 'x' : 'w';

if (v == 1)
Expand Down Expand Up @@ -491,6 +490,28 @@ int disasm_arm64(

return 4;
}
case OP_LD_LITERAL:
{
imm = ((opcode >> 5) & 0x7ffff);
imm = imm << 13;
imm = imm >> (13 - 2);
char reg_name = (size & 1) == 0 ? 'x' : 'w';

if (v == 1)
{
size |= ((opcode >> 23) & 1) << 2;
reg_name = scalar_size[size];
}

snprintf(instruction, length, "%s %c%d, 0x%04x (offset=%d)",
table_arm64[n].instr,
reg_name,
rd,
address + imm,
imm);

return 4;
}
default:
{
//print_error_internal(asm_context, __FILE__, __LINE__);
Expand Down
39 changes: 21 additions & 18 deletions table/arm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,28 +90,32 @@ struct _table_arm64 table_arm64[] =
{ "eret", 0xd69f0000, 0xfffffc1f, 3, '0', OP_RET },
{ "drps", 0xd6bf0000, 0xfffffc1f, 3, '0', OP_RET },

// C3.3.5 Load register (literal).
{ "ldr", 0x1c000000, 0x3b000000, 2, '0', OP_LD_LITERAL },
{ "ldrsw", 0x1c000000, 0x3b000000, 2, 'x', OP_LD_LITERAL },

// C3.3.8 Load/store register (immediate post-indexed).
// C3.3.9 Load/store register (immediate pre-indexed).
{ "strb", 0x38000000, 0x3fe00000, 3, 'w', OP_LD_ST_IMM_P },
{ "strh", 0x78000000, 0x3fe00000, 3, 'w', OP_LD_ST_IMM_P },
{ "str", 0xb8000000, 0x3fe00000, 3, '0', OP_LD_ST_IMM_P },
{ "strb", 0x38000000, 0x3be00000, 3, 'w', OP_LD_ST_IMM_P },
{ "strh", 0x78000000, 0x3be00000, 3, 'w', OP_LD_ST_IMM_P },
{ "str", 0xb8000000, 0x3be00000, 3, '0', OP_LD_ST_IMM_P },
{ "strh", 0x78000000, 0x3be00000, 3, 'w', OP_LD_ST_IMM_P },
{ "ldrb", 0x38400000, 0x3fe00000, 3, 'w', OP_LD_ST_IMM_P },
{ "ldrsb", 0x38400000, 0x3fe00000, 3, '0', OP_LD_ST_IMM_P },
{ "ldrh", 0x78400000, 0x3fe00000, 3, 'w', OP_LD_ST_IMM_P },
{ "ldrsh", 0x78400000, 0x3fe00000, 3, '0', OP_LD_ST_IMM_P },
{ "ldr", 0xb8400000, 0x3fe00000, 3, '0', OP_LD_ST_IMM_P },
{ "ldrb", 0x38400000, 0x3be00000, 3, 'w', OP_LD_ST_IMM_P },
{ "ldrsb", 0x38400000, 0x3be00000, 3, '0', OP_LD_ST_IMM_P },
{ "ldrh", 0x78400000, 0x3be00000, 3, 'w', OP_LD_ST_IMM_P },
{ "ldrsh", 0x78400000, 0x3be00000, 3, '0', OP_LD_ST_IMM_P },
{ "ldr", 0xb8400000, 0x3be00000, 3, '0', OP_LD_ST_IMM_P },

// C3.3.13 Load/store register (unsigned immediate).
{ "strb", 0x39000000, 0x3fe00000, 3, 'w', OP_LD_ST_IMM },
{ "strh", 0x79000000, 0x3fe00000, 3, 'w', OP_LD_ST_IMM },
{ "str", 0xb9000000, 0x3fe00000, 3, '0', OP_LD_ST_IMM },
{ "strh", 0x79000000, 0x3fe00000, 3, 'w', OP_LD_ST_IMM },
{ "ldrb", 0x39400000, 0x3fe00000, 3, 'w', OP_LD_ST_IMM },
{ "ldrsb", 0x39400000, 0x3fe00000, 3, '0', OP_LD_ST_IMM },
{ "ldrh", 0x79400000, 0x3fe00000, 3, 'w', OP_LD_ST_IMM },
{ "ldrsh", 0x79400000, 0x3fe00000, 3, '0', OP_LD_ST_IMM },
{ "ldr", 0xb9400000, 0x3fe00000, 3, '0', OP_LD_ST_IMM },
{ "strb", 0x39000000, 0x3be00000, 3, 'w', OP_LD_ST_IMM },
{ "strh", 0x79000000, 0x3be00000, 3, 'w', OP_LD_ST_IMM },
{ "str", 0xb9000000, 0x3be00000, 3, '0', OP_LD_ST_IMM },
{ "strh", 0x79000000, 0x3be00000, 3, 'w', OP_LD_ST_IMM },
{ "ldrb", 0x39400000, 0x3be00000, 3, 'w', OP_LD_ST_IMM },
{ "ldrsb", 0x39400000, 0x3be00000, 3, '0', OP_LD_ST_IMM },
{ "ldrh", 0x79400000, 0x3be00000, 3, 'w', OP_LD_ST_IMM },
{ "ldrsh", 0x79400000, 0x3be00000, 3, '0', OP_LD_ST_IMM },
{ "ldr", 0xb9400000, 0x3be00000, 3, '0', OP_LD_ST_IMM },

// C3.4.6 PC-rel addressing.
{ "adr", 0x10000000, 0x9f000000, 2, 'x', OP_REG_RELATIVE },
Expand Down Expand Up @@ -307,7 +311,6 @@ struct _table_arm64_uncond_branch table_arm64_uncond_branch[] =
// C3.3.2 AdvSIMD load/store multiple structures (post-indexed).
// C3.3.3 AdvSIMD load/store single structures.
// C3.3.4 AdvSIMD load/store single structures (post-indexed).
// C3.3.5 Load register (literal).
// C3.3.6 Load/store exclusive.
// C3.3.7 Load/store no-allocate pair (offset).
// C3.3.10 Load/store register (register offset).
Expand Down
4 changes: 2 additions & 2 deletions table/arm64.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ enum
OP_VECTOR_V_V_V,
OP_MATH_R_R_R,
OP_REG_REG_CRYPT,
OP_RET,
OP_LD_ST_IMM_P,
OP_LD_ST_IMM,

OP_RET,
OP_LD_LITERAL,
};

#define ARM64_IMM 0xff
Expand Down

0 comments on commit c4f9b62

Please sign in to comment.