6 typedef struct Opcode Opcode;
14 typedef struct Instr Instr;
22 char *curr; /* fill point in buffer */
23 char *end; /* end of buffer */
26 static void format(char*, Instr*, char*);
27 static char FRAMENAME[] = ".frame";
30 * Arm64-specific debugger interface
32 static char* arm64excep(Map*, Rgetter);
33 static int arm64foll(Map*, uvlong, Rgetter, uvlong*);
34 static int arm64inst(Map*, uvlong, char, char*, int);
35 static int arm64das(Map*, uvlong, char*, int);
36 static int arm64instlen(Map*, uvlong);
43 {0x00, 0x00, 0x20, 0xD4}, /* break point 0xD4200000 */
44 4, /* break point size */
45 leswab, /* short to local byte order */
46 leswal, /* long to local byte order */
47 leswav, /* long to local byte order */
48 risctrace, /* C traceback */
49 riscframe, /* Frame finder */
50 arm64excep, /* print exception */
51 0, /* breakpoint fixup */
52 0, /* single precision float printer */
53 0, /* double precision float printer */
54 arm64foll, /* following addresses */
55 arm64inst, /* print instruction */
56 arm64das, /* dissembler */
57 arm64instlen, /* instruction size */
60 static Opcode opcodes[] =
62 "0AA10000AAAAAAAAAAAAAAAAAAAddddd", "ADR", "$%A,R%d",
63 "1PP10000PPPPPPPPPPPPPPPPPPPddddd", "ADRP", "$%P,R%d",
64 "00011000lllllllllllllllllllddddd", "MOVWU", "%l,R%d",
65 "01011000LLLLLLLLLLLLLLLLLLLddddd", "MOV", "%L,R%d",
66 "10011000lllllllllllllllllllddddd", "MOVW", "%l,R%d",
67 "11011000lllllllllllllllllllddddd", "PRFM", "%l,$%d",
68 "1111100100uuuuuuuuuuuu11111ddddd", "MOV", "R%d,%u(SP)",
69 "1111100100uuuuuuuuuuuunnnnnddddd", "MOV", "R%d,%u(R%n)",
70 "WW11100100uuuuuuuuuuuu11111ddddd", "MOV%WU", "R%d,%u(SP)",
71 "WW11100100uuuuuuuuuuuunnnnnddddd", "MOV%WU", "R%d,%u(R%n)",
72 "1111100101uuuuuuuuuuuu11111ddddd", "MOV", "%u(SP),R%d",
73 "1111100101uuuuuuuuuuuunnnnnddddd", "MOV", "%u(R%n),R%d",
74 "WW11100101uuuuuuuuuuuu11111ddddd", "MOV%WU", "%u(SP),R%d",
75 "WW11100101uuuuuuuuuuuunnnnnddddd", "MOV%WU", "%u(R%n),R%d",
76 "WW11100110uuuuuuuuuuuu11111ddddd", "MOV%W", "%u(SP),R%d",
77 "WW11100110uuuuuuuuuuuunnnnnddddd", "MOV%W", "%u(R%n),R%d",
78 "11111000000ooooooooo0011111ddddd", "MOV", "R%d,%o(SP)",
79 "11111000000ooooooooo00nnnnnddddd", "MOV", "R%d,%o(R%n)",
80 "WW111000000ooooooooo0011111ddddd", "MOV%W", "R%d,%o(SP)",
81 "WW111000000ooooooooo00nnnnnddddd", "MOV%W", "R%d,%o(R%n)",
82 "11111000010ooooooooo0011111ddddd", "MOV", "%o(SP),R%d",
83 "11111000010ooooooooo00nnnnnddddd", "MOV", "%o(R%n),R%d",
84 "WW111000010ooooooooo0011111ddddd", "MOV%WU", "%o(SP),R%d",
85 "WW111000010ooooooooo00nnnnnddddd", "MOV%WU", "%o(R%n),R%d",
86 "WW111000100ooooooooo0011111ddddd", "MOV%W", "%o(SP),R%d",
87 "WW111000100ooooooooo00nnnnnddddd", "MOV%W", "%o(R%n),R%d",
88 "11111000000ooooooooo0111111ddddd", "MOV", "R%d,(SP)%o!",
89 "WW111000000ooooooooo0111111ddddd", "MOV%WU", "R%d,(SP)%o!",
90 "WW111000000ooooooooo01nnnnnddddd", "MOV%WU", "R%d,(R%n)%o!",
91 "11111000000ooooooooo1111111ddddd", "MOV", "R%d,%o(SP)!",
92 "WW111000000ooooooooo1111111ddddd", "MOV%WU", "R%d,%o(SP)!",
93 "WW111000000ooooooooo11nnnnnddddd", "MOV%WU", "R%d,%o(R%n)!",
94 "11111000010ooooooooo0111111ddddd", "MOV", "(SP)%o!,R%d",
95 "11111000010ooooooooo01nnnnnddddd", "MOV", "(R%n)%o!,R%d",
96 "WW111000010ooooooooo0111111ddddd", "MOV%WU", "(SP)%o!,R%d",
97 "WW111000010ooooooooo01nnnnnddddd", "MOV%WU", "(R%n)%o!,R%d",
98 "WW111000100ooooooooo0111111ddddd", "MOV%W", "(SP)%o!,R%d",
99 "WW111000100ooooooooo01nnnnnddddd", "MOV%W", "(R%n)%o!,R%d",
100 "11111000010ooooooooo1111111ddddd", "MOV", "%o(SP)!,R%d",
101 "11111000010ooooooooo11nnnnnddddd", "MOV", "%o(R%n)!,R%d",
102 "WW111000010ooooooooo1111111ddddd", "MOV%WU", "%o(SP)!,R%d",
103 "WW111000010ooooooooo11nnnnnddddd", "MOV%WU", "%o(R%n)!,R%d",
104 "WW111000100ooooooooo1111111ddddd", "MOV%W", "%o(SP)!,R%d",
105 "WW111000100ooooooooo11nnnnnddddd", "MOV%W", "%o(R%n)!,R%d",
106 "11111000001mmmmmeeei10nnnnnddddd", "MOV", "R%d,(R%n)(R%m%e)",
107 "11111000111mmmmmeeei10nnnnnddddd", "MOV", "(R%n)(R%m%e),R%d",
108 "WW111000001mmmmmeeei10nnnnnddddd", "MOV%W", "R%d,(R%n)(R%m%e)",
109 "WW111000011mmmmmeeei10nnnnnddddd", "MOV%WU", "(R%n)(R%m%e),R%d",
110 "WW111000101mmmmmeeei10nnnnnddddd", "MOV%W", "(R%n)(R%m%e),R%d",
111 "WW111000111mmmmmeeei10nnnnnddddd", "MOV%WW", "(R%n)(R%m%e),R%d",
112 "W00100101ssKKKKKKKKKKKKKKKKddddd", "MOVN%W", "$%K,R%d",
113 "W10100101ssKKKKKKKKKKKKKKKKddddd", "MOVZ%W", "$%K,R%d",
114 "W11100101ssKKKKKKKKKKKKKKKKddddd", "MOVK%W", "$%K,R%d",
115 "W0010001--00000000000011111ddddd", "MOV%W", "SP,R%d",
116 "W0010001--000000000000nnnnn11111", "MOV%W", "R%n,SP",
117 "0110100011ooooooommmmm11111ddddd", "MOVPSW", "(SP)%o!,R%d,R%m",
118 "0110100011ooooooommmmmnnnnnddddd", "MOVPSW", "(R%n)%o!,R%d,R%m",
119 "0110100101ooooooommmmm11111ddddd", "MOVPSW", "%o(SP),R%d,R%m",
120 "0110100101ooooooommmmmnnnnnddddd", "MOVPSW", "%o(R%n),R%d,R%m",
121 "0110100111ooooooommmmm11111ddddd", "MOVPSW", "%o(SP)!,R%d,R%m",
122 "0110100111ooooooommmmmnnnnnddddd", "MOVPSW", "%o(R%n)!,R%d,R%m",
123 "W010100010ooooooommmmm11111ddddd", "MOVP%W", "R%d,R%m,(SP)%o!",
124 "W010100010ooooooommmmmnnnnnddddd", "MOVP%W", "R%d,R%m,(R%n)%o!",
125 "W010100100ooooooommmmm11111ddddd", "MOVP%W", "R%d,R%m,%o(SP)",
126 "W010100100ooooooommmmmnnnnnddddd", "MOVP%W", "R%d,R%m,%o(R%n)",
127 "W010100110ooooooommmmm11111ddddd", "MOVP%W", "R%d,R%m,%o(SP)!",
128 "W010100110ooooooommmmmnnnnnddddd", "MOVP%W", "R%d,R%m,%o(R%n)!",
129 "W010100011ooooooommmmm11111ddddd", "MOVP%W", "(SP)%o!,R%d,R%m",
130 "W010100011ooooooommmmmnnnnnddddd", "MOVP%W", "(R%n)%o!,R%d,R%m",
131 "W010100101ooooooommmmm11111ddddd", "MOVP%W", "%o(SP),R%d,R%m",
132 "W010100101ooooooommmmmnnnnnddddd", "MOVP%W", "%o(R%n),R%d,R%m",
133 "W010100111ooooooommmmm11111ddddd", "MOVP%W", "%o(SP)!,R%d,R%m",
134 "W010100111ooooooommmmmnnnnnddddd", "MOVP%W", "%o(R%n)!,R%d,R%m",
135 "W0010001ssIIIIIIIIIIII1111111111", "ADD%W", "$%I,SP,SP",
136 "W0010001ssIIIIIIIIIIII11111ddddd", "ADD%W", "$%I,SP,R%d",
137 "W0010001ssIIIIIIIIIIIInnnnn11111", "ADD%W", "$%I,R%n,SP",
138 "W0110001ssIIIIIIIIIIII1111111111", "ADDS%W", "$%I,SP,SP",
139 "W0110001ssIIIIIIIIIIII11111ddddd", "ADDS%W", "$%I,SP,R%d",
140 "W0110001ssIIIIIIIIIIIInnnnn11111", "ADDS%W", "$%I,R%n,SP",
141 "W1010001ssIIIIIIIIIIII1111111111", "SUB%W", "$%I,SP,SP",
142 "W1010001ssIIIIIIIIIIII11111ddddd", "SUB%W", "$%I,SP,R%d",
143 "W1010001ssIIIIIIIIIIIInnnnn11111", "SUB%W", "$%I,R%n,SP",
144 "W1110001ssIIIIIIIIIIII1111111111", "CMP%W", "$%I,SP",
145 "W1110001ssIIIIIIIIIIIInnnnn11111", "CMP%W", "$%I,R%n",
146 "W1110001ssIIIIIIIIIIII11111ddddd", "SUBS%W", "$%I,SP,R%d",
147 "W0010001ssIIIIIIIIIIIInnnnnddddd", "ADD%W", "$%I,R%n,R%d",
148 "W0110001ssIIIIIIIIIIIInnnnnddddd", "ADDS%W", "$%I,R%n,R%d",
149 "W1010001ssIIIIIIIIIIIInnnnnddddd", "SUB%W", "$%I,R%n,R%d",
150 "W1110001ssIIIIIIIIIIIInnnnnddddd", "SUBS%W", "$%I,R%n,R%d",
151 "W00100100MMMMMMMMMMMMMnnnnn11111", "AND%W", "$%M,R%n,SP",
152 "W01100100MMMMMMMMMMMMMnnnnn11111", "ORR%W", "$%M,R%n,SP",
153 "W10100100MMMMMMMMMMMMMnnnnn11111", "EOR%W", "$%M,R%n,SP",
154 "W11100100MMMMMMMMMMMMMnnnnn11111", "ANDS%W", "$%M,R%n,SP",
155 "W00100100MMMMMMMMMMMMMnnnnnddddd", "AND%W", "$%M,R%n,R%d",
156 "W01100100MMMMMMMMMMMMMnnnnnddddd", "ORR%W", "$%M,R%n,R%d",
157 "W10100100MMMMMMMMMMMMMnnnnnddddd", "EOR%W", "$%M,R%n,R%d",
158 "W11100100MMMMMMMMMMMMMnnnnnddddd", "ANDS%W", "$%M,R%n,R%d",
159 "1001001101000000011111nnnnnddddd", "SXTW", "R%n,R%d",
160 "0101001100iiiiii011111nnnnnddddd", "LSRW", "$%i,R%n,R%d",
161 "1101001101iiiiii111111nnnnnddddd", "LSR", "$%i,R%n,R%d",
162 "W00100110-iiiiiijjjjjjnnnnnddddd", "SBFM%W", "$%i,$%j,R%n,R%d",
163 "W01100110-iiiiiijjjjjjnnnnnddddd", "BFM%W", "$%i,$%j,R%n,R%d",
164 "W10100110-iiiiiijjjjjjnnnnnddddd", "UBFM%W", "$%i,$%j,R%n,R%d",
165 "W1011010000mmmmm00000011111ddddd", "NGC%W", "R%m,R%d",
166 "W1111010000mmmmm00000011111ddddd", "NGCS%W", "R%m,R%d",
167 "W0011010000mmmmm000000nnnnnddddd", "ADC%W", "R%m,R%n,R%d",
168 "W0111010000mmmmm000000nnnnnddddd", "ADCS%W", "R%m,R%n,R%d",
169 "W1011010000mmmmm000000nnnnnddddd", "SBC%W", "R%m,R%n,R%d",
170 "W1111010000mmmmm000000nnnnnddddd", "SBCS%W", "R%m,R%n,R%d",
171 "W0101011ss0mmmmmiiiiiinnnnn11111", "CMN%W", "R%m%s,R%n",
172 "W1101011ss0mmmmmiiiiiinnnnn11111", "CMP%W", "R%m%s,R%n",
173 "W1001011ss0mmmmmiiiiii11111ddddd", "NEG%W", "R%m%s,R%d",
174 "W1101011ss0mmmmmiiiiii11111ddddd", "NEGS%W", "R%m%s,R%d",
175 "W0001011ss0mmmmmiiiiiinnnnnddddd", "ADD%W", "R%m%s,R%n,R%d",
176 "W0101011ss0mmmmmiiiiiinnnnnddddd", "ADDS%W", "R%m%s,R%n,R%d",
177 "W1001011ss0mmmmmiiiiiinnnnnddddd", "SUB%W", "R%m%s,R%n,R%d",
178 "W1101011ss0mmmmmiiiiiinnnnnddddd", "SUBS%W", "R%m%s,R%n,R%d",
179 "W0001011001mmmmmeeeiii1111111111", "ADD%W", "R%m%e,SP,SP",
180 "W0001011001mmmmmeeeiii11111ddddd", "ADD%W", "R%m%e,SP,R%d",
181 "W0001011001mmmmmeeeiiinnnnn11111", "ADD%W", "R%m%e,R%n,SP",
182 "W0101011001mmmmmeeeiii1111111111", "ADDS%W", "R%m%e,SP,SP",
183 "W0101011001mmmmmeeeiii11111ddddd", "ADDS%W", "R%m%e,SP,R%d",
184 "W0101011001mmmmmeeeiiinnnnn11111", "ADDS%W", "R%m%e,R%n,SP",
185 "W1001011001mmmmmeeeiii1111111111", "SUB%W", "R%m%e,SP,SP",
186 "W1001011001mmmmmeeeiii11111ddddd", "SUB%W", "R%m%e,SP,R%d",
187 "W1001011001mmmmmeeeiiinnnnn11111", "SUB%W", "R%m%e,R%n,SP",
188 "W1101011001mmmmmeeeiii1111111111", "SUBS%W", "R%m%e,SP,SP",
189 "W1101011001mmmmmeeeiii11111ddddd", "SUBS%W", "R%m%e,SP,R%d",
190 "W1101011001mmmmmeeeiiinnnnn11111", "SUBS%W", "R%m%e,R%n,SP",
191 "W0001011001mmmmmeeeiiinnnnnddddd", "ADD%W", "R%m%e,R%n,R%d",
192 "W0101011001mmmmmeeeiiinnnnnddddd", "ADDS%W", "R%m%e,R%n,R%d",
193 "W1001011001mmmmmeeeiiinnnnnddddd", "SUB%W", "R%m%e,R%n,R%d",
194 "W1101011001mmmmmeeeiiinnnnnddddd", "SUBS%W", "R%m%e,R%n,R%d",
195 "W0101010000mmmmm-0000011111ddddd", "MOV%W", "R%m,R%d",
196 "W0101010ss1mmmmmiiiiii11111ddddd", "NVM%W", "R%m%s,R%d",
197 "W1101010ss0mmmmmiiiiiinnnnn11111", "TST%W", "R%m%s,R%n",
198 "W0001010ss0mmmmmiiiiiinnnnnddddd", "AND%W", "R%m%s,R%n,R%d",
199 "W1101010ss0mmmmmiiiiiinnnnnddddd", "ANDS%W", "R%m%s,R%n,R%d",
200 "W0001010ss1mmmmmiiiiiinnnnnddddd", "BIC%W", "R%m%s,R%n,R%d",
201 "W1101010ss1mmmmmiiiiiinnnnnddddd", "BICS%W", "R%m%s,R%n,R%d",
202 "W1001010ss0mmmmmiiiiiinnnnnddddd", "EOR%W", "R%m%s,R%n,R%d",
203 "W1001010ss1mmmmmiiiiiinnnnnddddd", "EON%W", "R%m%s,R%n,R%d",
204 "W0101010ss0mmmmmiiiiiinnnnnddddd", "ORR%W", "R%m%s,R%n,R%d",
205 "W0101010ss1mmmmmiiiiiinnnnnddddd", "ORN%W", "R%m%s,R%n,R%d",
206 "W0011010110mmmmm001000nnnnnddddd", "LSL%W", "R%m,R%n,R%d",
207 "W0011010110mmmmm001001nnnnnddddd", "LSR%W", "R%m,R%n,R%d",
208 "W0011010110mmmmm001010nnnnnddddd", "ASR%W", "R%m,R%n,R%d",
209 "W0011010110mmmmm001011nnnnnddddd", "ROR%W", "R%m,R%n,R%d",
210 "W0011010110mmmmm000010nnnnnddddd", "UDIV%W", "R%m,R%n,R%d",
211 "W0011010110mmmmm000011nnnnnddddd", "SDIV%W", "R%m,R%n,R%d",
212 "W0011011000mmmmm011111nnnnnddddd", "MUL%W", "R%m,R%n,R%d",
213 "W0011011000mmmmm111111nnnnnddddd", "MNEG%W", "R%m,R%n,R%d",
214 "W0011011000mmmmm0aaaaannnnnddddd", "MADD%W", "R%m,R%n,R%a,R%d",
215 "W0011011000mmmmm1aaaaannnnnddddd", "MSUB%W", "R%m,R%n,R%a,R%d",
216 "10011011001mmmmm011111nnnnnddddd", "SMULL", "R%m,R%n,R%d",
217 "10011011001mmmmm111111nnnnnddddd", "SMNEGL", "R%m,R%n,R%d",
218 "10011011001mmmmm0aaaaannnnnddddd", "SMADDL", "R%m,R%n,R%a,R%d",
219 "10011011001mmmmm1aaaaannnnnddddd", "SMSUBL", "R%m,R%n,R%a,R%d",
220 "10011011101mmmmm011111nnnnnddddd", "UMULL", "R%m,R%n,R%d",
221 "10011011101mmmmm111111nnnnnddddd", "UMNEGL", "R%m,R%n,R%d",
222 "10011011101mmmmm0aaaaannnnnddddd", "UMADDL", "R%m,R%n,R%a,R%d",
223 "10011011101mmmmm1aaaaannnnnddddd", "UMSUBL", "R%m,R%n,R%a,R%d",
224 "W0110100TTTTTTTTTTTTTTTTTTTddddd", "CBZ%W", "R%d,%T",
225 "W0110101TTTTTTTTTTTTTTTTTTTddddd", "CBNZ%W", "R%d,%T",
226 "01010100TTTTTTTTTTTTTTTTTTT0CCCC", "B%C", "%T",
227 "000101TTTTTTTTTTTTTTTTTTTTTTTTTT", "B", "%T",
228 "100101TTTTTTTTTTTTTTTTTTTTTTTTTT", "BL", "%T",
229 "1101011000011111000000nnnnn00000", "BR", "R%n",
230 "1101011000111111000000nnnnn00000", "BLR", "R%n",
231 "11010110010111110000001111000000", "RETURN", nil,
232 "1101011001011111000000nnnnn00000", "RET", "R%n",
233 "11010110100111110000001111100000", "ERET", nil,
234 "11010110101111110000001111100000", "DRPS", nil,
235 "11010100000iiiiiiiiiiiiiiii00001", "SVC", "$%i",
236 "11010100000iiiiiiiiiiiiiiii00010", "HVC", "$%i",
237 "11010100000iiiiiiiiiiiiiiii00011", "SMC", "$%i",
238 "11010100001iiiiiiiiiiiiiiii00000", "BRK", "$%i",
239 "11010100010iiiiiiiiiiiiiiii00000", "HLT", "$%i",
240 "11010100101iiiiiiiiiiiiiiii00001", "DCPS1", "$%i",
241 "11010100101iiiiiiiiiiiiiiii00010", "DCPS2", "$%i",
242 "11010100101iiiiiiiiiiiiiiii00011", "DCPS3", "$%i",
243 "11010101000000110010000000011111", "NOP", nil,
244 "11010101000000110010000000111111", "YIELD", nil,
245 "11010101000000110010000001011111", "WFE", nil,
246 "11010101000000110010000001111111", "WFI", nil,
247 "11010101000000110010000010011111", "SEV", nil,
248 "11010101000000110010000010111111", "SEVL", nil,
249 "11010101000000110011xxxx01011111", "CLREX", "$%x",
250 "11010101000000110011xxxx10011111", "DSB", "$%x",
251 "11010101000000110011xxxx10111111", "DMB", "$%x",
252 "11010101000000110011xxxx11011111", "ISB", "$%x",
253 "1101010100001YYYYYYYYYYYYYY11111", "SYS", "%Y",
254 "1101010100001YYYYYYYYYYYYYYddddd", "SYS", "R%d,%Y",
255 "1101010100101YYYYYYYYYYYYYYddddd", "SYSL", "%Y,R%d",
256 "11010101000000000100xxxx10111111", "MSR", "$%x,SP",
257 "11010101000000110100xxxx11011111", "MSR", "$%x,DAIFSet",
258 "11010101000000110100xxxx11111111", "MSR", "$%x,DAIFClr",
259 "11010101000YYYYYYYYYYYYYYYYddddd", "MSR", "R%d,%Y",
260 "11010101001YYYYYYYYYYYYYYYYddddd", "MRS", "%Y,R%d",
261 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "WORD", "$%x",
264 #define SYSARG5(op0,op1,Cn,Cm,op2) ((op0)<<19|(op1)<<16|(Cn)<<12|(Cm)<<8|(op2)<<5)
267 smask(char *s, char c)
273 for(i=0; i<32 && *s != '\0'; i++, s++)
274 m |= (*s == c)<<(31-i);
303 if(m == 0 || m == ~0UL)
309 unshift(ulong w, ulong m)
313 if((m+1 & m) != 0){ // 0bxxx0000yyyyyy -> 0byyyyyyxxx
314 ulong b = (1UL<<nones(m))-1;
315 return ((w & b) << nbits(m & ~b)) | unshift(w, m & ~b);
325 l <<= sizeof(l)*8 - n;
326 l >>= sizeof(l)*8 - n;
332 arm64excep(Map *, Rgetter)
334 // uvlong c = (*rget)(map, "TYPE");
339 decode(Map *map, uvlong pc, Instr *i)
341 static ulong tab[2*nelem(opcodes)];
348 /* precalculate value/mask table */
349 for(j=0, o=opcodes; j<nelem(tab); j+=2, o++){
350 tab[j] = smask(o->p, '1');
351 tab[j|1] = tab[j] | smask(o->p, '0');
357 if(get4(map, pc, &w) < 0) {
358 werrstr("can't read instruction: %r");
365 for(j=0; j<nelem(tab); j+=2){
366 if((w & tab[j|1]) == tab[j]){
367 i->op = &opcodes[j/2];
372 /* should not happen */
376 #pragma varargck argpos bprint 2
379 bprint(Instr *i, char *fmt, ...)
384 i->curr = vseprint(i->curr, i->end, fmt, arg);
391 "<<", ">>", "->", "@>"
397 "UB", "UH", "UW", "UX",
398 "SB", "SH", "SW", "SX"
404 "EQ", "NE", "HS", "LO",
405 "MI", "PL", "VS", "VC",
406 "HI", "LS", "GE", "LT",
407 "GT", "LE", "", "NV",
411 decodebitmask(int n, int s, int r)
419 for(n = 5; n >= 1 && ((~s & 0x3F) & (1<<n)) == 0; n--)
430 w = (w >> r) | (w << (e-r));
442 format(char *mnemonic, Instr *i, char *f)
449 format(0, i, mnemonic);
455 for ( ; *f && i->curr < i->end; f++) {
460 m = smask(i->op->p, *++f);
461 u = unshift(i->w, m);
463 case 'C': // Condition
464 bprint(i, "%s", scond[u & 15]);
468 if(nbits(m) == 1) u += 2;
471 *i->curr++ = "BHW"[u];
474 case 'd': // Register Numbers
478 bprint(i, "%lud", u);
481 case 's': // Register shift
482 w = unshift(i->w, smask(i->op->p, 'i'));
484 bprint(i, "%s%lud", shtype[u & 3], w);
487 case 'e': // Register extension
489 bprint(i, ".%s", rextype[u]);
490 w = unshift(i->w, smask(i->op->p, 'i'));
491 if(w != 0 && u == 2+(i->w>>31))
492 bprint(i, "<<%lud", w);
496 v = decodebitmask((u>>12)&1, u&0x3F, (u>>6)&0x3F);
497 if((i->w & (1<<31)) == 0)
499 bprint(i, "%llux", v);
502 case 'I': // Shifted Immediate (12 bit)
503 case 'K': // Shifted Immediate (16 bit)
504 w = unshift(i->w, smask(i->op->p, 's'));
506 bprint(i, "(%lux<<%ld)", u, w*(*f == 'I' ? 12 : 16));
508 bprint(i, "%lud", u);
511 case 'o': // Signed byte offset
513 bprint(i, "%ld", sext(u, w) << (w == 7 ? 2 + (i->w>>31) : 0));
515 case 'u': // Unsigned offset
516 u <<= (i->w >> 30)&3;
520 bprint(i, "%lud", u);
524 bprint(i, "%lux", u);
527 case 'l': // 32-bit Literal
528 if(get4(i->map, i->addr + sext(u, nbits(m))*4, &w) < 0)
530 bprint(i, "$%lux", w);
532 case 'L': // 64-bit Literal
533 if(get8(i->map, i->addr + sext(u, nbits(m))*4, &v) < 0)
535 bprint(i, "$%llux", v);
537 case 'T': // Text address (PC relative)
539 v = i->addr + sext(u, nbits(m))*4;
540 if(findsym(v, CTEXT, &s)){
541 bprint(i, "%s", s.name);
543 bprint(i, "%llx", v - s.value);
545 bprint(i, "+%llx", v - s.value);
549 bprint(i, "%llux(SB)", v);
551 case 'A': // Data address (PC relative)
552 v = i->addr + sext(u, nbits(m));
554 case 'P': // Page address (PC relative)
555 v = i->addr + ((vlong)sext(u, nbits(m)) << 12);
557 if(findsym(v, CANY, &s)){
558 bprint(i, "%s", s.name);
560 bprint(i, "%llx", v - s.value);
562 bprint(i, "+%llx", v - s.value);
566 bprint(i, "%llux(SB)", v);
570 if(nbits(m) == 14){ // SYS/SYSL operands
571 bprint(i, "%lud,%lud,%lud,%lud",
572 (u>>(4+4+3))&7, // op1
573 (u>>(4+3))&15, // CRn
578 /* see /sys/src/cmd/7c/7.out.h */
580 case SYSARG5(3,3,4,2,1): bprint(i, "DAIF"); break;
581 case SYSARG5(3,3,4,2,0): bprint(i, "NZCV"); break;
582 case SYSARG5(3,3,4,4,1): bprint(i, "FPSR"); break;
583 case SYSARG5(3,3,4,4,0): bprint(i, "FPCR"); break;
584 case SYSARG5(3,0,4,0,0): bprint(i, "SPSR_EL1"); break;
585 case SYSARG5(3,0,4,0,1): bprint(i, "ELR_EL1"); break;
586 case SYSARG5(3,4,4,0,0): bprint(i, "SPSR_EL2"); break;
587 case SYSARG5(3,4,4,0,1): bprint(i, "ELR_EL2"); break;
588 case SYSARG5(3,0,4,2,2): bprint(i, "CurrentEL"); break;
589 case SYSARG5(3,0,4,1,0): bprint(i, "SP_EL0"); break;
590 case SYSARG5(3,0,4,2,0): bprint(i, "SPSel"); break;
591 default: bprint(i, "SPR(%lux)", i->w & m);
600 bprint(i, "%%%c", *f);
608 printins(Map *map, uvlong pc, char *buf, int n)
614 if(decode(map, pc, i) < 0)
616 format(i->op->o, i, i->op->a);
621 arm64inst(Map *map, uvlong pc, char modifier, char *buf, int n)
624 return printins(map, pc, buf, n);
628 arm64das(Map *map, uvlong pc, char *buf, int n)
634 if(decode(map, pc, i) < 0)
636 if(i->end-i->curr > 8)
637 i->curr = _hexify(buf, i->w, 7);
643 arm64instlen(Map*, uvlong)
649 readreg(Instr *i, Rgetter rget, int rc)
654 snprint(reg, sizeof(reg), "R%lud", unshift(i->w, smask(i->op->p, rc)));
655 v = (*rget)(i->map, reg);
656 m = smask(i->op->p, 'W');
657 if(m != 0 && unshift(i->w, m) == 0)
663 passcond(Instr *i, Rgetter rget)
671 psr = (*rget)(i->map, "PSR");
677 switch(unshift(i->w, smask(i->op->p, 'C'))) {
687 case 8: return c && !z;
688 case 9: return !c || z;
689 case 10: return n == v;
690 case 11: return n != v;
691 case 12: return !z && (n == v);
692 case 13: return z || (n != v);
701 ulong m = smask(i->op->p, 'T');
702 return i->addr + sext(unshift(i->w, m), m)*4;
706 arm64foll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
711 if(decode(map, pc, i) < 0)
715 if(strcmp(o, "ERET") == 0)
718 if(strcmp(o, "RET") == 0 || strcmp(o, "BR") == 0 || strcmp(o, "BLR") == 0){
719 foll[0] = readreg(i, rget, 'n');
722 if(strcmp(o, "B") == 0 || strcmp(o, "BL") == 0){
723 foll[0] = jumptarg(i);
726 if(strcmp(o, "B%C") == 0){
727 if(passcond(i, rget)){
728 foll[0] = jumptarg(i);
732 if(strcmp(o, "CBZ%W") == 0){
733 if(readreg(i, rget, 'd') == 0){
734 foll[0] = jumptarg(i);
738 if(strcmp(o, "CBNZ%W") == 0){
739 if(readreg(i, rget, 'd') != 0){
740 foll[0] = jumptarg(i);