changeset 7220: |
f49283fe4c5f |
parent: |
4dd5e2428c1d
|
child: |
d98974bc6c16 |
author: |
cinap_lenrek@felloff.net |
date: |
Thu, 09 May 2019 10:24:37 +0200 |
permissions: |
-rw-r--r-- |
description: |
libmach: support for MOVP instruction disassembly for arm64 |
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)!",
95 "11111000010ooooooooo0111111ddddd", "MOV", "(SP)%o!,R%d",
96 "11111000010ooooooooo01nnnnnddddd", "MOV", "(R%n)%o!,R%d",
97 "WW111000010ooooooooo0111111ddddd", "MOV%WU", "(SP)%o!,R%d",
98 "WW111000010ooooooooo01nnnnnddddd", "MOV%WU", "(R%n)%o!,R%d",
99 "WW111000100ooooooooo0111111ddddd", "MOV%W", "(SP)%o!,R%d",
100 "WW111000100ooooooooo01nnnnnddddd", "MOV%W", "(R%n)%o!,R%d",
101 "11111000010ooooooooo1111111ddddd", "MOV", "%o(SP)!,R%d",
102 "11111000010ooooooooo11nnnnnddddd", "MOV", "%o(R%n)!,R%d",
103 "WW111000010ooooooooo1111111ddddd", "MOV%WU", "%o(SP)!,R%d",
104 "WW111000010ooooooooo11nnnnnddddd", "MOV%WU", "%o(R%n)!,R%d",
105 "WW111000100ooooooooo1111111ddddd", "MOV%W", "%o(SP)!,R%d",
106 "WW111000100ooooooooo11nnnnnddddd", "MOV%W", "%o(R%n)!,R%d",
107 "11111000001mmmmmeeei10nnnnnddddd", "MOV", "R%d,(R%n)(R%m%e)",
108 "11111000111mmmmmeeei10nnnnnddddd", "MOV", "(R%n)(R%m%e),R%d",
109 "WW111000001mmmmmeeei10nnnnnddddd", "MOV%W", "R%d,(R%n)(R%m%e)",
110 "WW111000011mmmmmeeei10nnnnnddddd", "MOV%WU", "(R%n)(R%m%e),R%d",
111 "WW111000101mmmmmeeei10nnnnnddddd", "MOV%W", "(R%n)(R%m%e),R%d",
112 "WW111000111mmmmmeeei10nnnnnddddd", "MOV%WW", "(R%n)(R%m%e),R%d",
113 "W00100101ssKKKKKKKKKKKKKKKKddddd", "MOVN%W", "$%K,R%d",
114 "W10100101ssKKKKKKKKKKKKKKKKddddd", "MOVZ%W", "$%K,R%d",
115 "W11100101ssKKKKKKKKKKKKKKKKddddd", "MOVK%W", "$%K,R%d",
116 "W0010001--00000000000011111ddddd", "MOV%W", "SP,R%d",
117 "W0010001--000000000000nnnnn11111", "MOV%W", "R%n,SP",
118 "0110100011ooooooommmmm11111ddddd", "MOVPSW", "(SP)%o!,R%d,R%m",
119 "0110100011ooooooommmmmnnnnnddddd", "MOVPSW", "(R%n)%o!,R%d,R%m",
120 "0110100101ooooooommmmm11111ddddd", "MOVPSW", "%o(SP),R%d,R%m",
121 "0110100101ooooooommmmmnnnnnddddd", "MOVPSW", "%o(R%n),R%d,R%m",
122 "0110100111ooooooommmmm11111ddddd", "MOVPSW", "%o(SP)!,R%d,R%m",
123 "0110100111ooooooommmmmnnnnnddddd", "MOVPSW", "%o(R%n)!,R%d,R%m",
124 "W010100010ooooooommmmm11111ddddd", "MOVP%W", "R%d,R%m,(SP)%o!",
125 "W010100010ooooooommmmmnnnnnddddd", "MOVP%W", "R%d,R%m,(R%n)%o!",
126 "W010100100ooooooommmmm11111ddddd", "MOVP%W", "R%d,R%m,%o(SP)",
127 "W010100100ooooooommmmmnnnnnddddd", "MOVP%W", "R%d,R%m,%o(R%n)",
128 "W010100110ooooooommmmm11111ddddd", "MOVP%W", "R%d,R%m,%o(SP)!",
129 "W010100110ooooooommmmmnnnnnddddd", "MOVP%W", "R%d,R%m,%o(R%n)!",
130 "W010100011ooooooommmmm11111ddddd", "MOVP%W", "(SP)%o!,R%d,R%m",
131 "W010100011ooooooommmmmnnnnnddddd", "MOVP%W", "(R%n)%o!,R%d,R%m",
132 "W010100101ooooooommmmm11111ddddd", "MOVP%W", "%o(SP),R%d,R%m",
133 "W010100101ooooooommmmmnnnnnddddd", "MOVP%W", "%o(R%n),R%d,R%m",
134 "W010100111ooooooommmmm11111ddddd", "MOVP%W", "%o(SP)!,R%d,R%m",
135 "W010100111ooooooommmmmnnnnnddddd", "MOVP%W", "%o(R%n)!,R%d,R%m",
136 "W0010001ssIIIIIIIIIIII1111111111", "ADD%W", "$%I,SP,SP",
137 "W0010001ssIIIIIIIIIIII11111ddddd", "ADD%W", "$%I,SP,R%d",
138 "W0010001ssIIIIIIIIIIIInnnnn11111", "ADD%W", "$%I,R%n,SP",
139 "W0110001ssIIIIIIIIIIII1111111111", "ADDS%W", "$%I,SP,SP",
140 "W0110001ssIIIIIIIIIIII11111ddddd", "ADDS%W", "$%I,SP,R%d",
141 "W0110001ssIIIIIIIIIIIInnnnn11111", "ADDS%W", "$%I,R%n,SP",
142 "W1010001ssIIIIIIIIIIII1111111111", "SUB%W", "$%I,SP,SP",
143 "W1010001ssIIIIIIIIIIII11111ddddd", "SUB%W", "$%I,SP,R%d",
144 "W1010001ssIIIIIIIIIIIInnnnn11111", "SUB%W", "$%I,R%n,SP",
145 "W1110001ssIIIIIIIIIIII1111111111", "CMP%W", "$%I,SP",
146 "W1110001ssIIIIIIIIIIIInnnnn11111", "CMP%W", "$%I,R%n",
147 "W1110001ssIIIIIIIIIIII11111ddddd", "SUBS%W", "$%I,SP,R%d",
148 "W0010001ssIIIIIIIIIIIInnnnnddddd", "ADD%W", "$%I,R%n,R%d",
149 "W0110001ssIIIIIIIIIIIInnnnnddddd", "ADDS%W", "$%I,R%n,R%d",
150 "W1010001ssIIIIIIIIIIIInnnnnddddd", "SUB%W", "$%I,R%n,R%d",
151 "W1110001ssIIIIIIIIIIIInnnnnddddd", "SUBS%W", "$%I,R%n,R%d",
152 "W00100100MMMMMMMMMMMMMnnnnn11111", "AND%W", "$%M,R%n,SP",
153 "W01100100MMMMMMMMMMMMMnnnnn11111", "ORR%W", "$%M,R%n,SP",
154 "W10100100MMMMMMMMMMMMMnnnnn11111", "EOR%W", "$%M,R%n,SP",
155 "W11100100MMMMMMMMMMMMMnnnnn11111", "ANDS%W", "$%M,R%n,SP",
156 "W00100100MMMMMMMMMMMMMnnnnnddddd", "AND%W", "$%M,R%n,R%d",
157 "W01100100MMMMMMMMMMMMMnnnnnddddd", "ORR%W", "$%M,R%n,R%d",
158 "W10100100MMMMMMMMMMMMMnnnnnddddd", "EOR%W", "$%M,R%n,R%d",
159 "W11100100MMMMMMMMMMMMMnnnnnddddd", "ANDS%W", "$%M,R%n,R%d",
160 "1001001101000000011111nnnnnddddd", "SXTW", "R%n,R%d",
161 "0101001100iiiiii011111nnnnnddddd", "LSRW", "$%i,R%n,R%d",
162 "1101001101iiiiii111111nnnnnddddd", "LSR", "$%i,R%n,R%d",
163 "W00100110-iiiiiijjjjjjnnnnnddddd", "SBFM%W", "$%i,$%j,R%n,R%d",
164 "W01100110-iiiiiijjjjjjnnnnnddddd", "BFM%W", "$%i,$%j,R%n,R%d",
165 "W10100110-iiiiiijjjjjjnnnnnddddd", "UBFM%W", "$%i,$%j,R%n,R%d",
166 "W1011010000mmmmm00000011111ddddd", "NGC%W", "R%m,R%d",
167 "W1111010000mmmmm00000011111ddddd", "NGCS%W", "R%m,R%d",
168 "W0011010000mmmmm000000nnnnnddddd", "ADC%W", "R%m,R%n,R%d",
169 "W0111010000mmmmm000000nnnnnddddd", "ADCS%W", "R%m,R%n,R%d",
170 "W1011010000mmmmm000000nnnnnddddd", "SBC%W", "R%m,R%n,R%d",
171 "W1111010000mmmmm000000nnnnnddddd", "SBCS%W", "R%m,R%n,R%d",
172 "W0101011ss0mmmmmiiiiiinnnnn11111", "CMN%W", "R%m%s,R%n",
173 "W1101011ss0mmmmmiiiiiinnnnn11111", "CMP%W", "R%m%s,R%n",
174 "W1001011ss0mmmmmiiiiii11111ddddd", "NEG%W", "R%m%s,R%d",
175 "W1101011ss0mmmmmiiiiii11111ddddd", "NEGS%W", "R%m%s,R%d",
176 "W0001011ss0mmmmmiiiiiinnnnnddddd", "ADD%W", "R%m%s,R%n,R%d",
177 "W0101011ss0mmmmmiiiiiinnnnnddddd", "ADDS%W", "R%m%s,R%n,R%d",
178 "W1001011ss0mmmmmiiiiiinnnnnddddd", "SUB%W", "R%m%s,R%n,R%d",
179 "W1101011ss0mmmmmiiiiiinnnnnddddd", "SUBS%W", "R%m%s,R%n,R%d",
180 "W0001011001mmmmmeeeiii1111111111", "ADD%W", "R%m%e,SP,SP",
181 "W0001011001mmmmmeeeiii11111ddddd", "ADD%W", "R%m%e,SP,R%d",
182 "W0001011001mmmmmeeeiiinnnnn11111", "ADD%W", "R%m%e,R%n,SP",
183 "W0101011001mmmmmeeeiii1111111111", "ADDS%W", "R%m%e,SP,SP",
184 "W0101011001mmmmmeeeiii11111ddddd", "ADDS%W", "R%m%e,SP,R%d",
185 "W0101011001mmmmmeeeiiinnnnn11111", "ADDS%W", "R%m%e,R%n,SP",
186 "W1001011001mmmmmeeeiii1111111111", "SUB%W", "R%m%e,SP,SP",
187 "W1001011001mmmmmeeeiii11111ddddd", "SUB%W", "R%m%e,SP,R%d",
188 "W1001011001mmmmmeeeiiinnnnn11111", "SUB%W", "R%m%e,R%n,SP",
189 "W1101011001mmmmmeeeiii1111111111", "SUBS%W", "R%m%e,SP,SP",
190 "W1101011001mmmmmeeeiii11111ddddd", "SUBS%W", "R%m%e,SP,R%d",
191 "W1101011001mmmmmeeeiiinnnnn11111", "SUBS%W", "R%m%e,R%n,SP",
192 "W0001011001mmmmmeeeiiinnnnnddddd", "ADD%W", "R%m%e,R%n,R%d",
193 "W0101011001mmmmmeeeiiinnnnnddddd", "ADDS%W", "R%m%e,R%n,R%d",
194 "W1001011001mmmmmeeeiiinnnnnddddd", "SUB%W", "R%m%e,R%n,R%d",
195 "W1101011001mmmmmeeeiiinnnnnddddd", "SUBS%W", "R%m%e,R%n,R%d",
196 "W0101010000mmmmm-0000011111ddddd", "MOV%W", "R%m,R%d",
197 "W0101010ss1mmmmmiiiiii11111ddddd", "NVM%W", "R%m%s,R%d",
198 "W1101010ss0mmmmmiiiiiinnnnn11111", "TST%W", "R%m%s,R%n",
199 "W0001010ss0mmmmmiiiiiinnnnnddddd", "AND%W", "R%m%s,R%n,R%d",
200 "W1101010ss0mmmmmiiiiiinnnnnddddd", "ANDS%W", "R%m%s,R%n,R%d",
201 "W0001010ss1mmmmmiiiiiinnnnnddddd", "BIC%W", "R%m%s,R%n,R%d",
202 "W1101010ss1mmmmmiiiiiinnnnnddddd", "BICS%W", "R%m%s,R%n,R%d",
203 "W1001010ss0mmmmmiiiiiinnnnnddddd", "EOR%W", "R%m%s,R%n,R%d",
204 "W1001010ss1mmmmmiiiiiinnnnnddddd", "EON%W", "R%m%s,R%n,R%d",
205 "W0101010ss0mmmmmiiiiiinnnnnddddd", "ORR%W", "R%m%s,R%n,R%d",
206 "W0101010ss1mmmmmiiiiiinnnnnddddd", "ORN%W", "R%m%s,R%n,R%d",
207 "W0011010110mmmmm001000nnnnnddddd", "LSL%W", "R%m,R%n,R%d",
208 "W0011010110mmmmm001001nnnnnddddd", "LSR%W", "R%m,R%n,R%d",
209 "W0011010110mmmmm001010nnnnnddddd", "ASR%W", "R%m,R%n,R%d",
210 "W0011010110mmmmm001011nnnnnddddd", "ROR%W", "R%m,R%n,R%d",
211 "W0011010110mmmmm000010nnnnnddddd", "UDIV%W", "R%m,R%n,R%d",
212 "W0011010110mmmmm000011nnnnnddddd", "SDIV%W", "R%m,R%n,R%d",
213 "W0011011000mmmmm011111nnnnnddddd", "MUL%W", "R%m,R%n,R%d",
214 "W0011011000mmmmm111111nnnnnddddd", "MNEG%W", "R%m,R%n,R%d",
215 "W0011011000mmmmm0aaaaannnnnddddd", "MADD%W", "R%m,R%n,R%a,R%d",
216 "W0011011000mmmmm1aaaaannnnnddddd", "MSUB%W", "R%m,R%n,R%a,R%d",
217 "10011011001mmmmm011111nnnnnddddd", "SMULL", "R%m,R%n,R%d",
218 "10011011001mmmmm111111nnnnnddddd", "SMNEGL", "R%m,R%n,R%d",
219 "10011011001mmmmm0aaaaannnnnddddd", "SMADDL", "R%m,R%n,R%a,R%d",
220 "10011011001mmmmm1aaaaannnnnddddd", "SMSUBL", "R%m,R%n,R%a,R%d",
221 "10011011101mmmmm011111nnnnnddddd", "UMULL", "R%m,R%n,R%d",
222 "10011011101mmmmm111111nnnnnddddd", "UMNEGL", "R%m,R%n,R%d",
223 "10011011101mmmmm0aaaaannnnnddddd", "UMADDL", "R%m,R%n,R%a,R%d",
224 "10011011101mmmmm1aaaaannnnnddddd", "UMSUBL", "R%m,R%n,R%a,R%d",
225 "W0110100TTTTTTTTTTTTTTTTTTTddddd", "CBZ%W", "R%d,%T",
226 "W0110101TTTTTTTTTTTTTTTTTTTddddd", "CBNZ%W", "R%d,%T",
227 "01010100TTTTTTTTTTTTTTTTTTT0CCCC", "B%C", "%T",
228 "000101TTTTTTTTTTTTTTTTTTTTTTTTTT", "B", "%T",
229 "100101TTTTTTTTTTTTTTTTTTTTTTTTTT", "BL", "%T",
230 "1101011000011111000000nnnnn00000", "BR", "R%n",
231 "1101011000111111000000nnnnn00000", "BLR", "R%n",
232 "11010110010111110000001111000000", "RETURN", nil,
233 "1101011001011111000000nnnnn00000", "RET", "R%n",
234 "11010110100111110000001111100000", "ERET", nil,
235 "11010110101111110000001111100000", "DRPS", nil,
236 "11010100000iiiiiiiiiiiiiiii00001", "SVC", "$%i",
237 "11010100000iiiiiiiiiiiiiiii00010", "HVC", "$%i",
238 "11010100000iiiiiiiiiiiiiiii00011", "SMC", "$%i",
239 "11010100001iiiiiiiiiiiiiiii00000", "BRK", "$%i",
240 "11010100010iiiiiiiiiiiiiiii00000", "HLT", "$%i",
241 "11010100101iiiiiiiiiiiiiiii00001", "DCPS1", "$%i",
242 "11010100101iiiiiiiiiiiiiiii00010", "DCPS2", "$%i",
243 "11010100101iiiiiiiiiiiiiiii00011", "DCPS3", "$%i",
244 "11010101000000110010000000011111", "NOP", nil,
245 "11010101000000110010000000111111", "YIELD", nil,
246 "11010101000000110010000001011111", "WFE", nil,
247 "11010101000000110010000001111111", "WFI", nil,
248 "11010101000000110010000010011111", "SEV", nil,
249 "11010101000000110010000010111111", "SEVL", nil,
250 "11010101000000110011xxxx01011111", "CLREX", "$%x",
251 "11010101000000110011xxxx10011111", "DSB", "$%x",
252 "11010101000000110011xxxx10111111", "DMB", "$%x",
253 "11010101000000110011xxxx11011111", "ISB", "$%x",
254 "1101010100001YYYYYYYYYYYYYY11111", "SYS", "%Y",
255 "1101010100001YYYYYYYYYYYYYYddddd", "SYS", "R%d,%Y",
256 "1101010100101YYYYYYYYYYYYYYddddd", "SYSL", "%Y,R%d",
257 "11010101000000000100xxxx10111111", "MSR", "$%x,SP",
258 "11010101000000110100xxxx11011111", "MSR", "$%x,DAIFSet",
259 "11010101000000110100xxxx11111111", "MSR", "$%x,DAIFClr",
260 "11010101000YYYYYYYYYYYYYYYYddddd", "MSR", "R%d,%Y",
261 "11010101001YYYYYYYYYYYYYYYYddddd", "MRS", "%Y,R%d",
262 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "WORD", "$%x",
265 #define SYSARG5(op0,op1,Cn,Cm,op2) ((op0)<<19|(op1)<<16|(Cn)<<12|(Cm)<<8|(op2)<<5)
268 smask(char *s, char c)
274 for(i=0; i<32 && *s != '\0'; i++, s++)
275 m |= (*s == c)<<(31-i);
304 if(m == 0 || m == ~0UL)
310 unshift(ulong w, ulong m)
314 if((m+1 & m) != 0){ // 0bxxx0000yyyyyy -> 0byyyyyyxxx
315 ulong b = (1UL<<nones(m))-1;
316 return ((w & b) << nbits(m & ~b)) | unshift(w, m & ~b);
326 l <<= sizeof(l)*8 - n;
327 l >>= sizeof(l)*8 - n;
333 arm64excep(Map *, Rgetter)
335 // uvlong c = (*rget)(map, "TYPE");
340 decode(Map *map, uvlong pc, Instr *i)
342 static ulong tab[2*nelem(opcodes)];
349 /* precalculate value/mask table */
350 for(j=0, o=opcodes; j<nelem(tab); j+=2, o++){
351 tab[j] = smask(o->p, '1');
352 tab[j|1] = tab[j] | smask(o->p, '0');
358 if(get4(map, pc, &w) < 0) {
359 werrstr("can't read instruction: %r");
366 for(j=0; j<nelem(tab); j+=2){
367 if((w & tab[j|1]) == tab[j]){
368 i->op = &opcodes[j/2];
373 /* should not happen */
377 #pragma varargck argpos bprint 2
380 bprint(Instr *i, char *fmt, ...)
385 i->curr = vseprint(i->curr, i->end, fmt, arg);
392 "<<", ">>", "->", "@>"
398 "UB", "UH", "UW", "UX",
399 "SB", "SH", "SW", "SX"
405 "EQ", "NE", "HS", "LO",
406 "MI", "PL", "VS", "VC",
407 "HI", "LS", "GE", "LT",
408 "GT", "LE", "", "NV",
412 decodebitmask(int n, int s, int r)
420 for(n = 5; n >= 1 && ((~s & 0x3F) & (1<<n)) == 0; n--)
431 w = (w >> r) | (w << (e-r));
443 format(char *mnemonic, Instr *i, char *f)
450 format(0, i, mnemonic);
456 for ( ; *f && i->curr < i->end; f++) {
461 m = smask(i->op->p, *++f);
462 u = unshift(i->w, m);
464 case 'C': // Condition
465 bprint(i, "%s", scond[u & 15]);
469 if(nbits(m) == 1) u += 2;
472 *i->curr++ = "BHW"[u];
475 case 'd': // Register Numbers
479 bprint(i, "%lud", u);
482 case 's': // Register shift
483 w = unshift(i->w, smask(i->op->p, 'i'));
485 bprint(i, "%s%lud", shtype[u & 3], w);
488 case 'e': // Register extension
490 bprint(i, ".%s", rextype[u]);
491 w = unshift(i->w, smask(i->op->p, 'i'));
492 if(w != 0 && u == 2+(i->w>>31))
493 bprint(i, "<<%lud", w);
497 v = decodebitmask((u>>12)&1, u&0x3F, (u>>6)&0x3F);
498 if((i->w & (1<<31)) == 0)
500 bprint(i, "%llux", v);
503 case 'I': // Shifted Immediate (12 bit)
504 case 'K': // Shifted Immediate (16 bit)
505 w = unshift(i->w, smask(i->op->p, 's'));
507 bprint(i, "(%lux<<%ld)", u, w*(*f == 'I' ? 12 : 16));
509 bprint(i, "%lud", u);
512 case 'o': // Signed byte offset
514 bprint(i, "%ld", sext(u, w) << (w == 7 ? 2 + (i->w>>31) : 0));
516 case 'u': // Unsigned offset
517 u <<= (i->w >> 30)&3;
521 bprint(i, "%lud", u);
525 bprint(i, "%lux", u);
528 case 'l': // 32-bit Literal
529 if(get4(i->map, i->addr + sext(u, nbits(m))*4, &w) < 0)
531 bprint(i, "$%lux", w);
533 case 'L': // 64-bit Literal
534 if(get8(i->map, i->addr + sext(u, nbits(m))*4, &v) < 0)
536 bprint(i, "$%llux", v);
538 case 'T': // Text address (PC relative)
540 v = i->addr + sext(u, nbits(m))*4;
541 if(findsym(v, CTEXT, &s)){
542 bprint(i, "%s", s.name);
544 bprint(i, "%llx", v - s.value);
546 bprint(i, "+%llx", v - s.value);
550 bprint(i, "%llux(SB)", v);
552 case 'A': // Data address (PC relative)
553 v = i->addr + sext(u, nbits(m));
555 case 'P': // Page address (PC relative)
556 v = i->addr + ((vlong)sext(u, nbits(m)) << 12);
558 if(findsym(v, CANY, &s)){
559 bprint(i, "%s", s.name);
561 bprint(i, "%llx", v - s.value);
563 bprint(i, "+%llx", v - s.value);
567 bprint(i, "%llux(SB)", v);
571 if(nbits(m) == 14){ // SYS/SYSL operands
572 bprint(i, "%lud,%lud,%lud,%lud",
573 (u>>(4+4+3))&7, // op1
574 (u>>(4+3))&15, // CRn
579 /* see /sys/src/cmd/7c/7.out.h */
581 case SYSARG5(3,3,4,2,1): bprint(i, "DAIF"); break;
582 case SYSARG5(3,3,4,2,0): bprint(i, "NZCV"); break;
583 case SYSARG5(3,3,4,4,1): bprint(i, "FPSR"); break;
584 case SYSARG5(3,3,4,4,0): bprint(i, "FPCR"); break;
585 case SYSARG5(3,0,4,0,0): bprint(i, "SPSR_EL1"); break;
586 case SYSARG5(3,0,4,0,1): bprint(i, "ELR_EL1"); break;
587 case SYSARG5(3,4,4,0,0): bprint(i, "SPSR_EL2"); break;
588 case SYSARG5(3,4,4,0,1): bprint(i, "ELR_EL2"); break;
589 case SYSARG5(3,0,4,2,2): bprint(i, "CurrentEL"); break;
590 case SYSARG5(3,0,4,1,0): bprint(i, "SP_EL0"); break;
591 case SYSARG5(3,0,4,2,0): bprint(i, "SPSel"); break;
592 default: bprint(i, "SPR(%lux)", i->w & m);
601 bprint(i, "%%%c", *f);
609 printins(Map *map, uvlong pc, char *buf, int n)
615 if(decode(map, pc, i) < 0)
617 format(i->op->o, i, i->op->a);
622 arm64inst(Map *map, uvlong pc, char modifier, char *buf, int n)
625 return printins(map, pc, buf, n);
629 arm64das(Map *map, uvlong pc, char *buf, int n)
635 if(decode(map, pc, i) < 0)
637 if(i->end-i->curr > 8)
638 i->curr = _hexify(buf, i->w, 7);
644 arm64instlen(Map*, uvlong)
650 readreg(Instr *i, Rgetter rget, int rc)
655 snprint(reg, sizeof(reg), "R%lud", unshift(i->w, smask(i->op->p, rc)));
656 v = (*rget)(i->map, reg);
657 m = smask(i->op->p, 'W');
658 if(m != 0 && unshift(i->w, m) == 0)
664 passcond(Instr *i, Rgetter rget)
672 psr = (*rget)(i->map, "PSR");
678 switch(unshift(i->w, smask(i->op->p, 'C'))) {
688 case 8: return c && !z;
689 case 9: return !c || z;
690 case 10: return n == v;
691 case 11: return n != v;
692 case 12: return !z && (n == v);
693 case 13: return z || (n != v);
702 ulong m = smask(i->op->p, 'T');
703 return i->addr + sext(unshift(i->w, m), m)*4;
707 arm64foll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
712 if(decode(map, pc, i) < 0)
716 if(strcmp(o, "ERET") == 0)
719 if(strcmp(o, "RET") == 0 || strcmp(o, "BR") == 0 || strcmp(o, "BLR") == 0){
720 foll[0] = readreg(i, rget, 'n');
723 if(strcmp(o, "B") == 0 || strcmp(o, "BL") == 0){
724 foll[0] = jumptarg(i);
727 if(strcmp(o, "B%C") == 0){
728 if(passcond(i, rget)){
729 foll[0] = jumptarg(i);
733 if(strcmp(o, "CBZ%W") == 0){
734 if(readreg(i, rget, 'd') == 0){
735 foll[0] = jumptarg(i);
739 if(strcmp(o, "CBNZ%W") == 0){
740 if(readreg(i, rget, 'd') != 0){
741 foll[0] = jumptarg(i);