Skip to content

Commit

Permalink
update instr.d and disasmarm.d for AArch64
Browse files Browse the repository at this point in the history
  • Loading branch information
WalterBright authored and thewilsonator committed Aug 4, 2024
1 parent 548e9c1 commit 713a27c
Show file tree
Hide file tree
Showing 2 changed files with 219 additions and 11 deletions.
34 changes: 25 additions & 9 deletions compiler/src/dmd/backend/arm/disasmarm.d
Original file line number Diff line number Diff line change
Expand Up @@ -378,12 +378,15 @@ void disassemble(uint c) @trusted
p1 = addsubTab[opS];
p2 = regString(sf, Rd);
p3 = regString(sf, Rn);
p4 = wordtostring(imm12 << (sh * 12));
p4 = wordtostring(imm12);
if (sh)
p5 = "lsl #12";

if (opS == 0 && sh == 0 && imm12 == 0 && (Rd == 31 || Rn == 31))
{
p1 = "mov"; // https://www.scs.stanford.edu/~zyedidia/arm64/add_addsub_imm.html
p4 = "";
p5 = "";
}
else if (opS == 1 && Rd == 31) // adds
{
Expand Down Expand Up @@ -1377,7 +1380,7 @@ void disassemble(uint c) @trusted
p5 = "";
}
}
else if (field(ins, 28, 24) == 11 && field(ins, 21, 21) == 0) // https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#addsub_shift
else if (field(ins, 28, 24) == 0x0B && field(ins, 21, 21) == 0) // https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#addsub_shift
{
if (log) printf("Add/subtract (shifted register)\n");
uint sf = field(ins, 31, 31);
Expand Down Expand Up @@ -1429,7 +1432,7 @@ void disassemble(uint c) @trusted
}
}
}
else if (field(ins, 28, 24) == 11 && field(ins, 21, 21)) // https://www.scs.stanford.edu/~zyedidia/arm64/subs_addsub_ext.html
else if (field(ins, 28, 24) == 0x0B && field(ins, 21, 21)) // https://www.scs.stanford.edu/~zyedidia/arm64/subs_addsub_ext.html
{
if (log) printf("Add/subtract (extended register)\n");
uint sf = field(ins, 31, 31);
Expand Down Expand Up @@ -1474,7 +1477,7 @@ void disassemble(uint c) @trusted
p1 = "cmn"; // https://www.scs.stanford.edu/~zyedidia/arm64/cmn_adds_addsub_ext.html
shiftP();
}
else if (opS == 3 && Rd == 0)
else if (opS == 3 && Rd == 31)
{
p1 = "cmp"; // https://www.scs.stanford.edu/~zyedidia/arm64/cmp_subs_addsub_ext.html
shiftP();
Expand Down Expand Up @@ -1600,9 +1603,18 @@ void disassemble(uint c) @trusted
string[4] opstring = [ "csel", "csinc", "csinv", "csneg" ];
p1 = opstring[op * 2 + (op2 & 1)];
p2 = regString(sf, Rd);
p3 = regString(sf, Rn);
p4 = regString(sf, Rm);
p5 = condstring[cond];
if (op * 2 + (op2 & 1) == 1 &&
Rm == 0x1F && Rn == 0x1F)
{
p1 = "cset";
p3 = condstring[cond ^ 1];
}
else
{
p3 = regString(sf, Rn);
p4 = regString(sf, Rm);
p5 = condstring[cond];
}
}
else if (field(ins, 28, 24) == 0x1B) // http://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#dp_3src
{
Expand Down Expand Up @@ -2097,7 +2109,7 @@ const(char)[] labeltostring(ulong w)
@trusted
const(char)[] indexString(uint reg)
{
__gshared char[1 + 2 + 1 + 1] EA;
__gshared char[1 + 3 + 1 + 1] EA;

const n = snprintf(EA.ptr, EA.length, "[%s]", regString(1, reg).ptr);
assert(n <= EA.length);
Expand Down Expand Up @@ -2220,8 +2232,12 @@ unittest
unittest
{
int line64 = __LINE__;
string[46] cases64 = // 64 bit code gen
string[50] cases64 = // 64 bit code gen
[
"B9 00 03 A1 str w1,[x29]",
"1A 9F A7 E0 cset w0,lt",
"91 40 00 00 add x0,x0,#0,lsl #12",
"D5 3B D0 40 mrs x0,S3_3_c13_c0_2",
"A8 C1 7B FD ldp x29,x30,[sp],#16",
"90 00 00 00 adrp x0,#0",
"A9 01 7B FD stp x29,x30,[sp,#16]",
Expand Down
196 changes: 194 additions & 2 deletions compiler/src/dmd/backend/arm/instr.d
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,19 @@ import core.stdc.stdio;
nothrow:
@safe:

enum Extend
{
UXTB,
UXTH,
UXTW,
LSL,
UXTX = LSL,
SXTB,
SXTH,
SXTW,
SXTX,
}

/************************
* AArch64 instructions
*/
Expand All @@ -28,6 +41,7 @@ struct INSTR

enum uint nop = 0xD503201F;

alias reg_t = ubyte;

/************************************ Reserved ***********************************************/
/* https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#reserved */
Expand Down Expand Up @@ -68,6 +82,7 @@ struct INSTR
*/
static uint addsub_imm(uint sf, uint op, uint S, uint sh, uint imm12, ubyte Rn, ubyte Rd)
{
assert(imm12 < 0x1000);
return (sf << 31) |
(op << 30) |
(S << 29) |
Expand Down Expand Up @@ -118,6 +133,17 @@ struct INSTR
/****************************** Branches, Exception Generating and System instructions **************/
/* https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#control */

/* System register move
* MSR/MRS
* https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#systemmove
*/
static uint systemmove(uint L, uint sysreg, ubyte Rt)
{
return (0x354 << 22) | (L << 21) | (1 << 20) | (sysreg << 5) | Rt;
}

enum tpidr_el0 = 0x5E82;

/* Unconditional branch (register)
* BLR
* https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#branch_reg
Expand Down Expand Up @@ -211,10 +237,12 @@ struct INSTR
*/
static uint addsub_shift(uint sf, uint op, uint S, uint shift, ubyte Rm, uint imm6, ubyte Rn, ubyte Rd)
{
assert(shift < 4);
assert(imm6 < 64);
return (sf << 31) |
(op << 30) |
(S << 29) |
(0xA << 24) |
(0xB << 24) |
(shift << 22) |
(0 << 21) |
(Rm << 16) |
Expand All @@ -229,6 +257,7 @@ struct INSTR
*/
static uint addsub_ext(uint sf, uint op, uint S, uint opt, ubyte Rm, uint option, uint imm3, ubyte Rn, ubyte Rd)
{
assert(imm3 < 8);
return (sf << 31) |
(op << 30) |
(S << 29) |
Expand Down Expand Up @@ -308,6 +337,7 @@ struct INSTR
*/
static uint condsel(uint sf, uint op, uint S, ubyte Rm, uint cond, uint o2, ubyte Rn, ubyte Rd)
{
assert(cond < 16);
return (sf << 31) | (op << 30) | (S << 29) | (0xD4 << 21) | (Rm << 16) | (cond << 12) | (o2 << 10) | (Rn << 5) | Rd;
}

Expand Down Expand Up @@ -385,6 +415,24 @@ struct INSTR
Rt;
}

/* Load/store register (register offset)
* https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#ldst_regoff
*/
static uint ldst_regoff(uint size, uint VR, uint opc, ubyte Rm, uint option, uint S, ubyte Rn, ubyte Rt)
{
return (size << 30) |
(7 << 27) |
(VR << 26) |
(opc << 22) |
(1 << 21) |
(Rm << 16) |
(option << 13) |
(S << 12) |
(1 << 11) |
(Rn << 5) |
Rt;
}

/* Load/store register (unsigned immediate)
* https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#ldst_pos
*/
Expand Down Expand Up @@ -485,6 +533,38 @@ struct INSTR
return subs_imm(sf, sh, imm12, Rn, 31);
}

/* SUBS Rd, Rn, Rm, shift, #imm6
* http://www.scs.stanford.edu/~zyedidia/arm64/subs_addsub_shift.html
*/
static uint subs_shift(uint sf, ubyte Rm, uint shift, uint imm6, ubyte Rn, ubyte Rd)
{
return addsub_shift(sf, 1, 1, shift, Rm, imm6, Rn, Rd);
}

/* CMP Rn, Rm, shift, #imm6
* http://www.scs.stanford.edu/~zyedidia/arm64/cmp_subs_addsub_shift.html
*/
static uint cmp_shift(uint sf, ubyte Rm, uint shift, uint imm6, ubyte Rn)
{
return addsub_shift(sf, 1, 1, shift, Rm, imm6, Rn, 0x1F);
}

/* SUBS Rd, Rn, Rm, extend, #imm3
* http://www.scs.stanford.edu/~zyedidia/arm64/cmp_subs_addsub_ext.html
*/
static uint subs_ext(uint sf, ubyte Rm, uint option, uint imm3, ubyte Rn, ubyte Rd)
{
return addsub_ext(sf, 1, 1, 0, Rm, option, imm3, Rn, Rd);
}

/* CMP Rn, Rm, extend, #imm3
* http://www.scs.stanford.edu/~zyedidia/arm64/cmp_subs_addsub_ext.html
*/
static uint cmp_ext(uint sf, ubyte Rm, uint option, uint imm3, ubyte Rn)
{
return addsub_ext(sf, 1, 1, 0, Rm, option, imm3, Rn, 0x1F);
}

/* ORR Rd, Rn, Rm{, shift #amount}
* https://www.scs.stanford.edu/~zyedidia/arm64/orr_log_shift.html
*/
Expand All @@ -503,6 +583,14 @@ struct INSTR
return orr_shifted_register(sf, 0, Rm, 0, 31, Rd);
}

/* CSINC Rd, Rn, Rm, <cond>?
* https://www.scs.stanford.edu/~zyedidia/arm64/csinc.html
*/
static uint csinc(uint sf, ubyte Rm, uint cond, ubyte Rn, ubyte Rd)
{
return condsel(sf, 0, 0, Rm, cond, 1, Rn, Rd);
}

/* Loads and Stores */

/* Load/store no-allocate pair (offset)
Expand Down Expand Up @@ -537,12 +625,36 @@ struct INSTR
return ldstpair(opc, VR, 3, L, imm7, Rt2, Rn, Rt);
}

/* STRB (immediate) Unsigned offset
* https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#ldst_pos
* https://www.scs.stanford.edu/~zyedidia/arm64/strb_imm.html
*/
static uint strb_imm(ubyte Rt, ubyte Rn, ulong offset)
{
// STRB Rt,[Xn,#offset]
uint size = 0;
uint imm12 = offset & 0xFFF;
return ldst_pos(0, 0, 0, imm12, Rn, Rt);
}

/* STRH (immediate) Unsigned offset
* https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#ldst_pos
* https://www.scs.stanford.edu/~zyedidia/arm64/strh_imm.html
*/
static uint strh_imm(ubyte Rt, ubyte Rn, ulong offset)
{
// STRH Rt,[Xn,#offset]
uint size = 1;
uint imm12 = offset & 0xFFF;
return ldst_pos(0, 0, 0, imm12, Rn, Rt);
}

/* STR (immediate) Unsigned offset
* https://www.scs.stanford.edu/~zyedidia/arm64/str_imm_gen.html
*/
static uint str_imm_gen(uint is64, ubyte Rt, ubyte Rn, ulong offset)
{
// str Rt,[Rn,#offset]
// STR Rt,[Xn,#offset]
uint size = 2 + is64;
uint imm12 = (cast(uint)offset >> (is64 ? 3 : 2)) & 0xFFF;
return ldst_pos(size, 0, 0, imm12, Rn, Rt);
Expand All @@ -558,4 +670,84 @@ struct INSTR
uint imm12 = (cast(uint)offset >> (is64 ? 3 : 2)) & 0xFFF;
return ldst_pos(size, 0, 1, imm12, Rn, Rt);
}

/* STRB (register)
* https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#ldst_regoff
* https://www.scs.stanford.edu/~zyedidia/arm64/strb_reg.html
*/
static uint strb_reg(reg_t Rindex,uint extend,uint S,reg_t Xbase,reg_t Rt)
{
// STRB Rt,Xbase,Rindex,extend S
return ldst_regoff(0, 0, 0, Rindex, extend, S, Xbase, Rt);
}

/* STRH (register)
* https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#ldst_regoff
* https://www.scs.stanford.edu/~zyedidia/arm64/strh_reg.html
*/
static uint strh_reg(reg_t Rindex,uint extend,uint S,reg_t Xbase,reg_t Rt)
{
// STRH Rt,Xbase,Rindex,extend S
return ldst_regoff(0, 1, 0, Rindex, extend, S, Xbase, Rt);
}

/* STR (register)
* https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#ldst_regoff
* https://www.scs.stanford.edu/~zyedidia/arm64/str_reg_gen.html
*/
static uint str_reg_gen(uint sz,reg_t Rindex,uint extend,uint S,reg_t Rbase,reg_t Rt)
{
// STR Rt,Rbase,Rindex,extend S
return ldst_regoff(2 | sz, 0, 0, Rindex, extend, S, Rbase, Rt);
}

/* LDRB (register) Extended register
* https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#ldst_regoff
* https://www.scs.stanford.edu/~zyedidia/arm64/ldrb_reg.html
*/
static uint ldrb_reg(uint sz,reg_t Rindex,uint extend,uint S,reg_t Rbase,reg_t Rt)
{
// LDRB Rt,Rbase,Rindex,extend S
return ldst_regoff(0, 0, 1, Rindex, extend, S, Rbase, Rt);
}

/* LDRSB (register) Extended register
* https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#ldst_regoff
* https://www.scs.stanford.edu/~zyedidia/arm64/ldrb_reg.html
*/
static uint ldrsb_reg(uint sz,reg_t Rindex,uint extend,uint S,reg_t Rbase,reg_t Rt)
{
// LDRB Rt,Rbase,Rindex,extend S
return ldst_regoff(0, 0, 2 + (sz == 8), Rindex, extend, S, Rbase, Rt);
}

/* LDRH (register) Extended register
* https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#ldst_regoff
* https://www.scs.stanford.edu/~zyedidia/arm64/ldrh_reg.html
*/
static uint ldrh_reg(uint sz,reg_t Rindex,uint extend,uint S,reg_t Rbase,reg_t Rt)
{
// LDRH Rt,Rbase,Rindex,extend S
return ldst_regoff(1, 0, 1, Rindex, extend, S, Rbase, Rt);
}

/* LDRSH (register) Extended register
* https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#ldst_regoff
* https://www.scs.stanford.edu/~zyedidia/arm64/ldrsh_reg.html
*/
static uint ldrsh_reg(uint sz,reg_t Rindex,uint extend,uint S,reg_t Rbase,reg_t Rt)
{
// LDRSH Rt,Rbase,Rindex,extend S
return ldst_regoff(1, 0, 2 + (sz == 8), Rindex, extend, S, Rbase, Rt);
}

/* LDR (register)
* https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#ldst_regoff
* https://www.scs.stanford.edu/~zyedidia/arm64/ldr_reg_gen.html
*/
static uint ldr_reg_gen(uint sz,reg_t Rindex,uint extend,uint S,reg_t Rbase,reg_t Rt)
{
// LDR Rt,Rbase,Rindex,extend S
return ldst_regoff(2 | sz, 0, 1, Rindex, extend, S, Rbase, Rt);
}
}

0 comments on commit 713a27c

Please sign in to comment.