add some more info from tamarin opcode list, mark missing opcodes #s
[swf2.git] / asm / opcodes.lisp
blobbf68ad95fd7afcbafe51415919c7d217ed2f1c90
1 (in-package :avm2-asm)
3 (defun runtime-name-count (index)
4 "some opcodes need extra args when passed a runtime multiname, check
5 for that here and return count of extra args"
6 (let* ((mn (aref (avm2-asm::multinames avm2-asm::*assembler-context*) index))
7 (kind (car mn)))
8 (cond
9 ((or (= kind avm2-asm::+rt-qname+)
10 (= kind avm2-asm::+rt-qname-a+))
12 ((or (= kind avm2-asm::+rt-qname-l+)
13 (= kind avm2-asm::+rt-qname-la+))
15 (t 0))))
17 ;;; opcode lists:
18 ;;; http://ncannasse.fr/blog/adobe_alchemy
19 ;;;-- missing some from this one:
20 ;;; http://www.libspark.org/svn/as3/ByteCodeDisassembler/org/libspark/disassemble/abc/AbcParser.as
22 (define-ops
23 ;; name (args) opcode pop push pop-scope push-scope local flags
24 (:breakpoint () #x01 0 0) ;
25 (:nop () #x02 0 0) ;
26 (:throw () #x03 1 0) ;
27 (:get-super ((multiname multiname-q30)) #x04 (1+ (runtime-name-count multiname)) 1)
28 (:set-super ((multiname multiname-q30)) #x05 (+ 2 (runtime-name-count multiname)))
29 (:dxns ((string string-u30)) #x06 0 0 0 0 0 +set-dxns+)
30 (:dxnslate () #x07 1 0 0 0 0 +set-dxns+)
31 (:kill ((local-index u30)) #x08 0 0)
32 (:label () #x09 0 0)
33 ;; #x0a
34 ;; #x0b
35 (:if-nlt ((offset ofs24)) #x0c 2 0)
36 (:if-nle ((offset ofs24)) #x0d 2 0)
37 (:if-ngt ((offset ofs24)) #x0e 2 0)
38 (:if-nge ((offset ofs24)) #x0f 2 0)
39 (:jump ((offset ofs24)) #x10 0 0)
40 (:if-true ((offset ofs24)) #x11 1 0)
41 (:if-false ((offset ofs24)) #x12 1 0)
42 (:if-eq ((offset ofs24)) #x13 2 0)
43 (:if-ne ((offset ofs24)) #x14 2 0)
44 (:if-lt ((offset ofs24)) #x15 2 0)
45 (:if-le ((offset ofs24)) #x16 2 0)
46 (:if-gt ((offset ofs24)) #x17 2 0)
47 (:if-ge ((offset ofs24)) #x18 2 0)
48 (:if-strict-eq ((offset ofs24)) #x19 2 0)
49 (:if-strict-ne ((offset ofs24)) #x1a 2 0)
50 (:lookup-switch ((default-offset ofs24) (offsets counted-ofs24)) #x1b 1 0)
51 (:push-with () #x1c 1 0 0 1)
52 (:pop-scope () #x1d 0 0 1 0)
53 (:next-name () #x1e 2 1)
54 (:has-next () #x1f 2 1)
55 (:push-null () #x20 0 1)
56 (:push-undefined () #x21 0 1)
57 ;; (:push-constant ? #x22 ? ?) -- fp10 = illegal opcode
58 (:next-value () #x23 2 1)
59 (:push-byte ((byte u8)) #x24 0 1)
60 (:push-short ((value u30)) #x25 0 1)
61 (:push-true () #x26 0 1)
62 (:push-false () #x27 0 1)
63 (:push-nan () #x28 0 1)
64 (:pop () #x29 1 0)
65 (:dup () #x2a 1 2)
66 (:swap () #x2b 2 2)
67 (:push-string ((string string-u30)) #x2c 0 1)
68 (:push-int ((integer int-u30)) #x2d 0 1)
69 (:push-uint ((uinteger uint-u30)) #x2e 0 1)
70 (:push-double ((double double-u30)) #x2f 0 1)
71 (:push-scope () #x30 1 0 0 1)
72 (:push-namespace ((namespace namespace-q30)) #x31 0 1)
73 (:has-next-2 ((object-local-reg u30) (index-local-reg u30)) #x32 0 1 0 0 (max object-local-reg index-local-reg))
74 ;; #x33
75 ;; #x34
76 ;; #x35-#x3e: flash 10/alchemy instrs
77 ;; see http://ncannasse.fr/blog/adobe_alchemy
78 ;; (are these backwards? tamarin has li*/lf* then si*/sf*
79 (:store-int-8 () #x35 2 0) ;; stack=value,addr -> .
80 (:store-int-16 () #x36 2 0) ;; stack=value,addr -> .
81 (:store-int-32 () #x37 2 0) ;; stack=value,addr -> .
82 (:store-float-32 () #x38 2 0) ;; stack=value,addr -> .
83 (:store-float-64 () #x39 2 0) ;; stack=value,addr -> .
84 (:load-int-8 () #x3a 1 1) ;; stack=addr -> value
85 (:load-int-16 () #x3b 1 1) ;; stack=addr -> value
86 (:load-int-32 () #x3c 1 1) ;; stack=addr -> value
87 (:load-float-32 () #x3d 1 1) ;; stack=addr -> value
88 (:load-float-64 () #x3e 1 1) ;; stack=addr -> value
89 ;; #x3f
90 (:new-function ((method-index method-u30)) #x40 0 1)
91 (:call ((arg-count u30)) #x41 (+ 2 arg-count) 1)
92 (:construct ((arg-count u30)) #x42 (1+ arg-count) 1)
93 (:call-method ((method-index method-u30) (arg-count u30)) #x43 (+ 1 arg-count) 1)
94 (:call-static ((method-index method-u30) (arg-count u30)) #x44 (+ 1 arg-count) 1)
95 (:call-super ((multiname multiname-q30) (arg-count u30)) #x45 (+ 1 arg-count (runtime-name-count multiname)) 1)
96 (:call-property ((multiname multiname-q30) (arg-count u30)) #x46 (+ 1 arg-count (runtime-name-count multiname)) 1)
97 (:return-void () #x47 0 0)
98 (:return-value () #x48 1 0)
99 (:construct-super ((arg-count u30)) #x49 (1+ arg-count) 0)
100 (:construct-prop ((multiname multiname-q30) (arg-count u30)) #x4a (+ 1 arg-count (runtime-name-count multiname)) 1)
101 ;;(:call-super-id ? #x4b ? ?)
102 (:call-prop-lex ((multiname multiname-q30) (arg-count u30)) #x4c (+ 1 arg-count (runtime-name-count multiname)) 1)
103 ;;(:call-interface ? #x4d ? ?)
104 (:call-super-void ((multiname multiname-q30) (arg-count u30)) #x4e (+ 1 arg-count (runtime-name-count multiname)) 0)
105 (:call-prop-void ((multiname multiname-q30) (arg-count u30)) #x4f (+ 1 arg-count (runtime-name-count multiname)) 0)
106 ;; #50-#x52: flash 10/alchemy instructions
107 (:sign-extend-1to32 () #x50 1 1) ;; stack=value,value
108 (:sign-extend-8to32 () #x51 1 1) ;; stack=value,value
109 (:sign-extend-16to32 () #x52 1 1) ;; stack=value,value
110 ;; (:apply-type (?) #x53 1 1) ??
111 ;; #x54
112 (:new-object ((arg-count u32)) #x55 (* 2 arg-count) 1)
113 (:new-array ((arg-count u30)) #x56 arg-count 1)
114 (:new-activation () #x57 0 1 0 0 0 +need-activation+)
115 (:new-class ((class-index u30)) #x58 1 1) ;; 2->1 ? also see docs about scope stuff
116 (:get-descendants ((multiname multiname-q30)) #x59 (1+ (runtime-name-count multiname)) 1)
117 (:new-catch ((exception-index u30)) #x5a 0 1)
118 ;; #x5b
119 ;; #x5c
120 (:find-property-strict ((multiname multiname-q30)) #x5d (runtime-name-count multiname) 1)
121 (:find-property ((multiname multiname-q30)) #x5e (runtime-name-count multiname) 1)
122 (:find-def ((string string-u30)) #x5f 0 1) ;; ??
123 (:get-lex ((multiname multiname-q30)) #x60 0 1)
124 (:set-property ((multiname multiname-q30)) #x61 (+ 2 (runtime-name-count multiname)) 0)
125 (:get-local ((local-index u30)) #x62 0 1 0 0 local-index)
126 (:set-local ((local-index u30)) #x63 1 0 0 0 local-index)
127 (:get-global-scope () #x64 0 1)
128 (:get-scope-object ((scope-index u8)) #x65 0 1)
129 (:get-property ((multiname multiname-q30)) #x66 (1+ (runtime-name-count multiname)) 1)
130 ;;(:get-outer-scope (?) #x67 0 1) ??
131 (:init-property ((multiname multiname-q30)) #x68 (+ 2 (runtime-name-count multiname)) 0)
132 ;; #x69
133 (:delete-property ((multiname multiname-q30)) #x6a (1+ (runtime-name-count multiname)) 1)
134 ;; #x6b
135 (:get-slot ((slot-index u30)) #x6c 1 1)
136 (:set-slot ((slot-index u30)) #x6d 2 0)
137 (:get-global-slot ((slot-index u30)) #x6e 0 1) ;; deprecated?
138 (:set-global-slot ((slot-index u30)) #x6f 1 0) ;; deprecated?
139 (:convert-string () #x70 1 1)
140 (:esc_xelem () #x71 1 1)
141 (:esc_xattr () #x72 1 1)
142 (:convert-integer () #x73 1 1)
143 (:convert-unsigned () #x74 1 1)
144 (:convert-double () #x75 1 1)
145 (:convert-boolean () #x76 1 1)
146 (:convert-object () #x77 1 1)
147 (:check-filter () #x78 1 1)
148 ;; #x79
149 ;; #x7a
150 ;; #x7b
151 ;; #x7c
152 ;; #x7d
153 ;; #x7e
154 ;; #x7f
155 (:coerce ((multiname multiname-q30)) #x80 1 1)
156 (:coerce-b () #x81 1 1) ;; deprecated?
157 (:coerce-any () #x82 1 1)
158 (:coerce-i () #x83 1 1) ;; deprecated?
159 (:coerce-d () #x84 1 1) ;; deprecated?
160 (:coerce-string () #x85 1 1)
161 (:as-type ((multiname multiname-q30)) #x86 1 1)
162 (:as-type-late () #x87 2 1)
163 (:coerce-u () #x88 1 1) ;; deprecated?
164 (:coerce-object () #x89 1 1)
165 ;; #x8a
166 ;; #x8b
167 ;; #x8c
168 ;; #x8d
169 ;; #x8e
170 ;; #x8f
171 (:negate () #x90 1 1)
172 (:increment () #x91 1 1)
173 (:inc-local ((local-index u30)) #x92 0 0 0 0 local-index)
174 (:decrement () #x93 1 1)
175 (:dec-local ((local-index u30)) #x94 0 0 0 0 local-index)
176 (:type-of () #x95 1 1)
177 (:not () #x96 1 1)
178 (:bit-not () #x97 1 1)
179 ;; (:concat ? #x9a ? ?)
180 ;; (:add_d ? #x9b ? ?)
181 ;; #x9b
182 ;; #x9e
183 ;; #x9d
184 ;; #x9f
185 (:add () #xa0 2 1)
186 (:subtract () #xa1 2 1)
187 (:multiply () #xa2 2 1)
188 (:divide () #xa3 2 1)
189 (:modulo () #xa4 2 1)
190 (:lshift () #xa5 2 1)
191 (:rshift () #xa6 2 1)
192 (:unsigned-rshift () #xa7 2 1)
193 (:bit-and () #xa8 2 1)
194 (:bit-or () #xa9 2 1)
195 (:bit-xor () #xaa 2 1)
196 (:equals () #xab 2 1)
197 (:strict-equals () #xac 2 1)
198 (:less-than () #xad 2 1)
199 (:less-equals () #xae 2 1)
200 (:greater-than () #xaf 2 1)
201 (:greater-equals () #xb0 2 1)
202 (:instance-of () #xb1 2 1)
203 ;; :is-type seems broken (in player 10), unpredictably changes type
204 ;; of things on stack or scope stack causing verifier errors
205 (:is-type ((multiname multiname-q30)) #xb2 1 1)
206 (:is-type-late () #xb3 2 1)
207 (:in () #xb4 2 1)
208 ;; #xb5
209 ;; #xb6
210 ;; #xb7
211 ;; #xb8
212 ;; #xb9
213 ;; #xba
214 ;; #xbb
215 ;; #xbc
216 ;; #xbd
217 ;; #xbe
218 ;; #xbf
219 (:increment-i () #xc0 1 1)
220 (:decrement-i () #xc1 1 1)
221 (:inc-local-i ((local-index u30)) #xc2 0 0 0 0 local-index)
222 (:dec-local-i ((local-index u30)) #xc3 0 0 0 0 local-index)
223 (:negate-i () #xc4 1 1)
224 (:add-i () #xc5 2 1)
225 (:subtract-i () #xc6 2 1)
226 (:multiply-i () #xc7 2 1)
227 ;; #xc8
228 ;; #xc9
229 ;; #xca
230 ;; #xcb
231 ;; #xcc
232 ;; #xcd
233 ;; #xce
234 ;; #xcf
235 (:get-local-0 () #xd0 0 1 0 0 0)
236 (:get-local-1 () #xd1 0 1 0 0 1)
237 (:get-local-2 () #xd2 0 1 0 0 2)
238 (:get-local-3 () #xd3 0 1 0 0 3)
239 (:set-local-0 () #xd4 1 0 0 0 0)
240 (:set-local-1 () #xd5 1 0 0 0 1)
241 (:set-local-2 () #xd6 1 0 0 0 2)
242 (:set-local-3 () #xd7 1 0 0 0 3)
243 ;; #xd8
244 ;; #xd9
245 ;; #xda
246 ;; #xdb
247 ;; #xdc
248 ;; #xdd
249 ;; #xde
250 ;; #xdf
251 ;; #xe0
252 ;; #xe1
253 ;; #xe2
254 ;; #xe3
255 ;; #xe4
256 ;; #xe5
257 ;; #xe6
258 ;; #xe7
259 ;; #xe8
260 ;; #xe9
261 ;; #xea
262 ;; #xeb
263 ;; #xec
264 ;; #xed
265 ;; (:abs-jump () #xee 0 0) ?
266 (:debug ((debug-type u8) (string string-u30) (register u8) (extra u30)) #xef 0 0)
267 (:debug-line ((line-number u30)) #xf0 0 0)
268 (:debug-file ((string string-u30)) #xf1 0 0)
269 #+ (or) (:breakpoint-line ((line ?) #xf2))
270 (:timestamp () #xf3 0 0)
271 ;;(:verify-pass ? #xf5 ? ?)
272 ;;(:alloc ? #xf6 ? ?)
273 ;;(:mark ? #xf7 ? ?)
274 ;;(:wb ? #xf8 ? ?)
275 ;;(:prologue ? #xf9 ? ?)
276 ;;(:send-enter ? #xfa ? ?)
277 ;;(:double-to-atom ? #xfb ? ?)
278 ;;(:sweep ? #xfc ? ?)
279 ;;(:codegen-op ? #xfd ? ?)
280 ;;(:verify-op ? #xfe ? ?)
281 ;;(:decode ? #xff ? ?)
287 #+nil(format t "~{ ~x ~}~% "
288 (avm2-asm:assemble '((get-local-0)
289 (push-scope)
290 (return-void))))
291 ;; D0 30 47
294 #+nil
295 (let ((*assembler-context* (make-instance 'assembler-context)))
296 ;; intern some names so the code compiles
297 (avm2-intern "")
298 (avm2-ns-intern "")
299 (qname "a" "b")
300 (qname "b" "b")
301 (qname "c" "b")
302 (qname "d" "b")
303 (qname "e" "b")
304 (format t "~{ ~2,'0x~}~% "
305 (assemble '((:get-local-0)
306 (:push-scope)
307 (:get-local-0)
308 (:construct-super 0)
309 (:find-property-strict 3)
310 (:construct-prop 3 0)
311 (:coerce 3)
312 (:set-local-1)
313 (:get-local-1)
314 (:push-string 7)
315 (:push-string 7)
316 (:add)
317 (:set-property 4)
318 (:find-property-strict 5)
319 (:get-local-1)
320 (:call-prop-void 5 1)
321 (:return-void)))))
322 ;; D0 30 D0 49 00 5D 03 4A 03 00 80 03 D5 D1 2C 07 2C 07 A0 61 04 5D 05 D1 4F 05 01 47
323 ;; D0 30 D0 49 00 5D 03 4A 03 00 80 03 D5 D1 2C 07 2C 07 A0 61 04 5D 05 D1 4F 05 01 47
327 #+nil
328 (let ((*assembler-context* (make-instance 'assembler-context)))
329 ;; intern some names so the code compiles
330 (avm2-intern "")
331 (avm2-ns-intern "")
332 (qname "a" "b")
333 (qname "b" "b")
334 (qname "c" "b")
335 (qname "d" "b")
336 (qname "e" "b")
337 (format t "~{ ~2,'0x~}~% "
338 (assemble '((:get-local-0)
339 (:push-scope)
340 (:get-local-0)
341 (:construct-super 0)
342 (:find-property-strict 3)
343 (:construct-prop 3 0)
344 (:coerce 3)
345 (:push-null)
346 (:pop)
347 (:set-local-1)
348 (:get-local-1)
349 (:push-string 7)
350 (:push-string 7)
351 (:add)
352 (:set-property 4)
353 (:find-property-strict 5)
354 (:get-local-1)
355 (:call-prop-void 5 1)
356 (:return-void)))))
358 #+nil
359 (let ((*assembler-context* (make-instance 'assembler-context)))
360 ;; intern some names so the code compiles
361 (avm2-intern "")
362 (avm2-ns-intern "")
363 (qname "a" "b")
364 (qname "b" "b")
365 (qname "c" "b")
366 (qname "d" "b")
367 (qname "e" "b")
368 (format t "~{ ~s~%~}~% "
369 (avm2-disassemble
370 (assemble '((:get-local-0)
371 (:push-scope)
372 (:get-local-0)
373 (:construct-super 0)
374 (:find-property-strict (:id 3))
375 (:construct-prop (:id 3) 0)
376 (:coerce (:id 3))
377 (:push-null)
378 (:pop)
379 (:set-local-1)
380 (:get-local-1)
381 (:push-string "string1")
382 (:push-string "string2")
383 (:add)
384 (:set-property "foo:bar")
385 (:set-property (:qname "foo" "baz"))
386 (:set-property (:id 3))
387 (:find-property-strict "string1")
388 (:get-local-1)
389 (:call-prop-void (:id 5) 1)
390 (:return-void))))))
392 #+nil
393 (format t "~{ ~s~%~}"
394 (avm2-disassemble #(#xD0 #x30 #xD0 #x49 #x00 #x5D #x03 #x4A #x03 #x00
395 #x80 #x03 #xD5 #xD1 #x2C #x07 #x2C #x07 #xA0 #x61
396 #x04 #x5D #x05 #xD1 #x4F #x05 #x01 #x47)))
398 #+nil
399 (format t "~{ #x~2,'0x~}~%"
400 (assemble '( (:GET-LOCAL-0)
401 (:PUSH-SCOPE)
402 (:GET-LOCAL-0)
403 (:CONSTRUCT-SUPER 0)
404 (:FIND-PROPERTY-STRICT (:QNAME "flash.text" ":TextField"))
405 (:CONSTRUCT-PROP (:QNAME "flash.text" ":TextField") 0)
406 (:COERCE (:QNAME "flash.text" ":TextField"))
407 (:SET-LOCAL-1)
408 (:GET-LOCAL-1)
409 (:PUSH-STRING "TextField")
410 (:PUSH-STRING "TextField")
411 (:ADD)
412 (:SET-PROPERTY (:QNAME "" "foo"))
413 (:FIND-PROPERTY-STRICT (:QNAME "flash.text" "TextField"))
414 (:GET-LOCAL-1)
415 (:CALL-PROP-VOID (:QNAME "flash.text" "TextField") 1)
416 (:RETURN-VOID))))
418 #+nil
419 (format t "~{ ~s~%~}"
420 (avm2-disassemble
421 #( #xD0 #x30 #xD0 #x49 #x00 #x5D #x03 #x4A #x03 #x00 #x80 #x03 #xD5 #xD1 #x2C #x07 #x2C #x07 #xA0 #x61 #x04 #x5D #x05 #xD1 #x4F #x05 #x01 #x47)