get rid of extra special forms
[swf2.git] / asm / opcodes.lisp
blob5e9343d8d42dd57271b6ef250e552b38de9f2aa9
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 (:if-nlt ((offset ofs24)) #x0c 2 0)
34 (:if-nle ((offset ofs24)) #x0d 2 0)
35 (:if-ngt ((offset ofs24)) #x0e 2 0)
36 (:if-nge ((offset ofs24)) #x0f 2 0)
37 (:jump ((offset ofs24)) #x10 0 0)
38 (:if-true ((offset ofs24)) #x11 1 0)
39 (:if-false ((offset ofs24)) #x12 1 0)
40 (:if-eq ((offset ofs24)) #x13 2 0)
41 (:if-ne ((offset ofs24)) #x14 2 0)
42 (:if-lt ((offset ofs24)) #x15 2 0)
43 (:if-le ((offset ofs24)) #x16 2 0)
44 (:if-gt ((offset ofs24)) #x17 2 0)
45 (:if-ge ((offset ofs24)) #x18 2 0)
46 (:if-strict-eq ((offset ofs24)) #x19 2 0)
47 (:if-strict-ne ((offset ofs24)) #x1a 2 0)
48 (:lookup-switch ((default-offset ofs24) (offsets counted-ofs24)) #x1b 1 0)
49 (:push-with () #x1c 1 0 0 1)
50 (:pop-scope () #x1d 0 0 1 0)
51 (:next-name () #x1e 2 1)
52 (:has-next () #x1f 2 1)
53 (:push-null () #x20 0 1)
54 (:push-undefined () #x21 0 1)
55 ;; (:push-constant ? #x22 ? ?) -- fp10 = illegal opcode
56 (:next-value () #x23 2 1)
57 (:push-byte ((byte u8)) #x24 0 1)
58 (:push-short ((value u30)) #x25 0 1)
59 (:push-true () #x26 0 1)
60 (:push-false () #x27 0 1)
61 (:push-nan () #x28 0 1)
62 (:pop () #x29 1 0)
63 (:dup () #x2a 1 2)
64 (:swap () #x2b 2 2)
65 (:push-string ((string string-u30)) #x2c 0 1)
66 (:push-int ((integer int-u30)) #x2d 0 1)
67 (:push-uint ((uinteger uint-u30)) #x2e 0 1)
68 (:push-double ((double double-u30)) #x2f 0 1)
69 (:push-scope () #x30 1 0 0 1)
70 (:push-namespace ((namespace namespace-q30)) #x31 0 1)
71 (:has-next-2 ((object-local-reg u30) (index-local-reg u30)) #x32 0 1 0 0 (max object-local-reg index-local-reg))
72 ;; #x35-#x3e: flash 10/alchemy instrs
73 ;; see http://ncannasse.fr/blog/adobe_alchemy
74 (:store-int-8 () #x35 2 0) ;; stack=value,addr -> .
75 (:store-int-16 () #x36 2 0) ;; stack=value,addr -> .
76 (:store-int-32 () #x37 2 0) ;; stack=value,addr -> .
77 (:store-float-32 () #x38 2 0) ;; stack=value,addr -> .
78 (:store-float-64 () #x39 2 0) ;; stack=value,addr -> .
79 (:load-int-8 () #x3a 1 1) ;; stack=addr -> value
80 (:load-int-16 () #x3b 1 1) ;; stack=addr -> value
81 (:load-int-32 () #x3c 1 1) ;; stack=addr -> value
82 (:load-float-32 () #x3d 1 1) ;; stack=addr -> value
83 (:load-float-64 () #x3e 1 1) ;; stack=addr -> value
85 (:new-function ((method-index u30)) #x40 0 1)
86 (:call ((arg-count u30)) #x41 (+ 2 arg-count) 1)
87 (:construct ((arg-count u30)) #x42 (1+ arg-count) 1)
88 (:call-method ((method-index u30) (arg-count u30)) #x43 (+ 1 arg-count) 1)
89 (:call-static ((method-index u30) (arg-count u30)) #x44 (+ 1 arg-count) 1)
90 (:call-super ((multiname multiname-q30) (arg-count u30)) #x45 (+ 1 arg-count (runtime-name-count multiname)) 1)
91 (:call-property ((multiname multiname-q30) (arg-count u30)) #x46 (+ 1 arg-count (runtime-name-count multiname)) 1)
92 (:return-void () #x47 0 0)
93 (:return-value () #x48 1 0)
94 (:construct-super ((arg-count u30)) #x49 (1+ arg-count) 0)
95 (:construct-prop ((multiname multiname-q30) (arg-count u30)) #x4a (+ 1 arg-count (runtime-name-count multiname)) 1)
96 ;;(:call-super-id ? #x4b ? ?)
97 (:call-prop-lex ((multiname multiname-q30) (arg-count u30)) #x4c (+ 1 arg-count (runtime-name-count multiname)) 1)
98 ;;(:call-interface ? #x4d ? ?)
99 (:call-super-void ((multiname multiname-q30) (arg-count u30)) #x4e (+ 1 arg-count (runtime-name-count multiname)) 0)
100 (:call-prop-void ((multiname multiname-q30) (arg-count u30)) #x4f (+ 1 arg-count (runtime-name-count multiname)) 0)
101 ;; #50-#x52: flash 10/alchemy instructions
102 (:sign-extend-1to32 () #x50 1 1) ;; stack=value,value
103 (:sign-extend-8to32 () #x51 1 1) ;; stack=value,value
104 (:sign-extend-16to32 () #x52 1 1) ;; stack=value,value
107 (:new-object ((arg-count u32)) #x55 (* 2 arg-count) 1)
108 (:new-array ((arg-count u30)) #x56 arg-count 1)
109 (:new-activation () #x57 0 1 0 0 0 +need-activation+)
110 (:new-class ((class-index u30)) #x58 1 1) ;; 2->1 ? also see docs about scope stuff
111 (:get-descendants ((multiname multiname-q30)) #x59 (1+ (runtime-name-count multiname)) 1)
112 (:new-catch ((exception-index u30)) #x5a 0 1)
113 (:find-property-strict ((multiname multiname-q30)) #x5d (runtime-name-count multiname) 1)
114 (:find-property ((multiname multiname-q30)) #x5e (runtime-name-count multiname) 1)
115 (:find-def ((string string-u30)) #x5f 0 1) ;; ??
116 (:get-lex ((multiname multiname-q30)) #x60 0 1)
117 (:set-property ((multiname multiname-q30)) #x61 (+ 2 (runtime-name-count multiname)) 0)
118 (:get-local ((local-index u30)) #x62 0 1 0 0 local-index)
119 (:set-local ((local-index u30)) #x63 1 0 0 0 local-index)
120 (:get-global-scope () #x64 0 1)
121 (:get-scope-object ((scope-index u8)) #x65 0 1)
122 (:get-property ((multiname multiname-q30)) #x66 (1+ (runtime-name-count multiname)) 1)
123 (:init-property ((multiname multiname-q30)) #x68 (+ 2 (runtime-name-count multiname)) 0)
124 (:delete-property ((multiname multiname-q30)) #x6a (1+ (runtime-name-count multiname)) 1)
125 (:get-slot ((slot-index u30)) #x6c 1 1)
126 (:set-slot ((slot-index u30)) #x6d 2 0)
127 (:get-global-slot ((slot-index u30)) #x6e 0 1) ;; deprecated?
128 (:set-global-slot ((slot-index u30)) #x6f 1 0) ;; deprecated?
129 (:convert-string () #x70 1 1)
130 (:esc_xelem () #x71 1 1)
131 (:esc_xattr () #x72 1 1)
132 (:convert-integer () #x73 1 1)
133 (:convert-unsigned () #x74 1 1)
134 (:convert-double () #x75 1 1)
135 (:convert-boolean () #x76 1 1)
136 (:convert-object () #x77 1 1)
137 (:check-filter () #x78 1 1)
138 (:coerce ((multiname multiname-q30)) #x80 1 1)
139 (:coerce-b () #x81 1 1) ;; deprecated?
140 (:coerce-any () #x82 1 1)
141 (:coerce-i () #x83 1 1) ;; deprecated?
142 (:coerce-d () #x84 1 1) ;; deprecated?
143 (:coerce-string () #x85 1 1)
144 (:as-type ((multiname multiname-q30)) #x86 1 1)
145 (:as-type-late () #x87 2 1)
146 (:coerce-u () #x88 1 1) ;; deprecated?
147 (:coerce-object () #x89 1 1)
148 (:negate () #x90 1 1)
149 (:increment () #x91 1 1)
150 (:inc-local ((local-index u30)) #x92 0 0 0 0 local-index)
151 (:decrement () #x93 1 1)
152 (:dec-local ((local-index u30)) #x94 0 0 0 0 local-index)
153 (:type-of () #x95 1 1)
154 (:not () #x96 1 1)
155 (:bit-not () #x97 1 1)
156 ;; (:concat ? #x9a ? ?)
157 ;; (:add_d ? #x9b ? ?)
158 (:add () #xa0 2 1)
159 (:subtract () #xa1 2 1)
160 (:multiply () #xa2 2 1)
161 (:divide () #xa3 2 1)
162 (:modulo () #xa4 2 1)
163 (:lshift () #xa5 2 1)
164 (:rshift () #xa6 2 1)
165 (:unsigned-rshift () #xa7 2 1)
166 (:bit-and () #xa8 2 1)
167 (:bit-or () #xa9 2 1)
168 (:bit-xor () #xaa 2 1)
169 (:equals () #xab 2 1)
170 (:strict-equals () #xac 2 1)
171 (:less-than () #xad 2 1)
172 (:less-equals () #xae 2 1)
173 (:greater-than () #xaf 2 1)
174 (:greater-equals () #xb0 2 1)
175 (:instance-of () #xb1 2 1)
176 ;; :is-type seems broken (in player 10), unpredictably changes type
177 ;; of things on stack or scope stack causing verifier errors
178 (:is-type ((multiname multiname-q30)) #xb2 1 1)
179 (:is-type-late () #xb3 2 1)
180 (:in () #xb4 2 1)
181 (:increment-i () #xc0 1 1)
182 (:decrement-i () #xc1 1 1)
183 (:inc-local-i ((local-index u30)) #xc2 0 0 0 0 local-index)
184 (:dec-local-i ((local-index u30)) #xc3 0 0 0 0 local-index)
185 (:negate-i () #xc4 1 1)
186 (:add-i () #xc5 2 1)
187 (:subtract-i () #xc6 2 1)
188 (:multiply-i () #xc7 2 1)
189 (:get-local-0 () #xd0 0 1 0 0 0)
190 (:get-local-1 () #xd1 0 1 0 0 1)
191 (:get-local-2 () #xd2 0 1 0 0 2)
192 (:get-local-3 () #xd3 0 1 0 0 3)
193 (:set-local-0 () #xd4 1 0 0 0 0)
194 (:set-local-1 () #xd5 1 0 0 0 1)
195 (:set-local-2 () #xd6 1 0 0 0 2)
196 (:set-local-3 () #xd7 1 0 0 0 3)
197 (:debug ((debug-type u8) (string string-u30) (register u8) (extra u30)) #xef 0 0)
198 (:debug-line ((line-number u30)) #xf0 0 0)
199 (:debug-file ((string string-u30)) #xf1 0 0)
200 #+ (or) (:breakpoint-line ((line ?) #xf2))
201 (:timestamp () #xf3 0 0)
202 ;;(:verify-pass ? #xf5 ? ?)
203 ;;(:alloc ? #xf6 ? ?)
204 ;;(:mark ? #xf7 ? ?)
205 ;;(:wb ? #xf8 ? ?)
206 ;;(:prologue ? #xf9 ? ?)
207 ;;(:send-enter ? #xfa ? ?)
208 ;;(:double-to-atom ? #xfb ? ?)
209 ;;(:sweep ? #xfc ? ?)
210 ;;(:codegen-op ? #xfd ? ?)
211 ;;(:verify-op ? #xfe ? ?)
212 ;;(:decode ? #xff ? ?)
218 #+nil(format t "~{ ~x ~}~% "
219 (avm2-asm:assemble '((get-local-0)
220 (push-scope)
221 (return-void))))
222 ;; D0 30 47
225 #+nil
226 (let ((*assembler-context* (make-instance 'assembler-context)))
227 ;; intern some names so the code compiles
228 (avm2-intern "")
229 (avm2-ns-intern "")
230 (qname "a" "b")
231 (qname "b" "b")
232 (qname "c" "b")
233 (qname "d" "b")
234 (qname "e" "b")
235 (format t "~{ ~2,'0x~}~% "
236 (assemble '((:get-local-0)
237 (:push-scope)
238 (:get-local-0)
239 (:construct-super 0)
240 (:find-property-strict 3)
241 (:construct-prop 3 0)
242 (:coerce 3)
243 (:set-local-1)
244 (:get-local-1)
245 (:push-string 7)
246 (:push-string 7)
247 (:add)
248 (:set-property 4)
249 (:find-property-strict 5)
250 (:get-local-1)
251 (:call-prop-void 5 1)
252 (:return-void)))))
253 ;; 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
254 ;; 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
258 #+nil
259 (let ((*assembler-context* (make-instance 'assembler-context)))
260 ;; intern some names so the code compiles
261 (avm2-intern "")
262 (avm2-ns-intern "")
263 (qname "a" "b")
264 (qname "b" "b")
265 (qname "c" "b")
266 (qname "d" "b")
267 (qname "e" "b")
268 (format t "~{ ~2,'0x~}~% "
269 (assemble '((:get-local-0)
270 (:push-scope)
271 (:get-local-0)
272 (:construct-super 0)
273 (:find-property-strict 3)
274 (:construct-prop 3 0)
275 (:coerce 3)
276 (:push-null)
277 (:pop)
278 (:set-local-1)
279 (:get-local-1)
280 (:push-string 7)
281 (:push-string 7)
282 (:add)
283 (:set-property 4)
284 (:find-property-strict 5)
285 (:get-local-1)
286 (:call-prop-void 5 1)
287 (:return-void)))))
289 #+nil
290 (let ((*assembler-context* (make-instance 'assembler-context)))
291 ;; intern some names so the code compiles
292 (avm2-intern "")
293 (avm2-ns-intern "")
294 (qname "a" "b")
295 (qname "b" "b")
296 (qname "c" "b")
297 (qname "d" "b")
298 (qname "e" "b")
299 (format t "~{ ~s~%~}~% "
300 (avm2-disassemble
301 (assemble '((:get-local-0)
302 (:push-scope)
303 (:get-local-0)
304 (:construct-super 0)
305 (:find-property-strict (:id 3))
306 (:construct-prop (:id 3) 0)
307 (:coerce (:id 3))
308 (:push-null)
309 (:pop)
310 (:set-local-1)
311 (:get-local-1)
312 (:push-string "string1")
313 (:push-string "string2")
314 (:add)
315 (:set-property "foo:bar")
316 (:set-property (:qname "foo" "baz"))
317 (:set-property (:id 3))
318 (:find-property-strict "string1")
319 (:get-local-1)
320 (:call-prop-void (:id 5) 1)
321 (:return-void))))))
323 #+nil
324 (format t "~{ ~s~%~}"
325 (avm2-disassemble #(#xD0 #x30 #xD0 #x49 #x00 #x5D #x03 #x4A #x03 #x00
326 #x80 #x03 #xD5 #xD1 #x2C #x07 #x2C #x07 #xA0 #x61
327 #x04 #x5D #x05 #xD1 #x4F #x05 #x01 #x47)))
329 #+nil
330 (format t "~{ #x~2,'0x~}~%"
331 (assemble '( (:GET-LOCAL-0)
332 (:PUSH-SCOPE)
333 (:GET-LOCAL-0)
334 (:CONSTRUCT-SUPER 0)
335 (:FIND-PROPERTY-STRICT (:QNAME "flash.text" ":TextField"))
336 (:CONSTRUCT-PROP (:QNAME "flash.text" ":TextField") 0)
337 (:COERCE (:QNAME "flash.text" ":TextField"))
338 (:SET-LOCAL-1)
339 (:GET-LOCAL-1)
340 (:PUSH-STRING "TextField")
341 (:PUSH-STRING "TextField")
342 (:ADD)
343 (:SET-PROPERTY (:QNAME "" "foo"))
344 (:FIND-PROPERTY-STRICT (:QNAME "flash.text" "TextField"))
345 (:GET-LOCAL-1)
346 (:CALL-PROP-VOID (:QNAME "flash.text" "TextField") 1)
347 (:RETURN-VOID))))
349 #+nil
350 (format t "~{ ~s~%~}"
351 (avm2-disassemble
352 #( #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)