shithub: riscv

Download patch

ref: 14b69dcde0dfbb72df721424571d07cdf3dcbf05
parent: 9920ecc04b87cab3968f7f0c286b264bd31e132f
author: cinap_lenrek <[email protected]>
date: Fri May 3 17:00:17 EDT 2019

libmach: initial arm64 support

--- /dev/null
+++ b/sys/src/libmach/7.c
@@ -1,0 +1,80 @@
+/*
+ * arm definition
+ */
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <mach.h>
+
+#include "/arm64/include/ureg.h"
+
+#define	REGOFF(x)	(uintptr)(&((struct Ureg *) 0)->x)
+
+#define SP		REGOFF(sp)
+#define PC		REGOFF(pc)
+
+#define	REGSIZE		sizeof(struct Ureg)
+
+Reglist arm64reglist[] =
+{
+	{"TYPE",	REGOFF(type),		RINT|RRDONLY, 'Y'},
+	{"PSR",		REGOFF(psr),		RINT|RRDONLY, 'Y'},
+	{"PC",		PC,			RINT, 'Y'},
+	{"SP",		SP,			RINT, 'Y'},
+	{"R30",		REGOFF(r30),		RINT, 'Y'},
+	{"R29",		REGOFF(r29),		RINT, 'Y'},
+	{"R28",		REGOFF(r28),		RINT, 'Y'},
+	{"R27",		REGOFF(r27),		RINT, 'Y'},
+	{"R26",		REGOFF(r26),		RINT, 'Y'},
+	{"R25",		REGOFF(r25),		RINT, 'Y'},
+	{"R24",		REGOFF(r24),		RINT, 'Y'},
+	{"R23",		REGOFF(r23),		RINT, 'Y'},
+	{"R22",		REGOFF(r22),		RINT, 'Y'},
+	{"R21",		REGOFF(r21),		RINT, 'Y'},
+	{"R20",		REGOFF(r20),		RINT, 'Y'},
+	{"R19",		REGOFF(r19),		RINT, 'Y'},
+	{"R18",		REGOFF(r18),		RINT, 'Y'},
+	{"R17",		REGOFF(r17),		RINT, 'Y'},
+	{"R16",		REGOFF(r16),		RINT, 'Y'},
+	{"R15",		REGOFF(r15),		RINT, 'Y'},
+	{"R14",		REGOFF(r14),		RINT, 'Y'},
+	{"R13",		REGOFF(r13),		RINT, 'Y'},
+	{"R12",		REGOFF(r12),		RINT, 'Y'},
+	{"R11",		REGOFF(r11),		RINT, 'Y'},
+	{"R10",		REGOFF(r10),		RINT, 'Y'},
+	{"R9",		REGOFF(r9),		RINT, 'Y'},
+	{"R8",		REGOFF(r8),		RINT, 'Y'},
+	{"R7",		REGOFF(r7),		RINT, 'Y'},
+	{"R6",		REGOFF(r6),		RINT, 'Y'},
+	{"R5",		REGOFF(r5),		RINT, 'Y'},
+	{"R4",		REGOFF(r4),		RINT, 'Y'},
+	{"R3",		REGOFF(r3),		RINT, 'Y'},
+	{"R2",		REGOFF(r2),		RINT, 'Y'},
+	{"R1",		REGOFF(r1),		RINT, 'Y'},
+	{"R0",		REGOFF(r0),		RINT, 'Y'},
+	{  0 }
+};
+
+	/* the machine description */
+Mach marm64 =
+{
+	"arm64",
+	MARM64,		/* machine type */
+	arm64reglist,	/* register set */
+	REGSIZE,	/* register set size */
+	0,		/* fp register set size */
+	"PC",		/* name of PC */
+	"SP",		/* name of SP */
+	"R30",		/* name of link register */
+	"setSB",	/* static base register name */
+	0,		/* static base register value */
+	0x10000,	/* page size (for segment alignment) */
+	0xFFFFFFFF80000000ULL,	/* kernel base */
+	0xFFFF800000000000ULL,	/* kernel text mask */
+	0x00007FFFFFFF0000ULL,	/* user stack top */
+	4,		/* quantization of pc */
+	8,		/* szaddr */
+	8,		/* szreg */
+	4,		/* szfloat */
+	8,		/* szdouble */
+};
--- /dev/null
+++ b/sys/src/libmach/7db.c
@@ -1,0 +1,728 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <mach.h>
+
+typedef struct Opcode Opcode;
+struct Opcode
+{
+	char	*p;
+	char	*o;
+	char	*a;
+};
+
+typedef struct	Instr	Instr;
+struct	Instr
+{
+	Opcode	*op;
+	Map	*map;
+	uvlong	addr;
+	ulong	w;
+
+	char	*curr;		/* fill point in buffer */
+	char	*end;		/* end of buffer */
+};
+
+static	void	format(char*, Instr*, char*);
+static	char	FRAMENAME[] = ".frame";
+
+/*
+ * Arm64-specific debugger interface
+ */
+static	char*	arm64excep(Map*, Rgetter);
+static	int	arm64foll(Map*, uvlong, Rgetter, uvlong*);
+static	int	arm64inst(Map*, uvlong, char, char*, int);
+static	int	arm64das(Map*, uvlong, char*, int);
+static	int	arm64instlen(Map*, uvlong);
+
+/*
+ *	Debugger interface
+ */
+Machdata arm64mach =
+{
+	{0x00, 0x00, 0x20, 0xD4},	/* break point 0xD4200000 */
+	4,		/* break point size */
+	leswab,		/* short to local byte order */
+	leswal,		/* long to local byte order */
+	leswav,		/* long to local byte order */
+	risctrace,	/* C traceback */
+	riscframe,	/* Frame finder */
+	arm64excep,	/* print exception */
+	0,		/* breakpoint fixup */
+	0,		/* single precision float printer */
+	0,		/* double precision float printer */
+	arm64foll,	/* following addresses */
+	arm64inst,	/* print instruction */
+	arm64das,	/* dissembler */
+	arm64instlen,	/* instruction size */
+};
+
+static Opcode opcodes[] =
+{
+	"0AA10000AAAAAAAAAAAAAAAAAAAddddd",	"ADR",		"$%A,R%d",
+	"1PP10000PPPPPPPPPPPPPPPPPPPddddd",	"ADRP",		"$%P,R%d",
+	"00011000lllllllllllllllllllddddd",	"MOVWU",	"%l,R%d",
+	"01011000LLLLLLLLLLLLLLLLLLLddddd",	"MOV",		"%L,R%d",
+	"10011000lllllllllllllllllllddddd",	"MOVW",		"%l,R%d",
+	"11011000lllllllllllllllllllddddd",	"PRFM",		"%l,$%d",
+	"1111100100uuuuuuuuuuuu11111ddddd",	"MOV",		"R%d,%u(SP)",
+	"1111100100uuuuuuuuuuuunnnnnddddd",	"MOV",		"R%d,%u(R%n)",
+	"WW11100100uuuuuuuuuuuu11111ddddd",	"MOV%WU",	"R%d,%u(SP)",
+	"WW11100100uuuuuuuuuuuunnnnnddddd",	"MOV%WU",	"R%d,%u(R%n)",
+	"1111100101uuuuuuuuuuuu11111ddddd",	"MOV",		"%u(SP),R%d",
+	"1111100101uuuuuuuuuuuunnnnnddddd",	"MOV",		"%u(R%n),R%d",
+	"WW11100101uuuuuuuuuuuu11111ddddd",	"MOV%WU",	"%u(SP),R%d",
+	"WW11100101uuuuuuuuuuuunnnnnddddd",	"MOV%WU",	"%u(R%n),R%d",
+	"WW11100110uuuuuuuuuuuu11111ddddd",	"MOV%W",	"%u(SP),R%d",
+	"WW11100110uuuuuuuuuuuunnnnnddddd",	"MOV%W",	"%u(R%n),R%d",
+	"11111000000ooooooooo0011111ddddd",	"MOV",		"R%d,%o(SP)",
+	"11111000000ooooooooo00nnnnnddddd",	"MOV",		"R%d,%o(R%n)",
+	"WW111000000ooooooooo0011111ddddd",	"MOV%W",	"R%d,%o(SP)",
+	"WW111000000ooooooooo00nnnnnddddd",	"MOV%W",	"R%d,%o(R%n)",
+	"11111000010ooooooooo0011111ddddd",	"MOV",		"%o(SP),R%d",
+	"11111000010ooooooooo00nnnnnddddd",	"MOV",		"%o(R%n),R%d",
+	"WW111000010ooooooooo0011111ddddd",	"MOV%WU",	"%o(SP),R%d",
+	"WW111000010ooooooooo00nnnnnddddd",	"MOV%WU",	"%o(R%n),R%d",
+	"WW111000100ooooooooo0011111ddddd",	"MOV%W",	"%o(SP),R%d",
+	"WW111000100ooooooooo00nnnnnddddd",	"MOV%W",	"%o(R%n),R%d",
+	"11111000000ooooooooo0111111ddddd",	"MOV",		"R%d,(SP)%o!",
+	"WW111000000ooooooooo0111111ddddd",	"MOV%WU",	"R%d,(SP)%o!",
+	"WW111000000ooooooooo01nnnnnddddd",	"MOV%WU",	"R%d,(R%n)%o!",
+	"11111000000ooooooooo1111111ddddd",	"MOV",		"R%d,%o(SP)!",
+	"WW111000000ooooooooo1111111ddddd",	"MOV%WU",	"R%d,%o(SP)!",
+	"WW111000000ooooooooo11nnnnnddddd",	"MOV%WU",	"R%d,%o(R%n)!",
+	"11111000010ooooooooo0111111ddddd",	"MOV",		"(SP)%o!,R%d",
+	"11111000010ooooooooo01nnnnnddddd",	"MOV",		"(R%n)%o!,R%d",
+	"WW111000010ooooooooo0111111ddddd",	"MOV%WU",	"(SP)%o!,R%d",
+	"WW111000010ooooooooo01nnnnnddddd",	"MOV%WU",	"(R%n)%o!,R%d",
+	"WW111000100ooooooooo0111111ddddd",	"MOV%W",	"(SP)%o!,R%d",
+	"WW111000100ooooooooo01nnnnnddddd",	"MOV%W",	"(R%n)%o!,R%d",
+	"11111000010ooooooooo1111111ddddd",	"MOV",		"%o(SP)!,R%d",
+	"11111000010ooooooooo11nnnnnddddd",	"MOV",		"%o(R%n)!,R%d",
+	"WW111000010ooooooooo1111111ddddd",	"MOV%WU",	"%o(SP)!,R%d",
+	"WW111000010ooooooooo11nnnnnddddd",	"MOV%WU",	"%o(R%n)!,R%d",
+	"WW111000100ooooooooo1111111ddddd",	"MOV%W",	"%o(SP)!,R%d",
+	"WW111000100ooooooooo11nnnnnddddd",	"MOV%W",	"%o(R%n)!,R%d",
+	"11111000001mmmmmeeei10nnnnnddddd",	"MOV",		"R%d,(R%n)(R%m%e)",
+	"11111000111mmmmmeeei10nnnnnddddd",	"MOV",		"(R%n)(R%m%e),R%d",
+	"WW111000001mmmmmeeei10nnnnnddddd",	"MOV%W",	"R%d,(R%n)(R%m%e)",
+	"WW111000011mmmmmeeei10nnnnnddddd",	"MOV%WU",	"(R%n)(R%m%e),R%d",
+	"WW111000101mmmmmeeei10nnnnnddddd",	"MOV%W",	"(R%n)(R%m%e),R%d",
+	"WW111000111mmmmmeeei10nnnnnddddd",	"MOV%WW",	"(R%n)(R%m%e),R%d",
+	"W00100101ssKKKKKKKKKKKKKKKKddddd",	"MOVN%W",	"$%K,R%d",
+	"W10100101ssKKKKKKKKKKKKKKKKddddd",	"MOVZ%W",	"$%K,R%d",
+	"W11100101ssKKKKKKKKKKKKKKKKddddd",	"MOVK%W",	"$%K,R%d",
+	"W0010001--00000000000011111ddddd",	"MOV%W",	"SP,R%d",
+	"W0010001--000000000000nnnnn11111",	"MOV%W",	"R%n,SP",
+	"W0010001ssIIIIIIIIIIII1111111111",	"ADD%W",	"$%I,SP,SP",
+	"W0010001ssIIIIIIIIIIII11111ddddd",	"ADD%W",	"$%I,SP,R%d",
+	"W0010001ssIIIIIIIIIIIInnnnn11111",	"ADD%W",	"$%I,R%n,SP",
+	"W0110001ssIIIIIIIIIIII1111111111",	"ADDS%W",	"$%I,SP,SP",
+	"W0110001ssIIIIIIIIIIII11111ddddd",	"ADDS%W",	"$%I,SP,R%d",
+	"W0110001ssIIIIIIIIIIIInnnnn11111",	"ADDS%W",	"$%I,R%n,SP",
+	"W1010001ssIIIIIIIIIIII1111111111",	"SUB%W",	"$%I,SP,SP",
+	"W1010001ssIIIIIIIIIIII11111ddddd",	"SUB%W",	"$%I,SP,R%d",
+	"W1010001ssIIIIIIIIIIIInnnnn11111",	"SUB%W",	"$%I,R%n,SP",
+	"W1110001ssIIIIIIIIIIII1111111111",	"CMP%W",	"$%I,SP",
+	"W1110001ssIIIIIIIIIIIInnnnn11111",	"CMP%W",	"$%I,R%n",
+	"W1110001ssIIIIIIIIIIII11111ddddd",	"SUBS%W",	"$%I,SP,R%d",
+	"W0010001ssIIIIIIIIIIIInnnnnddddd",	"ADD%W",	"$%I,R%n,R%d",
+	"W0110001ssIIIIIIIIIIIInnnnnddddd",	"ADDS%W",	"$%I,R%n,R%d",
+	"W1010001ssIIIIIIIIIIIInnnnnddddd",	"SUB%W",	"$%I,R%n,R%d",
+	"W1110001ssIIIIIIIIIIIInnnnnddddd",	"SUBS%W",	"$%I,R%n,R%d",
+	"W00100100MMMMMMMMMMMMMnnnnn11111",	"AND%W",	"$%M,R%n,SP",
+	"W01100100MMMMMMMMMMMMMnnnnn11111",	"ORR%W",	"$%M,R%n,SP",
+	"W10100100MMMMMMMMMMMMMnnnnn11111",	"EOR%W",	"$%M,R%n,SP",
+	"W11100100MMMMMMMMMMMMMnnnnn11111",	"ANDS%W",	"$%M,R%n,SP",
+	"W00100100MMMMMMMMMMMMMnnnnnddddd",	"AND%W",	"$%M,R%n,R%d",
+	"W01100100MMMMMMMMMMMMMnnnnnddddd",	"ORR%W",	"$%M,R%n,R%d",
+	"W10100100MMMMMMMMMMMMMnnnnnddddd",	"EOR%W",	"$%M,R%n,R%d",
+	"W11100100MMMMMMMMMMMMMnnnnnddddd",	"ANDS%W",	"$%M,R%n,R%d",
+	"1001001101000000011111nnnnnddddd",	"SXTW",		"R%n,R%d",
+	"0101001100iiiiii011111nnnnnddddd",	"LSRW",		"$%i,R%n,R%d",
+	"1101001101iiiiii111111nnnnnddddd",	"LSR",		"$%i,R%n,R%d",
+	"W00100110-iiiiiijjjjjjnnnnnddddd",	"SBFM%W",	"$%i,$%j,R%n,R%d",
+	"W01100110-iiiiiijjjjjjnnnnnddddd",	"BFM%W",	"$%i,$%j,R%n,R%d",
+	"W10100110-iiiiiijjjjjjnnnnnddddd",	"UBFM%W",	"$%i,$%j,R%n,R%d",
+	"W1011010000mmmmm00000011111ddddd",	"NGC%W",	"R%m,R%d",
+	"W1111010000mmmmm00000011111ddddd",	"NGCS%W",	"R%m,R%d",
+	"W0011010000mmmmm000000nnnnnddddd",	"ADC%W",	"R%m,R%n,R%d",
+	"W0111010000mmmmm000000nnnnnddddd",	"ADCS%W",	"R%m,R%n,R%d",
+	"W1011010000mmmmm000000nnnnnddddd",	"SBC%W",	"R%m,R%n,R%d",
+	"W1111010000mmmmm000000nnnnnddddd",	"SBCS%W",	"R%m,R%n,R%d",
+	"W0101011ss0mmmmmiiiiiinnnnn11111",	"CMN%W",	"R%m%s,R%n",
+	"W1101011ss0mmmmmiiiiiinnnnn11111",	"CMP%W",	"R%m%s,R%n",
+	"W1001011ss0mmmmmiiiiii11111ddddd",	"NEG%W",	"R%m%s,R%d",
+	"W1101011ss0mmmmmiiiiii11111ddddd",	"NEGS%W",	"R%m%s,R%d",
+	"W0001011ss0mmmmmiiiiiinnnnnddddd",	"ADD%W",	"R%m%s,R%n,R%d",
+	"W0101011ss0mmmmmiiiiiinnnnnddddd",	"ADDS%W",	"R%m%s,R%n,R%d",
+	"W1001011ss0mmmmmiiiiiinnnnnddddd",	"SUB%W",	"R%m%s,R%n,R%d",
+	"W1101011ss0mmmmmiiiiiinnnnnddddd",	"SUBS%W",	"R%m%s,R%n,R%d",
+	"W0001011001mmmmmeeeiii1111111111",	"ADD%W",	"R%m%e,SP,SP",
+	"W0001011001mmmmmeeeiii11111ddddd",	"ADD%W",	"R%m%e,SP,R%d",
+	"W0001011001mmmmmeeeiiinnnnn11111",	"ADD%W",	"R%m%e,R%n,SP",
+	"W0101011001mmmmmeeeiii1111111111",	"ADDS%W",	"R%m%e,SP,SP",
+	"W0101011001mmmmmeeeiii11111ddddd",	"ADDS%W",	"R%m%e,SP,R%d",
+	"W0101011001mmmmmeeeiiinnnnn11111",	"ADDS%W",	"R%m%e,R%n,SP",
+	"W1001011001mmmmmeeeiii1111111111",	"SUB%W",	"R%m%e,SP,SP",
+	"W1001011001mmmmmeeeiii11111ddddd",	"SUB%W",	"R%m%e,SP,R%d",
+	"W1001011001mmmmmeeeiiinnnnn11111",	"SUB%W",	"R%m%e,R%n,SP",
+	"W1101011001mmmmmeeeiii1111111111",	"SUBS%W",	"R%m%e,SP,SP",
+	"W1101011001mmmmmeeeiii11111ddddd",	"SUBS%W",	"R%m%e,SP,R%d",
+	"W1101011001mmmmmeeeiiinnnnn11111",	"SUBS%W",	"R%m%e,R%n,SP",
+	"W0001011001mmmmmeeeiiinnnnnddddd",	"ADD%W",	"R%m%e,R%n,R%d",
+	"W0101011001mmmmmeeeiiinnnnnddddd",	"ADDS%W",	"R%m%e,R%n,R%d",
+	"W1001011001mmmmmeeeiiinnnnnddddd",	"SUB%W",	"R%m%e,R%n,R%d",
+	"W1101011001mmmmmeeeiiinnnnnddddd",	"SUBS%W",	"R%m%e,R%n,R%d",
+	"W0101010000mmmmm-0000011111ddddd",	"MOV%W",	"R%m,R%d",
+	"W0101010ss1mmmmmiiiiii11111ddddd",	"NVM%W",	"R%m%s,R%d",
+	"W1101010ss0mmmmmiiiiiinnnnn11111",	"TST%W",	"R%m%s,R%n",
+	"W0001010ss0mmmmmiiiiiinnnnnddddd",	"AND%W",	"R%m%s,R%n,R%d",
+	"W1101010ss0mmmmmiiiiiinnnnnddddd",	"ANDS%W",	"R%m%s,R%n,R%d",
+	"W0001010ss1mmmmmiiiiiinnnnnddddd",	"BIC%W",	"R%m%s,R%n,R%d",
+	"W1101010ss1mmmmmiiiiiinnnnnddddd",	"BICS%W",	"R%m%s,R%n,R%d",
+	"W1001010ss0mmmmmiiiiiinnnnnddddd",	"EOR%W",	"R%m%s,R%n,R%d",
+	"W1001010ss1mmmmmiiiiiinnnnnddddd",	"EON%W",	"R%m%s,R%n,R%d",
+	"W0101010ss0mmmmmiiiiiinnnnnddddd",	"ORR%W",	"R%m%s,R%n,R%d",
+	"W0101010ss1mmmmmiiiiiinnnnnddddd",	"ORN%W",	"R%m%s,R%n,R%d",
+	"W0011010110mmmmm001000nnnnnddddd",	"LSL%W",	"R%m,R%n,R%d",
+	"W0011010110mmmmm001001nnnnnddddd",	"LSR%W",	"R%m,R%n,R%d",
+	"W0011010110mmmmm001010nnnnnddddd",	"ASR%W",	"R%m,R%n,R%d",
+	"W0011010110mmmmm001011nnnnnddddd",	"ROR%W",	"R%m,R%n,R%d",
+	"W0011010110mmmmm000010nnnnnddddd",	"UDIV%W",	"R%m,R%n,R%d",
+	"W0011010110mmmmm000011nnnnnddddd",	"SDIV%W",	"R%m,R%n,R%d",
+	"W0011011000mmmmm011111nnnnnddddd",	"MUL%W",	"R%m,R%n,R%d",
+	"W0011011000mmmmm111111nnnnnddddd",	"MNEG%W",	"R%m,R%n,R%d",
+	"W0011011000mmmmm0aaaaannnnnddddd",	"MADD%W",	"R%m,R%n,R%a,R%d",
+	"W0011011000mmmmm1aaaaannnnnddddd",	"MSUB%W",	"R%m,R%n,R%a,R%d",
+	"10011011001mmmmm011111nnnnnddddd",	"SMULL",	"R%m,R%n,R%d",
+	"10011011001mmmmm111111nnnnnddddd",	"SMNEGL",	"R%m,R%n,R%d",
+	"10011011001mmmmm0aaaaannnnnddddd",	"SMADDL",	"R%m,R%n,R%a,R%d",
+	"10011011001mmmmm1aaaaannnnnddddd",	"SMSUBL",	"R%m,R%n,R%a,R%d",
+	"10011011101mmmmm011111nnnnnddddd",	"UMULL",	"R%m,R%n,R%d",
+	"10011011101mmmmm111111nnnnnddddd",	"UMNEGL",	"R%m,R%n,R%d",
+	"10011011101mmmmm0aaaaannnnnddddd",	"UMADDL",	"R%m,R%n,R%a,R%d",
+	"10011011101mmmmm1aaaaannnnnddddd",	"UMSUBL",	"R%m,R%n,R%a,R%d",
+	"W0110100TTTTTTTTTTTTTTTTTTTddddd",	"CBZ%W",	"R%d,%T",
+	"W0110101TTTTTTTTTTTTTTTTTTTddddd",	"CBNZ%W",	"R%d,%T",
+	"01010100TTTTTTTTTTTTTTTTTTT0CCCC",	"B%C",		"%T",
+	"000101TTTTTTTTTTTTTTTTTTTTTTTTTT",	"B",		"%T",
+	"100101TTTTTTTTTTTTTTTTTTTTTTTTTT",	"BL",		"%T",
+	"1101011000011111000000nnnnn00000",	"BR",		"R%n",
+	"1101011000111111000000nnnnn00000",	"BLR",		"R%n",
+	"11010110010111110000001111000000",	"RETURN",	nil,
+	"1101011001011111000000nnnnn00000",	"RET",		"R%n",
+	"11010110100111110000001111100000",	"ERET",		nil,
+	"11010110101111110000001111100000",	"DRPS",		nil,
+	"11010100000iiiiiiiiiiiiiiii00001",	"SVC",		"$%i",
+	"11010100000iiiiiiiiiiiiiiii00010",	"HVC",		"$%i",
+	"11010100000iiiiiiiiiiiiiiii00011",	"SMC",		"$%i",
+	"11010100001iiiiiiiiiiiiiiii00000",	"BRK",		"$%i",
+	"11010100010iiiiiiiiiiiiiiii00000",	"HLT",		"$%i",
+	"11010100101iiiiiiiiiiiiiiii00001",	"DCPS1",	"$%i",
+	"11010100101iiiiiiiiiiiiiiii00010",	"DCPS2",	"$%i",
+	"11010100101iiiiiiiiiiiiiiii00011",	"DCPS3",	"$%i",
+	"11010101000000110010000000011111",	"NOP",		nil,
+	"11010101000000110010000000111111",	"YIELD",	nil,
+	"11010101000000110010000001011111",	"WFE",		nil,
+	"11010101000000110010000001111111",	"WFI",		nil,
+	"11010101000000110010000010011111",	"SEV",		nil,
+	"11010101000000110010000010111111",	"SEVL",		nil,
+	"11010101000000110011xxxx01011111",	"CLREX",	"$%x",
+	"11010101000000110011xxxx10011111",	"DSB",		"$%x",
+	"11010101000000110011xxxx10111111",	"DMB",		"$%x",
+	"11010101000000110011xxxx11011111",	"ISB",		"$%x",
+	"1101010100001YYYYYYYYYYYYYY11111",	"SYS",		"%Y",
+	"1101010100001YYYYYYYYYYYYYYddddd",	"SYS",		"R%d,%Y",
+	"1101010100101YYYYYYYYYYYYYYddddd",	"SYSL",		"%Y,R%d",
+	"11010101000000000100xxxx10111111",	"MSR",		"$%x,SP",
+	"11010101000000110100xxxx11011111",	"MSR",		"$%x,DAIFSet",
+	"11010101000000110100xxxx11111111",	"MSR",		"$%x,DAIFClr",
+	"11010101000YYYYYYYYYYYYYYYYddddd",	"MSR",		"R%d,%Y",
+	"11010101001YYYYYYYYYYYYYYYYddddd",	"MRS",		"%Y,R%d",
+	"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",	"WORD",		"$%x",
+};
+
+#define	SYSARG5(op0,op1,Cn,Cm,op2)	((op0)<<19|(op1)<<16|(Cn)<<12|(Cm)<<8|(op2)<<5)
+
+static ulong
+smask(char *s, char c)
+{
+	ulong m;
+	int i;
+
+	m = 0;
+	for(i=0; i<32 && *s != '\0'; i++, s++)
+		m |= (*s == c)<<(31-i);
+	return m;
+}
+
+static int
+nbits(ulong v)
+{
+	int n = 0;
+	while(v != 0){
+		v &= v-1;
+		n++;
+	}
+	return n;
+}
+
+static int
+nones(ulong v)
+{
+	int n = 0;
+	while(v & 1){
+		v >>= 1;
+		n++;
+	}
+	return n;
+}
+
+static int
+nshift(ulong m)
+{
+	if(m == 0 || m == ~0UL)
+		return 0;
+	return nones(~m);
+}
+
+static ulong
+unshift(ulong w, ulong m)
+{
+	int s = nshift(m);
+	w >>= s, m >>= s;
+	if((m+1 & m) != 0){	// 0bxxx0000yyyyyy -> 0byyyyyyxxx
+		ulong b = (1UL<<nones(m))-1;
+		return ((w & b) << nbits(m & ~b)) | unshift(w, m & ~b);
+	}
+	return w & m;
+}
+
+static long
+sext(ulong u, int n)
+{
+	long l = (long)u;
+	if(n > 0){
+		l <<= sizeof(l)*8 - n;
+		l >>= sizeof(l)*8 - n;
+	}
+	return l;
+}
+
+static char*
+arm64excep(Map *, Rgetter)
+{
+//	uvlong c = (*rget)(map, "TYPE");
+	return "???";
+}
+
+static int
+decode(Map *map, uvlong pc, Instr *i)
+{
+	static ulong tab[2*nelem(opcodes)];
+	static int once;
+	ulong w, j;
+
+	if(!once){
+		Opcode *o;
+
+		/* precalculate value/mask table */
+		for(j=0, o=opcodes; j<nelem(tab); j+=2, o++){
+			tab[j] = smask(o->p, '1');
+			tab[j|1] = tab[j] | smask(o->p, '0');
+		}
+
+		once = 1;
+	}
+
+	if(get4(map, pc, &w) < 0) {
+		werrstr("can't read instruction: %r");
+		return -1;
+	}
+	i->addr = pc;
+	i->map = map;
+	i->w = w;
+
+	for(j=0; j<nelem(tab); j+=2){
+		if((w & tab[j|1]) == tab[j]){
+			i->op = &opcodes[j/2];
+			return 1;
+		}
+	}
+
+	/* should not happen */
+	return 0;
+}
+
+#pragma	varargck	argpos	bprint	2
+
+static void
+bprint(Instr *i, char *fmt, ...)
+{
+	va_list arg;
+
+	va_start(arg, fmt);
+	i->curr = vseprint(i->curr, i->end, fmt, arg);
+	va_end(arg);
+}
+
+static
+char*	shtype[4] =
+{
+	"<<",	">>",	"->",	"@>"
+};
+
+static
+char*	rextype[8] =
+{
+	"UB", "UH", "UW", "UX",
+	"SB", "SH", "SW", "SX"
+};
+
+static
+char*	scond[16] =
+{
+	"EQ", "NE", "HS", "LO",
+	"MI", "PL", "VS", "VC",
+	"HI", "LS", "GE", "LT",
+	"GT", "LE",   "", "NV",
+};
+
+static uvlong
+decodebitmask(int n, int s, int r)
+{
+	uvlong w;
+	int e;
+
+	if(n)
+		n = 6;
+	else {
+		for(n = 5; n >= 1 && ((~s & 0x3F) & (1<<n)) == 0; n--)
+			;
+	}
+	e = 1 << n;
+	s &= e-1;
+	r &= e-1;
+
+	w = 1ULL << s;
+	w |= w-1;
+
+	if(r != 0){
+		w = (w >> r) | (w << (e-r));
+		if(e < 64)
+			w &= (1ULL << e)-1;
+	}
+	while(e < 64){
+		w |= w << e;
+		e <<= 1;
+	}
+	return w;
+}
+
+static void
+format(char *mnemonic, Instr *i, char *f)
+{
+	Symbol s;
+	uvlong v;
+	ulong w, u, m;
+
+	if(mnemonic)
+		format(0, i, mnemonic);
+	if(f == 0)
+		return;
+	if(mnemonic)
+		if(i->curr < i->end)
+			*i->curr++ = '\t';
+	for ( ; *f && i->curr < i->end; f++) {
+		if(*f != '%') {
+			*i->curr++ = *f;
+			continue;
+		}
+		m = smask(i->op->p, *++f);
+		u = unshift(i->w, m);
+		switch (*f) {
+		case 'C':	// Condition
+			bprint(i, "%s", scond[u & 15]);
+			break;
+
+		case 'W':	// Width
+			if(nbits(m) == 1) u += 2;
+			u &= 3;
+			if(u < 3)
+				*i->curr++ = "BHW"[u];
+			break;
+
+		case 'd':	// Register Numbers
+		case 'n':
+		case 'a':
+		case 'm':
+			bprint(i, "%lud", u);
+			break;
+
+		case 's':	// Register shift
+			w = unshift(i->w, smask(i->op->p, 'i'));
+			if(w != 0)
+				bprint(i, "%s%lud", shtype[u & 3], w);
+			break;
+
+		case 'e':	// Register extension
+			u &= 7;
+			bprint(i, ".%s", rextype[u]);
+			w = unshift(i->w, smask(i->op->p, 'i'));
+			if(w != 0 && u == 2+(i->w>>31))
+				bprint(i, "<<%lud", w);
+			break;
+
+		case 'M':	// Bitmask
+			v = decodebitmask((u>>12)&1, u&0x3F, (u>>6)&0x3F);
+			if((i->w & (1<<31)) == 0)
+				v &= 0xFFFFFFFF;
+			bprint(i, "%llux", v);
+			break;
+
+		case 'I':	// Shifted Immediate (12 bit)
+		case 'K':	// Shifted Immediate (16 bit)
+			w = unshift(i->w, smask(i->op->p, 's'));
+			if(u != 0 && w != 0)
+				bprint(i, "(%lux<<%ld)", u, w*(*f == 'I' ? 12 : 16));
+			else
+				bprint(i, "%lud", u);
+			break;
+
+		case 'o':	// Signed byte offset
+			bprint(i, "%ld", sext(u, nbits(m)));
+			break;
+		case 'u':	// Unsigned offset
+			u <<= (i->w >> 30)&3;
+			/* wet floor */
+		case 'i':	// Decimal
+		case 'j':
+			bprint(i, "%lud", u);
+			break;
+
+		case 'x':	// Hex
+			bprint(i, "%lux", u);
+			break;
+
+		case 'l':	// 32-bit Literal
+			if(get4(i->map, i->addr + sext(u, nbits(m))*4, &w) < 0)
+				goto Ptext;
+			bprint(i, "$%lux", w);
+			break;
+		case 'L':	// 64-bit Literal
+			if(get8(i->map, i->addr + sext(u, nbits(m))*4, &v) < 0)
+				goto Ptext;
+			bprint(i, "$%llux", v);
+			break;
+		case 'T':	// Text address (PC relative)
+		Ptext:
+			v = i->addr + sext(u, nbits(m))*4;
+			if(findsym(v, CTEXT, &s)){
+				bprint(i, "%s", s.name);
+				if(v < s.value)
+					bprint(i, "%llx", v - s.value);
+				else if(v > s.value)
+					bprint(i, "+%llx", v - s.value);
+				bprint(i, "(SB)");
+				break;
+			}
+			bprint(i, "%llux(SB)", v);
+			break;
+		case 'A':	// Data address (PC relative)
+			v = i->addr + sext(u, nbits(m));
+			goto Pdata;
+		case 'P':	// Page address (PC relative)
+			v = i->addr + ((vlong)sext(u, nbits(m)) << 12);
+		Pdata:
+			if(findsym(v, CANY, &s)){
+				bprint(i, "%s", s.name);
+				if(v < s.value)
+					bprint(i, "%llx", v - s.value);
+				else if(v > s.value)
+					bprint(i, "+%llx", v - s.value);
+				bprint(i, "(SB)");
+				break;
+			}
+			bprint(i, "%llux(SB)", v);
+			break;
+
+		case 'Y':
+			if(nbits(m) == 14){ // SYS/SYSL operands
+				bprint(i, "%lud,%lud,%lud,%lud",
+					(u>>(4+4+3))&7,	// op1
+					(u>>(4+3))&15,	// CRn
+					(u>>3)&15,	// CRm
+					(u)&7);		// op2
+				break;
+			}
+			/* see /sys/src/cmd/7c/7.out.h */
+			switch(i->w & m){
+			case SYSARG5(3,3,4,2,1): bprint(i, "DAIF"); break;
+			case SYSARG5(3,3,4,2,0): bprint(i, "NZCV"); break;
+			case SYSARG5(3,3,4,4,1): bprint(i, "FPSR"); break;
+			case SYSARG5(3,3,4,4,0): bprint(i, "FPCR"); break;
+			case SYSARG5(3,0,4,0,0): bprint(i, "SPSR_EL1"); break;
+			case SYSARG5(3,0,4,0,1): bprint(i, "ELR_EL1"); break;
+			case SYSARG5(3,4,4,0,0): bprint(i, "SPSR_EL2"); break;
+			case SYSARG5(3,4,4,0,1): bprint(i, "ELR_EL2"); break;
+			case SYSARG5(3,0,4,2,2): bprint(i, "CurrentEL"); break;
+			case SYSARG5(3,0,4,1,0): bprint(i, "SP_EL0"); break;
+			case SYSARG5(3,0,4,2,0): bprint(i, "SPSel"); break;
+			default: bprint(i, "SPR(%lux)", i->w & m);
+			}
+			break;
+
+		case '\0':
+			*i->curr++ = '%';
+			return;
+
+		default:
+			bprint(i, "%%%c", *f);
+			break;
+		}
+	}
+	*i->curr = 0;
+}
+
+static int
+printins(Map *map, uvlong pc, char *buf, int n)
+{
+	Instr i[1];
+
+	i->curr = buf;
+	i->end = buf+n-1;
+	if(decode(map, pc, i) < 0)
+		return -1;
+	format(i->op->o, i, i->op->a);
+	return 4;
+}
+
+static int
+arm64inst(Map *map, uvlong pc, char modifier, char *buf, int n)
+{
+	USED(modifier);
+	return printins(map, pc, buf, n);
+}
+
+static int
+arm64das(Map *map, uvlong pc, char *buf, int n)
+{
+	Instr i[1];
+
+	i->curr = buf;
+	i->end = buf+n;
+	if(decode(map, pc, i) < 0)
+		return -1;
+	if(i->end-i->curr > 8)
+		i->curr = _hexify(buf, i->w, 7);
+	*i->curr = 0;
+	return 4;
+}
+
+static int
+arm64instlen(Map*, uvlong)
+{
+	return 4;
+}
+
+static uvlong
+readreg(Instr *i, Rgetter rget, int rc)
+{
+	ulong m;
+	uvlong v;
+	char reg[4];
+	snprint(reg, sizeof(reg), "R%lud", unshift(i->w, smask(i->op->p, rc)));
+	v = (*rget)(i->map, reg);
+	m = smask(i->op->p, 'W');
+	if(m != 0 && unshift(i->w, m) == 0)
+		v &= 0xFFFFFFFFULL;
+	return v;
+}
+
+static int
+passcond(Instr *i, Rgetter rget)
+{
+	uvlong psr;
+	uchar n;
+	uchar z;
+	uchar c;
+	uchar v;
+
+	psr = (*rget)(i->map, "PSR");
+	n = (psr >> 31) & 1;
+	z = (psr >> 30) & 1;
+	c = (psr >> 29) & 1;
+	v = (psr >> 28) & 1;
+
+	switch(unshift(i->w, smask(i->op->p, 'C'))) {
+	default:
+	case 0:		return z;
+	case 1:		return !z;
+	case 2:		return c;
+	case 3:		return !c;
+	case 4:		return n;
+	case 5:		return !n;
+	case 6:		return v;
+	case 7:		return !v;
+	case 8:		return c && !z;
+	case 9:		return !c || z;
+	case 10:	return n == v;
+	case 11:	return n != v;
+	case 12:	return !z && (n == v);
+	case 13:	return z || (n != v);
+	case 14:	return 1;
+	case 15:	return 0;
+	}
+}
+
+static uvlong
+jumptarg(Instr *i)
+{
+	ulong m = smask(i->op->p, 'T');
+	return i->addr + sext(unshift(i->w, m), m)*4;
+}
+
+static int
+arm64foll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
+{
+	Instr i[1];
+	char *o;
+
+	if(decode(map, pc, i) < 0)
+		return -1;
+
+	o = i->op->o;
+	if(strcmp(o, "ERET") == 0)
+		return -1;
+
+	if(strcmp(o, "RET") == 0 || strcmp(o, "BR") == 0 || strcmp(o, "BLR") == 0){
+		foll[0] = readreg(i, rget, 'n');
+		return 1;
+	}
+	if(strcmp(o, "B") == 0 || strcmp(o, "BL") == 0){
+		foll[0] = jumptarg(i);
+		return 1;
+	}
+	if(strcmp(o, "B%C") == 0){
+		if(passcond(i, rget)){
+			foll[0] = jumptarg(i);
+			return 1;
+		}
+	}
+	if(strcmp(o, "CBZ%W") == 0){
+		if(readreg(i, rget, 'd') == 0){
+			foll[0] = jumptarg(i);
+			return 1;
+		}
+	}
+	if(strcmp(o, "CBNZ%W") == 0){
+		if(readreg(i, rget, 'd') != 0){
+			foll[0] = jumptarg(i);
+			return 1;
+		}
+	}
+
+	foll[0] = i->addr+4;
+	return 1;
+}
--- /dev/null
+++ b/sys/src/libmach/7obj.c
@@ -1,0 +1,150 @@
+/*
+ * 7obj.c - identify and parse an arm64 object file
+ */
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <mach.h>
+#include "7c/7.out.h"
+#include "obj.h"
+
+typedef struct Addr	Addr;
+struct Addr
+{
+	char	type;
+	char	sym;
+	char	name;
+};
+static Addr addr(Biobuf*);
+static char type2char(int);
+static void skip(Biobuf*, int);
+
+int
+_is7(char *s)
+{
+	return  s[0] == (ANAME&0xff)			/* aslo = ANAME */
+		&& s[1] == ((ANAME>>8)&0xff)
+		&& s[2] == D_FILE			/* type */
+		&& s[3] == 1				/* sym */
+		&& s[4] == '<';				/* name of file */
+}
+
+int
+_read7(Biobuf *bp, Prog *p)
+{
+	int as, n;
+	Addr a;
+
+	as = (uchar)Bgetc(bp);				/* as */
+	as |= (uchar)Bgetc(bp)<<8;
+	if(as <= AXXX || as >= ALAST)
+		return 0;
+	p->kind = aNone;
+	p->sig = 0;
+	if(as == ANAME || as == ASIGNAME){
+		if(as == ASIGNAME){
+			Bread(bp, &p->sig, 4);
+			p->sig = leswal(p->sig);
+		}
+		p->kind = aName;
+		p->type = type2char(Bgetc(bp));		/* type */
+		p->sym = Bgetc(bp);			/* sym */
+		n = 0;
+		for(;;) {
+			as = Bgetc(bp);
+			if(as < 0)
+				return 0;
+			n++;
+			if(as == 0)
+				break;
+		}
+		p->id = malloc(n);
+		if(p->id == 0)
+			return 0;
+		Bseek(bp, -n, 1);
+		if(Bread(bp, p->id, n) != n)
+			return 0;
+		return 1;
+	}
+	if(as == ATEXT)
+		p->kind = aText;
+	else if(as == AGLOBL)
+		p->kind = aData;
+	skip(bp, 5);		/* reg(1) lineno(4) */
+	a = addr(bp);
+	addr(bp);
+	if(a.type != D_OREG || a.name != D_STATIC && a.name != D_EXTERN)
+		p->kind = aNone;
+	p->sym = a.sym;
+	return 1;
+}
+
+static Addr
+addr(Biobuf *bp)
+{
+	Addr a;
+	long off;
+
+	a.type = Bgetc(bp);	/* a.type */
+	skip(bp,1);		/* reg */
+	a.sym = Bgetc(bp);	/* sym index */
+	a.name = Bgetc(bp);	/* sym type */
+	switch(a.type){
+	default:
+	case D_NONE:
+	case D_REG:
+	case D_SP:
+	case D_FREG:
+	case D_VREG:
+	case D_COND:
+		break;
+
+	case D_OREG:
+	case D_XPRE:
+	case D_XPOST:
+	case D_CONST:
+	case D_BRANCH:
+	case D_SHIFT:
+	case D_EXTREG:
+	case D_ROFF:
+	case D_SPR:
+		off = Bgetc(bp);
+		off |= Bgetc(bp) << 8;
+		off |= Bgetc(bp) << 16;
+		off |= Bgetc(bp) << 24;
+		if(off < 0)
+			off = -off;
+		if(a.sym && (a.name==D_PARAM || a.name==D_AUTO))
+			_offset(a.sym, off);
+		break;
+	case D_DCONST:
+		skip(bp, 8);
+		break;
+	case D_SCONST:
+		skip(bp, NSNAME);
+		break;
+	case D_FCONST:
+		skip(bp, 8);
+		break;
+	}
+	return a;
+}
+
+static char
+type2char(int t)
+{
+	switch(t){
+	case D_EXTERN:		return 'U';
+	case D_STATIC:		return 'b';
+	case D_AUTO:		return 'a';
+	case D_PARAM:		return 'p';
+	default:		return UNKNOWN;
+	}
+}
+
+static void
+skip(Biobuf *bp, int n)
+{
+	while (n-- > 0)
+		Bgetc(bp);
+}
--- a/sys/src/libmach/executable.c
+++ b/sys/src/libmach/executable.c
@@ -66,6 +66,7 @@
 extern	Mach	mi386;
 extern	Mach	mamd64;
 extern	Mach	marm;
