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