]>
Commit | Line | Data |
---|---|---|
58eb6e7c AG |
1 | // interpret.cc - Code for the interpreter |
2 | ||
2ba5f774 | 3 | /* Copyright (C) 1999, 2000 Free Software Foundation |
58eb6e7c AG |
4 | |
5 | This file is part of libgcj. | |
6 | ||
7 | This software is copyrighted work licensed under the terms of the | |
8 | Libgcj License. Please consult the file "LIBGCJ_LICENSE" for | |
9 | details. */ | |
10 | ||
11 | /* Author: Kresten Krab Thorup <krab@gnu.org> */ | |
12 | ||
58eb6e7c AG |
13 | #include <config.h> |
14 | ||
15 | #pragma implementation "java-interp.h" | |
16 | ||
58eb6e7c | 17 | #include <jvm.h> |
58eb6e7c AG |
18 | #include <java-cpool.h> |
19 | #include <java-interp.h> | |
715bdd81 | 20 | // #include <java/lang/fdlibm.h> |
58eb6e7c AG |
21 | #include <java/lang/System.h> |
22 | #include <java/lang/String.h> | |
23 | #include <java/lang/Integer.h> | |
24 | #include <java/lang/StringBuffer.h> | |
58eb6e7c AG |
25 | #include <java/lang/Class.h> |
26 | #include <java/lang/reflect/Modifier.h> | |
27 | #include <java/lang/ClassCastException.h> | |
28 | #include <java/lang/VirtualMachineError.h> | |
29 | #include <java/lang/InternalError.h> | |
30 | #include <java/lang/NullPointerException.h> | |
31 | #include <java/lang/ArithmeticException.h> | |
32 | #include <java/lang/IncompatibleClassChangeError.h> | |
33 | #include <java-insns.h> | |
34 | #include <java-signal.h> | |
58eb6e7c | 35 | |
b099f07d | 36 | #ifdef INTERPRETER |
58eb6e7c AG |
37 | |
38 | #define ClassError _CL_Q34java4lang5Error | |
39 | extern java::lang::Class ClassError; | |
40 | ||
58eb6e7c AG |
41 | static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6); |
42 | ||
43 | static void throw_internal_error (char *msg) | |
44 | __attribute__ ((__noreturn__)); | |
45 | static void throw_incompatible_class_change_error (jstring msg) | |
46 | __attribute__ ((__noreturn__)); | |
715bdd81 | 47 | #ifndef HANDLE_SEGV |
58eb6e7c AG |
48 | static void throw_null_pointer_exception () |
49 | __attribute__ ((__noreturn__)); | |
50 | #endif | |
715bdd81 | 51 | #ifndef HANDLE_FPE |
58eb6e7c AG |
52 | static void throw_arithmetic_exception () |
53 | __attribute__ ((__noreturn__)); | |
54 | #endif | |
55 | ||
56 | ||
715bdd81 AH |
57 | extern "C" double __ieee754_fmod __P((double,double)); |
58 | ||
f7b4fb11 | 59 | static inline void dupx (_Jv_word *sp, int n, int x) |
58eb6e7c AG |
60 | { |
61 | // first "slide" n+x elements n to the right | |
62 | int top = n-1; | |
63 | for (int i = 0; i < n+x; i++) | |
64 | { | |
65 | sp[(top-i)] = sp[(top-i)-n]; | |
66 | } | |
67 | ||
68 | // next, copy the n top elements, n+x down | |
69 | for (int i = 0; i < n; i++) | |
70 | { | |
71 | sp[top-(n+x)-i] = sp[top-i]; | |
72 | } | |
73 | ||
58eb6e7c AG |
74 | }; |
75 | ||
76 | ||
eb4534a6 KKT |
77 | #define PUSHA(V) (sp++)->o = (V) |
78 | #define PUSHI(V) (sp++)->i = (V) | |
79 | #define PUSHF(V) (sp++)->f = (V) | |
7c51d9fb | 80 | #define PUSHL(V) do { _Jv_word2 w2; w2.l=(V); \ |
eb4534a6 | 81 | (sp++)->ia[0] = w2.ia[0]; \ |
7c51d9fb TT |
82 | (sp++)->ia[0] = w2.ia[1]; } while (0) |
83 | #define PUSHD(V) do { _Jv_word2 w2; w2.d=(V); \ | |
eb4534a6 | 84 | (sp++)->ia[0] = w2.ia[0]; \ |
7c51d9fb | 85 | (sp++)->ia[0] = w2.ia[1]; } while (0) |
7941ceab AG |
86 | |
87 | #define POPA() ((--sp)->o) | |
88 | #define POPI() ((jint) (--sp)->i) // cast since it may be promoted | |
89 | #define POPF() ((jfloat) (--sp)->f) | |
eb4534a6 KKT |
90 | #define POPL() ({ _Jv_word2 w2; \ |
91 | w2.ia[1] = (--sp)->ia[0]; \ | |
92 | w2.ia[0] = (--sp)->ia[0]; w2.l; }) | |
93 | #define POPD() ({ _Jv_word2 w2; \ | |
94 | w2.ia[1] = (--sp)->ia[0]; \ | |
95 | w2.ia[0] = (--sp)->ia[0]; w2.d; }) | |
7941ceab AG |
96 | |
97 | #define LOADA(I) (sp++)->o = locals[I].o | |
98 | #define LOADI(I) (sp++)->i = locals[I].i | |
99 | #define LOADF(I) (sp++)->f = locals[I].f | |
7c51d9fb | 100 | #define LOADL(I) do { jint __idx = (I); \ |
7941ceab AG |
101 | (sp++)->ia[0] = locals[__idx].ia[0]; \ |
102 | (sp++)->ia[0] = locals[__idx+1].ia[0]; \ | |
7c51d9fb | 103 | } while (0) |
7941ceab AG |
104 | #define LOADD(I) LOADL(I) |
105 | ||
106 | ||
107 | #define STOREA(I) locals[I].o = (--sp)->o | |
108 | #define STOREI(I) locals[I].i = (--sp)->i | |
109 | #define STOREF(I) locals[I].f = (--sp)->f | |
7c51d9fb | 110 | #define STOREL(I) do { jint __idx = (I); \ |
7941ceab AG |
111 | locals[__idx+1].ia[0] = (--sp)->ia[0]; \ |
112 | locals[__idx].ia[0] = (--sp)->ia[0]; \ | |
7c51d9fb | 113 | } while (0) |
7941ceab AG |
114 | #define STORED(I) STOREL(I) |
115 | ||
116 | #define PEEKI(I) (locals+(I))->i | |
117 | #define PEEKA(I) (locals+(I))->o | |
58eb6e7c | 118 | |
f7b4fb11 | 119 | #define POKEI(I,V) ((locals+(I))->i = (V)) |
58eb6e7c AG |
120 | |
121 | ||
122 | #define BINOPI(OP) { \ | |
123 | jint value2 = POPI(); \ | |
124 | jint value1 = POPI(); \ | |
125 | PUSHI(value1 OP value2); \ | |
126 | } | |
127 | ||
128 | #define BINOPF(OP) { \ | |
129 | jfloat value2 = POPF(); \ | |
130 | jfloat value1 = POPF(); \ | |
131 | PUSHF(value1 OP value2); \ | |
132 | } | |
133 | ||
134 | #define BINOPL(OP) { \ | |
135 | jlong value2 = POPL(); \ | |
136 | jlong value1 = POPL(); \ | |
137 | PUSHL(value1 OP value2); \ | |
138 | } | |
139 | ||
140 | #define BINOPD(OP) { \ | |
141 | jdouble value2 = POPD(); \ | |
142 | jdouble value1 = POPD(); \ | |
143 | PUSHD(value1 OP value2); \ | |
144 | } | |
145 | ||
146 | static inline jint get1s(unsigned char* loc) { | |
147 | return *(signed char*)loc; | |
148 | } | |
149 | ||
150 | static inline jint get1u(unsigned char* loc) { | |
151 | return *loc; | |
152 | } | |
153 | ||
154 | static inline jint get2s(unsigned char* loc) { | |
155 | return (((jint)*(signed char*)loc) << 8) | ((jint)*(loc+1)); | |
156 | } | |
157 | ||
158 | static inline jint get2u(unsigned char* loc) { | |
159 | return (((jint)(*loc)) << 8) | ((jint)*(loc+1)); | |
160 | } | |
161 | ||
162 | static jint get4(unsigned char* loc) { | |
163 | return (((jint)(loc[0])) << 24) | |
164 | | (((jint)(loc[1])) << 16) | |
165 | | (((jint)(loc[2])) << 8) | |
166 | | (((jint)(loc[3])) << 0); | |
167 | } | |
168 | ||
169 | ||
715bdd81 | 170 | #ifdef HANDLE_SEGV |
58eb6e7c AG |
171 | #define NULLCHECK(X) |
172 | #else | |
173 | #define NULLCHECK(X) \ | |
174 | do { if ((X)==NULL) throw_null_pointer_exception (); } while (0) | |
175 | #endif | |
176 | ||
715bdd81 | 177 | #ifdef HANDLE_FPE |
58eb6e7c AG |
178 | #define ZEROCHECK(X) |
179 | #else | |
180 | #define ZEROCHECK(X) \ | |
181 | do { if ((X) == 0) throw_arithmetic_exception (); } while (0) | |
182 | #endif | |
183 | ||
184 | // this method starts the actual running of the method. It is inlined | |
185 | // in three different variants in the static methods run_normal, | |
186 | // run_sync_object and run_sync_class (see below). Those static methods | |
187 | // are installed directly in the stub for this method (by | |
188 | // _Jv_InterpMethod::ncode, in resolve.cc). | |
189 | ||
190 | inline jobject | |
191 | _Jv_InterpMethod::run (ffi_cif* cif, | |
192 | void *retp, | |
7941ceab | 193 | ffi_raw *args, |
58eb6e7c AG |
194 | _Jv_InterpMethodInvocation *inv) |
195 | { | |
196 | inv->running = this; | |
197 | inv->pc = bytecode (); | |
198 | inv->sp = inv->stack_base (); | |
7941ceab | 199 | _Jv_word *locals = inv->local_base (); |
58eb6e7c AG |
200 | |
201 | /* Go straight at it! the ffi raw format matches the internal | |
7941ceab | 202 | stack representation exactly. At leat, that's the idea. |
58eb6e7c AG |
203 | */ |
204 | memcpy ((void*) locals, (void*) args, args_raw_size); | |
205 | ||
206 | next_segment: | |
b099f07d TT |
207 | |
208 | jobject ex = NULL; | |
209 | ||
210 | try | |
211 | { | |
212 | continue1 (inv); | |
213 | } | |
214 | catch (java::lang::Throwable *ex2) | |
215 | { | |
216 | ex = ex2; | |
217 | } | |
58eb6e7c AG |
218 | |
219 | if (ex == 0) // no exception... | |
220 | { | |
221 | /* define sp locally, so the POP? macros will pick it up */ | |
7941ceab | 222 | _Jv_word *sp = inv->sp; |
58eb6e7c AG |
223 | int rtype = cif->rtype->type; |
224 | ||
225 | if (rtype == FFI_TYPE_POINTER) | |
226 | { | |
227 | jobject r = POPA(); | |
228 | *(jobject*) retp = r; | |
229 | return 0; | |
230 | } | |
231 | else if (rtype == FFI_TYPE_SINT32) | |
232 | { | |
233 | jint r = POPI(); | |
234 | *(jint*)retp = r; | |
235 | return 0; | |
236 | } | |
237 | else if (rtype == FFI_TYPE_VOID) | |
238 | { | |
239 | return 0; | |
240 | } | |
241 | else switch (rtype) | |
242 | { | |
243 | case FFI_TYPE_FLOAT: | |
244 | { | |
245 | jfloat r = POPF(); | |
246 | *(jfloat*)retp = r; | |
247 | return 0; | |
248 | } | |
249 | ||
250 | case FFI_TYPE_DOUBLE: | |
251 | { | |
252 | jdouble r = POPD(); | |
253 | *(jdouble*)retp = r; | |
254 | return 0; | |
255 | } | |
256 | ||
257 | case FFI_TYPE_UINT8: | |
258 | case FFI_TYPE_UINT16: | |
259 | case FFI_TYPE_UINT32: | |
260 | case FFI_TYPE_SINT8: | |
261 | case FFI_TYPE_SINT16: | |
262 | { | |
263 | jint r = POPI(); | |
264 | *(jint*)retp = r; | |
265 | return 0; | |
266 | } | |
267 | ||
268 | case FFI_TYPE_SINT64: | |
269 | { | |
270 | jlong r = POPL(); | |
271 | *(jlong*)retp = r; | |
272 | return 0; | |
273 | } | |
274 | ||
275 | default: | |
276 | throw_internal_error ("unknown return type"); | |
277 | } | |
58eb6e7c AG |
278 | } |
279 | ||
280 | /** handle an exception */ | |
281 | if ( find_exception (ex, inv) ) | |
282 | goto next_segment; | |
283 | ||
58eb6e7c AG |
284 | return ex; |
285 | } | |
286 | ||
287 | bool _Jv_InterpMethod::find_exception (jobject ex, | |
288 | _Jv_InterpMethodInvocation *inv) | |
289 | { | |
290 | int logical_pc = inv->pc - bytecode (); | |
291 | _Jv_InterpException *exc = exceptions (); | |
292 | jclass exc_class = ex->getClass (); | |
293 | ||
294 | for (int i = 0; i < exc_count; i++) | |
295 | { | |
296 | if (exc[i].start_pc <= logical_pc && logical_pc < exc[i].end_pc) | |
297 | { | |
298 | jclass handler; | |
299 | ||
300 | if (exc[i].handler_type != 0) | |
7941ceab AG |
301 | handler = (_Jv_ResolvePoolEntry (defining_class, |
302 | exc[i].handler_type)).clazz; | |
58eb6e7c AG |
303 | else |
304 | handler = NULL; | |
305 | ||
306 | if (handler==NULL || handler->isAssignableFrom (exc_class)) | |
307 | { | |
308 | inv->pc = bytecode () + exc[i].handler_pc; | |
309 | inv->sp = inv->stack_base (); // reset stack | |
7941ceab | 310 | (inv->sp++)->o = ex; // push exception |
58eb6e7c AG |
311 | return true; |
312 | } | |
313 | } | |
314 | } | |
315 | return false; | |
316 | } | |
317 | ||
318 | void _Jv_InterpMethod::run_normal (ffi_cif* cif, | |
319 | void* ret, | |
7941ceab | 320 | ffi_raw * args, |
58eb6e7c AG |
321 | void* __this) |
322 | { | |
323 | _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this; | |
324 | ||
325 | // we do the alloca of the method invocation here, to allow the method | |
326 | // "run" ro be inlined. Otherwise gcc will ignore the inline directive. | |
327 | int storage_size = _this->max_stack+_this->max_locals; | |
328 | _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*) | |
329 | alloca (sizeof (_Jv_InterpMethodInvocation) | |
7941ceab | 330 | + storage_size * sizeof (_Jv_word)); |
58eb6e7c AG |
331 | |
332 | jobject ex = _this->run (cif, ret, args, inv); | |
333 | if (ex != 0) _Jv_Throw (ex); | |
334 | } | |
335 | ||
336 | void _Jv_InterpMethod::run_synch_object (ffi_cif* cif, | |
337 | void* ret, | |
7941ceab | 338 | ffi_raw * args, |
58eb6e7c AG |
339 | void* __this) |
340 | { | |
341 | _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this; | |
7941ceab | 342 | jobject rcv = (jobject)args[0].ptr; |
58eb6e7c AG |
343 | |
344 | int storage_size = _this->max_stack+_this->max_locals; | |
345 | _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*) | |
346 | alloca (sizeof (_Jv_InterpMethodInvocation) | |
7941ceab | 347 | + storage_size * sizeof (_Jv_word)); |
58eb6e7c AG |
348 | |
349 | _Jv_MonitorEnter (rcv); | |
350 | jobject ex = _this->run (cif, ret, args, inv); | |
351 | _Jv_MonitorExit (rcv); | |
352 | ||
353 | if (ex != 0) _Jv_Throw (ex); | |
354 | } | |
355 | ||
356 | void _Jv_InterpMethod::run_synch_class (ffi_cif* cif, | |
357 | void* ret, | |
7941ceab | 358 | ffi_raw * args, |
58eb6e7c AG |
359 | void* __this) |
360 | { | |
361 | _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this; | |
362 | jclass sync = _this->defining_class; | |
363 | ||
364 | int storage_size = _this->max_stack+_this->max_locals; | |
365 | _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*) | |
366 | alloca (sizeof (_Jv_InterpMethodInvocation) | |
7941ceab | 367 | + storage_size * sizeof (_Jv_word)); |
58eb6e7c AG |
368 | |
369 | _Jv_MonitorEnter (sync); | |
370 | jobject ex = _this->run (cif, ret, args, inv); | |
371 | _Jv_MonitorExit (sync); | |
372 | ||
373 | if (ex != 0) _Jv_Throw (ex); | |
374 | } | |
375 | ||
58eb6e7c AG |
376 | /* |
377 | This proceeds execution, as designated in "inv". If an exception | |
378 | happens, then it is simply thrown, and handled in Java. Thus, the pc | |
f7b4fb11 | 379 | needs to be stored in the inv->pc at all times, so we can figure |
58eb6e7c AG |
380 | out which handler (if any) to invoke. |
381 | ||
382 | One design issue, which I have not completely considered, is if it | |
383 | should be possible to have interpreted classes linked in! Seldom used | |
384 | (or non-critical) classes could reasonably be interpreted. | |
385 | */ | |
386 | ||
387 | ||
58eb6e7c AG |
388 | void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv) |
389 | { | |
e409a2c8 TT |
390 | using namespace java::lang::reflect; |
391 | ||
74436afa TT |
392 | register _Jv_word *sp = inv->sp; |
393 | register unsigned char *pc = inv->pc; | |
394 | _Jv_word *locals = inv->local_base (); | |
58eb6e7c | 395 | |
7941ceab | 396 | _Jv_word *pool_data = defining_class->constants.data; |
58eb6e7c AG |
397 | |
398 | /* these two are used in the invokeXXX instructions */ | |
399 | void (*fun)(...); | |
400 | _Jv_ResolvedMethod* rmeth; | |
401 | ||
f7b4fb11 KKT |
402 | #define INSN_LABEL(op) &&insn_##op |
403 | #define GOTO_INSN(op) goto *(insn_target[op]) | |
404 | ||
405 | static const void *const insn_target[] = | |
406 | { | |
407 | INSN_LABEL(nop), | |
408 | INSN_LABEL(aconst_null), | |
409 | INSN_LABEL(iconst_m1), | |
410 | INSN_LABEL(iconst_0), | |
411 | INSN_LABEL(iconst_1), | |
412 | INSN_LABEL(iconst_2), | |
413 | INSN_LABEL(iconst_3), | |
414 | INSN_LABEL(iconst_4), | |
415 | INSN_LABEL(iconst_5), | |
416 | INSN_LABEL(lconst_0), | |
417 | INSN_LABEL(lconst_1), | |
418 | INSN_LABEL(fconst_0), | |
419 | INSN_LABEL(fconst_1), | |
420 | INSN_LABEL(fconst_2), | |
421 | INSN_LABEL(dconst_0), | |
422 | INSN_LABEL(dconst_1), | |
423 | INSN_LABEL(bipush), | |
424 | INSN_LABEL(sipush), | |
425 | INSN_LABEL(ldc), | |
426 | INSN_LABEL(ldc_w), | |
427 | INSN_LABEL(ldc2_w), | |
428 | INSN_LABEL(iload), | |
429 | INSN_LABEL(lload), | |
430 | INSN_LABEL(fload), | |
431 | INSN_LABEL(dload), | |
432 | INSN_LABEL(aload), | |
433 | INSN_LABEL(iload_0), | |
434 | INSN_LABEL(iload_1), | |
435 | INSN_LABEL(iload_2), | |
436 | INSN_LABEL(iload_3), | |
437 | INSN_LABEL(lload_0), | |
438 | INSN_LABEL(lload_1), | |
439 | INSN_LABEL(lload_2), | |
440 | INSN_LABEL(lload_3), | |
441 | INSN_LABEL(fload_0), | |
442 | INSN_LABEL(fload_1), | |
443 | INSN_LABEL(fload_2), | |
444 | INSN_LABEL(fload_3), | |
445 | INSN_LABEL(dload_0), | |
446 | INSN_LABEL(dload_1), | |
447 | INSN_LABEL(dload_2), | |
448 | INSN_LABEL(dload_3), | |
449 | INSN_LABEL(aload_0), | |
450 | INSN_LABEL(aload_1), | |
451 | INSN_LABEL(aload_2), | |
452 | INSN_LABEL(aload_3), | |
453 | INSN_LABEL(iaload), | |
454 | INSN_LABEL(laload), | |
455 | INSN_LABEL(faload), | |
456 | INSN_LABEL(daload), | |
457 | INSN_LABEL(aaload), | |
458 | INSN_LABEL(baload), | |
459 | INSN_LABEL(caload), | |
460 | INSN_LABEL(saload), | |
461 | INSN_LABEL(istore), | |
462 | INSN_LABEL(lstore), | |
463 | INSN_LABEL(fstore), | |
464 | INSN_LABEL(dstore), | |
465 | INSN_LABEL(astore), | |
466 | INSN_LABEL(istore_0), | |
467 | INSN_LABEL(istore_1), | |
468 | INSN_LABEL(istore_2), | |
469 | INSN_LABEL(istore_3), | |
470 | INSN_LABEL(lstore_0), | |
471 | INSN_LABEL(lstore_1), | |
472 | INSN_LABEL(lstore_2), | |
473 | INSN_LABEL(lstore_3), | |
474 | INSN_LABEL(fstore_0), | |
475 | INSN_LABEL(fstore_1), | |
476 | INSN_LABEL(fstore_2), | |
477 | INSN_LABEL(fstore_3), | |
478 | INSN_LABEL(dstore_0), | |
479 | INSN_LABEL(dstore_1), | |
480 | INSN_LABEL(dstore_2), | |
481 | INSN_LABEL(dstore_3), | |
482 | INSN_LABEL(astore_0), | |
483 | INSN_LABEL(astore_1), | |
484 | INSN_LABEL(astore_2), | |
485 | INSN_LABEL(astore_3), | |
486 | INSN_LABEL(iastore), | |
487 | INSN_LABEL(lastore), | |
488 | INSN_LABEL(fastore), | |
489 | INSN_LABEL(dastore), | |
490 | INSN_LABEL(aastore), | |
491 | INSN_LABEL(bastore), | |
492 | INSN_LABEL(castore), | |
493 | INSN_LABEL(sastore), | |
494 | INSN_LABEL(pop), | |
495 | INSN_LABEL(pop2), | |
496 | INSN_LABEL(dup), | |
497 | INSN_LABEL(dup_x1), | |
498 | INSN_LABEL(dup_x2), | |
499 | INSN_LABEL(dup2), | |
500 | INSN_LABEL(dup2_x1), | |
501 | INSN_LABEL(dup2_x2), | |
502 | INSN_LABEL(swap), | |
503 | INSN_LABEL(iadd), | |
504 | INSN_LABEL(ladd), | |
505 | INSN_LABEL(fadd), | |
506 | INSN_LABEL(dadd), | |
507 | INSN_LABEL(isub), | |
508 | INSN_LABEL(lsub), | |
509 | INSN_LABEL(fsub), | |
510 | INSN_LABEL(dsub), | |
511 | INSN_LABEL(imul), | |
512 | INSN_LABEL(lmul), | |
513 | INSN_LABEL(fmul), | |
514 | INSN_LABEL(dmul), | |
515 | INSN_LABEL(idiv), | |
516 | INSN_LABEL(ldiv), | |
517 | INSN_LABEL(fdiv), | |
518 | INSN_LABEL(ddiv), | |
519 | INSN_LABEL(irem), | |
520 | INSN_LABEL(lrem), | |
521 | INSN_LABEL(frem), | |
522 | INSN_LABEL(drem), | |
523 | INSN_LABEL(ineg), | |
524 | INSN_LABEL(lneg), | |
525 | INSN_LABEL(fneg), | |
526 | INSN_LABEL(dneg), | |
527 | INSN_LABEL(ishl), | |
528 | INSN_LABEL(lshl), | |
529 | INSN_LABEL(ishr), | |
530 | INSN_LABEL(lshr), | |
531 | INSN_LABEL(iushr), | |
532 | INSN_LABEL(lushr), | |
533 | INSN_LABEL(iand), | |
534 | INSN_LABEL(land), | |
535 | INSN_LABEL(ior), | |
536 | INSN_LABEL(lor), | |
537 | INSN_LABEL(ixor), | |
538 | INSN_LABEL(lxor), | |
539 | INSN_LABEL(iinc), | |
540 | INSN_LABEL(i2l), | |
541 | INSN_LABEL(i2f), | |
542 | INSN_LABEL(i2d), | |
543 | INSN_LABEL(l2i), | |
544 | INSN_LABEL(l2f), | |
545 | INSN_LABEL(l2d), | |
546 | INSN_LABEL(f2i), | |
547 | INSN_LABEL(f2l), | |
548 | INSN_LABEL(f2d), | |
549 | INSN_LABEL(d2i), | |
550 | INSN_LABEL(d2l), | |
551 | INSN_LABEL(d2f), | |
552 | INSN_LABEL(i2b), | |
553 | INSN_LABEL(i2c), | |
554 | INSN_LABEL(i2s), | |
555 | INSN_LABEL(lcmp), | |
556 | INSN_LABEL(fcmpl), | |
557 | INSN_LABEL(fcmpg), | |
558 | INSN_LABEL(dcmpl), | |
559 | INSN_LABEL(dcmpg), | |
560 | INSN_LABEL(ifeq), | |
561 | INSN_LABEL(ifne), | |
562 | INSN_LABEL(iflt), | |
563 | INSN_LABEL(ifge), | |
564 | INSN_LABEL(ifgt), | |
565 | INSN_LABEL(ifle), | |
566 | INSN_LABEL(if_icmpeq), | |
567 | INSN_LABEL(if_icmpne), | |
568 | INSN_LABEL(if_icmplt), | |
569 | INSN_LABEL(if_icmpge), | |
570 | INSN_LABEL(if_icmpgt), | |
571 | INSN_LABEL(if_icmple), | |
572 | INSN_LABEL(if_acmpeq), | |
573 | INSN_LABEL(if_acmpne), | |
574 | INSN_LABEL(goto), | |
575 | INSN_LABEL(jsr), | |
576 | INSN_LABEL(ret), | |
577 | INSN_LABEL(tableswitch), | |
578 | INSN_LABEL(lookupswitch), | |
579 | INSN_LABEL(ireturn), | |
580 | INSN_LABEL(lreturn), | |
581 | INSN_LABEL(freturn), | |
582 | INSN_LABEL(dreturn), | |
583 | INSN_LABEL(areturn), | |
584 | INSN_LABEL(return), | |
585 | INSN_LABEL(getstatic), | |
586 | INSN_LABEL(putstatic), | |
587 | INSN_LABEL(getfield), | |
588 | INSN_LABEL(putfield), | |
589 | INSN_LABEL(invokevirtual), | |
590 | INSN_LABEL(invokespecial), | |
591 | INSN_LABEL(invokestatic), | |
592 | INSN_LABEL(invokeinterface), | |
593 | 0, /* op_xxxunusedxxx1, */ | |
594 | INSN_LABEL(new), | |
595 | INSN_LABEL(newarray), | |
596 | INSN_LABEL(anewarray), | |
597 | INSN_LABEL(arraylength), | |
598 | INSN_LABEL(athrow), | |
599 | INSN_LABEL(checkcast), | |
600 | INSN_LABEL(instanceof), | |
601 | INSN_LABEL(monitorenter), | |
602 | INSN_LABEL(monitorexit), | |
603 | INSN_LABEL(wide), | |
604 | INSN_LABEL(multianewarray), | |
605 | INSN_LABEL(ifnull), | |
606 | INSN_LABEL(ifnonnull), | |
607 | INSN_LABEL(goto_w), | |
608 | INSN_LABEL(jsr_w), | |
f7b4fb11 KKT |
609 | }; |
610 | ||
611 | #define SAVE_PC inv->pc = pc-1 | |
612 | ||
613 | /* If the macro INLINE_SWITCH is not defined, then the main loop | |
614 | operates as one big (normal) switch statement. If it is defined, | |
615 | then the case selection is performed `inline' in the end of the | |
616 | code for each case. The latter saves a native branch instruction | |
617 | for each java-instruction, but expands the code size somewhat. | |
618 | ||
619 | NOTE: On i386 defining INLINE_SWITCH improves over all | |
620 | performance approximately seven percent, but it may be different | |
621 | for other machines. At some point, this may be made into a proper | |
622 | configuration parameter. */ | |
623 | ||
624 | #define INLINE_SWITCH | |
625 | ||
626 | #ifdef INLINE_SWITCH | |
627 | ||
715bdd81 AH |
628 | #define NEXT_INSN do { GOTO_INSN(*pc++); } while (0) |
629 | ||
630 | ||
f7b4fb11 | 631 | NEXT_INSN; |
58eb6e7c AG |
632 | #else |
633 | ||
f7b4fb11 | 634 | #define NEXT_INSN goto next_insn |
58eb6e7c AG |
635 | |
636 | next_insn: | |
f7b4fb11 | 637 | GOTO_INSN (*pc++); |
58eb6e7c AG |
638 | |
639 | #endif | |
58eb6e7c | 640 | |
f7b4fb11 KKT |
641 | /* The first few instructions here are ordered according to their |
642 | frequency, in the hope that this will improve code locality a | |
643 | little. */ | |
644 | ||
645 | insn_aload_0: // 0x2a | |
58eb6e7c | 646 | LOADA(0); |
f7b4fb11 | 647 | NEXT_INSN; |
58eb6e7c | 648 | |
f7b4fb11 | 649 | insn_iload: // 0x15 |
58eb6e7c | 650 | LOADI (get1u (pc++)); |
f7b4fb11 | 651 | NEXT_INSN; |
58eb6e7c | 652 | |
f7b4fb11 | 653 | insn_iload_1: // 0x1b |
58eb6e7c | 654 | LOADI (1); |
f7b4fb11 | 655 | NEXT_INSN; |
58eb6e7c | 656 | |
f7b4fb11 KKT |
657 | insn_invokevirtual: // 0xb6 |
658 | SAVE_PC; | |
58eb6e7c AG |
659 | { |
660 | int index = get2u (pc); pc += 2; | |
661 | ||
662 | /* _Jv_ResolvePoolEntry returns immediately if the value already | |
663 | * is resolved. If we want to clutter up the code here to gain | |
664 | * a little performance, then we can check the corresponding bit | |
665 | * JV_CONSTANT_ResolvedFlag in the tag directly. For now, I | |
666 | * don't think it is worth it. */ | |
667 | ||
7941ceab | 668 | rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod; |
58eb6e7c AG |
669 | |
670 | sp -= rmeth->stack_item_count; | |
671 | NULLCHECK(sp[0]); | |
672 | ||
673 | if (rmeth->vtable_index == -1) | |
674 | { | |
675 | // final methods do not appear in the vtable, | |
676 | // if it does not appear in the superclass. | |
677 | fun = (void (*) (...)) rmeth->method->ncode; | |
678 | } | |
679 | else | |
680 | { | |
7941ceab | 681 | jobject rcv = sp[0].o; |
58eb6e7c AG |
682 | _Jv_VTable *table = *(_Jv_VTable**)rcv; |
683 | fun = (void (*) (...))table->method[rmeth->vtable_index]; | |
684 | } | |
685 | } | |
686 | goto perform_invoke; | |
687 | ||
f7b4fb11 | 688 | perform_invoke: |
58eb6e7c AG |
689 | { |
690 | /* here goes the magic again... */ | |
691 | ffi_cif *cif = &rmeth->cif; | |
7941ceab | 692 | ffi_raw *raw = (ffi_raw*) sp; |
58eb6e7c AG |
693 | |
694 | jdouble rvalue; | |
695 | ||
7941ceab | 696 | ffi_raw_call (cif, fun, (void*)&rvalue, raw); |
58eb6e7c AG |
697 | |
698 | int rtype = cif->rtype->type; | |
699 | ||
700 | /* the likelyhood of object, int, or void return is very high, | |
701 | * so those are checked before the switch */ | |
702 | if (rtype == FFI_TYPE_POINTER) | |
703 | { | |
704 | PUSHA (*(jobject*)&rvalue); | |
705 | } | |
706 | else if (rtype == FFI_TYPE_SINT32) | |
707 | { | |
708 | PUSHI (*(jint*)&rvalue); | |
709 | } | |
710 | else if (rtype == FFI_TYPE_VOID) | |
711 | { | |
712 | /* skip */ | |
713 | } | |
714 | else switch (rtype) | |
715 | { | |
716 | case FFI_TYPE_SINT8: | |
717 | { | |
718 | jbyte value = (*(jint*)&rvalue) & 0xff; | |
719 | PUSHI (value); | |
720 | } | |
721 | break; | |
722 | ||
723 | case FFI_TYPE_SINT16: | |
724 | { | |
725 | jshort value = (*(jint*)&rvalue) & 0xffff; | |
726 | PUSHI (value); | |
727 | } | |
728 | break; | |
729 | ||
730 | case FFI_TYPE_UINT16: | |
731 | { | |
732 | jint value = (*(jint*)&rvalue) & 0xffff; | |
733 | PUSHI (value); | |
734 | } | |
735 | break; | |
736 | ||
737 | case FFI_TYPE_FLOAT: | |
738 | PUSHF (*(jfloat*)&rvalue); | |
739 | break; | |
740 | ||
741 | case FFI_TYPE_DOUBLE: | |
742 | PUSHD (rvalue); | |
743 | break; | |
744 | ||
745 | case FFI_TYPE_SINT64: | |
746 | PUSHL (*(jlong*)&rvalue); | |
747 | break; | |
f7b4fb11 | 748 | |
58eb6e7c AG |
749 | default: |
750 | throw_internal_error ("unknown return type in invokeXXX"); | |
751 | } | |
f7b4fb11 | 752 | |
58eb6e7c | 753 | } |
f7b4fb11 | 754 | NEXT_INSN; |
58eb6e7c AG |
755 | |
756 | ||
f7b4fb11 KKT |
757 | insn_nop: |
758 | NEXT_INSN; | |
58eb6e7c | 759 | |
f7b4fb11 | 760 | insn_aconst_null: |
58eb6e7c | 761 | PUSHA (NULL); |
f7b4fb11 KKT |
762 | NEXT_INSN; |
763 | ||
764 | insn_iconst_m1: | |
765 | PUSHI (-1); | |
766 | NEXT_INSN; | |
767 | ||
768 | insn_iconst_0: | |
769 | PUSHI (0); | |
770 | NEXT_INSN; | |
771 | ||
772 | insn_iconst_1: | |
773 | PUSHI (1); | |
774 | NEXT_INSN; | |
775 | ||
776 | insn_iconst_2: | |
777 | PUSHI (2); | |
778 | NEXT_INSN; | |
779 | ||
780 | insn_iconst_3: | |
781 | PUSHI (3); | |
782 | NEXT_INSN; | |
783 | ||
784 | insn_iconst_4: | |
785 | PUSHI (4); | |
786 | NEXT_INSN; | |
787 | ||
788 | insn_iconst_5: | |
789 | PUSHI (5); | |
790 | NEXT_INSN; | |
791 | ||
792 | insn_lconst_0: | |
793 | PUSHL (0); | |
794 | NEXT_INSN; | |
795 | ||
796 | insn_lconst_1: | |
797 | PUSHL (1); | |
798 | NEXT_INSN; | |
799 | ||
800 | insn_fconst_0: | |
801 | PUSHF (0); | |
802 | NEXT_INSN; | |
803 | ||
804 | insn_fconst_1: | |
805 | PUSHF (1); | |
806 | NEXT_INSN; | |
807 | ||
808 | insn_fconst_2: | |
809 | PUSHF (2); | |
810 | NEXT_INSN; | |
811 | ||
812 | insn_dconst_0: | |
813 | PUSHD (0); | |
814 | NEXT_INSN; | |
815 | ||
816 | insn_dconst_1: | |
817 | PUSHD (1); | |
818 | NEXT_INSN; | |
819 | ||
820 | insn_bipush: | |
58eb6e7c | 821 | PUSHI (get1s(pc++)); |
f7b4fb11 KKT |
822 | NEXT_INSN; |
823 | ||
824 | insn_sipush: | |
58eb6e7c | 825 | PUSHI (get2s(pc)); pc += 2; |
f7b4fb11 | 826 | NEXT_INSN; |
58eb6e7c | 827 | |
f7b4fb11 | 828 | insn_ldc: |
58eb6e7c AG |
829 | { |
830 | int index = get1u (pc++); | |
7941ceab | 831 | PUSHA(pool_data[index].o); |
58eb6e7c | 832 | } |
f7b4fb11 | 833 | NEXT_INSN; |
58eb6e7c | 834 | |
f7b4fb11 | 835 | insn_ldc_w: |
58eb6e7c AG |
836 | { |
837 | int index = get2u (pc); pc += 2; | |
7941ceab | 838 | PUSHA(pool_data[index].o); |
58eb6e7c | 839 | } |
f7b4fb11 | 840 | NEXT_INSN; |
58eb6e7c | 841 | |
f7b4fb11 | 842 | insn_ldc2_w: |
58eb6e7c AG |
843 | { |
844 | int index = get2u (pc); pc += 2; | |
7941ceab | 845 | memcpy (sp, &pool_data[index], 2*sizeof (_Jv_word)); |
58eb6e7c AG |
846 | sp += 2; |
847 | } | |
f7b4fb11 | 848 | NEXT_INSN; |
58eb6e7c | 849 | |
f7b4fb11 | 850 | insn_lload: |
58eb6e7c | 851 | LOADL (get1u (pc++)); |
f7b4fb11 | 852 | NEXT_INSN; |
58eb6e7c | 853 | |
f7b4fb11 | 854 | insn_fload: |
58eb6e7c | 855 | LOADF (get1u (pc++)); |
f7b4fb11 | 856 | NEXT_INSN; |
58eb6e7c | 857 | |
f7b4fb11 | 858 | insn_dload: |
58eb6e7c | 859 | LOADD (get1u (pc++)); |
f7b4fb11 | 860 | NEXT_INSN; |
58eb6e7c | 861 | |
f7b4fb11 | 862 | insn_aload: |
58eb6e7c | 863 | LOADA (get1u (pc++)); |
f7b4fb11 | 864 | NEXT_INSN; |
58eb6e7c | 865 | |
f7b4fb11 | 866 | insn_iload_0: |
58eb6e7c | 867 | LOADI (0); |
f7b4fb11 | 868 | NEXT_INSN; |
58eb6e7c | 869 | |
f7b4fb11 | 870 | insn_iload_2: |
58eb6e7c | 871 | LOADI (2); |
f7b4fb11 | 872 | NEXT_INSN; |
58eb6e7c | 873 | |
f7b4fb11 | 874 | insn_iload_3: |
58eb6e7c | 875 | LOADI (3); |
f7b4fb11 KKT |
876 | NEXT_INSN; |
877 | ||
878 | insn_lload_0: | |
879 | LOADL (0); | |
880 | NEXT_INSN; | |
881 | ||
882 | insn_lload_1: | |
883 | LOADL (1); | |
884 | NEXT_INSN; | |
885 | ||
886 | insn_lload_2: | |
887 | LOADL (2); | |
888 | NEXT_INSN; | |
889 | ||
890 | insn_lload_3: | |
891 | LOADL (3); | |
892 | NEXT_INSN; | |
893 | ||
894 | insn_fload_0: | |
895 | LOADF (0); | |
896 | NEXT_INSN; | |
897 | ||
898 | insn_fload_1: | |
899 | LOADF (1); | |
900 | NEXT_INSN; | |
901 | ||
902 | insn_fload_2: | |
903 | LOADF (2); | |
904 | NEXT_INSN; | |
905 | ||
906 | insn_fload_3: | |
907 | LOADF (3); | |
908 | NEXT_INSN; | |
909 | ||
910 | insn_dload_0: | |
911 | LOADD (0); | |
912 | NEXT_INSN; | |
913 | ||
914 | insn_dload_1: | |
915 | LOADD (1); | |
916 | NEXT_INSN; | |
917 | ||
918 | insn_dload_2: | |
919 | LOADD (2); | |
920 | NEXT_INSN; | |
921 | ||
922 | insn_dload_3: | |
923 | LOADD (3); | |
924 | NEXT_INSN; | |
925 | ||
926 | insn_aload_1: | |
58eb6e7c | 927 | LOADA(1); |
f7b4fb11 | 928 | NEXT_INSN; |
58eb6e7c | 929 | |
f7b4fb11 | 930 | insn_aload_2: |
58eb6e7c | 931 | LOADA(2); |
f7b4fb11 | 932 | NEXT_INSN; |
58eb6e7c | 933 | |
f7b4fb11 | 934 | insn_aload_3: |
58eb6e7c | 935 | LOADA(3); |
f7b4fb11 | 936 | NEXT_INSN; |
58eb6e7c | 937 | |
f7b4fb11 KKT |
938 | insn_iaload: |
939 | SAVE_PC; | |
58eb6e7c AG |
940 | { |
941 | jint index = POPI(); | |
942 | jintArray arr = (jintArray) POPA(); | |
943 | NULLCHECK (arr); | |
944 | if (index < 0 || index >= arr->length) | |
f7b4fb11 | 945 | { |
58eb6e7c AG |
946 | _Jv_ThrowBadArrayIndex (index); |
947 | } | |
948 | PUSHI( elements(arr)[index] ); | |
949 | } | |
f7b4fb11 | 950 | NEXT_INSN; |
58eb6e7c | 951 | |
f7b4fb11 KKT |
952 | insn_laload: |
953 | SAVE_PC; | |
58eb6e7c AG |
954 | { |
955 | jint index = POPI(); | |
956 | jlongArray arr = (jlongArray) POPA(); | |
957 | NULLCHECK (arr); | |
958 | if (index < 0 || index >= arr->length) | |
f7b4fb11 | 959 | { |
58eb6e7c AG |
960 | _Jv_ThrowBadArrayIndex (index); |
961 | } | |
962 | PUSHL( elements(arr)[index] ); | |
963 | } | |
f7b4fb11 | 964 | NEXT_INSN; |
58eb6e7c | 965 | |
f7b4fb11 KKT |
966 | insn_faload: |
967 | SAVE_PC; | |
58eb6e7c AG |
968 | { |
969 | jint index = POPI(); | |
970 | jfloatArray arr = (jfloatArray) POPA(); | |
971 | NULLCHECK (arr); | |
972 | if (index < 0 || index >= arr->length) | |
f7b4fb11 | 973 | { |
58eb6e7c AG |
974 | _Jv_ThrowBadArrayIndex (index); |
975 | } | |
976 | PUSHF( elements(arr)[index] ); | |
977 | } | |
f7b4fb11 | 978 | NEXT_INSN; |
58eb6e7c | 979 | |
f7b4fb11 KKT |
980 | insn_daload: |
981 | SAVE_PC; | |
58eb6e7c AG |
982 | { |
983 | jint index = POPI(); | |
984 | jdoubleArray arr = (jdoubleArray) POPA(); | |
985 | NULLCHECK (arr); | |
986 | if (index < 0 || index >= arr->length) | |
f7b4fb11 | 987 | { |
58eb6e7c AG |
988 | _Jv_ThrowBadArrayIndex (index); |
989 | } | |
990 | PUSHD( elements(arr)[index] ); | |
991 | } | |
f7b4fb11 | 992 | NEXT_INSN; |
58eb6e7c | 993 | |
f7b4fb11 KKT |
994 | insn_aaload: |
995 | SAVE_PC; | |
58eb6e7c AG |
996 | { |
997 | jint index = POPI(); | |
998 | jobjectArray arr = (jobjectArray) POPA(); | |
999 | NULLCHECK (arr); | |
1000 | if (index < 0 || index >= arr->length) | |
f7b4fb11 | 1001 | { |
58eb6e7c AG |
1002 | _Jv_ThrowBadArrayIndex (index); |
1003 | } | |
1004 | PUSHA( elements(arr)[index] ); | |
1005 | } | |
f7b4fb11 | 1006 | NEXT_INSN; |
58eb6e7c | 1007 | |
f7b4fb11 KKT |
1008 | insn_baload: |
1009 | SAVE_PC; | |
58eb6e7c AG |
1010 | { |
1011 | jint index = POPI(); | |
1012 | jbyteArray arr = (jbyteArray) POPA(); | |
1013 | NULLCHECK (arr); | |
1014 | if (index < 0 || index >= arr->length) | |
f7b4fb11 | 1015 | { |
58eb6e7c AG |
1016 | _Jv_ThrowBadArrayIndex (index); |
1017 | } | |
1018 | PUSHI( elements(arr)[index] ); | |
1019 | } | |
f7b4fb11 | 1020 | NEXT_INSN; |
58eb6e7c | 1021 | |
f7b4fb11 KKT |
1022 | insn_caload: |
1023 | SAVE_PC; | |
58eb6e7c AG |
1024 | { |
1025 | jint index = POPI(); | |
1026 | jcharArray arr = (jcharArray) POPA(); | |
1027 | NULLCHECK (arr); | |
1028 | if (index < 0 || index >= arr->length) | |
f7b4fb11 | 1029 | { |
58eb6e7c AG |
1030 | _Jv_ThrowBadArrayIndex (index); |
1031 | } | |
1032 | PUSHI( elements(arr)[index] ); | |
1033 | } | |
f7b4fb11 | 1034 | NEXT_INSN; |
58eb6e7c | 1035 | |
f7b4fb11 KKT |
1036 | insn_saload: |
1037 | SAVE_PC; | |
58eb6e7c AG |
1038 | { |
1039 | jint index = POPI(); | |
1040 | jshortArray arr = (jshortArray) POPA(); | |
1041 | NULLCHECK (arr); | |
1042 | if (index < 0 || index >= arr->length) | |
f7b4fb11 | 1043 | { |
58eb6e7c AG |
1044 | _Jv_ThrowBadArrayIndex (index); |
1045 | } | |
1046 | PUSHI( elements(arr)[index] ); | |
1047 | } | |
f7b4fb11 | 1048 | NEXT_INSN; |
58eb6e7c | 1049 | |
f7b4fb11 | 1050 | insn_istore: |
58eb6e7c | 1051 | STOREI (get1u (pc++)); |
f7b4fb11 | 1052 | NEXT_INSN; |
58eb6e7c | 1053 | |
f7b4fb11 | 1054 | insn_lstore: |
58eb6e7c | 1055 | STOREL (get1u (pc++)); |
f7b4fb11 | 1056 | NEXT_INSN; |
58eb6e7c | 1057 | |
f7b4fb11 | 1058 | insn_fstore: |
58eb6e7c | 1059 | STOREF (get1u (pc++)); |
f7b4fb11 | 1060 | NEXT_INSN; |
58eb6e7c | 1061 | |
f7b4fb11 | 1062 | insn_dstore: |
58eb6e7c | 1063 | STORED (get1u (pc++)); |
f7b4fb11 | 1064 | NEXT_INSN; |
58eb6e7c | 1065 | |
f7b4fb11 | 1066 | insn_astore: |
28ec5077 | 1067 | STOREA (get1u (pc++)); |
f7b4fb11 KKT |
1068 | NEXT_INSN; |
1069 | ||
1070 | insn_istore_0: | |
1071 | STOREI (0); | |
1072 | NEXT_INSN; | |
1073 | ||
1074 | insn_istore_1: | |
1075 | STOREI (1); | |
1076 | NEXT_INSN; | |
1077 | ||
1078 | insn_istore_2: | |
1079 | STOREI (2); | |
1080 | NEXT_INSN; | |
1081 | ||
1082 | insn_istore_3: | |
1083 | STOREI (3); | |
1084 | NEXT_INSN; | |
1085 | ||
1086 | insn_lstore_0: | |
1087 | STOREL (0); | |
1088 | NEXT_INSN; | |
1089 | ||
1090 | insn_lstore_1: | |
1091 | STOREL (1); | |
1092 | NEXT_INSN; | |
1093 | ||
1094 | insn_lstore_2: | |
1095 | STOREL (2); | |
1096 | NEXT_INSN; | |
1097 | ||
1098 | insn_lstore_3: | |
1099 | STOREL (3); | |
1100 | NEXT_INSN; | |
1101 | ||
1102 | insn_fstore_0: | |
1103 | STOREF (0); | |
1104 | NEXT_INSN; | |
1105 | ||
1106 | insn_fstore_1: | |
1107 | STOREF (1); | |
1108 | NEXT_INSN; | |
1109 | ||
1110 | insn_fstore_2: | |
1111 | STOREF (2); | |
1112 | NEXT_INSN; | |
1113 | ||
1114 | insn_fstore_3: | |
1115 | STOREF (3); | |
1116 | NEXT_INSN; | |
1117 | ||
1118 | insn_dstore_0: | |
1119 | STORED (0); | |
1120 | NEXT_INSN; | |
1121 | ||
1122 | insn_dstore_1: | |
1123 | STORED (1); | |
1124 | NEXT_INSN; | |
1125 | ||
1126 | insn_dstore_2: | |
1127 | STORED (2); | |
1128 | NEXT_INSN; | |
1129 | ||
1130 | insn_dstore_3: | |
1131 | STORED (3); | |
1132 | NEXT_INSN; | |
1133 | ||
1134 | insn_astore_0: | |
1135 | STOREA(0); | |
1136 | NEXT_INSN; | |
1137 | ||
1138 | insn_astore_1: | |
1139 | STOREA(1); | |
1140 | NEXT_INSN; | |
1141 | ||
1142 | insn_astore_2: | |
1143 | STOREA(2); | |
1144 | NEXT_INSN; | |
1145 | ||
1146 | insn_astore_3: | |
1147 | STOREA(3); | |
1148 | NEXT_INSN; | |
1149 | ||
1150 | insn_iastore: | |
1151 | SAVE_PC; | |
58eb6e7c AG |
1152 | { |
1153 | jint value = POPI(); | |
1154 | jint index = POPI(); | |
1155 | jintArray arr = (jintArray) POPA(); | |
1156 | NULLCHECK (arr); | |
1157 | if (index < 0 || index >= arr->length) | |
f7b4fb11 | 1158 | { |
58eb6e7c AG |
1159 | _Jv_ThrowBadArrayIndex (index); |
1160 | } | |
1161 | elements(arr)[index] = value; | |
1162 | } | |
f7b4fb11 | 1163 | NEXT_INSN; |
58eb6e7c | 1164 | |
f7b4fb11 KKT |
1165 | insn_lastore: |
1166 | SAVE_PC; | |
58eb6e7c AG |
1167 | { |
1168 | jlong value = POPL(); | |
1169 | jint index = POPI(); | |
1170 | jlongArray arr = (jlongArray) POPA(); | |
1171 | NULLCHECK (arr); | |
1172 | if (index < 0 || index >= arr->length) | |
f7b4fb11 | 1173 | { |
58eb6e7c AG |
1174 | _Jv_ThrowBadArrayIndex (index); |
1175 | } | |
1176 | elements(arr)[index] = value; | |
1177 | } | |
f7b4fb11 | 1178 | NEXT_INSN; |
58eb6e7c | 1179 | |
f7b4fb11 KKT |
1180 | insn_fastore: |
1181 | SAVE_PC; | |
58eb6e7c AG |
1182 | { |
1183 | jfloat value = POPF(); | |
1184 | jint index = POPI(); | |
1185 | jfloatArray arr = (jfloatArray) POPA(); | |
1186 | NULLCHECK (arr); | |
1187 | if (index < 0 || index >= arr->length) | |
f7b4fb11 | 1188 | { |
58eb6e7c AG |
1189 | _Jv_ThrowBadArrayIndex (index); |
1190 | } | |
1191 | elements(arr)[index] = value; | |
1192 | } | |
f7b4fb11 | 1193 | NEXT_INSN; |
58eb6e7c | 1194 | |
f7b4fb11 KKT |
1195 | insn_dastore: |
1196 | SAVE_PC; | |
58eb6e7c AG |
1197 | { |
1198 | jdouble value = POPD(); | |
1199 | jint index = POPI(); | |
1200 | jdoubleArray arr = (jdoubleArray) POPA(); | |
1201 | NULLCHECK (arr); | |
1202 | if (index < 0 || index >= arr->length) | |
f7b4fb11 | 1203 | { |
58eb6e7c AG |
1204 | _Jv_ThrowBadArrayIndex (index); |
1205 | } | |
1206 | elements(arr)[index] = value; | |
1207 | } | |
f7b4fb11 | 1208 | NEXT_INSN; |
58eb6e7c | 1209 | |
f7b4fb11 KKT |
1210 | insn_aastore: |
1211 | SAVE_PC; | |
58eb6e7c AG |
1212 | { |
1213 | jobject value = POPA(); | |
1214 | jint index = POPI(); | |
1215 | jobjectArray arr = (jobjectArray) POPA(); | |
1216 | NULLCHECK (arr); | |
1217 | if (index < 0 || index >= arr->length) | |
f7b4fb11 | 1218 | { |
58eb6e7c AG |
1219 | _Jv_ThrowBadArrayIndex (index); |
1220 | } | |
1221 | _Jv_CheckArrayStore (arr, value); | |
1222 | elements(arr)[index] = value; | |
1223 | } | |
f7b4fb11 | 1224 | NEXT_INSN; |
58eb6e7c | 1225 | |
f7b4fb11 KKT |
1226 | insn_bastore: |
1227 | SAVE_PC; | |
58eb6e7c AG |
1228 | { |
1229 | jbyte value = (jbyte) POPI(); | |
1230 | jint index = POPI(); | |
1231 | jbyteArray arr = (jbyteArray) POPA(); | |
1232 | NULLCHECK (arr); | |
1233 | if (index < 0 || index >= arr->length) | |
f7b4fb11 | 1234 | { |
58eb6e7c AG |
1235 | _Jv_ThrowBadArrayIndex (index); |
1236 | } | |
1237 | elements(arr)[index] = value; | |
1238 | } | |
f7b4fb11 | 1239 | NEXT_INSN; |
58eb6e7c | 1240 | |
f7b4fb11 KKT |
1241 | insn_castore: |
1242 | SAVE_PC; | |
58eb6e7c AG |
1243 | { |
1244 | jchar value = (jchar) POPI(); | |
1245 | jint index = POPI(); | |
1246 | jcharArray arr = (jcharArray) POPA(); | |
1247 | NULLCHECK (arr); | |
1248 | if (index < 0 || index >= arr->length) | |
f7b4fb11 | 1249 | { |
58eb6e7c AG |
1250 | _Jv_ThrowBadArrayIndex (index); |
1251 | } | |
1252 | elements(arr)[index] = value; | |
1253 | } | |
f7b4fb11 | 1254 | NEXT_INSN; |
58eb6e7c | 1255 | |
f7b4fb11 KKT |
1256 | insn_sastore: |
1257 | SAVE_PC; | |
58eb6e7c AG |
1258 | { |
1259 | jshort value = (jshort) POPI(); | |
1260 | jint index = POPI(); | |
1261 | jshortArray arr = (jshortArray) POPA(); | |
1262 | NULLCHECK (arr); | |
1263 | if (index < 0 || index >= arr->length) | |
f7b4fb11 | 1264 | { |
58eb6e7c AG |
1265 | _Jv_ThrowBadArrayIndex (index); |
1266 | } | |
1267 | elements(arr)[index] = value; | |
1268 | } | |
f7b4fb11 | 1269 | NEXT_INSN; |
58eb6e7c | 1270 | |
f7b4fb11 | 1271 | insn_pop: |
58eb6e7c | 1272 | sp -= 1; |
f7b4fb11 | 1273 | NEXT_INSN; |
58eb6e7c | 1274 | |
f7b4fb11 | 1275 | insn_pop2: |
58eb6e7c | 1276 | sp -= 2; |
f7b4fb11 | 1277 | NEXT_INSN; |
58eb6e7c | 1278 | |
f7b4fb11 | 1279 | insn_dup: |
58eb6e7c AG |
1280 | sp[0] = sp[-1]; |
1281 | sp += 1; | |
f7b4fb11 | 1282 | NEXT_INSN; |
58eb6e7c | 1283 | |
f7b4fb11 KKT |
1284 | insn_dup_x1: |
1285 | dupx (sp, 1, 1); sp+=1; | |
1286 | NEXT_INSN; | |
58eb6e7c | 1287 | |
f7b4fb11 KKT |
1288 | insn_dup_x2: |
1289 | dupx (sp, 1, 2); sp+=1; | |
1290 | NEXT_INSN; | |
58eb6e7c | 1291 | |
f7b4fb11 | 1292 | insn_dup2: |
58eb6e7c AG |
1293 | sp[0] = sp[-2]; |
1294 | sp[1] = sp[-1]; | |
1295 | sp += 2; | |
f7b4fb11 | 1296 | NEXT_INSN; |
58eb6e7c | 1297 | |
f7b4fb11 KKT |
1298 | insn_dup2_x1: |
1299 | dupx (sp, 2, 1); sp+=2; | |
1300 | NEXT_INSN; | |
58eb6e7c | 1301 | |
f7b4fb11 KKT |
1302 | insn_dup2_x2: |
1303 | dupx (sp, 2, 2); sp+=2; | |
1304 | NEXT_INSN; | |
58eb6e7c | 1305 | |
f7b4fb11 | 1306 | insn_swap: |
58eb6e7c AG |
1307 | { |
1308 | jobject tmp1 = POPA(); | |
1309 | jobject tmp2 = POPA(); | |
1310 | PUSHA (tmp1); | |
1311 | PUSHA (tmp2); | |
1312 | } | |
f7b4fb11 | 1313 | NEXT_INSN; |
58eb6e7c | 1314 | |
f7b4fb11 | 1315 | insn_iadd: |
58eb6e7c | 1316 | BINOPI(+); |
f7b4fb11 | 1317 | NEXT_INSN; |
58eb6e7c | 1318 | |
f7b4fb11 | 1319 | insn_ladd: |
58eb6e7c | 1320 | BINOPL(+); |
f7b4fb11 | 1321 | NEXT_INSN; |
58eb6e7c | 1322 | |
f7b4fb11 | 1323 | insn_fadd: |
58eb6e7c | 1324 | BINOPF(+); |
f7b4fb11 | 1325 | NEXT_INSN; |
58eb6e7c | 1326 | |
f7b4fb11 | 1327 | insn_dadd: |
58eb6e7c | 1328 | BINOPD(+); |
f7b4fb11 | 1329 | NEXT_INSN; |
58eb6e7c | 1330 | |
f7b4fb11 | 1331 | insn_isub: |
58eb6e7c | 1332 | BINOPI(-); |
f7b4fb11 | 1333 | NEXT_INSN; |
58eb6e7c | 1334 | |
f7b4fb11 | 1335 | insn_lsub: |
58eb6e7c | 1336 | BINOPL(-); |
f7b4fb11 | 1337 | NEXT_INSN; |
58eb6e7c | 1338 | |
f7b4fb11 | 1339 | insn_fsub: |
58eb6e7c | 1340 | BINOPF(-); |
f7b4fb11 | 1341 | NEXT_INSN; |
58eb6e7c | 1342 | |
f7b4fb11 | 1343 | insn_dsub: |
58eb6e7c | 1344 | BINOPD(-); |
f7b4fb11 | 1345 | NEXT_INSN; |
58eb6e7c | 1346 | |
f7b4fb11 | 1347 | insn_imul: |
58eb6e7c | 1348 | BINOPI(*); |
f7b4fb11 | 1349 | NEXT_INSN; |
58eb6e7c | 1350 | |
f7b4fb11 | 1351 | insn_lmul: |
58eb6e7c | 1352 | BINOPL(*); |
f7b4fb11 | 1353 | NEXT_INSN; |
58eb6e7c | 1354 | |
f7b4fb11 | 1355 | insn_fmul: |
58eb6e7c | 1356 | BINOPF(*); |
f7b4fb11 | 1357 | NEXT_INSN; |
58eb6e7c | 1358 | |
f7b4fb11 | 1359 | insn_dmul: |
58eb6e7c | 1360 | BINOPD(*); |
f7b4fb11 | 1361 | NEXT_INSN; |
58eb6e7c | 1362 | |
f7b4fb11 KKT |
1363 | insn_idiv: |
1364 | SAVE_PC; | |
58eb6e7c AG |
1365 | { |
1366 | jint value2 = POPI(); | |
1367 | jint value1 = POPI(); | |
1368 | ZEROCHECK (value2); | |
1369 | jint res = value1 / value2; | |
1370 | PUSHI (res); | |
1371 | } | |
f7b4fb11 | 1372 | NEXT_INSN; |
58eb6e7c | 1373 | |
f7b4fb11 KKT |
1374 | insn_ldiv: |
1375 | SAVE_PC; | |
1376 | { | |
58eb6e7c AG |
1377 | jlong value2 = POPL(); |
1378 | jlong value1 = POPL(); | |
1379 | ZEROCHECK (value2); | |
1380 | jlong res = value1 / value2; | |
1381 | PUSHL (res); | |
1382 | } | |
f7b4fb11 | 1383 | NEXT_INSN; |
58eb6e7c | 1384 | |
f7b4fb11 KKT |
1385 | insn_fdiv: |
1386 | SAVE_PC; | |
58eb6e7c AG |
1387 | { |
1388 | jfloat value2 = POPF(); | |
1389 | jfloat value1 = POPF(); | |
1390 | ZEROCHECK (value2); | |
1391 | jfloat res = value1 / value2; | |
1392 | PUSHF (res); | |
1393 | } | |
f7b4fb11 | 1394 | NEXT_INSN; |
58eb6e7c | 1395 | |
f7b4fb11 KKT |
1396 | insn_ddiv: |
1397 | SAVE_PC; | |
58eb6e7c AG |
1398 | { |
1399 | jdouble value2 = POPD(); | |
1400 | jdouble value1 = POPD(); | |
1401 | ZEROCHECK (value2); | |
1402 | jdouble res = value1 / value2; | |
1403 | PUSHD (res); | |
1404 | } | |
f7b4fb11 | 1405 | NEXT_INSN; |
58eb6e7c | 1406 | |
f7b4fb11 KKT |
1407 | insn_irem: |
1408 | SAVE_PC; | |
58eb6e7c AG |
1409 | { |
1410 | jint value2 = POPI(); | |
1411 | jint value1 = POPI(); | |
1412 | ZEROCHECK (value2); | |
1413 | jint res = value1 % value2; | |
1414 | PUSHI (res); | |
1415 | } | |
f7b4fb11 | 1416 | NEXT_INSN; |
58eb6e7c | 1417 | |
f7b4fb11 KKT |
1418 | insn_lrem: |
1419 | SAVE_PC; | |
1420 | { | |
58eb6e7c AG |
1421 | jlong value2 = POPL(); |
1422 | jlong value1 = POPL(); | |
1423 | ZEROCHECK (value2); | |
1424 | jlong res = value1 % value2; | |
1425 | PUSHL (res); | |
1426 | } | |
f7b4fb11 | 1427 | NEXT_INSN; |
58eb6e7c | 1428 | |
f7b4fb11 KKT |
1429 | insn_frem: |
1430 | SAVE_PC; | |
58eb6e7c AG |
1431 | { |
1432 | jfloat value2 = POPF(); | |
1433 | jfloat value1 = POPF(); | |
1434 | ZEROCHECK (value2); | |
1435 | jfloat res = __ieee754_fmod (value1, value2); | |
1436 | PUSHF (res); | |
1437 | } | |
f7b4fb11 | 1438 | NEXT_INSN; |
58eb6e7c | 1439 | |
f7b4fb11 KKT |
1440 | insn_drem: |
1441 | SAVE_PC; | |
58eb6e7c AG |
1442 | { |
1443 | jdouble value2 = POPD(); | |
1444 | jdouble value1 = POPD(); | |
1445 | ZEROCHECK (value2); | |
1446 | jdouble res = __ieee754_fmod (value1, value2); | |
1447 | PUSHD (res); | |
1448 | } | |
f7b4fb11 | 1449 | NEXT_INSN; |
58eb6e7c | 1450 | |
f7b4fb11 KKT |
1451 | insn_ineg: |
1452 | { | |
1453 | jint value = POPI(); | |
1454 | PUSHI (value * -1); | |
1455 | } | |
1456 | NEXT_INSN; | |
58eb6e7c | 1457 | |
f7b4fb11 KKT |
1458 | insn_lneg: |
1459 | { | |
1460 | jlong value = POPL(); | |
1461 | PUSHL (value * -1); | |
1462 | } | |
1463 | NEXT_INSN; | |
58eb6e7c | 1464 | |
f7b4fb11 KKT |
1465 | insn_fneg: |
1466 | { | |
1467 | jfloat value = POPF(); | |
1468 | PUSHF (value * -1); | |
1469 | } | |
1470 | NEXT_INSN; | |
58eb6e7c | 1471 | |
f7b4fb11 KKT |
1472 | insn_dneg: |
1473 | { | |
1474 | jdouble value = POPD(); | |
1475 | PUSHD (value * -1); | |
1476 | } | |
1477 | NEXT_INSN; | |
58eb6e7c | 1478 | |
f7b4fb11 | 1479 | insn_ishl: |
58eb6e7c AG |
1480 | { |
1481 | jint shift = (POPI() & 0x1f); | |
1482 | jint value = POPI(); | |
1483 | PUSHI (value << shift); | |
1484 | } | |
f7b4fb11 | 1485 | NEXT_INSN; |
58eb6e7c | 1486 | |
f7b4fb11 | 1487 | insn_lshl: |
58eb6e7c AG |
1488 | { |
1489 | jint shift = (POPI() & 0x3f); | |
1490 | jlong value = POPL(); | |
1491 | PUSHL (value << shift); | |
1492 | } | |
f7b4fb11 | 1493 | NEXT_INSN; |
58eb6e7c | 1494 | |
f7b4fb11 | 1495 | insn_ishr: |
58eb6e7c AG |
1496 | { |
1497 | jint shift = (POPI() & 0x1f); | |
1498 | jint value = POPI(); | |
1499 | PUSHI (value >> shift); | |
1500 | } | |
f7b4fb11 | 1501 | NEXT_INSN; |
58eb6e7c | 1502 | |
f7b4fb11 | 1503 | insn_lshr: |
58eb6e7c AG |
1504 | { |
1505 | jint shift = (POPI() & 0x3f); | |
1506 | jlong value = POPL(); | |
1507 | PUSHL (value >> shift); | |
1508 | } | |
f7b4fb11 | 1509 | NEXT_INSN; |
58eb6e7c | 1510 | |
f7b4fb11 | 1511 | insn_iushr: |
58eb6e7c AG |
1512 | { |
1513 | jint shift = (POPI() & 0x1f); | |
1514 | unsigned long value = POPI(); | |
1515 | PUSHI ((jint) (value >> shift)); | |
1516 | } | |
f7b4fb11 | 1517 | NEXT_INSN; |
58eb6e7c | 1518 | |
f7b4fb11 | 1519 | insn_lushr: |
58eb6e7c AG |
1520 | { |
1521 | jint shift = (POPI() & 0x3f); | |
1522 | UINT64 value = (UINT64) POPL(); | |
1523 | PUSHL ((value >> shift)); | |
1524 | } | |
f7b4fb11 | 1525 | NEXT_INSN; |
58eb6e7c | 1526 | |
f7b4fb11 | 1527 | insn_iand: |
58eb6e7c | 1528 | BINOPI (&); |
f7b4fb11 | 1529 | NEXT_INSN; |
58eb6e7c | 1530 | |
f7b4fb11 | 1531 | insn_land: |
58eb6e7c | 1532 | BINOPL (&); |
f7b4fb11 | 1533 | NEXT_INSN; |
58eb6e7c | 1534 | |
f7b4fb11 | 1535 | insn_ior: |
58eb6e7c | 1536 | BINOPI (|); |
f7b4fb11 | 1537 | NEXT_INSN; |
58eb6e7c | 1538 | |
f7b4fb11 | 1539 | insn_lor: |
58eb6e7c | 1540 | BINOPL (|); |
f7b4fb11 | 1541 | NEXT_INSN; |
58eb6e7c | 1542 | |
f7b4fb11 | 1543 | insn_ixor: |
58eb6e7c | 1544 | BINOPI (^); |
f7b4fb11 | 1545 | NEXT_INSN; |
58eb6e7c | 1546 | |
f7b4fb11 | 1547 | insn_lxor: |
58eb6e7c | 1548 | BINOPL (^); |
f7b4fb11 | 1549 | NEXT_INSN; |
58eb6e7c | 1550 | |
f7b4fb11 | 1551 | insn_iinc: |
58eb6e7c AG |
1552 | { |
1553 | jint index = get1u (pc++); | |
1554 | jint amount = get1s (pc++); | |
f7b4fb11 | 1555 | locals[index].i += amount; |
58eb6e7c | 1556 | } |
f7b4fb11 | 1557 | NEXT_INSN; |
58eb6e7c | 1558 | |
f7b4fb11 | 1559 | insn_i2l: |
eb4534a6 | 1560 | {jlong value = POPI(); PUSHL (value);} |
f7b4fb11 | 1561 | NEXT_INSN; |
58eb6e7c | 1562 | |
f7b4fb11 | 1563 | insn_i2f: |
eb4534a6 | 1564 | {jfloat value = POPI(); PUSHF (value);} |
f7b4fb11 | 1565 | NEXT_INSN; |
58eb6e7c | 1566 | |
f7b4fb11 | 1567 | insn_i2d: |
eb4534a6 | 1568 | {jdouble value = POPI(); PUSHD (value);} |
f7b4fb11 | 1569 | NEXT_INSN; |
58eb6e7c | 1570 | |
f7b4fb11 | 1571 | insn_l2i: |
eb4534a6 | 1572 | {jint value = POPL(); PUSHI (value);} |
f7b4fb11 | 1573 | NEXT_INSN; |
58eb6e7c | 1574 | |
f7b4fb11 | 1575 | insn_l2f: |
eb4534a6 | 1576 | {jfloat value = POPL(); PUSHF (value);} |
f7b4fb11 | 1577 | NEXT_INSN; |
58eb6e7c | 1578 | |
f7b4fb11 | 1579 | insn_l2d: |
eb4534a6 | 1580 | {jdouble value = POPL(); PUSHD (value);} |
f7b4fb11 | 1581 | NEXT_INSN; |
58eb6e7c | 1582 | |
f7b4fb11 | 1583 | insn_f2i: |
eb4534a6 | 1584 | { jint value = (jint)POPF (); PUSHI(value); } |
f7b4fb11 | 1585 | NEXT_INSN; |
58eb6e7c | 1586 | |
f7b4fb11 | 1587 | insn_f2l: |
eb4534a6 | 1588 | { jlong value = (jlong)POPF (); PUSHL(value); } |
f7b4fb11 | 1589 | NEXT_INSN; |
58eb6e7c | 1590 | |
f7b4fb11 | 1591 | insn_f2d: |
eb4534a6 | 1592 | { jdouble value = POPF (); PUSHD(value); } |
f7b4fb11 | 1593 | NEXT_INSN; |
58eb6e7c | 1594 | |
f7b4fb11 | 1595 | insn_d2i: |
eb4534a6 | 1596 | { jint value = (jint)POPD (); PUSHI(value); } |
f7b4fb11 | 1597 | NEXT_INSN; |
58eb6e7c | 1598 | |
f7b4fb11 | 1599 | insn_d2l: |
eb4534a6 | 1600 | { jlong value = (jlong)POPD (); PUSHL(value); } |
f7b4fb11 | 1601 | NEXT_INSN; |
58eb6e7c | 1602 | |
f7b4fb11 | 1603 | insn_d2f: |
eb4534a6 | 1604 | { jfloat value = POPD (); PUSHF(value); } |
f7b4fb11 | 1605 | NEXT_INSN; |
58eb6e7c | 1606 | |
f7b4fb11 | 1607 | insn_i2b: |
eb4534a6 | 1608 | { jbyte value = POPI (); PUSHI(value); } |
f7b4fb11 | 1609 | NEXT_INSN; |
58eb6e7c | 1610 | |
f7b4fb11 | 1611 | insn_i2c: |
eb4534a6 | 1612 | { jchar value = POPI (); PUSHI(value); } |
f7b4fb11 | 1613 | NEXT_INSN; |
58eb6e7c | 1614 | |
f7b4fb11 | 1615 | insn_i2s: |
eb4534a6 | 1616 | { jshort value = POPI (); PUSHI(value); } |
f7b4fb11 | 1617 | NEXT_INSN; |
58eb6e7c | 1618 | |
f7b4fb11 | 1619 | insn_lcmp: |
58eb6e7c AG |
1620 | { |
1621 | jlong value2 = POPL (); | |
1622 | jlong value1 = POPL (); | |
1623 | if (value1 > value2) | |
1624 | { PUSHI (1); } | |
1625 | else if (value1 == value2) | |
1626 | { PUSHI (0); } | |
1627 | else | |
1628 | { PUSHI (-1); } | |
1629 | } | |
f7b4fb11 | 1630 | NEXT_INSN; |
58eb6e7c | 1631 | |
f7b4fb11 KKT |
1632 | insn_fcmpl: |
1633 | insn_fcmpg: | |
58eb6e7c AG |
1634 | { |
1635 | jfloat value2 = POPF (); | |
1636 | jfloat value1 = POPF (); | |
1637 | if (value1 > value2) | |
1638 | PUSHI (1); | |
1639 | else if (value1 == value2) | |
1640 | PUSHI (0); | |
1641 | else if (value1 < value2) | |
1642 | PUSHI (-1); | |
f7b4fb11 | 1643 | else if ((*(pc-1)) == op_fcmpg) |
58eb6e7c AG |
1644 | PUSHI (1); |
1645 | else | |
1646 | PUSHI (-1); | |
1647 | } | |
f7b4fb11 | 1648 | NEXT_INSN; |
58eb6e7c | 1649 | |
f7b4fb11 KKT |
1650 | insn_dcmpl: |
1651 | insn_dcmpg: | |
58eb6e7c AG |
1652 | { |
1653 | jdouble value2 = POPD (); | |
1654 | jdouble value1 = POPD (); | |
1655 | if (value1 > value2) | |
1656 | PUSHI (1); | |
1657 | else if (value1 == value2) | |
1658 | PUSHI (0); | |
1659 | else if (value1 < value2) | |
1660 | PUSHI (-1); | |
f7b4fb11 | 1661 | else if ((*(pc-1)) == op_dcmpg) |
58eb6e7c AG |
1662 | PUSHI (1); |
1663 | else | |
1664 | PUSHI (-1); | |
1665 | } | |
f7b4fb11 | 1666 | NEXT_INSN; |
58eb6e7c | 1667 | |
f7b4fb11 | 1668 | insn_ifeq: |
58eb6e7c AG |
1669 | { |
1670 | jint offset = get2s (pc); | |
1671 | if (POPI() == 0) | |
1672 | pc = pc-1+offset; | |
1673 | else | |
1674 | pc = pc+2; | |
1675 | } | |
f7b4fb11 | 1676 | NEXT_INSN; |
58eb6e7c | 1677 | |
f7b4fb11 | 1678 | insn_ifne: |
58eb6e7c AG |
1679 | { |
1680 | jint offset = get2s (pc); | |
1681 | if (POPI() != 0) | |
1682 | pc = pc-1+offset; | |
1683 | else | |
1684 | pc = pc+2; | |
1685 | } | |
f7b4fb11 | 1686 | NEXT_INSN; |
58eb6e7c | 1687 | |
f7b4fb11 | 1688 | insn_iflt: |
58eb6e7c AG |
1689 | { |
1690 | jint offset = get2s (pc); | |
1691 | if (POPI() < 0) | |
1692 | pc = pc-1+offset; | |
1693 | else | |
1694 | pc = pc+2; | |
1695 | } | |
f7b4fb11 | 1696 | NEXT_INSN; |
58eb6e7c | 1697 | |
f7b4fb11 | 1698 | insn_ifge: |
58eb6e7c AG |
1699 | { |
1700 | jint offset = get2s (pc); | |
1701 | if (POPI() >= 0) | |
1702 | pc = pc-1+offset; | |
1703 | else | |
1704 | pc = pc+2; | |
1705 | } | |
f7b4fb11 | 1706 | NEXT_INSN; |
58eb6e7c | 1707 | |
f7b4fb11 | 1708 | insn_ifgt: |
58eb6e7c AG |
1709 | { |
1710 | jint offset = get2s (pc); | |
1711 | if (POPI() > 0) | |
1712 | pc = pc-1+offset; | |
1713 | else | |
1714 | pc = pc+2; | |
1715 | } | |
f7b4fb11 | 1716 | NEXT_INSN; |
58eb6e7c | 1717 | |
f7b4fb11 | 1718 | insn_ifle: |
58eb6e7c AG |
1719 | { |
1720 | jint offset = get2s (pc); | |
1721 | if (POPI() <= 0) | |
1722 | pc = pc-1+offset; | |
1723 | else | |
1724 | pc = pc+2; | |
1725 | } | |
f7b4fb11 | 1726 | NEXT_INSN; |
58eb6e7c | 1727 | |
f7b4fb11 | 1728 | insn_if_icmpeq: |
58eb6e7c AG |
1729 | { |
1730 | jint offset = get2s (pc); | |
1731 | jint value2 = POPI(); | |
1732 | jint value1 = POPI(); | |
1733 | if (value1 == value2) | |
1734 | pc = pc-1+offset; | |
1735 | else | |
1736 | pc = pc+2; | |
1737 | } | |
f7b4fb11 | 1738 | NEXT_INSN; |
58eb6e7c | 1739 | |
f7b4fb11 | 1740 | insn_if_icmpne: |
58eb6e7c AG |
1741 | { |
1742 | jint offset = get2s (pc); | |
1743 | jint value2 = POPI(); | |
1744 | jint value1 = POPI(); | |
1745 | if (value1 != value2) | |
1746 | pc = pc-1+offset; | |
1747 | else | |
1748 | pc = pc+2; | |
1749 | } | |
f7b4fb11 | 1750 | NEXT_INSN; |
58eb6e7c | 1751 | |
f7b4fb11 | 1752 | insn_if_icmplt: |
58eb6e7c AG |
1753 | { |
1754 | jint offset = get2s (pc); | |
1755 | jint value2 = POPI(); | |
1756 | jint value1 = POPI(); | |
1757 | if (value1 < value2) | |
1758 | pc = pc-1+offset; | |
1759 | else | |
1760 | pc = pc+2; | |
1761 | } | |
f7b4fb11 | 1762 | NEXT_INSN; |
58eb6e7c | 1763 | |
f7b4fb11 | 1764 | insn_if_icmpge: |
58eb6e7c AG |
1765 | { |
1766 | jint offset = get2s (pc); | |
1767 | jint value2 = POPI(); | |
1768 | jint value1 = POPI(); | |
1769 | if (value1 >= value2) | |
1770 | pc = pc-1+offset; | |
1771 | else | |
1772 | pc = pc+2; | |
1773 | } | |
f7b4fb11 | 1774 | NEXT_INSN; |
58eb6e7c | 1775 | |
f7b4fb11 | 1776 | insn_if_icmpgt: |
58eb6e7c AG |
1777 | { |
1778 | jint offset = get2s (pc); | |
1779 | jint value2 = POPI(); | |
1780 | jint value1 = POPI(); | |
1781 | if (value1 > value2) | |
1782 | pc = pc-1+offset; | |
1783 | else | |
1784 | pc = pc+2; | |
1785 | } | |
f7b4fb11 | 1786 | NEXT_INSN; |
58eb6e7c | 1787 | |
f7b4fb11 | 1788 | insn_if_icmple: |
58eb6e7c AG |
1789 | { |
1790 | jint offset = get2s (pc); | |
1791 | jint value2 = POPI(); | |
1792 | jint value1 = POPI(); | |
1793 | if (value1 <= value2) | |
1794 | pc = pc-1+offset; | |
1795 | else | |
1796 | pc = pc+2; | |
1797 | } | |
f7b4fb11 | 1798 | NEXT_INSN; |
58eb6e7c | 1799 | |
f7b4fb11 | 1800 | insn_if_acmpeq: |
58eb6e7c AG |
1801 | { |
1802 | jint offset = get2s (pc); | |
1803 | jobject value2 = POPA(); | |
1804 | jobject value1 = POPA(); | |
1805 | if (value1 == value2) | |
1806 | pc = pc-1+offset; | |
1807 | else | |
1808 | pc = pc+2; | |
1809 | } | |
f7b4fb11 | 1810 | NEXT_INSN; |
58eb6e7c | 1811 | |
f7b4fb11 | 1812 | insn_if_acmpne: |
58eb6e7c AG |
1813 | { |
1814 | jint offset = get2s (pc); | |
1815 | jobject value2 = POPA(); | |
1816 | jobject value1 = POPA(); | |
1817 | if (value1 != value2) | |
1818 | pc = pc-1+offset; | |
1819 | else | |
1820 | pc = pc+2; | |
1821 | } | |
f7b4fb11 | 1822 | NEXT_INSN; |
58eb6e7c | 1823 | |
f7b4fb11 | 1824 | insn_goto: |
58eb6e7c AG |
1825 | { |
1826 | jint offset = get2s (pc); | |
1827 | pc = pc-1+offset; | |
1828 | } | |
f7b4fb11 | 1829 | NEXT_INSN; |
58eb6e7c | 1830 | |
f7b4fb11 | 1831 | insn_jsr: |
58eb6e7c AG |
1832 | { |
1833 | unsigned char *base_pc = pc-1; | |
1834 | jint offset = get2s (pc); pc += 2; | |
1835 | PUSHA ((jobject)pc); | |
1836 | pc = base_pc+offset; | |
1837 | } | |
f7b4fb11 | 1838 | NEXT_INSN; |
58eb6e7c | 1839 | |
f7b4fb11 | 1840 | insn_ret: |
58eb6e7c AG |
1841 | { |
1842 | jint index = get1u (pc); | |
1843 | pc = (unsigned char*) PEEKA (index); | |
1844 | } | |
f7b4fb11 | 1845 | NEXT_INSN; |
58eb6e7c | 1846 | |
f7b4fb11 | 1847 | insn_tableswitch: |
58eb6e7c AG |
1848 | { |
1849 | unsigned char *base_pc = pc-1; | |
1850 | int index = POPI(); | |
f7b4fb11 | 1851 | |
58eb6e7c AG |
1852 | unsigned char* base = bytecode (); |
1853 | while ((pc-base) % 4 != 0) | |
1854 | pc++; | |
1855 | ||
1856 | jint def = get4 (pc); | |
1857 | jint low = get4 (pc+4); | |
1858 | jint high = get4 (pc+8); | |
1859 | ||
1860 | if (index < low || index > high) | |
1861 | pc = base_pc + def; | |
1862 | else | |
1863 | pc = base_pc + get4 (pc+4*(index-low+3)); | |
1864 | } | |
f7b4fb11 | 1865 | NEXT_INSN; |
58eb6e7c | 1866 | |
f7b4fb11 | 1867 | insn_lookupswitch: |
58eb6e7c AG |
1868 | { |
1869 | unsigned char *base_pc = pc-1; | |
1870 | int index = POPI(); | |
f7b4fb11 | 1871 | |
58eb6e7c AG |
1872 | unsigned char* base = bytecode (); |
1873 | while ((pc-base) % 4 != 0) | |
1874 | pc++; | |
f7b4fb11 | 1875 | |
58eb6e7c AG |
1876 | jint def = get4 (pc); |
1877 | jint npairs = get4 (pc+4); | |
f7b4fb11 | 1878 | |
58eb6e7c AG |
1879 | int max = npairs-1; |
1880 | int min = 0; | |
1881 | ||
1882 | // simple binary search... | |
1883 | while (min < max) | |
1884 | { | |
1885 | int half = (min+max)/2; | |
1886 | int match = get4 (pc+ 4*(2 + 2*half)); | |
1887 | ||
1888 | if (index == match) | |
1889 | min = max = half; | |
1890 | ||
1891 | else if (index < match) | |
1892 | max = half-1; | |
f7b4fb11 | 1893 | |
58eb6e7c AG |
1894 | else |
1895 | min = half+1; | |
1896 | } | |
f7b4fb11 | 1897 | |
58eb6e7c AG |
1898 | if (index == get4 (pc+ 4*(2 + 2*min))) |
1899 | pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1)); | |
1900 | else | |
1901 | pc = base_pc + def; | |
1902 | } | |
f7b4fb11 | 1903 | NEXT_INSN; |
58eb6e7c AG |
1904 | |
1905 | /* on return, just save the sp and return to caller */ | |
f7b4fb11 KKT |
1906 | insn_ireturn: |
1907 | insn_lreturn: | |
1908 | insn_freturn: | |
1909 | insn_dreturn: | |
1910 | insn_areturn: | |
1911 | insn_return: | |
58eb6e7c | 1912 | inv->sp = sp; |
58eb6e7c AG |
1913 | return; |
1914 | ||
f7b4fb11 KKT |
1915 | insn_getstatic: |
1916 | SAVE_PC; | |
58eb6e7c | 1917 | { |
58eb6e7c AG |
1918 | jint fieldref_index = get2u (pc); pc += 2; |
1919 | _Jv_ResolvePoolEntry (defining_class, fieldref_index); | |
7941ceab | 1920 | _Jv_Field *field = pool_data[fieldref_index].field; |
58eb6e7c | 1921 | |
e409a2c8 | 1922 | if ((field->flags & Modifier::STATIC) == 0) |
58eb6e7c AG |
1923 | throw_incompatible_class_change_error |
1924 | (JvNewStringLatin1 ("field no longer static")); | |
1925 | ||
1926 | jclass type = field->type; | |
1927 | ||
1928 | if (type->isPrimitive ()) | |
1929 | { | |
1930 | switch (type->size_in_bytes) | |
1931 | { | |
1932 | case 1: | |
715bdd81 | 1933 | PUSHI (*(jbyte*) (field->u.addr)); |
f7b4fb11 | 1934 | |
58eb6e7c AG |
1935 | case 2: |
1936 | if (type == JvPrimClass (char)) | |
715bdd81 | 1937 | PUSHI(*(jchar*) (field->u.addr)); |
58eb6e7c | 1938 | else |
715bdd81 | 1939 | PUSHI(*(jshort*) (field->u.addr)); |
58eb6e7c AG |
1940 | break; |
1941 | ||
1942 | case 4: | |
715bdd81 | 1943 | PUSHI(*(jint*) (field->u.addr)); |
58eb6e7c AG |
1944 | break; |
1945 | ||
1946 | case 8: | |
715bdd81 | 1947 | PUSHL(*(jlong*) (field->u.addr)); |
58eb6e7c AG |
1948 | break; |
1949 | } | |
1950 | } | |
1951 | else | |
1952 | { | |
715bdd81 | 1953 | PUSHA(*(jobject*) (field->u.addr)); |
58eb6e7c | 1954 | } |
58eb6e7c | 1955 | } |
f7b4fb11 | 1956 | NEXT_INSN; |
58eb6e7c | 1957 | |
f7b4fb11 KKT |
1958 | insn_getfield: |
1959 | SAVE_PC; | |
58eb6e7c | 1960 | { |
58eb6e7c AG |
1961 | jint fieldref_index = get2u (pc); pc += 2; |
1962 | _Jv_ResolvePoolEntry (defining_class, fieldref_index); | |
7941ceab | 1963 | _Jv_Field *field = pool_data[fieldref_index].field; |
58eb6e7c | 1964 | |
e409a2c8 | 1965 | if ((field->flags & Modifier::STATIC) != 0) |
58eb6e7c AG |
1966 | throw_incompatible_class_change_error |
1967 | (JvNewStringLatin1 ("field is static")); | |
1968 | ||
1969 | jclass type = field->type; | |
715bdd81 AH |
1970 | jint field_offset = field->u.boffset; |
1971 | if (field_offset > 0xffff) | |
1972 | JvThrow (new java::lang::VirtualMachineError); | |
1973 | ||
1974 | jobject obj = POPA(); | |
1975 | NULLCHECK(obj); | |
58eb6e7c AG |
1976 | |
1977 | if (type->isPrimitive ()) | |
1978 | { | |
1979 | switch (type->size_in_bytes) | |
1980 | { | |
1981 | case 1: | |
715bdd81 | 1982 | PUSHI (*(jbyte*) ((char*)obj + field_offset)); |
58eb6e7c | 1983 | break; |
f7b4fb11 | 1984 | |
58eb6e7c AG |
1985 | case 2: |
1986 | if (type == JvPrimClass (char)) | |
715bdd81 | 1987 | PUSHI (*(jchar*) ((char*)obj + field_offset)); |
58eb6e7c | 1988 | else |
715bdd81 | 1989 | PUSHI (*(jshort*) ((char*)obj + field_offset)); |
58eb6e7c AG |
1990 | break; |
1991 | ||
1992 | case 4: | |
715bdd81 | 1993 | PUSHI (*(jint*) ((char*)obj + field_offset)); |
58eb6e7c AG |
1994 | break; |
1995 | ||
1996 | case 8: | |
715bdd81 | 1997 | PUSHL(*(jlong*) ((char*)obj + field_offset)); |
58eb6e7c AG |
1998 | break; |
1999 | } | |
2000 | } | |
2001 | else | |
2002 | { | |
715bdd81 | 2003 | PUSHA(*(jobject*) ((char*)obj + field_offset)); |
58eb6e7c | 2004 | } |
58eb6e7c | 2005 | } |
f7b4fb11 | 2006 | NEXT_INSN; |
58eb6e7c | 2007 | |
f7b4fb11 KKT |
2008 | insn_putstatic: |
2009 | SAVE_PC; | |
58eb6e7c | 2010 | { |
58eb6e7c AG |
2011 | jint fieldref_index = get2u (pc); pc += 2; |
2012 | _Jv_ResolvePoolEntry (defining_class, fieldref_index); | |
7941ceab | 2013 | _Jv_Field *field = pool_data[fieldref_index].field; |
58eb6e7c AG |
2014 | |
2015 | jclass type = field->type; | |
2016 | ||
2017 | // ResolvePoolEntry cannot check this | |
e409a2c8 | 2018 | if ((field->flags & Modifier::STATIC) == 0) |
58eb6e7c AG |
2019 | throw_incompatible_class_change_error |
2020 | (JvNewStringLatin1 ("field no longer static")); | |
2021 | ||
58eb6e7c AG |
2022 | if (type->isPrimitive ()) |
2023 | { | |
2024 | switch (type->size_in_bytes) | |
2025 | { | |
2026 | case 1: | |
715bdd81 AH |
2027 | { |
2028 | jint value = POPI(); | |
2029 | *(jbyte*) (field->u.addr) = value; | |
2030 | break; | |
2031 | } | |
58eb6e7c AG |
2032 | |
2033 | case 2: | |
715bdd81 AH |
2034 | { |
2035 | jint value = POPI(); | |
2036 | *(jchar*) (field->u.addr) = value; | |
2037 | break; | |
2038 | } | |
f7b4fb11 | 2039 | |
58eb6e7c | 2040 | case 4: |
715bdd81 AH |
2041 | { |
2042 | jint value = POPI(); | |
2043 | *(jint*) (field->u.addr) = value; | |
2044 | break; | |
2045 | } | |
f7b4fb11 | 2046 | |
58eb6e7c | 2047 | case 8: |
715bdd81 AH |
2048 | { |
2049 | jlong value = POPL(); | |
2050 | *(jlong*) (field->u.addr) = value; | |
2051 | break; | |
2052 | } | |
58eb6e7c AG |
2053 | } |
2054 | } | |
2055 | else | |
2056 | { | |
715bdd81 AH |
2057 | jobject value = POPA(); |
2058 | *(jobject*) (field->u.addr) = value; | |
58eb6e7c | 2059 | } |
58eb6e7c | 2060 | } |
f7b4fb11 | 2061 | NEXT_INSN; |
58eb6e7c AG |
2062 | |
2063 | ||
f7b4fb11 KKT |
2064 | insn_putfield: |
2065 | SAVE_PC; | |
58eb6e7c | 2066 | { |
58eb6e7c AG |
2067 | jint fieldref_index = get2u (pc); pc += 2; |
2068 | _Jv_ResolvePoolEntry (defining_class, fieldref_index); | |
7941ceab | 2069 | _Jv_Field *field = pool_data[fieldref_index].field; |
58eb6e7c AG |
2070 | |
2071 | jclass type = field->type; | |
2072 | ||
e409a2c8 | 2073 | if ((field->flags & Modifier::STATIC) != 0) |
58eb6e7c AG |
2074 | throw_incompatible_class_change_error |
2075 | (JvNewStringLatin1 ("field is static")); | |
2076 | ||
715bdd81 AH |
2077 | jint field_offset = field->u.boffset; |
2078 | if (field_offset > 0xffff) | |
2079 | JvThrow (new java::lang::VirtualMachineError); | |
2080 | ||
58eb6e7c AG |
2081 | if (type->isPrimitive ()) |
2082 | { | |
2083 | switch (type->size_in_bytes) | |
2084 | { | |
2085 | case 1: | |
715bdd81 AH |
2086 | { |
2087 | jint value = POPI(); | |
2088 | jobject obj = POPA(); | |
2089 | NULLCHECK(obj); | |
2090 | *(jbyte*) ((char*)obj + field_offset) = value; | |
2091 | break; | |
2092 | } | |
58eb6e7c AG |
2093 | |
2094 | case 2: | |
715bdd81 AH |
2095 | { |
2096 | jint value = POPI(); | |
2097 | jobject obj = POPA(); | |
2098 | NULLCHECK(obj); | |
2099 | *(jchar*) ((char*)obj + field_offset) = value; | |
2100 | break; | |
2101 | } | |
58eb6e7c AG |
2102 | |
2103 | case 4: | |
715bdd81 AH |
2104 | { |
2105 | jint value = POPI(); | |
2106 | jobject obj = POPA(); | |
2107 | NULLCHECK(obj); | |
2108 | *(jint*) ((char*)obj + field_offset) = value; | |
2109 | break; | |
2110 | } | |
58eb6e7c AG |
2111 | |
2112 | case 8: | |
715bdd81 AH |
2113 | { |
2114 | jlong value = POPL(); | |
2115 | jobject obj = POPA(); | |
2116 | NULLCHECK(obj); | |
2117 | *(jlong*) ((char*)obj + field_offset) = value; | |
2118 | break; | |
2119 | } | |
58eb6e7c AG |
2120 | } |
2121 | } | |
2122 | else | |
2123 | { | |
715bdd81 AH |
2124 | jobject value = POPA(); |
2125 | jobject obj = POPA(); | |
2126 | NULLCHECK(obj); | |
2127 | *(jobject*) ((char*)obj + field_offset) = value; | |
58eb6e7c | 2128 | } |
58eb6e7c | 2129 | } |
f7b4fb11 | 2130 | NEXT_INSN; |
58eb6e7c | 2131 | |
f7b4fb11 KKT |
2132 | insn_invokespecial: |
2133 | SAVE_PC; | |
58eb6e7c AG |
2134 | { |
2135 | int index = get2u (pc); pc += 2; | |
2136 | ||
7941ceab | 2137 | rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod; |
58eb6e7c AG |
2138 | |
2139 | sp -= rmeth->stack_item_count; | |
f7b4fb11 | 2140 | |
58eb6e7c AG |
2141 | NULLCHECK(sp[0]); |
2142 | ||
2143 | fun = (void (*) (...))rmeth->method->ncode; | |
2144 | } | |
2145 | goto perform_invoke; | |
2146 | ||
f7b4fb11 KKT |
2147 | insn_invokestatic: |
2148 | SAVE_PC; | |
58eb6e7c AG |
2149 | { |
2150 | int index = get2u (pc); pc += 2; | |
2151 | ||
7941ceab | 2152 | rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod; |
58eb6e7c AG |
2153 | |
2154 | sp -= rmeth->stack_item_count; | |
f7b4fb11 | 2155 | |
58eb6e7c AG |
2156 | _Jv_InitClass (rmeth->klass); |
2157 | fun = (void (*) (...))rmeth->method->ncode; | |
2158 | } | |
2159 | goto perform_invoke; | |
2160 | ||
f7b4fb11 KKT |
2161 | insn_invokeinterface: |
2162 | SAVE_PC; | |
58eb6e7c AG |
2163 | { |
2164 | int index = get2u (pc); pc += 2; | |
2165 | ||
2166 | // invokeinterface has two unused bytes... | |
2167 | pc += 2; | |
2168 | ||
7941ceab | 2169 | rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod; |
58eb6e7c AG |
2170 | |
2171 | sp -= rmeth->stack_item_count; | |
2172 | NULLCHECK(sp[0]); | |
f7b4fb11 | 2173 | |
7941ceab | 2174 | jobject rcv = sp[0].o; |
58eb6e7c AG |
2175 | |
2176 | fun = (void (*) (...)) | |
2177 | _Jv_LookupInterfaceMethod (rcv->getClass (), | |
2178 | rmeth->method->name, | |
2179 | rmeth->method->signature); | |
2180 | } | |
2181 | goto perform_invoke; | |
2182 | ||
2183 | ||
f7b4fb11 KKT |
2184 | insn_new: |
2185 | SAVE_PC; | |
58eb6e7c AG |
2186 | { |
2187 | int index = get2u (pc); pc += 2; | |
7941ceab | 2188 | jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz; |
58eb6e7c AG |
2189 | _Jv_InitClass (klass); |
2190 | jobject res = _Jv_AllocObject (klass, klass->size_in_bytes); | |
2191 | PUSHA (res); | |
2192 | } | |
f7b4fb11 | 2193 | NEXT_INSN; |
58eb6e7c | 2194 | |
f7b4fb11 KKT |
2195 | insn_newarray: |
2196 | SAVE_PC; | |
58eb6e7c AG |
2197 | { |
2198 | int atype = get1u (pc++); | |
2199 | int size = POPI(); | |
2200 | jobject result = _Jv_NewArray (atype, size); | |
2201 | PUSHA (result); | |
2202 | } | |
f7b4fb11 KKT |
2203 | NEXT_INSN; |
2204 | ||
2205 | insn_anewarray: | |
2206 | SAVE_PC; | |
58eb6e7c AG |
2207 | { |
2208 | int index = get2u (pc); pc += 2; | |
7941ceab | 2209 | jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz; |
58eb6e7c AG |
2210 | int size = POPI(); |
2211 | _Jv_InitClass (klass); | |
2212 | jobject result = _Jv_NewObjectArray (size, klass, 0); | |
2213 | PUSHA (result); | |
2214 | } | |
f7b4fb11 | 2215 | NEXT_INSN; |
58eb6e7c | 2216 | |
f7b4fb11 KKT |
2217 | insn_arraylength: |
2218 | SAVE_PC; | |
58eb6e7c AG |
2219 | { |
2220 | __JArray *arr = (__JArray*)POPA(); | |
2221 | PUSHI (arr->length); | |
2222 | } | |
f7b4fb11 | 2223 | NEXT_INSN; |
58eb6e7c | 2224 | |
f7b4fb11 KKT |
2225 | insn_athrow: |
2226 | SAVE_PC; | |
58eb6e7c AG |
2227 | { |
2228 | jobject value = POPA(); | |
58eb6e7c AG |
2229 | JvThrow (value); |
2230 | } | |
f7b4fb11 | 2231 | NEXT_INSN; |
58eb6e7c | 2232 | |
f7b4fb11 KKT |
2233 | insn_checkcast: |
2234 | SAVE_PC; | |
58eb6e7c AG |
2235 | { |
2236 | jobject value = POPA(); | |
2237 | jint index = get2u (pc); pc += 2; | |
7941ceab | 2238 | jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz; |
58eb6e7c AG |
2239 | |
2240 | if (value != NULL && ! to->isInstance (value)) | |
2241 | { | |
58eb6e7c AG |
2242 | JvThrow (new java::lang::ClassCastException |
2243 | (to->getName())); | |
2244 | } | |
2245 | ||
2246 | PUSHA (value); | |
2247 | } | |
f7b4fb11 | 2248 | NEXT_INSN; |
58eb6e7c | 2249 | |
f7b4fb11 KKT |
2250 | insn_instanceof: |
2251 | SAVE_PC; | |
58eb6e7c AG |
2252 | { |
2253 | jobject value = POPA(); | |
2254 | jint index = get2u (pc); pc += 2; | |
7941ceab | 2255 | jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz; |
58eb6e7c AG |
2256 | PUSHI (to->isInstance (value)); |
2257 | } | |
f7b4fb11 | 2258 | NEXT_INSN; |
58eb6e7c | 2259 | |
f7b4fb11 KKT |
2260 | insn_monitorenter: |
2261 | SAVE_PC; | |
58eb6e7c AG |
2262 | { |
2263 | jobject value = POPA(); | |
2264 | NULLCHECK(value); | |
2265 | _Jv_MonitorEnter (value); | |
2266 | } | |
f7b4fb11 | 2267 | NEXT_INSN; |
58eb6e7c | 2268 | |
f7b4fb11 KKT |
2269 | insn_monitorexit: |
2270 | SAVE_PC; | |
58eb6e7c AG |
2271 | { |
2272 | jobject value = POPA(); | |
2273 | NULLCHECK(value); | |
2274 | _Jv_MonitorExit (value); | |
2275 | } | |
f7b4fb11 | 2276 | NEXT_INSN; |
58eb6e7c | 2277 | |
f7b4fb11 | 2278 | insn_ifnull: |
58eb6e7c AG |
2279 | { |
2280 | unsigned char* base_pc = pc-1; | |
2281 | jint offset = get2s (pc); pc += 2; | |
2282 | jobject val = POPA(); | |
2283 | if (val == NULL) | |
2284 | pc = base_pc+offset; | |
2285 | } | |
f7b4fb11 | 2286 | NEXT_INSN; |
58eb6e7c | 2287 | |
f7b4fb11 | 2288 | insn_ifnonnull: |
58eb6e7c AG |
2289 | { |
2290 | unsigned char* base_pc = pc-1; | |
2291 | jint offset = get2s (pc); pc += 2; | |
2292 | jobject val = POPA(); | |
2293 | if (val != NULL) | |
2294 | pc = base_pc+offset; | |
2295 | } | |
f7b4fb11 | 2296 | NEXT_INSN; |
58eb6e7c | 2297 | |
f7b4fb11 KKT |
2298 | insn_wide: |
2299 | SAVE_PC; | |
58eb6e7c AG |
2300 | { |
2301 | jint the_mod_op = get1u (pc++); | |
2302 | jint wide = get2u (pc); pc += 2; | |
2303 | ||
2304 | switch (the_mod_op) | |
2305 | { | |
2306 | case op_istore: | |
2307 | STOREI (wide); | |
f7b4fb11 | 2308 | NEXT_INSN; |
58eb6e7c AG |
2309 | |
2310 | case op_fstore: | |
2311 | STOREF (wide); | |
f7b4fb11 | 2312 | NEXT_INSN; |
58eb6e7c AG |
2313 | |
2314 | case op_astore: | |
2315 | STOREA (wide); | |
f7b4fb11 | 2316 | NEXT_INSN; |
58eb6e7c AG |
2317 | |
2318 | case op_lload: | |
2319 | LOADL (wide); | |
f7b4fb11 | 2320 | NEXT_INSN; |
58eb6e7c AG |
2321 | |
2322 | case op_dload: | |
2323 | LOADD (wide); | |
f7b4fb11 | 2324 | NEXT_INSN; |
58eb6e7c AG |
2325 | |
2326 | case op_iload: | |
2327 | LOADI (wide); | |
f7b4fb11 | 2328 | NEXT_INSN; |
58eb6e7c AG |
2329 | |
2330 | case op_aload: | |
2331 | LOADA (wide); | |
f7b4fb11 | 2332 | NEXT_INSN; |
58eb6e7c AG |
2333 | |
2334 | case op_lstore: | |
2335 | STOREL (wide); | |
f7b4fb11 | 2336 | NEXT_INSN; |
58eb6e7c AG |
2337 | |
2338 | case op_dstore: | |
2339 | STORED (wide); | |
f7b4fb11 | 2340 | NEXT_INSN; |
58eb6e7c AG |
2341 | |
2342 | case op_ret: | |
2343 | pc = (unsigned char*) PEEKA (wide); | |
f7b4fb11 | 2344 | NEXT_INSN; |
58eb6e7c AG |
2345 | |
2346 | case op_iinc: | |
2347 | { | |
2348 | jint amount = get2s (pc); pc += 2; | |
2349 | jint value = PEEKI (wide); | |
2350 | POKEI (wide, value+amount); | |
2351 | } | |
f7b4fb11 | 2352 | NEXT_INSN; |
58eb6e7c AG |
2353 | |
2354 | default: | |
2355 | throw_internal_error ("illegal bytecode modified by wide"); | |
2356 | } | |
2357 | ||
2358 | } | |
2359 | ||
f7b4fb11 KKT |
2360 | insn_multianewarray: |
2361 | SAVE_PC; | |
58eb6e7c AG |
2362 | { |
2363 | int kind_index = get2u (pc); pc += 2; | |
2364 | int dim = get1u (pc); pc += 1; | |
2365 | ||
7941ceab AG |
2366 | jclass type |
2367 | = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz; | |
58eb6e7c AG |
2368 | _Jv_InitClass (type); |
2369 | jint *sizes = (jint*) alloca (sizeof (jint)*dim); | |
2370 | ||
2371 | for (int i = dim - 1; i >= 0; i--) | |
2372 | { | |
2373 | sizes[i] = POPI (); | |
2374 | } | |
f7b4fb11 | 2375 | |
58eb6e7c | 2376 | jobject res = _Jv_NewMultiArray (type,dim, sizes); |
f7b4fb11 | 2377 | |
58eb6e7c AG |
2378 | PUSHA (res); |
2379 | } | |
f7b4fb11 | 2380 | NEXT_INSN; |
58eb6e7c | 2381 | |
f7b4fb11 | 2382 | insn_goto_w: |
58eb6e7c AG |
2383 | { |
2384 | unsigned char* base_pc = pc-1; | |
2385 | int offset = get4 (pc); pc += 4; | |
2386 | pc = base_pc+offset; | |
2387 | } | |
f7b4fb11 | 2388 | NEXT_INSN; |
58eb6e7c | 2389 | |
f7b4fb11 | 2390 | insn_jsr_w: |
58eb6e7c AG |
2391 | { |
2392 | unsigned char* base_pc = pc-1; | |
2393 | int offset = get4 (pc); pc += 4; | |
2394 | PUSHA((jobject)pc); | |
2395 | pc = base_pc+offset; | |
2396 | } | |
f7b4fb11 | 2397 | NEXT_INSN; |
58eb6e7c AG |
2398 | } |
2399 | ||
2400 | ||
2401 | static void | |
2402 | throw_internal_error (char *msg) | |
2403 | { | |
2404 | JvThrow (new java::lang::InternalError (JvNewStringLatin1 (msg))); | |
2405 | } | |
2406 | ||
2407 | static void | |
2408 | throw_incompatible_class_change_error (jstring msg) | |
2409 | { | |
2410 | JvThrow (new java::lang::IncompatibleClassChangeError (msg)); | |
2411 | } | |
2412 | ||
715bdd81 | 2413 | #ifndef HANDLE_SEGV |
58eb6e7c AG |
2414 | static java::lang::NullPointerException *null_pointer_exc; |
2415 | static void | |
2416 | throw_null_pointer_exception () | |
2417 | { | |
2418 | if (null_pointer_exc == NULL) | |
2419 | null_pointer_exc = new java::lang::NullPointerException; | |
2420 | ||
2421 | JvThrow (null_pointer_exc); | |
2422 | } | |
2423 | #endif | |
2424 | ||
715bdd81 | 2425 | #ifndef HANDLE_FPE |
58eb6e7c AG |
2426 | static java::lang::ArithmeticException *arithmetic_exc; |
2427 | static void | |
2428 | throw_arithmetic_exception () | |
2429 | { | |
2430 | if (arithmetic_exc == NULL) | |
2431 | arithmetic_exc = new java::lang::ArithmeticException | |
2432 | (JvNewStringLatin1 ("/ by zero")); | |
2433 | ||
2434 | JvThrow (arithmetic_exc); | |
2435 | } | |
2436 | #endif | |
2437 | ||
58eb6e7c AG |
2438 | |
2439 | #endif // INTERPRETER |