+extern	Mach	marm64;
 extern	Mach	mpower;
 extern	Mach	mpower64;
 
@@ -233,6 +234,15 @@
 		sizeof(Exec),
 		leswal,
 		armdotout },
+	{ R_MAGIC,			/* Arm64 7.out and boot image */
+		"arm64 plan 9 executable",
+		"arm64 plan 9 dlm",
+		FARM64,
+		1,
+		&marm64,
+		sizeof(Exec)+8,
+		nil,
+		commonllp64 },
 	{ 0 },
 };
 
@@ -373,6 +383,12 @@
 		fp->type = FARMB;
 		fp->txtaddr = (u32int)fp->entry;
 		fp->name = "ARM plan 9 boot image";
+		fp->dataddr = _round(fp->txtaddr+fp->txtsz, mach->pgsize);
+		return;
+	case FARM64:
+		fp->type = FARM64B;
+		fp->txtaddr = fp->entry;
+		fp->name = "arm64 plan 9 boot image";
 		fp->dataddr = _round(fp->txtaddr+fp->txtsz, mach->pgsize);
 		return;
 	case FPOWER:
--- a/sys/src/libmach/mkfile
+++ b/sys/src/libmach/mkfile
@@ -18,6 +18,7 @@
 	2\
 	5\
 	6\
