blob: a6f88b4479196da3f98f7b56487a1449840691b8 [file] [log] [blame]
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001/*
2 * This file was generated automatically by gen-mterp.py for 'x86'.
3 *
4 * --> DO NOT EDIT <--
5 */
6
7/* File: x86/header.S */
8/*
9 * Copyright (C) 2008 The Android Open Source Project
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 * http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23/*
24 * 32-bit x86 definitions and declarations.
25 */
26
27/*
28386 ABI general notes:
29
30Caller save set:
31 eax, edx, ecx, st(0)-st(7)
32Callee save set:
33 ebx, esi, edi, ebp
34Return regs:
35 32-bit in eax
36 64-bit in edx:eax (low-order 32 in eax)
37 fp on top of fp stack st(0)
38
39Parameters passed on stack, pushed right-to-left. On entry to target, first
40parm is at 4(%esp). Traditional entry code is:
41
42functEntry:
43 push %ebp # save old frame pointer
44 mov %ebp,%esp # establish new frame pointer
45 sub FrameSize,%esp # Allocate storage for spill, locals & outs
46
47Once past the prologue, arguments are referenced at ((argno + 2)*4)(%ebp)
48
49Alignment of stack not strictly required, but should be for performance. We'll
50align frame sizes to 16-byte multiples.
51
52If we're not doing variable stack allocation (alloca), the frame pointer can be
53eliminated and all arg references adjusted to be esp relative.
54
55Mterp notes:
56
57Some key interpreter variables will be assigned to registers. Note that each
58will also have an associated spill location (mostly used useful for those assigned
59to callee save registers).
60
61 nick reg purpose
62 rPC edx interpreted program counter, used for fetching instructions
63 rFP esi interpreted frame pointer, used for accessing locals and args
64 rIBASE edi Base pointer for instruction dispatch computed goto
65 rINST bx first 16-bit code of current instruction
66 rOPCODE bl opcode portion of instruction word
67 rINST_HI bh high byte of instruction word, usually contains src/tgt reg names
68
69Notes:
70 o High order 16 bits of ebx must be zero on entry to handler
71 o rPC, rFP, rIBASE, rINST/rOPCODE valid on handler entry and exit
72 o eax and ecx are scratch, rINST/ebx sometimes scratch
73 o rPC is in the caller save set, and will be killed across external calls. Don't
74 forget to SPILL/UNSPILL it around call points
75
76*/
77
78#define rPC %edx
79#define rFP %esi
80#define rIBASE %edi
81#define rINST_FULL %ebx
82#define rINST %bx
83#define rINST_HI %bh
84#define rINST_LO %bl
85#define rOPCODE %bl
86
87
88/* Frame diagram while executing dvmMterpStdRun, high to low addresses */
89#define IN_ARG0 ( 8)
90#define CALLER_RP ( 4)
91#define PREV_FP ( 0) /* <- dvmMterpStdRun ebp */
92/* Spill offsets relative to %ebp */
93#define EDI_SPILL ( -4)
94#define ESI_SPILL ( -8)
95#define EDX_SPILL (-12) /* <- esp following dmMterpStdRun header */
96#define rPC_SPILL (-16)
97#define rFP_SPILL (-20)
98#define rGLUE_SPILL (-24)
99#define rIBASE_SPILL (-28)
100#define rINST_FULL_SPILL (-32)
101#define TMP_SPILL (-36)
102#define LOCAL0_OFFSET (-40)
103#define LOCAL1_OFFSET (-44)
104#define LOCAL2_OFFSET (-48)
105#define LOCAL3_OFFSET (-52)
106/* Out Arg offsets, relative to %sp */
107#define OUT_ARG4 ( 16)
108#define OUT_ARG3 ( 12)
109#define OUT_ARG2 ( 8)
110#define OUT_ARG1 ( 4)
111#define OUT_ARG0 ( 0) /* <- dvmMterpStdRun esp */
112
113#define SPILL(reg) movl reg##,reg##_SPILL(%ebp)
114#define UNSPILL(reg) movl reg##_SPILL(%ebp),reg
115#define SPILL_TMP(reg) movl reg,TMP_SPILL(%ebp)
116#define UNSPILL_TMP(reg) movl TMP_SPILL(%ebp),reg
117
118
119/* save/restore the PC and/or FP from the glue struct */
120#define LOAD_PC_FROM_GLUE(_glu) movl offGlue_pc(_glu),rPC
121#define SAVE_PC_TO_GLUE(_glu) movl rPC,offGlue_pc(_glu)
122#define LOAD_FP_FROM_GLUE(_glu) movl offGlue_fp(_glu),rFP
123#define SAVE_FP_TO_GLUE(_glu) movl rFP,offGlue_fp(_glu)
124
125#define GET_GLUE(_reg) movl rGLUE_SPILL(%ebp),_reg
126
127/* The interpreter assumes a properly aligned stack on entry, and
128 * will preserve 16-byte alignment.
129 */
130
131/*
132 * "export" the PC to the interpreted stack frame, f/b/o future exception
133 * objects. Must * be done *before* something calls dvmThrowException.
134 *
135 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
136 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
137 *
138 * It's okay to do this more than once.
139 */
140#define EXPORT_PC() \
141 movl rPC, (-sizeofStackSaveArea + offStackSaveArea_currentPc)(rFP)
142
143/*
144 * Given a frame pointer, find the stack save area.
145 *
146 * In C this is "((StackSaveArea*)(_fp) -1)".
147 */
148#define SAVEAREA_FROM_FP(_reg, _fpreg) \
149 leal -sizeofStackSaveArea(_fpreg),_reg
150
151/*
152 * Fetch the next instruction from rPC into rINST. Does not advance rPC.
153 */
154#define FETCH_INST() movzwl (rPC),rINST_FULL
155
156/*
157 * Fetch the nth instruction word from rPC into rINST. Does not advance
158 * rPC, and _count is in words
159 */
160#define FETCH_INST_WORD(_count) movzwl _count*2(rPC),rINST_FULL
161
162/*
163 * Fetch instruction word indexed (used for branching).
164 * Index is in instruction word units.
165 */
166#define FETCH_INST_INDEXED(_reg) movzwl (rPC,_reg,2),rINST_FULL
167
168/*
169 * Extract the opcode of the instruction in rINST
170 */
171#define EXTRACT_OPCODE(_reg) movzx rOPCODE,_reg
172
173/*
174 * Advance rPC by instruction count
175 */
176#define ADVANCE_PC(_count) leal 2*_count(rPC),rPC
177
178/*
179 * Advance rPC by branch offset in register
180 */
181#define ADVANCE_PC_INDEXED(_reg) leal (rPC,_reg,2),rPC
182
183/*
184 * Note: assumes opcode previously fetched and in rINST, and
185 * %eax is killable at this point.
186 */
187#if 1
188.macro GOTO_NEXT
189 /* For computed next version */
190 movzx rOPCODE,%eax
191 sall $6,%eax
192 addl rIBASE,%eax
193 jmp *%eax
194.endm
195#else
196 /* For jump table version */
197.macro GOTO_NEXT
198 movzx rOPCODE,%eax
199 jmp *(rIBASE,%eax,4)
200.endm
201#endif
202
203/*
204 * Get/set the 32-bit value from a Dalvik register.
205 */
206#define GET_VREG(_reg, _vreg) movl (rFP,_vreg,4),_reg
207#define SET_VREG(_reg, _vreg) movl _reg,(rFP,_vreg,4)
208#define GET_VREG_WORD(_reg, _vreg, _offset) movl 4*(_offset)(rFP,_vreg,4),_reg
209#define SET_VREG_WORD(_reg, _vreg, _offset) movl _reg,4*(_offset)(rFP,_vreg,4)
210
211/*
212 * This is a #include, not a %include, because we want the C pre-processor
213 * to expand the macros into assembler assignment statements.
214 */
215#include "../common/asm-constants.h"
216
217
218
219 .global dvmAsmInstructionStart
220 .type dvmAsmInstructionStart, %function
221dvmAsmInstructionStart = .L_OP_NOP
222 .text
223
224/* ------------------------------ */
225 .balign 64
226.L_OP_NOP: /* 0x00 */
227/* File: x86/OP_NOP.S */
228 FETCH_INST_WORD(1)
229 ADVANCE_PC(1)
230 GOTO_NEXT
231
232/* ------------------------------ */
233 .balign 64
234.L_OP_MOVE: /* 0x01 */
235/* File: x86/OP_MOVE.S */
236 /* for move, move-object, long-to-int */
237 /* op vA, vB */
238 movzbl rINST_HI,%eax # eax<- BA
239 andb $0xf,%al # eax<- A
240 shrl $12,rINST_FULL # rINST_FULL<- B
241 GET_VREG(%ecx,rINST_FULL)
242 FETCH_INST_WORD(1)
243 ADVANCE_PC(1)
244 SET_VREG(%ecx,%eax) # fp[A]<-fp[B]
245 GOTO_NEXT
246
247/* ------------------------------ */
248 .balign 64
249.L_OP_MOVE_FROM16: /* 0x02 */
250/* File: x86/OP_MOVE_FROM16.S */
251 /* for: move/from16, move-object/from16 */
252 /* op vAA, vBBBB */
253 movzx rINST_HI,%eax # eax <= AA
254 movw 2(rPC),rINST # rINST <= BBBB
255 GET_VREG (%ecx,rINST_FULL) # ecx<- fp[BBBB]
256 FETCH_INST_WORD(2)
257 ADVANCE_PC(2)
258 SET_VREG (%ecx,%eax) # fp[AA]<- ecx]
259 GOTO_NEXT
260
261
262/* ------------------------------ */
263 .balign 64
264.L_OP_MOVE_16: /* 0x03 */
265/* File: x86/OP_MOVE_16.S */
266 /* for: move/16, move-object/16 */
267 /* op vAAAA, vBBBB */
268 movzwl 4(rPC),%ecx # ecx<- BBBB
269 movzwl 2(rPC),%eax # eax<- AAAA
270 GET_VREG(%ecx,%ecx)
271 FETCH_INST_WORD(3)
272 ADVANCE_PC(3)
273 SET_VREG(%ecx,%eax)
274 GOTO_NEXT
275
276/* ------------------------------ */
277 .balign 64
278.L_OP_MOVE_WIDE: /* 0x04 */
279/* File: x86/OP_MOVE_WIDE.S */
280 /* move-wide vA, vB */
281 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
282 movzbl rINST_HI,%ecx # ecx <- BA
283 sarl $12,rINST_FULL # rinst_FULL<- B
284 GET_VREG_WORD(%eax,rINST_FULL,0) # eax<- v[B+0]
285 GET_VREG_WORD(rINST_FULL,rINST_FULL,1) # rINST_FULL<- v[B+1]
286 andb $0xf,%cl # ecx <- A
287 SET_VREG_WORD(rINST_FULL,%ecx,1) # v[A+1]<- rINST_FULL
288 FETCH_INST_WORD(1)
289 ADVANCE_PC(1)
290 SET_VREG_WORD(%eax,%ecx,0) # v[A+0]<- eax
291 GOTO_NEXT
292
293/* ------------------------------ */
294 .balign 64
295.L_OP_MOVE_WIDE_FROM16: /* 0x05 */
296/* File: x86/OP_MOVE_WIDE_FROM16.S */
297 /* move-wide/from16 vAA, vBBBB */
298 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
299 movzwl 2(rPC),%ecx # ecx<- BBBB
300 movzbl rINST_HI,%eax # eax<- AAAA
301 GET_VREG_WORD(rINST_FULL,%ecx,0) # rINST_FULL<- v[BBBB+0]
302 GET_VREG_WORD(%ecx,%ecx,1) # ecx<- v[BBBB+1]
303 SET_VREG_WORD(rINST_FULL,%eax,0) # v[AAAA+0]<- rINST_FULL
304 FETCH_INST_WORD(2)
305 ADVANCE_PC(2)
306 SET_VREG_WORD(%ecx,%eax,1) # v[AAAA+1]<- eax
307 GOTO_NEXT
308
309/* ------------------------------ */
310 .balign 64
311.L_OP_MOVE_WIDE_16: /* 0x06 */
312/* File: x86/OP_MOVE_WIDE_16.S */
313 /* move-wide/16 vAAAA, vBBBB */
314 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
315 movzwl 4(rPC),%ecx # ecx<- BBBB
316 movzwl 2(rPC),%eax # eax<- AAAA
317 GET_VREG_WORD(rINST_FULL,%ecx,0) # rINST_WORD<- v[BBBB+0]
318 GET_VREG_WORD(%ecx,%ecx,1) # ecx<- v[BBBB+1]
319 SET_VREG_WORD(rINST_FULL,%eax,0) # v[AAAA+0]<- rINST_FULL
320 FETCH_INST_WORD(3)
321 ADVANCE_PC(3)
322 SET_VREG_WORD(%ecx,%eax,1) # v[AAAA+1]<- ecx
323 GOTO_NEXT
324
325/* ------------------------------ */
326 .balign 64
327.L_OP_MOVE_OBJECT: /* 0x07 */
328/* File: x86/OP_MOVE_OBJECT.S */
329/* File: x86/OP_MOVE.S */
330 /* for move, move-object, long-to-int */
331 /* op vA, vB */
332 movzbl rINST_HI,%eax # eax<- BA
333 andb $0xf,%al # eax<- A
334 shrl $12,rINST_FULL # rINST_FULL<- B
335 GET_VREG(%ecx,rINST_FULL)
336 FETCH_INST_WORD(1)
337 ADVANCE_PC(1)
338 SET_VREG(%ecx,%eax) # fp[A]<-fp[B]
339 GOTO_NEXT
340
341
342/* ------------------------------ */
343 .balign 64
344.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
345/* File: x86/OP_MOVE_OBJECT_FROM16.S */
346/* File: x86/OP_MOVE_FROM16.S */
347 /* for: move/from16, move-object/from16 */
348 /* op vAA, vBBBB */
349 movzx rINST_HI,%eax # eax <= AA
350 movw 2(rPC),rINST # rINST <= BBBB
351 GET_VREG (%ecx,rINST_FULL) # ecx<- fp[BBBB]
352 FETCH_INST_WORD(2)
353 ADVANCE_PC(2)
354 SET_VREG (%ecx,%eax) # fp[AA]<- ecx]
355 GOTO_NEXT
356
357
358
359/* ------------------------------ */
360 .balign 64
361.L_OP_MOVE_OBJECT_16: /* 0x09 */
362/* File: x86/OP_MOVE_OBJECT_16.S */
363/* File: x86/OP_MOVE_16.S */
364 /* for: move/16, move-object/16 */
365 /* op vAAAA, vBBBB */
366 movzwl 4(rPC),%ecx # ecx<- BBBB
367 movzwl 2(rPC),%eax # eax<- AAAA
368 GET_VREG(%ecx,%ecx)
369 FETCH_INST_WORD(3)
370 ADVANCE_PC(3)
371 SET_VREG(%ecx,%eax)
372 GOTO_NEXT
373
374
375/* ------------------------------ */
376 .balign 64
377.L_OP_MOVE_RESULT: /* 0x0a */
378/* File: x86/OP_MOVE_RESULT.S */
379 /* for: move-result, move-result-object */
380 /* op vAA */
381 GET_GLUE(%eax) # eax<- rGLUE
382 movzx rINST_HI,%ecx # ecx<- AA
383 movl offGlue_retval(%eax),%eax # eax<- glue->retval.l
384 FETCH_INST_WORD(1)
385 ADVANCE_PC(1)
386 SET_VREG (%eax,%ecx) # fp[AA]<- retval.l
387 GOTO_NEXT
388
389/* ------------------------------ */
390 .balign 64
391.L_OP_MOVE_RESULT_WIDE: /* 0x0b */
392/* File: x86/OP_MOVE_RESULT_WIDE.S */
393 /* move-result-wide vAA */
394 GET_GLUE(%ecx)
395 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
396 movl offGlue_retval(%ecx),%eax
397 movl 4+offGlue_retval(%ecx),%ecx
398 SET_VREG_WORD(%eax,rINST_FULL,0) # v[AA+0] <- eax
399 SET_VREG_WORD(%ecx,rINST_FULL,1) # v[AA+1] <- ecx
400 FETCH_INST_WORD(1)
401 ADVANCE_PC(1)
402 GOTO_NEXT
403
404/* ------------------------------ */
405 .balign 64
406.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
407/* File: x86/OP_MOVE_RESULT_OBJECT.S */
408/* File: x86/OP_MOVE_RESULT.S */
409 /* for: move-result, move-result-object */
410 /* op vAA */
411 GET_GLUE(%eax) # eax<- rGLUE
412 movzx rINST_HI,%ecx # ecx<- AA
413 movl offGlue_retval(%eax),%eax # eax<- glue->retval.l
414 FETCH_INST_WORD(1)
415 ADVANCE_PC(1)
416 SET_VREG (%eax,%ecx) # fp[AA]<- retval.l
417 GOTO_NEXT
418
419
420/* ------------------------------ */
421 .balign 64
422.L_OP_MOVE_EXCEPTION: /* 0x0d */
423/* File: x86/OP_MOVE_EXCEPTION.S */
424 /* move-exception vAA */
425 GET_GLUE(%ecx)
426 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
427 movl offGlue_self(%ecx),%ecx # ecx<- glue->self
428 movl offThread_exception(%ecx),%eax # eax<- dvmGetException bypass
429 SET_VREG(%eax,rINST_FULL) # fp[AA]<- exception object
430 FETCH_INST_WORD(1)
431 ADVANCE_PC(1)
432 movl $0,offThread_exception(%ecx) # dvmClearException bypass
433 GOTO_NEXT
434
435/* ------------------------------ */
436 .balign 64
437.L_OP_RETURN_VOID: /* 0x0e */
438/* File: x86/OP_RETURN_VOID.S */
439 jmp common_returnFromMethod
440
441
442/* ------------------------------ */
443 .balign 64
444.L_OP_RETURN: /* 0x0f */
445/* File: x86/OP_RETURN.S */
446 /*
447 * Return a 32-bit value. Copies the return value into the "glue"
448 * structure, then jumps to the return handler.
449 *
450 * for: return, return-object
451 */
452 /* op vAA */
453 GET_GLUE(%ecx)
454 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
455 GET_VREG(%eax,rINST_FULL) # eax<- vAA
456 movl %eax,offGlue_retval(%ecx) # retval.i <- AA
457 jmp common_returnFromMethod
458
459/* ------------------------------ */
460 .balign 64
461.L_OP_RETURN_WIDE: /* 0x10 */
462/* File: x86/OP_RETURN_WIDE.S */
463 /*
464 * Return a 64-bit value. Copies the return value into the "glue"
465 * structure, then jumps to the return handler.
466 */
467 /* return-wide vAA */
468 GET_GLUE(%ecx)
469 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
470 GET_VREG_WORD(%eax,rINST_FULL,0) # eax<- v[AA+0]
471 GET_VREG_WORD(rINST_FULL,rINST_FULL,1) # rINST_FULL<- v[AA+1]
472 movl %eax,offGlue_retval(%ecx)
473 movl rINST_FULL,4+offGlue_retval(%ecx)
474 jmp common_returnFromMethod
475
476/* ------------------------------ */
477 .balign 64
478.L_OP_RETURN_OBJECT: /* 0x11 */
479/* File: x86/OP_RETURN_OBJECT.S */
480/* File: x86/OP_RETURN.S */
481 /*
482 * Return a 32-bit value. Copies the return value into the "glue"
483 * structure, then jumps to the return handler.
484 *
485 * for: return, return-object
486 */
487 /* op vAA */
488 GET_GLUE(%ecx)
489 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
490 GET_VREG(%eax,rINST_FULL) # eax<- vAA
491 movl %eax,offGlue_retval(%ecx) # retval.i <- AA
492 jmp common_returnFromMethod
493
494
495/* ------------------------------ */
496 .balign 64
497.L_OP_CONST_4: /* 0x12 */
498/* File: x86/OP_CONST_4.S */
499 /* const/4 vA, #+B */
500 movsx rINST_HI,%eax # eax<-ssssssBx
501 movl $0xf,%ecx
502 andl %eax,%ecx # ecx<- A
503 FETCH_INST_WORD(1)
504 ADVANCE_PC(1)
505 sarl $4,%eax
506 SET_VREG(%eax,%ecx)
507 GOTO_NEXT
508
509
510/* ------------------------------ */
511 .balign 64
512.L_OP_CONST_16: /* 0x13 */
513/* File: x86/OP_CONST_16.S */
514 /* const/16 vAA, #+BBBB */
515 movswl 2(rPC),%ecx # ecx<- ssssBBBB
516 movzx rINST_HI,%eax # eax<- AA
517 FETCH_INST_WORD(2)
518 ADVANCE_PC(2)
519 SET_VREG(%ecx,%eax) # vAA<- ssssBBBB
520 GOTO_NEXT
521
522/* ------------------------------ */
523 .balign 64
524.L_OP_CONST: /* 0x14 */
525/* File: x86/OP_CONST.S */
526 /* const vAA, #+BBBBbbbb */
527 movzbl rINST_HI,%ecx # ecx<- AA
528 movl 2(rPC),%eax # grab all 32 bits at once
529 FETCH_INST_WORD(3)
530 ADVANCE_PC(3)
531 SET_VREG(%eax,%ecx) # vAA<- eax
532 GOTO_NEXT
533
534/* ------------------------------ */
535 .balign 64
536.L_OP_CONST_HIGH16: /* 0x15 */
537/* File: x86/OP_CONST_HIGH16.S */
538 /* const/high16 vAA, #+BBBB0000 */
539 movzwl 2(rPC),%eax # eax<- 0000BBBB
540 movzbl rINST_HI,%ecx # ecx<- AA
541 FETCH_INST_WORD(2)
542 ADVANCE_PC(2)
543 sall $16,%eax # eax<- BBBB0000
544 SET_VREG(%eax,%ecx) # vAA<- eax
545 GOTO_NEXT
546
547/* ------------------------------ */
548 .balign 64
549.L_OP_CONST_WIDE_16: /* 0x16 */
550/* File: x86/OP_CONST_WIDE_16.S */
551 /* const-wide/16 vAA, #+BBBB */
552 movswl 2(rPC),%eax # eax<- ssssBBBB
553 SPILL(rPC)
554 movzbl rINST_HI,%ecx # ecx<- AA
555 FETCH_INST_WORD(2)
556 cltd # rPC:eax<- ssssssssssssBBBB
557 SET_VREG_WORD(rPC,%ecx,1) # store msw
558 UNSPILL(rPC)
559 SET_VREG_WORD(%eax,%ecx,0) # store lsw
560 ADVANCE_PC(2)
561 GOTO_NEXT
562
563/* ------------------------------ */
564 .balign 64
565.L_OP_CONST_WIDE_32: /* 0x17 */
566/* File: x86/OP_CONST_WIDE_32.S */
567 /* const-wide/32 vAA, #+BBBBbbbb */
568 movl 2(rPC),%eax # eax<- BBBBbbbb
569 SPILL(rPC)
570 movzbl rINST_HI,%ecx # ecx<- AA
571 FETCH_INST_WORD(3)
572 cltd # rPC:eax<- ssssssssssssBBBB
573 SET_VREG_WORD(rPC,%ecx,1) # store msw
574 UNSPILL(rPC)
575 SET_VREG_WORD(%eax,%ecx,0) # store lsw
576 ADVANCE_PC(3)
577 GOTO_NEXT
578
579/* ------------------------------ */
580 .balign 64
581.L_OP_CONST_WIDE: /* 0x18 */
582/* File: x86/OP_CONST_WIDE.S */
583 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
584 movl 2(rPC),%eax # eax<- lsw
585 movzbl rINST_HI,%ecx # ecx <- AA
586 movl 6(rPC),rINST_FULL # rINST_FULL<- msw
587 leal (rFP,%ecx,4),%ecx # dst addr
588 movl rINST_FULL,4(%ecx)
589 FETCH_INST_WORD(5)
590 movl %eax,(%ecx)
591 ADVANCE_PC(5)
592 GOTO_NEXT
593
594
595/* ------------------------------ */
596 .balign 64
597.L_OP_CONST_WIDE_HIGH16: /* 0x19 */
598/* File: x86/OP_CONST_WIDE_HIGH16.S */
599 /* const-wide/high16 vAA, #+BBBB000000000000 */
600 movzwl 2(rPC),%eax # eax<- 0000BBBB
601 movzbl rINST_HI,%ecx # ecx<- AA
602 FETCH_INST_WORD(2)
603 ADVANCE_PC(2)
604 sall $16,%eax # eax<- BBBB0000
605 SET_VREG_WORD(%eax,%ecx,1) # v[AA+1]<- eax
606 xorl %eax,%eax
607 SET_VREG_WORD(%eax,%ecx,0) # v[AA+0]<- eax
608 GOTO_NEXT
609
610
611/* ------------------------------ */
612 .balign 64
613.L_OP_CONST_STRING: /* 0x1a */
614/* File: x86/OP_CONST_STRING.S */
615
616 /* const/string vAA, String@BBBB */
617 GET_GLUE(%ecx)
618 movzwl 2(rPC),%eax # eax<- BBBB
619 movl offGlue_methodClassDex(%ecx),%ecx# ecx<- glue->methodClassDex
620 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
621 movl offDvmDex_pResStrings(%ecx),%ecx # ecx<- dvmDex->pResStrings
622 movl (%ecx,%eax,4),%eax # eax<- rResString[BBBB]
623 movl rINST_FULL,%ecx
624 FETCH_INST_WORD(2)
625 testl %eax,%eax # resolved yet?
626 je .LOP_CONST_STRING_resolve
627 SET_VREG(%eax,%ecx) # vAA<- rResString[BBBB]
628 ADVANCE_PC(2)
629 GOTO_NEXT
630
631/* ------------------------------ */
632 .balign 64
633.L_OP_CONST_STRING_JUMBO: /* 0x1b */
634/* File: x86/OP_CONST_STRING_JUMBO.S */
635
636 /* const/string vAA, String@BBBBBBBB */
637 GET_GLUE(%ecx)
638 movl 2(rPC),%eax # eax<- BBBBBBBB
639 movl offGlue_methodClassDex(%ecx),%ecx# ecx<- glue->methodClassDex
640 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
641 movl offDvmDex_pResStrings(%ecx),%ecx # ecx<- dvmDex->pResStrings
642 movl (%ecx,%eax,4),%eax # eax<- rResString[BBBB]
643 movl rINST_FULL,%ecx
644 FETCH_INST_WORD(3)
645 testl %eax,%eax # resolved yet?
646 je .LOP_CONST_STRING_JUMBO_resolve
647 SET_VREG(%eax,%ecx) # vAA<- rResString[BBBB]
648 ADVANCE_PC(3)
649 GOTO_NEXT
650
651/* ------------------------------ */
652 .balign 64
653.L_OP_CONST_CLASS: /* 0x1c */
654/* File: x86/OP_CONST_CLASS.S */
655
656 /* const/class vAA, Class@BBBB */
657 GET_GLUE(%ecx)
658 movzwl 2(rPC),%eax # eax<- BBBB
659 movl offGlue_methodClassDex(%ecx),%ecx# ecx<- glue->methodClassDex
660 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
661 movl offDvmDex_pResClasses(%ecx),%ecx # ecx<- dvmDex->pResClasses
662 movl (%ecx,%eax,4),%eax # eax<- rResClasses[BBBB]
663 movl rINST_FULL,%ecx
664 FETCH_INST_WORD(2)
665 testl %eax,%eax # resolved yet?
666 je .LOP_CONST_CLASS_resolve
667 SET_VREG(%eax,%ecx) # vAA<- rResClasses[BBBB]
668 ADVANCE_PC(2)
669 GOTO_NEXT
670
671/* ------------------------------ */
672 .balign 64
673.L_OP_MONITOR_ENTER: /* 0x1d */
674/* File: x86/OP_MONITOR_ENTER.S */
675 /*
676 * Synchronize on an object.
677 */
678 /* monitor-enter vAA */
679 GET_GLUE(%ecx)
680 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
681 GET_VREG(%eax,rINST_FULL) # eax<- vAA
682 movl offGlue_self(%ecx),%ecx # ecx<- glue->self
683 FETCH_INST_WORD(1)
684 testl %eax,%eax # null object?
The Android Open Source Project99409882009-03-18 22:20:24 -0700685 EXPORT_PC() # need for precise GC, MONITOR_TRACKING
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800686 jne .LOP_MONITOR_ENTER_continue
687 jmp common_errNullObject
688
689/* ------------------------------ */
690 .balign 64
691.L_OP_MONITOR_EXIT: /* 0x1e */
692/* File: x86/OP_MONITOR_EXIT.S */
693 /*
694 * Unlock an object.
695 *
696 * Exceptions that occur when unlocking a monitor need to appear as
697 * if they happened at the following instruction. See the Dalvik
698 * instruction spec.
699 */
700 /* monitor-exit vAA */
701 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
702 GET_VREG(%eax,rINST_FULL)
703 GET_GLUE(%ecx)
704 EXPORT_PC()
705 testl %eax,%eax # null object?
706 je common_errNullObject # go if so
707 movl offGlue_self(%ecx),%ecx # ecx<- glue->self
708 movl %eax,OUT_ARG1(%esp)
709 SPILL(rPC)
710 movl %ecx,OUT_ARG0(%esp)
711 jmp .LOP_MONITOR_EXIT_continue
712
713/* ------------------------------ */
714 .balign 64
715.L_OP_CHECK_CAST: /* 0x1f */
716/* File: x86/OP_CHECK_CAST.S */
717 /*
718 * Check to see if a cast from one class to another is allowed.
719 */
720 /* check-cast vAA, class@BBBB */
721 GET_GLUE(%ecx)
722 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
723 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- vAA (object)
724 movzwl 2(rPC),%eax # eax<- BBBB
725 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
726 testl rINST_FULL,rINST_FULL # is oject null?
727 movl offDvmDex_pResClasses(%ecx),%ecx # ecx<- pDvmDex->pResClasses
728 je .LOP_CHECK_CAST_okay # null obj, cast always succeeds
729 movl (%ecx,%eax,4),%eax # eax<- resolved class
730 movl offObject_clazz(rINST_FULL),%ecx # ecx<- obj->clazz
731 testl %eax,%eax # have we resolved this before?
732 je .LOP_CHECK_CAST_resolve # no, go do it now
733.LOP_CHECK_CAST_resolved:
734 cmpl %eax,%ecx # same class (trivial success)?
735 jne .LOP_CHECK_CAST_fullcheck # no, do full check
736.LOP_CHECK_CAST_okay:
737 FETCH_INST_WORD(2)
738 ADVANCE_PC(2)
739 GOTO_NEXT
740
741/* ------------------------------ */
742 .balign 64
743.L_OP_INSTANCE_OF: /* 0x20 */
744/* File: x86/OP_INSTANCE_OF.S */
745 /*
746 * Check to see if an object reference is an instance of a class.
747 *
748 * Most common situation is a non-null object, being compared against
749 * an already-resolved class.
750 */
751 /* instance-of vA, vB, class@CCCC */
752 movzbl rINST_HI,%eax # eax<- BA
753 sarl $4,%eax # eax<- B
754 GET_VREG(%eax,%eax) # eax<- vB (obj)
755 GET_GLUE(%ecx)
756 testl %eax,%eax # object null?
757 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
758 SPILL(rPC)
759 je .LOP_INSTANCE_OF_store # null obj, not instance, store it
760 movzwl 2(rPC),rPC # rPC<- CCCC
761 movl offDvmDex_pResClasses(%ecx),%ecx # ecx<- pDvmDex->pResClasses
762 movl (%ecx,rPC,4),%ecx # ecx<- resolved class
763 movl offObject_clazz(%eax),%eax # eax<- obj->clazz
764 testl %ecx,%ecx # have we resolved this before?
765 je .LOP_INSTANCE_OF_resolve # not resolved, do it now
766.LOP_INSTANCE_OF_resolved: # eax<- obj->clazz, ecx<- resolved class
767 cmpl %eax,%ecx # same class (trivial success)?
768 je .LOP_INSTANCE_OF_trivial # yes, trivial finish
769 jmp .LOP_INSTANCE_OF_fullcheck # no, do full check
770
771/* ------------------------------ */
772 .balign 64
773.L_OP_ARRAY_LENGTH: /* 0x21 */
774/* File: x86/OP_ARRAY_LENGTH.S */
775 /*
776 * Return the length of an array.
777 */
778 movzbl rINST_HI,%eax # eax<- BA
779 sarl $12,rINST_FULL # rINST_FULL<- B
780 GET_VREG(%ecx,rINST_FULL) # ecx<- vB (object ref)
781 andb $0xf,%al # eax<- A
782 testl %ecx,%ecx # is null?
783 je common_errNullObject
784 FETCH_INST_WORD(1)
785 movl offArrayObject_length(%ecx),%ecx
786 ADVANCE_PC(1)
787 SET_VREG(%ecx,%eax)
788 GOTO_NEXT
789
790/* ------------------------------ */
791 .balign 64
792.L_OP_NEW_INSTANCE: /* 0x22 */
793/* File: x86/OP_NEW_INSTANCE.S */
794 /*
795 * Create a new instance of a class.
796 */
797 /* new-instance vAA, class@BBBB */
798 GET_GLUE(%ecx)
799 movzwl 2(rPC),%eax # eax<- BBBB
800 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
801 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
802 movl offDvmDex_pResClasses(%ecx),%ecx # ecx<- pDvmDex->pResClasses
803 EXPORT_PC()
804 movl (%ecx,%eax,4),%ecx # ecx<- resolved class
805 SPILL(rPC)
806 testl %ecx,%ecx # resolved?
807 je .LOP_NEW_INSTANCE_resolve # no, go do it
808.LOP_NEW_INSTANCE_resolved: # on entry, ecx<- class
809 cmpb $CLASS_INITIALIZED,offClassObject_status(%ecx)
810 je .LOP_NEW_INSTANCE_initialized
811 jmp .LOP_NEW_INSTANCE_needinit
812
813/* ------------------------------ */
814 .balign 64
815.L_OP_NEW_ARRAY: /* 0x23 */
816/* File: x86/OP_NEW_ARRAY.S */
817 /*
818 * Allocate an array of objects, specified with the array class
819 * and a count.
820 *
821 * The verifier guarantees that this is an array class, so we don't
822 * check for it here.
823 */
824 /* new-array vA, vB, class@CCCC */
825 GET_GLUE(%ecx)
826 EXPORT_PC()
827 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
828 movzwl 2(rPC),%eax # eax<- CCCC
829 movl offDvmDex_pResClasses(%ecx),%ecx # ecx<- pDvmDex->pResClasses
830 movl (%ecx,%eax,4),%ecx # ecx<- resolved class
831 movzbl rINST_HI,%eax
832 sarl $4,%eax # eax<- B
833 GET_VREG(%eax,%eax) # eax<- vB (array length)
834 movzbl rINST_HI,rINST_FULL
835 andb $0xf,rINST_LO # rINST_FULL<- A
836 testl %eax,%eax
837 js common_errNegativeArraySize # bail
838 testl %ecx,%ecx # already resolved?
839 jne .LOP_NEW_ARRAY_finish # yes, fast path
840 jmp .LOP_NEW_ARRAY_resolve # resolve now
841
842/* ------------------------------ */
843 .balign 64
844.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
845/* File: x86/OP_FILLED_NEW_ARRAY.S */
846 /*
847 * Create a new array with elements filled from registers.
848 *
849 * for: filled-new-array, filled-new-array/range
850 */
851 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
852 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
853 GET_GLUE(%eax)
854 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA or BA
855 movl offGlue_methodClassDex(%eax),%eax # eax<- pDvmDex
856 movzwl 2(rPC),%ecx # ecx<- BBBB
857 movl offDvmDex_pResClasses(%eax),%eax # eax<- pDvmDex->pResClasses
858 SPILL(rPC)
859 movl (%eax,%ecx,4),%eax # eax<- resolved class
860 EXPORT_PC()
861 testl %eax,%eax # already resolved?
862 jne .LOP_FILLED_NEW_ARRAY_continue # yes, continue
863 # less frequent path, so we'll redo some work
864 GET_GLUE(%eax)
865 movl $0,OUT_ARG2(%esp) # arg2<- false
866 movl %ecx,OUT_ARG1(%esp) # arg1<- BBBB
867 movl offGlue_method(%eax),%eax # eax<- glue->method
868 jmp .LOP_FILLED_NEW_ARRAY_more
869
870/* ------------------------------ */
871 .balign 64
872.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
873/* File: x86/OP_FILLED_NEW_ARRAY_RANGE.S */
874/* File: x86/OP_FILLED_NEW_ARRAY.S */
875 /*
876 * Create a new array with elements filled from registers.
877 *
878 * for: filled-new-array, filled-new-array/range
879 */
880 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
881 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
882 GET_GLUE(%eax)
883 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA or BA
884 movl offGlue_methodClassDex(%eax),%eax # eax<- pDvmDex
885 movzwl 2(rPC),%ecx # ecx<- BBBB
886 movl offDvmDex_pResClasses(%eax),%eax # eax<- pDvmDex->pResClasses
887 SPILL(rPC)
888 movl (%eax,%ecx,4),%eax # eax<- resolved class
889 EXPORT_PC()
890 testl %eax,%eax # already resolved?
891 jne .LOP_FILLED_NEW_ARRAY_RANGE_continue # yes, continue
892 # less frequent path, so we'll redo some work
893 GET_GLUE(%eax)
894 movl $0,OUT_ARG2(%esp) # arg2<- false
895 movl %ecx,OUT_ARG1(%esp) # arg1<- BBBB
896 movl offGlue_method(%eax),%eax # eax<- glue->method
897 jmp .LOP_FILLED_NEW_ARRAY_RANGE_more
898
899
900/* ------------------------------ */
901 .balign 64
902.L_OP_FILL_ARRAY_DATA: /* 0x26 */
903/* File: x86/OP_FILL_ARRAY_DATA.S */
904 /* fill-array-data vAA, +BBBBBBBB */
905 movl 2(rPC),%ecx # ecx<- BBBBbbbb
906 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
907 leal (rPC,%ecx,2),%ecx # ecx<- PC + BBBBbbbb*2
908 GET_VREG(%eax,rINST_FULL)
909 SPILL(rPC)
910 EXPORT_PC()
911 movl %eax,OUT_ARG0(%esp)
912 movl %ecx,OUT_ARG1(%esp)
913 call dvmInterpHandleFillArrayData
914 UNSPILL(rPC)
915 FETCH_INST_WORD(3)
916 testl %eax,%eax # exception thrown?
917 je common_exceptionThrown
918 ADVANCE_PC(3)
919 GOTO_NEXT
920
921/* ------------------------------ */
922 .balign 64
923.L_OP_THROW: /* 0x27 */
924/* File: x86/OP_THROW.S */
925 /*
926 * Throw an exception object in the current thread.
927 */
928 /* throw vAA */
929 GET_GLUE(%ecx)
930 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
931 GET_VREG(%eax,rINST_FULL) # eax<- exception object
932 movl offGlue_self(%ecx),%ecx # ecx<- glue->self
933 testl %eax,%eax # null object?
934 je common_errNullObject
935 movl %eax,offThread_exception(%ecx) # thread->exception<- obj
936 jmp common_exceptionThrown
937
938/* ------------------------------ */
939 .balign 64
940.L_OP_GOTO: /* 0x28 */
941/* File: x86/OP_GOTO.S */
942 /*
943 * Unconditional branch, 8-bit offset.
944 *
945 * The branch distance is a signed code-unit offset, which we need to
946 * double to get a byte offset.
947 */
948 /* goto +AA */
949 movsbl rINST_HI,rINST_FULL # ebx<- ssssssAA
950 testl rINST_FULL,rINST_FULL # test for <0
951 js common_backwardBranch
952 movl rINST_FULL,%eax
953 FETCH_INST_INDEXED(%eax)
954 ADVANCE_PC_INDEXED(%eax)
955 GOTO_NEXT
956
957/* ------------------------------ */
958 .balign 64
959.L_OP_GOTO_16: /* 0x29 */
960/* File: x86/OP_GOTO_16.S */
961 /*
962 * Unconditional branch, 16-bit offset.
963 *
964 * The branch distance is a signed code-unit offset
965 */
966 /* goto/16 +AAAA */
967 movswl 2(rPC),rINST_FULL # rINST_FULL<- ssssAAAA
968 testl rINST_FULL,rINST_FULL # test for <0
969 js common_backwardBranch
970 movl rINST_FULL,%eax
971 FETCH_INST_INDEXED(%eax)
972 ADVANCE_PC_INDEXED(%eax)
973 GOTO_NEXT
974
975/* ------------------------------ */
976 .balign 64
977.L_OP_GOTO_32: /* 0x2a */
978/* File: x86/OP_GOTO_32.S */
979 /*
980 * Unconditional branch, 32-bit offset.
981 *
982 * The branch distance is a signed code-unit offset.
983 *
984 * Unlike most opcodes, this one is allowed to branch to itself, so
985 * our "backward branch" test must be "<=0" instead of "<0".
986 */
987 /* goto/32 AAAAAAAA */
988 movl 2(rPC),rINST_FULL # rINST_FULL<- AAAAAAAA
989 cmpl $0,rINST_FULL # test for <= 0
990 jle common_backwardBranch
991 movl rINST_FULL,%eax
992 FETCH_INST_INDEXED(%eax)
993 ADVANCE_PC_INDEXED(%eax)
994 GOTO_NEXT
995
996/* ------------------------------ */
997 .balign 64
998.L_OP_PACKED_SWITCH: /* 0x2b */
999/* File: x86/OP_PACKED_SWITCH.S */
1000 /*
1001 * Handle a packed-switch or sparse-switch instruction. In both cases
1002 * we decode it and hand it off to a helper function.
1003 *
1004 * We don't really expect backward branches in a switch statement, but
1005 * they're perfectly legal, so we check for them here.
1006 *
1007 * for: packed-switch, sparse-switch
1008 */
1009 /* op vAA, +BBBB */
1010 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
1011 movl 2(rPC),%ecx # ecx<- BBBBbbbb
1012 GET_VREG(%eax,rINST_FULL) # eax<- vAA
1013 leal (rPC,%ecx,2),%ecx # ecx<- PC + BBBBbbbb*2
1014 movl %eax,OUT_ARG1(%esp) # ARG1<- vAA
1015 movl %ecx,OUT_ARG0(%esp) # ARG0<- switchData
1016 SPILL(rPC)
1017 call dvmInterpHandlePackedSwitch
1018 UNSPILL(rPC)
1019 testl %eax,%eax
1020 movl %eax,rINST_FULL # set up word offset
1021 jle common_backwardBranch # check on special actions
1022 ADVANCE_PC_INDEXED(rINST_FULL)
1023 FETCH_INST()
1024 GOTO_NEXT
1025
1026/* ------------------------------ */
1027 .balign 64
1028.L_OP_SPARSE_SWITCH: /* 0x2c */
1029/* File: x86/OP_SPARSE_SWITCH.S */
1030/* File: x86/OP_PACKED_SWITCH.S */
1031 /*
1032 * Handle a packed-switch or sparse-switch instruction. In both cases
1033 * we decode it and hand it off to a helper function.
1034 *
1035 * We don't really expect backward branches in a switch statement, but
1036 * they're perfectly legal, so we check for them here.
1037 *
1038 * for: packed-switch, sparse-switch
1039 */
1040 /* op vAA, +BBBB */
1041 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
1042 movl 2(rPC),%ecx # ecx<- BBBBbbbb
1043 GET_VREG(%eax,rINST_FULL) # eax<- vAA
1044 leal (rPC,%ecx,2),%ecx # ecx<- PC + BBBBbbbb*2
1045 movl %eax,OUT_ARG1(%esp) # ARG1<- vAA
1046 movl %ecx,OUT_ARG0(%esp) # ARG0<- switchData
1047 SPILL(rPC)
1048 call dvmInterpHandleSparseSwitch
1049 UNSPILL(rPC)
1050 testl %eax,%eax
1051 movl %eax,rINST_FULL # set up word offset
1052 jle common_backwardBranch # check on special actions
1053 ADVANCE_PC_INDEXED(rINST_FULL)
1054 FETCH_INST()
1055 GOTO_NEXT
1056
1057
1058/* ------------------------------ */
1059 .balign 64
1060.L_OP_CMPL_FLOAT: /* 0x2d */
1061/* File: x86/OP_CMPL_FLOAT.S */
1062/* File: x86/OP_CMPG_DOUBLE.S */
1063 /* float/double_cmp[gl] vAA, vBB, vCC */
1064 movzbl 3(rPC),%eax # eax<- CC
1065 movzbl 2(rPC),%ecx # ecx<- BB
1066 .if 0
1067 fldl (rFP,%eax,4)
1068 fldl (rFP,%ecx,4)
1069 .else
1070 flds (rFP,%eax,4)
1071 flds (rFP,%ecx,4)
1072 .endif
1073 movzbl rINST_HI,rINST_FULL
1074 xorl %ecx,%ecx
1075 fucompp # z if equal, p set if NaN, c set if st0 < st1
1076 fnstsw %ax
1077 sahf
1078 movl rINST_FULL,%eax
1079 FETCH_INST_WORD(2)
1080 jp .LOP_CMPL_FLOAT_isNaN
1081 je .LOP_CMPL_FLOAT_finish
1082 sbbl %ecx,%ecx
1083 jb .LOP_CMPL_FLOAT_finish
1084 incl %ecx
1085.LOP_CMPL_FLOAT_finish:
1086 SET_VREG(%ecx,%eax)
1087 ADVANCE_PC(2)
1088 GOTO_NEXT
1089
1090
1091/* ------------------------------ */
1092 .balign 64
1093.L_OP_CMPG_FLOAT: /* 0x2e */
1094/* File: x86/OP_CMPG_FLOAT.S */
1095/* File: x86/OP_CMPG_DOUBLE.S */
1096 /* float/double_cmp[gl] vAA, vBB, vCC */
1097 movzbl 3(rPC),%eax # eax<- CC
1098 movzbl 2(rPC),%ecx # ecx<- BB
1099 .if 0
1100 fldl (rFP,%eax,4)
1101 fldl (rFP,%ecx,4)
1102 .else
1103 flds (rFP,%eax,4)
1104 flds (rFP,%ecx,4)
1105 .endif
1106 movzbl rINST_HI,rINST_FULL
1107 xorl %ecx,%ecx
1108 fucompp # z if equal, p set if NaN, c set if st0 < st1
1109 fnstsw %ax
1110 sahf
1111 movl rINST_FULL,%eax
1112 FETCH_INST_WORD(2)
1113 jp .LOP_CMPG_FLOAT_isNaN
1114 je .LOP_CMPG_FLOAT_finish
1115 sbbl %ecx,%ecx
1116 jb .LOP_CMPG_FLOAT_finish
1117 incl %ecx
1118.LOP_CMPG_FLOAT_finish:
1119 SET_VREG(%ecx,%eax)
1120 ADVANCE_PC(2)
1121 GOTO_NEXT
1122
1123
1124/* ------------------------------ */
1125 .balign 64
1126.L_OP_CMPL_DOUBLE: /* 0x2f */
1127/* File: x86/OP_CMPL_DOUBLE.S */
1128/* File: x86/OP_CMPG_DOUBLE.S */
1129 /* float/double_cmp[gl] vAA, vBB, vCC */
1130 movzbl 3(rPC),%eax # eax<- CC
1131 movzbl 2(rPC),%ecx # ecx<- BB
1132 .if 1
1133 fldl (rFP,%eax,4)
1134 fldl (rFP,%ecx,4)
1135 .else
1136 flds (rFP,%eax,4)
1137 flds (rFP,%ecx,4)
1138 .endif
1139 movzbl rINST_HI,rINST_FULL
1140 xorl %ecx,%ecx
1141 fucompp # z if equal, p set if NaN, c set if st0 < st1
1142 fnstsw %ax
1143 sahf
1144 movl rINST_FULL,%eax
1145 FETCH_INST_WORD(2)
1146 jp .LOP_CMPL_DOUBLE_isNaN
1147 je .LOP_CMPL_DOUBLE_finish
1148 sbbl %ecx,%ecx
1149 jb .LOP_CMPL_DOUBLE_finish
1150 incl %ecx
1151.LOP_CMPL_DOUBLE_finish:
1152 SET_VREG(%ecx,%eax)
1153 ADVANCE_PC(2)
1154 GOTO_NEXT
1155
1156
1157/* ------------------------------ */
1158 .balign 64
1159.L_OP_CMPG_DOUBLE: /* 0x30 */
1160/* File: x86/OP_CMPG_DOUBLE.S */
1161 /* float/double_cmp[gl] vAA, vBB, vCC */
1162 movzbl 3(rPC),%eax # eax<- CC
1163 movzbl 2(rPC),%ecx # ecx<- BB
1164 .if 1
1165 fldl (rFP,%eax,4)
1166 fldl (rFP,%ecx,4)
1167 .else
1168 flds (rFP,%eax,4)
1169 flds (rFP,%ecx,4)
1170 .endif
1171 movzbl rINST_HI,rINST_FULL
1172 xorl %ecx,%ecx
1173 fucompp # z if equal, p set if NaN, c set if st0 < st1
1174 fnstsw %ax
1175 sahf
1176 movl rINST_FULL,%eax
1177 FETCH_INST_WORD(2)
1178 jp .LOP_CMPG_DOUBLE_isNaN
1179 je .LOP_CMPG_DOUBLE_finish
1180 sbbl %ecx,%ecx
1181 jb .LOP_CMPG_DOUBLE_finish
1182 incl %ecx
1183.LOP_CMPG_DOUBLE_finish:
1184 SET_VREG(%ecx,%eax)
1185 ADVANCE_PC(2)
1186 GOTO_NEXT
1187
1188/* ------------------------------ */
1189 .balign 64
1190.L_OP_CMP_LONG: /* 0x31 */
1191/* File: x86/OP_CMP_LONG.S */
1192 /*
1193 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination
1194 * register based on the results of the comparison.
1195 */
1196 /* cmp-long vAA, vBB, vCC */
1197 movzbl 2(rPC),%ecx # ecx<- BB
1198 SPILL(rPC)
1199 movzbl 3(rPC),rPC # rPC<- CC
1200 GET_VREG_WORD(%eax,%ecx,1) # eax<- v[BB+1]
1201 GET_VREG_WORD(%ecx,%ecx,0) # ecx<- v[BB+0]
1202 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
1203 cmpl 4(rFP,rPC,4),%eax
1204 jl .LOP_CMP_LONG_smaller
1205 jg .LOP_CMP_LONG_bigger
1206 sub (rFP,rPC,4),%ecx
1207 ja .LOP_CMP_LONG_bigger
1208 jb .LOP_CMP_LONG_smaller
1209 UNSPILL(rPC)
1210 jmp .LOP_CMP_LONG_finish
1211
1212/* ------------------------------ */
1213 .balign 64
1214.L_OP_IF_EQ: /* 0x32 */
1215/* File: x86/OP_IF_EQ.S */
1216/* File: x86/bincmp.S */
1217 /*
1218 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1219 * fragment that specifies the *reverse* comparison to perform, e.g.
1220 * for "if-le" you would use "gt".
1221 *
1222 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1223 */
1224 /* if-cmp vA, vB, +CCCC */
1225 movzx rINST_HI,%ecx # ecx <- A+
1226 andb $0xf,%cl # ecx <- A
1227 GET_VREG(%eax,%ecx) # eax <- vA
1228 sarl $12,rINST_FULL # rINST_FULL<- B
1229 cmpl (rFP,rINST_FULL,4),%eax # compare (vA, vB)
1230 movswl 2(rPC),rINST_FULL # Get signed branch offset
1231 movl $2,%eax # assume not taken
1232 jne 1f
1233 testl rINST_FULL,rINST_FULL
1234 js common_backwardBranch
1235 movl rINST_FULL,%eax
12361:
1237 FETCH_INST_INDEXED(%eax)
1238 ADVANCE_PC_INDEXED(%eax)
1239 GOTO_NEXT
1240 GOTO_NEXT
1241
1242
1243/* ------------------------------ */
1244 .balign 64
1245.L_OP_IF_NE: /* 0x33 */
1246/* File: x86/OP_IF_NE.S */
1247/* File: x86/bincmp.S */
1248 /*
1249 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1250 * fragment that specifies the *reverse* comparison to perform, e.g.
1251 * for "if-le" you would use "gt".
1252 *
1253 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1254 */
1255 /* if-cmp vA, vB, +CCCC */
1256 movzx rINST_HI,%ecx # ecx <- A+
1257 andb $0xf,%cl # ecx <- A
1258 GET_VREG(%eax,%ecx) # eax <- vA
1259 sarl $12,rINST_FULL # rINST_FULL<- B
1260 cmpl (rFP,rINST_FULL,4),%eax # compare (vA, vB)
1261 movswl 2(rPC),rINST_FULL # Get signed branch offset
1262 movl $2,%eax # assume not taken
1263 je 1f
1264 testl rINST_FULL,rINST_FULL
1265 js common_backwardBranch
1266 movl rINST_FULL,%eax
12671:
1268 FETCH_INST_INDEXED(%eax)
1269 ADVANCE_PC_INDEXED(%eax)
1270 GOTO_NEXT
1271 GOTO_NEXT
1272
1273
1274/* ------------------------------ */
1275 .balign 64
1276.L_OP_IF_LT: /* 0x34 */
1277/* File: x86/OP_IF_LT.S */
1278/* File: x86/bincmp.S */
1279 /*
1280 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1281 * fragment that specifies the *reverse* comparison to perform, e.g.
1282 * for "if-le" you would use "gt".
1283 *
1284 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1285 */
1286 /* if-cmp vA, vB, +CCCC */
1287 movzx rINST_HI,%ecx # ecx <- A+
1288 andb $0xf,%cl # ecx <- A
1289 GET_VREG(%eax,%ecx) # eax <- vA
1290 sarl $12,rINST_FULL # rINST_FULL<- B
1291 cmpl (rFP,rINST_FULL,4),%eax # compare (vA, vB)
1292 movswl 2(rPC),rINST_FULL # Get signed branch offset
1293 movl $2,%eax # assume not taken
1294 jge 1f
1295 testl rINST_FULL,rINST_FULL
1296 js common_backwardBranch
1297 movl rINST_FULL,%eax
12981:
1299 FETCH_INST_INDEXED(%eax)
1300 ADVANCE_PC_INDEXED(%eax)
1301 GOTO_NEXT
1302 GOTO_NEXT
1303
1304
1305/* ------------------------------ */
1306 .balign 64
1307.L_OP_IF_GE: /* 0x35 */
1308/* File: x86/OP_IF_GE.S */
1309/* File: x86/bincmp.S */
1310 /*
1311 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1312 * fragment that specifies the *reverse* comparison to perform, e.g.
1313 * for "if-le" you would use "gt".
1314 *
1315 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1316 */
1317 /* if-cmp vA, vB, +CCCC */
1318 movzx rINST_HI,%ecx # ecx <- A+
1319 andb $0xf,%cl # ecx <- A
1320 GET_VREG(%eax,%ecx) # eax <- vA
1321 sarl $12,rINST_FULL # rINST_FULL<- B
1322 cmpl (rFP,rINST_FULL,4),%eax # compare (vA, vB)
1323 movswl 2(rPC),rINST_FULL # Get signed branch offset
1324 movl $2,%eax # assume not taken
1325 jl 1f
1326 testl rINST_FULL,rINST_FULL
1327 js common_backwardBranch
1328 movl rINST_FULL,%eax
13291:
1330 FETCH_INST_INDEXED(%eax)
1331 ADVANCE_PC_INDEXED(%eax)
1332 GOTO_NEXT
1333 GOTO_NEXT
1334
1335
1336/* ------------------------------ */
1337 .balign 64
1338.L_OP_IF_GT: /* 0x36 */
1339/* File: x86/OP_IF_GT.S */
1340/* File: x86/bincmp.S */
1341 /*
1342 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1343 * fragment that specifies the *reverse* comparison to perform, e.g.
1344 * for "if-le" you would use "gt".
1345 *
1346 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1347 */
1348 /* if-cmp vA, vB, +CCCC */
1349 movzx rINST_HI,%ecx # ecx <- A+
1350 andb $0xf,%cl # ecx <- A
1351 GET_VREG(%eax,%ecx) # eax <- vA
1352 sarl $12,rINST_FULL # rINST_FULL<- B
1353 cmpl (rFP,rINST_FULL,4),%eax # compare (vA, vB)
1354 movswl 2(rPC),rINST_FULL # Get signed branch offset
1355 movl $2,%eax # assume not taken
1356 jle 1f
1357 testl rINST_FULL,rINST_FULL
1358 js common_backwardBranch
1359 movl rINST_FULL,%eax
13601:
1361 FETCH_INST_INDEXED(%eax)
1362 ADVANCE_PC_INDEXED(%eax)
1363 GOTO_NEXT
1364 GOTO_NEXT
1365
1366
1367/* ------------------------------ */
1368 .balign 64
1369.L_OP_IF_LE: /* 0x37 */
1370/* File: x86/OP_IF_LE.S */
1371/* File: x86/bincmp.S */
1372 /*
1373 * Generic two-operand compare-and-branch operation. Provide a "revcmp"
1374 * fragment that specifies the *reverse* comparison to perform, e.g.
1375 * for "if-le" you would use "gt".
1376 *
1377 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1378 */
1379 /* if-cmp vA, vB, +CCCC */
1380 movzx rINST_HI,%ecx # ecx <- A+
1381 andb $0xf,%cl # ecx <- A
1382 GET_VREG(%eax,%ecx) # eax <- vA
1383 sarl $12,rINST_FULL # rINST_FULL<- B
1384 cmpl (rFP,rINST_FULL,4),%eax # compare (vA, vB)
1385 movswl 2(rPC),rINST_FULL # Get signed branch offset
1386 movl $2,%eax # assume not taken
1387 jg 1f
1388 testl rINST_FULL,rINST_FULL
1389 js common_backwardBranch
1390 movl rINST_FULL,%eax
13911:
1392 FETCH_INST_INDEXED(%eax)
1393 ADVANCE_PC_INDEXED(%eax)
1394 GOTO_NEXT
1395 GOTO_NEXT
1396
1397
1398/* ------------------------------ */
1399 .balign 64
1400.L_OP_IF_EQZ: /* 0x38 */
1401/* File: x86/OP_IF_EQZ.S */
1402/* File: x86/zcmp.S */
1403 /*
1404 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1405 * fragment that specifies the *reverse* comparison to perform, e.g.
1406 * for "if-le" you would use "gt".
1407 *
1408 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1409 */
1410 /* if-cmp vAA, +BBBB */
1411 movzx rINST_HI,%ecx # ecx <- AA
1412 cmpl $0,(rFP,%ecx,4) # compare (vA, 0)
1413 movswl 2(rPC),rINST_FULL # fetch signed displacement
1414 movl $2,%eax # assume branch not taken
1415 jne 1f
1416 testl rINST_FULL,rINST_FULL
1417 js common_backwardBranch
1418 movl rINST_FULL,%eax
14191:
1420 FETCH_INST_INDEXED(%eax)
1421 ADVANCE_PC_INDEXED(%eax)
1422 GOTO_NEXT
1423
1424
1425
1426/* ------------------------------ */
1427 .balign 64
1428.L_OP_IF_NEZ: /* 0x39 */
1429/* File: x86/OP_IF_NEZ.S */
1430/* File: x86/zcmp.S */
1431 /*
1432 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1433 * fragment that specifies the *reverse* comparison to perform, e.g.
1434 * for "if-le" you would use "gt".
1435 *
1436 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1437 */
1438 /* if-cmp vAA, +BBBB */
1439 movzx rINST_HI,%ecx # ecx <- AA
1440 cmpl $0,(rFP,%ecx,4) # compare (vA, 0)
1441 movswl 2(rPC),rINST_FULL # fetch signed displacement
1442 movl $2,%eax # assume branch not taken
1443 je 1f
1444 testl rINST_FULL,rINST_FULL
1445 js common_backwardBranch
1446 movl rINST_FULL,%eax
14471:
1448 FETCH_INST_INDEXED(%eax)
1449 ADVANCE_PC_INDEXED(%eax)
1450 GOTO_NEXT
1451
1452
1453
1454/* ------------------------------ */
1455 .balign 64
1456.L_OP_IF_LTZ: /* 0x3a */
1457/* File: x86/OP_IF_LTZ.S */
1458/* File: x86/zcmp.S */
1459 /*
1460 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1461 * fragment that specifies the *reverse* comparison to perform, e.g.
1462 * for "if-le" you would use "gt".
1463 *
1464 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1465 */
1466 /* if-cmp vAA, +BBBB */
1467 movzx rINST_HI,%ecx # ecx <- AA
1468 cmpl $0,(rFP,%ecx,4) # compare (vA, 0)
1469 movswl 2(rPC),rINST_FULL # fetch signed displacement
1470 movl $2,%eax # assume branch not taken
1471 jge 1f
1472 testl rINST_FULL,rINST_FULL
1473 js common_backwardBranch
1474 movl rINST_FULL,%eax
14751:
1476 FETCH_INST_INDEXED(%eax)
1477 ADVANCE_PC_INDEXED(%eax)
1478 GOTO_NEXT
1479
1480
1481
1482/* ------------------------------ */
1483 .balign 64
1484.L_OP_IF_GEZ: /* 0x3b */
1485/* File: x86/OP_IF_GEZ.S */
1486/* File: x86/zcmp.S */
1487 /*
1488 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1489 * fragment that specifies the *reverse* comparison to perform, e.g.
1490 * for "if-le" you would use "gt".
1491 *
1492 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1493 */
1494 /* if-cmp vAA, +BBBB */
1495 movzx rINST_HI,%ecx # ecx <- AA
1496 cmpl $0,(rFP,%ecx,4) # compare (vA, 0)
1497 movswl 2(rPC),rINST_FULL # fetch signed displacement
1498 movl $2,%eax # assume branch not taken
1499 jl 1f
1500 testl rINST_FULL,rINST_FULL
1501 js common_backwardBranch
1502 movl rINST_FULL,%eax
15031:
1504 FETCH_INST_INDEXED(%eax)
1505 ADVANCE_PC_INDEXED(%eax)
1506 GOTO_NEXT
1507
1508
1509
1510/* ------------------------------ */
1511 .balign 64
1512.L_OP_IF_GTZ: /* 0x3c */
1513/* File: x86/OP_IF_GTZ.S */
1514/* File: x86/zcmp.S */
1515 /*
1516 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1517 * fragment that specifies the *reverse* comparison to perform, e.g.
1518 * for "if-le" you would use "gt".
1519 *
1520 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1521 */
1522 /* if-cmp vAA, +BBBB */
1523 movzx rINST_HI,%ecx # ecx <- AA
1524 cmpl $0,(rFP,%ecx,4) # compare (vA, 0)
1525 movswl 2(rPC),rINST_FULL # fetch signed displacement
1526 movl $2,%eax # assume branch not taken
1527 jle 1f
1528 testl rINST_FULL,rINST_FULL
1529 js common_backwardBranch
1530 movl rINST_FULL,%eax
15311:
1532 FETCH_INST_INDEXED(%eax)
1533 ADVANCE_PC_INDEXED(%eax)
1534 GOTO_NEXT
1535
1536
1537
1538/* ------------------------------ */
1539 .balign 64
1540.L_OP_IF_LEZ: /* 0x3d */
1541/* File: x86/OP_IF_LEZ.S */
1542/* File: x86/zcmp.S */
1543 /*
1544 * Generic one-operand compare-and-branch operation. Provide a "revcmp"
1545 * fragment that specifies the *reverse* comparison to perform, e.g.
1546 * for "if-le" you would use "gt".
1547 *
1548 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1549 */
1550 /* if-cmp vAA, +BBBB */
1551 movzx rINST_HI,%ecx # ecx <- AA
1552 cmpl $0,(rFP,%ecx,4) # compare (vA, 0)
1553 movswl 2(rPC),rINST_FULL # fetch signed displacement
1554 movl $2,%eax # assume branch not taken
1555 jg 1f
1556 testl rINST_FULL,rINST_FULL
1557 js common_backwardBranch
1558 movl rINST_FULL,%eax
15591:
1560 FETCH_INST_INDEXED(%eax)
1561 ADVANCE_PC_INDEXED(%eax)
1562 GOTO_NEXT
1563
1564
1565
1566/* ------------------------------ */
1567 .balign 64
1568.L_OP_UNUSED_3E: /* 0x3e */
1569/* File: x86/OP_UNUSED_3E.S */
1570/* File: x86/unused.S */
1571 jmp common_abort
1572
1573
1574/* ------------------------------ */
1575 .balign 64
1576.L_OP_UNUSED_3F: /* 0x3f */
1577/* File: x86/OP_UNUSED_3F.S */
1578/* File: x86/unused.S */
1579 jmp common_abort
1580
1581
1582/* ------------------------------ */
1583 .balign 64
1584.L_OP_UNUSED_40: /* 0x40 */
1585/* File: x86/OP_UNUSED_40.S */
1586/* File: x86/unused.S */
1587 jmp common_abort
1588
1589
1590/* ------------------------------ */
1591 .balign 64
1592.L_OP_UNUSED_41: /* 0x41 */
1593/* File: x86/OP_UNUSED_41.S */
1594/* File: x86/unused.S */
1595 jmp common_abort
1596
1597
1598/* ------------------------------ */
1599 .balign 64
1600.L_OP_UNUSED_42: /* 0x42 */
1601/* File: x86/OP_UNUSED_42.S */
1602/* File: x86/unused.S */
1603 jmp common_abort
1604
1605
1606/* ------------------------------ */
1607 .balign 64
1608.L_OP_UNUSED_43: /* 0x43 */
1609/* File: x86/OP_UNUSED_43.S */
1610/* File: x86/unused.S */
1611 jmp common_abort
1612
1613
1614/* ------------------------------ */
1615 .balign 64
1616.L_OP_AGET: /* 0x44 */
1617/* File: x86/OP_AGET.S */
1618 /*
1619 * Array get, 32 bits or less. vAA <- vBB[vCC].
1620 *
1621 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1622 */
1623 /* op vAA, vBB, vCC */
1624 movzbl 2(rPC),%eax # eax<- BB
1625 movzbl 3(rPC),%ecx # ecx<- CC
1626 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
1627 GET_VREG(%eax,%eax) # eax<- vBB (array object)
1628 GET_VREG(%ecx,%ecx) # ecs<- vCC (requested index)
1629 testl %eax,%eax # null array object?
1630 je common_errNullObject # bail if so
1631 cmpl offArrayObject_length(%eax),%ecx
1632 jae common_errArrayIndex # index >= length, bail
1633 movl offArrayObject_contents(%eax,%ecx,4),%eax
1634 movl rINST_FULL,%ecx
1635 FETCH_INST_WORD(2)
1636 SET_VREG(%eax,%ecx)
1637 ADVANCE_PC(2)
1638 GOTO_NEXT
1639
1640
1641/* ------------------------------ */
1642 .balign 64
1643.L_OP_AGET_WIDE: /* 0x45 */
1644/* File: x86/OP_AGET_WIDE.S */
1645 /*
1646 * Array get, 64 bits. vAA <- vBB[vCC].
1647 *
1648 */
1649 /* op vAA, vBB, vCC */
1650 movzbl 2(rPC),%eax # eax<- BB
1651 movzbl 3(rPC),%ecx # ecx<- CC
1652 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
1653 GET_VREG(%eax,%eax) # eax<- vBB (array object)
1654 GET_VREG(%ecx,%ecx) # ecs<- vCC (requested index)
1655 testl %eax,%eax # null array object?
1656 je common_errNullObject # bail if so
1657 cmpl offArrayObject_length(%eax),%ecx
1658 jb .LOP_AGET_WIDE_finish # index < length, OK
1659 jmp common_errArrayIndex # index >= length, bail
1660
1661/* ------------------------------ */
1662 .balign 64
1663.L_OP_AGET_OBJECT: /* 0x46 */
1664/* File: x86/OP_AGET_OBJECT.S */
1665/* File: x86/OP_AGET.S */
1666 /*
1667 * Array get, 32 bits or less. vAA <- vBB[vCC].
1668 *
1669 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1670 */
1671 /* op vAA, vBB, vCC */
1672 movzbl 2(rPC),%eax # eax<- BB
1673 movzbl 3(rPC),%ecx # ecx<- CC
1674 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
1675 GET_VREG(%eax,%eax) # eax<- vBB (array object)
1676 GET_VREG(%ecx,%ecx) # ecs<- vCC (requested index)
1677 testl %eax,%eax # null array object?
1678 je common_errNullObject # bail if so
1679 cmpl offArrayObject_length(%eax),%ecx
1680 jae common_errArrayIndex # index >= length, bail
1681 movl offArrayObject_contents(%eax,%ecx,4),%eax
1682 movl rINST_FULL,%ecx
1683 FETCH_INST_WORD(2)
1684 SET_VREG(%eax,%ecx)
1685 ADVANCE_PC(2)
1686 GOTO_NEXT
1687
1688
1689
1690/* ------------------------------ */
1691 .balign 64
1692.L_OP_AGET_BOOLEAN: /* 0x47 */
1693/* File: x86/OP_AGET_BOOLEAN.S */
1694/* File: x86/OP_AGET.S */
1695 /*
1696 * Array get, 32 bits or less. vAA <- vBB[vCC].
1697 *
1698 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1699 */
1700 /* op vAA, vBB, vCC */
1701 movzbl 2(rPC),%eax # eax<- BB
1702 movzbl 3(rPC),%ecx # ecx<- CC
1703 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
1704 GET_VREG(%eax,%eax) # eax<- vBB (array object)
1705 GET_VREG(%ecx,%ecx) # ecs<- vCC (requested index)
1706 testl %eax,%eax # null array object?
1707 je common_errNullObject # bail if so
1708 cmpl offArrayObject_length(%eax),%ecx
1709 jae common_errArrayIndex # index >= length, bail
1710 movzbl offArrayObject_contents(%eax,%ecx,1),%eax
1711 movl rINST_FULL,%ecx
1712 FETCH_INST_WORD(2)
1713 SET_VREG(%eax,%ecx)
1714 ADVANCE_PC(2)
1715 GOTO_NEXT
1716
1717
1718
1719/* ------------------------------ */
1720 .balign 64
1721.L_OP_AGET_BYTE: /* 0x48 */
1722/* File: x86/OP_AGET_BYTE.S */
1723/* File: x86/OP_AGET.S */
1724 /*
1725 * Array get, 32 bits or less. vAA <- vBB[vCC].
1726 *
1727 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1728 */
1729 /* op vAA, vBB, vCC */
1730 movzbl 2(rPC),%eax # eax<- BB
1731 movzbl 3(rPC),%ecx # ecx<- CC
1732 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
1733 GET_VREG(%eax,%eax) # eax<- vBB (array object)
1734 GET_VREG(%ecx,%ecx) # ecs<- vCC (requested index)
1735 testl %eax,%eax # null array object?
1736 je common_errNullObject # bail if so
1737 cmpl offArrayObject_length(%eax),%ecx
1738 jae common_errArrayIndex # index >= length, bail
1739 movsbl offArrayObject_contents(%eax,%ecx,1),%eax
1740 movl rINST_FULL,%ecx
1741 FETCH_INST_WORD(2)
1742 SET_VREG(%eax,%ecx)
1743 ADVANCE_PC(2)
1744 GOTO_NEXT
1745
1746
1747
1748/* ------------------------------ */
1749 .balign 64
1750.L_OP_AGET_CHAR: /* 0x49 */
1751/* File: x86/OP_AGET_CHAR.S */
1752/* File: x86/OP_AGET.S */
1753 /*
1754 * Array get, 32 bits or less. vAA <- vBB[vCC].
1755 *
1756 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1757 */
1758 /* op vAA, vBB, vCC */
1759 movzbl 2(rPC),%eax # eax<- BB
1760 movzbl 3(rPC),%ecx # ecx<- CC
1761 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
1762 GET_VREG(%eax,%eax) # eax<- vBB (array object)
1763 GET_VREG(%ecx,%ecx) # ecs<- vCC (requested index)
1764 testl %eax,%eax # null array object?
1765 je common_errNullObject # bail if so
1766 cmpl offArrayObject_length(%eax),%ecx
1767 jae common_errArrayIndex # index >= length, bail
1768 movzwl offArrayObject_contents(%eax,%ecx,2),%eax
1769 movl rINST_FULL,%ecx
1770 FETCH_INST_WORD(2)
1771 SET_VREG(%eax,%ecx)
1772 ADVANCE_PC(2)
1773 GOTO_NEXT
1774
1775
1776
1777/* ------------------------------ */
1778 .balign 64
1779.L_OP_AGET_SHORT: /* 0x4a */
1780/* File: x86/OP_AGET_SHORT.S */
1781/* File: x86/OP_AGET.S */
1782 /*
1783 * Array get, 32 bits or less. vAA <- vBB[vCC].
1784 *
1785 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1786 */
1787 /* op vAA, vBB, vCC */
1788 movzbl 2(rPC),%eax # eax<- BB
1789 movzbl 3(rPC),%ecx # ecx<- CC
1790 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
1791 GET_VREG(%eax,%eax) # eax<- vBB (array object)
1792 GET_VREG(%ecx,%ecx) # ecs<- vCC (requested index)
1793 testl %eax,%eax # null array object?
1794 je common_errNullObject # bail if so
1795 cmpl offArrayObject_length(%eax),%ecx
1796 jae common_errArrayIndex # index >= length, bail
1797 movswl offArrayObject_contents(%eax,%ecx,2),%eax
1798 movl rINST_FULL,%ecx
1799 FETCH_INST_WORD(2)
1800 SET_VREG(%eax,%ecx)
1801 ADVANCE_PC(2)
1802 GOTO_NEXT
1803
1804
1805
1806/* ------------------------------ */
1807 .balign 64
1808.L_OP_APUT: /* 0x4b */
1809/* File: x86/OP_APUT.S */
1810 /*
1811 * Array put, 32 bits or less. vBB[vCC] <- vAA
1812 *
1813 * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
1814 */
1815 /* op vAA, vBB, vCC */
1816 movzbl 2(rPC),%eax # eax<- BB
1817 movzbl 3(rPC),%ecx # ecx<- CC
1818 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
1819 GET_VREG(%eax,%eax) # eax<- vBB (array object)
1820 GET_VREG(%ecx,%ecx) # ecs<- vCC (requested index)
1821 testl %eax,%eax # null array object?
1822 je common_errNullObject # bail if so
1823 cmpl offArrayObject_length(%eax),%ecx
1824 jae common_errArrayIndex # index >= length, bail
1825 leal offArrayObject_contents(%eax,%ecx,4),%eax
1826 GET_VREG(%ecx,rINST_FULL)
1827 FETCH_INST_WORD(2)
1828 movl %ecx,(%eax)
1829 ADVANCE_PC(2)
1830 GOTO_NEXT
1831
1832
1833/* ------------------------------ */
1834 .balign 64
1835.L_OP_APUT_WIDE: /* 0x4c */
1836/* File: x86/OP_APUT_WIDE.S */
1837 /*
1838 * Array put, 64 bits. vBB[vCC]<-vAA.
1839 *
1840 */
1841 /* op vAA, vBB, vCC */
1842 movzbl 2(rPC),%eax # eax<- BB
1843 movzbl 3(rPC),%ecx # ecx<- CC
1844 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
1845 GET_VREG(%eax,%eax) # eax<- vBB (array object)
1846 GET_VREG(%ecx,%ecx) # ecs<- vCC (requested index)
1847 testl %eax,%eax # null array object?
1848 je common_errNullObject # bail if so
1849 cmpl offArrayObject_length(%eax),%ecx
1850 jb .LOP_APUT_WIDE_finish # index < length, OK
1851 jmp common_errArrayIndex # index >= length, bail
1852
1853/* ------------------------------ */
1854 .balign 64
1855.L_OP_APUT_OBJECT: /* 0x4d */
1856/* File: x86/OP_APUT_OBJECT.S */
1857 /*
1858 * Array put, 32 bits or less. vBB[vCC] <- vAA
1859 *
1860 * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
1861 */
1862 /* op vAA, vBB, vCC */
1863 movzbl 2(rPC),%eax # eax<- BB
1864 movzbl 3(rPC),%ecx # ecx<- CC
1865 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
1866 GET_VREG(%eax,%eax) # eax<- vBB (array object)
1867 GET_VREG(%ecx,%ecx) # ecs<- vCC (requested index)
1868 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- vAA
1869 testl %eax,%eax # null array object?
1870 je common_errNullObject # bail if so
1871 cmpl offArrayObject_length(%eax),%ecx
1872 jb .LOP_APUT_OBJECT_continue
1873 jmp common_errArrayIndex # index >= length, bail
1874
1875/* ------------------------------ */
1876 .balign 64
1877.L_OP_APUT_BOOLEAN: /* 0x4e */
1878/* File: x86/OP_APUT_BOOLEAN.S */
1879/* File: x86/OP_APUT.S */
1880 /*
1881 * Array put, 32 bits or less. vBB[vCC] <- vAA
1882 *
1883 * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
1884 */
1885 /* op vAA, vBB, vCC */
1886 movzbl 2(rPC),%eax # eax<- BB
1887 movzbl 3(rPC),%ecx # ecx<- CC
1888 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
1889 GET_VREG(%eax,%eax) # eax<- vBB (array object)
1890 GET_VREG(%ecx,%ecx) # ecs<- vCC (requested index)
1891 testl %eax,%eax # null array object?
1892 je common_errNullObject # bail if so
1893 cmpl offArrayObject_length(%eax),%ecx
1894 jae common_errArrayIndex # index >= length, bail
1895 leal offArrayObject_contents(%eax,%ecx,1),%eax
1896 GET_VREG(%ecx,rINST_FULL)
1897 FETCH_INST_WORD(2)
1898 movb %cl,(%eax)
1899 ADVANCE_PC(2)
1900 GOTO_NEXT
1901
1902
1903
1904/* ------------------------------ */
1905 .balign 64
1906.L_OP_APUT_BYTE: /* 0x4f */
1907/* File: x86/OP_APUT_BYTE.S */
1908/* File: x86/OP_APUT.S */
1909 /*
1910 * Array put, 32 bits or less. vBB[vCC] <- vAA
1911 *
1912 * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
1913 */
1914 /* op vAA, vBB, vCC */
1915 movzbl 2(rPC),%eax # eax<- BB
1916 movzbl 3(rPC),%ecx # ecx<- CC
1917 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
1918 GET_VREG(%eax,%eax) # eax<- vBB (array object)
1919 GET_VREG(%ecx,%ecx) # ecs<- vCC (requested index)
1920 testl %eax,%eax # null array object?
1921 je common_errNullObject # bail if so
1922 cmpl offArrayObject_length(%eax),%ecx
1923 jae common_errArrayIndex # index >= length, bail
1924 leal offArrayObject_contents(%eax,%ecx,1),%eax
1925 GET_VREG(%ecx,rINST_FULL)
1926 FETCH_INST_WORD(2)
1927 movb %cl,(%eax)
1928 ADVANCE_PC(2)
1929 GOTO_NEXT
1930
1931
1932
1933/* ------------------------------ */
1934 .balign 64
1935.L_OP_APUT_CHAR: /* 0x50 */
1936/* File: x86/OP_APUT_CHAR.S */
1937/* File: x86/OP_APUT.S */
1938 /*
1939 * Array put, 32 bits or less. vBB[vCC] <- vAA
1940 *
1941 * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
1942 */
1943 /* op vAA, vBB, vCC */
1944 movzbl 2(rPC),%eax # eax<- BB
1945 movzbl 3(rPC),%ecx # ecx<- CC
1946 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
1947 GET_VREG(%eax,%eax) # eax<- vBB (array object)
1948 GET_VREG(%ecx,%ecx) # ecs<- vCC (requested index)
1949 testl %eax,%eax # null array object?
1950 je common_errNullObject # bail if so
1951 cmpl offArrayObject_length(%eax),%ecx
1952 jae common_errArrayIndex # index >= length, bail
1953 leal offArrayObject_contents(%eax,%ecx,2),%eax
1954 GET_VREG(%ecx,rINST_FULL)
1955 FETCH_INST_WORD(2)
1956 movw %cx,(%eax)
1957 ADVANCE_PC(2)
1958 GOTO_NEXT
1959
1960
1961
1962/* ------------------------------ */
1963 .balign 64
1964.L_OP_APUT_SHORT: /* 0x51 */
1965/* File: x86/OP_APUT_SHORT.S */
1966/* File: x86/OP_APUT.S */
1967 /*
1968 * Array put, 32 bits or less. vBB[vCC] <- vAA
1969 *
1970 * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
1971 */
1972 /* op vAA, vBB, vCC */
1973 movzbl 2(rPC),%eax # eax<- BB
1974 movzbl 3(rPC),%ecx # ecx<- CC
1975 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
1976 GET_VREG(%eax,%eax) # eax<- vBB (array object)
1977 GET_VREG(%ecx,%ecx) # ecs<- vCC (requested index)
1978 testl %eax,%eax # null array object?
1979 je common_errNullObject # bail if so
1980 cmpl offArrayObject_length(%eax),%ecx
1981 jae common_errArrayIndex # index >= length, bail
1982 leal offArrayObject_contents(%eax,%ecx,2),%eax
1983 GET_VREG(%ecx,rINST_FULL)
1984 FETCH_INST_WORD(2)
1985 movw %cx,(%eax)
1986 ADVANCE_PC(2)
1987 GOTO_NEXT
1988
1989
1990
1991/* ------------------------------ */
1992 .balign 64
1993.L_OP_IGET: /* 0x52 */
1994/* File: x86/OP_IGET.S */
1995 /*
1996 * General 32-bit instance field get.
1997 *
1998 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
1999 */
2000 /* op vA, vB, field@CCCC */
2001 GET_GLUE(%ecx)
2002 SPILL(rIBASE) # need another reg
2003 movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC
2004 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
2005 movzbl rINST_HI,%ecx # ecx<- BA
2006 sarl $4,%ecx # ecx<- B
2007 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
2008 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
2009 andb $0xf,rINST_LO # rINST_FULL<- A
2010 GET_VREG(%ecx,%ecx) # ecx<- fp[B], the object ptr
2011 movl (%eax,rIBASE,4),%eax # resolved entry
2012 testl %eax,%eax # is resolved entry null?
2013 jne .LOP_IGET_finish # no, already resolved
2014 movl rIBASE,OUT_ARG1(%esp) # needed by dvmResolveInstField
2015 GET_GLUE(rIBASE)
2016 jmp .LOP_IGET_resolve
2017
2018/* ------------------------------ */
2019 .balign 64
2020.L_OP_IGET_WIDE: /* 0x53 */
2021/* File: x86/OP_IGET_WIDE.S */
2022 /*
2023 * 64-bit instance field get.
2024 *
2025 */
2026 /* op vA, vB, field@CCCC */
2027 GET_GLUE(%ecx)
2028 SPILL(rIBASE) # need another reg
2029 movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC
2030 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
2031 movzbl rINST_HI,%ecx # ecx<- BA
2032 sarl $4,%ecx # ecx<- B
2033 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
2034 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
2035 andb $0xf,rINST_LO # rINST_FULL<- A
2036 GET_VREG(%ecx,%ecx) # ecx<- fp[B], the object ptr
2037 movl (%eax,rIBASE,4),%eax # resolved entry
2038 testl %eax,%eax # is resolved entry null?
2039 jne .LOP_IGET_WIDE_finish # no, already resolved
2040 movl rIBASE,OUT_ARG1(%esp) # needed by dvmResolveInstField
2041 GET_GLUE(rIBASE)
2042 jmp .LOP_IGET_WIDE_resolve
2043
2044/* ------------------------------ */
2045 .balign 64
2046.L_OP_IGET_OBJECT: /* 0x54 */
2047/* File: x86/OP_IGET_OBJECT.S */
2048/* File: x86/OP_IGET.S */
2049 /*
2050 * General 32-bit instance field get.
2051 *
2052 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2053 */
2054 /* op vA, vB, field@CCCC */
2055 GET_GLUE(%ecx)
2056 SPILL(rIBASE) # need another reg
2057 movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC
2058 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
2059 movzbl rINST_HI,%ecx # ecx<- BA
2060 sarl $4,%ecx # ecx<- B
2061 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
2062 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
2063 andb $0xf,rINST_LO # rINST_FULL<- A
2064 GET_VREG(%ecx,%ecx) # ecx<- fp[B], the object ptr
2065 movl (%eax,rIBASE,4),%eax # resolved entry
2066 testl %eax,%eax # is resolved entry null?
2067 jne .LOP_IGET_OBJECT_finish # no, already resolved
2068 movl rIBASE,OUT_ARG1(%esp) # needed by dvmResolveInstField
2069 GET_GLUE(rIBASE)
2070 jmp .LOP_IGET_OBJECT_resolve
2071
2072
2073/* ------------------------------ */
2074 .balign 64
2075.L_OP_IGET_BOOLEAN: /* 0x55 */
2076/* File: x86/OP_IGET_BOOLEAN.S */
2077/* File: x86/OP_IGET.S */
2078 /*
2079 * General 32-bit instance field get.
2080 *
2081 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2082 */
2083 /* op vA, vB, field@CCCC */
2084 GET_GLUE(%ecx)
2085 SPILL(rIBASE) # need another reg
2086 movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC
2087 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
2088 movzbl rINST_HI,%ecx # ecx<- BA
2089 sarl $4,%ecx # ecx<- B
2090 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
2091 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
2092 andb $0xf,rINST_LO # rINST_FULL<- A
2093 GET_VREG(%ecx,%ecx) # ecx<- fp[B], the object ptr
2094 movl (%eax,rIBASE,4),%eax # resolved entry
2095 testl %eax,%eax # is resolved entry null?
2096 jne .LOP_IGET_BOOLEAN_finish # no, already resolved
2097 movl rIBASE,OUT_ARG1(%esp) # needed by dvmResolveInstField
2098 GET_GLUE(rIBASE)
2099 jmp .LOP_IGET_BOOLEAN_resolve
2100
2101
2102/* ------------------------------ */
2103 .balign 64
2104.L_OP_IGET_BYTE: /* 0x56 */
2105/* File: x86/OP_IGET_BYTE.S */
2106/* File: x86/OP_IGET.S */
2107 /*
2108 * General 32-bit instance field get.
2109 *
2110 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2111 */
2112 /* op vA, vB, field@CCCC */
2113 GET_GLUE(%ecx)
2114 SPILL(rIBASE) # need another reg
2115 movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC
2116 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
2117 movzbl rINST_HI,%ecx # ecx<- BA
2118 sarl $4,%ecx # ecx<- B
2119 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
2120 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
2121 andb $0xf,rINST_LO # rINST_FULL<- A
2122 GET_VREG(%ecx,%ecx) # ecx<- fp[B], the object ptr
2123 movl (%eax,rIBASE,4),%eax # resolved entry
2124 testl %eax,%eax # is resolved entry null?
2125 jne .LOP_IGET_BYTE_finish # no, already resolved
2126 movl rIBASE,OUT_ARG1(%esp) # needed by dvmResolveInstField
2127 GET_GLUE(rIBASE)
2128 jmp .LOP_IGET_BYTE_resolve
2129
2130
2131/* ------------------------------ */
2132 .balign 64
2133.L_OP_IGET_CHAR: /* 0x57 */
2134/* File: x86/OP_IGET_CHAR.S */
2135/* File: x86/OP_IGET.S */
2136 /*
2137 * General 32-bit instance field get.
2138 *
2139 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2140 */
2141 /* op vA, vB, field@CCCC */
2142 GET_GLUE(%ecx)
2143 SPILL(rIBASE) # need another reg
2144 movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC
2145 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
2146 movzbl rINST_HI,%ecx # ecx<- BA
2147 sarl $4,%ecx # ecx<- B
2148 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
2149 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
2150 andb $0xf,rINST_LO # rINST_FULL<- A
2151 GET_VREG(%ecx,%ecx) # ecx<- fp[B], the object ptr
2152 movl (%eax,rIBASE,4),%eax # resolved entry
2153 testl %eax,%eax # is resolved entry null?
2154 jne .LOP_IGET_CHAR_finish # no, already resolved
2155 movl rIBASE,OUT_ARG1(%esp) # needed by dvmResolveInstField
2156 GET_GLUE(rIBASE)
2157 jmp .LOP_IGET_CHAR_resolve
2158
2159
2160/* ------------------------------ */
2161 .balign 64
2162.L_OP_IGET_SHORT: /* 0x58 */
2163/* File: x86/OP_IGET_SHORT.S */
2164/* File: x86/OP_IGET.S */
2165 /*
2166 * General 32-bit instance field get.
2167 *
2168 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2169 */
2170 /* op vA, vB, field@CCCC */
2171 GET_GLUE(%ecx)
2172 SPILL(rIBASE) # need another reg
2173 movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC
2174 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
2175 movzbl rINST_HI,%ecx # ecx<- BA
2176 sarl $4,%ecx # ecx<- B
2177 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
2178 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
2179 andb $0xf,rINST_LO # rINST_FULL<- A
2180 GET_VREG(%ecx,%ecx) # ecx<- fp[B], the object ptr
2181 movl (%eax,rIBASE,4),%eax # resolved entry
2182 testl %eax,%eax # is resolved entry null?
2183 jne .LOP_IGET_SHORT_finish # no, already resolved
2184 movl rIBASE,OUT_ARG1(%esp) # needed by dvmResolveInstField
2185 GET_GLUE(rIBASE)
2186 jmp .LOP_IGET_SHORT_resolve
2187
2188
2189/* ------------------------------ */
2190 .balign 64
2191.L_OP_IPUT: /* 0x59 */
2192/* File: x86/OP_IPUT.S */
2193
2194 /*
2195 * General 32-bit instance field put.
2196 *
2197 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2198 */
2199 /* op vA, vB, field@CCCC */
2200 GET_GLUE(%ecx)
2201 SPILL(rIBASE) # need another reg
2202 movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC
2203 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
2204 movzbl rINST_HI,%ecx # ecx<- BA
2205 sarl $4,%ecx # ecx<- B
2206 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
2207 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
2208 andb $0xf,rINST_LO # rINST_FULL<- A
2209 GET_VREG(%ecx,%ecx) # ecx<- fp[B], the object ptr
2210 movl (%eax,rIBASE,4),%eax # resolved entry
2211 testl %eax,%eax # is resolved entry null?
2212 jne .LOP_IPUT_finish # no, already resolved
2213 movl rIBASE,OUT_ARG1(%esp)
2214 GET_GLUE(rIBASE)
2215 jmp .LOP_IPUT_resolve
2216
2217/* ------------------------------ */
2218 .balign 64
2219.L_OP_IPUT_WIDE: /* 0x5a */
2220/* File: x86/OP_IPUT_WIDE.S */
2221 /*
2222 * 64-bit instance field put.
2223 *
2224 */
2225 /* op vA, vB, field@CCCC */
2226 GET_GLUE(%ecx)
2227 SPILL(rIBASE) # need another reg
2228 movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC
2229 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
2230 movzbl rINST_HI,%ecx # ecx<- BA
2231 sarl $4,%ecx # ecx<- B
2232 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
2233 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
2234 andb $0xf,rINST_LO # rINST_FULL<- A
2235 GET_VREG(%ecx,%ecx) # ecx<- fp[B], the object ptr
2236 movl (%eax,rIBASE,4),%eax # resolved entry
2237 testl %eax,%eax # is resolved entry null?
2238 jne .LOP_IPUT_WIDE_finish # no, already resolved
2239 movl rIBASE,OUT_ARG1(%esp)
2240 GET_GLUE(rIBASE)
2241 jmp .LOP_IPUT_WIDE_resolve
2242
2243/* ------------------------------ */
2244 .balign 64
2245.L_OP_IPUT_OBJECT: /* 0x5b */
2246/* File: x86/OP_IPUT_OBJECT.S */
2247/* File: x86/OP_IPUT.S */
2248
2249 /*
2250 * General 32-bit instance field put.
2251 *
2252 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2253 */
2254 /* op vA, vB, field@CCCC */
2255 GET_GLUE(%ecx)
2256 SPILL(rIBASE) # need another reg
2257 movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC
2258 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
2259 movzbl rINST_HI,%ecx # ecx<- BA
2260 sarl $4,%ecx # ecx<- B
2261 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
2262 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
2263 andb $0xf,rINST_LO # rINST_FULL<- A
2264 GET_VREG(%ecx,%ecx) # ecx<- fp[B], the object ptr
2265 movl (%eax,rIBASE,4),%eax # resolved entry
2266 testl %eax,%eax # is resolved entry null?
2267 jne .LOP_IPUT_OBJECT_finish # no, already resolved
2268 movl rIBASE,OUT_ARG1(%esp)
2269 GET_GLUE(rIBASE)
2270 jmp .LOP_IPUT_OBJECT_resolve
2271
2272
2273/* ------------------------------ */
2274 .balign 64
2275.L_OP_IPUT_BOOLEAN: /* 0x5c */
2276/* File: x86/OP_IPUT_BOOLEAN.S */
2277/* File: x86/OP_IPUT.S */
2278
2279 /*
2280 * General 32-bit instance field put.
2281 *
2282 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2283 */
2284 /* op vA, vB, field@CCCC */
2285 GET_GLUE(%ecx)
2286 SPILL(rIBASE) # need another reg
2287 movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC
2288 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
2289 movzbl rINST_HI,%ecx # ecx<- BA
2290 sarl $4,%ecx # ecx<- B
2291 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
2292 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
2293 andb $0xf,rINST_LO # rINST_FULL<- A
2294 GET_VREG(%ecx,%ecx) # ecx<- fp[B], the object ptr
2295 movl (%eax,rIBASE,4),%eax # resolved entry
2296 testl %eax,%eax # is resolved entry null?
2297 jne .LOP_IPUT_BOOLEAN_finish # no, already resolved
2298 movl rIBASE,OUT_ARG1(%esp)
2299 GET_GLUE(rIBASE)
2300 jmp .LOP_IPUT_BOOLEAN_resolve
2301
2302
2303/* ------------------------------ */
2304 .balign 64
2305.L_OP_IPUT_BYTE: /* 0x5d */
2306/* File: x86/OP_IPUT_BYTE.S */
2307/* File: x86/OP_IPUT.S */
2308
2309 /*
2310 * General 32-bit instance field put.
2311 *
2312 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2313 */
2314 /* op vA, vB, field@CCCC */
2315 GET_GLUE(%ecx)
2316 SPILL(rIBASE) # need another reg
2317 movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC
2318 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
2319 movzbl rINST_HI,%ecx # ecx<- BA
2320 sarl $4,%ecx # ecx<- B
2321 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
2322 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
2323 andb $0xf,rINST_LO # rINST_FULL<- A
2324 GET_VREG(%ecx,%ecx) # ecx<- fp[B], the object ptr
2325 movl (%eax,rIBASE,4),%eax # resolved entry
2326 testl %eax,%eax # is resolved entry null?
2327 jne .LOP_IPUT_BYTE_finish # no, already resolved
2328 movl rIBASE,OUT_ARG1(%esp)
2329 GET_GLUE(rIBASE)
2330 jmp .LOP_IPUT_BYTE_resolve
2331
2332
2333/* ------------------------------ */
2334 .balign 64
2335.L_OP_IPUT_CHAR: /* 0x5e */
2336/* File: x86/OP_IPUT_CHAR.S */
2337/* File: x86/OP_IPUT.S */
2338
2339 /*
2340 * General 32-bit instance field put.
2341 *
2342 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2343 */
2344 /* op vA, vB, field@CCCC */
2345 GET_GLUE(%ecx)
2346 SPILL(rIBASE) # need another reg
2347 movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC
2348 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
2349 movzbl rINST_HI,%ecx # ecx<- BA
2350 sarl $4,%ecx # ecx<- B
2351 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
2352 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
2353 andb $0xf,rINST_LO # rINST_FULL<- A
2354 GET_VREG(%ecx,%ecx) # ecx<- fp[B], the object ptr
2355 movl (%eax,rIBASE,4),%eax # resolved entry
2356 testl %eax,%eax # is resolved entry null?
2357 jne .LOP_IPUT_CHAR_finish # no, already resolved
2358 movl rIBASE,OUT_ARG1(%esp)
2359 GET_GLUE(rIBASE)
2360 jmp .LOP_IPUT_CHAR_resolve
2361
2362
2363/* ------------------------------ */
2364 .balign 64
2365.L_OP_IPUT_SHORT: /* 0x5f */
2366/* File: x86/OP_IPUT_SHORT.S */
2367/* File: x86/OP_IPUT.S */
2368
2369 /*
2370 * General 32-bit instance field put.
2371 *
2372 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2373 */
2374 /* op vA, vB, field@CCCC */
2375 GET_GLUE(%ecx)
2376 SPILL(rIBASE) # need another reg
2377 movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC
2378 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex
2379 movzbl rINST_HI,%ecx # ecx<- BA
2380 sarl $4,%ecx # ecx<- B
2381 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
2382 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
2383 andb $0xf,rINST_LO # rINST_FULL<- A
2384 GET_VREG(%ecx,%ecx) # ecx<- fp[B], the object ptr
2385 movl (%eax,rIBASE,4),%eax # resolved entry
2386 testl %eax,%eax # is resolved entry null?
2387 jne .LOP_IPUT_SHORT_finish # no, already resolved
2388 movl rIBASE,OUT_ARG1(%esp)
2389 GET_GLUE(rIBASE)
2390 jmp .LOP_IPUT_SHORT_resolve
2391
2392
2393/* ------------------------------ */
2394 .balign 64
2395.L_OP_SGET: /* 0x60 */
2396/* File: x86/OP_SGET.S */
2397 /*
2398 * General 32-bit SGET handler.
2399 *
2400 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2401 */
2402 /* op vAA, field@BBBB */
2403 GET_GLUE(%ecx)
2404 movzwl 2(rPC),%eax # eax<- field ref BBBB
2405 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
2406 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
2407 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
2408 testl %eax,%eax # resolved entry null?
2409 je .LOP_SGET_resolve # if not, make it so
2410.LOP_SGET_finish: # field ptr in eax
2411 movl offStaticField_value(%eax),%eax
2412 movzbl rINST_HI,%ecx # ecx<- AA
2413 FETCH_INST_WORD(2)
2414 ADVANCE_PC(2)
2415 SET_VREG(%eax,%ecx)
2416 GOTO_NEXT
2417
2418/* ------------------------------ */
2419 .balign 64
2420.L_OP_SGET_WIDE: /* 0x61 */
2421/* File: x86/OP_SGET_WIDE.S */
2422 /*
2423 * 64-bit SGET handler.
2424 *
2425 */
2426 /* sget-wide vAA, field@BBBB */
2427 GET_GLUE(%ecx)
2428 movzwl 2(rPC),%eax # eax<- field ref BBBB
2429 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
2430 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
2431 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
2432 testl %eax,%eax # resolved entry null?
2433 je .LOP_SGET_WIDE_resolve # if not, make it so
2434.LOP_SGET_WIDE_finish: # field ptr in eax
2435 movl offStaticField_value(%eax),%ecx # ecx<- lsw
2436 movl 4+offStaticField_value(%eax),%eax # eax<- msw
2437 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
2438 SET_VREG_WORD(%ecx,rINST_FULL,0)
2439 SET_VREG_WORD(%eax,rINST_FULL,1)
2440 FETCH_INST_WORD(2)
2441 ADVANCE_PC(2)
2442 GOTO_NEXT
2443
2444/* ------------------------------ */
2445 .balign 64
2446.L_OP_SGET_OBJECT: /* 0x62 */
2447/* File: x86/OP_SGET_OBJECT.S */
2448/* File: x86/OP_SGET.S */
2449 /*
2450 * General 32-bit SGET handler.
2451 *
2452 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2453 */
2454 /* op vAA, field@BBBB */
2455 GET_GLUE(%ecx)
2456 movzwl 2(rPC),%eax # eax<- field ref BBBB
2457 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
2458 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
2459 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
2460 testl %eax,%eax # resolved entry null?
2461 je .LOP_SGET_OBJECT_resolve # if not, make it so
2462.LOP_SGET_OBJECT_finish: # field ptr in eax
2463 movl offStaticField_value(%eax),%eax
2464 movzbl rINST_HI,%ecx # ecx<- AA
2465 FETCH_INST_WORD(2)
2466 ADVANCE_PC(2)
2467 SET_VREG(%eax,%ecx)
2468 GOTO_NEXT
2469
2470
2471/* ------------------------------ */
2472 .balign 64
2473.L_OP_SGET_BOOLEAN: /* 0x63 */
2474/* File: x86/OP_SGET_BOOLEAN.S */
2475/* File: x86/OP_SGET.S */
2476 /*
2477 * General 32-bit SGET handler.
2478 *
2479 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2480 */
2481 /* op vAA, field@BBBB */
2482 GET_GLUE(%ecx)
2483 movzwl 2(rPC),%eax # eax<- field ref BBBB
2484 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
2485 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
2486 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
2487 testl %eax,%eax # resolved entry null?
2488 je .LOP_SGET_BOOLEAN_resolve # if not, make it so
2489.LOP_SGET_BOOLEAN_finish: # field ptr in eax
2490 movl offStaticField_value(%eax),%eax
2491 movzbl rINST_HI,%ecx # ecx<- AA
2492 FETCH_INST_WORD(2)
2493 ADVANCE_PC(2)
2494 SET_VREG(%eax,%ecx)
2495 GOTO_NEXT
2496
2497
2498/* ------------------------------ */
2499 .balign 64
2500.L_OP_SGET_BYTE: /* 0x64 */
2501/* File: x86/OP_SGET_BYTE.S */
2502/* File: x86/OP_SGET.S */
2503 /*
2504 * General 32-bit SGET handler.
2505 *
2506 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2507 */
2508 /* op vAA, field@BBBB */
2509 GET_GLUE(%ecx)
2510 movzwl 2(rPC),%eax # eax<- field ref BBBB
2511 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
2512 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
2513 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
2514 testl %eax,%eax # resolved entry null?
2515 je .LOP_SGET_BYTE_resolve # if not, make it so
2516.LOP_SGET_BYTE_finish: # field ptr in eax
2517 movl offStaticField_value(%eax),%eax
2518 movzbl rINST_HI,%ecx # ecx<- AA
2519 FETCH_INST_WORD(2)
2520 ADVANCE_PC(2)
2521 SET_VREG(%eax,%ecx)
2522 GOTO_NEXT
2523
2524
2525/* ------------------------------ */
2526 .balign 64
2527.L_OP_SGET_CHAR: /* 0x65 */
2528/* File: x86/OP_SGET_CHAR.S */
2529/* File: x86/OP_SGET.S */
2530 /*
2531 * General 32-bit SGET handler.
2532 *
2533 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2534 */
2535 /* op vAA, field@BBBB */
2536 GET_GLUE(%ecx)
2537 movzwl 2(rPC),%eax # eax<- field ref BBBB
2538 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
2539 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
2540 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
2541 testl %eax,%eax # resolved entry null?
2542 je .LOP_SGET_CHAR_resolve # if not, make it so
2543.LOP_SGET_CHAR_finish: # field ptr in eax
2544 movl offStaticField_value(%eax),%eax
2545 movzbl rINST_HI,%ecx # ecx<- AA
2546 FETCH_INST_WORD(2)
2547 ADVANCE_PC(2)
2548 SET_VREG(%eax,%ecx)
2549 GOTO_NEXT
2550
2551
2552/* ------------------------------ */
2553 .balign 64
2554.L_OP_SGET_SHORT: /* 0x66 */
2555/* File: x86/OP_SGET_SHORT.S */
2556/* File: x86/OP_SGET.S */
2557 /*
2558 * General 32-bit SGET handler.
2559 *
2560 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2561 */
2562 /* op vAA, field@BBBB */
2563 GET_GLUE(%ecx)
2564 movzwl 2(rPC),%eax # eax<- field ref BBBB
2565 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
2566 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
2567 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
2568 testl %eax,%eax # resolved entry null?
2569 je .LOP_SGET_SHORT_resolve # if not, make it so
2570.LOP_SGET_SHORT_finish: # field ptr in eax
2571 movl offStaticField_value(%eax),%eax
2572 movzbl rINST_HI,%ecx # ecx<- AA
2573 FETCH_INST_WORD(2)
2574 ADVANCE_PC(2)
2575 SET_VREG(%eax,%ecx)
2576 GOTO_NEXT
2577
2578
2579/* ------------------------------ */
2580 .balign 64
2581.L_OP_SPUT: /* 0x67 */
2582/* File: x86/OP_SPUT.S */
2583 /*
2584 * General 32-bit SPUT handler.
2585 *
2586 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2587 */
2588 /* op vAA, field@BBBB */
2589 GET_GLUE(%ecx)
2590 movzwl 2(rPC),%eax # eax<- field ref BBBB
2591 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
2592 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
2593 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
2594 testl %eax,%eax # resolved entry null?
2595 je .LOP_SPUT_resolve # if not, make it so
2596.LOP_SPUT_finish: # field ptr in eax
2597 movzbl rINST_HI,%ecx # ecx<- AA
2598 GET_VREG(%ecx,%ecx)
2599 FETCH_INST_WORD(2)
2600 movl %ecx,offStaticField_value(%eax)
2601 ADVANCE_PC(2)
2602 GOTO_NEXT
2603
2604/* ------------------------------ */
2605 .balign 64
2606.L_OP_SPUT_WIDE: /* 0x68 */
2607/* File: x86/OP_SPUT_WIDE.S */
2608 /*
2609 * General 32-bit SPUT handler.
2610 *
2611 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2612 */
2613 /* op vAA, field@BBBB */
2614 GET_GLUE(%ecx)
2615 movzwl 2(rPC),%eax # eax<- field ref BBBB
2616 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
2617 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
2618 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
2619 testl %eax,%eax # resolved entry null?
2620 je .LOP_SPUT_WIDE_resolve # if not, make it so
2621.LOP_SPUT_WIDE_finish: # field ptr in eax
2622 movzbl rINST_HI,%ecx # ecx<- AA
2623 GET_VREG_WORD(rINST_FULL,%ecx,0) # rINST_FULL<- lsw
2624 GET_VREG_WORD(%ecx,%ecx,1) # ecx<- msw
2625 movl rINST_FULL,offStaticField_value(%eax)
2626 FETCH_INST_WORD(2)
2627 ADVANCE_PC(2)
2628 movl %ecx,4+offStaticField_value(%eax)
2629 GOTO_NEXT
2630
2631/* ------------------------------ */
2632 .balign 64
2633.L_OP_SPUT_OBJECT: /* 0x69 */
2634/* File: x86/OP_SPUT_OBJECT.S */
2635/* File: x86/OP_SPUT.S */
2636 /*
2637 * General 32-bit SPUT handler.
2638 *
2639 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2640 */
2641 /* op vAA, field@BBBB */
2642 GET_GLUE(%ecx)
2643 movzwl 2(rPC),%eax # eax<- field ref BBBB
2644 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
2645 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
2646 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
2647 testl %eax,%eax # resolved entry null?
2648 je .LOP_SPUT_OBJECT_resolve # if not, make it so
2649.LOP_SPUT_OBJECT_finish: # field ptr in eax
2650 movzbl rINST_HI,%ecx # ecx<- AA
2651 GET_VREG(%ecx,%ecx)
2652 FETCH_INST_WORD(2)
2653 movl %ecx,offStaticField_value(%eax)
2654 ADVANCE_PC(2)
2655 GOTO_NEXT
2656
2657
2658/* ------------------------------ */
2659 .balign 64
2660.L_OP_SPUT_BOOLEAN: /* 0x6a */
2661/* File: x86/OP_SPUT_BOOLEAN.S */
2662/* File: x86/OP_SPUT.S */
2663 /*
2664 * General 32-bit SPUT handler.
2665 *
2666 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2667 */
2668 /* op vAA, field@BBBB */
2669 GET_GLUE(%ecx)
2670 movzwl 2(rPC),%eax # eax<- field ref BBBB
2671 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
2672 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
2673 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
2674 testl %eax,%eax # resolved entry null?
2675 je .LOP_SPUT_BOOLEAN_resolve # if not, make it so
2676.LOP_SPUT_BOOLEAN_finish: # field ptr in eax
2677 movzbl rINST_HI,%ecx # ecx<- AA
2678 GET_VREG(%ecx,%ecx)
2679 FETCH_INST_WORD(2)
2680 movl %ecx,offStaticField_value(%eax)
2681 ADVANCE_PC(2)
2682 GOTO_NEXT
2683
2684
2685/* ------------------------------ */
2686 .balign 64
2687.L_OP_SPUT_BYTE: /* 0x6b */
2688/* File: x86/OP_SPUT_BYTE.S */
2689/* File: x86/OP_SPUT.S */
2690 /*
2691 * General 32-bit SPUT handler.
2692 *
2693 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2694 */
2695 /* op vAA, field@BBBB */
2696 GET_GLUE(%ecx)
2697 movzwl 2(rPC),%eax # eax<- field ref BBBB
2698 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
2699 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
2700 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
2701 testl %eax,%eax # resolved entry null?
2702 je .LOP_SPUT_BYTE_resolve # if not, make it so
2703.LOP_SPUT_BYTE_finish: # field ptr in eax
2704 movzbl rINST_HI,%ecx # ecx<- AA
2705 GET_VREG(%ecx,%ecx)
2706 FETCH_INST_WORD(2)
2707 movl %ecx,offStaticField_value(%eax)
2708 ADVANCE_PC(2)
2709 GOTO_NEXT
2710
2711
2712/* ------------------------------ */
2713 .balign 64
2714.L_OP_SPUT_CHAR: /* 0x6c */
2715/* File: x86/OP_SPUT_CHAR.S */
2716/* File: x86/OP_SPUT.S */
2717 /*
2718 * General 32-bit SPUT handler.
2719 *
2720 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2721 */
2722 /* op vAA, field@BBBB */
2723 GET_GLUE(%ecx)
2724 movzwl 2(rPC),%eax # eax<- field ref BBBB
2725 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
2726 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
2727 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
2728 testl %eax,%eax # resolved entry null?
2729 je .LOP_SPUT_CHAR_resolve # if not, make it so
2730.LOP_SPUT_CHAR_finish: # field ptr in eax
2731 movzbl rINST_HI,%ecx # ecx<- AA
2732 GET_VREG(%ecx,%ecx)
2733 FETCH_INST_WORD(2)
2734 movl %ecx,offStaticField_value(%eax)
2735 ADVANCE_PC(2)
2736 GOTO_NEXT
2737
2738
2739/* ------------------------------ */
2740 .balign 64
2741.L_OP_SPUT_SHORT: /* 0x6d */
2742/* File: x86/OP_SPUT_SHORT.S */
2743/* File: x86/OP_SPUT.S */
2744 /*
2745 * General 32-bit SPUT handler.
2746 *
2747 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2748 */
2749 /* op vAA, field@BBBB */
2750 GET_GLUE(%ecx)
2751 movzwl 2(rPC),%eax # eax<- field ref BBBB
2752 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex
2753 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
2754 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
2755 testl %eax,%eax # resolved entry null?
2756 je .LOP_SPUT_SHORT_resolve # if not, make it so
2757.LOP_SPUT_SHORT_finish: # field ptr in eax
2758 movzbl rINST_HI,%ecx # ecx<- AA
2759 GET_VREG(%ecx,%ecx)
2760 FETCH_INST_WORD(2)
2761 movl %ecx,offStaticField_value(%eax)
2762 ADVANCE_PC(2)
2763 GOTO_NEXT
2764
2765
2766/* ------------------------------ */
2767 .balign 64
2768.L_OP_INVOKE_VIRTUAL: /* 0x6e */
2769/* File: x86/OP_INVOKE_VIRTUAL.S */
2770
2771 /*
2772 * Handle a virtual method call.
2773 *
2774 * for: invoke-virtual, invoke-virtual/range
2775 */
2776 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
2777 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
2778 GET_GLUE(%eax)
2779 movzwl 2(rPC),%ecx # ecx<- BBBB
2780 movl offGlue_methodClassDex(%eax),%eax # eax<- pDvmDex
2781 EXPORT_PC()
2782 movl offDvmDex_pResMethods(%eax),%eax # eax<- pDvmDex->pResMethods
2783 movl (%eax,%ecx,4),%eax # eax<- resolved baseMethod
2784 testl %eax,%eax # already resolved?
2785 jne .LOP_INVOKE_VIRTUAL_continue # yes, continue
2786 GET_GLUE(%eax)
2787 movl %ecx,OUT_ARG1(%esp) # arg1<- ref
2788 movl offGlue_method(%eax),%eax # eax<- glue->method
2789 SPILL(rPC)
2790 jmp .LOP_INVOKE_VIRTUAL_more
2791
2792/* ------------------------------ */
2793 .balign 64
2794.L_OP_INVOKE_SUPER: /* 0x6f */
2795/* File: x86/OP_INVOKE_SUPER.S */
2796 /*
2797 * Handle a "super" method call.
2798 *
2799 * for: invoke-super, invoke-super/range
2800 */
2801 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
2802 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
2803 GET_GLUE(rINST_FULL)
2804 movzwl 2(rPC),%eax # eax<- BBBB
2805 movl offGlue_methodClassDex(rINST_FULL),%ecx # ecx<- pDvmDex
2806 EXPORT_PC()
2807 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods
2808 movl (%ecx,%eax,4),%ecx # ecx<- resolved baseMethod
2809 movl offGlue_method(rINST_FULL),%eax # eax<- method
2810 movzwl 4(rPC),rINST_FULL # rINST_FULL<- GFED or CCCC
2811 .if (!0)
2812 andl $0xf,rINST_FULL # rINST_FULL<- D (or stays CCCC)
2813 .endif
2814 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- "this" ptr
2815 testl rINST_FULL,rINST_FULL # null "this"?
2816 je common_errNullObject # yes, throw
2817 movl offMethod_clazz(%eax),%eax # eax<- method->clazz
2818 testl %ecx,%ecx # already resolved?
2819 jne .LOP_INVOKE_SUPER_continue # yes - go on
2820 jmp .LOP_INVOKE_SUPER_resolve
2821
2822/* ------------------------------ */
2823 .balign 64
2824.L_OP_INVOKE_DIRECT: /* 0x70 */
2825/* File: x86/OP_INVOKE_DIRECT.S */
2826 /*
2827 * Handle a direct method call.
2828 *
2829 * (We could defer the "is 'this' pointer null" test to the common
2830 * method invocation code, and use a flag to indicate that static
2831 * calls don't count. If we do this as part of copying the arguments
2832 * out we could avoiding loading the first arg twice.)
2833 *
2834 * for: invoke-direct, invoke-direct/range
2835 */
2836 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
2837 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
2838 GET_GLUE(%ecx)
2839 movzwl 2(rPC),%eax # eax<- BBBB
2840 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
2841 EXPORT_PC()
2842 SPILL(rPC)
2843 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods
2844 movzwl 4(rPC),rPC # rPC<- GFED or CCCC
2845 movl (%ecx,%eax,4),%eax # eax<- resolved methodToCall
2846 .if (!0)
2847 andl $0xf,rPC # rPC<- D (or stays CCCC)
2848 .endif
2849 testl %eax,%eax # already resolved?
2850 GET_VREG(%ecx,rPC) # ecx<- "this" ptr
2851 je .LOP_INVOKE_DIRECT_resolve # not resolved, do it now
2852.LOP_INVOKE_DIRECT_finish:
2853 UNSPILL(rPC)
2854 testl %ecx,%ecx # null "this"?
Johnnie Birchc4080f62009-02-10 15:41:06 -08002855 jne common_invokeMethodNoRange # no, continue on
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002856 jmp common_errNullObject
2857
2858/* ------------------------------ */
2859 .balign 64
2860.L_OP_INVOKE_STATIC: /* 0x71 */
2861/* File: x86/OP_INVOKE_STATIC.S */
2862 /*
2863 * Handle a static method call.
2864 *
2865 * for: invoke-static, invoke-static/range
2866 */
2867 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
2868 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
2869 GET_GLUE(%ecx)
2870 movzwl 2(rPC),%eax # eax<- BBBB
2871 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
2872 EXPORT_PC()
2873 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods
2874 movl (%ecx,%eax,4),%eax # eax<- resolved methodToCall
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002875 testl %eax,%eax
Johnnie Birchc4080f62009-02-10 15:41:06 -08002876 jne common_invokeMethodNoRange
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002877 GET_GLUE(%ecx)
2878 movl offGlue_method(%ecx),%ecx # ecx<- glue->method
2879 movzwl 2(rPC),%eax
2880 movl offMethod_clazz(%ecx),%ecx# ecx<- method->clazz
2881 movl %eax,OUT_ARG1(%esp) # arg1<- BBBB
2882 movl %ecx,OUT_ARG0(%esp) # arg0<- clazz
2883 jmp .LOP_INVOKE_STATIC_continue
2884
2885/* ------------------------------ */
2886 .balign 64
2887.L_OP_INVOKE_INTERFACE: /* 0x72 */
2888/* File: x86/OP_INVOKE_INTERFACE.S */
2889 /*
2890 * Handle an interface method call.
2891 *
2892 * for: invoke-interface, invoke-interface/range
2893 */
2894 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
2895 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
2896 movzwl 4(rPC),%eax # eax<- FEDC or CCCC
2897 GET_GLUE(%ecx)
2898 .if (!0)
2899 andl $0xf,%eax # eax<- C (or stays CCCC)
2900 .endif
2901 GET_VREG(%eax,%eax) # eax<- "this"
2902 EXPORT_PC()
2903 testl %eax,%eax # null this?
2904 je common_errNullObject # yes, fail
2905 movl offObject_clazz(%eax),%eax# eax<- thisPtr->clazz
2906 movl %eax,OUT_ARG0(%esp) # arg0<- class
2907 movl offGlue_methodClassDex(%ecx),%eax # eax<- methodClassDex
2908 movl offGlue_method(%ecx),%ecx # ecx<- method
2909 movl %eax,OUT_ARG3(%esp) # arg3<- dex
2910 movzwl 2(rPC),%eax # eax<- BBBB
2911 movl %ecx,OUT_ARG2(%esp) # arg2<- method
2912 movl %eax,OUT_ARG1(%esp) # arg1<- BBBB
2913 SPILL(rPC)
2914 jmp .LOP_INVOKE_INTERFACE_continue
2915
2916/* ------------------------------ */
2917 .balign 64
2918.L_OP_UNUSED_73: /* 0x73 */
2919/* File: x86/OP_UNUSED_73.S */
2920/* File: x86/unused.S */
2921 jmp common_abort
2922
2923
2924/* ------------------------------ */
2925 .balign 64
2926.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
2927/* File: x86/OP_INVOKE_VIRTUAL_RANGE.S */
2928/* File: x86/OP_INVOKE_VIRTUAL.S */
2929
2930 /*
2931 * Handle a virtual method call.
2932 *
2933 * for: invoke-virtual, invoke-virtual/range
2934 */
2935 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
2936 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
2937 GET_GLUE(%eax)
2938 movzwl 2(rPC),%ecx # ecx<- BBBB
2939 movl offGlue_methodClassDex(%eax),%eax # eax<- pDvmDex
2940 EXPORT_PC()
2941 movl offDvmDex_pResMethods(%eax),%eax # eax<- pDvmDex->pResMethods
2942 movl (%eax,%ecx,4),%eax # eax<- resolved baseMethod
2943 testl %eax,%eax # already resolved?
2944 jne .LOP_INVOKE_VIRTUAL_RANGE_continue # yes, continue
2945 GET_GLUE(%eax)
2946 movl %ecx,OUT_ARG1(%esp) # arg1<- ref
2947 movl offGlue_method(%eax),%eax # eax<- glue->method
2948 SPILL(rPC)
2949 jmp .LOP_INVOKE_VIRTUAL_RANGE_more
2950
2951
2952/* ------------------------------ */
2953 .balign 64
2954.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
2955/* File: x86/OP_INVOKE_SUPER_RANGE.S */
2956/* File: x86/OP_INVOKE_SUPER.S */
2957 /*
2958 * Handle a "super" method call.
2959 *
2960 * for: invoke-super, invoke-super/range
2961 */
2962 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
2963 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
2964 GET_GLUE(rINST_FULL)
2965 movzwl 2(rPC),%eax # eax<- BBBB
2966 movl offGlue_methodClassDex(rINST_FULL),%ecx # ecx<- pDvmDex
2967 EXPORT_PC()
2968 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods
2969 movl (%ecx,%eax,4),%ecx # ecx<- resolved baseMethod
2970 movl offGlue_method(rINST_FULL),%eax # eax<- method
2971 movzwl 4(rPC),rINST_FULL # rINST_FULL<- GFED or CCCC
2972 .if (!1)
2973 andl $0xf,rINST_FULL # rINST_FULL<- D (or stays CCCC)
2974 .endif
2975 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- "this" ptr
2976 testl rINST_FULL,rINST_FULL # null "this"?
2977 je common_errNullObject # yes, throw
2978 movl offMethod_clazz(%eax),%eax # eax<- method->clazz
2979 testl %ecx,%ecx # already resolved?
2980 jne .LOP_INVOKE_SUPER_RANGE_continue # yes - go on
2981 jmp .LOP_INVOKE_SUPER_RANGE_resolve
2982
2983
2984/* ------------------------------ */
2985 .balign 64
2986.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
2987/* File: x86/OP_INVOKE_DIRECT_RANGE.S */
2988/* File: x86/OP_INVOKE_DIRECT.S */
2989 /*
2990 * Handle a direct method call.
2991 *
2992 * (We could defer the "is 'this' pointer null" test to the common
2993 * method invocation code, and use a flag to indicate that static
2994 * calls don't count. If we do this as part of copying the arguments
2995 * out we could avoiding loading the first arg twice.)
2996 *
2997 * for: invoke-direct, invoke-direct/range
2998 */
2999 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3000 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3001 GET_GLUE(%ecx)
3002 movzwl 2(rPC),%eax # eax<- BBBB
3003 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
3004 EXPORT_PC()
3005 SPILL(rPC)
3006 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods
3007 movzwl 4(rPC),rPC # rPC<- GFED or CCCC
3008 movl (%ecx,%eax,4),%eax # eax<- resolved methodToCall
3009 .if (!1)
3010 andl $0xf,rPC # rPC<- D (or stays CCCC)
3011 .endif
3012 testl %eax,%eax # already resolved?
3013 GET_VREG(%ecx,rPC) # ecx<- "this" ptr
3014 je .LOP_INVOKE_DIRECT_RANGE_resolve # not resolved, do it now
3015.LOP_INVOKE_DIRECT_RANGE_finish:
3016 UNSPILL(rPC)
3017 testl %ecx,%ecx # null "this"?
Johnnie Birchc4080f62009-02-10 15:41:06 -08003018 jne common_invokeMethodRange # no, continue on
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003019 jmp common_errNullObject
3020
3021
3022/* ------------------------------ */
3023 .balign 64
3024.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3025/* File: x86/OP_INVOKE_STATIC_RANGE.S */
3026/* File: x86/OP_INVOKE_STATIC.S */
3027 /*
3028 * Handle a static method call.
3029 *
3030 * for: invoke-static, invoke-static/range
3031 */
3032 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3033 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3034 GET_GLUE(%ecx)
3035 movzwl 2(rPC),%eax # eax<- BBBB
3036 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
3037 EXPORT_PC()
3038 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods
3039 movl (%ecx,%eax,4),%eax # eax<- resolved methodToCall
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003040 testl %eax,%eax
Johnnie Birchc4080f62009-02-10 15:41:06 -08003041 jne common_invokeMethodRange
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003042 GET_GLUE(%ecx)
3043 movl offGlue_method(%ecx),%ecx # ecx<- glue->method
3044 movzwl 2(rPC),%eax
3045 movl offMethod_clazz(%ecx),%ecx# ecx<- method->clazz
3046 movl %eax,OUT_ARG1(%esp) # arg1<- BBBB
3047 movl %ecx,OUT_ARG0(%esp) # arg0<- clazz
3048 jmp .LOP_INVOKE_STATIC_RANGE_continue
3049
3050
3051/* ------------------------------ */
3052 .balign 64
3053.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3054/* File: x86/OP_INVOKE_INTERFACE_RANGE.S */
3055/* File: x86/OP_INVOKE_INTERFACE.S */
3056 /*
3057 * Handle an interface method call.
3058 *
3059 * for: invoke-interface, invoke-interface/range
3060 */
3061 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3062 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3063 movzwl 4(rPC),%eax # eax<- FEDC or CCCC
3064 GET_GLUE(%ecx)
3065 .if (!1)
3066 andl $0xf,%eax # eax<- C (or stays CCCC)
3067 .endif
3068 GET_VREG(%eax,%eax) # eax<- "this"
3069 EXPORT_PC()
3070 testl %eax,%eax # null this?
3071 je common_errNullObject # yes, fail
3072 movl offObject_clazz(%eax),%eax# eax<- thisPtr->clazz
3073 movl %eax,OUT_ARG0(%esp) # arg0<- class
3074 movl offGlue_methodClassDex(%ecx),%eax # eax<- methodClassDex
3075 movl offGlue_method(%ecx),%ecx # ecx<- method
3076 movl %eax,OUT_ARG3(%esp) # arg3<- dex
3077 movzwl 2(rPC),%eax # eax<- BBBB
3078 movl %ecx,OUT_ARG2(%esp) # arg2<- method
3079 movl %eax,OUT_ARG1(%esp) # arg1<- BBBB
3080 SPILL(rPC)
3081 jmp .LOP_INVOKE_INTERFACE_RANGE_continue
3082
3083
3084/* ------------------------------ */
3085 .balign 64
3086.L_OP_UNUSED_79: /* 0x79 */
3087/* File: x86/OP_UNUSED_79.S */
3088/* File: x86/unused.S */
3089 jmp common_abort
3090
3091
3092/* ------------------------------ */
3093 .balign 64
3094.L_OP_UNUSED_7A: /* 0x7a */
3095/* File: x86/OP_UNUSED_7A.S */
3096/* File: x86/unused.S */
3097 jmp common_abort
3098
3099
3100/* ------------------------------ */
3101 .balign 64
3102.L_OP_NEG_INT: /* 0x7b */
3103/* File: x86/OP_NEG_INT.S */
3104/* File: x86/unop.S */
3105 /*
3106 * Generic 32-bit unary operation. Provide an "instr" line that
3107 * specifies an instruction that performs "result = op eax".
3108 */
3109 /* unop vA, vB */
3110 movzbl rINST_HI,%ecx # ecx<- A+
3111 sarl $12,rINST_FULL # rINST_FULL<- B
3112 GET_VREG(%eax,rINST_FULL) # eax<- vB
3113 andb $0xf,%cl # ecx<- A
3114 FETCH_INST_WORD(1)
3115 ADVANCE_PC(1)
3116
3117
3118 negl %eax
3119 SET_VREG(%eax,%ecx)
3120 GOTO_NEXT
3121
3122
3123/* ------------------------------ */
3124 .balign 64
3125.L_OP_NOT_INT: /* 0x7c */
3126/* File: x86/OP_NOT_INT.S */
3127/* File: x86/unop.S */
3128 /*
3129 * Generic 32-bit unary operation. Provide an "instr" line that
3130 * specifies an instruction that performs "result = op eax".
3131 */
3132 /* unop vA, vB */
3133 movzbl rINST_HI,%ecx # ecx<- A+
3134 sarl $12,rINST_FULL # rINST_FULL<- B
3135 GET_VREG(%eax,rINST_FULL) # eax<- vB
3136 andb $0xf,%cl # ecx<- A
3137 FETCH_INST_WORD(1)
3138 ADVANCE_PC(1)
3139
3140
3141 notl %eax
3142 SET_VREG(%eax,%ecx)
3143 GOTO_NEXT
3144
3145
3146/* ------------------------------ */
3147 .balign 64
3148.L_OP_NEG_LONG: /* 0x7d */
3149/* File: x86/OP_NEG_LONG.S */
3150 /* unop vA, vB */
3151 movzbl rINST_HI,%ecx # ecx<- BA
3152 sarl $4,%ecx # ecx<- B
3153 movzbl rINST_HI,rINST_FULL # ecx<- BA
3154 andb $0xf,rINST_LO # rINST_FULL<- A
3155 GET_VREG_WORD(%eax,%ecx,0) # eax<- v[B+0]
3156 GET_VREG_WORD(%ecx,%ecx,1) # ecx<- v[B+1]
3157 negl %eax
3158 adcl $0,%ecx
3159 negl %ecx
3160 SET_VREG_WORD(%eax,rINST_FULL,0) # v[A+0]<- eax
3161 SET_VREG_WORD(%ecx,rINST_FULL,1) # v[A+1]<- ecx
3162 FETCH_INST_WORD(1)
3163 ADVANCE_PC(1)
3164 GOTO_NEXT
3165
3166/* ------------------------------ */
3167 .balign 64
3168.L_OP_NOT_LONG: /* 0x7e */
3169/* File: x86/OP_NOT_LONG.S */
3170 /* unop vA, vB */
3171 movzbl rINST_HI,%ecx # ecx<- BA
3172 sarl $4,%ecx # ecx<- B
3173 movzbl rINST_HI,rINST_FULL # ecx<- BA
3174 andb $0xf,rINST_LO # rINST_FULL<- A
3175 GET_VREG_WORD(%eax,%ecx,0) # eax<- v[B+0]
3176 GET_VREG_WORD(%ecx,%ecx,1) # ecx<- v[B+1]
3177 notl %eax
3178 notl %ecx
3179 SET_VREG_WORD(%eax,rINST_FULL,0) # v[A+0]<- eax
3180 SET_VREG_WORD(%ecx,rINST_FULL,1) # v[A+1]<- ecx
3181 FETCH_INST_WORD(1)
3182 ADVANCE_PC(1)
3183 GOTO_NEXT
3184
3185/* ------------------------------ */
3186 .balign 64
3187.L_OP_NEG_FLOAT: /* 0x7f */
3188/* File: x86/OP_NEG_FLOAT.S */
3189/* File: x86/fpcvt.S */
3190 /*
3191 * Generic 32-bit FP conversion operation.
3192 */
3193 /* unop vA, vB */
3194 movzbl rINST_HI,%ecx # ecx<- A+
3195 sarl $12,rINST_FULL # rINST_FULL<- B
3196 flds (rFP,rINST_FULL,4) # %st0<- vB
3197 andb $0xf,%cl # ecx<- A
3198 FETCH_INST_WORD(1)
3199 ADVANCE_PC(1)
3200 fchs
3201 fstps (rFP,%ecx,4) # vA<- %st0
3202 GOTO_NEXT
3203
3204
3205/* ------------------------------ */
3206 .balign 64
3207.L_OP_NEG_DOUBLE: /* 0x80 */
3208/* File: x86/OP_NEG_DOUBLE.S */
3209/* File: x86/fpcvt.S */
3210 /*
3211 * Generic 32-bit FP conversion operation.
3212 */
3213 /* unop vA, vB */
3214 movzbl rINST_HI,%ecx # ecx<- A+
3215 sarl $12,rINST_FULL # rINST_FULL<- B
3216 fldl (rFP,rINST_FULL,4) # %st0<- vB
3217 andb $0xf,%cl # ecx<- A
3218 FETCH_INST_WORD(1)
3219 ADVANCE_PC(1)
3220 fchs
3221 fstpl (rFP,%ecx,4) # vA<- %st0
3222 GOTO_NEXT
3223
3224
3225/* ------------------------------ */
3226 .balign 64
3227.L_OP_INT_TO_LONG: /* 0x81 */
3228/* File: x86/OP_INT_TO_LONG.S */
3229 /* int to long vA, vB */
3230 movzbl rINST_HI,%ecx # ecx<- +A
3231 sarl $12,rINST_FULL # rINST_FULL<- B
3232 GET_VREG(%eax,rINST_FULL) # eax<- vB
3233 SPILL(rPC) # will step on edx later
3234 andb $0xf,%cl # ecx<- A
3235 cltd # edx:eax<- sssssssBBBBBBBB
3236 SET_VREG_WORD(%edx,%ecx,1) # v[A+1]<- edx/rPC
3237 UNSPILL(rPC)
3238 SET_VREG_WORD(%eax,%ecx,0) # v[A+0]<- %eax
3239 FETCH_INST_WORD(1)
3240 ADVANCE_PC(1)
3241 GOTO_NEXT
3242
3243/* ------------------------------ */
3244 .balign 64
3245.L_OP_INT_TO_FLOAT: /* 0x82 */
3246/* File: x86/OP_INT_TO_FLOAT.S */
3247/* File: x86/fpcvt.S */
3248 /*
3249 * Generic 32-bit FP conversion operation.
3250 */
3251 /* unop vA, vB */
3252 movzbl rINST_HI,%ecx # ecx<- A+
3253 sarl $12,rINST_FULL # rINST_FULL<- B
3254 fildl (rFP,rINST_FULL,4) # %st0<- vB
3255 andb $0xf,%cl # ecx<- A
3256 FETCH_INST_WORD(1)
3257 ADVANCE_PC(1)
3258
3259 fstps (rFP,%ecx,4) # vA<- %st0
3260 GOTO_NEXT
3261
3262
3263/* ------------------------------ */
3264 .balign 64
3265.L_OP_INT_TO_DOUBLE: /* 0x83 */
3266/* File: x86/OP_INT_TO_DOUBLE.S */
3267/* File: x86/fpcvt.S */
3268 /*
3269 * Generic 32-bit FP conversion operation.
3270 */
3271 /* unop vA, vB */
3272 movzbl rINST_HI,%ecx # ecx<- A+
3273 sarl $12,rINST_FULL # rINST_FULL<- B
3274 fildl (rFP,rINST_FULL,4) # %st0<- vB
3275 andb $0xf,%cl # ecx<- A
3276 FETCH_INST_WORD(1)
3277 ADVANCE_PC(1)
3278
3279 fstpl (rFP,%ecx,4) # vA<- %st0
3280 GOTO_NEXT
3281
3282
3283/* ------------------------------ */
3284 .balign 64
3285.L_OP_LONG_TO_INT: /* 0x84 */
3286/* File: x86/OP_LONG_TO_INT.S */
3287/* we ignore the high word, making this equivalent to a 32-bit reg move */
3288/* File: x86/OP_MOVE.S */
3289 /* for move, move-object, long-to-int */
3290 /* op vA, vB */
3291 movzbl rINST_HI,%eax # eax<- BA
3292 andb $0xf,%al # eax<- A
3293 shrl $12,rINST_FULL # rINST_FULL<- B
3294 GET_VREG(%ecx,rINST_FULL)
3295 FETCH_INST_WORD(1)
3296 ADVANCE_PC(1)
3297 SET_VREG(%ecx,%eax) # fp[A]<-fp[B]
3298 GOTO_NEXT
3299
3300
3301/* ------------------------------ */
3302 .balign 64
3303.L_OP_LONG_TO_FLOAT: /* 0x85 */
3304/* File: x86/OP_LONG_TO_FLOAT.S */
3305/* File: x86/fpcvt.S */
3306 /*
3307 * Generic 32-bit FP conversion operation.
3308 */
3309 /* unop vA, vB */
3310 movzbl rINST_HI,%ecx # ecx<- A+
3311 sarl $12,rINST_FULL # rINST_FULL<- B
3312 fildll (rFP,rINST_FULL,4) # %st0<- vB
3313 andb $0xf,%cl # ecx<- A
3314 FETCH_INST_WORD(1)
3315 ADVANCE_PC(1)
3316
3317 fstps (rFP,%ecx,4) # vA<- %st0
3318 GOTO_NEXT
3319
3320
3321/* ------------------------------ */
3322 .balign 64
3323.L_OP_LONG_TO_DOUBLE: /* 0x86 */
3324/* File: x86/OP_LONG_TO_DOUBLE.S */
3325/* File: x86/fpcvt.S */
3326 /*
3327 * Generic 32-bit FP conversion operation.
3328 */
3329 /* unop vA, vB */
3330 movzbl rINST_HI,%ecx # ecx<- A+
3331 sarl $12,rINST_FULL # rINST_FULL<- B
3332 fildll (rFP,rINST_FULL,4) # %st0<- vB
3333 andb $0xf,%cl # ecx<- A
3334 FETCH_INST_WORD(1)
3335 ADVANCE_PC(1)
3336
3337 fstpl (rFP,%ecx,4) # vA<- %st0
3338 GOTO_NEXT
3339
3340
3341/* ------------------------------ */
3342 .balign 64
3343.L_OP_FLOAT_TO_INT: /* 0x87 */
3344/* File: x86/OP_FLOAT_TO_INT.S */
3345/* File: x86/cvtfp_int.S */
3346/* On fp to int conversions, Java requires that
3347 * if the result > maxint, it should be clamped to maxint. If it is less
3348 * than minint, it should be clamped to minint. If it is a nan, the result
3349 * should be zero. Further, the rounding mode is to truncate. This model
3350 * differs from what is delivered normally via the x86 fpu, so we have
3351 * to play some games.
3352 */
3353 /* float/double to int/long vA, vB */
3354 movzbl rINST_HI,%ecx # ecx<- A+
3355 sarl $12,rINST_FULL # rINST_FULL<- B
3356 .if 0
3357 fldl (rFP,rINST_FULL,4) # %st0<- vB
3358 .else
3359 flds (rFP,rINST_FULL,4) # %st0<- vB
3360 .endif
3361 ftst
3362 fnstcw LOCAL0_OFFSET(%ebp) # remember original rounding mode
3363 movzwl LOCAL0_OFFSET(%ebp),%eax
3364 movb $0xc,%ah
3365 movw %ax,LOCAL0_OFFSET+2(%ebp)
3366 fldcw LOCAL0_OFFSET+2(%ebp) # set "to zero" rounding mode
3367 FETCH_INST_WORD(1)
3368 andb $0xf,%cl # ecx<- A
3369 .if 0
3370 fistpll (rFP,%ecx,4) # convert and store
3371 .else
3372 fistpl (rFP,%ecx,4) # convert and store
3373 .endif
3374 fldcw LOCAL0_OFFSET(%ebp) # restore previous rounding mode
3375 jmp .LOP_FLOAT_TO_INT_continue
3376
3377
3378/* ------------------------------ */
3379 .balign 64
3380.L_OP_FLOAT_TO_LONG: /* 0x88 */
3381/* File: x86/OP_FLOAT_TO_LONG.S */
3382/* File: x86/cvtfp_int.S */
3383/* On fp to int conversions, Java requires that
3384 * if the result > maxint, it should be clamped to maxint. If it is less
3385 * than minint, it should be clamped to minint. If it is a nan, the result
3386 * should be zero. Further, the rounding mode is to truncate. This model
3387 * differs from what is delivered normally via the x86 fpu, so we have
3388 * to play some games.
3389 */
3390 /* float/double to int/long vA, vB */
3391 movzbl rINST_HI,%ecx # ecx<- A+
3392 sarl $12,rINST_FULL # rINST_FULL<- B
3393 .if 0
3394 fldl (rFP,rINST_FULL,4) # %st0<- vB
3395 .else
3396 flds (rFP,rINST_FULL,4) # %st0<- vB
3397 .endif
3398 ftst
3399 fnstcw LOCAL0_OFFSET(%ebp) # remember original rounding mode
3400 movzwl LOCAL0_OFFSET(%ebp),%eax
3401 movb $0xc,%ah
3402 movw %ax,LOCAL0_OFFSET+2(%ebp)
3403 fldcw LOCAL0_OFFSET+2(%ebp) # set "to zero" rounding mode
3404 FETCH_INST_WORD(1)
3405 andb $0xf,%cl # ecx<- A
3406 .if 1
3407 fistpll (rFP,%ecx,4) # convert and store
3408 .else
3409 fistpl (rFP,%ecx,4) # convert and store
3410 .endif
3411 fldcw LOCAL0_OFFSET(%ebp) # restore previous rounding mode
3412 jmp .LOP_FLOAT_TO_LONG_continue
3413
3414
3415/* ------------------------------ */
3416 .balign 64
3417.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3418/* File: x86/OP_FLOAT_TO_DOUBLE.S */
3419/* File: x86/fpcvt.S */
3420 /*
3421 * Generic 32-bit FP conversion operation.
3422 */
3423 /* unop vA, vB */
3424 movzbl rINST_HI,%ecx # ecx<- A+
3425 sarl $12,rINST_FULL # rINST_FULL<- B
3426 flds (rFP,rINST_FULL,4) # %st0<- vB
3427 andb $0xf,%cl # ecx<- A
3428 FETCH_INST_WORD(1)
3429 ADVANCE_PC(1)
3430
3431 fstpl (rFP,%ecx,4) # vA<- %st0
3432 GOTO_NEXT
3433
3434
3435/* ------------------------------ */
3436 .balign 64
3437.L_OP_DOUBLE_TO_INT: /* 0x8a */
3438/* File: x86/OP_DOUBLE_TO_INT.S */
3439/* File: x86/cvtfp_int.S */
3440/* On fp to int conversions, Java requires that
3441 * if the result > maxint, it should be clamped to maxint. If it is less
3442 * than minint, it should be clamped to minint. If it is a nan, the result
3443 * should be zero. Further, the rounding mode is to truncate. This model
3444 * differs from what is delivered normally via the x86 fpu, so we have
3445 * to play some games.
3446 */
3447 /* float/double to int/long vA, vB */
3448 movzbl rINST_HI,%ecx # ecx<- A+
3449 sarl $12,rINST_FULL # rINST_FULL<- B
3450 .if 1
3451 fldl (rFP,rINST_FULL,4) # %st0<- vB
3452 .else
3453 flds (rFP,rINST_FULL,4) # %st0<- vB
3454 .endif
3455 ftst
3456 fnstcw LOCAL0_OFFSET(%ebp) # remember original rounding mode
3457 movzwl LOCAL0_OFFSET(%ebp),%eax
3458 movb $0xc,%ah
3459 movw %ax,LOCAL0_OFFSET+2(%ebp)
3460 fldcw LOCAL0_OFFSET+2(%ebp) # set "to zero" rounding mode
3461 FETCH_INST_WORD(1)
3462 andb $0xf,%cl # ecx<- A
3463 .if 0
3464 fistpll (rFP,%ecx,4) # convert and store
3465 .else
3466 fistpl (rFP,%ecx,4) # convert and store
3467 .endif
3468 fldcw LOCAL0_OFFSET(%ebp) # restore previous rounding mode
3469 jmp .LOP_DOUBLE_TO_INT_continue
3470
3471
3472/* ------------------------------ */
3473 .balign 64
3474.L_OP_DOUBLE_TO_LONG: /* 0x8b */
3475/* File: x86/OP_DOUBLE_TO_LONG.S */
3476/* File: x86/cvtfp_int.S */
3477/* On fp to int conversions, Java requires that
3478 * if the result > maxint, it should be clamped to maxint. If it is less
3479 * than minint, it should be clamped to minint. If it is a nan, the result
3480 * should be zero. Further, the rounding mode is to truncate. This model
3481 * differs from what is delivered normally via the x86 fpu, so we have
3482 * to play some games.
3483 */
3484 /* float/double to int/long vA, vB */
3485 movzbl rINST_HI,%ecx # ecx<- A+
3486 sarl $12,rINST_FULL # rINST_FULL<- B
3487 .if 1
3488 fldl (rFP,rINST_FULL,4) # %st0<- vB
3489 .else
3490 flds (rFP,rINST_FULL,4) # %st0<- vB
3491 .endif
3492 ftst
3493 fnstcw LOCAL0_OFFSET(%ebp) # remember original rounding mode
3494 movzwl LOCAL0_OFFSET(%ebp),%eax
3495 movb $0xc,%ah
3496 movw %ax,LOCAL0_OFFSET+2(%ebp)
3497 fldcw LOCAL0_OFFSET+2(%ebp) # set "to zero" rounding mode
3498 FETCH_INST_WORD(1)
3499 andb $0xf,%cl # ecx<- A
3500 .if 1
3501 fistpll (rFP,%ecx,4) # convert and store
3502 .else
3503 fistpl (rFP,%ecx,4) # convert and store
3504 .endif
3505 fldcw LOCAL0_OFFSET(%ebp) # restore previous rounding mode
3506 jmp .LOP_DOUBLE_TO_LONG_continue
3507
3508
3509/* ------------------------------ */
3510 .balign 64
3511.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3512/* File: x86/OP_DOUBLE_TO_FLOAT.S */
3513/* File: x86/fpcvt.S */
3514 /*
3515 * Generic 32-bit FP conversion operation.
3516 */
3517 /* unop vA, vB */
3518 movzbl rINST_HI,%ecx # ecx<- A+
3519 sarl $12,rINST_FULL # rINST_FULL<- B
3520 fldl (rFP,rINST_FULL,4) # %st0<- vB
3521 andb $0xf,%cl # ecx<- A
3522 FETCH_INST_WORD(1)
3523 ADVANCE_PC(1)
3524
3525 fstps (rFP,%ecx,4) # vA<- %st0
3526 GOTO_NEXT
3527
3528
3529/* ------------------------------ */
3530 .balign 64
3531.L_OP_INT_TO_BYTE: /* 0x8d */
3532/* File: x86/OP_INT_TO_BYTE.S */
3533/* File: x86/unop.S */
3534 /*
3535 * Generic 32-bit unary operation. Provide an "instr" line that
3536 * specifies an instruction that performs "result = op eax".
3537 */
3538 /* unop vA, vB */
3539 movzbl rINST_HI,%ecx # ecx<- A+
3540 sarl $12,rINST_FULL # rINST_FULL<- B
3541 GET_VREG(%eax,rINST_FULL) # eax<- vB
3542 andb $0xf,%cl # ecx<- A
3543 FETCH_INST_WORD(1)
3544 ADVANCE_PC(1)
3545
3546
3547 movsbl %al,%eax
3548 SET_VREG(%eax,%ecx)
3549 GOTO_NEXT
3550
3551
3552/* ------------------------------ */
3553 .balign 64
3554.L_OP_INT_TO_CHAR: /* 0x8e */
3555/* File: x86/OP_INT_TO_CHAR.S */
3556/* File: x86/unop.S */
3557 /*
3558 * Generic 32-bit unary operation. Provide an "instr" line that
3559 * specifies an instruction that performs "result = op eax".
3560 */
3561 /* unop vA, vB */
3562 movzbl rINST_HI,%ecx # ecx<- A+
3563 sarl $12,rINST_FULL # rINST_FULL<- B
3564 GET_VREG(%eax,rINST_FULL) # eax<- vB
3565 andb $0xf,%cl # ecx<- A
3566 FETCH_INST_WORD(1)
3567 ADVANCE_PC(1)
3568
3569
3570 movzwl %ax,%eax
3571 SET_VREG(%eax,%ecx)
3572 GOTO_NEXT
3573
3574
3575/* ------------------------------ */
3576 .balign 64
3577.L_OP_INT_TO_SHORT: /* 0x8f */
3578/* File: x86/OP_INT_TO_SHORT.S */
3579/* File: x86/unop.S */
3580 /*
3581 * Generic 32-bit unary operation. Provide an "instr" line that
3582 * specifies an instruction that performs "result = op eax".
3583 */
3584 /* unop vA, vB */
3585 movzbl rINST_HI,%ecx # ecx<- A+
3586 sarl $12,rINST_FULL # rINST_FULL<- B
3587 GET_VREG(%eax,rINST_FULL) # eax<- vB
3588 andb $0xf,%cl # ecx<- A
3589 FETCH_INST_WORD(1)
3590 ADVANCE_PC(1)
3591
3592
3593 movswl %ax,%eax
3594 SET_VREG(%eax,%ecx)
3595 GOTO_NEXT
3596
3597
3598/* ------------------------------ */
3599 .balign 64
3600.L_OP_ADD_INT: /* 0x90 */
3601/* File: x86/OP_ADD_INT.S */
3602/* File: x86/binop.S */
3603 /*
3604 * Generic 32-bit binary operation. Provide an "instr" line that
3605 * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
3606 * This could be an x86 instruction or a function call. (If the result
3607 * comes back in a register other than eax, you can override "result".)
3608 *
3609 * For: add-int, sub-int, and-int, or-int,
3610 * xor-int, shl-int, shr-int, ushr-int
3611 */
3612 /* binop vAA, vBB, vCC */
3613 movzbl 2(rPC),%eax # eax<- BB
3614 movzbl 3(rPC),%ecx # ecx<- CC
3615 GET_VREG(%eax,%eax) # eax<- vBB
3616 addl (rFP,%ecx,4),%eax # ex: addl (rFP,%ecx,4),%eax
3617 movzbl rINST_HI,%ecx # ecx<- AA
3618 FETCH_INST_WORD(2)
3619 ADVANCE_PC(2)
3620 SET_VREG(%eax,%ecx)
3621 GOTO_NEXT
3622
3623
3624
3625/* ------------------------------ */
3626 .balign 64
3627.L_OP_SUB_INT: /* 0x91 */
3628/* File: x86/OP_SUB_INT.S */
3629/* File: x86/binop.S */
3630 /*
3631 * Generic 32-bit binary operation. Provide an "instr" line that
3632 * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
3633 * This could be an x86 instruction or a function call. (If the result
3634 * comes back in a register other than eax, you can override "result".)
3635 *
3636 * For: add-int, sub-int, and-int, or-int,
3637 * xor-int, shl-int, shr-int, ushr-int
3638 */
3639 /* binop vAA, vBB, vCC */
3640 movzbl 2(rPC),%eax # eax<- BB
3641 movzbl 3(rPC),%ecx # ecx<- CC
3642 GET_VREG(%eax,%eax) # eax<- vBB
3643 subl (rFP,%ecx,4),%eax # ex: addl (rFP,%ecx,4),%eax
3644 movzbl rINST_HI,%ecx # ecx<- AA
3645 FETCH_INST_WORD(2)
3646 ADVANCE_PC(2)
3647 SET_VREG(%eax,%ecx)
3648 GOTO_NEXT
3649
3650
3651
3652/* ------------------------------ */
3653 .balign 64
3654.L_OP_MUL_INT: /* 0x92 */
3655/* File: x86/OP_MUL_INT.S */
3656 /*
3657 * 32-bit binary multiplication.
3658 */
3659 /* mul vAA, vBB, vCC */
3660 movzbl 2(rPC),%eax # eax<- BB
3661 movzbl 3(rPC),%ecx # ecx<- CC
3662 SPILL(rPC)
3663 GET_VREG(%eax,%eax) # eax<- vBB
3664 imull (rFP,%ecx,4),%eax # trashes rPC/edx
3665 UNSPILL(rPC)
3666 movzbl rINST_HI,%ecx # ecx<- AA
3667 FETCH_INST_WORD(2)
3668 ADVANCE_PC(2)
3669 SET_VREG(%eax,%ecx)
3670 GOTO_NEXT
3671
3672/* ------------------------------ */
3673 .balign 64
3674.L_OP_DIV_INT: /* 0x93 */
3675/* File: x86/OP_DIV_INT.S */
3676/* File: x86/bindiv.S */
3677
3678 /*
3679 * 32-bit binary div/rem operation. Handles special case of op0=minint and
3680 * op1=-1.
3681 */
3682 /* binop vAA, vBB, vCC */
3683 movzbl 2(rPC),%eax # eax<- BB
3684 movzbl 3(rPC),%ecx # ecx<- CC
3685 GET_VREG(%eax,%eax) # eax<- vBB
3686 GET_VREG(%ecx,%ecx) # eax<- vBB
3687 SPILL(rPC)
3688 cmpl $0,%ecx
3689 je common_errDivideByZero
3690 cmpl $-1,%ecx
3691 jne .LOP_DIV_INT_continue_div
3692 cmpl $0x80000000,%eax
3693 jne .LOP_DIV_INT_continue_div
3694 movl $0x80000000,%eax
3695 jmp .LOP_DIV_INT_finish_div
3696
3697
3698
3699/* ------------------------------ */
3700 .balign 64
3701.L_OP_REM_INT: /* 0x94 */
3702/* File: x86/OP_REM_INT.S */
3703/* File: x86/bindiv.S */
3704
3705 /*
3706 * 32-bit binary div/rem operation. Handles special case of op0=minint and
3707 * op1=-1.
3708 */
3709 /* binop vAA, vBB, vCC */
3710 movzbl 2(rPC),%eax # eax<- BB
3711 movzbl 3(rPC),%ecx # ecx<- CC
3712 GET_VREG(%eax,%eax) # eax<- vBB
3713 GET_VREG(%ecx,%ecx) # eax<- vBB
3714 SPILL(rPC)
3715 cmpl $0,%ecx
3716 je common_errDivideByZero
3717 cmpl $-1,%ecx
3718 jne .LOP_REM_INT_continue_div
3719 cmpl $0x80000000,%eax
3720 jne .LOP_REM_INT_continue_div
3721 movl $0,%edx
3722 jmp .LOP_REM_INT_finish_div
3723
3724
3725
3726/* ------------------------------ */
3727 .balign 64
3728.L_OP_AND_INT: /* 0x95 */
3729/* File: x86/OP_AND_INT.S */
3730/* File: x86/binop.S */
3731 /*
3732 * Generic 32-bit binary operation. Provide an "instr" line that
3733 * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
3734 * This could be an x86 instruction or a function call. (If the result
3735 * comes back in a register other than eax, you can override "result".)
3736 *
3737 * For: add-int, sub-int, and-int, or-int,
3738 * xor-int, shl-int, shr-int, ushr-int
3739 */
3740 /* binop vAA, vBB, vCC */
3741 movzbl 2(rPC),%eax # eax<- BB
3742 movzbl 3(rPC),%ecx # ecx<- CC
3743 GET_VREG(%eax,%eax) # eax<- vBB
3744 andl (rFP,%ecx,4),%eax # ex: addl (rFP,%ecx,4),%eax
3745 movzbl rINST_HI,%ecx # ecx<- AA
3746 FETCH_INST_WORD(2)
3747 ADVANCE_PC(2)
3748 SET_VREG(%eax,%ecx)
3749 GOTO_NEXT
3750
3751
3752
3753/* ------------------------------ */
3754 .balign 64
3755.L_OP_OR_INT: /* 0x96 */
3756/* File: x86/OP_OR_INT.S */
3757/* File: x86/binop.S */
3758 /*
3759 * Generic 32-bit binary operation. Provide an "instr" line that
3760 * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
3761 * This could be an x86 instruction or a function call. (If the result
3762 * comes back in a register other than eax, you can override "result".)
3763 *
3764 * For: add-int, sub-int, and-int, or-int,
3765 * xor-int, shl-int, shr-int, ushr-int
3766 */
3767 /* binop vAA, vBB, vCC */
3768 movzbl 2(rPC),%eax # eax<- BB
3769 movzbl 3(rPC),%ecx # ecx<- CC
3770 GET_VREG(%eax,%eax) # eax<- vBB
3771 orl (rFP,%ecx,4),%eax # ex: addl (rFP,%ecx,4),%eax
3772 movzbl rINST_HI,%ecx # ecx<- AA
3773 FETCH_INST_WORD(2)
3774 ADVANCE_PC(2)
3775 SET_VREG(%eax,%ecx)
3776 GOTO_NEXT
3777
3778
3779
3780/* ------------------------------ */
3781 .balign 64
3782.L_OP_XOR_INT: /* 0x97 */
3783/* File: x86/OP_XOR_INT.S */
3784/* File: x86/binop.S */
3785 /*
3786 * Generic 32-bit binary operation. Provide an "instr" line that
3787 * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
3788 * This could be an x86 instruction or a function call. (If the result
3789 * comes back in a register other than eax, you can override "result".)
3790 *
3791 * For: add-int, sub-int, and-int, or-int,
3792 * xor-int, shl-int, shr-int, ushr-int
3793 */
3794 /* binop vAA, vBB, vCC */
3795 movzbl 2(rPC),%eax # eax<- BB
3796 movzbl 3(rPC),%ecx # ecx<- CC
3797 GET_VREG(%eax,%eax) # eax<- vBB
3798 xorl (rFP,%ecx,4),%eax # ex: addl (rFP,%ecx,4),%eax
3799 movzbl rINST_HI,%ecx # ecx<- AA
3800 FETCH_INST_WORD(2)
3801 ADVANCE_PC(2)
3802 SET_VREG(%eax,%ecx)
3803 GOTO_NEXT
3804
3805
3806
3807/* ------------------------------ */
3808 .balign 64
3809.L_OP_SHL_INT: /* 0x98 */
3810/* File: x86/OP_SHL_INT.S */
3811/* File: x86/binop1.S */
3812 /*
3813 * Generic 32-bit binary operation in which both operands loaded to
3814 * registers (op0 in eax, op1 in ecx).
3815 */
3816 /* binop vAA, vBB, vCC */
3817 movzbl 2(rPC),%eax # eax<- BB
3818 movzbl 3(rPC),%ecx # ecx<- CC
3819 GET_VREG(%eax,%eax) # eax<- vBB
3820 GET_VREG(%ecx,%ecx) # eax<- vBB
3821 sall %cl,%eax # ex: addl %ecx,%eax
3822 movzbl rINST_HI,%ecx # tmp<- AA
3823 FETCH_INST_WORD(2)
3824 ADVANCE_PC(2)
3825 SET_VREG(%eax,%ecx)
3826 GOTO_NEXT
3827
3828
3829/* ------------------------------ */
3830 .balign 64
3831.L_OP_SHR_INT: /* 0x99 */
3832/* File: x86/OP_SHR_INT.S */
3833/* File: x86/binop1.S */
3834 /*
3835 * Generic 32-bit binary operation in which both operands loaded to
3836 * registers (op0 in eax, op1 in ecx).
3837 */
3838 /* binop vAA, vBB, vCC */
3839 movzbl 2(rPC),%eax # eax<- BB
3840 movzbl 3(rPC),%ecx # ecx<- CC
3841 GET_VREG(%eax,%eax) # eax<- vBB
3842 GET_VREG(%ecx,%ecx) # eax<- vBB
3843 sarl %cl,%eax # ex: addl %ecx,%eax
3844 movzbl rINST_HI,%ecx # tmp<- AA
3845 FETCH_INST_WORD(2)
3846 ADVANCE_PC(2)
3847 SET_VREG(%eax,%ecx)
3848 GOTO_NEXT
3849
3850
3851/* ------------------------------ */
3852 .balign 64
3853.L_OP_USHR_INT: /* 0x9a */
3854/* File: x86/OP_USHR_INT.S */
3855/* File: x86/binop1.S */
3856 /*
3857 * Generic 32-bit binary operation in which both operands loaded to
3858 * registers (op0 in eax, op1 in ecx).
3859 */
3860 /* binop vAA, vBB, vCC */
3861 movzbl 2(rPC),%eax # eax<- BB
3862 movzbl 3(rPC),%ecx # ecx<- CC
3863 GET_VREG(%eax,%eax) # eax<- vBB
3864 GET_VREG(%ecx,%ecx) # eax<- vBB
3865 shrl %cl,%eax # ex: addl %ecx,%eax
3866 movzbl rINST_HI,%ecx # tmp<- AA
3867 FETCH_INST_WORD(2)
3868 ADVANCE_PC(2)
3869 SET_VREG(%eax,%ecx)
3870 GOTO_NEXT
3871
3872
3873/* ------------------------------ */
3874 .balign 64
3875.L_OP_ADD_LONG: /* 0x9b */
3876/* File: x86/OP_ADD_LONG.S */
3877/* File: x86/binopWide.S */
3878 /*
3879 * Generic 64-bit binary operation.
3880 */
3881 /* binop vAA, vBB, vCC */
3882
3883 movzbl 2(rPC),%eax # eax<- BB
3884 movzbl 3(rPC),%ecx # ecx<- CC
3885 SPILL(rPC)
3886 GET_VREG_WORD(rPC,%eax,0) # rPC<- v[BB+0]
3887 GET_VREG_WORD(%eax,%eax,1) # eax<- v[BB+1]
3888 addl (rFP,%ecx,4),rPC # ex: addl (rFP,%ecx,4),rPC
3889 adcl 4(rFP,%ecx,4),%eax # ex: adcl 4(rFP,%ecx,4),%eax
3890 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
3891 SET_VREG_WORD(rPC,rINST_FULL,0) # v[AA+0] <- rPC
3892 UNSPILL(rPC)
3893 SET_VREG_WORD(%eax,rINST_FULL,1) # v[AA+1] <- eax
3894 FETCH_INST_WORD(2)
3895 ADVANCE_PC(2)
3896 GOTO_NEXT
3897
3898
3899/* ------------------------------ */
3900 .balign 64
3901.L_OP_SUB_LONG: /* 0x9c */
3902/* File: x86/OP_SUB_LONG.S */
3903/* File: x86/binopWide.S */
3904 /*
3905 * Generic 64-bit binary operation.
3906 */
3907 /* binop vAA, vBB, vCC */
3908
3909 movzbl 2(rPC),%eax # eax<- BB
3910 movzbl 3(rPC),%ecx # ecx<- CC
3911 SPILL(rPC)
3912 GET_VREG_WORD(rPC,%eax,0) # rPC<- v[BB+0]
3913 GET_VREG_WORD(%eax,%eax,1) # eax<- v[BB+1]
3914 subl (rFP,%ecx,4),rPC # ex: addl (rFP,%ecx,4),rPC
3915 sbbl 4(rFP,%ecx,4),%eax # ex: adcl 4(rFP,%ecx,4),%eax
3916 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
3917 SET_VREG_WORD(rPC,rINST_FULL,0) # v[AA+0] <- rPC
3918 UNSPILL(rPC)
3919 SET_VREG_WORD(%eax,rINST_FULL,1) # v[AA+1] <- eax
3920 FETCH_INST_WORD(2)
3921 ADVANCE_PC(2)
3922 GOTO_NEXT
3923
3924
3925/* ------------------------------ */
3926 .balign 64
3927.L_OP_MUL_LONG: /* 0x9d */
3928/* File: x86/OP_MUL_LONG.S */
3929 /*
3930 * Signed 64-bit integer multiply.
3931 *
3932 * We could definately use more free registers for
3933 * this code. We must spill rPC (edx) because it
3934 * is used by imul. We'll also spill rINST (ebx),
3935 * giving us eax, ebc, ecx and edx as computational
3936 * temps. On top of that, we'll spill rIBASE (edi)
3937 * for use as the vB pointer and rFP (esi) for use
3938 * as the vC pointer. Yuck.
3939 */
3940 /* mul-long vAA, vBB, vCC */
3941 movzbl 2(rPC),%eax # eax<- B
3942 movzbl 3(rPC),%ecx # ecx<- C
3943 SPILL(rPC)
3944 SPILL(rIBASE)
3945 SPILL(rFP)
3946 SPILL(rINST_FULL)
3947 leal (rFP,%eax,4),rIBASE # rIBASE<- &v[B]
3948 leal (rFP,%ecx,4),rFP # rFP<- &v[C]
3949 movl 4(rIBASE),%ecx # ecx<- Bmsw
3950 imull (rFP),%ecx # ecx<- (Bmsw*Clsw)
3951 movl 4(rFP),%eax # eax<- Cmsw
3952 imull (rIBASE),%eax # eax<- (Cmsw*Blsw)
3953 addl %eax,%ecx # ecx<- (Bmsw*Clsw)+(Cmsw*Blsw)
3954 movl (rFP),%eax # eax<- Clsw
3955 mull (rIBASE) # eax<- (Clsw*Alsw)
3956 UNSPILL(rINST_FULL)
3957 UNSPILL(rFP)
3958 jmp .LOP_MUL_LONG_continue
3959
3960/* ------------------------------ */
3961 .balign 64
3962.L_OP_DIV_LONG: /* 0x9e */
3963/* File: x86/OP_DIV_LONG.S */
3964 /* div vAA, vBB, vCC */
3965 movzbl 3(rPC),%eax # eax<- CC
3966 movzbl 2(rPC),%ecx # ecx<- BB
3967 SPILL(rPC)
3968 GET_VREG_WORD(rPC,%eax,0)
3969 GET_VREG_WORD(%eax,%eax,1)
3970 movl rPC,OUT_ARG2(%esp)
3971 testl %eax,%eax
3972 je .LOP_DIV_LONG_check_zero
3973 cmpl $-1,%eax
3974 je .LOP_DIV_LONG_check_neg1
3975.LOP_DIV_LONG_notSpecial:
3976 GET_VREG_WORD(rPC,%ecx,0)
3977 GET_VREG_WORD(%ecx,%ecx,1)
3978.LOP_DIV_LONG_notSpecial1:
3979 movl %eax,OUT_ARG3(%esp)
3980 movl rPC,OUT_ARG0(%esp)
3981 movl %ecx,OUT_ARG1(%esp)
3982 jmp .LOP_DIV_LONG_continue
3983
3984/* ------------------------------ */
3985 .balign 64
3986.L_OP_REM_LONG: /* 0x9f */
3987/* File: x86/OP_REM_LONG.S */
3988/* File: x86/OP_DIV_LONG.S */
3989 /* div vAA, vBB, vCC */
3990 movzbl 3(rPC),%eax # eax<- CC
3991 movzbl 2(rPC),%ecx # ecx<- BB
3992 SPILL(rPC)
3993 GET_VREG_WORD(rPC,%eax,0)
3994 GET_VREG_WORD(%eax,%eax,1)
3995 movl rPC,OUT_ARG2(%esp)
3996 testl %eax,%eax
3997 je .LOP_REM_LONG_check_zero
3998 cmpl $-1,%eax
3999 je .LOP_REM_LONG_check_neg1
4000.LOP_REM_LONG_notSpecial:
4001 GET_VREG_WORD(rPC,%ecx,0)
4002 GET_VREG_WORD(%ecx,%ecx,1)
4003.LOP_REM_LONG_notSpecial1:
4004 movl %eax,OUT_ARG3(%esp)
4005 movl rPC,OUT_ARG0(%esp)
4006 movl %ecx,OUT_ARG1(%esp)
4007 jmp .LOP_REM_LONG_continue
4008
4009
4010/* ------------------------------ */
4011 .balign 64
4012.L_OP_AND_LONG: /* 0xa0 */
4013/* File: x86/OP_AND_LONG.S */
4014/* File: x86/binopWide.S */
4015 /*
4016 * Generic 64-bit binary operation.
4017 */
4018 /* binop vAA, vBB, vCC */
4019
4020 movzbl 2(rPC),%eax # eax<- BB
4021 movzbl 3(rPC),%ecx # ecx<- CC
4022 SPILL(rPC)
4023 GET_VREG_WORD(rPC,%eax,0) # rPC<- v[BB+0]
4024 GET_VREG_WORD(%eax,%eax,1) # eax<- v[BB+1]
4025 andl (rFP,%ecx,4),rPC # ex: addl (rFP,%ecx,4),rPC
4026 andl 4(rFP,%ecx,4),%eax # ex: adcl 4(rFP,%ecx,4),%eax
4027 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
4028 SET_VREG_WORD(rPC,rINST_FULL,0) # v[AA+0] <- rPC
4029 UNSPILL(rPC)
4030 SET_VREG_WORD(%eax,rINST_FULL,1) # v[AA+1] <- eax
4031 FETCH_INST_WORD(2)
4032 ADVANCE_PC(2)
4033 GOTO_NEXT
4034
4035
4036/* ------------------------------ */
4037 .balign 64
4038.L_OP_OR_LONG: /* 0xa1 */
4039/* File: x86/OP_OR_LONG.S */
4040/* File: x86/binopWide.S */
4041 /*
4042 * Generic 64-bit binary operation.
4043 */
4044 /* binop vAA, vBB, vCC */
4045
4046 movzbl 2(rPC),%eax # eax<- BB
4047 movzbl 3(rPC),%ecx # ecx<- CC
4048 SPILL(rPC)
4049 GET_VREG_WORD(rPC,%eax,0) # rPC<- v[BB+0]
4050 GET_VREG_WORD(%eax,%eax,1) # eax<- v[BB+1]
4051 orl (rFP,%ecx,4),rPC # ex: addl (rFP,%ecx,4),rPC
4052 orl 4(rFP,%ecx,4),%eax # ex: adcl 4(rFP,%ecx,4),%eax
4053 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
4054 SET_VREG_WORD(rPC,rINST_FULL,0) # v[AA+0] <- rPC
4055 UNSPILL(rPC)
4056 SET_VREG_WORD(%eax,rINST_FULL,1) # v[AA+1] <- eax
4057 FETCH_INST_WORD(2)
4058 ADVANCE_PC(2)
4059 GOTO_NEXT
4060
4061
4062/* ------------------------------ */
4063 .balign 64
4064.L_OP_XOR_LONG: /* 0xa2 */
4065/* File: x86/OP_XOR_LONG.S */
4066/* File: x86/binopWide.S */
4067 /*
4068 * Generic 64-bit binary operation.
4069 */
4070 /* binop vAA, vBB, vCC */
4071
4072 movzbl 2(rPC),%eax # eax<- BB
4073 movzbl 3(rPC),%ecx # ecx<- CC
4074 SPILL(rPC)
4075 GET_VREG_WORD(rPC,%eax,0) # rPC<- v[BB+0]
4076 GET_VREG_WORD(%eax,%eax,1) # eax<- v[BB+1]
4077 xorl (rFP,%ecx,4),rPC # ex: addl (rFP,%ecx,4),rPC
4078 xorl 4(rFP,%ecx,4),%eax # ex: adcl 4(rFP,%ecx,4),%eax
4079 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA
4080 SET_VREG_WORD(rPC,rINST_FULL,0) # v[AA+0] <- rPC
4081 UNSPILL(rPC)
4082 SET_VREG_WORD(%eax,rINST_FULL,1) # v[AA+1] <- eax
4083 FETCH_INST_WORD(2)
4084 ADVANCE_PC(2)
4085 GOTO_NEXT
4086
4087
4088/* ------------------------------ */
4089 .balign 64
4090.L_OP_SHL_LONG: /* 0xa3 */
4091/* File: x86/OP_SHL_LONG.S */
4092 /*
4093 * Long integer shift. This is different from the generic 32/64-bit
4094 * binary operations because vAA/vBB are 64-bit but vCC (the shift
4095 * distance) is 32-bit. Also, Dalvik requires us to mask off the low
4096 * 6 bits of the shift distance. x86 shifts automatically mask off
4097 * the low 5 bits of %cl, so have to handle the 64 > shiftcount > 31
4098 * case specially.
4099 */
4100 /* shl-long vAA, vBB, vCC */
4101 /* ecx gets shift count */
4102 /* Need to spill edx */
4103 /* rINST gets AA */
4104 movzbl 2(rPC),%eax # eax<- BB
4105 movzbl 3(rPC),%ecx # ecx<- CC
4106 SPILL(rPC) # spill edx
4107 GET_VREG_WORD(%edx,%eax,1) # ecx<- v[BB+1]
4108 GET_VREG (%ecx,%ecx) # ecx<- vCC
4109 GET_VREG_WORD(%eax,%eax,0) # eax<- v[BB+0]
4110 shldl %eax,%edx
4111 sall %cl,%eax
4112 testb $32,%cl
4113 je 2f
4114 movl %eax,%edx
4115 xorl %eax,%eax
41162:
4117 movzbl rINST_HI,%ecx
4118 SET_VREG_WORD(%edx,%ecx,1) # v[AA+1]<- %edx
4119 UNSPILL(rPC)
4120 FETCH_INST_WORD(2)
4121 jmp .LOP_SHL_LONG_finish
4122
4123/* ------------------------------ */
4124 .balign 64
4125.L_OP_SHR_LONG: /* 0xa4 */
4126/* File: x86/OP_SHR_LONG.S */
4127 /*
4128 * Long integer shift. This is different from the generic 32/64-bit
4129 * binary operations because vAA/vBB are 64-bit but vCC (the shift
4130 * distance) is 32-bit. Also, Dalvik requires us to mask off the low
4131 * 6 bits of the shift distance. x86 shifts automatically mask off
4132 * the low 5 bits of %cl, so have to handle the 64 > shiftcount > 31
4133 * case specially.
4134 */
4135 /* shr-long vAA, vBB, vCC */
4136 /* ecx gets shift count */
4137 /* Need to spill edx */
4138 /* rINST gets AA */
4139 movzbl 2(rPC),%eax # eax<- BB
4140 movzbl 3(rPC),%ecx # ecx<- CC
4141 SPILL(rPC) # spill edx
4142 GET_VREG_WORD(%edx,%eax,1) # edx<- v[BB+1]
4143 GET_VREG (%ecx,%ecx) # ecx<- vCC
4144 GET_VREG_WORD(%eax,%eax,0) # eax<- v[BB+0]
4145 shrdl %edx,%eax
4146 sarl %cl,%edx
4147 testb $32,%cl
4148 je 2f
4149 movl %edx,%eax
4150 sarl $31,%edx
41512:
4152 movzbl rINST_HI,%ecx
4153 SET_VREG_WORD(%edx,%ecx,1) # v[AA+1]<- edx
4154 UNSPILL(rPC)
4155 FETCH_INST_WORD(2)
4156 jmp .LOP_SHR_LONG_finish
4157
4158/* ------------------------------ */
4159 .balign 64
4160.L_OP_USHR_LONG: /* 0xa5 */
4161/* File: x86/OP_USHR_LONG.S */
4162 /*
4163 * Long integer shift. This is different from the generic 32/64-bit
4164 * binary operations because vAA/vBB are 64-bit but vCC (the shift
4165 * distance) is 32-bit. Also, Dalvik requires us to mask off the low
4166 * 6 bits of the shift distance. x86 shifts automatically mask off
4167 * the low 5 bits of %cl, so have to handle the 64 > shiftcount > 31
4168 * case specially.
4169 */
4170 /* shr-long vAA, vBB, vCC */
4171 /* ecx gets shift count */
4172 /* Need to spill edx */
4173 /* rINST gets AA */
4174 movzbl 2(rPC),%eax # eax<- BB
4175 movzbl 3(rPC),%ecx # ecx<- CC
4176 SPILL(rPC) # spill edx
4177 GET_VREG_WORD(%edx,%eax,1) # edx<- v[BB+1]
4178 GET_VREG (%ecx,%ecx) # ecx<- vCC
4179 GET_VREG_WORD(%eax,%eax,0) # eax<- v[BB+0]
4180 shrdl %edx,%eax
4181 shrl %cl,%edx
4182 testb $32,%cl
4183 je 2f
4184 movl %edx,%eax
4185 xorl %edx,%edx
41862:
4187 movzbl rINST_HI,%ecx
4188 SET_VREG_WORD(%edx,%ecx,1) # v[BB+1]<- edx
4189 UNSPILL(rPC)
4190 jmp .LOP_USHR_LONG_finish
4191
4192/* ------------------------------ */
4193 .balign 64
4194.L_OP_ADD_FLOAT: /* 0xa6 */
4195/* File: x86/OP_ADD_FLOAT.S */
4196/* File: x86/binflop.S */
4197 /*
4198 * Generic 32-bit binary float operation.
4199 *
4200 * For: add-fp, sub-fp, mul-fp, div-fp
4201 */
4202 /* binop vAA, vBB, vCC */
4203 movzbl 2(rPC),%eax # eax<- CC
4204 movzbl 3(rPC),%ecx # ecx<- BB
4205 flds (rFP,%eax,4) # vCC to fp stack
4206 fadds (rFP,%ecx,4) # ex: faddp
4207 movzbl rINST_HI,%ecx # ecx<- AA
4208 FETCH_INST_WORD(2)
4209 ADVANCE_PC(2)
4210 fstps (rFP,%ecx,4) # %st to vAA
4211 GOTO_NEXT
4212
4213
4214
4215/* ------------------------------ */
4216 .balign 64
4217.L_OP_SUB_FLOAT: /* 0xa7 */
4218/* File: x86/OP_SUB_FLOAT.S */
4219/* File: x86/binflop.S */
4220 /*
4221 * Generic 32-bit binary float operation.
4222 *
4223 * For: add-fp, sub-fp, mul-fp, div-fp
4224 */
4225 /* binop vAA, vBB, vCC */
4226 movzbl 2(rPC),%eax # eax<- CC
4227 movzbl 3(rPC),%ecx # ecx<- BB
4228 flds (rFP,%eax,4) # vCC to fp stack
4229 fsubs (rFP,%ecx,4) # ex: faddp
4230 movzbl rINST_HI,%ecx # ecx<- AA
4231 FETCH_INST_WORD(2)
4232 ADVANCE_PC(2)
4233 fstps (rFP,%ecx,4) # %st to vAA
4234 GOTO_NEXT
4235
4236
4237
4238/* ------------------------------ */
4239 .balign 64
4240.L_OP_MUL_FLOAT: /* 0xa8 */
4241/* File: x86/OP_MUL_FLOAT.S */
4242/* File: x86/binflop.S */
4243 /*
4244 * Generic 32-bit binary float operation.
4245 *
4246 * For: add-fp, sub-fp, mul-fp, div-fp
4247 */
4248 /* binop vAA, vBB, vCC */
4249 movzbl 2(rPC),%eax # eax<- CC
4250 movzbl 3(rPC),%ecx # ecx<- BB
4251 flds (rFP,%eax,4) # vCC to fp stack
4252 fmuls (rFP,%ecx,4) # ex: faddp
4253 movzbl rINST_HI,%ecx # ecx<- AA
4254 FETCH_INST_WORD(2)
4255 ADVANCE_PC(2)
4256 fstps (rFP,%ecx,4) # %st to vAA
4257 GOTO_NEXT
4258
4259
4260
4261/* ------------------------------ */
4262 .balign 64
4263.L_OP_DIV_FLOAT: /* 0xa9 */
4264/* File: x86/OP_DIV_FLOAT.S */
4265/* File: x86/binflop.S */
4266 /*
4267 * Generic 32-bit binary float operation.
4268 *
4269 * For: add-fp, sub-fp, mul-fp, div-fp
4270 */
4271 /* binop vAA, vBB, vCC */
4272 movzbl 2(rPC),%eax # eax<- CC
4273 movzbl 3(rPC),%ecx # ecx<- BB
4274 flds (rFP,%eax,4) # vCC to fp stack
4275 fdivs (rFP,%ecx,4) # ex: faddp
4276 movzbl rINST_HI,%ecx # ecx<- AA
4277 FETCH_INST_WORD(2)
4278 ADVANCE_PC(2)
4279 fstps (rFP,%ecx,4) # %st to vAA
4280 GOTO_NEXT
4281
4282
4283
4284/* ------------------------------ */
4285 .balign 64
4286.L_OP_REM_FLOAT: /* 0xaa */
4287/* File: x86/OP_REM_FLOAT.S */
4288 /* rem_float vAA, vBB, vCC */
4289 movzbl 3(rPC),%ecx # ecx<- BB
4290 movzbl 2(rPC),%eax # eax<- CC
4291 flds (rFP,%ecx,4) # vCC to fp stack
4292 flds (rFP,%eax,4) # vCC to fp stack
4293 movzbl rINST_HI,%ecx # ecx<- AA
4294 FETCH_INST_WORD(2)
42951:
4296 fprem
4297 fstsw %ax
4298 sahf
4299 jp 1b
4300 fstp %st(1)
4301 ADVANCE_PC(2)
4302 fstps (rFP,%ecx,4) # %st to vAA
4303 GOTO_NEXT
4304
4305/* ------------------------------ */
4306 .balign 64
4307.L_OP_ADD_DOUBLE: /* 0xab */
4308/* File: x86/OP_ADD_DOUBLE.S */
4309/* File: x86/binflop.S */
4310 /*
4311 * Generic 32-bit binary float operation.
4312 *
4313 * For: add-fp, sub-fp, mul-fp, div-fp
4314 */
4315 /* binop vAA, vBB, vCC */
4316 movzbl 2(rPC),%eax # eax<- CC
4317 movzbl 3(rPC),%ecx # ecx<- BB
4318 fldl (rFP,%eax,4) # vCC to fp stack
4319 faddl (rFP,%ecx,4) # ex: faddp
4320 movzbl rINST_HI,%ecx # ecx<- AA
4321 FETCH_INST_WORD(2)
4322 ADVANCE_PC(2)
4323 fstpl (rFP,%ecx,4) # %st to vAA
4324 GOTO_NEXT
4325
4326
4327
4328/* ------------------------------ */
4329 .balign 64
4330.L_OP_SUB_DOUBLE: /* 0xac */
4331/* File: x86/OP_SUB_DOUBLE.S */
4332/* File: x86/binflop.S */
4333 /*
4334 * Generic 32-bit binary float operation.
4335 *
4336 * For: add-fp, sub-fp, mul-fp, div-fp
4337 */
4338 /* binop vAA, vBB, vCC */
4339 movzbl 2(rPC),%eax # eax<- CC
4340 movzbl 3(rPC),%ecx # ecx<- BB
4341 fldl (rFP,%eax,4) # vCC to fp stack
4342 fsubl (rFP,%ecx,4) # ex: faddp
4343 movzbl rINST_HI,%ecx # ecx<- AA
4344 FETCH_INST_WORD(2)
4345 ADVANCE_PC(2)
4346 fstpl (rFP,%ecx,4) # %st to vAA
4347 GOTO_NEXT
4348
4349
4350
4351/* ------------------------------ */
4352 .balign 64
4353.L_OP_MUL_DOUBLE: /* 0xad */
4354/* File: x86/OP_MUL_DOUBLE.S */
4355/* File: x86/binflop.S */
4356 /*
4357 * Generic 32-bit binary float operation.
4358 *
4359 * For: add-fp, sub-fp, mul-fp, div-fp
4360 */
4361 /* binop vAA, vBB, vCC */
4362 movzbl 2(rPC),%eax # eax<- CC
4363 movzbl 3(rPC),%ecx # ecx<- BB
4364 fldl (rFP,%eax,4) # vCC to fp stack
4365 fmull (rFP,%ecx,4) # ex: faddp
4366 movzbl rINST_HI,%ecx # ecx<- AA
4367 FETCH_INST_WORD(2)
4368 ADVANCE_PC(2)
4369 fstpl (rFP,%ecx,4) # %st to vAA
4370 GOTO_NEXT
4371
4372
4373
4374/* ------------------------------ */
4375 .balign 64
4376.L_OP_DIV_DOUBLE: /* 0xae */
4377/* File: x86/OP_DIV_DOUBLE.S */
4378/* File: x86/binflop.S */
4379 /*
4380 * Generic 32-bit binary float operation.
4381 *
4382 * For: add-fp, sub-fp, mul-fp, div-fp
4383 */
4384 /* binop vAA, vBB, vCC */
4385 movzbl 2(rPC),%eax # eax<- CC
4386 movzbl 3(rPC),%ecx # ecx<- BB
4387 fldl (rFP,%eax,4) # vCC to fp stack
4388 fdivl (rFP,%ecx,4) # ex: faddp
4389 movzbl rINST_HI,%ecx # ecx<- AA
4390 FETCH_INST_WORD(2)
4391 ADVANCE_PC(2)
4392 fstpl (rFP,%ecx,4) # %st to vAA
4393 GOTO_NEXT
4394
4395
4396
4397/* ------------------------------ */
4398 .balign 64
4399.L_OP_REM_DOUBLE: /* 0xaf */
4400/* File: x86/OP_REM_DOUBLE.S */
4401 /* rem_float vAA, vBB, vCC */
4402 movzbl 3(rPC),%ecx # ecx<- BB
4403 movzbl 2(rPC),%eax # eax<- CC
4404 fldl (rFP,%ecx,4) # vCC to fp stack
4405 fldl (rFP,%eax,4) # vCC to fp stack
4406 movzbl rINST_HI,%ecx # ecx<- AA
4407 FETCH_INST_WORD(2)
44081:
4409 fprem
4410 fstsw %ax
4411 sahf
4412 jp 1b
4413 fstp %st(1)
4414 ADVANCE_PC(2)
4415 fstpl (rFP,%ecx,4) # %st to vAA
4416 GOTO_NEXT
4417
4418/* ------------------------------ */
4419 .balign 64
4420.L_OP_ADD_INT_2ADDR: /* 0xb0 */
4421/* File: x86/OP_ADD_INT_2ADDR.S */
4422/* File: x86/binop2addr.S */
4423 /*
4424 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
4425 * that specifies an instruction that performs "result = r0 op r1".
4426 * This could be an ARM instruction or a function call. (If the result
4427 * comes back in a register other than r0, you can override "result".)
4428 *
4429 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4430 * vCC (r1). Useful for integer division and modulus.
4431 *
4432 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
4433 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
4434 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
4435 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
4436 */
4437 /* binop/2addr vA, vB */
4438 movzx rINST_HI,%ecx # ecx<- A+
4439 sarl $12,rINST_FULL # rINST_FULL<- B
4440 GET_VREG(%eax,rINST_FULL) # eax<- vB
4441 FETCH_INST_WORD(1)
4442 andb $0xf,%cl # ecx<- A
4443 addl %eax,(rFP,%ecx,4) # for ex: addl %eax,(rFP,%ecx,4)
4444 ADVANCE_PC(1)
4445 GOTO_NEXT
4446
4447
4448/* ------------------------------ */
4449 .balign 64
4450.L_OP_SUB_INT_2ADDR: /* 0xb1 */
4451/* File: x86/OP_SUB_INT_2ADDR.S */
4452/* File: x86/binop2addr.S */
4453 /*
4454 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
4455 * that specifies an instruction that performs "result = r0 op r1".
4456 * This could be an ARM instruction or a function call. (If the result
4457 * comes back in a register other than r0, you can override "result".)
4458 *
4459 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4460 * vCC (r1). Useful for integer division and modulus.
4461 *
4462 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
4463 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
4464 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
4465 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
4466 */
4467 /* binop/2addr vA, vB */
4468 movzx rINST_HI,%ecx # ecx<- A+
4469 sarl $12,rINST_FULL # rINST_FULL<- B
4470 GET_VREG(%eax,rINST_FULL) # eax<- vB
4471 FETCH_INST_WORD(1)
4472 andb $0xf,%cl # ecx<- A
4473 subl %eax,(rFP,%ecx,4) # for ex: addl %eax,(rFP,%ecx,4)
4474 ADVANCE_PC(1)
4475 GOTO_NEXT
4476
4477
4478/* ------------------------------ */
4479 .balign 64
4480.L_OP_MUL_INT_2ADDR: /* 0xb2 */
4481/* File: x86/OP_MUL_INT_2ADDR.S */
4482 /* mul vA, vB */
4483 movzx rINST_HI,%ecx # ecx<- A+
4484 sarl $12,rINST_FULL # rINST_FULL<- B
4485 GET_VREG(%eax,rINST_FULL) # eax<- vB
4486 andb $0xf,%cl # ecx<- A
4487 SPILL(rPC)
4488 imull (rFP,%ecx,4),%eax
4489 UNSPILL(rPC)
4490 SET_VREG(%eax,%ecx)
4491 FETCH_INST_WORD(1)
4492 ADVANCE_PC(1)
4493 GOTO_NEXT
4494
4495/* ------------------------------ */
4496 .balign 64
4497.L_OP_DIV_INT_2ADDR: /* 0xb3 */
4498/* File: x86/OP_DIV_INT_2ADDR.S */
4499/* File: x86/bindiv2addr.S */
4500 /*
4501 * 32-bit binary div/rem operation. Handles special case of op0=minint and
4502 * op1=-1.
4503 */
4504 /* div/rem/2addr vA, vB */
4505 movzx rINST_HI,%ecx # eax<- BA
4506 sarl $4,%ecx # ecx<- B
4507 GET_VREG(%ecx,%ecx) # eax<- vBB
4508 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
4509 andb $0xf,rINST_LO # rINST_FULL<- A
4510 GET_VREG(%eax,rINST_FULL) # eax<- vBB
4511 SPILL(rPC)
4512 cmpl $0,%ecx
4513 je common_errDivideByZero
4514 cmpl $-1,%ecx
4515 jne .LOP_DIV_INT_2ADDR_continue_div2addr
4516 cmpl $0x80000000,%eax
4517 jne .LOP_DIV_INT_2ADDR_continue_div2addr
4518 movl $0x80000000,%eax
4519 jmp .LOP_DIV_INT_2ADDR_finish_div2addr
4520
4521
4522
4523/* ------------------------------ */
4524 .balign 64
4525.L_OP_REM_INT_2ADDR: /* 0xb4 */
4526/* File: x86/OP_REM_INT_2ADDR.S */
4527/* File: x86/bindiv2addr.S */
4528 /*
4529 * 32-bit binary div/rem operation. Handles special case of op0=minint and
4530 * op1=-1.
4531 */
4532 /* div/rem/2addr vA, vB */
4533 movzx rINST_HI,%ecx # eax<- BA
4534 sarl $4,%ecx # ecx<- B
4535 GET_VREG(%ecx,%ecx) # eax<- vBB
4536 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
4537 andb $0xf,rINST_LO # rINST_FULL<- A
4538 GET_VREG(%eax,rINST_FULL) # eax<- vBB
4539 SPILL(rPC)
4540 cmpl $0,%ecx
4541 je common_errDivideByZero
4542 cmpl $-1,%ecx
4543 jne .LOP_REM_INT_2ADDR_continue_div2addr
4544 cmpl $0x80000000,%eax
4545 jne .LOP_REM_INT_2ADDR_continue_div2addr
4546 movl $0,%edx
4547 jmp .LOP_REM_INT_2ADDR_finish_div2addr
4548
4549
4550
4551/* ------------------------------ */
4552 .balign 64
4553.L_OP_AND_INT_2ADDR: /* 0xb5 */
4554/* File: x86/OP_AND_INT_2ADDR.S */
4555/* File: x86/binop2addr.S */
4556 /*
4557 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
4558 * that specifies an instruction that performs "result = r0 op r1".
4559 * This could be an ARM instruction or a function call. (If the result
4560 * comes back in a register other than r0, you can override "result".)
4561 *
4562 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4563 * vCC (r1). Useful for integer division and modulus.
4564 *
4565 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
4566 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
4567 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
4568 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
4569 */
4570 /* binop/2addr vA, vB */
4571 movzx rINST_HI,%ecx # ecx<- A+
4572 sarl $12,rINST_FULL # rINST_FULL<- B
4573 GET_VREG(%eax,rINST_FULL) # eax<- vB
4574 FETCH_INST_WORD(1)
4575 andb $0xf,%cl # ecx<- A
4576 andl %eax,(rFP,%ecx,4) # for ex: addl %eax,(rFP,%ecx,4)
4577 ADVANCE_PC(1)
4578 GOTO_NEXT
4579
4580
4581/* ------------------------------ */
4582 .balign 64
4583.L_OP_OR_INT_2ADDR: /* 0xb6 */
4584/* File: x86/OP_OR_INT_2ADDR.S */
4585/* File: x86/binop2addr.S */
4586 /*
4587 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
4588 * that specifies an instruction that performs "result = r0 op r1".
4589 * This could be an ARM instruction or a function call. (If the result
4590 * comes back in a register other than r0, you can override "result".)
4591 *
4592 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4593 * vCC (r1). Useful for integer division and modulus.
4594 *
4595 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
4596 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
4597 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
4598 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
4599 */
4600 /* binop/2addr vA, vB */
4601 movzx rINST_HI,%ecx # ecx<- A+
4602 sarl $12,rINST_FULL # rINST_FULL<- B
4603 GET_VREG(%eax,rINST_FULL) # eax<- vB
4604 FETCH_INST_WORD(1)
4605 andb $0xf,%cl # ecx<- A
4606 orl %eax,(rFP,%ecx,4) # for ex: addl %eax,(rFP,%ecx,4)
4607 ADVANCE_PC(1)
4608 GOTO_NEXT
4609
4610
4611/* ------------------------------ */
4612 .balign 64
4613.L_OP_XOR_INT_2ADDR: /* 0xb7 */
4614/* File: x86/OP_XOR_INT_2ADDR.S */
4615/* File: x86/binop2addr.S */
4616 /*
4617 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
4618 * that specifies an instruction that performs "result = r0 op r1".
4619 * This could be an ARM instruction or a function call. (If the result
4620 * comes back in a register other than r0, you can override "result".)
4621 *
4622 * If "chkzero" is set to 1, we perform a divide-by-zero check on
4623 * vCC (r1). Useful for integer division and modulus.
4624 *
4625 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
4626 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
4627 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
4628 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
4629 */
4630 /* binop/2addr vA, vB */
4631 movzx rINST_HI,%ecx # ecx<- A+
4632 sarl $12,rINST_FULL # rINST_FULL<- B
4633 GET_VREG(%eax,rINST_FULL) # eax<- vB
4634 FETCH_INST_WORD(1)
4635 andb $0xf,%cl # ecx<- A
4636 xorl %eax,(rFP,%ecx,4) # for ex: addl %eax,(rFP,%ecx,4)
4637 ADVANCE_PC(1)
4638 GOTO_NEXT
4639
4640
4641/* ------------------------------ */
4642 .balign 64
4643.L_OP_SHL_INT_2ADDR: /* 0xb8 */
4644/* File: x86/OP_SHL_INT_2ADDR.S */
4645/* File: x86/shop2addr.S */
4646 /*
4647 * Generic 32-bit "shift/2addr" operation.
4648 */
4649 /* shift/2addr vA, vB */
4650 movzx rINST_HI,%ecx # eax<- BA
4651 sarl $4,%ecx # ecx<- B
4652 GET_VREG(%ecx,%ecx) # eax<- vBB
4653 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
4654 andb $0xf,rINST_LO # rINST_FULL<- A
4655 GET_VREG(%eax,rINST_FULL) # eax<- vAA
4656 sall %cl,%eax # ex: sarl %cl,%eax
4657 SET_VREG(%eax,rINST_FULL)
4658 FETCH_INST_WORD(1)
4659 ADVANCE_PC(1)
4660 GOTO_NEXT
4661
4662
4663
4664/* ------------------------------ */
4665 .balign 64
4666.L_OP_SHR_INT_2ADDR: /* 0xb9 */
4667/* File: x86/OP_SHR_INT_2ADDR.S */
4668/* File: x86/shop2addr.S */
4669 /*
4670 * Generic 32-bit "shift/2addr" operation.
4671 */
4672 /* shift/2addr vA, vB */
4673 movzx rINST_HI,%ecx # eax<- BA
4674 sarl $4,%ecx # ecx<- B
4675 GET_VREG(%ecx,%ecx) # eax<- vBB
4676 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
4677 andb $0xf,rINST_LO # rINST_FULL<- A
4678 GET_VREG(%eax,rINST_FULL) # eax<- vAA
4679 sarl %cl,%eax # ex: sarl %cl,%eax
4680 SET_VREG(%eax,rINST_FULL)
4681 FETCH_INST_WORD(1)
4682 ADVANCE_PC(1)
4683 GOTO_NEXT
4684
4685
4686
4687/* ------------------------------ */
4688 .balign 64
4689.L_OP_USHR_INT_2ADDR: /* 0xba */
4690/* File: x86/OP_USHR_INT_2ADDR.S */
4691/* File: x86/shop2addr.S */
4692 /*
4693 * Generic 32-bit "shift/2addr" operation.
4694 */
4695 /* shift/2addr vA, vB */
4696 movzx rINST_HI,%ecx # eax<- BA
4697 sarl $4,%ecx # ecx<- B
4698 GET_VREG(%ecx,%ecx) # eax<- vBB
4699 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
4700 andb $0xf,rINST_LO # rINST_FULL<- A
4701 GET_VREG(%eax,rINST_FULL) # eax<- vAA
4702 shrl %cl,%eax # ex: sarl %cl,%eax
4703 SET_VREG(%eax,rINST_FULL)
4704 FETCH_INST_WORD(1)
4705 ADVANCE_PC(1)
4706 GOTO_NEXT
4707
4708
4709
4710/* ------------------------------ */
4711 .balign 64
4712.L_OP_ADD_LONG_2ADDR: /* 0xbb */
4713/* File: x86/OP_ADD_LONG_2ADDR.S */
4714/* File: x86/binopWide2addr.S */
4715 /*
4716 * Generic 64-bit binary operation.
4717 */
4718 /* binop/2addr vA, vB */
4719 movzbl rINST_HI,%ecx # ecx<- BA
4720 sarl $4,%ecx # ecx<- B
4721 GET_VREG_WORD(%eax,%ecx,0) # eax<- v[B+0]
4722 GET_VREG_WORD(%ecx,%ecx,1) # eax<- v[B+1]
4723 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
4724 andb $0xF,rINST_LO # rINST_FULL<- A
4725 addl %eax,(rFP,rINST_FULL,4) # example: addl %eax,(rFP,rINST_FULL,4)
4726 adcl %ecx,4(rFP,rINST_FULL,4) # example: adcl %ecx,4(rFP,rINST_FULL,4)
4727 FETCH_INST_WORD(1)
4728 ADVANCE_PC(1)
4729 GOTO_NEXT
4730
4731
4732/* ------------------------------ */
4733 .balign 64
4734.L_OP_SUB_LONG_2ADDR: /* 0xbc */
4735/* File: x86/OP_SUB_LONG_2ADDR.S */
4736/* File: x86/binopWide2addr.S */
4737 /*
4738 * Generic 64-bit binary operation.
4739 */
4740 /* binop/2addr vA, vB */
4741 movzbl rINST_HI,%ecx # ecx<- BA
4742 sarl $4,%ecx # ecx<- B
4743 GET_VREG_WORD(%eax,%ecx,0) # eax<- v[B+0]
4744 GET_VREG_WORD(%ecx,%ecx,1) # eax<- v[B+1]
4745 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
4746 andb $0xF,rINST_LO # rINST_FULL<- A
4747 subl %eax,(rFP,rINST_FULL,4) # example: addl %eax,(rFP,rINST_FULL,4)
4748 sbbl %ecx,4(rFP,rINST_FULL,4) # example: adcl %ecx,4(rFP,rINST_FULL,4)
4749 FETCH_INST_WORD(1)
4750 ADVANCE_PC(1)
4751 GOTO_NEXT
4752
4753
4754/* ------------------------------ */
4755 .balign 64
4756.L_OP_MUL_LONG_2ADDR: /* 0xbd */
4757/* File: x86/OP_MUL_LONG_2ADDR.S */
4758 /*
4759 * Signed 64-bit integer multiply, 2-addr version
4760 *
4761 * We could definately use more free registers for
4762 * this code. We must spill rPC (edx) because it
4763 * is used by imul. We'll also spill rINST (ebx),
4764 * giving us eax, ebc, ecx and edx as computational
4765 * temps. On top of that, we'll spill rIBASE (edi)
4766 * for use as the vA pointer and rFP (esi) for use
4767 * as the vB pointer. Yuck.
4768 */
4769 /* mul-long/2addr vA, vB */
4770 movzbl rINST_HI,%eax # eax<- BA
4771 andb $0xf,%al # eax<- A
4772 sarl $12,rINST_FULL # rINST_FULL<- B
4773 SPILL(rPC)
4774 SPILL(rIBASE)
4775 SPILL(rFP)
4776 leal (rFP,%eax,4),rIBASE # rIBASE<- &v[A]
4777 leal (rFP,rINST_FULL,4),rFP # rFP<- &v[B]
4778 movl 4(rIBASE),%ecx # ecx<- Amsw
4779 imull (rFP),%ecx # ecx<- (Amsw*Blsw)
4780 movl 4(rFP),%eax # eax<- Bmsw
4781 imull (rIBASE),%eax # eax<- (Bmsw*Alsw)
4782 addl %eax,%ecx # ecx<- (Amsw*Blsw)+(Bmsw*Alsw)
4783 movl (rFP),%eax # eax<- Blsw
4784 mull (rIBASE) # eax<- (Blsw*Alsw)
4785 jmp .LOP_MUL_LONG_2ADDR_continue
4786
4787/* ------------------------------ */
4788 .balign 64
4789.L_OP_DIV_LONG_2ADDR: /* 0xbe */
4790/* File: x86/OP_DIV_LONG_2ADDR.S */
4791 /* div/2addr vA, vB */
4792 movzbl rINST_HI,%eax
4793 shrl $4,%eax # eax<- B
4794 movzbl rINST_HI,rINST_FULL
4795 andb $0xf,rINST_LO # rINST_FULL<- A
4796 SPILL(rPC)
4797 GET_VREG_WORD(rPC,%eax,0)
4798 GET_VREG_WORD(%eax,%eax,1)
4799 movl rPC,OUT_ARG2(%esp)
4800 testl %eax,%eax
4801 je .LOP_DIV_LONG_2ADDR_check_zero
4802 cmpl $-1,%eax
4803 je .LOP_DIV_LONG_2ADDR_check_neg1
4804.LOP_DIV_LONG_2ADDR_notSpecial:
4805 GET_VREG_WORD(rPC,rINST_FULL,0)
4806 GET_VREG_WORD(%ecx,rINST_FULL,1)
4807.LOP_DIV_LONG_2ADDR_notSpecial1:
4808 jmp .LOP_DIV_LONG_2ADDR_continue
4809
4810/* ------------------------------ */
4811 .balign 64
4812.L_OP_REM_LONG_2ADDR: /* 0xbf */
4813/* File: x86/OP_REM_LONG_2ADDR.S */
4814/* File: x86/OP_DIV_LONG_2ADDR.S */
4815 /* div/2addr vA, vB */
4816 movzbl rINST_HI,%eax
4817 shrl $4,%eax # eax<- B
4818 movzbl rINST_HI,rINST_FULL
4819 andb $0xf,rINST_LO # rINST_FULL<- A
4820 SPILL(rPC)
4821 GET_VREG_WORD(rPC,%eax,0)
4822 GET_VREG_WORD(%eax,%eax,1)
4823 movl rPC,OUT_ARG2(%esp)
4824 testl %eax,%eax
4825 je .LOP_REM_LONG_2ADDR_check_zero
4826 cmpl $-1,%eax
4827 je .LOP_REM_LONG_2ADDR_check_neg1
4828.LOP_REM_LONG_2ADDR_notSpecial:
4829 GET_VREG_WORD(rPC,rINST_FULL,0)
4830 GET_VREG_WORD(%ecx,rINST_FULL,1)
4831.LOP_REM_LONG_2ADDR_notSpecial1:
4832 jmp .LOP_REM_LONG_2ADDR_continue
4833
4834
4835/* ------------------------------ */
4836 .balign 64
4837.L_OP_AND_LONG_2ADDR: /* 0xc0 */
4838/* File: x86/OP_AND_LONG_2ADDR.S */
4839/* File: x86/binopWide2addr.S */
4840 /*
4841 * Generic 64-bit binary operation.
4842 */
4843 /* binop/2addr vA, vB */
4844 movzbl rINST_HI,%ecx # ecx<- BA
4845 sarl $4,%ecx # ecx<- B
4846 GET_VREG_WORD(%eax,%ecx,0) # eax<- v[B+0]
4847 GET_VREG_WORD(%ecx,%ecx,1) # eax<- v[B+1]
4848 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
4849 andb $0xF,rINST_LO # rINST_FULL<- A
4850 andl %eax,(rFP,rINST_FULL,4) # example: addl %eax,(rFP,rINST_FULL,4)
4851 andl %ecx,4(rFP,rINST_FULL,4) # example: adcl %ecx,4(rFP,rINST_FULL,4)
4852 FETCH_INST_WORD(1)
4853 ADVANCE_PC(1)
4854 GOTO_NEXT
4855
4856
4857/* ------------------------------ */
4858 .balign 64
4859.L_OP_OR_LONG_2ADDR: /* 0xc1 */
4860/* File: x86/OP_OR_LONG_2ADDR.S */
4861/* File: x86/binopWide2addr.S */
4862 /*
4863 * Generic 64-bit binary operation.
4864 */
4865 /* binop/2addr vA, vB */
4866 movzbl rINST_HI,%ecx # ecx<- BA
4867 sarl $4,%ecx # ecx<- B
4868 GET_VREG_WORD(%eax,%ecx,0) # eax<- v[B+0]
4869 GET_VREG_WORD(%ecx,%ecx,1) # eax<- v[B+1]
4870 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
4871 andb $0xF,rINST_LO # rINST_FULL<- A
4872 orl %eax,(rFP,rINST_FULL,4) # example: addl %eax,(rFP,rINST_FULL,4)
4873 orl %ecx,4(rFP,rINST_FULL,4) # example: adcl %ecx,4(rFP,rINST_FULL,4)
4874 FETCH_INST_WORD(1)
4875 ADVANCE_PC(1)
4876 GOTO_NEXT
4877
4878
4879/* ------------------------------ */
4880 .balign 64
4881.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
4882/* File: x86/OP_XOR_LONG_2ADDR.S */
4883/* File: x86/binopWide2addr.S */
4884 /*
4885 * Generic 64-bit binary operation.
4886 */
4887 /* binop/2addr vA, vB */
4888 movzbl rINST_HI,%ecx # ecx<- BA
4889 sarl $4,%ecx # ecx<- B
4890 GET_VREG_WORD(%eax,%ecx,0) # eax<- v[B+0]
4891 GET_VREG_WORD(%ecx,%ecx,1) # eax<- v[B+1]
4892 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
4893 andb $0xF,rINST_LO # rINST_FULL<- A
4894 xorl %eax,(rFP,rINST_FULL,4) # example: addl %eax,(rFP,rINST_FULL,4)
4895 xorl %ecx,4(rFP,rINST_FULL,4) # example: adcl %ecx,4(rFP,rINST_FULL,4)
4896 FETCH_INST_WORD(1)
4897 ADVANCE_PC(1)
4898 GOTO_NEXT
4899
4900
4901/* ------------------------------ */
4902 .balign 64
4903.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
4904/* File: x86/OP_SHL_LONG_2ADDR.S */
4905 /*
4906 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
4907 * 32-bit shift distance.
4908 */
4909 /* shl-long/2addr vA, vB */
4910 /* ecx gets shift count */
4911 /* Need to spill edx */
4912 /* rINST gets AA */
4913 movzbl rINST_HI,%ecx # ecx<- BA
4914 movzbl rINST_HI,rINST_FULL # rINST_HI<- BA
4915 andb $0xf,rINST_LO # rINST_FULL<- A
4916 GET_VREG_WORD(%eax,rINST_FULL,0) # eax<- v[AA+0]
4917 sarl $4,%ecx # ecx<- B
4918 SPILL(rPC)
4919 GET_VREG_WORD(%edx,rINST_FULL,1) # edx<- v[AA+1]
4920 GET_VREG(%ecx,%ecx) # ecx<- vBB
4921 shldl %eax,%edx
4922 sall %cl,%eax
4923 testb $32,%cl
4924 je 2f
4925 movl %eax,%edx
4926 xorl %eax,%eax
49272:
4928 SET_VREG_WORD(%edx,rINST_FULL,1) # v[AA+1]<- edx
4929 UNSPILL(rPC)
4930 jmp .LOP_SHL_LONG_2ADDR_finish
4931
4932/* ------------------------------ */
4933 .balign 64
4934.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
4935/* File: x86/OP_SHR_LONG_2ADDR.S */
4936 /*
4937 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
4938 * 32-bit shift distance.
4939 */
4940 /* shl-long/2addr vA, vB */
4941 /* ecx gets shift count */
4942 /* Need to spill edx */
4943 /* rINST gets AA */
4944 movzbl rINST_HI,%ecx # ecx<- BA
4945 movzbl rINST_HI,rINST_FULL # rINST_HI<- BA
4946 andb $0xf,rINST_LO # rINST_FULL<- A
4947 GET_VREG_WORD(%eax,rINST_FULL,0) # eax<- v[AA+0]
4948 sarl $4,%ecx # ecx<- B
4949 SPILL(rPC)
4950 GET_VREG_WORD(%edx,rINST_FULL,1) # edx<- v[AA+1]
4951 GET_VREG(%ecx,%ecx) # ecx<- vBB
4952 shrdl %edx,%eax
4953 sarl %cl,%edx
4954 testb $32,%cl
4955 je 2f
4956 movl %edx,%eax
4957 sarl $31,%edx
49582:
4959 SET_VREG_WORD(%edx,rINST_FULL,1) # v[AA+1]<- edx
4960 UNSPILL(rPC)
4961 jmp .LOP_SHR_LONG_2ADDR_finish
4962
4963/* ------------------------------ */
4964 .balign 64
4965.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
4966/* File: x86/OP_USHR_LONG_2ADDR.S */
4967 /*
4968 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
4969 * 32-bit shift distance.
4970 */
4971 /* shl-long/2addr vA, vB */
4972 /* ecx gets shift count */
4973 /* Need to spill edx */
4974 /* rINST gets AA */
4975 movzbl rINST_HI,%ecx # ecx<- BA
4976 movzbl rINST_HI,rINST_FULL # rINST_HI<- BA
4977 andb $0xf,rINST_LO # rINST_FULL<- A
4978 GET_VREG_WORD(%eax,rINST_FULL,0) # eax<- v[AA+0]
4979 sarl $4,%ecx # ecx<- B
4980 SPILL(rPC)
4981 GET_VREG_WORD(%edx,rINST_FULL,1) # edx<- v[AA+1]
4982 GET_VREG(%ecx,%ecx) # ecx<- vBB
4983 shrdl %edx,%eax
4984 shrl %cl,%edx
4985 testb $32,%cl
4986 je 2f
4987 movl %edx,%eax
4988 xorl %edx,%edx
49892:
4990 SET_VREG_WORD(%edx,rINST_FULL,1) # v[AA+1]<- edx
4991 UNSPILL(rPC)
4992 jmp .LOP_USHR_LONG_2ADDR_finish
4993
4994/* ------------------------------ */
4995 .balign 64
4996.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
4997/* File: x86/OP_ADD_FLOAT_2ADDR.S */
4998/* File: x86/binflop2addr.S */
4999 /*
5000 * Generic 32-bit binary float operation.
5001 *
5002 * For: add-fp, sub-fp, mul-fp, div-fp
5003 */
5004
5005 /* binop/2addr vA, vB */
5006 movzx rINST_HI,%ecx # ecx<- A+
5007 andb $0xf,%cl # ecx<- A
5008 flds (rFP,%ecx,4) # vAA to fp stack
5009 sarl $12,rINST_FULL # rINST_FULL<- B
5010 fadds (rFP,rINST_FULL,4) # ex: faddp
5011 FETCH_INST_WORD(1)
5012 ADVANCE_PC(1)
5013 fstps (rFP,%ecx,4) # %st to vA
5014 GOTO_NEXT
5015
5016
5017/* ------------------------------ */
5018 .balign 64
5019.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
5020/* File: x86/OP_SUB_FLOAT_2ADDR.S */
5021/* File: x86/binflop2addr.S */
5022 /*
5023 * Generic 32-bit binary float operation.
5024 *
5025 * For: add-fp, sub-fp, mul-fp, div-fp
5026 */
5027
5028 /* binop/2addr vA, vB */
5029 movzx rINST_HI,%ecx # ecx<- A+
5030 andb $0xf,%cl # ecx<- A
5031 flds (rFP,%ecx,4) # vAA to fp stack
5032 sarl $12,rINST_FULL # rINST_FULL<- B
5033 fsubs (rFP,rINST_FULL,4) # ex: faddp
5034 FETCH_INST_WORD(1)
5035 ADVANCE_PC(1)
5036 fstps (rFP,%ecx,4) # %st to vA
5037 GOTO_NEXT
5038
5039
5040/* ------------------------------ */
5041 .balign 64
5042.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
5043/* File: x86/OP_MUL_FLOAT_2ADDR.S */
5044/* File: x86/binflop2addr.S */
5045 /*
5046 * Generic 32-bit binary float operation.
5047 *
5048 * For: add-fp, sub-fp, mul-fp, div-fp
5049 */
5050
5051 /* binop/2addr vA, vB */
5052 movzx rINST_HI,%ecx # ecx<- A+
5053 andb $0xf,%cl # ecx<- A
5054 flds (rFP,%ecx,4) # vAA to fp stack
5055 sarl $12,rINST_FULL # rINST_FULL<- B
5056 fmuls (rFP,rINST_FULL,4) # ex: faddp
5057 FETCH_INST_WORD(1)
5058 ADVANCE_PC(1)
5059 fstps (rFP,%ecx,4) # %st to vA
5060 GOTO_NEXT
5061
5062
5063/* ------------------------------ */
5064 .balign 64
5065.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
5066/* File: x86/OP_DIV_FLOAT_2ADDR.S */
5067/* File: x86/binflop2addr.S */
5068 /*
5069 * Generic 32-bit binary float operation.
5070 *
5071 * For: add-fp, sub-fp, mul-fp, div-fp
5072 */
5073
5074 /* binop/2addr vA, vB */
5075 movzx rINST_HI,%ecx # ecx<- A+
5076 andb $0xf,%cl # ecx<- A
5077 flds (rFP,%ecx,4) # vAA to fp stack
5078 sarl $12,rINST_FULL # rINST_FULL<- B
5079 fdivs (rFP,rINST_FULL,4) # ex: faddp
5080 FETCH_INST_WORD(1)
5081 ADVANCE_PC(1)
5082 fstps (rFP,%ecx,4) # %st to vA
5083 GOTO_NEXT
5084
5085
5086/* ------------------------------ */
5087 .balign 64
5088.L_OP_REM_FLOAT_2ADDR: /* 0xca */
5089/* File: x86/OP_REM_FLOAT_2ADDR.S */
5090 /* rem_float/2addr vA, vB */
5091 movzx rINST_HI,%ecx # ecx<- A+
5092 sarl $12,rINST_FULL # rINST_FULL<- B
5093 flds (rFP,rINST_FULL,4) # vBB to fp stack
5094 andb $0xf,%cl # ecx<- A
5095 flds (rFP,%ecx,4) # vAA to fp stack
5096 FETCH_INST_WORD(1)
50971:
5098 fprem
5099 fstsw %ax
5100 sahf
5101 jp 1b
5102 fstp %st(1)
5103 ADVANCE_PC(1)
5104 fstps (rFP,%ecx,4) # %st to vA
5105 GOTO_NEXT
5106
5107/* ------------------------------ */
5108 .balign 64
5109.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
5110/* File: x86/OP_ADD_DOUBLE_2ADDR.S */
5111/* File: x86/binflop2addr.S */
5112 /*
5113 * Generic 32-bit binary float operation.
5114 *
5115 * For: add-fp, sub-fp, mul-fp, div-fp
5116 */
5117
5118 /* binop/2addr vA, vB */
5119 movzx rINST_HI,%ecx # ecx<- A+
5120 andb $0xf,%cl # ecx<- A
5121 fldl (rFP,%ecx,4) # vAA to fp stack
5122 sarl $12,rINST_FULL # rINST_FULL<- B
5123 faddl (rFP,rINST_FULL,4) # ex: faddp
5124 FETCH_INST_WORD(1)
5125 ADVANCE_PC(1)
5126 fstpl (rFP,%ecx,4) # %st to vA
5127 GOTO_NEXT
5128
5129
5130/* ------------------------------ */
5131 .balign 64
5132.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
5133/* File: x86/OP_SUB_DOUBLE_2ADDR.S */
5134/* File: x86/binflop2addr.S */
5135 /*
5136 * Generic 32-bit binary float operation.
5137 *
5138 * For: add-fp, sub-fp, mul-fp, div-fp
5139 */
5140
5141 /* binop/2addr vA, vB */
5142 movzx rINST_HI,%ecx # ecx<- A+
5143 andb $0xf,%cl # ecx<- A
5144 fldl (rFP,%ecx,4) # vAA to fp stack
5145 sarl $12,rINST_FULL # rINST_FULL<- B
5146 fsubl (rFP,rINST_FULL,4) # ex: faddp
5147 FETCH_INST_WORD(1)
5148 ADVANCE_PC(1)
5149 fstpl (rFP,%ecx,4) # %st to vA
5150 GOTO_NEXT
5151
5152
5153/* ------------------------------ */
5154 .balign 64
5155.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
5156/* File: x86/OP_MUL_DOUBLE_2ADDR.S */
5157/* File: x86/binflop2addr.S */
5158 /*
5159 * Generic 32-bit binary float operation.
5160 *
5161 * For: add-fp, sub-fp, mul-fp, div-fp
5162 */
5163
5164 /* binop/2addr vA, vB */
5165 movzx rINST_HI,%ecx # ecx<- A+
5166 andb $0xf,%cl # ecx<- A
5167 fldl (rFP,%ecx,4) # vAA to fp stack
5168 sarl $12,rINST_FULL # rINST_FULL<- B
5169 fmull (rFP,rINST_FULL,4) # ex: faddp
5170 FETCH_INST_WORD(1)
5171 ADVANCE_PC(1)
5172 fstpl (rFP,%ecx,4) # %st to vA
5173 GOTO_NEXT
5174
5175
5176/* ------------------------------ */
5177 .balign 64
5178.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
5179/* File: x86/OP_DIV_DOUBLE_2ADDR.S */
5180/* File: x86/binflop2addr.S */
5181 /*
5182 * Generic 32-bit binary float operation.
5183 *
5184 * For: add-fp, sub-fp, mul-fp, div-fp
5185 */
5186
5187 /* binop/2addr vA, vB */
5188 movzx rINST_HI,%ecx # ecx<- A+
5189 andb $0xf,%cl # ecx<- A
5190 fldl (rFP,%ecx,4) # vAA to fp stack
5191 sarl $12,rINST_FULL # rINST_FULL<- B
5192 fdivl (rFP,rINST_FULL,4) # ex: faddp
5193 FETCH_INST_WORD(1)
5194 ADVANCE_PC(1)
5195 fstpl (rFP,%ecx,4) # %st to vA
5196 GOTO_NEXT
5197
5198
5199/* ------------------------------ */
5200 .balign 64
5201.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
5202/* File: x86/OP_REM_DOUBLE_2ADDR.S */
5203 /* rem_float/2addr vA, vB */
5204 movzx rINST_HI,%ecx # ecx<- A+
5205 sarl $12,rINST_FULL # rINST_FULL<- B
5206 fldl (rFP,rINST_FULL,4) # vBB to fp stack
5207 andb $0xf,%cl # ecx<- A
5208 fldl (rFP,%ecx,4) # vAA to fp stack
5209 FETCH_INST_WORD(1)
52101:
5211 fprem
5212 fstsw %ax
5213 sahf
5214 jp 1b
5215 fstp %st(1)
5216 ADVANCE_PC(1)
5217 fstpl (rFP,%ecx,4) # %st to vA
5218 GOTO_NEXT
5219
5220/* ------------------------------ */
5221 .balign 64
5222.L_OP_ADD_INT_LIT16: /* 0xd0 */
5223/* File: x86/OP_ADD_INT_LIT16.S */
5224/* File: x86/binopLit16.S */
5225 /*
5226 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
5227 * that specifies an instruction that performs "result = eax op ecx".
5228 * This could be an x86 instruction or a function call. (If the result
5229 * comes back in a register other than eax, you can override "result".)
5230 *
5231 * For: add-int/lit16, rsub-int,
5232 * and-int/lit16, or-int/lit16, xor-int/lit16
5233 */
5234 /* binop/lit16 vA, vB, #+CCCC */
5235 movzbl rINST_HI,%eax # eax<- 000000BA
5236 sarl $4,%eax # eax<- B
5237 GET_VREG(%eax,%eax) # eax<- vB
5238 movswl 2(rPC),%ecx # ecx<- ssssCCCC
5239 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
5240 andb $0xf,rINST_LO # rINST_FULL<- A
5241 addl %ecx,%eax # for example: addl %ecx, %eax
5242 SET_VREG(%eax,rINST_FULL)
5243 FETCH_INST_WORD(2)
5244 ADVANCE_PC(2)
5245 GOTO_NEXT
5246
5247
5248/* ------------------------------ */
5249 .balign 64
5250.L_OP_RSUB_INT: /* 0xd1 */
5251/* File: x86/OP_RSUB_INT.S */
5252/* File: x86/binopLit16.S */
5253 /*
5254 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
5255 * that specifies an instruction that performs "result = eax op ecx".
5256 * This could be an x86 instruction or a function call. (If the result
5257 * comes back in a register other than eax, you can override "result".)
5258 *
5259 * For: add-int/lit16, rsub-int,
5260 * and-int/lit16, or-int/lit16, xor-int/lit16
5261 */
5262 /* binop/lit16 vA, vB, #+CCCC */
5263 movzbl rINST_HI,%eax # eax<- 000000BA
5264 sarl $4,%eax # eax<- B
5265 GET_VREG(%eax,%eax) # eax<- vB
5266 movswl 2(rPC),%ecx # ecx<- ssssCCCC
5267 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
5268 andb $0xf,rINST_LO # rINST_FULL<- A
5269 subl %eax,%ecx # for example: addl %ecx, %eax
5270 SET_VREG(%ecx,rINST_FULL)
5271 FETCH_INST_WORD(2)
5272 ADVANCE_PC(2)
5273 GOTO_NEXT
5274
5275
5276/* ------------------------------ */
5277 .balign 64
5278.L_OP_MUL_INT_LIT16: /* 0xd2 */
5279/* File: x86/OP_MUL_INT_LIT16.S */
5280 /* mul/lit16 vA, vB, #+CCCC */
5281 /* Need A in rINST_FULL, ssssCCCC in ecx, vB in eax */
5282 movzbl rINST_HI,%eax # eax<- 000000BA
5283 sarl $4,%eax # eax<- B
5284 GET_VREG(%eax,%eax) # eax<- vB
5285 movswl 2(rPC),%ecx # ecx<- ssssCCCC
5286 SPILL(rPC)
5287 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
5288 andb $0xf,rINST_LO # rINST_FULL<- A
5289 imull %ecx,%eax # trashes rPC
5290 UNSPILL(rPC)
5291 SET_VREG(%eax,rINST_FULL)
5292 FETCH_INST_WORD(2)
5293 ADVANCE_PC(2)
5294 GOTO_NEXT
5295
5296/* ------------------------------ */
5297 .balign 64
5298.L_OP_DIV_INT_LIT16: /* 0xd3 */
5299/* File: x86/OP_DIV_INT_LIT16.S */
5300/* File: x86/bindivLit16.S */
5301 /*
5302 * 32-bit binary div/rem operation. Handles special case of op0=minint and
5303 * op1=-1.
5304 */
5305 /* div/rem/lit16 vA, vB, #+CCCC */
5306 /* Need A in rINST_FULL, ssssCCCC in ecx, vB in eax */
5307 movzbl rINST_HI,%eax # eax<- 000000BA
5308 sarl $4,%eax # eax<- B
5309 GET_VREG(%eax,%eax) # eax<- vB
5310 movswl 2(rPC),%ecx # ecx<- ssssCCCC
5311 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
5312 andb $0xf,rINST_LO # rINST_FULL<- A
5313 SPILL(rPC)
5314 cmpl $0,%ecx
5315 je common_errDivideByZero
5316 cmpl $-1,%ecx
5317 jne .LOP_DIV_INT_LIT16_continue_div
5318 cmpl $0x80000000,%eax
5319 jne .LOP_DIV_INT_LIT16_continue_div
5320 movl $0x80000000,%eax
5321 jmp .LOP_DIV_INT_LIT16_finish_div
5322
5323
5324
5325/* ------------------------------ */
5326 .balign 64
5327.L_OP_REM_INT_LIT16: /* 0xd4 */
5328/* File: x86/OP_REM_INT_LIT16.S */
5329/* File: x86/bindivLit16.S */
5330 /*
5331 * 32-bit binary div/rem operation. Handles special case of op0=minint and
5332 * op1=-1.
5333 */
5334 /* div/rem/lit16 vA, vB, #+CCCC */
5335 /* Need A in rINST_FULL, ssssCCCC in ecx, vB in eax */
5336 movzbl rINST_HI,%eax # eax<- 000000BA
5337 sarl $4,%eax # eax<- B
5338 GET_VREG(%eax,%eax) # eax<- vB
5339 movswl 2(rPC),%ecx # ecx<- ssssCCCC
5340 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
5341 andb $0xf,rINST_LO # rINST_FULL<- A
5342 SPILL(rPC)
5343 cmpl $0,%ecx
5344 je common_errDivideByZero
5345 cmpl $-1,%ecx
5346 jne .LOP_REM_INT_LIT16_continue_div
5347 cmpl $0x80000000,%eax
5348 jne .LOP_REM_INT_LIT16_continue_div
5349 movl $0,%edx
5350 jmp .LOP_REM_INT_LIT16_finish_div
5351
5352
5353
5354/* ------------------------------ */
5355 .balign 64
5356.L_OP_AND_INT_LIT16: /* 0xd5 */
5357/* File: x86/OP_AND_INT_LIT16.S */
5358/* File: x86/binopLit16.S */
5359 /*
5360 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
5361 * that specifies an instruction that performs "result = eax op ecx".
5362 * This could be an x86 instruction or a function call. (If the result
5363 * comes back in a register other than eax, you can override "result".)
5364 *
5365 * For: add-int/lit16, rsub-int,
5366 * and-int/lit16, or-int/lit16, xor-int/lit16
5367 */
5368 /* binop/lit16 vA, vB, #+CCCC */
5369 movzbl rINST_HI,%eax # eax<- 000000BA
5370 sarl $4,%eax # eax<- B
5371 GET_VREG(%eax,%eax) # eax<- vB
5372 movswl 2(rPC),%ecx # ecx<- ssssCCCC
5373 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
5374 andb $0xf,rINST_LO # rINST_FULL<- A
5375 andl %ecx,%eax # for example: addl %ecx, %eax
5376 SET_VREG(%eax,rINST_FULL)
5377 FETCH_INST_WORD(2)
5378 ADVANCE_PC(2)
5379 GOTO_NEXT
5380
5381
5382/* ------------------------------ */
5383 .balign 64
5384.L_OP_OR_INT_LIT16: /* 0xd6 */
5385/* File: x86/OP_OR_INT_LIT16.S */
5386/* File: x86/binopLit16.S */
5387 /*
5388 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
5389 * that specifies an instruction that performs "result = eax op ecx".
5390 * This could be an x86 instruction or a function call. (If the result
5391 * comes back in a register other than eax, you can override "result".)
5392 *
5393 * For: add-int/lit16, rsub-int,
5394 * and-int/lit16, or-int/lit16, xor-int/lit16
5395 */
5396 /* binop/lit16 vA, vB, #+CCCC */
5397 movzbl rINST_HI,%eax # eax<- 000000BA
5398 sarl $4,%eax # eax<- B
5399 GET_VREG(%eax,%eax) # eax<- vB
5400 movswl 2(rPC),%ecx # ecx<- ssssCCCC
5401 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
5402 andb $0xf,rINST_LO # rINST_FULL<- A
5403 orl %ecx,%eax # for example: addl %ecx, %eax
5404 SET_VREG(%eax,rINST_FULL)
5405 FETCH_INST_WORD(2)
5406 ADVANCE_PC(2)
5407 GOTO_NEXT
5408
5409
5410
5411/* ------------------------------ */
5412 .balign 64
5413.L_OP_XOR_INT_LIT16: /* 0xd7 */
5414/* File: x86/OP_XOR_INT_LIT16.S */
5415/* File: x86/binopLit16.S */
5416 /*
5417 * Generic 32-bit "lit16" binary operation. Provide an "instr" line
5418 * that specifies an instruction that performs "result = eax op ecx".
5419 * This could be an x86 instruction or a function call. (If the result
5420 * comes back in a register other than eax, you can override "result".)
5421 *
5422 * For: add-int/lit16, rsub-int,
5423 * and-int/lit16, or-int/lit16, xor-int/lit16
5424 */
5425 /* binop/lit16 vA, vB, #+CCCC */
5426 movzbl rINST_HI,%eax # eax<- 000000BA
5427 sarl $4,%eax # eax<- B
5428 GET_VREG(%eax,%eax) # eax<- vB
5429 movswl 2(rPC),%ecx # ecx<- ssssCCCC
5430 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA
5431 andb $0xf,rINST_LO # rINST_FULL<- A
5432 xor %ecx,%eax # for example: addl %ecx, %eax
5433 SET_VREG(%eax,rINST_FULL)
5434 FETCH_INST_WORD(2)
5435 ADVANCE_PC(2)
5436 GOTO_NEXT
5437
5438
5439/* ------------------------------ */
5440 .balign 64
5441.L_OP_ADD_INT_LIT8: /* 0xd8 */
5442/* File: x86/OP_ADD_INT_LIT8.S */
5443/* File: x86/binopLit8.S */
5444 /*
5445 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
5446 * that specifies an instruction that performs "result = eax op ecx".
5447 * This could be an x86 instruction or a function call. (If the result
5448 * comes back in a register other than r0, you can override "result".)
5449 *
5450 * For: add-int/lit8, rsub-int/lit8
5451 * and-int/lit8, or-int/lit8, xor-int/lit8,
5452 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
5453 */
5454 /* binop/lit8 vAA, vBB, #+CC */
5455 movzbl 2(rPC),%eax # eax<- BB
5456 movsbl 3(rPC),%ecx # ecx<- ssssssCC
5457 movzx rINST_HI,rINST_FULL # rINST_FULL<- AA
5458 GET_VREG (%eax,%eax) # eax<- rBB
5459 addl %ecx,%eax # ex: addl %ecx,%eax
5460 SET_VREG (%eax,rINST_FULL)
5461 FETCH_INST_WORD(2)
5462 ADVANCE_PC(2)
5463 GOTO_NEXT
5464
5465
5466/* ------------------------------ */
5467 .balign 64
5468.L_OP_RSUB_INT_LIT8: /* 0xd9 */
5469/* File: x86/OP_RSUB_INT_LIT8.S */
5470/* File: x86/binopLit8.S */
5471 /*
5472 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
5473 * that specifies an instruction that performs "result = eax op ecx".
5474 * This could be an x86 instruction or a function call. (If the result
5475 * comes back in a register other than r0, you can override "result".)
5476 *
5477 * For: add-int/lit8, rsub-int/lit8
5478 * and-int/lit8, or-int/lit8, xor-int/lit8,
5479 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
5480 */
5481 /* binop/lit8 vAA, vBB, #+CC */
5482 movzbl 2(rPC),%eax # eax<- BB
5483 movsbl 3(rPC),%ecx # ecx<- ssssssCC
5484 movzx rINST_HI,rINST_FULL # rINST_FULL<- AA
5485 GET_VREG (%eax,%eax) # eax<- rBB
5486 subl %eax,%ecx # ex: addl %ecx,%eax
5487 SET_VREG (%ecx,rINST_FULL)
5488 FETCH_INST_WORD(2)
5489 ADVANCE_PC(2)
5490 GOTO_NEXT
5491
5492
5493/* ------------------------------ */
5494 .balign 64
5495.L_OP_MUL_INT_LIT8: /* 0xda */
5496/* File: x86/OP_MUL_INT_LIT8.S */
5497 /* mul/lit8 vAA, vBB, #+CC */
5498 movzbl 2(rPC),%eax # eax<- BB
5499 movsbl 3(rPC),%ecx # ecx<- ssssssCC
5500 SPILL(rPC)
5501 movzx rINST_HI,rINST_FULL # rINST_FULL<- AA
5502 GET_VREG (%eax,%eax) # eax<- rBB
5503 imull %ecx,%eax # trashes rPC
5504 UNSPILL(rPC)
5505 SET_VREG (%eax,rINST_FULL)
5506 FETCH_INST_WORD(2)
5507 ADVANCE_PC(2)
5508 GOTO_NEXT
5509
5510
5511/* ------------------------------ */
5512 .balign 64
5513.L_OP_DIV_INT_LIT8: /* 0xdb */
5514/* File: x86/OP_DIV_INT_LIT8.S */
5515/* File: x86/bindivLit8.S */
5516 /*
5517 * 32-bit div/rem "lit8" binary operation. Handles special case of
5518 * op0=minint & op1=-1
5519 */
5520 /* div/rem/lit8 vAA, vBB, #+CC */
5521 movzbl 2(rPC),%eax # eax<- BB
5522 movsbl 3(rPC),%ecx # ecx<- ssssssCC
5523 GET_VREG (%eax,%eax) # eax<- rBB
5524 movzx rINST_HI,rINST_FULL # rINST_FULL<- AA
5525 SPILL(rPC)
5526 cmpl $0,%ecx
5527 je common_errDivideByZero
5528 cmpl $0x80000000,%eax
5529 jne .LOP_DIV_INT_LIT8_continue_div
5530 cmpl $-1,%ecx
5531 jne .LOP_DIV_INT_LIT8_continue_div
5532 movl $0x80000000,%eax
5533 jmp .LOP_DIV_INT_LIT8_finish_div
5534
5535
5536
5537/* ------------------------------ */
5538 .balign 64
5539.L_OP_REM_INT_LIT8: /* 0xdc */
5540/* File: x86/OP_REM_INT_LIT8.S */
5541/* File: x86/bindivLit8.S */
5542 /*
5543 * 32-bit div/rem "lit8" binary operation. Handles special case of
5544 * op0=minint & op1=-1
5545 */
5546 /* div/rem/lit8 vAA, vBB, #+CC */
5547 movzbl 2(rPC),%eax # eax<- BB
5548 movsbl 3(rPC),%ecx # ecx<- ssssssCC
5549 GET_VREG (%eax,%eax) # eax<- rBB
5550 movzx rINST_HI,rINST_FULL # rINST_FULL<- AA
5551 SPILL(rPC)
5552 cmpl $0,%ecx
5553 je common_errDivideByZero
5554 cmpl $0x80000000,%eax
5555 jne .LOP_REM_INT_LIT8_continue_div
5556 cmpl $-1,%ecx
5557 jne .LOP_REM_INT_LIT8_continue_div
5558 movl $0,%edx
5559 jmp .LOP_REM_INT_LIT8_finish_div
5560
5561
5562
5563/* ------------------------------ */
5564 .balign 64
5565.L_OP_AND_INT_LIT8: /* 0xdd */
5566/* File: x86/OP_AND_INT_LIT8.S */
5567/* File: x86/binopLit8.S */
5568 /*
5569 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
5570 * that specifies an instruction that performs "result = eax op ecx".
5571 * This could be an x86 instruction or a function call. (If the result
5572 * comes back in a register other than r0, you can override "result".)
5573 *
5574 * For: add-int/lit8, rsub-int/lit8
5575 * and-int/lit8, or-int/lit8, xor-int/lit8,
5576 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
5577 */
5578 /* binop/lit8 vAA, vBB, #+CC */
5579 movzbl 2(rPC),%eax # eax<- BB
5580 movsbl 3(rPC),%ecx # ecx<- ssssssCC
5581 movzx rINST_HI,rINST_FULL # rINST_FULL<- AA
5582 GET_VREG (%eax,%eax) # eax<- rBB
5583 andl %ecx,%eax # ex: addl %ecx,%eax
5584 SET_VREG (%eax,rINST_FULL)
5585 FETCH_INST_WORD(2)
5586 ADVANCE_PC(2)
5587 GOTO_NEXT
5588
5589
5590/* ------------------------------ */
5591 .balign 64
5592.L_OP_OR_INT_LIT8: /* 0xde */
5593/* File: x86/OP_OR_INT_LIT8.S */
5594/* File: x86/binopLit8.S */
5595 /*
5596 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
5597 * that specifies an instruction that performs "result = eax op ecx".
5598 * This could be an x86 instruction or a function call. (If the result
5599 * comes back in a register other than r0, you can override "result".)
5600 *
5601 * For: add-int/lit8, rsub-int/lit8
5602 * and-int/lit8, or-int/lit8, xor-int/lit8,
5603 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
5604 */
5605 /* binop/lit8 vAA, vBB, #+CC */
5606 movzbl 2(rPC),%eax # eax<- BB
5607 movsbl 3(rPC),%ecx # ecx<- ssssssCC
5608 movzx rINST_HI,rINST_FULL # rINST_FULL<- AA
5609 GET_VREG (%eax,%eax) # eax<- rBB
5610 orl %ecx,%eax # ex: addl %ecx,%eax
5611 SET_VREG (%eax,rINST_FULL)
5612 FETCH_INST_WORD(2)
5613 ADVANCE_PC(2)
5614 GOTO_NEXT
5615
5616
5617
5618/* ------------------------------ */
5619 .balign 64
5620.L_OP_XOR_INT_LIT8: /* 0xdf */
5621/* File: x86/OP_XOR_INT_LIT8.S */
5622/* File: x86/binopLit8.S */
5623 /*
5624 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
5625 * that specifies an instruction that performs "result = eax op ecx".
5626 * This could be an x86 instruction or a function call. (If the result
5627 * comes back in a register other than r0, you can override "result".)
5628 *
5629 * For: add-int/lit8, rsub-int/lit8
5630 * and-int/lit8, or-int/lit8, xor-int/lit8,
5631 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
5632 */
5633 /* binop/lit8 vAA, vBB, #+CC */
5634 movzbl 2(rPC),%eax # eax<- BB
5635 movsbl 3(rPC),%ecx # ecx<- ssssssCC
5636 movzx rINST_HI,rINST_FULL # rINST_FULL<- AA
5637 GET_VREG (%eax,%eax) # eax<- rBB
5638 xor %ecx,%eax # ex: addl %ecx,%eax
5639 SET_VREG (%eax,rINST_FULL)
5640 FETCH_INST_WORD(2)
5641 ADVANCE_PC(2)
5642 GOTO_NEXT
5643
5644
5645/* ------------------------------ */
5646 .balign 64
5647.L_OP_SHL_INT_LIT8: /* 0xe0 */
5648/* File: x86/OP_SHL_INT_LIT8.S */
5649/* File: x86/binopLit8.S */
5650 /*
5651 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
5652 * that specifies an instruction that performs "result = eax op ecx".
5653 * This could be an x86 instruction or a function call. (If the result
5654 * comes back in a register other than r0, you can override "result".)
5655 *
5656 * For: add-int/lit8, rsub-int/lit8
5657 * and-int/lit8, or-int/lit8, xor-int/lit8,
5658 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
5659 */
5660 /* binop/lit8 vAA, vBB, #+CC */
5661 movzbl 2(rPC),%eax # eax<- BB
5662 movsbl 3(rPC),%ecx # ecx<- ssssssCC
5663 movzx rINST_HI,rINST_FULL # rINST_FULL<- AA
5664 GET_VREG (%eax,%eax) # eax<- rBB
5665 sall %cl,%eax # ex: addl %ecx,%eax
5666 SET_VREG (%eax,rINST_FULL)
5667 FETCH_INST_WORD(2)
5668 ADVANCE_PC(2)
5669 GOTO_NEXT
5670
5671
5672/* ------------------------------ */
5673 .balign 64
5674.L_OP_SHR_INT_LIT8: /* 0xe1 */
5675/* File: x86/OP_SHR_INT_LIT8.S */
5676/* File: x86/binopLit8.S */
5677 /*
5678 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
5679 * that specifies an instruction that performs "result = eax op ecx".
5680 * This could be an x86 instruction or a function call. (If the result
5681 * comes back in a register other than r0, you can override "result".)
5682 *
5683 * For: add-int/lit8, rsub-int/lit8
5684 * and-int/lit8, or-int/lit8, xor-int/lit8,
5685 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
5686 */
5687 /* binop/lit8 vAA, vBB, #+CC */
5688 movzbl 2(rPC),%eax # eax<- BB
5689 movsbl 3(rPC),%ecx # ecx<- ssssssCC
5690 movzx rINST_HI,rINST_FULL # rINST_FULL<- AA
5691 GET_VREG (%eax,%eax) # eax<- rBB
5692 sarl %cl,%eax # ex: addl %ecx,%eax
5693 SET_VREG (%eax,rINST_FULL)
5694 FETCH_INST_WORD(2)
5695 ADVANCE_PC(2)
5696 GOTO_NEXT
5697
5698
5699/* ------------------------------ */
5700 .balign 64
5701.L_OP_USHR_INT_LIT8: /* 0xe2 */
5702/* File: x86/OP_USHR_INT_LIT8.S */
5703/* File: x86/binopLit8.S */
5704 /*
5705 * Generic 32-bit "lit8" binary operation. Provide an "instr" line
5706 * that specifies an instruction that performs "result = eax op ecx".
5707 * This could be an x86 instruction or a function call. (If the result
5708 * comes back in a register other than r0, you can override "result".)
5709 *
5710 * For: add-int/lit8, rsub-int/lit8
5711 * and-int/lit8, or-int/lit8, xor-int/lit8,
5712 * shl-int/lit8, shr-int/lit8, ushr-int/lit8
5713 */
5714 /* binop/lit8 vAA, vBB, #+CC */
5715 movzbl 2(rPC),%eax # eax<- BB
5716 movsbl 3(rPC),%ecx # ecx<- ssssssCC
5717 movzx rINST_HI,rINST_FULL # rINST_FULL<- AA
5718 GET_VREG (%eax,%eax) # eax<- rBB
5719 shrl %cl,%eax # ex: addl %ecx,%eax
5720 SET_VREG (%eax,rINST_FULL)
5721 FETCH_INST_WORD(2)
5722 ADVANCE_PC(2)
5723 GOTO_NEXT
5724
5725
5726/* ------------------------------ */
5727 .balign 64
5728.L_OP_UNUSED_E3: /* 0xe3 */
5729/* File: x86/OP_UNUSED_E3.S */
5730/* File: x86/unused.S */
5731 jmp common_abort
5732
5733
5734/* ------------------------------ */
5735 .balign 64
5736.L_OP_UNUSED_E4: /* 0xe4 */
5737/* File: x86/OP_UNUSED_E4.S */
5738/* File: x86/unused.S */
5739 jmp common_abort
5740
5741
5742/* ------------------------------ */
5743 .balign 64
5744.L_OP_UNUSED_E5: /* 0xe5 */
5745/* File: x86/OP_UNUSED_E5.S */
5746/* File: x86/unused.S */
5747 jmp common_abort
5748
5749
5750/* ------------------------------ */
5751 .balign 64
5752.L_OP_UNUSED_E6: /* 0xe6 */
5753/* File: x86/OP_UNUSED_E6.S */
5754/* File: x86/unused.S */
5755 jmp common_abort
5756
5757
5758/* ------------------------------ */
5759 .balign 64
5760.L_OP_UNUSED_E7: /* 0xe7 */
5761/* File: x86/OP_UNUSED_E7.S */
5762/* File: x86/unused.S */
5763 jmp common_abort
5764
5765
5766/* ------------------------------ */
5767 .balign 64
5768.L_OP_UNUSED_E8: /* 0xe8 */
5769/* File: x86/OP_UNUSED_E8.S */
5770/* File: x86/unused.S */
5771 jmp common_abort
5772
5773
5774/* ------------------------------ */
5775 .balign 64
5776.L_OP_UNUSED_E9: /* 0xe9 */
5777/* File: x86/OP_UNUSED_E9.S */
5778/* File: x86/unused.S */
5779 jmp common_abort
5780
5781
5782/* ------------------------------ */
5783 .balign 64
5784.L_OP_UNUSED_EA: /* 0xea */
5785/* File: x86/OP_UNUSED_EA.S */
5786/* File: x86/unused.S */
5787 jmp common_abort
5788
5789
5790/* ------------------------------ */
5791 .balign 64
5792.L_OP_UNUSED_EB: /* 0xeb */
5793/* File: x86/OP_UNUSED_EB.S */
5794/* File: x86/unused.S */
5795 jmp common_abort
5796
5797
5798/* ------------------------------ */
5799 .balign 64
5800.L_OP_UNUSED_EC: /* 0xec */
5801/* File: x86/OP_UNUSED_EC.S */
5802/* File: x86/unused.S */
5803 jmp common_abort
5804
5805
5806/* ------------------------------ */
5807 .balign 64
Andy McFadden3a1aedb2009-05-07 13:30:23 -07005808.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
5809/* File: x86/OP_THROW_VERIFICATION_ERROR.S */
5810 /* TODO */
5811 call dvmAbort
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005812
5813
5814/* ------------------------------ */
5815 .balign 64
5816.L_OP_EXECUTE_INLINE: /* 0xee */
5817/* File: x86/OP_EXECUTE_INLINE.S */
5818 /*
5819 * Execute a "native inline" instruction.
5820 *
5821 * We will be calling through a function table:
5822 *
5823 * (*gDvmInlineOpsTable[opIndex].func)(arg0, arg1, arg2, arg3, pResult)
5824 *
5825 */
5826 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
5827 GET_GLUE(%ecx)
5828 EXPORT_PC()
5829 movzwl 2(rPC),%eax # eax<- BBBB
5830 leal offGlue_retval(%ecx),%ecx # ecx<- & glue->retval
5831 movl %ecx,OUT_ARG4(%esp)
5832 sarl $12,rINST_FULL # rINST_FULL<- arg count (0-4)
5833 SPILL(rPC)
5834 call .LOP_EXECUTE_INLINE_continue # make call; will return after
5835 UNSPILL(rPC)
5836 testl %eax,%eax # successful?
5837 FETCH_INST_WORD(3)
5838 je common_exceptionThrown # no, handle exception
5839 ADVANCE_PC(3)
5840 GOTO_NEXT
5841
5842/* ------------------------------ */
5843 .balign 64
5844.L_OP_UNUSED_EF: /* 0xef */
5845/* File: x86/OP_UNUSED_EF.S */
5846/* File: x86/unused.S */
5847 jmp common_abort
5848
5849
5850/* ------------------------------ */
5851 .balign 64
5852.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
5853/* File: x86/OP_INVOKE_DIRECT_EMPTY.S */
5854 /*
5855 * invoke-direct-empty is a no-op in a "standard" interpreter.
5856 */
5857 FETCH_INST_WORD(3)
5858 ADVANCE_PC(3)
5859 GOTO_NEXT
5860
5861/* ------------------------------ */
5862 .balign 64
5863.L_OP_UNUSED_F1: /* 0xf1 */
5864/* File: x86/OP_UNUSED_F1.S */
5865/* File: x86/unused.S */
5866 jmp common_abort
5867
5868
5869/* ------------------------------ */
5870 .balign 64
5871.L_OP_IGET_QUICK: /* 0xf2 */
5872/* File: x86/OP_IGET_QUICK.S */
5873 /* For: iget-quick, iget-object-quick */
5874 /* op vA, vB, offset@CCCC */
5875 movzbl rINST_HI,%ecx # ecx<- BA
5876 sarl $4,%ecx # ecx<- B
5877 GET_VREG(%ecx,%ecx) # vB (object we're operating on)
5878 movzwl 2(rPC),%eax # eax<- field byte offset
5879 cmpl $0,%ecx # is object null?
5880 je common_errNullObject
5881 movl (%ecx,%eax,1),%eax
5882 movzbl rINST_HI,%ecx
5883 FETCH_INST_WORD(2)
5884 ADVANCE_PC(2)
5885 andb $0xf,%cl # rINST_FULL<- A
5886 SET_VREG (%eax,%ecx) # fp[A]<- result
5887 GOTO_NEXT
5888
5889/* ------------------------------ */
5890 .balign 64
5891.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
5892/* File: x86/OP_IGET_WIDE_QUICK.S */
5893 /* For: iget-wide-quick */
5894 /* op vA, vB, offset@CCCC */
5895 movzbl rINST_HI,%ecx # ecx<- BA
5896 sarl $4,%ecx # ecx<- B
5897 GET_VREG(%ecx,%ecx) # vB (object we're operating on)
5898 movzwl 2(rPC),%eax # eax<- field byte offset
5899 cmpl $0,%ecx # is object null?
5900 je common_errNullObject
5901 leal (%ecx,%eax,1),%eax # eax<- address of 64-bit source
5902 movl (%eax),%ecx # ecx<- lsw
5903 movl 4(%eax),%eax # eax<- msw
5904 movzbl rINST_HI,rINST_FULL
5905 andb $0xf,rINST_LO # rINST_FULL<- A
5906 SET_VREG_WORD(%ecx,rINST_FULL,0) # v[A+0]<- lsw
5907 SET_VREG_WORD(%eax,rINST_FULL,1) # v[A+1]<- msw
5908 FETCH_INST_WORD(2)
5909 ADVANCE_PC(2)
5910 GOTO_NEXT
5911
5912/* ------------------------------ */
5913 .balign 64
5914.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
5915/* File: x86/OP_IGET_OBJECT_QUICK.S */
5916/* File: x86/OP_IGET_QUICK.S */
5917 /* For: iget-quick, iget-object-quick */
5918 /* op vA, vB, offset@CCCC */
5919 movzbl rINST_HI,%ecx # ecx<- BA
5920 sarl $4,%ecx # ecx<- B
5921 GET_VREG(%ecx,%ecx) # vB (object we're operating on)
5922 movzwl 2(rPC),%eax # eax<- field byte offset
5923 cmpl $0,%ecx # is object null?
5924 je common_errNullObject
5925 movl (%ecx,%eax,1),%eax
5926 movzbl rINST_HI,%ecx
5927 FETCH_INST_WORD(2)
5928 ADVANCE_PC(2)
5929 andb $0xf,%cl # rINST_FULL<- A
5930 SET_VREG (%eax,%ecx) # fp[A]<- result
5931 GOTO_NEXT
5932
5933
5934/* ------------------------------ */
5935 .balign 64
5936.L_OP_IPUT_QUICK: /* 0xf5 */
5937/* File: x86/OP_IPUT_QUICK.S */
5938 /* For: iput-quick, iput-object-quick */
5939 /* op vA, vB, offset@CCCC */
5940 movzbl rINST_HI,%ecx # ecx<- BA
5941 sarl $4,%ecx # ecx<- B
5942 GET_VREG(%ecx,%ecx) # vB (object we're operating on)
5943 movzbl rINST_HI,rINST_FULL
5944 andb $0xf,rINST_LO # rINST_FULL<- A
5945 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A]
5946 movzwl 2(rPC),%eax # eax<- field byte offset
5947 testl %ecx,%ecx # is object null?
5948 je common_errNullObject
5949 movl rINST_FULL,(%ecx,%eax,1)
5950 FETCH_INST_WORD(2)
5951 ADVANCE_PC(2)
5952 GOTO_NEXT
5953
5954/* ------------------------------ */
5955 .balign 64
5956.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
5957/* File: x86/OP_IPUT_WIDE_QUICK.S */
5958 /* For: iput-wide-quick */
5959 /* op vA, vB, offset@CCCC */
5960 movzbl rINST_HI,%ecx # ecx<- BA
5961 sarl $4,%ecx # ecx<- B
5962 GET_VREG(%ecx,%ecx) # vB (object we're operating on)
5963 movzwl 2(rPC),%eax # eax<- field byte offset
5964 testl %ecx,%ecx # is object null?
5965 je common_errNullObject
5966 leal (%ecx,%eax,1),%ecx # ecx<- Address of 64-bit target
5967 movzbl rINST_HI,rINST_FULL
5968 andb $0xf,rINST_LO # rINST_FULL<- A
5969 GET_VREG_WORD(%eax,rINST_FULL,0) # eax<- lsw
5970 GET_VREG_WORD(rINST_FULL,rINST_FULL,1) # rINST_FULL<- msw
5971 movl %eax,(%ecx)
5972 movl rINST_FULL,4(%ecx)
5973 FETCH_INST_WORD(2)
5974 ADVANCE_PC(2)
5975 GOTO_NEXT
5976
5977/* ------------------------------ */
5978 .balign 64
5979.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
5980/* File: x86/OP_IPUT_OBJECT_QUICK.S */
5981/* File: x86/OP_IPUT_QUICK.S */
5982 /* For: iput-quick, iput-object-quick */
5983 /* op vA, vB, offset@CCCC */
5984 movzbl rINST_HI,%ecx # ecx<- BA
5985 sarl $4,%ecx # ecx<- B
5986 GET_VREG(%ecx,%ecx) # vB (object we're operating on)
5987 movzbl rINST_HI,rINST_FULL
5988 andb $0xf,rINST_LO # rINST_FULL<- A
5989 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A]
5990 movzwl 2(rPC),%eax # eax<- field byte offset
5991 testl %ecx,%ecx # is object null?
5992 je common_errNullObject
5993 movl rINST_FULL,(%ecx,%eax,1)
5994 FETCH_INST_WORD(2)
5995 ADVANCE_PC(2)
5996 GOTO_NEXT
5997
5998
5999/* ------------------------------ */
6000 .balign 64
6001.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
6002/* File: x86/OP_INVOKE_VIRTUAL_QUICK.S */
6003 /*
6004 * Handle an optimized virtual method call.
6005 *
6006 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
6007 */
6008 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
6009 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
6010 movzwl 4(rPC),%eax # eax<- FEDC or CCCC
6011 movzwl 2(rPC),%ecx # ecx<- BBBB
6012 .if (!0)
6013 andl $0xf,%eax # eax<- C (or stays CCCC)
6014 .endif
6015 GET_VREG(%eax,%eax) # eax<- vC ("this" ptr)
6016 testl %eax,%eax # null?
6017 je common_errNullObject # yep, throw exception
6018 movl offObject_clazz(%eax),%eax # eax<- thisPtr->clazz
6019 movl offClassObject_vtable(%eax),%eax # eax<- thisPtr->clazz->vtable
6020 EXPORT_PC() # might throw later - get ready
6021 movl (%eax,%ecx,4),%eax # eax<- vtable[BBBB]
Johnnie Birchc4080f62009-02-10 15:41:06 -08006022 jmp common_invokeMethodNoRange
6023
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08006024
6025
6026/* ------------------------------ */
6027 .balign 64
6028.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
6029/* File: x86/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
6030/* File: x86/OP_INVOKE_VIRTUAL_QUICK.S */
6031 /*
6032 * Handle an optimized virtual method call.
6033 *
6034 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
6035 */
6036 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
6037 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
6038 movzwl 4(rPC),%eax # eax<- FEDC or CCCC
6039 movzwl 2(rPC),%ecx # ecx<- BBBB
6040 .if (!1)
6041 andl $0xf,%eax # eax<- C (or stays CCCC)
6042 .endif
6043 GET_VREG(%eax,%eax) # eax<- vC ("this" ptr)
6044 testl %eax,%eax # null?
6045 je common_errNullObject # yep, throw exception
6046 movl offObject_clazz(%eax),%eax # eax<- thisPtr->clazz
6047 movl offClassObject_vtable(%eax),%eax # eax<- thisPtr->clazz->vtable
6048 EXPORT_PC() # might throw later - get ready
6049 movl (%eax,%ecx,4),%eax # eax<- vtable[BBBB]
Johnnie Birchc4080f62009-02-10 15:41:06 -08006050 jmp common_invokeMethodRange
6051
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08006052
6053
6054
6055/* ------------------------------ */
6056 .balign 64
6057.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
6058/* File: x86/OP_INVOKE_SUPER_QUICK.S */
6059 /*
6060 * Handle an optimized "super" method call.
6061 *
6062 * for: [opt] invoke-super-quick, invoke-super-quick/range
6063 */
6064 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
6065 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
6066 GET_GLUE(%ecx)
6067 movzwl 4(rPC),%eax # eax<- GFED or CCCC
6068 movl offGlue_method(%ecx),%ecx # ecx<- current method
6069 .if (!0)
6070 andl $0xf,%eax # eax<- D (or stays CCCC)
6071 .endif
6072 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
6073 GET_VREG(%eax,%eax) # eax<- "this"
6074 movl offClassObject_super(%ecx),%ecx # ecx<- method->clazz->super
6075 testl %eax,%eax # null "this"?
6076 je common_errNullObject # "this" is null, throw exception
6077 movzwl 2(rPC),%eax # eax<- BBBB
6078 movl offClassObject_vtable(%ecx),%ecx # ecx<- vtable
6079 EXPORT_PC()
6080 movl (%ecx,%eax,4),%eax # eax<- super->vtable[BBBB]
Johnnie Birchc4080f62009-02-10 15:41:06 -08006081 jmp common_invokeMethodNoRange
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08006082
6083
6084/* ------------------------------ */
6085 .balign 64
6086.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
6087/* File: x86/OP_INVOKE_SUPER_QUICK_RANGE.S */
6088/* File: x86/OP_INVOKE_SUPER_QUICK.S */
6089 /*
6090 * Handle an optimized "super" method call.
6091 *
6092 * for: [opt] invoke-super-quick, invoke-super-quick/range
6093 */
6094 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
6095 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
6096 GET_GLUE(%ecx)
6097 movzwl 4(rPC),%eax # eax<- GFED or CCCC
6098 movl offGlue_method(%ecx),%ecx # ecx<- current method
6099 .if (!1)
6100 andl $0xf,%eax # eax<- D (or stays CCCC)
6101 .endif
6102 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
6103 GET_VREG(%eax,%eax) # eax<- "this"
6104 movl offClassObject_super(%ecx),%ecx # ecx<- method->clazz->super
6105 testl %eax,%eax # null "this"?
6106 je common_errNullObject # "this" is null, throw exception
6107 movzwl 2(rPC),%eax # eax<- BBBB
6108 movl offClassObject_vtable(%ecx),%ecx # ecx<- vtable
6109 EXPORT_PC()
6110 movl (%ecx,%eax,4),%eax # eax<- super->vtable[BBBB]
Johnnie Birchc4080f62009-02-10 15:41:06 -08006111 jmp common_invokeMethodRange
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08006112
6113
6114
6115/* ------------------------------ */
6116 .balign 64
6117.L_OP_UNUSED_FC: /* 0xfc */
6118/* File: x86/OP_UNUSED_FC.S */
6119/* File: x86/unused.S */
6120 jmp common_abort
6121
6122
6123/* ------------------------------ */
6124 .balign 64
6125.L_OP_UNUSED_FD: /* 0xfd */
6126/* File: x86/OP_UNUSED_FD.S */
6127/* File: x86/unused.S */
6128 jmp common_abort
6129
6130
6131/* ------------------------------ */
6132 .balign 64
6133.L_OP_UNUSED_FE: /* 0xfe */
6134/* File: x86/OP_UNUSED_FE.S */
6135/* File: x86/unused.S */
6136 jmp common_abort
6137
6138
6139/* ------------------------------ */
6140 .balign 64
6141.L_OP_UNUSED_FF: /* 0xff */
6142/* File: x86/OP_UNUSED_FF.S */
6143/* File: x86/unused.S */
6144 jmp common_abort
6145
6146
6147
6148 .balign 64
6149 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart
6150 .global dvmAsmInstructionEnd
6151dvmAsmInstructionEnd:
6152
6153/*
6154 * ===========================================================================
6155 * Sister implementations
6156 * ===========================================================================
6157 */
6158 .global dvmAsmSisterStart
6159 .type dvmAsmSisterStart, %function
6160 .text
6161 .balign 4
6162dvmAsmSisterStart:
6163
6164/* continuation for OP_CONST_STRING */
6165
6166/* This is the less common path, so we'll redo some work
6167 here rather than force spills on the common path */
6168.LOP_CONST_STRING_resolve:
6169 GET_GLUE(%eax)
6170 movl %ecx,rINST_FULL # rINST_FULL<- AA
6171 EXPORT_PC()
6172 movl offGlue_method(%eax),%eax # eax<- glue->method
6173 movzwl 2(rPC),%ecx # ecx<- BBBB
6174 movl offMethod_clazz(%eax),%eax
6175 SPILL(rPC)
6176 movl %ecx,OUT_ARG1(%esp)
6177 movl %eax,OUT_ARG0(%esp)
6178 call dvmResolveString # go resolve
6179 UNSPILL(rPC)
6180 testl %eax,%eax # failed?
6181 je common_exceptionThrown
6182 SET_VREG(%eax,rINST_FULL)
6183 FETCH_INST_WORD(2)
6184 ADVANCE_PC(2)
6185 GOTO_NEXT
6186
6187
6188/* continuation for OP_CONST_STRING_JUMBO */
6189
6190/* This is the less common path, so we'll redo some work
6191 here rather than force spills on the common path */
6192.LOP_CONST_STRING_JUMBO_resolve:
6193 GET_GLUE(%eax)
6194 movl %ecx,rINST_FULL # rINST_FULL<- AA
6195 EXPORT_PC()
6196 movl offGlue_method(%eax),%eax # eax<- glue->method
6197 movl 2(rPC),%ecx # ecx<- BBBBBBBB
6198 movl offMethod_clazz(%eax),%eax
6199 SPILL(rPC)
6200 movl %ecx,OUT_ARG1(%esp)
6201 movl %eax,OUT_ARG0(%esp)
6202 call dvmResolveString # go resolve
6203 UNSPILL(rPC)
6204 testl %eax,%eax # failed?
6205 je common_exceptionThrown
6206 SET_VREG(%eax,rINST_FULL)
6207 FETCH_INST_WORD(3)
6208 ADVANCE_PC(3)
6209 GOTO_NEXT
6210
6211
6212/* continuation for OP_CONST_CLASS */
6213
6214/* This is the less common path, so we'll redo some work
6215 here rather than force spills on the common path */
6216.LOP_CONST_CLASS_resolve:
6217 GET_GLUE(%eax)
6218 movl %ecx,rINST_FULL # rINST_FULL<- AA
6219 EXPORT_PC()
6220 movl offGlue_method(%eax),%eax # eax<- glue->method
6221 movl $1,OUT_ARG2(%esp) # true
6222 movzwl 2(rPC),%ecx # ecx<- BBBB
6223 movl offMethod_clazz(%eax),%eax
6224 SPILL(rPC)
6225 movl %ecx,OUT_ARG1(%esp)
6226 movl %eax,OUT_ARG0(%esp)
6227 call dvmResolveClass # go resolve
6228 UNSPILL(rPC)
6229 testl %eax,%eax # failed?
6230 je common_exceptionThrown
6231 SET_VREG(%eax,rINST_FULL)
6232 FETCH_INST_WORD(2)
6233 ADVANCE_PC(2)
6234 GOTO_NEXT
6235
6236
6237/* continuation for OP_MONITOR_ENTER */
6238
6239.LOP_MONITOR_ENTER_continue:
6240 SPILL(rPC) # have to - caller save
6241 movl %ecx,OUT_ARG0(%esp)
6242 movl %eax,OUT_ARG1(%esp)
6243 call dvmLockObject # dvmLockObject(self,object)
6244 UNSPILL(rPC)
6245#ifdef WITH_DEADLOCK_PREDICTION
6246 GET_GLUE(%ecx)
6247 movl offGlueSelf(%ecx),%ecx # ecx<- glue->self
6248 movl offThread_exception(%ecx),%eax
6249 testl %eax,%eax
6250 jne common_exceptionThrown
6251#endif
6252 ADVANCE_PC(1)
6253 GOTO_NEXT
6254
6255/* continuation for OP_MONITOR_EXIT */
6256
6257.LOP_MONITOR_EXIT_continue:
6258 call dvmUnlockObject # unlock(self,obj)
6259 UNSPILL(rPC)
6260 FETCH_INST_WORD(1)
6261 testl %eax,%eax # success?
6262 je common_exceptionThrown # no, exception pending
6263 ADVANCE_PC(1)
6264 GOTO_NEXT
6265
6266/* continuation for OP_CHECK_CAST */
6267
6268 /*
6269 * Trivial test failed, need to perform full check. This is common.
6270 * ecx holds obj->clazz
6271 * eax holds class resolved from BBBB
6272 * rINST_FULL holds object
6273 */
6274.LOP_CHECK_CAST_fullcheck:
6275 movl %eax,OUT_ARG1(%esp)
6276 movl %ecx,OUT_ARG0(%esp)
6277 SPILL(rPC)
6278 call dvmInstanceofNonTrivial # eax<- boolean result
6279 UNSPILL(rPC)
6280 testl %eax,%eax # failed?
6281 jne .LOP_CHECK_CAST_okay # no, success
6282
6283 # A cast has failed. We need to throw a ClassCastException with the
6284 # class of the object that failed to be cast.
6285 EXPORT_PC()
6286 movl offObject_clazz(rINST_FULL),%ecx # ecx<- obj->clazz
6287 movl $.LstrClassCastException,%eax
6288 movl offClassObject_descriptor(%ecx),%ecx
6289 movl %eax,OUT_ARG0(%esp) # arg0<- message
6290 movl %ecx,OUT_ARG1(%esp) # arg1<- obj->clazz->descriptor
6291 SPILL(rPC)
6292 call dvmThrowExceptionWithClassMessage
6293 UNSPILL(rPC)
6294 jmp common_exceptionThrown
6295
6296 /*
6297 * Resolution required. This is the least-likely path, and we're
6298 * going to have to recreate some data.
6299 *
6300 * rINST_FULL holds object
6301 */
6302.LOP_CHECK_CAST_resolve:
6303 GET_GLUE(%ecx)
6304 EXPORT_PC()
6305 movzwl 2(rPC),%eax # eax<- BBBB
6306 movl offGlue_method(%ecx),%ecx # ecx<- glue->method
6307 movl %eax,OUT_ARG1(%esp) # arg1<- BBBB
6308 movl offMethod_clazz(%ecx),%ecx # ecx<- metho->clazz
6309 movl $0,OUT_ARG2(%esp) # arg2<- false
6310 movl %ecx,OUT_ARG0(%esp) # arg0<- method->clazz
6311 SPILL(rPC)
6312 call dvmResolveClass # eax<- resolved ClassObject ptr
6313 UNSPILL(rPC)
6314 testl %eax,%eax # got null?
6315 je common_exceptionThrown # yes, handle exception
6316 movl offObject_clazz(rINST_FULL),%ecx # ecx<- obj->clazz
6317 jmp .LOP_CHECK_CAST_resolved # pick up where we left off
6318
6319/* continuation for OP_INSTANCE_OF */
6320
6321 /*
6322 * Trivial test failed, need to perform full check. This is common.
6323 * eax holds obj->clazz
6324 * ecx holds class resolved from BBBB
6325 * rINST_HI has BA
6326 * rPC already spilled
6327 */
6328.LOP_INSTANCE_OF_fullcheck:
6329 movl %eax,OUT_ARG0(%esp)
6330 movl %ecx,OUT_ARG1(%esp)
6331 call dvmInstanceofNonTrivial # eax<- boolean result
6332 # fall through to OP_INSTANCE_OF_store
6333
6334 /*
6335 * eax holds boolean result
6336 * rINST_HI holds BA
6337 */
6338.LOP_INSTANCE_OF_store:
6339 UNSPILL(rPC)
6340 movzbl rINST_HI,%ecx # ecx<- BA
6341 FETCH_INST_WORD(2)
6342 andb $0xf,%cl # ecl<- A
6343 ADVANCE_PC(2)
6344 SET_VREG(%eax,%ecx) # vA<- eax
6345 GOTO_NEXT
6346
6347 /*
6348 * Trivial test succeeded, save and bail.
6349 * r9 holds A
6350 */
6351.LOP_INSTANCE_OF_trivial:
6352 UNSPILL(rPC)
6353 movzbl rINST_HI,%ecx # ecx<- BA
6354 FETCH_INST_WORD(2)
6355 andb $0xf,%cl # ecl<- A
6356 ADVANCE_PC(2)
6357 movl $1,%eax
6358 SET_VREG(%eax,%ecx) # vA<- true
6359 GOTO_NEXT
6360
6361 /*
6362 * Resolution required. This is the least-likely path.
6363 *
6364 * rPC holds BBBB
6365 * rINST_HI holds BA
6366 */
6367.LOP_INSTANCE_OF_resolve:
6368 movl rPC,OUT_ARG1(%esp) # arg1<- BBBB
6369 GET_GLUE(%ecx)
6370 UNSPILL(rPC)
6371 movl offGlue_method(%ecx),%ecx
6372 movl $1,OUT_ARG2(%esp) # arg2<- true
6373 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
6374 EXPORT_PC()
6375 movl %ecx,OUT_ARG0(%esp) # arg0<- method->clazz
6376 call dvmResolveClass # eax<- resolved ClassObject ptr
6377 UNSPILL(rPC)
6378 testl %eax,%eax # success?
6379 je common_exceptionThrown # no, handle exception
6380/* Now, we need to sync up with fast path. We need eax to
6381 * hold the obj->clazz, and ecx to hold the resolved class
6382 */
6383 movl %eax,%ecx # ecx<- resolved class
6384 movzbl rINST_HI,%eax # eax<- BA
6385 sarl $4,%eax # eax<- B
6386 GET_VREG(%eax,%eax) # eax<- vB (obj)
6387 movl offObject_clazz(%eax),%eax # eax<- obj->clazz
6388 jmp .LOP_INSTANCE_OF_resolved
6389
6390
6391/* continuation for OP_NEW_INSTANCE */
6392
6393.LOP_NEW_INSTANCE_initialized: # on entry, ecx<- class
6394 testl $(ACC_INTERFACE|ACC_ABSTRACT),offClassObject_accessFlags(%ecx)
6395 movl $ALLOC_DONT_TRACK,OUT_ARG1(%esp)
6396 jne .LOP_NEW_INSTANCE_abstract
6397.LOP_NEW_INSTANCE_finish: # ecx=class
6398 movl %ecx,OUT_ARG0(%esp)
6399 call dvmAllocObject # eax<- new object
6400 UNSPILL(rPC)
6401 movl rINST_FULL,%ecx
6402 FETCH_INST_WORD(2)
6403 testl %eax,%eax # success?
6404 je common_exceptionThrown # no, bail out
6405 SET_VREG(%eax,%ecx)
6406 ADVANCE_PC(2)
6407 GOTO_NEXT
6408
6409 /*
6410 * Class initialization required.
6411 *
6412 * ecx holds class object
6413 */
6414.LOP_NEW_INSTANCE_needinit:
6415 SPILL_TMP(%ecx) # save object
6416 movl %ecx,OUT_ARG0(%esp)
6417 call dvmInitClass # initialize class
6418 UNSPILL_TMP(%ecx) # restore object
6419 testl %eax,%eax # success?
6420 jne .LOP_NEW_INSTANCE_initialized # success, continue
6421 UNSPILL(rPC) # failed, restore PC
6422 jmp common_exceptionThrown # go deal with init exception
6423
6424 /*
6425 * Resolution required. This is the least-likely path.
6426 *
6427 */
6428.LOP_NEW_INSTANCE_resolve:
6429 GET_GLUE(%ecx)
6430 movzwl 2(rPC),%eax
6431 movl offGlue_method(%ecx),%ecx # ecx<- glue->method
6432 movl %eax,OUT_ARG1(%esp)
6433 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
6434 movl $0,OUT_ARG2(%esp)
6435 movl %ecx,OUT_ARG0(%esp)
6436 call dvmResolveClass # call(clazz,off,flags)
6437 movl %eax,%ecx # ecx<- resolved ClassObject ptr
6438 testl %ecx,%ecx # success?
6439 jne .LOP_NEW_INSTANCE_resolved # good to go
6440 UNSPILL(rPC)
6441 jmp common_exceptionThrown # no, handle exception
6442
6443 /*
6444 * We can't instantiate an abstract class or interface, so throw an
6445 * InstantiationError with the class descriptor as the message.
6446 *
6447 * ecx holds class object
6448 */
6449.LOP_NEW_INSTANCE_abstract:
6450 movl offClassObject_descriptor(%ecx),%eax
6451 movl $.LstrInstantiationError,OUT_ARG0(%esp)
6452 movl %eax,OUT_ARG1(%esp)
6453 call dvmThrowExceptionWithClassMessage
6454 UNSPILL(rPC)
6455 jmp common_exceptionThrown
6456
6457
6458
6459
6460/* continuation for OP_NEW_ARRAY */
6461
6462 /*
6463 * Resolve class. (This is an uncommon case.)
6464 * ecx holds class (null here)
6465 * eax holds array length (vB)
6466 */
6467.LOP_NEW_ARRAY_resolve:
6468 GET_GLUE(%ecx)
6469 SPILL_TMP(%eax) # save array length
6470 movl offGlue_method(%ecx),%ecx # ecx<- glue->method
6471 movzwl 2(rPC),%eax # eax<- CCCC
6472 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
6473 movl %eax,OUT_ARG1(%esp)
6474 movl $0,OUT_ARG2(%esp)
6475 movl %ecx,OUT_ARG0(%esp)
6476 SPILL(rPC)
6477 call dvmResolveClass # eax<- call(clazz,ref,flag)
6478 UNSPILL(rPC)
6479 movl %eax,%ecx
6480 UNSPILL_TMP(%eax)
6481 testl %ecx,%ecx # successful resolution?
6482 je common_exceptionThrown # no, bail.
6483# fall through to OP_NEW_ARRAY_finish
6484
6485 /*
6486 * Finish allocation
6487 *
6488 * ecx holds class
6489 * eax holds array length (vB)
6490 */
6491.LOP_NEW_ARRAY_finish:
6492 movl %ecx,OUT_ARG0(%esp)
6493 movl %eax,OUT_ARG1(%esp)
6494 movl $ALLOC_DONT_TRACK,OUT_ARG2(%esp)
6495 SPILL(rPC)
6496 call dvmAllocArrayByClass # eax<- call(clazz,length,flags)
6497 UNSPILL(rPC)
6498 testl %eax,%eax # failed?
6499 je common_exceptionThrown # yup - go handle
6500 movl rINST_FULL,%ecx
6501 FETCH_INST_WORD(2)
6502 SET_VREG(%eax,%ecx)
6503 ADVANCE_PC(2)
6504 GOTO_NEXT
6505
6506
6507/* continuation for OP_FILLED_NEW_ARRAY */
6508
6509.LOP_FILLED_NEW_ARRAY_more:
6510 movl offMethod_clazz(%eax),%eax # eax<- method->clazz
6511 movl %eax,OUT_ARG0(%esp) # arg0<- clazz
6512 call dvmResolveClass # eax<- call(clazz,ref,flag)
6513 UNSPILL(rPC)
6514 testl %eax,%eax # null?
6515 je common_exceptionThrown # yes, handle it
6516
6517 # note: fall through to .LOP_FILLED_NEW_ARRAY_continue
6518
6519 /*
6520 * On entry:
6521 * eax holds array class [r0]
6522 * rINST_FULL holds AA or BB [r10]
6523 * ecx is scratch
6524 * rPC is valid, but has been spilled
6525 */
6526.LOP_FILLED_NEW_ARRAY_continue:
6527 movl offClassObject_descriptor(%eax),%ecx # ecx<- arrayClass->descriptor
6528 movl $ALLOC_DONT_TRACK,OUT_ARG2(%esp) # arg2<- flags
6529 movzbl 1(%ecx),%ecx # ecx<- descriptor[1]
6530 movl %eax,OUT_ARG0(%esp) # arg0<- arrayClass
6531 cmpb $'I',%cl # supported?
6532 je 1f
6533 cmpb $'L',%cl
6534 je 1f
6535 cmpb $'[',%cl
6536 jne .LOP_FILLED_NEW_ARRAY_notimpl # no, not handled yet
65371:
6538 .if (!0)
6539 SPILL_TMP(rINST_FULL) # save copy, need "B" later
6540 sarl $4,rINST_FULL
6541 .endif
6542 movl rINST_FULL,OUT_ARG1(%esp) # arg1<- A or AA (length)
6543 call dvmAllocArrayByClass # eax<- call(arrayClass, length, flags)
6544 UNSPILL(rPC)
6545 GET_GLUE(%ecx)
6546 testl %eax,%eax # alloc successful?
6547 je common_exceptionThrown # no, handle exception
6548 movl %eax,offGlue_retval(%ecx) # retval.l<- new array
6549 movzwl 4(rPC),%ecx # ecx<- FEDC or CCCC
6550 leal offArrayObject_contents(%eax),%eax # eax<- newArray->contents
6551
6552/* at this point:
6553 * eax is pointer to tgt
6554 * rINST_FULL is length
6555 * ecx is FEDC or CCCC
6556 * TMP_SPILL is BA
6557 * rPC is valid, but spilled
6558 * We now need to copy values from registers into the array
6559 */
6560
6561 .if 0
6562 # set up src pointer
6563 SPILL(rFP) # esi
6564 SPILL(rIBASE) # edi
6565 movl %eax,%edi # set up dst ptr
6566 leal (rFP,%ecx,4),%esi # set up src ptr
6567 movl rINST_FULL,%ecx # load count register
6568 FETCH_INST_WORD(3)
6569 rep
6570 movsd
6571 UNSPILL(rIBASE)
6572 UNSPILL(rFP)
6573 .else
6574 testl rINST_FULL,rINST_FULL
6575 je 4f
6576 UNSPILL_TMP(rPC)
6577 andl $0x0f,rPC # rPC<- 0000000A
6578 sall $16,rPC # rPC<- 000A0000
6579 orl %ecx,rPC # rpc<- 000AFEDC
65803:
6581 movl $0xf,%ecx
6582 andl rPC,%ecx # ecx<- next reg to load
6583 GET_VREG(%ecx,%ecx)
6584 shrl $4,rPC
6585 leal 4(%eax),%eax
6586 movl %ecx,-4(%eax)
6587 sub $1,rINST_FULL
6588 jne 3b
65894:
6590 UNSPILL(rPC)
6591 FETCH_INST_WORD(3)
6592 .endif
6593
6594 ADVANCE_PC(3)
6595 GOTO_NEXT
6596
6597
6598 /*
6599 * Throw an exception indicating that we have not implemented this
6600 * mode of filled-new-array.
6601 */
6602.LOP_FILLED_NEW_ARRAY_notimpl:
6603 movl $.LstrInternalError,%eax
6604 movl %eax,OUT_ARG0(%esp)
6605 movl $.LstrFilledNewArrayNotImpl,%eax
6606 movl %eax,OUT_ARG1(%esp)
6607 call dvmThrowException
6608 UNSPILL(rPC)
6609 jmp common_exceptionThrown
6610
6611
6612/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
6613
6614.LOP_FILLED_NEW_ARRAY_RANGE_more:
6615 movl offMethod_clazz(%eax),%eax # eax<- method->clazz
6616 movl %eax,OUT_ARG0(%esp) # arg0<- clazz
6617 call dvmResolveClass # eax<- call(clazz,ref,flag)
6618 UNSPILL(rPC)
6619 testl %eax,%eax # null?
6620 je common_exceptionThrown # yes, handle it
6621
6622 # note: fall through to .LOP_FILLED_NEW_ARRAY_RANGE_continue
6623
6624 /*
6625 * On entry:
6626 * eax holds array class [r0]
6627 * rINST_FULL holds AA or BB [r10]
6628 * ecx is scratch
6629 * rPC is valid, but has been spilled
6630 */
6631.LOP_FILLED_NEW_ARRAY_RANGE_continue:
6632 movl offClassObject_descriptor(%eax),%ecx # ecx<- arrayClass->descriptor
6633 movl $ALLOC_DONT_TRACK,OUT_ARG2(%esp) # arg2<- flags
6634 movzbl 1(%ecx),%ecx # ecx<- descriptor[1]
6635 movl %eax,OUT_ARG0(%esp) # arg0<- arrayClass
6636 cmpb $'I',%cl # supported?
6637 je 1f
6638 cmpb $'L',%cl
6639 je 1f
6640 cmpb $'[',%cl
6641 jne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl # no, not handled yet
66421:
6643 .if (!1)
6644 SPILL_TMP(rINST_FULL) # save copy, need "B" later
6645 sarl $4,rINST_FULL
6646 .endif
6647 movl rINST_FULL,OUT_ARG1(%esp) # arg1<- A or AA (length)
6648 call dvmAllocArrayByClass # eax<- call(arrayClass, length, flags)
6649 UNSPILL(rPC)
6650 GET_GLUE(%ecx)
6651 testl %eax,%eax # alloc successful?
6652 je common_exceptionThrown # no, handle exception
6653 movl %eax,offGlue_retval(%ecx) # retval.l<- new array
6654 movzwl 4(rPC),%ecx # ecx<- FEDC or CCCC
6655 leal offArrayObject_contents(%eax),%eax # eax<- newArray->contents
6656
6657/* at this point:
6658 * eax is pointer to tgt
6659 * rINST_FULL is length
6660 * ecx is FEDC or CCCC
6661 * TMP_SPILL is BA
6662 * rPC is valid, but spilled
6663 * We now need to copy values from registers into the array
6664 */
6665
6666 .if 1
6667 # set up src pointer
6668 SPILL(rFP) # esi
6669 SPILL(rIBASE) # edi
6670 movl %eax,%edi # set up dst ptr
6671 leal (rFP,%ecx,4),%esi # set up src ptr
6672 movl rINST_FULL,%ecx # load count register
6673 FETCH_INST_WORD(3)
6674 rep
6675 movsd
6676 UNSPILL(rIBASE)
6677 UNSPILL(rFP)
6678 .else
6679 testl rINST_FULL,rINST_FULL
6680 je 4f
6681 UNSPILL_TMP(rPC)
6682 andl $0x0f,rPC # rPC<- 0000000A
6683 sall $16,rPC # rPC<- 000A0000
6684 orl %ecx,rPC # rpc<- 000AFEDC
66853:
6686 movl $0xf,%ecx
6687 andl rPC,%ecx # ecx<- next reg to load
6688 GET_VREG(%ecx,%ecx)
6689 shrl $4,rPC
6690 leal 4(%eax),%eax
6691 movl %ecx,-4(%eax)
6692 sub $1,rINST_FULL
6693 jne 3b
66944:
6695 UNSPILL(rPC)
6696 FETCH_INST_WORD(3)
6697 .endif
6698
6699 ADVANCE_PC(3)
6700 GOTO_NEXT
6701
6702
6703 /*
6704 * Throw an exception indicating that we have not implemented this
6705 * mode of filled-new-array.
6706 */
6707.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
6708 movl $.LstrInternalError,%eax
6709 movl %eax,OUT_ARG0(%esp)
6710 movl $.LstrFilledNewArrayNotImpl,%eax
6711 movl %eax,OUT_ARG1(%esp)
6712 call dvmThrowException
6713 UNSPILL(rPC)
6714 jmp common_exceptionThrown
6715
6716
6717/* continuation for OP_CMPL_FLOAT */
6718
6719.LOP_CMPL_FLOAT_isNaN:
6720 movl $-1,%ecx
6721 jmp .LOP_CMPL_FLOAT_finish
6722
6723/* continuation for OP_CMPG_FLOAT */
6724
6725.LOP_CMPG_FLOAT_isNaN:
6726 movl $1,%ecx
6727 jmp .LOP_CMPG_FLOAT_finish
6728
6729/* continuation for OP_CMPL_DOUBLE */
6730
6731.LOP_CMPL_DOUBLE_isNaN:
6732 movl $-1,%ecx
6733 jmp .LOP_CMPL_DOUBLE_finish
6734
6735/* continuation for OP_CMPG_DOUBLE */
6736
6737.LOP_CMPG_DOUBLE_isNaN:
6738 movl $1,%ecx
6739 jmp .LOP_CMPG_DOUBLE_finish
6740
6741/* continuation for OP_CMP_LONG */
6742
6743.LOP_CMP_LONG_bigger:
6744 UNSPILL(rPC)
6745 movl $1,%ecx
6746 jmp .LOP_CMP_LONG_finish
6747.LOP_CMP_LONG_smaller:
6748 UNSPILL(rPC)
6749 movl $-1,%ecx
6750.LOP_CMP_LONG_finish:
6751 SET_VREG(%ecx,rINST_FULL)
6752 FETCH_INST_WORD(2)
6753 ADVANCE_PC(2)
6754 GOTO_NEXT
6755
6756/* continuation for OP_AGET_WIDE */
6757
6758.LOP_AGET_WIDE_finish:
6759 leal offArrayObject_contents(%eax,%ecx,8),%eax
6760 movl (%eax),%ecx
6761 movl 4(%eax),%eax
6762 SET_VREG_WORD(%ecx,rINST_FULL,0)
6763 SET_VREG_WORD(%eax,rINST_FULL,1)
6764 FETCH_INST_WORD(2)
6765 ADVANCE_PC(2)
6766 GOTO_NEXT
6767
6768
6769/* continuation for OP_APUT_WIDE */
6770
6771.LOP_APUT_WIDE_finish:
6772 leal offArrayObject_contents(%eax,%ecx,8),%eax
6773 GET_VREG_WORD(%ecx,rINST_FULL,0)
6774 GET_VREG_WORD(rINST_FULL,rINST_FULL,1)
6775 movl rINST_FULL,4(%eax)
6776 FETCH_INST_WORD(2)
6777 movl %ecx,(%eax)
6778 ADVANCE_PC(2)
6779 GOTO_NEXT
6780
6781
6782/* continuation for OP_APUT_OBJECT */
6783
6784 /* On entry:
6785 * eax<- array object
6786 * ecx<- index
6787 * rINST_FULL<- vAA
6788 */
6789.LOP_APUT_OBJECT_continue:
6790 leal offArrayObject_contents(%eax,%ecx,4),%ecx
6791 testl rINST_FULL,rINST_FULL # storing null reference?
6792 je .LOP_APUT_OBJECT_skip_check
6793 SPILL(rPC)
6794 SPILL_TMP(%ecx)
6795 movl offObject_clazz(%eax),%eax # eax<- arrayObj->clazz
6796 movl offObject_clazz(rINST_FULL),%ecx # ecx<- obj->clazz
6797 movl %eax,OUT_ARG1(%esp)
6798 movl %ecx,OUT_ARG0(%esp)
6799 call dvmCanPutArrayElement # test object type vs. array type
6800 UNSPILL(rPC)
6801 UNSPILL_TMP(%ecx)
6802 testl %eax,%eax
6803 je common_errArrayStore
6804
6805.LOP_APUT_OBJECT_skip_check:
6806 movl rINST_FULL,(%ecx)
6807 FETCH_INST_WORD(2)
6808 ADVANCE_PC(2)
6809 GOTO_NEXT
6810
6811
6812/* continuation for OP_IGET */
6813
6814
6815.LOP_IGET_resolve:
6816 EXPORT_PC()
6817 SPILL(rPC)
6818 movl offGlue_method(rIBASE),rPC # rPC<- current method
6819 UNSPILL(rIBASE)
6820 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz
6821 SPILL_TMP(%ecx) # save object pointer across call
6822 movl rPC,OUT_ARG0(%esp) # pass in method->clazz
6823 call dvmResolveInstField # ... to dvmResolveInstField
6824 UNSPILL_TMP(%ecx)
6825 UNSPILL(rPC)
6826 testl %eax,%eax # ... which returns InstrField ptr
6827 jne .LOP_IGET_finish
6828 jmp common_exceptionThrown
6829
6830.LOP_IGET_finish:
6831 /*
6832 * Currently:
6833 * eax holds resolved field
6834 * ecx holds object
6835 * rIBASE is scratch, but needs to be unspilled
6836 * rINST_FULL holds A
6837 */
6838 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
6839 UNSPILL(rIBASE)
6840 testl %ecx,%ecx # object null?
6841 je common_errNullObject # object was null
6842 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits)
6843 movl rINST_FULL,%eax # eax<- A
6844 FETCH_INST_WORD(2)
6845 SET_VREG(%ecx,%eax)
6846 ADVANCE_PC(2)
6847 GOTO_NEXT
6848
6849
6850/* continuation for OP_IGET_WIDE */
6851
6852
6853.LOP_IGET_WIDE_resolve:
6854 EXPORT_PC()
6855 SPILL(rPC)
6856 movl offGlue_method(rIBASE),rPC # rPC<- current method
6857 UNSPILL(rIBASE)
6858 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz
6859 SPILL_TMP(%ecx) # save object pointer across call
6860 movl rPC,OUT_ARG0(%esp) # pass in method->clazz
6861 call dvmResolveInstField # ... to dvmResolveInstField
6862 UNSPILL_TMP(%ecx)
6863 UNSPILL(rPC)
6864 testl %eax,%eax # ... which returns InstrField ptr
6865 jne .LOP_IGET_WIDE_finish
6866 jmp common_exceptionThrown
6867
6868.LOP_IGET_WIDE_finish:
6869 /*
6870 * Currently:
6871 * eax holds resolved field
6872 * ecx holds object
6873 * rIBASE is scratch, but needs to be unspilled
6874 * rINST_FULL holds A
6875 */
6876 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
6877 UNSPILL(rIBASE)
6878 testl %ecx,%ecx # object null?
6879 je common_errNullObject # object was null
6880 leal (%ecx,%eax,1),%eax # eax<- address of field
6881 movl (%eax),%ecx # ecx<- lsw
6882 movl 4(%eax),%eax # eax<- msw
6883 SET_VREG_WORD(%ecx,rINST_FULL,0)
6884 SET_VREG_WORD(%eax,rINST_FULL,1)
6885 FETCH_INST_WORD(2)
6886 ADVANCE_PC(2)
6887 GOTO_NEXT
6888
6889
6890/* continuation for OP_IGET_OBJECT */
6891
6892
6893.LOP_IGET_OBJECT_resolve:
6894 EXPORT_PC()
6895 SPILL(rPC)
6896 movl offGlue_method(rIBASE),rPC # rPC<- current method
6897 UNSPILL(rIBASE)
6898 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz
6899 SPILL_TMP(%ecx) # save object pointer across call
6900 movl rPC,OUT_ARG0(%esp) # pass in method->clazz
6901 call dvmResolveInstField # ... to dvmResolveInstField
6902 UNSPILL_TMP(%ecx)
6903 UNSPILL(rPC)
6904 testl %eax,%eax # ... which returns InstrField ptr
6905 jne .LOP_IGET_OBJECT_finish
6906 jmp common_exceptionThrown
6907
6908.LOP_IGET_OBJECT_finish:
6909 /*
6910 * Currently:
6911 * eax holds resolved field
6912 * ecx holds object
6913 * rIBASE is scratch, but needs to be unspilled
6914 * rINST_FULL holds A
6915 */
6916 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
6917 UNSPILL(rIBASE)
6918 testl %ecx,%ecx # object null?
6919 je common_errNullObject # object was null
6920 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits)
6921 movl rINST_FULL,%eax # eax<- A
6922 FETCH_INST_WORD(2)
6923 SET_VREG(%ecx,%eax)
6924 ADVANCE_PC(2)
6925 GOTO_NEXT
6926
6927
6928/* continuation for OP_IGET_BOOLEAN */
6929
6930
6931.LOP_IGET_BOOLEAN_resolve:
6932 EXPORT_PC()
6933 SPILL(rPC)
6934 movl offGlue_method(rIBASE),rPC # rPC<- current method
6935 UNSPILL(rIBASE)
6936 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz
6937 SPILL_TMP(%ecx) # save object pointer across call
6938 movl rPC,OUT_ARG0(%esp) # pass in method->clazz
6939 call dvmResolveInstField # ... to dvmResolveInstField
6940 UNSPILL_TMP(%ecx)
6941 UNSPILL(rPC)
6942 testl %eax,%eax # ... which returns InstrField ptr
6943 jne .LOP_IGET_BOOLEAN_finish
6944 jmp common_exceptionThrown
6945
6946.LOP_IGET_BOOLEAN_finish:
6947 /*
6948 * Currently:
6949 * eax holds resolved field
6950 * ecx holds object
6951 * rIBASE is scratch, but needs to be unspilled
6952 * rINST_FULL holds A
6953 */
6954 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
6955 UNSPILL(rIBASE)
6956 testl %ecx,%ecx # object null?
6957 je common_errNullObject # object was null
6958 movzbl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits)
6959 movl rINST_FULL,%eax # eax<- A
6960 FETCH_INST_WORD(2)
6961 SET_VREG(%ecx,%eax)
6962 ADVANCE_PC(2)
6963 GOTO_NEXT
6964
6965
6966/* continuation for OP_IGET_BYTE */
6967
6968
6969.LOP_IGET_BYTE_resolve:
6970 EXPORT_PC()
6971 SPILL(rPC)
6972 movl offGlue_method(rIBASE),rPC # rPC<- current method
6973 UNSPILL(rIBASE)
6974 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz
6975 SPILL_TMP(%ecx) # save object pointer across call
6976 movl rPC,OUT_ARG0(%esp) # pass in method->clazz
6977 call dvmResolveInstField # ... to dvmResolveInstField
6978 UNSPILL_TMP(%ecx)
6979 UNSPILL(rPC)
6980 testl %eax,%eax # ... which returns InstrField ptr
6981 jne .LOP_IGET_BYTE_finish
6982 jmp common_exceptionThrown
6983
6984.LOP_IGET_BYTE_finish:
6985 /*
6986 * Currently:
6987 * eax holds resolved field
6988 * ecx holds object
6989 * rIBASE is scratch, but needs to be unspilled
6990 * rINST_FULL holds A
6991 */
6992 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
6993 UNSPILL(rIBASE)
6994 testl %ecx,%ecx # object null?
6995 je common_errNullObject # object was null
6996 movsbl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits)
6997 movl rINST_FULL,%eax # eax<- A
6998 FETCH_INST_WORD(2)
6999 SET_VREG(%ecx,%eax)
7000 ADVANCE_PC(2)
7001 GOTO_NEXT
7002
7003
7004/* continuation for OP_IGET_CHAR */
7005
7006
7007.LOP_IGET_CHAR_resolve:
7008 EXPORT_PC()
7009 SPILL(rPC)
7010 movl offGlue_method(rIBASE),rPC # rPC<- current method
7011 UNSPILL(rIBASE)
7012 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz
7013 SPILL_TMP(%ecx) # save object pointer across call
7014 movl rPC,OUT_ARG0(%esp) # pass in method->clazz
7015 call dvmResolveInstField # ... to dvmResolveInstField
7016 UNSPILL_TMP(%ecx)
7017 UNSPILL(rPC)
7018 testl %eax,%eax # ... which returns InstrField ptr
7019 jne .LOP_IGET_CHAR_finish
7020 jmp common_exceptionThrown
7021
7022.LOP_IGET_CHAR_finish:
7023 /*
7024 * Currently:
7025 * eax holds resolved field
7026 * ecx holds object
7027 * rIBASE is scratch, but needs to be unspilled
7028 * rINST_FULL holds A
7029 */
7030 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7031 UNSPILL(rIBASE)
7032 testl %ecx,%ecx # object null?
7033 je common_errNullObject # object was null
7034 movzwl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits)
7035 movl rINST_FULL,%eax # eax<- A
7036 FETCH_INST_WORD(2)
7037 SET_VREG(%ecx,%eax)
7038 ADVANCE_PC(2)
7039 GOTO_NEXT
7040
7041
7042/* continuation for OP_IGET_SHORT */
7043
7044
7045.LOP_IGET_SHORT_resolve:
7046 EXPORT_PC()
7047 SPILL(rPC)
7048 movl offGlue_method(rIBASE),rPC # rPC<- current method
7049 UNSPILL(rIBASE)
7050 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz
7051 SPILL_TMP(%ecx) # save object pointer across call
7052 movl rPC,OUT_ARG0(%esp) # pass in method->clazz
7053 call dvmResolveInstField # ... to dvmResolveInstField
7054 UNSPILL_TMP(%ecx)
7055 UNSPILL(rPC)
7056 testl %eax,%eax # ... which returns InstrField ptr
7057 jne .LOP_IGET_SHORT_finish
7058 jmp common_exceptionThrown
7059
7060.LOP_IGET_SHORT_finish:
7061 /*
7062 * Currently:
7063 * eax holds resolved field
7064 * ecx holds object
7065 * rIBASE is scratch, but needs to be unspilled
7066 * rINST_FULL holds A
7067 */
7068 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7069 UNSPILL(rIBASE)
7070 testl %ecx,%ecx # object null?
7071 je common_errNullObject # object was null
7072 movswl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits)
7073 movl rINST_FULL,%eax # eax<- A
7074 FETCH_INST_WORD(2)
7075 SET_VREG(%ecx,%eax)
7076 ADVANCE_PC(2)
7077 GOTO_NEXT
7078
7079
7080/* continuation for OP_IPUT */
7081
7082
7083.LOP_IPUT_resolve:
7084 EXPORT_PC()
7085 SPILL(rPC)
7086 movl offGlue_method(rIBASE),rPC # rPC<- current method
7087 UNSPILL(rIBASE)
7088 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz
7089 SPILL_TMP(%ecx) # save object pointer across call
7090 movl rPC,OUT_ARG0(%esp) # pass in method->clazz
7091 call dvmResolveInstField # ... to dvmResolveInstField
7092 UNSPILL_TMP(%ecx)
7093 UNSPILL(rPC)
7094 testl %eax,%eax # ... which returns InstrField ptr
7095 jne .LOP_IPUT_finish
7096 jmp common_exceptionThrown
7097
7098.LOP_IPUT_finish:
7099 /*
7100 * Currently:
7101 * eax holds resolved field
7102 * ecx holds object
7103 * rIBASE is scratch, but needs to be unspilled
7104 * rINST_FULL holds A
7105 */
7106 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A]
7107 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7108 UNSPILL(rIBASE)
7109 testl %ecx,%ecx # object null?
7110 je common_errNullObject # object was null
7111 movl rINST_FULL,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits)
7112 FETCH_INST_WORD(2)
7113 ADVANCE_PC(2)
7114 GOTO_NEXT
7115
7116/* continuation for OP_IPUT_WIDE */
7117
7118
7119.LOP_IPUT_WIDE_resolve:
7120 EXPORT_PC()
7121 SPILL(rPC)
7122 movl offGlue_method(rIBASE),rPC # rPC<- current method
7123 UNSPILL(rIBASE)
7124 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz
7125 SPILL_TMP(%ecx) # save object pointer across call
7126 movl rPC,OUT_ARG0(%esp) # pass in method->clazz
7127 call dvmResolveInstField # ... to dvmResolveInstField
7128 UNSPILL_TMP(%ecx)
7129 UNSPILL(rPC)
7130 testl %eax,%eax # ... which returns InstrField ptr
7131 jne .LOP_IPUT_WIDE_finish
7132 jmp common_exceptionThrown
7133
7134.LOP_IPUT_WIDE_finish:
7135 /*
7136 * Currently:
7137 * eax holds resolved field
7138 * ecx holds object
7139 * rIBASE is scratch, but needs to be unspilled
7140 * rINST_FULL holds A
7141 */
7142 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7143 UNSPILL(rIBASE)
7144 testl %ecx,%ecx # object null?
7145 je common_errNullObject # object was null
7146 leal (%ecx,%eax,1),%eax # eax<- address of field
7147 GET_VREG_WORD(%ecx,rINST_FULL,0) # ecx<- lsw
7148 GET_VREG_WORD(rINST_FULL,rINST_FULL,1) # rINST_FULL<- msw
7149 movl rINST_FULL,4(%eax)
7150 FETCH_INST_WORD(2)
7151 movl %ecx,(%eax)
7152 ADVANCE_PC(2)
7153 GOTO_NEXT
7154
7155/* continuation for OP_IPUT_OBJECT */
7156
7157
7158.LOP_IPUT_OBJECT_resolve:
7159 EXPORT_PC()
7160 SPILL(rPC)
7161 movl offGlue_method(rIBASE),rPC # rPC<- current method
7162 UNSPILL(rIBASE)
7163 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz
7164 SPILL_TMP(%ecx) # save object pointer across call
7165 movl rPC,OUT_ARG0(%esp) # pass in method->clazz
7166 call dvmResolveInstField # ... to dvmResolveInstField
7167 UNSPILL_TMP(%ecx)
7168 UNSPILL(rPC)
7169 testl %eax,%eax # ... which returns InstrField ptr
7170 jne .LOP_IPUT_OBJECT_finish
7171 jmp common_exceptionThrown
7172
7173.LOP_IPUT_OBJECT_finish:
7174 /*
7175 * Currently:
7176 * eax holds resolved field
7177 * ecx holds object
7178 * rIBASE is scratch, but needs to be unspilled
7179 * rINST_FULL holds A
7180 */
7181 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A]
7182 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7183 UNSPILL(rIBASE)
7184 testl %ecx,%ecx # object null?
7185 je common_errNullObject # object was null
7186 movl rINST_FULL,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits)
7187 FETCH_INST_WORD(2)
7188 ADVANCE_PC(2)
7189 GOTO_NEXT
7190
7191/* continuation for OP_IPUT_BOOLEAN */
7192
7193
7194.LOP_IPUT_BOOLEAN_resolve:
7195 EXPORT_PC()
7196 SPILL(rPC)
7197 movl offGlue_method(rIBASE),rPC # rPC<- current method
7198 UNSPILL(rIBASE)
7199 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz
7200 SPILL_TMP(%ecx) # save object pointer across call
7201 movl rPC,OUT_ARG0(%esp) # pass in method->clazz
7202 call dvmResolveInstField # ... to dvmResolveInstField
7203 UNSPILL_TMP(%ecx)
7204 UNSPILL(rPC)
7205 testl %eax,%eax # ... which returns InstrField ptr
7206 jne .LOP_IPUT_BOOLEAN_finish
7207 jmp common_exceptionThrown
7208
7209.LOP_IPUT_BOOLEAN_finish:
7210 /*
7211 * Currently:
7212 * eax holds resolved field
7213 * ecx holds object
7214 * rIBASE is scratch, but needs to be unspilled
7215 * rINST_FULL holds A
7216 */
7217 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A]
7218 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7219 UNSPILL(rIBASE)
7220 testl %ecx,%ecx # object null?
7221 je common_errNullObject # object was null
7222 movb rINST_LO,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits)
7223 FETCH_INST_WORD(2)
7224 ADVANCE_PC(2)
7225 GOTO_NEXT
7226
7227/* continuation for OP_IPUT_BYTE */
7228
7229
7230.LOP_IPUT_BYTE_resolve:
7231 EXPORT_PC()
7232 SPILL(rPC)
7233 movl offGlue_method(rIBASE),rPC # rPC<- current method
7234 UNSPILL(rIBASE)
7235 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz
7236 SPILL_TMP(%ecx) # save object pointer across call
7237 movl rPC,OUT_ARG0(%esp) # pass in method->clazz
7238 call dvmResolveInstField # ... to dvmResolveInstField
7239 UNSPILL_TMP(%ecx)
7240 UNSPILL(rPC)
7241 testl %eax,%eax # ... which returns InstrField ptr
7242 jne .LOP_IPUT_BYTE_finish
7243 jmp common_exceptionThrown
7244
7245.LOP_IPUT_BYTE_finish:
7246 /*
7247 * Currently:
7248 * eax holds resolved field
7249 * ecx holds object
7250 * rIBASE is scratch, but needs to be unspilled
7251 * rINST_FULL holds A
7252 */
7253 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A]
7254 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7255 UNSPILL(rIBASE)
7256 testl %ecx,%ecx # object null?
7257 je common_errNullObject # object was null
7258 movb rINST_LO,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits)
7259 FETCH_INST_WORD(2)
7260 ADVANCE_PC(2)
7261 GOTO_NEXT
7262
7263/* continuation for OP_IPUT_CHAR */
7264
7265
7266.LOP_IPUT_CHAR_resolve:
7267 EXPORT_PC()
7268 SPILL(rPC)
7269 movl offGlue_method(rIBASE),rPC # rPC<- current method
7270 UNSPILL(rIBASE)
7271 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz
7272 SPILL_TMP(%ecx) # save object pointer across call
7273 movl rPC,OUT_ARG0(%esp) # pass in method->clazz
7274 call dvmResolveInstField # ... to dvmResolveInstField
7275 UNSPILL_TMP(%ecx)
7276 UNSPILL(rPC)
7277 testl %eax,%eax # ... which returns InstrField ptr
7278 jne .LOP_IPUT_CHAR_finish
7279 jmp common_exceptionThrown
7280
7281.LOP_IPUT_CHAR_finish:
7282 /*
7283 * Currently:
7284 * eax holds resolved field
7285 * ecx holds object
7286 * rIBASE is scratch, but needs to be unspilled
7287 * rINST_FULL holds A
7288 */
7289 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A]
7290 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7291 UNSPILL(rIBASE)
7292 testl %ecx,%ecx # object null?
7293 je common_errNullObject # object was null
7294 movw rINST,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits)
7295 FETCH_INST_WORD(2)
7296 ADVANCE_PC(2)
7297 GOTO_NEXT
7298
7299/* continuation for OP_IPUT_SHORT */
7300
7301
7302.LOP_IPUT_SHORT_resolve:
7303 EXPORT_PC()
7304 SPILL(rPC)
7305 movl offGlue_method(rIBASE),rPC # rPC<- current method
7306 UNSPILL(rIBASE)
7307 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz
7308 SPILL_TMP(%ecx) # save object pointer across call
7309 movl rPC,OUT_ARG0(%esp) # pass in method->clazz
7310 call dvmResolveInstField # ... to dvmResolveInstField
7311 UNSPILL_TMP(%ecx)
7312 UNSPILL(rPC)
7313 testl %eax,%eax # ... which returns InstrField ptr
7314 jne .LOP_IPUT_SHORT_finish
7315 jmp common_exceptionThrown
7316
7317.LOP_IPUT_SHORT_finish:
7318 /*
7319 * Currently:
7320 * eax holds resolved field
7321 * ecx holds object
7322 * rIBASE is scratch, but needs to be unspilled
7323 * rINST_FULL holds A
7324 */
7325 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A]
7326 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7327 UNSPILL(rIBASE)
7328 testl %ecx,%ecx # object null?
7329 je common_errNullObject # object was null
7330 movw rINST,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits)
7331 FETCH_INST_WORD(2)
7332 ADVANCE_PC(2)
7333 GOTO_NEXT
7334
7335/* continuation for OP_SGET */
7336
7337 /*
7338 * Go resolve the field
7339 */
7340.LOP_SGET_resolve:
7341 GET_GLUE(%ecx)
7342 movzwl 2(rPC),%eax # eax<- field ref BBBB
7343 movl offGlue_method(%ecx),%ecx # ecx<- current method
7344 EXPORT_PC() # could throw, need to export
7345 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7346 SPILL(rPC)
7347 movl %eax,OUT_ARG1(%esp)
7348 movl %ecx,OUT_ARG0(%esp)
7349 call dvmResolveStaticField # eax<- resolved StaticField ptr
7350 UNSPILL(rPC)
7351 testl %eax,%eax
7352 jne .LOP_SGET_finish # success, continue
7353 jmp common_exceptionThrown # no, handle exception
7354
7355
7356/* continuation for OP_SGET_WIDE */
7357
7358 /*
7359 * Go resolve the field
7360 */
7361.LOP_SGET_WIDE_resolve:
7362 GET_GLUE(%ecx)
7363 movzwl 2(rPC),%eax # eax<- field ref BBBB
7364 movl offGlue_method(%ecx),%ecx # ecx<- current method
7365 EXPORT_PC() # could throw, need to export
7366 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7367 SPILL(rPC)
7368 movl %eax,OUT_ARG1(%esp)
7369 movl %ecx,OUT_ARG0(%esp)
7370 call dvmResolveStaticField # eax<- resolved StaticField ptr
7371 UNSPILL(rPC)
7372 testl %eax,%eax
7373 jne .LOP_SGET_WIDE_finish # success, continue
7374 jmp common_exceptionThrown # no, handle exception
7375
7376
7377/* continuation for OP_SGET_OBJECT */
7378
7379 /*
7380 * Go resolve the field
7381 */
7382.LOP_SGET_OBJECT_resolve:
7383 GET_GLUE(%ecx)
7384 movzwl 2(rPC),%eax # eax<- field ref BBBB
7385 movl offGlue_method(%ecx),%ecx # ecx<- current method
7386 EXPORT_PC() # could throw, need to export
7387 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7388 SPILL(rPC)
7389 movl %eax,OUT_ARG1(%esp)
7390 movl %ecx,OUT_ARG0(%esp)
7391 call dvmResolveStaticField # eax<- resolved StaticField ptr
7392 UNSPILL(rPC)
7393 testl %eax,%eax
7394 jne .LOP_SGET_OBJECT_finish # success, continue
7395 jmp common_exceptionThrown # no, handle exception
7396
7397
7398/* continuation for OP_SGET_BOOLEAN */
7399
7400 /*
7401 * Go resolve the field
7402 */
7403.LOP_SGET_BOOLEAN_resolve:
7404 GET_GLUE(%ecx)
7405 movzwl 2(rPC),%eax # eax<- field ref BBBB
7406 movl offGlue_method(%ecx),%ecx # ecx<- current method
7407 EXPORT_PC() # could throw, need to export
7408 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7409 SPILL(rPC)
7410 movl %eax,OUT_ARG1(%esp)
7411 movl %ecx,OUT_ARG0(%esp)
7412 call dvmResolveStaticField # eax<- resolved StaticField ptr
7413 UNSPILL(rPC)
7414 testl %eax,%eax
7415 jne .LOP_SGET_BOOLEAN_finish # success, continue
7416 jmp common_exceptionThrown # no, handle exception
7417
7418
7419/* continuation for OP_SGET_BYTE */
7420
7421 /*
7422 * Go resolve the field
7423 */
7424.LOP_SGET_BYTE_resolve:
7425 GET_GLUE(%ecx)
7426 movzwl 2(rPC),%eax # eax<- field ref BBBB
7427 movl offGlue_method(%ecx),%ecx # ecx<- current method
7428 EXPORT_PC() # could throw, need to export
7429 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7430 SPILL(rPC)
7431 movl %eax,OUT_ARG1(%esp)
7432 movl %ecx,OUT_ARG0(%esp)
7433 call dvmResolveStaticField # eax<- resolved StaticField ptr
7434 UNSPILL(rPC)
7435 testl %eax,%eax
7436 jne .LOP_SGET_BYTE_finish # success, continue
7437 jmp common_exceptionThrown # no, handle exception
7438
7439
7440/* continuation for OP_SGET_CHAR */
7441
7442 /*
7443 * Go resolve the field
7444 */
7445.LOP_SGET_CHAR_resolve:
7446 GET_GLUE(%ecx)
7447 movzwl 2(rPC),%eax # eax<- field ref BBBB
7448 movl offGlue_method(%ecx),%ecx # ecx<- current method
7449 EXPORT_PC() # could throw, need to export
7450 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7451 SPILL(rPC)
7452 movl %eax,OUT_ARG1(%esp)
7453 movl %ecx,OUT_ARG0(%esp)
7454 call dvmResolveStaticField # eax<- resolved StaticField ptr
7455 UNSPILL(rPC)
7456 testl %eax,%eax
7457 jne .LOP_SGET_CHAR_finish # success, continue
7458 jmp common_exceptionThrown # no, handle exception
7459
7460
7461/* continuation for OP_SGET_SHORT */
7462
7463 /*
7464 * Go resolve the field
7465 */
7466.LOP_SGET_SHORT_resolve:
7467 GET_GLUE(%ecx)
7468 movzwl 2(rPC),%eax # eax<- field ref BBBB
7469 movl offGlue_method(%ecx),%ecx # ecx<- current method
7470 EXPORT_PC() # could throw, need to export
7471 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7472 SPILL(rPC)
7473 movl %eax,OUT_ARG1(%esp)
7474 movl %ecx,OUT_ARG0(%esp)
7475 call dvmResolveStaticField # eax<- resolved StaticField ptr
7476 UNSPILL(rPC)
7477 testl %eax,%eax
7478 jne .LOP_SGET_SHORT_finish # success, continue
7479 jmp common_exceptionThrown # no, handle exception
7480
7481
7482/* continuation for OP_SPUT */
7483
7484 /*
7485 * Go resolve the field
7486 */
7487.LOP_SPUT_resolve:
7488 GET_GLUE(%ecx)
7489 movzwl 2(rPC),%eax # eax<- field ref BBBB
7490 movl offGlue_method(%ecx),%ecx # ecx<- current method
7491 EXPORT_PC() # could throw, need to export
7492 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7493 SPILL(rPC)
7494 movl %eax,OUT_ARG1(%esp)
7495 movl %ecx,OUT_ARG0(%esp)
7496 call dvmResolveStaticField # eax<- resolved StaticField ptr
7497 UNSPILL(rPC)
7498 testl %eax,%eax
7499 jne .LOP_SPUT_finish # success, continue
7500 jmp common_exceptionThrown # no, handle exception
7501
7502
7503/* continuation for OP_SPUT_WIDE */
7504
7505 /*
7506 * Go resolve the field
7507 */
7508.LOP_SPUT_WIDE_resolve:
7509 GET_GLUE(%ecx)
7510 movzwl 2(rPC),%eax # eax<- field ref BBBB
7511 movl offGlue_method(%ecx),%ecx # ecx<- current method
7512 EXPORT_PC() # could throw, need to export
7513 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7514 SPILL(rPC)
7515 movl %eax,OUT_ARG1(%esp)
7516 movl %ecx,OUT_ARG0(%esp)
7517 call dvmResolveStaticField # eax<- resolved StaticField ptr
7518 UNSPILL(rPC)
7519 testl %eax,%eax
7520 jne .LOP_SPUT_WIDE_finish # success, continue
7521 jmp common_exceptionThrown # no, handle exception
7522
7523
7524/* continuation for OP_SPUT_OBJECT */
7525
7526 /*
7527 * Go resolve the field
7528 */
7529.LOP_SPUT_OBJECT_resolve:
7530 GET_GLUE(%ecx)
7531 movzwl 2(rPC),%eax # eax<- field ref BBBB
7532 movl offGlue_method(%ecx),%ecx # ecx<- current method
7533 EXPORT_PC() # could throw, need to export
7534 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7535 SPILL(rPC)
7536 movl %eax,OUT_ARG1(%esp)
7537 movl %ecx,OUT_ARG0(%esp)
7538 call dvmResolveStaticField # eax<- resolved StaticField ptr
7539 UNSPILL(rPC)
7540 testl %eax,%eax
7541 jne .LOP_SPUT_OBJECT_finish # success, continue
7542 jmp common_exceptionThrown # no, handle exception
7543
7544
7545/* continuation for OP_SPUT_BOOLEAN */
7546
7547 /*
7548 * Go resolve the field
7549 */
7550.LOP_SPUT_BOOLEAN_resolve:
7551 GET_GLUE(%ecx)
7552 movzwl 2(rPC),%eax # eax<- field ref BBBB
7553 movl offGlue_method(%ecx),%ecx # ecx<- current method
7554 EXPORT_PC() # could throw, need to export
7555 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7556 SPILL(rPC)
7557 movl %eax,OUT_ARG1(%esp)
7558 movl %ecx,OUT_ARG0(%esp)
7559 call dvmResolveStaticField # eax<- resolved StaticField ptr
7560 UNSPILL(rPC)
7561 testl %eax,%eax
7562 jne .LOP_SPUT_BOOLEAN_finish # success, continue
7563 jmp common_exceptionThrown # no, handle exception
7564
7565
7566/* continuation for OP_SPUT_BYTE */
7567
7568 /*
7569 * Go resolve the field
7570 */
7571.LOP_SPUT_BYTE_resolve:
7572 GET_GLUE(%ecx)
7573 movzwl 2(rPC),%eax # eax<- field ref BBBB
7574 movl offGlue_method(%ecx),%ecx # ecx<- current method
7575 EXPORT_PC() # could throw, need to export
7576 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7577 SPILL(rPC)
7578 movl %eax,OUT_ARG1(%esp)
7579 movl %ecx,OUT_ARG0(%esp)
7580 call dvmResolveStaticField # eax<- resolved StaticField ptr
7581 UNSPILL(rPC)
7582 testl %eax,%eax
7583 jne .LOP_SPUT_BYTE_finish # success, continue
7584 jmp common_exceptionThrown # no, handle exception
7585
7586
7587/* continuation for OP_SPUT_CHAR */
7588
7589 /*
7590 * Go resolve the field
7591 */
7592.LOP_SPUT_CHAR_resolve:
7593 GET_GLUE(%ecx)
7594 movzwl 2(rPC),%eax # eax<- field ref BBBB
7595 movl offGlue_method(%ecx),%ecx # ecx<- current method
7596 EXPORT_PC() # could throw, need to export
7597 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7598 SPILL(rPC)
7599 movl %eax,OUT_ARG1(%esp)
7600 movl %ecx,OUT_ARG0(%esp)
7601 call dvmResolveStaticField # eax<- resolved StaticField ptr
7602 UNSPILL(rPC)
7603 testl %eax,%eax
7604 jne .LOP_SPUT_CHAR_finish # success, continue
7605 jmp common_exceptionThrown # no, handle exception
7606
7607
7608/* continuation for OP_SPUT_SHORT */
7609
7610 /*
7611 * Go resolve the field
7612 */
7613.LOP_SPUT_SHORT_resolve:
7614 GET_GLUE(%ecx)
7615 movzwl 2(rPC),%eax # eax<- field ref BBBB
7616 movl offGlue_method(%ecx),%ecx # ecx<- current method
7617 EXPORT_PC() # could throw, need to export
7618 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7619 SPILL(rPC)
7620 movl %eax,OUT_ARG1(%esp)
7621 movl %ecx,OUT_ARG0(%esp)
7622 call dvmResolveStaticField # eax<- resolved StaticField ptr
7623 UNSPILL(rPC)
7624 testl %eax,%eax
7625 jne .LOP_SPUT_SHORT_finish # success, continue
7626 jmp common_exceptionThrown # no, handle exception
7627
7628
7629/* continuation for OP_INVOKE_VIRTUAL */
7630
7631
7632.LOP_INVOKE_VIRTUAL_more:
7633 movl offMethod_clazz(%eax),%eax # ecx<- method->clazz
7634 movl %eax,OUT_ARG0(%esp) # arg0<- clazz
7635 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags
7636 call dvmResolveMethod # eax<- call(clazz, ref, flags)
7637 UNSPILL(rPC)
7638 testl %eax,%eax # got null?
7639 jne .LOP_INVOKE_VIRTUAL_continue # no, continue
7640 jmp common_exceptionThrown # yes, handle exception
7641
7642 /* At this point:
7643 * eax = resolved base method
7644 * ecx = scratch
7645 */
7646.LOP_INVOKE_VIRTUAL_continue:
7647 movzwl 4(rPC),%ecx # ecx<- GFED or CCCC
7648 .if (!0)
7649 andl $0xf,%ecx # ecx<- D (or stays CCCC)
7650 .endif
7651 GET_VREG(%ecx,%ecx) # ecx<- "this"
7652 movzwl offMethod_methodIndex(%eax),%eax # eax<- baseMethod->methodIndex
7653 testl %ecx,%ecx # null this?
7654 je common_errNullObject # go if so
7655 movl offObject_clazz(%ecx),%ecx # ecx<- thisPtr->clazz
7656 movl offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable
7657 movl (%ecx,%eax,4),%eax # eax<- vtable[methodIndex]
Johnnie Birchc4080f62009-02-10 15:41:06 -08007658 jmp common_invokeMethodNoRange
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08007659
7660
7661/* continuation for OP_INVOKE_SUPER */
7662
7663 /*
7664 * At this point:
7665 * ecx = resolved base method [r0]
7666 * eax = method->clazz [r9]
7667 */
7668.LOP_INVOKE_SUPER_continue:
7669 movl offClassObject_super(%eax),%eax # eax<- method->clazz->super
7670 movzwl offMethod_methodIndex(%ecx),%ecx # ecx<- baseMthod->methodIndex
7671 cmpl offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount)
7672 jae .LOP_INVOKE_SUPER_nsm # method not present in superclass
7673 movl offClassObject_vtable(%eax),%eax # eax<- ...clazz->super->vtable
7674 movl (%eax,%ecx,4),%eax # eax<- vtable[methodIndex]
Johnnie Birchc4080f62009-02-10 15:41:06 -08007675 jmp common_invokeMethodNoRange
7676
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08007677
7678 /* At this point:
7679 * ecx = null (needs to be resolved base method)
7680 * eax = method->clazz
7681 */
7682.LOP_INVOKE_SUPER_resolve:
7683 SPILL_TMP(%eax) # method->clazz
7684 movl %eax,OUT_ARG0(%esp) # arg0<- method->clazz
7685 movzwl 2(rPC),%ecx # ecx<- BBBB
7686 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- resolver method type
7687 movl %ecx,OUT_ARG1(%esp) # arg1<- ref
7688 SPILL(rPC)
7689 call dvmResolveMethod # eax<- call(clazz, ref, flags)
7690 UNSPILL(rPC)
7691 testl %eax,%eax # got null?
7692 movl %eax,%ecx # ecx<- resolved base method
7693 UNSPILL_TMP(%eax) # restore method->clazz
7694 jne .LOP_INVOKE_SUPER_continue # good to go - continue
7695 jmp common_exceptionThrown # handle exception
7696
7697 /*
7698 * Throw a NoSuchMethodError with the method name as the message.
7699 * ecx = resolved base method
7700 */
7701.LOP_INVOKE_SUPER_nsm:
7702 movl offMethod_name(%ecx),%eax
7703 mov %eax,OUT_ARG1(%esp)
7704 jmp common_errNoSuchMethod
7705
7706/* continuation for OP_INVOKE_DIRECT */
7707
7708 /*
7709 * On entry:
7710 * TMP_SPILL <- "this" register
7711 * Things a bit ugly on this path, but it's the less
7712 * frequent one. We'll have to do some reloading.
7713 */
7714.LOP_INVOKE_DIRECT_resolve:
7715 SPILL_TMP(%ecx)
7716 GET_GLUE(%ecx)
7717 UNSPILL(rPC)
7718 movl offGlue_method(%ecx),%ecx # ecx<- glue->method
7719 movzwl 2(rPC),%eax # reference (BBBB or CCCC)
7720 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7721 movl $METHOD_DIRECT,OUT_ARG2(%esp)
7722 movl %eax,OUT_ARG1(%esp)
7723 movl %ecx,OUT_ARG0(%esp)
7724 call dvmResolveMethod # eax<- call(clazz, ref, flags)
7725 UNSPILL_TMP(%ecx)
7726 testl %eax,%eax
7727 jne .LOP_INVOKE_DIRECT_finish
7728 UNSPILL(rPC)
7729 jmp common_exceptionThrown
7730
7731/* continuation for OP_INVOKE_STATIC */
7732
7733.LOP_INVOKE_STATIC_continue:
7734 movl $METHOD_STATIC,%eax
7735 movl %eax,OUT_ARG2(%esp) # arg2<- flags
7736 SPILL(rPC)
7737 call dvmResolveMethod # call(clazz,ref,flags)
7738 UNSPILL(rPC)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08007739 testl %eax,%eax # got null?
Johnnie Birchc4080f62009-02-10 15:41:06 -08007740 jne common_invokeMethodNoRange
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08007741 jmp common_exceptionThrown
7742
7743
7744/* continuation for OP_INVOKE_INTERFACE */
7745
7746.LOP_INVOKE_INTERFACE_continue:
7747 call dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex)
7748 UNSPILL(rPC)
7749 testl %eax,%eax
7750 je common_exceptionThrown
Johnnie Birchc4080f62009-02-10 15:41:06 -08007751 jmp common_invokeMethodNoRange
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08007752
7753
7754/* continuation for OP_INVOKE_VIRTUAL_RANGE */
7755
7756
7757.LOP_INVOKE_VIRTUAL_RANGE_more:
7758 movl offMethod_clazz(%eax),%eax # ecx<- method->clazz
7759 movl %eax,OUT_ARG0(%esp) # arg0<- clazz
7760 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags
7761 call dvmResolveMethod # eax<- call(clazz, ref, flags)
7762 UNSPILL(rPC)
7763 testl %eax,%eax # got null?
7764 jne .LOP_INVOKE_VIRTUAL_RANGE_continue # no, continue
7765 jmp common_exceptionThrown # yes, handle exception
7766
7767 /* At this point:
7768 * eax = resolved base method
7769 * ecx = scratch
7770 */
7771.LOP_INVOKE_VIRTUAL_RANGE_continue:
7772 movzwl 4(rPC),%ecx # ecx<- GFED or CCCC
7773 .if (!1)
7774 andl $0xf,%ecx # ecx<- D (or stays CCCC)
7775 .endif
7776 GET_VREG(%ecx,%ecx) # ecx<- "this"
7777 movzwl offMethod_methodIndex(%eax),%eax # eax<- baseMethod->methodIndex
7778 testl %ecx,%ecx # null this?
7779 je common_errNullObject # go if so
7780 movl offObject_clazz(%ecx),%ecx # ecx<- thisPtr->clazz
7781 movl offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable
7782 movl (%ecx,%eax,4),%eax # eax<- vtable[methodIndex]
Johnnie Birchc4080f62009-02-10 15:41:06 -08007783 jmp common_invokeMethodRange
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08007784
7785
7786/* continuation for OP_INVOKE_SUPER_RANGE */
7787
7788 /*
7789 * At this point:
7790 * ecx = resolved base method [r0]
7791 * eax = method->clazz [r9]
7792 */
7793.LOP_INVOKE_SUPER_RANGE_continue:
7794 movl offClassObject_super(%eax),%eax # eax<- method->clazz->super
7795 movzwl offMethod_methodIndex(%ecx),%ecx # ecx<- baseMthod->methodIndex
7796 cmpl offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount)
7797 jae .LOP_INVOKE_SUPER_RANGE_nsm # method not present in superclass
7798 movl offClassObject_vtable(%eax),%eax # eax<- ...clazz->super->vtable
7799 movl (%eax,%ecx,4),%eax # eax<- vtable[methodIndex]
Johnnie Birchc4080f62009-02-10 15:41:06 -08007800 jmp common_invokeMethodRange
7801
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08007802
7803 /* At this point:
7804 * ecx = null (needs to be resolved base method)
7805 * eax = method->clazz
7806 */
7807.LOP_INVOKE_SUPER_RANGE_resolve:
7808 SPILL_TMP(%eax) # method->clazz
7809 movl %eax,OUT_ARG0(%esp) # arg0<- method->clazz
7810 movzwl 2(rPC),%ecx # ecx<- BBBB
7811 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- resolver method type
7812 movl %ecx,OUT_ARG1(%esp) # arg1<- ref
7813 SPILL(rPC)
7814 call dvmResolveMethod # eax<- call(clazz, ref, flags)
7815 UNSPILL(rPC)
7816 testl %eax,%eax # got null?
7817 movl %eax,%ecx # ecx<- resolved base method
7818 UNSPILL_TMP(%eax) # restore method->clazz
7819 jne .LOP_INVOKE_SUPER_RANGE_continue # good to go - continue
7820 jmp common_exceptionThrown # handle exception
7821
7822 /*
7823 * Throw a NoSuchMethodError with the method name as the message.
7824 * ecx = resolved base method
7825 */
7826.LOP_INVOKE_SUPER_RANGE_nsm:
7827 movl offMethod_name(%ecx),%eax
7828 mov %eax,OUT_ARG1(%esp)
7829 jmp common_errNoSuchMethod
7830
7831/* continuation for OP_INVOKE_DIRECT_RANGE */
7832
7833 /*
7834 * On entry:
7835 * TMP_SPILL <- "this" register
7836 * Things a bit ugly on this path, but it's the less
7837 * frequent one. We'll have to do some reloading.
7838 */
7839.LOP_INVOKE_DIRECT_RANGE_resolve:
7840 SPILL_TMP(%ecx)
7841 GET_GLUE(%ecx)
7842 UNSPILL(rPC)
7843 movl offGlue_method(%ecx),%ecx # ecx<- glue->method
7844 movzwl 2(rPC),%eax # reference (BBBB or CCCC)
7845 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7846 movl $METHOD_DIRECT,OUT_ARG2(%esp)
7847 movl %eax,OUT_ARG1(%esp)
7848 movl %ecx,OUT_ARG0(%esp)
7849 call dvmResolveMethod # eax<- call(clazz, ref, flags)
7850 UNSPILL_TMP(%ecx)
7851 testl %eax,%eax
7852 jne .LOP_INVOKE_DIRECT_RANGE_finish
7853 UNSPILL(rPC)
7854 jmp common_exceptionThrown
7855
7856/* continuation for OP_INVOKE_STATIC_RANGE */
7857
7858.LOP_INVOKE_STATIC_RANGE_continue:
7859 movl $METHOD_STATIC,%eax
7860 movl %eax,OUT_ARG2(%esp) # arg2<- flags
7861 SPILL(rPC)
7862 call dvmResolveMethod # call(clazz,ref,flags)
7863 UNSPILL(rPC)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08007864 testl %eax,%eax # got null?
Johnnie Birchc4080f62009-02-10 15:41:06 -08007865 jne common_invokeMethodRange
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08007866 jmp common_exceptionThrown
7867
7868
7869/* continuation for OP_INVOKE_INTERFACE_RANGE */
7870
7871.LOP_INVOKE_INTERFACE_RANGE_continue:
7872 call dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex)
7873 UNSPILL(rPC)
7874 testl %eax,%eax
7875 je common_exceptionThrown
Johnnie Birchc4080f62009-02-10 15:41:06 -08007876 jmp common_invokeMethodRange
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08007877
7878
7879/* continuation for OP_FLOAT_TO_INT */
7880
7881
7882.LOP_FLOAT_TO_INT_continue:
7883 .if 0
7884 movl $0x80000000,%eax
7885 xorl 4(rFP,%ecx,4),%eax
7886 orl (rFP,%ecx,4),%eax
7887 .else
7888 cmpl $0x80000000,(rFP,%ecx,4)
7889 .endif
7890 je .LOP_FLOAT_TO_INT_special_case # fix up result
7891
7892.LOP_FLOAT_TO_INT_finish:
7893 ADVANCE_PC(1)
7894 GOTO_NEXT
7895
7896.LOP_FLOAT_TO_INT_special_case:
7897 fnstsw %ax
7898 sahf
7899 jp .LOP_FLOAT_TO_INT_isNaN
7900 adcl $-1,(rFP,%ecx,4)
7901 .if 0
7902 adcl $-1,4(rFP,%ecx,4)
7903 .endif
7904 jmp .LOP_FLOAT_TO_INT_finish
7905.LOP_FLOAT_TO_INT_isNaN:
7906 movl $0,(rFP,%ecx,4)
7907 .if 0
7908 movl $0,4(rFP,%ecx,4)
7909 .endif
7910 jmp .LOP_FLOAT_TO_INT_finish
7911
7912/* continuation for OP_FLOAT_TO_LONG */
7913
7914
7915.LOP_FLOAT_TO_LONG_continue:
7916 .if 1
7917 movl $0x80000000,%eax
7918 xorl 4(rFP,%ecx,4),%eax
7919 orl (rFP,%ecx,4),%eax
7920 .else
7921 cmpl $0x80000000,(rFP,%ecx,4)
7922 .endif
7923 je .LOP_FLOAT_TO_LONG_special_case # fix up result
7924
7925.LOP_FLOAT_TO_LONG_finish:
7926 ADVANCE_PC(1)
7927 GOTO_NEXT
7928
7929.LOP_FLOAT_TO_LONG_special_case:
7930 fnstsw %ax
7931 sahf
7932 jp .LOP_FLOAT_TO_LONG_isNaN
7933 adcl $-1,(rFP,%ecx,4)
7934 .if 1
7935 adcl $-1,4(rFP,%ecx,4)
7936 .endif
7937 jmp .LOP_FLOAT_TO_LONG_finish
7938.LOP_FLOAT_TO_LONG_isNaN:
7939 movl $0,(rFP,%ecx,4)
7940 .if 1
7941 movl $0,4(rFP,%ecx,4)
7942 .endif
7943 jmp .LOP_FLOAT_TO_LONG_finish
7944
7945/* continuation for OP_DOUBLE_TO_INT */
7946
7947
7948.LOP_DOUBLE_TO_INT_continue:
7949 .if 0
7950 movl $0x80000000,%eax
7951 xorl 4(rFP,%ecx,4),%eax
7952 orl (rFP,%ecx,4),%eax
7953 .else
7954 cmpl $0x80000000,(rFP,%ecx,4)
7955 .endif
7956 je .LOP_DOUBLE_TO_INT_special_case # fix up result
7957
7958.LOP_DOUBLE_TO_INT_finish:
7959 ADVANCE_PC(1)
7960 GOTO_NEXT
7961
7962.LOP_DOUBLE_TO_INT_special_case:
7963 fnstsw %ax
7964 sahf
7965 jp .LOP_DOUBLE_TO_INT_isNaN
7966 adcl $-1,(rFP,%ecx,4)
7967 .if 0
7968 adcl $-1,4(rFP,%ecx,4)
7969 .endif
7970 jmp .LOP_DOUBLE_TO_INT_finish
7971.LOP_DOUBLE_TO_INT_isNaN:
7972 movl $0,(rFP,%ecx,4)
7973 .if 0
7974 movl $0,4(rFP,%ecx,4)
7975 .endif
7976 jmp .LOP_DOUBLE_TO_INT_finish
7977
7978/* continuation for OP_DOUBLE_TO_LONG */
7979
7980
7981.LOP_DOUBLE_TO_LONG_continue:
7982 .if 1
7983 movl $0x80000000,%eax
7984 xorl 4(rFP,%ecx,4),%eax
7985 orl (rFP,%ecx,4),%eax
7986 .else
7987 cmpl $0x80000000,(rFP,%ecx,4)
7988 .endif
7989 je .LOP_DOUBLE_TO_LONG_special_case # fix up result
7990
7991.LOP_DOUBLE_TO_LONG_finish:
7992 ADVANCE_PC(1)
7993 GOTO_NEXT
7994
7995.LOP_DOUBLE_TO_LONG_special_case:
7996 fnstsw %ax
7997 sahf
7998 jp .LOP_DOUBLE_TO_LONG_isNaN
7999 adcl $-1,(rFP,%ecx,4)
8000 .if 1
8001 adcl $-1,4(rFP,%ecx,4)
8002 .endif
8003 jmp .LOP_DOUBLE_TO_LONG_finish
8004.LOP_DOUBLE_TO_LONG_isNaN:
8005 movl $0,(rFP,%ecx,4)
8006 .if 1
8007 movl $0,4(rFP,%ecx,4)
8008 .endif
8009 jmp .LOP_DOUBLE_TO_LONG_finish
8010
8011/* continuation for OP_DIV_INT */
8012.LOP_DIV_INT_continue_div:
8013 cltd
8014 idivl %ecx
8015.LOP_DIV_INT_finish_div:
8016 movzbl rINST_HI,%ecx # ecl<- AA
8017 SET_VREG(%eax,%ecx)
8018 UNSPILL(rPC)
8019 FETCH_INST_WORD(2)
8020 ADVANCE_PC(2)
8021 GOTO_NEXT
8022
8023/* continuation for OP_REM_INT */
8024.LOP_REM_INT_continue_div:
8025 cltd
8026 idivl %ecx
8027.LOP_REM_INT_finish_div:
8028 movzbl rINST_HI,%ecx # ecl<- AA
8029 SET_VREG(%edx,%ecx)
8030 UNSPILL(rPC)
8031 FETCH_INST_WORD(2)
8032 ADVANCE_PC(2)
8033 GOTO_NEXT
8034
8035/* continuation for OP_MUL_LONG */
8036
8037.LOP_MUL_LONG_continue:
8038 leal (%ecx,%edx),%edx # full result now in %edx:%eax
8039 movzbl rINST_HI,%ecx # ecx<- A
8040 movl %edx,4(rFP,%ecx,4) # v[B+1]<- %edx
8041 UNSPILL(rPC) # restore rPC/%edx
8042 FETCH_INST_WORD(2)
8043 UNSPILL(rIBASE)
8044 movl %eax,(rFP,%ecx,4) # v[B]<- %eax
8045 ADVANCE_PC(2)
8046 GOTO_NEXT
8047
8048
8049/* continuation for OP_DIV_LONG */
8050
8051.LOP_DIV_LONG_continue:
8052 call __divdi3
8053.LOP_DIV_LONG_finish:
8054 movzbl rINST_HI,%ecx
8055 SET_VREG_WORD(rPC,%ecx,1)
8056 UNSPILL(rPC)
8057 SET_VREG_WORD(%eax,%ecx,0)
8058 FETCH_INST_WORD(2)
8059 ADVANCE_PC(2)
8060 GOTO_NEXT
8061
8062.LOP_DIV_LONG_check_zero:
8063 testl rPC,rPC
8064 jne .LOP_DIV_LONG_notSpecial
8065 UNSPILL(rPC)
8066 jmp common_errDivideByZero
8067.LOP_DIV_LONG_check_neg1:
8068 testl rPC,%eax
8069 jne .LOP_DIV_LONG_notSpecial
8070 GET_VREG_WORD(rPC,%ecx,0)
8071 GET_VREG_WORD(%ecx,%ecx,1)
8072 testl rPC,rPC
8073 jne .LOP_DIV_LONG_notSpecial1
8074 cmpl $0x80000000,%ecx
8075 jne .LOP_DIV_LONG_notSpecial1
8076 /* minint / -1, return minint on div, 0 on rem */
8077 xorl %eax,%eax
8078 movl $0x80000000,%edx
8079 jmp .LOP_DIV_LONG_finish
8080
8081
8082
8083
8084/* continuation for OP_REM_LONG */
8085
8086.LOP_REM_LONG_continue:
8087 call __moddi3
8088.LOP_REM_LONG_finish:
8089 movzbl rINST_HI,%ecx
8090 SET_VREG_WORD(rPC,%ecx,1)
8091 UNSPILL(rPC)
8092 SET_VREG_WORD(%eax,%ecx,0)
8093 FETCH_INST_WORD(2)
8094 ADVANCE_PC(2)
8095 GOTO_NEXT
8096
8097.LOP_REM_LONG_check_zero:
8098 testl rPC,rPC
8099 jne .LOP_REM_LONG_notSpecial
8100 UNSPILL(rPC)
8101 jmp common_errDivideByZero
8102.LOP_REM_LONG_check_neg1:
8103 testl rPC,%eax
8104 jne .LOP_REM_LONG_notSpecial
8105 GET_VREG_WORD(rPC,%ecx,0)
8106 GET_VREG_WORD(%ecx,%ecx,1)
8107 testl rPC,rPC
8108 jne .LOP_REM_LONG_notSpecial1
8109 cmpl $0x80000000,%ecx
8110 jne .LOP_REM_LONG_notSpecial1
8111 /* minint / -1, return minint on div, 0 on rem */
8112 xorl %eax,%eax
8113 movl $0,%edx
8114 jmp .LOP_REM_LONG_finish
8115
8116
8117
8118
8119/* continuation for OP_SHL_LONG */
8120
8121.LOP_SHL_LONG_finish:
8122 SET_VREG_WORD(%eax,%ecx,0) # v[AA+0]<- %eax
8123 ADVANCE_PC(2)
8124 GOTO_NEXT
8125
8126/* continuation for OP_SHR_LONG */
8127
8128
8129.LOP_SHR_LONG_finish:
8130 SET_VREG_WORD(%eax,%ecx,0) # v[AA+0]<- eax
8131 ADVANCE_PC(2)
8132 GOTO_NEXT
8133
8134/* continuation for OP_USHR_LONG */
8135
8136
8137.LOP_USHR_LONG_finish:
8138 SET_VREG_WORD(%eax,%ecx,0) # v[BB+0]<- eax
8139 FETCH_INST_WORD(2)
8140 ADVANCE_PC(2)
8141 GOTO_NEXT
8142
8143/* continuation for OP_DIV_INT_2ADDR */
8144.LOP_DIV_INT_2ADDR_continue_div2addr:
8145 cltd
8146 idivl %ecx
8147.LOP_DIV_INT_2ADDR_finish_div2addr:
8148 SET_VREG(%eax,rINST_FULL)
8149 UNSPILL(rPC)
8150 FETCH_INST_WORD(1)
8151 ADVANCE_PC(1)
8152 GOTO_NEXT
8153
8154/* continuation for OP_REM_INT_2ADDR */
8155.LOP_REM_INT_2ADDR_continue_div2addr:
8156 cltd
8157 idivl %ecx
8158.LOP_REM_INT_2ADDR_finish_div2addr:
8159 SET_VREG(%edx,rINST_FULL)
8160 UNSPILL(rPC)
8161 FETCH_INST_WORD(1)
8162 ADVANCE_PC(1)
8163 GOTO_NEXT
8164
8165/* continuation for OP_MUL_LONG_2ADDR */
8166
8167.LOP_MUL_LONG_2ADDR_continue:
8168 leal (%ecx,%edx),%edx # full result now in %edx:%eax
8169 movl %edx,4(rIBASE) # v[A+1]<- %edx
8170 UNSPILL(rPC) # restore rPC/%edx
8171 FETCH_INST_WORD(1)
8172 movl %eax,(rIBASE) # v[A]<- %eax
8173 UNSPILL(rFP)
8174 UNSPILL(rIBASE)
8175 ADVANCE_PC(1)
8176 GOTO_NEXT
8177
8178
8179/* continuation for OP_DIV_LONG_2ADDR */
8180
8181.LOP_DIV_LONG_2ADDR_continue:
8182 movl %eax,OUT_ARG3(%esp)
8183 movl rPC,OUT_ARG0(%esp)
8184 movl %ecx,OUT_ARG1(%esp)
8185 call __divdi3
8186.LOP_DIV_LONG_2ADDR_finish:
8187 movl rINST_FULL,%ecx
8188 SET_VREG_WORD(rPC,%ecx,1)
8189 UNSPILL(rPC)
8190 SET_VREG_WORD(%eax,%ecx,0)
8191 FETCH_INST_WORD(1)
8192 ADVANCE_PC(1)
8193 GOTO_NEXT
8194
8195.LOP_DIV_LONG_2ADDR_check_zero:
8196 testl rPC,rPC
8197 jne .LOP_DIV_LONG_2ADDR_notSpecial
8198 UNSPILL(rPC)
8199 jmp common_errDivideByZero
8200.LOP_DIV_LONG_2ADDR_check_neg1:
8201 testl rPC,%eax
8202 jne .LOP_DIV_LONG_2ADDR_notSpecial
8203 GET_VREG_WORD(rPC,rINST_FULL,0)
8204 GET_VREG_WORD(%ecx,rINST_FULL,1)
8205 testl rPC,rPC
8206 jne .LOP_DIV_LONG_2ADDR_notSpecial1
8207 cmpl $0x80000000,%ecx
8208 jne .LOP_DIV_LONG_2ADDR_notSpecial1
8209 /* minint / -1, return minint on div, 0 on rem */
8210 xorl %eax,%eax
8211 movl $0x80000000,%edx
8212 jmp .LOP_DIV_LONG_2ADDR_finish
8213
8214
8215/* continuation for OP_REM_LONG_2ADDR */
8216
8217.LOP_REM_LONG_2ADDR_continue:
8218 movl %eax,OUT_ARG3(%esp)
8219 movl rPC,OUT_ARG0(%esp)
8220 movl %ecx,OUT_ARG1(%esp)
8221 call __moddi3
8222.LOP_REM_LONG_2ADDR_finish:
8223 movl rINST_FULL,%ecx
8224 SET_VREG_WORD(rPC,%ecx,1)
8225 UNSPILL(rPC)
8226 SET_VREG_WORD(%eax,%ecx,0)
8227 FETCH_INST_WORD(1)
8228 ADVANCE_PC(1)
8229 GOTO_NEXT
8230
8231.LOP_REM_LONG_2ADDR_check_zero:
8232 testl rPC,rPC
8233 jne .LOP_REM_LONG_2ADDR_notSpecial
8234 UNSPILL(rPC)
8235 jmp common_errDivideByZero
8236.LOP_REM_LONG_2ADDR_check_neg1:
8237 testl rPC,%eax
8238 jne .LOP_REM_LONG_2ADDR_notSpecial
8239 GET_VREG_WORD(rPC,rINST_FULL,0)
8240 GET_VREG_WORD(%ecx,rINST_FULL,1)
8241 testl rPC,rPC
8242 jne .LOP_REM_LONG_2ADDR_notSpecial1
8243 cmpl $0x80000000,%ecx
8244 jne .LOP_REM_LONG_2ADDR_notSpecial1
8245 /* minint / -1, return minint on div, 0 on rem */
8246 xorl %eax,%eax
8247 movl $0,%edx
8248 jmp .LOP_REM_LONG_2ADDR_finish
8249
8250
8251/* continuation for OP_SHL_LONG_2ADDR */
8252
8253
8254.LOP_SHL_LONG_2ADDR_finish:
8255 SET_VREG_WORD(%eax,rINST_FULL,0) # v[AA+0]<- eax
8256 FETCH_INST_WORD(1)
8257 ADVANCE_PC(1)
8258 GOTO_NEXT
8259
8260/* continuation for OP_SHR_LONG_2ADDR */
8261
8262
8263.LOP_SHR_LONG_2ADDR_finish:
8264 SET_VREG_WORD(%eax,rINST_FULL,0) # v[AA+0]<- eax
8265 FETCH_INST_WORD(1)
8266 ADVANCE_PC(1)
8267 GOTO_NEXT
8268
8269/* continuation for OP_USHR_LONG_2ADDR */
8270
8271
8272.LOP_USHR_LONG_2ADDR_finish:
8273 SET_VREG_WORD(%eax,rINST_FULL,0) # v[AA+0]<- eax
8274 FETCH_INST_WORD(1)
8275 ADVANCE_PC(1)
8276 GOTO_NEXT
8277
8278/* continuation for OP_DIV_INT_LIT16 */
8279.LOP_DIV_INT_LIT16_continue_div:
8280 cltd
8281 idivl %ecx
8282.LOP_DIV_INT_LIT16_finish_div:
8283 SET_VREG(%eax,rINST_FULL)
8284 UNSPILL(rPC)
8285 FETCH_INST_WORD(2)
8286 ADVANCE_PC(2)
8287 GOTO_NEXT
8288
8289/* continuation for OP_REM_INT_LIT16 */
8290.LOP_REM_INT_LIT16_continue_div:
8291 cltd
8292 idivl %ecx
8293.LOP_REM_INT_LIT16_finish_div:
8294 SET_VREG(%edx,rINST_FULL)
8295 UNSPILL(rPC)
8296 FETCH_INST_WORD(2)
8297 ADVANCE_PC(2)
8298 GOTO_NEXT
8299
8300/* continuation for OP_DIV_INT_LIT8 */
8301.LOP_DIV_INT_LIT8_continue_div:
8302 cltd
8303 idivl %ecx
8304.LOP_DIV_INT_LIT8_finish_div:
8305 SET_VREG(%eax,rINST_FULL)
8306 UNSPILL(rPC)
8307 FETCH_INST_WORD(2)
8308 ADVANCE_PC(2)
8309 GOTO_NEXT
8310
8311/* continuation for OP_REM_INT_LIT8 */
8312.LOP_REM_INT_LIT8_continue_div:
8313 cltd
8314 idivl %ecx
8315.LOP_REM_INT_LIT8_finish_div:
8316 SET_VREG(%edx,rINST_FULL)
8317 UNSPILL(rPC)
8318 FETCH_INST_WORD(2)
8319 ADVANCE_PC(2)
8320 GOTO_NEXT
8321
8322/* continuation for OP_EXECUTE_INLINE */
8323
8324.LOP_EXECUTE_INLINE_continue:
8325 /*
8326 * Extract args, call function.
8327 * ecx = #of args (0-4)
8328 * eax = call index
8329 * @esp = return addr
8330 * esp is -4 from normal
8331 *
8332 * Go ahead and load all 4 args, even if not used.
8333 */
8334 movzwl 4(rPC),rPC
8335
8336 movl $0xf,%ecx
8337 andl rPC,%ecx
8338 GET_VREG(%ecx,%ecx)
8339 sarl $4,rPC
8340 movl %ecx,4+OUT_ARG0(%esp)
8341
8342 movl $0xf,%ecx
8343 andl rPC,%ecx
8344 GET_VREG(%ecx,%ecx)
8345 sarl $4,rPC
8346 movl %ecx,4+OUT_ARG1(%esp)
8347
8348 movl $0xf,%ecx
8349 andl rPC,%ecx
8350 GET_VREG(%ecx,%ecx)
8351 sarl $4,rPC
8352 movl %ecx,4+OUT_ARG2(%esp)
8353
8354 movl $0xf,%ecx
8355 andl rPC,%ecx
8356 GET_VREG(%ecx,%ecx)
8357 sarl $4,rPC
8358 movl %ecx,4+OUT_ARG3(%esp)
8359
8360 sall $4,%eax # index *= sizeof(table entry)
8361 jmp *gDvmInlineOpsTable(%eax)
8362 # will return to caller of .LOP_EXECUTE_INLINE_continue
8363
8364
8365 .size dvmAsmSisterStart, .-dvmAsmSisterStart
8366 .global dvmAsmSisterEnd
8367dvmAsmSisterEnd:
8368
8369/* File: x86/entry.S */
8370/*
8371 * Copyright (C) 2008 The Android Open Source Project
8372 *
8373 * Licensed under the Apache License, Version 2.0 (the "License");
8374 * you may not use this file except in compliance with the License.
8375 * You may obtain a copy of the License at
8376 *
8377 * http://www.apache.org/licenses/LICENSE-2.0
8378 *
8379 * Unless required by applicable law or agreed to in writing, software
8380 * distributed under the License is distributed on an "AS IS" BASIS,
8381 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8382 * See the License for the specific language governing permissions and
8383 * limitations under the License.
8384 */
8385
8386
8387 .text
8388 .global dvmMterpStdRun
8389 .type dvmMterpStdRun, %function
8390/*
8391 * bool dvmMterpStdRun(MterpGlue* glue)
8392 *
8393 * Interpreter entry point. Returns changeInterp.
8394 *
8395 */
8396dvmMterpStdRun:
8397 push %ebp
8398 movl %esp,%ebp
8399 push %edi
8400 push %esi
8401 push %ebx
8402
8403/* at this point, stack is misaligned by 1 word
8404 We're allocating spill space for 6 words, plus
8405 outgoing argument (5 words) and local variables
8406 (4 words) - 15 words or 60 bytes total. See
8407 diagram in header.S
8408*/
8409 subl $60,%esp
8410
8411/* Set up "named" registers */
8412 movl IN_ARG0(%ebp),%ecx
8413 movl %ecx,rGLUE_SPILL(%ebp)
8414 LOAD_PC_FROM_GLUE(%ecx)
8415 LOAD_FP_FROM_GLUE(%ecx)
8416 movl $dvmAsmInstructionStart,rIBASE
8417
8418/* Remember %esp for future "longjmp" */
8419 movl %esp,offGlue_bailPtr(%ecx)
8420
8421/* How to start? */
8422 movb offGlue_entryPoint(%ecx),%al
8423
8424/* Normal start? */
8425 cmpb $kInterpEntryInstr,%al
8426 jne .Lnot_instr
8427
8428 /* Normal case: start executing the instruction at rPC */
8429 FETCH_INST()
8430 GOTO_NEXT
8431
8432.Lnot_instr:
8433 /* Reset to normal case */
8434 movb $kInterpEntryInstr,offGlue_entryPoint(%ecx)
8435 cmpb $kInterpEntryReturn,%al
8436 je common_returnFromMethod
8437 cmpb $kInterpEntryThrow,%al
8438 je common_exceptionThrown
8439 movzx %al,%eax
8440 movl %eax,OUT_ARG1(%esp)
8441 movl $.LstrBadEntryPoint,OUT_ARG0(%esp)
8442 call printf
8443 call dvmAbort
8444 /* Not reached */
8445
8446
8447 .global dvmMterpStdBail
8448 .type dvmMterpStdBail, %function
8449/*
8450 * void dvmMterpStdBail(MterpGlue* glue, bool changeInterp)
8451 *
8452 * Restore the stack pointer and PC from the save point established on entry.
8453 * This is essentially the same as a longjmp, but should be cheaper. The
8454 * last instruction causes us to return to whoever called dvmMterpStdRun.
8455 *
8456 * We're not going to build a standard frame here, so the arg accesses will
8457 * look a little strange.
8458 *
8459 * On entry:
8460 * esp+4 (arg0) MterpGlue* glue
8461 * esp+8 (arg1) bool changeInterp
8462 */
8463dvmMterpStdBail:
8464 movl 4(%esp),%ecx # grab glue
8465 movl 8(%esp),%eax # changeInterp to return reg
8466 movl offGlue_bailPtr(%ecx),%esp # Stack back to normal
8467 addl $60,%esp # Strip dvmMterpStdRun's frame
8468 pop %ebx
8469 pop %esi
8470 pop %edi
8471 pop %ebp
8472 ret # return to dvmMterpStdRun's caller
8473
8474
8475/*
8476 * Strings
8477 */
8478 .section .rodata
8479.LstrBadEntryPoint:
8480 .asciz "Bad entry point %d\n"
8481
8482/* File: x86/footer.S */
8483/*
8484 * Copyright (C) 2008 The Android Open Source Project
8485 *
8486 * Licensed under the Apache License, Version 2.0 (the "License");
8487 * you may not use this file except in compliance with the License.
8488 * You may obtain a copy of the License at
8489 *
8490 * http://www.apache.org/licenses/LICENSE-2.0
8491 *
8492 * Unless required by applicable law or agreed to in writing, software
8493 * distributed under the License is distributed on an "AS IS" BASIS,
8494 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8495 * See the License for the specific language governing permissions and
8496 * limitations under the License.
8497 */
8498/*
8499 * Common subroutines and data.
8500 */
8501
8502/*
8503 * Common code when a backwards branch is taken
8504 *
8505 * On entry:
8506 * ebx (a.k.a. rINST_FULL) -> PC adjustment in 16-bit words
8507 */
8508common_backwardBranch:
8509 GET_GLUE(%ecx)
Johnnie Birchc4080f62009-02-10 15:41:06 -08008510 call common_periodicChecks # Note: expects rPC to be preserved
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08008511 ADVANCE_PC_INDEXED(rINST_FULL)
8512 FETCH_INST()
8513 GOTO_NEXT
8514
Johnnie Birchc4080f62009-02-10 15:41:06 -08008515
8516
8517/*
8518 * Common code for method invocation with range.
8519 *
8520 * On entry:
8521 * eax = Method* methodToCall
8522 * rINST trashed, must reload
8523 */
8524
8525common_invokeMethodRange:
8526.LinvokeNewRange:
8527
8528 /*
8529 * prepare to copy args to "outs" area of current frame
8530 */
8531
8532 movzbl 1(rPC),rINST_FULL # rINST_FULL<- AA
8533 movzwl 4(rPC), %ecx # %ecx<- CCCC
8534 SPILL(rPC)
8535 SAVEAREA_FROM_FP(%edx,rFP) # %edx<- &StackSaveArea
8536 test rINST_FULL, rINST_FULL
8537 movl rINST_FULL, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- AA
8538 jz .LinvokeArgsDone # no args; jump to args done
8539
8540
8541 /*
8542 * %eax=methodToCall, %ecx=CCCC, LOCAL0_OFFSET(%ebp)=count, %edx=&outs (&stackSaveArea)
8543 * (very few methods have > 10 args; could unroll for common cases)
8544 */
8545
8546 movl %ebx, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- save %ebx
8547 lea (rFP, %ecx, 4), %ecx # %ecx<- &vCCCC
8548 shll $2, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- offset
8549 subl LOCAL0_OFFSET(%ebp), %edx # %edx<- update &outs
8550 shrl $2, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- offset
85511:
8552 movl (%ecx), %ebx # %ebx<- vCCCC
8553 lea 4(%ecx), %ecx # %ecx<- &vCCCC++
8554 subl $1, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET<- LOCAL0_OFFSET--
8555 movl %ebx, (%edx) # *outs<- vCCCC
8556 lea 4(%edx), %edx # outs++
8557 jne 1b # loop if count (LOCAL0_OFFSET(%ebp)) not zero
8558 movl LOCAL1_OFFSET(%ebp), %ebx # %ebx<- restore %ebx
8559 jmp .LinvokeArgsDone # continue
8560
8561 /*
8562 * %eax is "Method* methodToCall", the method we're trying to call
8563 * prepare to copy args to "outs" area of current frame
8564 */
8565
8566common_invokeMethodNoRange:
8567.LinvokeNewNoRange:
8568 movzbl 1(rPC),rINST_FULL # rINST_FULL<- BA
8569 SPILL(rPC)
8570 movl rINST_FULL, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- BA
8571 shrl $4, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- B
8572 je .LinvokeArgsDone # no args; jump to args done
8573 movzwl 4(rPC), %ecx # %ecx<- GFED
8574 SAVEAREA_FROM_FP(%edx,rFP) # %edx<- &StackSaveArea
8575
8576 /*
8577 * %eax=methodToCall, %ecx=GFED, LOCAL0_OFFSET(%ebp)=count, %edx=outs
8578 */
8579
8580.LinvokeNonRange:
8581 cmp $2, LOCAL0_OFFSET(%ebp) # compare LOCAL0_OFFSET(%ebp) to 2
8582 movl %ecx, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- GFED
8583 jl 1f # handle 1 arg
8584 je 2f # handle 2 args
8585 cmp $4, LOCAL0_OFFSET(%ebp) # compare LOCAL0_OFFSET(%ebp) to 4
8586 jl 3f # handle 3 args
8587 je 4f # handle 4 args
85885:
8589 andl $15, rINST_FULL # rINST<- A
8590 lea -4(%edx), %edx # %edx<- update &outs; &outs--
8591 movl (rFP, rINST_FULL, 4), %ecx # %ecx<- vA
8592 movl %ecx, (%edx) # *outs<- vA
8593 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED
85944:
8595 shr $12, %ecx # %ecx<- G
8596 lea -4(%edx), %edx # %edx<- update &outs; &outs--
8597 movl (rFP, %ecx, 4), %ecx # %ecx<- vG
8598 movl %ecx, (%edx) # *outs<- vG
8599 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED
86003:
8601 and $0x0f00, %ecx # %ecx<- 0F00
8602 shr $8, %ecx # %ecx<- F
8603 lea -4(%edx), %edx # %edx<- update &outs; &outs--
8604 movl (rFP, %ecx, 4), %ecx # %ecx<- vF
8605 movl %ecx, (%edx) # *outs<- vF
8606 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED
86072:
8608 and $0x00f0, %ecx # %ecx<- 00E0
8609 shr $4, %ecx # %ecx<- E
8610 lea -4(%edx), %edx # %edx<- update &outs; &outs--
8611 movl (rFP, %ecx, 4), %ecx # %ecx<- vE
8612 movl %ecx, (%edx) # *outs<- vE
8613 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED
86141:
8615 and $0x000f, %ecx # %ecx<- 000D
8616 movl (rFP, %ecx, 4), %ecx # %ecx<- vD
8617 movl %ecx, -4(%edx) # *--outs<- vD
86180:
8619
8620 /*
8621 * %eax is "Method* methodToCall", the method we're trying to call
8622 * find space for the new stack frame, check for overflow
8623 */
8624
8625.LinvokeArgsDone:
8626 movzwl offMethod_registersSize(%eax), %edx # %edx<- methodToCall->regsSize
8627 movzwl offMethod_outsSize(%eax), %ecx # %ecx<- methodToCall->outsSize
8628 movl %eax, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET<- methodToCall
8629 shl $2, %edx # %edx<- update offset
8630 SAVEAREA_FROM_FP(%eax,rFP) # %eax<- &StackSaveArea
8631 subl %edx, %eax # %eax<- newFP; (old savearea - regsSize)
8632 GET_GLUE(%edx) # %edx<- pMterpGlue
8633 movl %eax, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- &outs
8634 subl $sizeofStackSaveArea, %eax # %eax<- newSaveArea (stack save area using newFP)
8635 movl offGlue_interpStackEnd(%edx), %edx # %edx<- glue->interpStackEnd
8636 movl %edx, LOCAL2_OFFSET(%ebp) # LOCAL2_OFFSET<- glue->interpStackEnd
8637 shl $2, %ecx # %ecx<- update offset for outsSize
8638 movl %eax, %edx # %edx<- newSaveArea
8639 sub %ecx, %eax # %eax<- bottom; (newSaveArea - outsSize)
8640 cmp LOCAL2_OFFSET(%ebp), %eax # compare interpStackEnd and bottom
8641 movl LOCAL0_OFFSET(%ebp), %eax # %eax<- restore methodToCall
8642 jl .LstackOverflow # handle frame overflow
8643
8644 /*
8645 * set up newSaveArea
8646 */
8647
8648#ifdef EASY_GDB
8649 SAVEAREA_FROM_FP(%ecx,rFP) # %ecx<- &StackSaveArea
8650 movl %ecx, offStackSaveArea_prevSave(%edx) # newSaveArea->prevSave<- &outs
8651#endif
8652 movl rFP, offStackSaveArea_prevFrame(%edx) # newSaveArea->prevFrame<- rFP
8653 movl rPC_SPILL(%ebp), %ecx
8654 movl %ecx, offStackSaveArea_savedPc(%edx) # newSaveArea->savedPc<- rPC
8655 testl $ACC_NATIVE, offMethod_accessFlags(%eax) # check for native call
8656 movl %eax, offStackSaveArea_method(%edx) # newSaveArea->method<- method to call
8657 jne .LinvokeNative # handle native call
8658
8659 /*
8660 * Update "glue" values for the new method
8661 * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFp
8662 */
8663
8664 movl offMethod_clazz(%eax), %edx # %edx<- method->clazz
8665 GET_GLUE(%ecx) # %ecx<- pMterpGlue
8666 movl offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex
8667 movl %eax, offGlue_method(%ecx) # glue->method<- methodToCall
8668 movl %edx, offGlue_methodClassDex(%ecx) # glue->methodClassDex<- method->clazz->pDvmDex
8669 movl offMethod_insns(%eax), rPC # rPC<- methodToCall->insns
8670 movl offGlue_self(%ecx), %eax # %eax<- glue->self
8671 movl LOCAL1_OFFSET(%ebp), rFP # rFP<- newFP
8672 movl rFP, offThread_curFrame(%eax) # glue->self->curFrame<- newFP
8673 FETCH_INST()
8674 GOTO_NEXT # jump to methodToCall->insns
8675
8676 /*
8677 * Prep for the native call
8678 * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFP, %edx=newSaveArea
8679 */
8680
8681.LinvokeNative:
8682 GET_GLUE(%ecx) # %ecx<- pMterpGlue
8683 movl %eax, OUT_ARG1(%esp) # push parameter methodToCall
8684 movl offGlue_self(%ecx), %ecx # %ecx<- glue->self
8685 movl offThread_jniLocal_nextEntry(%ecx), %eax # %eax<- glue->self->thread->refNext
8686 movl %eax, offStackSaveArea_localRefTop(%edx) # newSaveArea->localRefTop<- refNext
8687 movl %edx, OUT_ARG4(%esp) # save newSaveArea
8688 movl LOCAL1_OFFSET(%ebp), %edx # %edx<- newFP
8689 movl %edx, offThread_curFrame(%ecx) # glue->self->curFrame<- newFP
8690 movl %ecx, OUT_ARG3(%esp) # save glue->self
8691 movl %ecx, OUT_ARG2(%esp) # push parameter glue->self
8692 GET_GLUE(%ecx) # %ecx<- pMterpGlue
8693 movl OUT_ARG1(%esp), %eax # %eax<- methodToCall
8694 lea offGlue_retval(%ecx), %ecx # %ecx<- &retval
8695 movl %ecx, OUT_ARG0(%esp) # push parameter pMterpGlue
8696 push %edx # push parameter newFP
8697
8698 call *offMethod_nativeFunc(%eax) # call methodToCall->nativeFunc
8699 lea 4(%esp), %esp
8700 movl OUT_ARG4(%esp), %ecx # %ecx<- newSaveArea
8701 movl OUT_ARG3(%esp), %eax # %eax<- glue->self
8702 movl offStackSaveArea_localRefTop(%ecx), %edx # %edx<- newSaveArea->localRefTop
8703 cmp $0, offThread_exception(%eax) # check for exception
8704 movl rFP, offThread_curFrame(%eax) # glue->self->curFrame<- rFP
8705 movl %edx, offThread_jniLocal_nextEntry(%eax) # glue->self<- newSaveArea->localRefTop
8706 UNSPILL(rPC)
8707 jne common_exceptionThrown # handle exception
8708 FETCH_INST_WORD(3)
8709 ADVANCE_PC(3)
8710 GOTO_NEXT # jump to next instruction
8711
8712.LstackOverflow:
8713 GET_GLUE(%eax) # %eax<- pMterpGlue
8714 movl offGlue_self(%eax), %eax # %eax<- glue->self
8715 movl %eax, OUT_ARG0(%esp) # push parameter self
8716 call dvmHandleStackOverflow # call: (Thread* self)
8717 UNSPILL(rPC) # return: void
8718 jmp common_exceptionThrown # handle exception
8719
8720
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08008721/*
8722 * Common invoke code (old-style).
8723 * TUNING: Rewrite along lines of new armv5 code?
8724 *
8725 * On entry:
8726 * eax = Method* methodToCall
8727 * ecx = bool methodCallRange
8728 * rINST trashed, must reload
8729 */
8730common_invokeOld:
8731 movl %ecx,OUT_ARG1(%esp) # arg1<- methodCallRange
8732 GET_GLUE(%ecx)
8733 movzwl (rPC),rINST_FULL # recover rINST
8734 movl %eax,OUT_ARG2(%esp) # arg2<- method
8735 movzwl 4(rPC),%eax # eax<- GFED or CCCC
8736 SAVE_PC_TO_GLUE(%ecx)
8737 SAVE_FP_TO_GLUE(%ecx)
8738 movzbl rINST_HI,rINST_FULL
8739 movl rINST_FULL,OUT_ARG3(%esp)# arg3<- AA
8740 movl %ecx,OUT_ARG0(%esp) # arg0<- GLUE
8741 movl %eax,OUT_ARG4(%esp) # arg4<- GFED/CCCC
8742 call dvmMterp_invokeMethod
8743 jmp common_resumeAfterGlueCall
8744
8745
8746/*
8747 * Do we need the thread to be suspended or have debugger/profiling activity?
8748 *
8749 * On entry:
8750 * ebx -> PC adjustment in 16-bit words (must be preserved)
8751 * ecx -> GLUE pointer
8752 *
8753 * Note: A call will normally kill %eax, rPC/%edx and %ecx. To
8754 * streamline the normal case, this routine will preserve rPC and
8755 * %ecx in addition to the normal caller save regs. The save/restore
8756 * is a bit ugly, but will happen in the relatively uncommon path.
8757 * TUNING: Might be worthwhile to inline this.
8758 * TODO: Basic-block style Jit will need a hook here as well. Fold it into
8759 * the suspendCount check so we can get both in 1 shot.
8760 */
8761common_periodicChecks:
8762 movl offGlue_pSelfSuspendCount(%ecx),%eax # eax <- &suspendCount
8763 cmpl $0,(%eax)
8764 jne 1f
8765
8766#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
8767#if defined(WITH_DEBUGGER)
8768 movl offGlue_pDebuggerActive(%ecx),%eax # eax <- &DebuggerActive
8769#endif
8770#if defined(WITH_PROFILER)
8771 movl offGlue_pActiveProfilers(%ecx),%ecx # ecx <- &ActiveProfilers
8772#endif
8773#if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
8774 movzbl (%eax),%eax # eax <- debuggerActive (boolean)
8775 orl (%ecx),%eax # eax <- debuggerActive || activeProfilers
8776#elif defined(WITH_DEBUGGER)
8777 movzbl (%eax),%eax # eax <- debuggerActive (boolean)
8778#elif defined(WITH_PROFILER)
8779 movl (%ecx),%eax # eax <= activeProfilers
8780#endif
8781 GET_GLUE(%ecx) # restore rGLUE
8782 testl %eax,%eax
8783 jne 3f # one or both active - switch interp
8784#endif
8785
8786 ret
8787
8788 /* Check for suspend */
87891:
8790 /* At this point, the return pointer to the caller of
8791 * common_periodicChecks is on the top of stack. We need to preserve
8792 * rPC(edx) and GLUE(ecx). We'll spill rPC, and reload GLUE.
8793 * The outgoing profile is:
8794 * bool dvmCheckSuspendPending(Thread* self)
8795 * Because we reached here via a call, go ahead and build a new frame.
8796 */
The Android Open Source Project99409882009-03-18 22:20:24 -07008797 EXPORT_PC() # need for precise GC
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08008798 movl offGlue_self(%ecx),%eax # eax<- glue->self
8799 SPILL(rPC) # save edx
8800 push %ebp
8801 movl %esp,%ebp
8802 subl $24,%esp
8803 movl %eax,OUT_ARG0(%esp)
8804 call dvmCheckSuspendPending
8805 addl $24,%esp
8806 pop %ebp
8807 UNSPILL(rPC)
8808 GET_GLUE(%ecx)
8809 ret
8810
8811 /* Switch interpreters */
8812 /* Note: %ebx contains the 16-bit word offset to be applied to rPC to
8813 * "complete" the interpretation of backwards branches. In effect, we
8814 * are completing the interpretation of the branch instruction here,
8815 * and the new interpreter will resume interpretation at the branch
8816 * target. However, a switch request recognized during the handling
8817 * of a return from method instruction results in an immediate abort,
8818 * and the new interpreter will resume by re-interpreting the return
8819 * instruction.
8820 */
88213:
8822 leal (rPC,%ebx,2),rPC # adjust pc to show target
8823 GET_GLUE(%ecx) # bail expect GLUE already loaded
8824 movl $1,rINST_FULL # set changeInterp to true
8825 jmp common_gotoBail
8826
8827
8828/*
8829 * Common code for handling a return instruction
8830 */
8831common_returnFromMethod:
8832 GET_GLUE(%ecx)
8833 /* Set entry mode in case we bail */
8834 movb $kInterpEntryReturn,offGlue_entryPoint(%ecx)
8835 xorl rINST_FULL,rINST_FULL # zero offset in case we switch interps
8836 call common_periodicChecks # Note: expects %ecx to be preserved
8837
8838 SAVEAREA_FROM_FP(%eax,rFP) # eax<- saveArea (old)
8839 movl offStackSaveArea_prevFrame(%eax),rFP # rFP<- prevFrame
8840 movl (offStackSaveArea_method-sizeofStackSaveArea)(rFP),rINST_FULL
8841 cmpl $0,rINST_FULL # break?
8842 je common_gotoBail # break frame, bail out completely
8843
8844 movl offStackSaveArea_savedPc(%eax),rPC # pc<- saveArea->savedPC
8845 movl offGlue_self(%ecx),%eax # eax<- self
8846 movl rINST_FULL,offGlue_method(%ecx) # glue->method = newSave->meethod
8847 movl rFP,offThread_curFrame(%eax) # self->curFrame = fp
8848 movl offMethod_clazz(rINST_FULL),%eax # eax<- method->clazz
8849 FETCH_INST_WORD(3)
8850 movl offClassObject_pDvmDex(%eax),%eax # eax<- method->clazz->pDvmDex
8851 ADVANCE_PC(3)
8852 movl %eax,offGlue_methodClassDex(%ecx)
8853 /* not bailing - restore entry mode to default */
8854 movb $kInterpEntryInstr,offGlue_entryPoint(%ecx)
8855 GOTO_NEXT
8856
8857/*
8858 * Prepare to strip the current frame and "longjump" back to caller of
8859 * dvmMterpStdRun.
8860 *
8861 * on entry:
8862 * rINST_FULL holds changeInterp
8863 * ecx holds glue pointer
8864 *
8865 * expected profile: dvmMterpStdBail(MterpGlue *glue, bool changeInterp)
8866 */
8867common_gotoBail:
8868 SAVE_PC_TO_GLUE(%ecx) # export state to glue
8869 SAVE_FP_TO_GLUE(%ecx)
8870 movl %ecx,OUT_ARG0(%esp) # glue in arg0
8871 movl rINST_FULL,OUT_ARG1(%esp) # changeInterp in arg1
8872 call dvmMterpStdBail # bail out....
8873
8874
8875/*
8876 * After returning from a "glued" function, pull out the updated values
8877 * and start executing at the next instruction.
8878 */
8879 common_resumeAfterGlueCall:
8880 GET_GLUE(%ecx)
8881 LOAD_PC_FROM_GLUE(%ecx)
8882 LOAD_FP_FROM_GLUE(%ecx)
8883 FETCH_INST()
8884 GOTO_NEXT
8885
8886/*
8887 * Integer divide or mod by zero
8888 */
8889common_errDivideByZero:
8890 EXPORT_PC()
8891 movl $.LstrArithmeticException,%eax
8892 movl %eax,OUT_ARG0(%esp)
8893 movl $.LstrDivideByZero,%eax
8894 movl %eax,OUT_ARG1(%esp)
8895 SPILL(rPC)
8896 call dvmThrowException
8897 UNSPILL(rPC)
8898 jmp common_exceptionThrown
8899
8900/*
8901 * Attempt to allocate an array with a negative size.
8902 */
8903common_errNegativeArraySize:
8904 EXPORT_PC()
8905 movl $.LstrNegativeArraySizeException,%eax
8906 movl %eax,OUT_ARG0(%esp)
8907 xorl %eax,%eax
8908 movl %eax,OUT_ARG1(%esp)
8909 SPILL(rPC)
8910 call dvmThrowException
8911 UNSPILL(rPC)
8912 jmp common_exceptionThrown
8913
8914/*
8915 * Attempt to allocate an array with a negative size.
8916 */
8917common_errNoSuchMethod:
8918
8919 EXPORT_PC()
8920 movl $.LstrNoSuchMethodError,%eax
8921 movl %eax,OUT_ARG0(%esp)
8922 xorl %eax,%eax
8923 movl %eax,OUT_ARG1(%esp)
8924 SPILL(rPC)
8925 call dvmThrowException
8926 UNSPILL(rPC)
8927 jmp common_exceptionThrown
8928
8929/*
8930 * Hit a null object when we weren't expecting one. Export the PC, throw a
8931 * NullPointerException and goto the exception processing code.
8932 */
8933common_errNullObject:
8934 EXPORT_PC()
8935 movl $.LstrNullPointerException,%eax
8936 movl %eax,OUT_ARG0(%esp)
8937 xorl %eax,%eax
8938 movl %eax,OUT_ARG1(%esp)
8939 SPILL(rPC)
8940 call dvmThrowException
8941 UNSPILL(rPC)
8942 jmp common_exceptionThrown
8943
8944/*
8945 * Array index exceeds max.
8946 */
8947common_errArrayIndex:
8948 EXPORT_PC()
8949 movl $.LstrArrayIndexException,%eax
8950 movl %eax,OUT_ARG0(%esp)
8951 xorl %eax,%eax
8952 movl %eax,OUT_ARG1(%esp)
8953 SPILL(rPC)
8954 call dvmThrowException
8955 UNSPILL(rPC)
8956 jmp common_exceptionThrown
8957/*
8958 * Invalid array value.
8959 */
8960common_errArrayStore:
8961 EXPORT_PC()
8962 movl $.LstrArrayStoreException,%eax
8963 movl %eax,OUT_ARG0(%esp)
8964 xorl %eax,%eax
8965 movl %eax,OUT_ARG1(%esp)
8966 SPILL(rPC)
8967 call dvmThrowException
8968 UNSPILL(rPC)
8969 jmp common_exceptionThrown
8970
8971/*
8972 * Somebody has thrown an exception. Handle it.
8973 *
8974 * If the exception processing code returns to us (instead of falling
8975 * out of the interpreter), continue with whatever the next instruction
8976 * now happens to be.
8977 *
8978 * This does not return.
8979 */
8980common_exceptionThrown:
8981 GET_GLUE(%ecx)
8982 SAVE_PC_TO_GLUE(%ecx)
8983 SAVE_FP_TO_GLUE(%ecx)
8984 movl %ecx,OUT_ARG0(%esp)
8985 call dvmMterp_exceptionThrown
8986 jmp common_resumeAfterGlueCall
8987
8988common_abort:
8989 movl $0xdeadf00d,%eax
8990 call *%eax
8991
8992
8993/*
8994 * Strings
8995 */
8996
8997 .section .rodata
8998.LstrNullPointerException:
8999 .asciz "Ljava/lang/NullPointerException;"
9000.LstrArithmeticException:
9001 .asciz "Ljava/lang/ArithmeticException;"
9002.LstrDivideByZero:
9003 .asciz "divide by zero"
9004.LstrArrayIndexException:
9005 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;"
9006.LstrArrayStoreException:
9007 .asciz "Ljava/lang/ArrayStoreException;"
9008.LstrNegativeArraySizeException:
9009 .asciz "Ljava/lang/NegativeArraySizeException;"
9010.LstrInstantiationError:
9011 .asciz "Ljava/lang/InstantiationError;"
9012.LstrClassCastException:
9013 .asciz "Ljava/lang/ClassCastException;"
9014.LstrNoSuchMethodError:
9015 .asciz "Ljava/lang/NoSuchMethodError;"
9016.LstrInternalError:
9017 .asciz "Ljava/lang/InternalError;"
9018.LstrFilledNewArrayNotImpl:
9019 .asciz "filled-new-array only implemented for 'int'"
9020
9021