changelog shortlog tags branches files raw gz bz2 help

Mercurial > hg > plan9front / changeset: libmach: initial arm64 support

changeset 7186: 4dd5e2428c1d
parent 7185: fb00248097c0
child 7187: 87d146071182
author: cinap_lenrek@felloff.net
date: Fri, 03 May 2019 21:00:17 +0200
files: sys/src/libmach/7.c sys/src/libmach/7db.c sys/src/libmach/7obj.c sys/src/libmach/executable.c sys/src/libmach/mkfile sys/src/libmach/obj.c sys/src/libmach/setmach.c
description: libmach: initial arm64 support
     1.1new file mode 100644
     1.2--- /dev/null
     1.3+++ b/sys/src/libmach/7.c
     1.4@@ -0,0 +1,80 @@
     1.5+/*
     1.6+ * arm definition
     1.7+ */
     1.8+#include <u.h>
     1.9+#include <libc.h>
    1.10+#include <bio.h>
    1.11+#include <mach.h>
    1.12+
    1.13+#include "/arm64/include/ureg.h"
    1.14+
    1.15+#define	REGOFF(x)	(uintptr)(&((struct Ureg *) 0)->x)
    1.16+
    1.17+#define SP		REGOFF(sp)
    1.18+#define PC		REGOFF(pc)
    1.19+
    1.20+#define	REGSIZE		sizeof(struct Ureg)
    1.21+
    1.22+Reglist arm64reglist[] =
    1.23+{
    1.24+	{"TYPE",	REGOFF(type),		RINT|RRDONLY, 'Y'},
    1.25+	{"PSR",		REGOFF(psr),		RINT|RRDONLY, 'Y'},
    1.26+	{"PC",		PC,			RINT, 'Y'},
    1.27+	{"SP",		SP,			RINT, 'Y'},
    1.28+	{"R30",		REGOFF(r30),		RINT, 'Y'},
    1.29+	{"R29",		REGOFF(r29),		RINT, 'Y'},
    1.30+	{"R28",		REGOFF(r28),		RINT, 'Y'},
    1.31+	{"R27",		REGOFF(r27),		RINT, 'Y'},
    1.32+	{"R26",		REGOFF(r26),		RINT, 'Y'},
    1.33+	{"R25",		REGOFF(r25),		RINT, 'Y'},
    1.34+	{"R24",		REGOFF(r24),		RINT, 'Y'},
    1.35+	{"R23",		REGOFF(r23),		RINT, 'Y'},
    1.36+	{"R22",		REGOFF(r22),		RINT, 'Y'},
    1.37+	{"R21",		REGOFF(r21),		RINT, 'Y'},
    1.38+	{"R20",		REGOFF(r20),		RINT, 'Y'},
    1.39+	{"R19",		REGOFF(r19),		RINT, 'Y'},
    1.40+	{"R18",		REGOFF(r18),		RINT, 'Y'},
    1.41+	{"R17",		REGOFF(r17),		RINT, 'Y'},
    1.42+	{"R16",		REGOFF(r16),		RINT, 'Y'},
    1.43+	{"R15",		REGOFF(r15),		RINT, 'Y'},
    1.44+	{"R14",		REGOFF(r14),		RINT, 'Y'},
    1.45+	{"R13",		REGOFF(r13),		RINT, 'Y'},
    1.46+	{"R12",		REGOFF(r12),		RINT, 'Y'},
    1.47+	{"R11",		REGOFF(r11),		RINT, 'Y'},
    1.48+	{"R10",		REGOFF(r10),		RINT, 'Y'},
    1.49+	{"R9",		REGOFF(r9),		RINT, 'Y'},
    1.50+	{"R8",		REGOFF(r8),		RINT, 'Y'},
    1.51+	{"R7",		REGOFF(r7),		RINT, 'Y'},
    1.52+	{"R6",		REGOFF(r6),		RINT, 'Y'},
    1.53+	{"R5",		REGOFF(r5),		RINT, 'Y'},
    1.54+	{"R4",		REGOFF(r4),		RINT, 'Y'},
    1.55+	{"R3",		REGOFF(r3),		RINT, 'Y'},
    1.56+	{"R2",		REGOFF(r2),		RINT, 'Y'},
    1.57+	{"R1",		REGOFF(r1),		RINT, 'Y'},
    1.58+	{"R0",		REGOFF(r0),		RINT, 'Y'},
    1.59+	{  0 }
    1.60+};
    1.61+
    1.62+	/* the machine description */
    1.63+Mach marm64 =
    1.64+{
    1.65+	"arm64",
    1.66+	MARM64,		/* machine type */
    1.67+	arm64reglist,	/* register set */
    1.68+	REGSIZE,	/* register set size */
    1.69+	0,		/* fp register set size */
    1.70+	"PC",		/* name of PC */
    1.71+	"SP",		/* name of SP */
    1.72+	"R30",		/* name of link register */
    1.73+	"setSB",	/* static base register name */
    1.74+	0,		/* static base register value */
    1.75+	0x10000,	/* page size (for segment alignment) */
    1.76+	0xFFFFFFFF80000000ULL,	/* kernel base */
    1.77+	0xFFFF800000000000ULL,	/* kernel text mask */
    1.78+	0x00007FFFFFFF0000ULL,	/* user stack top */
    1.79+	4,		/* quantization of pc */
    1.80+	8,		/* szaddr */
    1.81+	8,		/* szreg */
    1.82+	4,		/* szfloat */
    1.83+	8,		/* szdouble */
    1.84+};
     2.1new file mode 100644
     2.2--- /dev/null
     2.3+++ b/sys/src/libmach/7db.c
     2.4@@ -0,0 +1,728 @@
     2.5+#include <u.h>
     2.6+#include <libc.h>
     2.7+#include <bio.h>
     2.8+#include <mach.h>
     2.9+
    2.10+typedef struct Opcode Opcode;
    2.11+struct Opcode
    2.12+{
    2.13+	char	*p;
    2.14+	char	*o;
    2.15+	char	*a;
    2.16+};
    2.17+
    2.18+typedef struct	Instr	Instr;
    2.19+struct	Instr
    2.20+{
    2.21+	Opcode	*op;
    2.22+	Map	*map;
    2.23+	uvlong	addr;
    2.24+	ulong	w;
    2.25+
    2.26+	char	*curr;		/* fill point in buffer */
    2.27+	char	*end;		/* end of buffer */
    2.28+};
    2.29+
    2.30+static	void	format(char*, Instr*, char*);
    2.31+static	char	FRAMENAME[] = ".frame";
    2.32+
    2.33+/*
    2.34+ * Arm64-specific debugger interface
    2.35+ */
    2.36+static	char*	arm64excep(Map*, Rgetter);
    2.37+static	int	arm64foll(Map*, uvlong, Rgetter, uvlong*);
    2.38+static	int	arm64inst(Map*, uvlong, char, char*, int);
    2.39+static	int	arm64das(Map*, uvlong, char*, int);
    2.40+static	int	arm64instlen(Map*, uvlong);
    2.41+
    2.42+/*
    2.43+ *	Debugger interface
    2.44+ */
    2.45+Machdata arm64mach =
    2.46+{
    2.47+	{0x00, 0x00, 0x20, 0xD4},	/* break point 0xD4200000 */
    2.48+	4,		/* break point size */
    2.49+	leswab,		/* short to local byte order */
    2.50+	leswal,		/* long to local byte order */
    2.51+	leswav,		/* long to local byte order */
    2.52+	risctrace,	/* C traceback */
    2.53+	riscframe,	/* Frame finder */
    2.54+	arm64excep,	/* print exception */
    2.55+	0,		/* breakpoint fixup */
    2.56+	0,		/* single precision float printer */
    2.57+	0,		/* double precision float printer */
    2.58+	arm64foll,	/* following addresses */
    2.59+	arm64inst,	/* print instruction */
    2.60+	arm64das,	/* dissembler */
    2.61+	arm64instlen,	/* instruction size */
    2.62+};
    2.63+
    2.64+static Opcode opcodes[] =
    2.65+{
    2.66+	"0AA10000AAAAAAAAAAAAAAAAAAAddddd",	"ADR",		"$%A,R%d",
    2.67+	"1PP10000PPPPPPPPPPPPPPPPPPPddddd",	"ADRP",		"$%P,R%d",
    2.68+	"00011000lllllllllllllllllllddddd",	"MOVWU",	"%l,R%d",
    2.69+	"01011000LLLLLLLLLLLLLLLLLLLddddd",	"MOV",		"%L,R%d",
    2.70+	"10011000lllllllllllllllllllddddd",	"MOVW",		"%l,R%d",
    2.71+	"11011000lllllllllllllllllllddddd",	"PRFM",		"%l,$%d",
    2.72+	"1111100100uuuuuuuuuuuu11111ddddd",	"MOV",		"R%d,%u(SP)",
    2.73+	"1111100100uuuuuuuuuuuunnnnnddddd",	"MOV",		"R%d,%u(R%n)",
    2.74+	"WW11100100uuuuuuuuuuuu11111ddddd",	"MOV%WU",	"R%d,%u(SP)",
    2.75+	"WW11100100uuuuuuuuuuuunnnnnddddd",	"MOV%WU",	"R%d,%u(R%n)",
    2.76+	"1111100101uuuuuuuuuuuu11111ddddd",	"MOV",		"%u(SP),R%d",
    2.77+	"1111100101uuuuuuuuuuuunnnnnddddd",	"MOV",		"%u(R%n),R%d",
    2.78+	"WW11100101uuuuuuuuuuuu11111ddddd",	"MOV%WU",	"%u(SP),R%d",
    2.79+	"WW11100101uuuuuuuuuuuunnnnnddddd",	"MOV%WU",	"%u(R%n),R%d",
    2.80+	"WW11100110uuuuuuuuuuuu11111ddddd",	"MOV%W",	"%u(SP),R%d",
    2.81+	"WW11100110uuuuuuuuuuuunnnnnddddd",	"MOV%W",	"%u(R%n),R%d",
    2.82+	"11111000000ooooooooo0011111ddddd",	"MOV",		"R%d,%o(SP)",
    2.83+	"11111000000ooooooooo00nnnnnddddd",	"MOV",		"R%d,%o(R%n)",
    2.84+	"WW111000000ooooooooo0011111ddddd",	"MOV%W",	"R%d,%o(SP)",
    2.85+	"WW111000000ooooooooo00nnnnnddddd",	"MOV%W",	"R%d,%o(R%n)",
    2.86+	"11111000010ooooooooo0011111ddddd",	"MOV",		"%o(SP),R%d",
    2.87+	"11111000010ooooooooo00nnnnnddddd",	"MOV",		"%o(R%n),R%d",
    2.88+	"WW111000010ooooooooo0011111ddddd",	"MOV%WU",	"%o(SP),R%d",
    2.89+	"WW111000010ooooooooo00nnnnnddddd",	"MOV%WU",	"%o(R%n),R%d",
    2.90+	"WW111000100ooooooooo0011111ddddd",	"MOV%W",	"%o(SP),R%d",
    2.91+	"WW111000100ooooooooo00nnnnnddddd",	"MOV%W",	"%o(R%n),R%d",
    2.92+	"11111000000ooooooooo0111111ddddd",	"MOV",		"R%d,(SP)%o!",
    2.93+	"WW111000000ooooooooo0111111ddddd",	"MOV%WU",	"R%d,(SP)%o!",
    2.94+	"WW111000000ooooooooo01nnnnnddddd",	"MOV%WU",	"R%d,(R%n)%o!",
    2.95+	"11111000000ooooooooo1111111ddddd",	"MOV",		"R%d,%o(SP)!",
    2.96+	"WW111000000ooooooooo1111111ddddd",	"MOV%WU",	"R%d,%o(SP)!",
    2.97+	"WW111000000ooooooooo11nnnnnddddd",	"MOV%WU",	"R%d,%o(R%n)!",
    2.98+	"11111000010ooooooooo0111111ddddd",	"MOV",		"(SP)%o!,R%d",
    2.99+	"11111000010ooooooooo01nnnnnddddd",	"MOV",		"(R%n)%o!,R%d",
   2.100+	"WW111000010ooooooooo0111111ddddd",	"MOV%WU",	"(SP)%o!,R%d",
   2.101+	"WW111000010ooooooooo01nnnnnddddd",	"MOV%WU",	"(R%n)%o!,R%d",
   2.102+	"WW111000100ooooooooo0111111ddddd",	"MOV%W",	"(SP)%o!,R%d",
   2.103+	"WW111000100ooooooooo01nnnnnddddd",	"MOV%W",	"(R%n)%o!,R%d",
   2.104+	"11111000010ooooooooo1111111ddddd",	"MOV",		"%o(SP)!,R%d",
   2.105+	"11111000010ooooooooo11nnnnnddddd",	"MOV",		"%o(R%n)!,R%d",
   2.106+	"WW111000010ooooooooo1111111ddddd",	"MOV%WU",	"%o(SP)!,R%d",
   2.107+	"WW111000010ooooooooo11nnnnnddddd",	"MOV%WU",	"%o(R%n)!,R%d",
   2.108+	"WW111000100ooooooooo1111111ddddd",	"MOV%W",	"%o(SP)!,R%d",
   2.109+	"WW111000100ooooooooo11nnnnnddddd",	"MOV%W",	"%o(R%n)!,R%d",
   2.110+	"11111000001mmmmmeeei10nnnnnddddd",	"MOV",		"R%d,(R%n)(R%m%e)",
   2.111+	"11111000111mmmmmeeei10nnnnnddddd",	"MOV",		"(R%n)(R%m%e),R%d",
   2.112+	"WW111000001mmmmmeeei10nnnnnddddd",	"MOV%W",	"R%d,(R%n)(R%m%e)",
   2.113+	"WW111000011mmmmmeeei10nnnnnddddd",	"MOV%WU",	"(R%n)(R%m%e),R%d",
   2.114+	"WW111000101mmmmmeeei10nnnnnddddd",	"MOV%W",	"(R%n)(R%m%e),R%d",
   2.115+	"WW111000111mmmmmeeei10nnnnnddddd",	"MOV%WW",	"(R%n)(R%m%e),R%d",
   2.116+	"W00100101ssKKKKKKKKKKKKKKKKddddd",	"MOVN%W",	"$%K,R%d",
   2.117+	"W10100101ssKKKKKKKKKKKKKKKKddddd",	"MOVZ%W",	"$%K,R%d",
   2.118+	"W11100101ssKKKKKKKKKKKKKKKKddddd",	"MOVK%W",	"$%K,R%d",
   2.119+	"W0010001--00000000000011111ddddd",	"MOV%W",	"SP,R%d",
   2.120+	"W0010001--000000000000nnnnn11111",	"MOV%W",	"R%n,SP",
   2.121+	"W0010001ssIIIIIIIIIIII1111111111",	"ADD%W",	"$%I,SP,SP",
   2.122+	"W0010001ssIIIIIIIIIIII11111ddddd",	"ADD%W",	"$%I,SP,R%d",
   2.123+	"W0010001ssIIIIIIIIIIIInnnnn11111",	"ADD%W",	"$%I,R%n,SP",
   2.124+	"W0110001ssIIIIIIIIIIII1111111111",	"ADDS%W",	"$%I,SP,SP",
   2.125+	"W0110001ssIIIIIIIIIIII11111ddddd",	"ADDS%W",	"$%I,SP,R%d",
   2.126+	"W0110001ssIIIIIIIIIIIInnnnn11111",	"ADDS%W",	"$%I,R%n,SP",
   2.127+	"W1010001ssIIIIIIIIIIII1111111111",	"SUB%W",	"$%I,SP,SP",
   2.128+	"W1010001ssIIIIIIIIIIII11111ddddd",	"SUB%W",	"$%I,SP,R%d",
   2.129+	"W1010001ssIIIIIIIIIIIInnnnn11111",	"SUB%W",	"$%I,R%n,SP",
   2.130+	"W1110001ssIIIIIIIIIIII1111111111",	"CMP%W",	"$%I,SP",
   2.131+	"W1110001ssIIIIIIIIIIIInnnnn11111",	"CMP%W",	"$%I,R%n",
   2.132+	"W1110001ssIIIIIIIIIIII11111ddddd",	"SUBS%W",	"$%I,SP,R%d",
   2.133+	"W0010001ssIIIIIIIIIIIInnnnnddddd",	"ADD%W",	"$%I,R%n,R%d",
   2.134+	"W0110001ssIIIIIIIIIIIInnnnnddddd",	"ADDS%W",	"$%I,R%n,R%d",
   2.135+	"W1010001ssIIIIIIIIIIIInnnnnddddd",	"SUB%W",	"$%I,R%n,R%d",
   2.136+	"W1110001ssIIIIIIIIIIIInnnnnddddd",	"SUBS%W",	"$%I,R%n,R%d",
   2.137+	"W00100100MMMMMMMMMMMMMnnnnn11111",	"AND%W",	"$%M,R%n,SP",
   2.138+	"W01100100MMMMMMMMMMMMMnnnnn11111",	"ORR%W",	"$%M,R%n,SP",
   2.139+	"W10100100MMMMMMMMMMMMMnnnnn11111",	"EOR%W",	"$%M,R%n,SP",
   2.140+	"W11100100MMMMMMMMMMMMMnnnnn11111",	"ANDS%W",	"$%M,R%n,SP",
   2.141+	"W00100100MMMMMMMMMMMMMnnnnnddddd",	"AND%W",	"$%M,R%n,R%d",
   2.142+	"W01100100MMMMMMMMMMMMMnnnnnddddd",	"ORR%W",	"$%M,R%n,R%d",
   2.143+	"W10100100MMMMMMMMMMMMMnnnnnddddd",	"EOR%W",	"$%M,R%n,R%d",
   2.144+	"W11100100MMMMMMMMMMMMMnnnnnddddd",	"ANDS%W",	"$%M,R%n,R%d",
   2.145+	"1001001101000000011111nnnnnddddd",	"SXTW",		"R%n,R%d",
   2.146+	"0101001100iiiiii011111nnnnnddddd",	"LSRW",		"$%i,R%n,R%d",
   2.147+	"1101001101iiiiii111111nnnnnddddd",	"LSR",		"$%i,R%n,R%d",
   2.148+	"W00100110-iiiiiijjjjjjnnnnnddddd",	"SBFM%W",	"$%i,$%j,R%n,R%d",
   2.149+	"W01100110-iiiiiijjjjjjnnnnnddddd",	"BFM%W",	"$%i,$%j,R%n,R%d",
   2.150+	"W10100110-iiiiiijjjjjjnnnnnddddd",	"UBFM%W",	"$%i,$%j,R%n,R%d",
   2.151+	"W1011010000mmmmm00000011111ddddd",	"NGC%W",	"R%m,R%d",
   2.152+	"W1111010000mmmmm00000011111ddddd",	"NGCS%W",	"R%m,R%d",
   2.153+	"W0011010000mmmmm000000nnnnnddddd",	"ADC%W",	"R%m,R%n,R%d",
   2.154+	"W0111010000mmmmm000000nnnnnddddd",	"ADCS%W",	"R%m,R%n,R%d",
   2.155+	"W1011010000mmmmm000000nnnnnddddd",	"SBC%W",	"R%m,R%n,R%d",
   2.156+	"W1111010000mmmmm000000nnnnnddddd",	"SBCS%W",	"R%m,R%n,R%d",
   2.157+	"W0101011ss0mmmmmiiiiiinnnnn11111",	"CMN%W",	"R%m%s,R%n",
   2.158+	"W1101011ss0mmmmmiiiiiinnnnn11111",	"CMP%W",	"R%m%s,R%n",
   2.159+	"W1001011ss0mmmmmiiiiii11111ddddd",	"NEG%W",	"R%m%s,R%d",
   2.160+	"W1101011ss0mmmmmiiiiii11111ddddd",	"NEGS%W",	"R%m%s,R%d",
   2.161+	"W0001011ss0mmmmmiiiiiinnnnnddddd",	"ADD%W",	"R%m%s,R%n,R%d",
   2.162+	"W0101011ss0mmmmmiiiiiinnnnnddddd",	"ADDS%W",	"R%m%s,R%n,R%d",
   2.163+	"W1001011ss0mmmmmiiiiiinnnnnddddd",	"SUB%W",	"R%m%s,R%n,R%d",
   2.164+	"W1101011ss0mmmmmiiiiiinnnnnddddd",	"SUBS%W",	"R%m%s,R%n,R%d",
   2.165+	"W0001011001mmmmmeeeiii1111111111",	"ADD%W",	"R%m%e,SP,SP",
   2.166+	"W0001011001mmmmmeeeiii11111ddddd",	"ADD%W",	"R%m%e,SP,R%d",
   2.167+	"W0001011001mmmmmeeeiiinnnnn11111",	"ADD%W",	"R%m%e,R%n,SP",
   2.168+	"W0101011001mmmmmeeeiii1111111111",	"ADDS%W",	"R%m%e,SP,SP",
   2.169+	"W0101011001mmmmmeeeiii11111ddddd",	"ADDS%W",	"R%m%e,SP,R%d",
   2.170+	"W0101011001mmmmmeeeiiinnnnn11111",	"ADDS%W",	"R%m%e,R%n,SP",
   2.171+	"W1001011001mmmmmeeeiii1111111111",	"SUB%W",	"R%m%e,SP,SP",
   2.172+	"W1001011001mmmmmeeeiii11111ddddd",	"SUB%W",	"R%m%e,SP,R%d",
   2.173+	"W1001011001mmmmmeeeiiinnnnn11111",	"SUB%W",	"R%m%e,R%n,SP",
   2.174+	"W1101011001mmmmmeeeiii1111111111",	"SUBS%W",	"R%m%e,SP,SP",
   2.175+	"W1101011001mmmmmeeeiii11111ddddd",	"SUBS%W",	"R%m%e,SP,R%d",
   2.176+	"W1101011001mmmmmeeeiiinnnnn11111",	"SUBS%W",	"R%m%e,R%n,SP",
   2.177+	"W0001011001mmmmmeeeiiinnnnnddddd",	"ADD%W",	"R%m%e,R%n,R%d",
   2.178+	"W0101011001mmmmmeeeiiinnnnnddddd",	"ADDS%W",	"R%m%e,R%n,R%d",
   2.179+	"W1001011001mmmmmeeeiiinnnnnddddd",	"SUB%W",	"R%m%e,R%n,R%d",
   2.180+	"W1101011001mmmmmeeeiiinnnnnddddd",	"SUBS%W",	"R%m%e,R%n,R%d",
   2.181+	"W0101010000mmmmm-0000011111ddddd",	"MOV%W",	"R%m,R%d",
   2.182+	"W0101010ss1mmmmmiiiiii11111ddddd",	"NVM%W",	"R%m%s,R%d",
   2.183+	"W1101010ss0mmmmmiiiiiinnnnn11111",	"TST%W",	"R%m%s,R%n",
   2.184+	"W0001010ss0mmmmmiiiiiinnnnnddddd",	"AND%W",	"R%m%s,R%n,R%d",
   2.185+	"W1101010ss0mmmmmiiiiiinnnnnddddd",	"ANDS%W",	"R%m%s,R%n,R%d",
   2.186+	"W0001010ss1mmmmmiiiiiinnnnnddddd",	"BIC%W",	"R%m%s,R%n,R%d",
   2.187+	"W1101010ss1mmmmmiiiiiinnnnnddddd",	"BICS%W",	"R%m%s,R%n,R%d",
   2.188+	"W1001010ss0mmmmmiiiiiinnnnnddddd",	"EOR%W",	"R%m%s,R%n,R%d",
   2.189+	"W1001010ss1mmmmmiiiiiinnnnnddddd",	"EON%W",	"R%m%s,R%n,R%d",
   2.190+	"W0101010ss0mmmmmiiiiiinnnnnddddd",	"ORR%W",	"R%m%s,R%n,R%d",
   2.191+	"W0101010ss1mmmmmiiiiiinnnnnddddd",	"ORN%W",	"R%m%s,R%n,R%d",
   2.192+	"W0011010110mmmmm001000nnnnnddddd",	"LSL%W",	"R%m,R%n,R%d",
   2.193+	"W0011010110mmmmm001001nnnnnddddd",	"LSR%W",	"R%m,R%n,R%d",
   2.194+	"W0011010110mmmmm001010nnnnnddddd",	"ASR%W",	"R%m,R%n,R%d",
   2.195+	"W0011010110mmmmm001011nnnnnddddd",	"ROR%W",	"R%m,R%n,R%d",
   2.196+	"W0011010110mmmmm000010nnnnnddddd",	"UDIV%W",	"R%m,R%n,R%d",
   2.197+	"W0011010110mmmmm000011nnnnnddddd",	"SDIV%W",	"R%m,R%n,R%d",
   2.198+	"W0011011000mmmmm011111nnnnnddddd",	"MUL%W",	"R%m,R%n,R%d",
   2.199+	"W0011011000mmmmm111111nnnnnddddd",	"MNEG%W",	"R%m,R%n,R%d",
   2.200+	"W0011011000mmmmm0aaaaannnnnddddd",	"MADD%W",	"R%m,R%n,R%a,R%d",
   2.201+	"W0011011000mmmmm1aaaaannnnnddddd",	"MSUB%W",	"R%m,R%n,R%a,R%d",
   2.202+	"10011011001mmmmm011111nnnnnddddd",	"SMULL",	"R%m,R%n,R%d",
   2.203+	"10011011001mmmmm111111nnnnnddddd",	"SMNEGL",	"R%m,R%n,R%d",
   2.204+	"10011011001mmmmm0aaaaannnnnddddd",	"SMADDL",	"R%m,R%n,R%a,R%d",
   2.205+	"10011011001mmmmm1aaaaannnnnddddd",	"SMSUBL",	"R%m,R%n,R%a,R%d",
   2.206+	"10011011101mmmmm011111nnnnnddddd",	"UMULL",	"R%m,R%n,R%d",
   2.207+	"10011011101mmmmm111111nnnnnddddd",	"UMNEGL",	"R%m,R%n,R%d",
   2.208+	"10011011101mmmmm0aaaaannnnnddddd",	"UMADDL",	"R%m,R%n,R%a,R%d",
   2.209+	"10011011101mmmmm1aaaaannnnnddddd",	"UMSUBL",	"R%m,R%n,R%a,R%d",
   2.210+	"W0110100TTTTTTTTTTTTTTTTTTTddddd",	"CBZ%W",	"R%d,%T",
   2.211+	"W0110101TTTTTTTTTTTTTTTTTTTddddd",	"CBNZ%W",	"R%d,%T",
   2.212+	"01010100TTTTTTTTTTTTTTTTTTT0CCCC",	"B%C",		"%T",
   2.213+	"000101TTTTTTTTTTTTTTTTTTTTTTTTTT",	"B",		"%T",
   2.214+	"100101TTTTTTTTTTTTTTTTTTTTTTTTTT",	"BL",		"%T",
   2.215+	"1101011000011111000000nnnnn00000",	"BR",		"R%n",
   2.216+	"1101011000111111000000nnnnn00000",	"BLR",		"R%n",
   2.217+	"11010110010111110000001111000000",	"RETURN",	nil,
   2.218+	"1101011001011111000000nnnnn00000",	"RET",		"R%n",
   2.219+	"11010110100111110000001111100000",	"ERET",		nil,
   2.220+	"11010110101111110000001111100000",	"DRPS",		nil,
   2.221+	"11010100000iiiiiiiiiiiiiiii00001",	"SVC",		"$%i",
   2.222+	"11010100000iiiiiiiiiiiiiiii00010",	"HVC",		"$%i",
   2.223+	"11010100000iiiiiiiiiiiiiiii00011",	"SMC",		"$%i",
   2.224+	"11010100001iiiiiiiiiiiiiiii00000",	"BRK",		"$%i",
   2.225+	"11010100010iiiiiiiiiiiiiiii00000",	"HLT",		"$%i",
   2.226+	"11010100101iiiiiiiiiiiiiiii00001",	"DCPS1",	"$%i",
   2.227+	"11010100101iiiiiiiiiiiiiiii00010",	"DCPS2",	"$%i",
   2.228+	"11010100101iiiiiiiiiiiiiiii00011",	"DCPS3",	"$%i",
   2.229+	"11010101000000110010000000011111",	"NOP",		nil,
   2.230+	"11010101000000110010000000111111",	"YIELD",	nil,
   2.231+	"11010101000000110010000001011111",	"WFE",		nil,
   2.232+	"11010101000000110010000001111111",	"WFI",		nil,
   2.233+	"11010101000000110010000010011111",	"SEV",		nil,
   2.234+	"11010101000000110010000010111111",	"SEVL",		nil,
   2.235+	"11010101000000110011xxxx01011111",	"CLREX",	"$%x",
   2.236+	"11010101000000110011xxxx10011111",	"DSB",		"$%x",
   2.237+	"11010101000000110011xxxx10111111",	"DMB",		"$%x",
   2.238+	"11010101000000110011xxxx11011111",	"ISB",		"$%x",
   2.239+	"1101010100001YYYYYYYYYYYYYY11111",	"SYS",		"%Y",
   2.240+	"1101010100001YYYYYYYYYYYYYYddddd",	"SYS",		"R%d,%Y",
   2.241+	"1101010100101YYYYYYYYYYYYYYddddd",	"SYSL",		"%Y,R%d",
   2.242+	"11010101000000000100xxxx10111111",	"MSR",		"$%x,SP",
   2.243+	"11010101000000110100xxxx11011111",	"MSR",		"$%x,DAIFSet",
   2.244+	"11010101000000110100xxxx11111111",	"MSR",		"$%x,DAIFClr",
   2.245+	"11010101000YYYYYYYYYYYYYYYYddddd",	"MSR",		"R%d,%Y",
   2.246+	"11010101001YYYYYYYYYYYYYYYYddddd",	"MRS",		"%Y,R%d",
   2.247+	"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",	"WORD",		"$%x",
   2.248+};
   2.249+
   2.250+#define	SYSARG5(op0,op1,Cn,Cm,op2)	((op0)<<19|(op1)<<16|(Cn)<<12|(Cm)<<8|(op2)<<5)
   2.251+
   2.252+static ulong
   2.253+smask(char *s, char c)
   2.254+{
   2.255+	ulong m;
   2.256+	int i;
   2.257+
   2.258+	m = 0;
   2.259+	for(i=0; i<32 && *s != '\0'; i++, s++)
   2.260+		m |= (*s == c)<<(31-i);
   2.261+	return m;
   2.262+}
   2.263+
   2.264+static int
   2.265+nbits(ulong v)
   2.266+{
   2.267+	int n = 0;
   2.268+	while(v != 0){
   2.269+		v &= v-1;
   2.270+		n++;
   2.271+	}
   2.272+	return n;
   2.273+}
   2.274+
   2.275+static int
   2.276+nones(ulong v)
   2.277+{
   2.278+	int n = 0;
   2.279+	while(v & 1){
   2.280+		v >>= 1;
   2.281+		n++;
   2.282+	}
   2.283+	return n;
   2.284+}
   2.285+
   2.286+static int
   2.287+nshift(ulong m)
   2.288+{
   2.289+	if(m == 0 || m == ~0UL)
   2.290+		return 0;
   2.291+	return nones(~m);
   2.292+}
   2.293+
   2.294+static ulong
   2.295+unshift(ulong w, ulong m)
   2.296+{
   2.297+	int s = nshift(m);
   2.298+	w >>= s, m >>= s;
   2.299+	if((m+1 & m) != 0){	// 0bxxx0000yyyyyy -> 0byyyyyyxxx
   2.300+		ulong b = (1UL<<nones(m))-1;
   2.301+		return ((w & b) << nbits(m & ~b)) | unshift(w, m & ~b);
   2.302+	}
   2.303+	return w & m;
   2.304+}
   2.305+
   2.306+static long
   2.307+sext(ulong u, int n)
   2.308+{
   2.309+	long l = (long)u;
   2.310+	if(n > 0){
   2.311+		l <<= sizeof(l)*8 - n;
   2.312+		l >>= sizeof(l)*8 - n;
   2.313+	}
   2.314+	return l;
   2.315+}
   2.316+
   2.317+static char*
   2.318+arm64excep(Map *, Rgetter)
   2.319+{
   2.320+//	uvlong c = (*rget)(map, "TYPE");
   2.321+	return "???";
   2.322+}
   2.323+
   2.324+static int
   2.325+decode(Map *map, uvlong pc, Instr *i)
   2.326+{
   2.327+	static ulong tab[2*nelem(opcodes)];
   2.328+	static int once;
   2.329+	ulong w, j;
   2.330+
   2.331+	if(!once){
   2.332+		Opcode *o;
   2.333+
   2.334+		/* precalculate value/mask table */
   2.335+		for(j=0, o=opcodes; j<nelem(tab); j+=2, o++){
   2.336+			tab[j] = smask(o->p, '1');
   2.337+			tab[j|1] = tab[j] | smask(o->p, '0');
   2.338+		}
   2.339+
   2.340+		once = 1;
   2.341+	}
   2.342+
   2.343+	if(get4(map, pc, &w) < 0) {
   2.344+		werrstr("can't read instruction: %r");
   2.345+		return -1;
   2.346+	}
   2.347+	i->addr = pc;
   2.348+	i->map = map;
   2.349+	i->w = w;
   2.350+
   2.351+	for(j=0; j<nelem(tab); j+=2){
   2.352+		if((w & tab[j|1]) == tab[j]){
   2.353+			i->op = &opcodes[j/2];
   2.354+			return 1;
   2.355+		}
   2.356+	}
   2.357+
   2.358+	/* should not happen */
   2.359+	return 0;
   2.360+}
   2.361+
   2.362+#pragma	varargck	argpos	bprint	2
   2.363+
   2.364+static void
   2.365+bprint(Instr *i, char *fmt, ...)
   2.366+{
   2.367+	va_list arg;
   2.368+
   2.369+	va_start(arg, fmt);
   2.370+	i->curr = vseprint(i->curr, i->end, fmt, arg);
   2.371+	va_end(arg);
   2.372+}
   2.373+
   2.374+static
   2.375+char*	shtype[4] =
   2.376+{
   2.377+	"<<",	">>",	"->",	"@>"
   2.378+};
   2.379+
   2.380+static
   2.381+char*	rextype[8] =
   2.382+{
   2.383+	"UB", "UH", "UW", "UX",
   2.384+	"SB", "SH", "SW", "SX"
   2.385+};
   2.386+
   2.387+static
   2.388+char*	scond[16] =
   2.389+{
   2.390+	"EQ", "NE", "HS", "LO",
   2.391+	"MI", "PL", "VS", "VC",
   2.392+	"HI", "LS", "GE", "LT",
   2.393+	"GT", "LE",   "", "NV",
   2.394+};
   2.395+
   2.396+static uvlong
   2.397+decodebitmask(int n, int s, int r)
   2.398+{
   2.399+	uvlong w;
   2.400+	int e;
   2.401+
   2.402+	if(n)
   2.403+		n = 6;
   2.404+	else {
   2.405+		for(n = 5; n >= 1 && ((~s & 0x3F) & (1<<n)) == 0; n--)
   2.406+			;
   2.407+	}
   2.408+	e = 1 << n;
   2.409+	s &= e-1;
   2.410+	r &= e-1;
   2.411+
   2.412+	w = 1ULL << s;
   2.413+	w |= w-1;
   2.414+
   2.415+	if(r != 0){
   2.416+		w = (w >> r) | (w << (e-r));
   2.417+		if(e < 64)
   2.418+			w &= (1ULL << e)-1;
   2.419+	}
   2.420+	while(e < 64){
   2.421+		w |= w << e;
   2.422+		e <<= 1;
   2.423+	}
   2.424+	return w;
   2.425+}
   2.426+
   2.427+static void
   2.428+format(char *mnemonic, Instr *i, char *f)
   2.429+{
   2.430+	Symbol s;
   2.431+	uvlong v;
   2.432+	ulong w, u, m;
   2.433+
   2.434+	if(mnemonic)
   2.435+		format(0, i, mnemonic);
   2.436+	if(f == 0)
   2.437+		return;
   2.438+	if(mnemonic)
   2.439+		if(i->curr < i->end)
   2.440+			*i->curr++ = '\t';
   2.441+	for ( ; *f && i->curr < i->end; f++) {
   2.442+		if(*f != '%') {
   2.443+			*i->curr++ = *f;
   2.444+			continue;
   2.445+		}
   2.446+		m = smask(i->op->p, *++f);
   2.447+		u = unshift(i->w, m);
   2.448+		switch (*f) {
   2.449+		case 'C':	// Condition
   2.450+			bprint(i, "%s", scond[u & 15]);
   2.451+			break;
   2.452+
   2.453+		case 'W':	// Width
   2.454+			if(nbits(m) == 1) u += 2;
   2.455+			u &= 3;
   2.456+			if(u < 3)
   2.457+				*i->curr++ = "BHW"[u];
   2.458+			break;
   2.459+
   2.460+		case 'd':	// Register Numbers
   2.461+		case 'n':
   2.462+		case 'a':
   2.463+		case 'm':
   2.464+			bprint(i, "%lud", u);
   2.465+			break;
   2.466+
   2.467+		case 's':	// Register shift
   2.468+			w = unshift(i->w, smask(i->op->p, 'i'));
   2.469+			if(w != 0)
   2.470+				bprint(i, "%s%lud", shtype[u & 3], w);
   2.471+			break;
   2.472+
   2.473+		case 'e':	// Register extension
   2.474+			u &= 7;
   2.475+			bprint(i, ".%s", rextype[u]);
   2.476+			w = unshift(i->w, smask(i->op->p, 'i'));
   2.477+			if(w != 0 && u == 2+(i->w>>31))
   2.478+				bprint(i, "<<%lud", w);
   2.479+			break;
   2.480+
   2.481+		case 'M':	// Bitmask
   2.482+			v = decodebitmask((u>>12)&1, u&0x3F, (u>>6)&0x3F);
   2.483+			if((i->w & (1<<31)) == 0)
   2.484+				v &= 0xFFFFFFFF;
   2.485+			bprint(i, "%llux", v);
   2.486+			break;
   2.487+
   2.488+		case 'I':	// Shifted Immediate (12 bit)
   2.489+		case 'K':	// Shifted Immediate (16 bit)
   2.490+			w = unshift(i->w, smask(i->op->p, 's'));
   2.491+			if(u != 0 && w != 0)
   2.492+				bprint(i, "(%lux<<%ld)", u, w*(*f == 'I' ? 12 : 16));
   2.493+			else
   2.494+				bprint(i, "%lud", u);
   2.495+			break;
   2.496+
   2.497+		case 'o':	// Signed byte offset
   2.498+			bprint(i, "%ld", sext(u, nbits(m)));
   2.499+			break;
   2.500+		case 'u':	// Unsigned offset
   2.501+			u <<= (i->w >> 30)&3;
   2.502+			/* wet floor */
   2.503+		case 'i':	// Decimal
   2.504+		case 'j':
   2.505+			bprint(i, "%lud", u);
   2.506+			break;
   2.507+
   2.508+		case 'x':	// Hex
   2.509+			bprint(i, "%lux", u);
   2.510+			break;
   2.511+
   2.512+		case 'l':	// 32-bit Literal
   2.513+			if(get4(i->map, i->addr + sext(u, nbits(m))*4, &w) < 0)
   2.514+				goto Ptext;
   2.515+			bprint(i, "$%lux", w);
   2.516+			break;
   2.517+		case 'L':	// 64-bit Literal
   2.518+			if(get8(i->map, i->addr + sext(u, nbits(m))*4, &v) < 0)
   2.519+				goto Ptext;
   2.520+			bprint(i, "$%llux", v);
   2.521+			break;
   2.522+		case 'T':	// Text address (PC relative)
   2.523+		Ptext:
   2.524+			v = i->addr + sext(u, nbits(m))*4;
   2.525+			if(findsym(v, CTEXT, &s)){
   2.526+				bprint(i, "%s", s.name);
   2.527+				if(v < s.value)
   2.528+					bprint(i, "%llx", v - s.value);
   2.529+				else if(v > s.value)
   2.530+					bprint(i, "+%llx", v - s.value);
   2.531+				bprint(i, "(SB)");
   2.532+				break;
   2.533+			}
   2.534+			bprint(i, "%llux(SB)", v);
   2.535+			break;
   2.536+		case 'A':	// Data address (PC relative)
   2.537+			v = i->addr + sext(u, nbits(m));
   2.538+			goto Pdata;
   2.539+		case 'P':	// Page address (PC relative)
   2.540+			v = i->addr + ((vlong)sext(u, nbits(m)) << 12);
   2.541+		Pdata:
   2.542+			if(findsym(v, CANY, &s)){
   2.543+				bprint(i, "%s", s.name);
   2.544+				if(v < s.value)
   2.545+					bprint(i, "%llx", v - s.value);
   2.546+				else if(v > s.value)
   2.547+					bprint(i, "+%llx", v - s.value);
   2.548+				bprint(i, "(SB)");
   2.549+				break;
   2.550+			}
   2.551+			bprint(i, "%llux(SB)", v);
   2.552+			break;
   2.553+
   2.554+		case 'Y':
   2.555+			if(nbits(m) == 14){ // SYS/SYSL operands
   2.556+				bprint(i, "%lud,%lud,%lud,%lud",
   2.557+					(u>>(4+4+3))&7,	// op1
   2.558+					(u>>(4+3))&15,	// CRn
   2.559+					(u>>3)&15,	// CRm
   2.560+					(u)&7);		// op2
   2.561+				break;
   2.562+			}
   2.563+			/* see /sys/src/cmd/7c/7.out.h */
   2.564+			switch(i->w & m){
   2.565+			case SYSARG5(3,3,4,2,1): bprint(i, "DAIF"); break;
   2.566+			case SYSARG5(3,3,4,2,0): bprint(i, "NZCV"); break;
   2.567+			case SYSARG5(3,3,4,4,1): bprint(i, "FPSR"); break;
   2.568+			case SYSARG5(3,3,4,4,0): bprint(i, "FPCR"); break;
   2.569+			case SYSARG5(3,0,4,0,0): bprint(i, "SPSR_EL1"); break;
   2.570+			case SYSARG5(3,0,4,0,1): bprint(i, "ELR_EL1"); break;
   2.571+			case SYSARG5(3,4,4,0,0): bprint(i, "SPSR_EL2"); break;
   2.572+			case SYSARG5(3,4,4,0,1): bprint(i, "ELR_EL2"); break;
   2.573+			case SYSARG5(3,0,4,2,2): bprint(i, "CurrentEL"); break;
   2.574+			case SYSARG5(3,0,4,1,0): bprint(i, "SP_EL0"); break;
   2.575+			case SYSARG5(3,0,4,2,0): bprint(i, "SPSel"); break;
   2.576+			default: bprint(i, "SPR(%lux)", i->w & m);
   2.577+			}
   2.578+			break;
   2.579+
   2.580+		case '\0':
   2.581+			*i->curr++ = '%';
   2.582+			return;
   2.583+
   2.584+		default:
   2.585+			bprint(i, "%%%c", *f);
   2.586+			break;
   2.587+		}
   2.588+	}
   2.589+	*i->curr = 0;
   2.590+}
   2.591+
   2.592+static int
   2.593+printins(Map *map, uvlong pc, char *buf, int n)
   2.594+{
   2.595+	Instr i[1];
   2.596+
   2.597+	i->curr = buf;
   2.598+	i->end = buf+n-1;
   2.599+	if(decode(map, pc, i) < 0)
   2.600+		return -1;
   2.601+	format(i->op->o, i, i->op->a);
   2.602+	return 4;
   2.603+}
   2.604+
   2.605+static int
   2.606+arm64inst(Map *map, uvlong pc, char modifier, char *buf, int n)
   2.607+{
   2.608+	USED(modifier);
   2.609+	return printins(map, pc, buf, n);
   2.610+}
   2.611+
   2.612+static int
   2.613+arm64das(Map *map, uvlong pc, char *buf, int n)
   2.614+{
   2.615+	Instr i[1];
   2.616+
   2.617+	i->curr = buf;
   2.618+	i->end = buf+n;
   2.619+	if(decode(map, pc, i) < 0)
   2.620+		return -1;
   2.621+	if(i->end-i->curr > 8)
   2.622+		i->curr = _hexify(buf, i->w, 7);
   2.623+	*i->curr = 0;
   2.624+	return 4;
   2.625+}
   2.626+
   2.627+static int
   2.628+arm64instlen(Map*, uvlong)
   2.629+{
   2.630+	return 4;
   2.631+}
   2.632+
   2.633+static uvlong
   2.634+readreg(Instr *i, Rgetter rget, int rc)
   2.635+{
   2.636+	ulong m;
   2.637+	uvlong v;
   2.638+	char reg[4];
   2.639+	snprint(reg, sizeof(reg), "R%lud", unshift(i->w, smask(i->op->p, rc)));
   2.640+	v = (*rget)(i->map, reg);
   2.641+	m = smask(i->op->p, 'W');
   2.642+	if(m != 0 && unshift(i->w, m) == 0)
   2.643+		v &= 0xFFFFFFFFULL;
   2.644+	return v;
   2.645+}
   2.646+
   2.647+static int
   2.648+passcond(Instr *i, Rgetter rget)
   2.649+{
   2.650+	uvlong psr;
   2.651+	uchar n;
   2.652+	uchar z;
   2.653+	uchar c;
   2.654+	uchar v;
   2.655+
   2.656+	psr = (*rget)(i->map, "PSR");
   2.657+	n = (psr >> 31) & 1;
   2.658+	z = (psr >> 30) & 1;
   2.659+	c = (psr >> 29) & 1;
   2.660+	v = (psr >> 28) & 1;
   2.661+
   2.662+	switch(unshift(i->w, smask(i->op->p, 'C'))) {
   2.663+	default:
   2.664+	case 0:		return z;
   2.665+	case 1:		return !z;
   2.666+	case 2:		return c;
   2.667+	case 3:		return !c;
   2.668+	case 4:		return n;
   2.669+	case 5:		return !n;
   2.670+	case 6:		return v;
   2.671+	case 7:		return !v;
   2.672+	case 8:		return c && !z;
   2.673+	case 9:		return !c || z;
   2.674+	case 10:	return n == v;
   2.675+	case 11:	return n != v;
   2.676+	case 12:	return !z && (n == v);
   2.677+	case 13:	return z || (n != v);
   2.678+	case 14:	return 1;
   2.679+	case 15:	return 0;
   2.680+	}
   2.681+}
   2.682+
   2.683+static uvlong
   2.684+jumptarg(Instr *i)
   2.685+{
   2.686+	ulong m = smask(i->op->p, 'T');
   2.687+	return i->addr + sext(unshift(i->w, m), m)*4;
   2.688+}
   2.689+
   2.690+static int
   2.691+arm64foll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
   2.692+{
   2.693+	Instr i[1];
   2.694+	char *o;
   2.695+
   2.696+	if(decode(map, pc, i) < 0)
   2.697+		return -1;
   2.698+
   2.699+	o = i->op->o;
   2.700+	if(strcmp(o, "ERET") == 0)
   2.701+		return -1;
   2.702+
   2.703+	if(strcmp(o, "RET") == 0 || strcmp(o, "BR") == 0 || strcmp(o, "BLR") == 0){
   2.704+		foll[0] = readreg(i, rget, 'n');
   2.705+		return 1;
   2.706+	}
   2.707+	if(strcmp(o, "B") == 0 || strcmp(o, "BL") == 0){
   2.708+		foll[0] = jumptarg(i);
   2.709+		return 1;
   2.710+	}
   2.711+	if(strcmp(o, "B%C") == 0){
   2.712+		if(passcond(i, rget)){
   2.713+			foll[0] = jumptarg(i);
   2.714+			return 1;
   2.715+		}
   2.716+	}
   2.717+	if(strcmp(o, "CBZ%W") == 0){
   2.718+		if(readreg(i, rget, 'd') == 0){
   2.719+			foll[0] = jumptarg(i);
   2.720+			return 1;
   2.721+		}
   2.722+	}
   2.723+	if(strcmp(o, "CBNZ%W") == 0){
   2.724+		if(readreg(i, rget, 'd') != 0){
   2.725+			foll[0] = jumptarg(i);
   2.726+			return 1;
   2.727+		}
   2.728+	}
   2.729+
   2.730+	foll[0] = i->addr+4;
   2.731+	return 1;
   2.732+}
     3.1new file mode 100644
     3.2--- /dev/null
     3.3+++ b/sys/src/libmach/7obj.c
     3.4@@ -0,0 +1,150 @@
     3.5+/*
     3.6+ * 7obj.c - identify and parse an arm64 object file
     3.7+ */
     3.8+#include <u.h>
     3.9+#include <libc.h>
    3.10+#include <bio.h>
    3.11+#include <mach.h>
    3.12+#include "7c/7.out.h"
    3.13+#include "obj.h"
    3.14+
    3.15+typedef struct Addr	Addr;
    3.16+struct Addr
    3.17+{
    3.18+	char	type;
    3.19+	char	sym;
    3.20+	char	name;
    3.21+};
    3.22+static Addr addr(Biobuf*);
    3.23+static char type2char(int);
    3.24+static void skip(Biobuf*, int);
    3.25+
    3.26+int
    3.27+_is7(char *s)
    3.28+{
    3.29+	return  s[0] == (ANAME&0xff)			/* aslo = ANAME */
    3.30+		&& s[1] == ((ANAME>>8)&0xff)
    3.31+		&& s[2] == D_FILE			/* type */
    3.32+		&& s[3] == 1				/* sym */
    3.33+		&& s[4] == '<';				/* name of file */
    3.34+}
    3.35+
    3.36+int
    3.37+_read7(Biobuf *bp, Prog *p)
    3.38+{
    3.39+	int as, n;
    3.40+	Addr a;
    3.41+
    3.42+	as = (uchar)Bgetc(bp);				/* as */
    3.43+	as |= (uchar)Bgetc(bp)<<8;
    3.44+	if(as <= AXXX || as >= ALAST)
    3.45+		return 0;
    3.46+	p->kind = aNone;
    3.47+	p->sig = 0;
    3.48+	if(as == ANAME || as == ASIGNAME){
    3.49+		if(as == ASIGNAME){
    3.50+			Bread(bp, &p->sig, 4);
    3.51+			p->sig = leswal(p->sig);
    3.52+		}
    3.53+		p->kind = aName;
    3.54+		p->type = type2char(Bgetc(bp));		/* type */
    3.55+		p->sym = Bgetc(bp);			/* sym */
    3.56+		n = 0;
    3.57+		for(;;) {
    3.58+			as = Bgetc(bp);
    3.59+			if(as < 0)
    3.60+				return 0;
    3.61+			n++;
    3.62+			if(as == 0)
    3.63+				break;
    3.64+		}
    3.65+		p->id = malloc(n);
    3.66+		if(p->id == 0)
    3.67+			return 0;
    3.68+		Bseek(bp, -n, 1);
    3.69+		if(Bread(bp, p->id, n) != n)
    3.70+			return 0;
    3.71+		return 1;
    3.72+	}
    3.73+	if(as == ATEXT)
    3.74+		p->kind = aText;
    3.75+	else if(as == AGLOBL)
    3.76+		p->kind = aData;
    3.77+	skip(bp, 5);		/* reg(1) lineno(4) */
    3.78+	a = addr(bp);
    3.79+	addr(bp);
    3.80+	if(a.type != D_OREG || a.name != D_STATIC && a.name != D_EXTERN)
    3.81+		p->kind = aNone;
    3.82+	p->sym = a.sym;
    3.83+	return 1;
    3.84+}
    3.85+
    3.86+static Addr
    3.87+addr(Biobuf *bp)
    3.88+{
    3.89+	Addr a;
    3.90+	long off;
    3.91+
    3.92+	a.type = Bgetc(bp);	/* a.type */
    3.93+	skip(bp,1);		/* reg */
    3.94+	a.sym = Bgetc(bp);	/* sym index */
    3.95+	a.name = Bgetc(bp);	/* sym type */
    3.96+	switch(a.type){
    3.97+	default:
    3.98+	case D_NONE:
    3.99+	case D_REG:
   3.100+	case D_SP:
   3.101+	case D_FREG:
   3.102+	case D_VREG:
   3.103+	case D_COND:
   3.104+		break;
   3.105+
   3.106+	case D_OREG:
   3.107+	case D_XPRE:
   3.108+	case D_XPOST:
   3.109+	case D_CONST:
   3.110+	case D_BRANCH:
   3.111+	case D_SHIFT:
   3.112+	case D_EXTREG:
   3.113+	case D_ROFF:
   3.114+	case D_SPR:
   3.115+		off = Bgetc(bp);
   3.116+		off |= Bgetc(bp) << 8;
   3.117+		off |= Bgetc(bp) << 16;
   3.118+		off |= Bgetc(bp) << 24;
   3.119+		if(off < 0)
   3.120+			off = -off;
   3.121+		if(a.sym && (a.name==D_PARAM || a.name==D_AUTO))
   3.122+			_offset(a.sym, off);
   3.123+		break;
   3.124+	case D_DCONST:
   3.125+		skip(bp, 8);
   3.126+		break;
   3.127+	case D_SCONST:
   3.128+		skip(bp, NSNAME);
   3.129+		break;
   3.130+	case D_FCONST:
   3.131+		skip(bp, 8);
   3.132+		break;
   3.133+	}
   3.134+	return a;
   3.135+}
   3.136+
   3.137+static char
   3.138+type2char(int t)
   3.139+{
   3.140+	switch(t){
   3.141+	case D_EXTERN:		return 'U';
   3.142+	case D_STATIC:		return 'b';
   3.143+	case D_AUTO:		return 'a';
   3.144+	case D_PARAM:		return 'p';
   3.145+	default:		return UNKNOWN;
   3.146+	}
   3.147+}
   3.148+
   3.149+static void
   3.150+skip(Biobuf *bp, int n)
   3.151+{
   3.152+	while (n-- > 0)
   3.153+		Bgetc(bp);
   3.154+}
     4.1--- a/sys/src/libmach/executable.c
     4.2+++ b/sys/src/libmach/executable.c
     4.3@@ -66,6 +66,7 @@ extern	Mach	m68020;
     4.4 extern	Mach	mi386;
     4.5 extern	Mach	mamd64;
     4.6 extern	Mach	marm;
     4.7+extern	Mach	marm64;
     4.8 extern	Mach	mpower;
     4.9 extern	Mach	mpower64;
    4.10 
    4.11@@ -233,6 +234,15 @@ ExecTable exectab[] =
    4.12 		sizeof(Exec),
    4.13 		leswal,
    4.14 		armdotout },
    4.15+	{ R_MAGIC,			/* Arm64 7.out and boot image */
    4.16+		"arm64 plan 9 executable",
    4.17+		"arm64 plan 9 dlm",
    4.18+		FARM64,
    4.19+		1,
    4.20+		&marm64,
    4.21+		sizeof(Exec)+8,
    4.22+		nil,
    4.23+		commonllp64 },
    4.24 	{ 0 },
    4.25 };
    4.26 
    4.27@@ -375,6 +385,12 @@ commonboot(Fhdr *fp)
    4.28 		fp->name = "ARM plan 9 boot image";
    4.29 		fp->dataddr = _round(fp->txtaddr+fp->txtsz, mach->pgsize);
    4.30 		return;
    4.31+	case FARM64:
    4.32+		fp->type = FARM64B;
    4.33+		fp->txtaddr = fp->entry;
    4.34+		fp->name = "arm64 plan 9 boot image";
    4.35+		fp->dataddr = _round(fp->txtaddr+fp->txtsz, mach->pgsize);
    4.36+		return;
    4.37 	case FPOWER:
    4.38 		fp->type = FPOWERB;
    4.39 		fp->txtaddr = (u32int)fp->entry;
     5.1--- a/sys/src/libmach/mkfile
     5.2+++ b/sys/src/libmach/mkfile
     5.3@@ -18,6 +18,7 @@ FILES=\
     5.4 	2\
     5.5 	5\
     5.6 	6\
     5.7+	7\
     5.8 	8\
     5.9 	9\
    5.10 	vdb\
    5.11@@ -26,6 +27,7 @@ FILES=\
    5.12 	qdb\
    5.13 	2db\
    5.14 	5db\
    5.15+	7db\
    5.16 	8db\
    5.17 	vobj\
    5.18 	kobj\
    5.19@@ -33,6 +35,7 @@ FILES=\
    5.20 	2obj\
    5.21 	5obj\
    5.22 	6obj\
    5.23+	7obj\
    5.24 	8obj\
    5.25 	9obj\
    5.26 	qobj\
    5.27@@ -56,6 +59,7 @@ CFLAGS=$CFLAGS -I/sys/src/cmd
    5.28 2obj.$O: /sys/src/cmd/2c/2.out.h
    5.29 5obj.$O: /sys/src/cmd/5c/5.out.h
    5.30 6obj.$O: /sys/src/cmd/6c/6.out.h
    5.31+7obj.$O: /sys/src/cmd/7c/7.out.h
    5.32 8obj.$O: /sys/src/cmd/8c/8.out.h
    5.33 kobj.$O: /sys/src/cmd/kc/k.out.h
    5.34 qobj.$O: /sys/src/cmd/qc/q.out.h
     6.1--- a/sys/src/libmach/obj.c
     6.2+++ b/sys/src/libmach/obj.c
     6.3@@ -33,6 +33,7 @@ int	_is2(char*),		/* in [$OS].c */
     6.4 	_read2(Biobuf*, Prog*),
     6.5 	_read5(Biobuf*, Prog*),
     6.6 	_read6(Biobuf*, Prog*),
     6.7+	_read7(Biobuf*, Prog*),
     6.8 	_read8(Biobuf*, Prog*),
     6.9 	_read9(Biobuf*, Prog*),
    6.10 	_readk(Biobuf*, Prog*),
    6.11@@ -55,6 +56,7 @@ static Obj	obj[] =
    6.12 	[Obj68020]	"68020 .2",	_is2, _read2,
    6.13 	[ObjAmd64]	"amd64 .6",	_is6, _read6,
    6.14 	[ObjArm]	"arm .5",	_is5, _read5,
    6.15+	[ObjArm64]	"arm64 .7",	_is7, _read7,
    6.16 	[Obj386]	"386 .8",	_is8, _read8,
    6.17 	[ObjSparc]	"sparc .k",	_isk, _readk,
    6.18 	[ObjPower]	"power .q",	_isq, _readq,
     7.1--- a/sys/src/libmach/setmach.c
     7.2+++ b/sys/src/libmach/setmach.c
     7.3@@ -17,9 +17,9 @@ struct machtab
     7.4 };
     7.5 
     7.6 extern	Mach		mmips, msparc, m68020, mi386, mamd64,
     7.7-			marm, mmips2be, mmips2le, mpower, mpower64, msparc64;
     7.8+			marm, marm64, mmips2be, mmips2le, mpower, mpower64, msparc64;
     7.9 extern	Machdata	mipsmach, mipsmachle, sparcmach, m68020mach, i386mach,
    7.10-			armmach, mipsmach2le, powermach, sparc64mach;
    7.11+			armmach, arm64mach, mipsmach2le, powermach, sparc64mach;
    7.12 
    7.13 /*
    7.14  *	machine selection table.  machines with native disassemblers should
    7.15@@ -106,6 +106,12 @@ Machtab	machines[] =
    7.16 		AARM,
    7.17 		&marm,
    7.18 		&armmach,	},
    7.19+	{	"arm64",			/*ARM64*/
    7.20+		FARM64,
    7.21+		FARM64B,
    7.22+		AARM64,
    7.23+		&marm64,
    7.24+		&arm64mach,	},
    7.25 	{	"power",			/*PowerPC*/
    7.26 		FPOWER,
    7.27 		FPOWERB,