+	7\
 	8\
 	9\
 	vdb\
@@ -26,6 +27,7 @@
 	qdb\
 	2db\
 	5db\
+	7db\
 	8db\
 	vobj\
 	kobj\
@@ -33,6 +35,7 @@
 	2obj\
 	5obj\
 	6obj\
+	7obj\
 	8obj\
 	9obj\
 	qobj\
@@ -56,6 +59,7 @@
 2obj.$O: /sys/src/cmd/2c/2.out.h
 5obj.$O: /sys/src/cmd/5c/5.out.h
 6obj.$O: /sys/src/cmd/6c/6.out.h
+7obj.$O: /sys/src/cmd/7c/7.out.h
 8obj.$O: /sys/src/cmd/8c/8.out.h
 kobj.$O: /sys/src/cmd/kc/k.out.h
 qobj.$O: /sys/src/cmd/qc/q.out.h
--- a/sys/src/libmach/obj.c
+++ b/sys/src/libmach/obj.c
@@ -33,6 +33,7 @@
 	_read2(Biobuf*, Prog*),
 	_read5(Biobuf*, Prog*),
 	_read6(Biobuf*, Prog*),
+	_read7(Biobuf*, Prog*),
 	_read8(Biobuf*, Prog*),
 	_read9(Biobuf*, Prog*),
 	_readk(Biobuf*, Prog*),
@@ -55,6 +56,7 @@
 	[Obj68020]	"68020 .2",	_is2, _read2,
 	[ObjAmd64]	"amd64 .6",	_is6, _read6,
 	[ObjArm]	"arm .5",	_is5, _read5,
+	[ObjArm64]	"arm64 .7",	_is7, _read7,
 	[Obj386]	"386 .8",	_is8, _read8,
 	[ObjSparc]	"sparc .k",	_isk, _readk,
 	[ObjPower]	"power .q",	_isq, _readq,
--- a/sys/src/libmach/setmach.c
+++ b/sys/src/libmach/setmach.c
@@ -17,9 +17,9 @@
 };
 
 extern	Mach		mmips, msparc, m68020, mi386, mamd64,
-			marm, mmips2be, mmips2le, mpower, mpower64, msparc64;
+			marm, marm64, mmips2be, mmips2le, mpower, mpower64, msparc64;
 extern	Machdata	mipsmach, mipsmachle, sparcmach, m68020mach, i386mach,
-			armmach, mipsmach2le, powermach, sparc64mach;
+			armmach, arm64mach, mipsmach2le, powermach, sparc64mach;
 
 /*
  *	machine selection table.  machines with native disassemblers should
@@ -106,6 +106,12 @@
 		AARM,
 		&marm,
 		&armmach,	},
+	{	"arm64",			/*ARM64*/
+		FARM64,
+		FARM64B,
+		AARM64,
+		&marm64,
+		&arm64mach,	},
 	{	"power",			/*PowerPC*/
 		FPOWER,
 		FPOWERB,