blob: 2df6c2071637a48ec059818340d4101b1872dbf1 [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 */
Andy McFaddenb51ea112009-05-08 16:50:17 -07005809 /* (stub) */
5810 GET_GLUE(%ecx)
5811 SAVE_PC_TO_GLUE(%ecx) # only need to export these two
5812 SAVE_FP_TO_GLUE(%ecx) # only need to export these two
5813 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function
5814 call dvmMterp_OP_THROW_VERIFICATION_ERROR # do the real work
5815 GET_GLUE(%ecx)
5816 LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values
5817 LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values
5818 FETCH_INST()
5819 GOTO_NEXT
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005820/* ------------------------------ */
5821 .balign 64
5822.L_OP_EXECUTE_INLINE: /* 0xee */
5823/* File: x86/OP_EXECUTE_INLINE.S */
5824 /*
5825 * Execute a "native inline" instruction.
5826 *
5827 * We will be calling through a function table:
5828 *
5829 * (*gDvmInlineOpsTable[opIndex].func)(arg0, arg1, arg2, arg3, pResult)
5830 *
5831 */
5832 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
5833 GET_GLUE(%ecx)
5834 EXPORT_PC()
5835 movzwl 2(rPC),%eax # eax<- BBBB
5836 leal offGlue_retval(%ecx),%ecx # ecx<- & glue->retval
5837 movl %ecx,OUT_ARG4(%esp)
5838 sarl $12,rINST_FULL # rINST_FULL<- arg count (0-4)
5839 SPILL(rPC)
5840 call .LOP_EXECUTE_INLINE_continue # make call; will return after
5841 UNSPILL(rPC)
5842 testl %eax,%eax # successful?
5843 FETCH_INST_WORD(3)
5844 je common_exceptionThrown # no, handle exception
5845 ADVANCE_PC(3)
5846 GOTO_NEXT
5847
5848/* ------------------------------ */
5849 .balign 64
5850.L_OP_UNUSED_EF: /* 0xef */
5851/* File: x86/OP_UNUSED_EF.S */
5852/* File: x86/unused.S */
5853 jmp common_abort
5854
5855
5856/* ------------------------------ */
5857 .balign 64
5858.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
5859/* File: x86/OP_INVOKE_DIRECT_EMPTY.S */
5860 /*
5861 * invoke-direct-empty is a no-op in a "standard" interpreter.
5862 */
5863 FETCH_INST_WORD(3)
5864 ADVANCE_PC(3)
5865 GOTO_NEXT
5866
5867/* ------------------------------ */
5868 .balign 64
5869.L_OP_UNUSED_F1: /* 0xf1 */
5870/* File: x86/OP_UNUSED_F1.S */
5871/* File: x86/unused.S */
5872 jmp common_abort
5873
5874
5875/* ------------------------------ */
5876 .balign 64
5877.L_OP_IGET_QUICK: /* 0xf2 */
5878/* File: x86/OP_IGET_QUICK.S */
5879 /* For: iget-quick, iget-object-quick */
5880 /* op vA, vB, offset@CCCC */
5881 movzbl rINST_HI,%ecx # ecx<- BA
5882 sarl $4,%ecx # ecx<- B
5883 GET_VREG(%ecx,%ecx) # vB (object we're operating on)
5884 movzwl 2(rPC),%eax # eax<- field byte offset
5885 cmpl $0,%ecx # is object null?
5886 je common_errNullObject
5887 movl (%ecx,%eax,1),%eax
5888 movzbl rINST_HI,%ecx
5889 FETCH_INST_WORD(2)
5890 ADVANCE_PC(2)
5891 andb $0xf,%cl # rINST_FULL<- A
5892 SET_VREG (%eax,%ecx) # fp[A]<- result
5893 GOTO_NEXT
5894
5895/* ------------------------------ */
5896 .balign 64
5897.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
5898/* File: x86/OP_IGET_WIDE_QUICK.S */
5899 /* For: iget-wide-quick */
5900 /* op vA, vB, offset@CCCC */
5901 movzbl rINST_HI,%ecx # ecx<- BA
5902 sarl $4,%ecx # ecx<- B
5903 GET_VREG(%ecx,%ecx) # vB (object we're operating on)
5904 movzwl 2(rPC),%eax # eax<- field byte offset
5905 cmpl $0,%ecx # is object null?
5906 je common_errNullObject
5907 leal (%ecx,%eax,1),%eax # eax<- address of 64-bit source
5908 movl (%eax),%ecx # ecx<- lsw
5909 movl 4(%eax),%eax # eax<- msw
5910 movzbl rINST_HI,rINST_FULL
5911 andb $0xf,rINST_LO # rINST_FULL<- A
5912 SET_VREG_WORD(%ecx,rINST_FULL,0) # v[A+0]<- lsw
5913 SET_VREG_WORD(%eax,rINST_FULL,1) # v[A+1]<- msw
5914 FETCH_INST_WORD(2)
5915 ADVANCE_PC(2)
5916 GOTO_NEXT
5917
5918/* ------------------------------ */
5919 .balign 64
5920.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
5921/* File: x86/OP_IGET_OBJECT_QUICK.S */
5922/* File: x86/OP_IGET_QUICK.S */
5923 /* For: iget-quick, iget-object-quick */
5924 /* op vA, vB, offset@CCCC */
5925 movzbl rINST_HI,%ecx # ecx<- BA
5926 sarl $4,%ecx # ecx<- B
5927 GET_VREG(%ecx,%ecx) # vB (object we're operating on)
5928 movzwl 2(rPC),%eax # eax<- field byte offset
5929 cmpl $0,%ecx # is object null?
5930 je common_errNullObject
5931 movl (%ecx,%eax,1),%eax
5932 movzbl rINST_HI,%ecx
5933 FETCH_INST_WORD(2)
5934 ADVANCE_PC(2)
5935 andb $0xf,%cl # rINST_FULL<- A
5936 SET_VREG (%eax,%ecx) # fp[A]<- result
5937 GOTO_NEXT
5938
5939
5940/* ------------------------------ */
5941 .balign 64
5942.L_OP_IPUT_QUICK: /* 0xf5 */
5943/* File: x86/OP_IPUT_QUICK.S */
5944 /* For: iput-quick, iput-object-quick */
5945 /* op vA, vB, offset@CCCC */
5946 movzbl rINST_HI,%ecx # ecx<- BA
5947 sarl $4,%ecx # ecx<- B
5948 GET_VREG(%ecx,%ecx) # vB (object we're operating on)
5949 movzbl rINST_HI,rINST_FULL
5950 andb $0xf,rINST_LO # rINST_FULL<- A
5951 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A]
5952 movzwl 2(rPC),%eax # eax<- field byte offset
5953 testl %ecx,%ecx # is object null?
5954 je common_errNullObject
5955 movl rINST_FULL,(%ecx,%eax,1)
5956 FETCH_INST_WORD(2)
5957 ADVANCE_PC(2)
5958 GOTO_NEXT
5959
5960/* ------------------------------ */
5961 .balign 64
5962.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
5963/* File: x86/OP_IPUT_WIDE_QUICK.S */
5964 /* For: iput-wide-quick */
5965 /* op vA, vB, offset@CCCC */
5966 movzbl rINST_HI,%ecx # ecx<- BA
5967 sarl $4,%ecx # ecx<- B
5968 GET_VREG(%ecx,%ecx) # vB (object we're operating on)
5969 movzwl 2(rPC),%eax # eax<- field byte offset
5970 testl %ecx,%ecx # is object null?
5971 je common_errNullObject
5972 leal (%ecx,%eax,1),%ecx # ecx<- Address of 64-bit target
5973 movzbl rINST_HI,rINST_FULL
5974 andb $0xf,rINST_LO # rINST_FULL<- A
5975 GET_VREG_WORD(%eax,rINST_FULL,0) # eax<- lsw
5976 GET_VREG_WORD(rINST_FULL,rINST_FULL,1) # rINST_FULL<- msw
5977 movl %eax,(%ecx)
5978 movl rINST_FULL,4(%ecx)
5979 FETCH_INST_WORD(2)
5980 ADVANCE_PC(2)
5981 GOTO_NEXT
5982
5983/* ------------------------------ */
5984 .balign 64
5985.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
5986/* File: x86/OP_IPUT_OBJECT_QUICK.S */
5987/* File: x86/OP_IPUT_QUICK.S */
5988 /* For: iput-quick, iput-object-quick */
5989 /* op vA, vB, offset@CCCC */
5990 movzbl rINST_HI,%ecx # ecx<- BA
5991 sarl $4,%ecx # ecx<- B
5992 GET_VREG(%ecx,%ecx) # vB (object we're operating on)
5993 movzbl rINST_HI,rINST_FULL
5994 andb $0xf,rINST_LO # rINST_FULL<- A
5995 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A]
5996 movzwl 2(rPC),%eax # eax<- field byte offset
5997 testl %ecx,%ecx # is object null?
5998 je common_errNullObject
5999 movl rINST_FULL,(%ecx,%eax,1)
6000 FETCH_INST_WORD(2)
6001 ADVANCE_PC(2)
6002 GOTO_NEXT
6003
6004
6005/* ------------------------------ */
6006 .balign 64
6007.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
6008/* File: x86/OP_INVOKE_VIRTUAL_QUICK.S */
6009 /*
6010 * Handle an optimized virtual method call.
6011 *
6012 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
6013 */
6014 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
6015 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
6016 movzwl 4(rPC),%eax # eax<- FEDC or CCCC
6017 movzwl 2(rPC),%ecx # ecx<- BBBB
6018 .if (!0)
6019 andl $0xf,%eax # eax<- C (or stays CCCC)
6020 .endif
6021 GET_VREG(%eax,%eax) # eax<- vC ("this" ptr)
6022 testl %eax,%eax # null?
6023 je common_errNullObject # yep, throw exception
6024 movl offObject_clazz(%eax),%eax # eax<- thisPtr->clazz
6025 movl offClassObject_vtable(%eax),%eax # eax<- thisPtr->clazz->vtable
6026 EXPORT_PC() # might throw later - get ready
6027 movl (%eax,%ecx,4),%eax # eax<- vtable[BBBB]
Johnnie Birchc4080f62009-02-10 15:41:06 -08006028 jmp common_invokeMethodNoRange
6029
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08006030
6031
6032/* ------------------------------ */
6033 .balign 64
6034.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
6035/* File: x86/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
6036/* File: x86/OP_INVOKE_VIRTUAL_QUICK.S */
6037 /*
6038 * Handle an optimized virtual method call.
6039 *
6040 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
6041 */
6042 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
6043 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
6044 movzwl 4(rPC),%eax # eax<- FEDC or CCCC
6045 movzwl 2(rPC),%ecx # ecx<- BBBB
6046 .if (!1)
6047 andl $0xf,%eax # eax<- C (or stays CCCC)
6048 .endif
6049 GET_VREG(%eax,%eax) # eax<- vC ("this" ptr)
6050 testl %eax,%eax # null?
6051 je common_errNullObject # yep, throw exception
6052 movl offObject_clazz(%eax),%eax # eax<- thisPtr->clazz
6053 movl offClassObject_vtable(%eax),%eax # eax<- thisPtr->clazz->vtable
6054 EXPORT_PC() # might throw later - get ready
6055 movl (%eax,%ecx,4),%eax # eax<- vtable[BBBB]
Johnnie Birchc4080f62009-02-10 15:41:06 -08006056 jmp common_invokeMethodRange
6057
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08006058
6059
6060
6061/* ------------------------------ */
6062 .balign 64
6063.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
6064/* File: x86/OP_INVOKE_SUPER_QUICK.S */
6065 /*
6066 * Handle an optimized "super" method call.
6067 *
6068 * for: [opt] invoke-super-quick, invoke-super-quick/range
6069 */
6070 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
6071 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
6072 GET_GLUE(%ecx)
6073 movzwl 4(rPC),%eax # eax<- GFED or CCCC
6074 movl offGlue_method(%ecx),%ecx # ecx<- current method
6075 .if (!0)
6076 andl $0xf,%eax # eax<- D (or stays CCCC)
6077 .endif
6078 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
6079 GET_VREG(%eax,%eax) # eax<- "this"
6080 movl offClassObject_super(%ecx),%ecx # ecx<- method->clazz->super
6081 testl %eax,%eax # null "this"?
6082 je common_errNullObject # "this" is null, throw exception
6083 movzwl 2(rPC),%eax # eax<- BBBB
6084 movl offClassObject_vtable(%ecx),%ecx # ecx<- vtable
6085 EXPORT_PC()
6086 movl (%ecx,%eax,4),%eax # eax<- super->vtable[BBBB]
Johnnie Birchc4080f62009-02-10 15:41:06 -08006087 jmp common_invokeMethodNoRange
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08006088
6089
6090/* ------------------------------ */
6091 .balign 64
6092.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
6093/* File: x86/OP_INVOKE_SUPER_QUICK_RANGE.S */
6094/* File: x86/OP_INVOKE_SUPER_QUICK.S */
6095 /*
6096 * Handle an optimized "super" method call.
6097 *
6098 * for: [opt] invoke-super-quick, invoke-super-quick/range
6099 */
6100 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
6101 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
6102 GET_GLUE(%ecx)
6103 movzwl 4(rPC),%eax # eax<- GFED or CCCC
6104 movl offGlue_method(%ecx),%ecx # ecx<- current method
6105 .if (!1)
6106 andl $0xf,%eax # eax<- D (or stays CCCC)
6107 .endif
6108 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
6109 GET_VREG(%eax,%eax) # eax<- "this"
6110 movl offClassObject_super(%ecx),%ecx # ecx<- method->clazz->super
6111 testl %eax,%eax # null "this"?
6112 je common_errNullObject # "this" is null, throw exception
6113 movzwl 2(rPC),%eax # eax<- BBBB
6114 movl offClassObject_vtable(%ecx),%ecx # ecx<- vtable
6115 EXPORT_PC()
6116 movl (%ecx,%eax,4),%eax # eax<- super->vtable[BBBB]
Johnnie Birchc4080f62009-02-10 15:41:06 -08006117 jmp common_invokeMethodRange
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08006118
6119
6120
6121/* ------------------------------ */
6122 .balign 64
6123.L_OP_UNUSED_FC: /* 0xfc */
6124/* File: x86/OP_UNUSED_FC.S */
6125/* File: x86/unused.S */
6126 jmp common_abort
6127
6128
6129/* ------------------------------ */
6130 .balign 64
6131.L_OP_UNUSED_FD: /* 0xfd */
6132/* File: x86/OP_UNUSED_FD.S */
6133/* File: x86/unused.S */
6134 jmp common_abort
6135
6136
6137/* ------------------------------ */
6138 .balign 64
6139.L_OP_UNUSED_FE: /* 0xfe */
6140/* File: x86/OP_UNUSED_FE.S */
6141/* File: x86/unused.S */
6142 jmp common_abort
6143
6144
6145/* ------------------------------ */
6146 .balign 64
6147.L_OP_UNUSED_FF: /* 0xff */
6148/* File: x86/OP_UNUSED_FF.S */
6149/* File: x86/unused.S */
6150 jmp common_abort
6151
6152
6153
6154 .balign 64
6155 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart
6156 .global dvmAsmInstructionEnd
6157dvmAsmInstructionEnd:
6158
6159/*
6160 * ===========================================================================
6161 * Sister implementations
6162 * ===========================================================================
6163 */
6164 .global dvmAsmSisterStart
6165 .type dvmAsmSisterStart, %function
6166 .text
6167 .balign 4
6168dvmAsmSisterStart:
6169
6170/* continuation for OP_CONST_STRING */
6171
6172/* This is the less common path, so we'll redo some work
6173 here rather than force spills on the common path */
6174.LOP_CONST_STRING_resolve:
6175 GET_GLUE(%eax)
6176 movl %ecx,rINST_FULL # rINST_FULL<- AA
6177 EXPORT_PC()
6178 movl offGlue_method(%eax),%eax # eax<- glue->method
6179 movzwl 2(rPC),%ecx # ecx<- BBBB
6180 movl offMethod_clazz(%eax),%eax
6181 SPILL(rPC)
6182 movl %ecx,OUT_ARG1(%esp)
6183 movl %eax,OUT_ARG0(%esp)
6184 call dvmResolveString # go resolve
6185 UNSPILL(rPC)
6186 testl %eax,%eax # failed?
6187 je common_exceptionThrown
6188 SET_VREG(%eax,rINST_FULL)
6189 FETCH_INST_WORD(2)
6190 ADVANCE_PC(2)
6191 GOTO_NEXT
6192
6193
6194/* continuation for OP_CONST_STRING_JUMBO */
6195
6196/* This is the less common path, so we'll redo some work
6197 here rather than force spills on the common path */
6198.LOP_CONST_STRING_JUMBO_resolve:
6199 GET_GLUE(%eax)
6200 movl %ecx,rINST_FULL # rINST_FULL<- AA
6201 EXPORT_PC()
6202 movl offGlue_method(%eax),%eax # eax<- glue->method
6203 movl 2(rPC),%ecx # ecx<- BBBBBBBB
6204 movl offMethod_clazz(%eax),%eax
6205 SPILL(rPC)
6206 movl %ecx,OUT_ARG1(%esp)
6207 movl %eax,OUT_ARG0(%esp)
6208 call dvmResolveString # go resolve
6209 UNSPILL(rPC)
6210 testl %eax,%eax # failed?
6211 je common_exceptionThrown
6212 SET_VREG(%eax,rINST_FULL)
6213 FETCH_INST_WORD(3)
6214 ADVANCE_PC(3)
6215 GOTO_NEXT
6216
6217
6218/* continuation for OP_CONST_CLASS */
6219
6220/* This is the less common path, so we'll redo some work
6221 here rather than force spills on the common path */
6222.LOP_CONST_CLASS_resolve:
6223 GET_GLUE(%eax)
6224 movl %ecx,rINST_FULL # rINST_FULL<- AA
6225 EXPORT_PC()
6226 movl offGlue_method(%eax),%eax # eax<- glue->method
6227 movl $1,OUT_ARG2(%esp) # true
6228 movzwl 2(rPC),%ecx # ecx<- BBBB
6229 movl offMethod_clazz(%eax),%eax
6230 SPILL(rPC)
6231 movl %ecx,OUT_ARG1(%esp)
6232 movl %eax,OUT_ARG0(%esp)
6233 call dvmResolveClass # go resolve
6234 UNSPILL(rPC)
6235 testl %eax,%eax # failed?
6236 je common_exceptionThrown
6237 SET_VREG(%eax,rINST_FULL)
6238 FETCH_INST_WORD(2)
6239 ADVANCE_PC(2)
6240 GOTO_NEXT
6241
6242
6243/* continuation for OP_MONITOR_ENTER */
6244
6245.LOP_MONITOR_ENTER_continue:
6246 SPILL(rPC) # have to - caller save
6247 movl %ecx,OUT_ARG0(%esp)
6248 movl %eax,OUT_ARG1(%esp)
6249 call dvmLockObject # dvmLockObject(self,object)
6250 UNSPILL(rPC)
6251#ifdef WITH_DEADLOCK_PREDICTION
6252 GET_GLUE(%ecx)
6253 movl offGlueSelf(%ecx),%ecx # ecx<- glue->self
6254 movl offThread_exception(%ecx),%eax
6255 testl %eax,%eax
6256 jne common_exceptionThrown
6257#endif
6258 ADVANCE_PC(1)
6259 GOTO_NEXT
6260
6261/* continuation for OP_MONITOR_EXIT */
6262
6263.LOP_MONITOR_EXIT_continue:
6264 call dvmUnlockObject # unlock(self,obj)
6265 UNSPILL(rPC)
6266 FETCH_INST_WORD(1)
6267 testl %eax,%eax # success?
6268 je common_exceptionThrown # no, exception pending
6269 ADVANCE_PC(1)
6270 GOTO_NEXT
6271
6272/* continuation for OP_CHECK_CAST */
6273
6274 /*
6275 * Trivial test failed, need to perform full check. This is common.
6276 * ecx holds obj->clazz
6277 * eax holds class resolved from BBBB
6278 * rINST_FULL holds object
6279 */
6280.LOP_CHECK_CAST_fullcheck:
6281 movl %eax,OUT_ARG1(%esp)
6282 movl %ecx,OUT_ARG0(%esp)
6283 SPILL(rPC)
6284 call dvmInstanceofNonTrivial # eax<- boolean result
6285 UNSPILL(rPC)
6286 testl %eax,%eax # failed?
6287 jne .LOP_CHECK_CAST_okay # no, success
6288
6289 # A cast has failed. We need to throw a ClassCastException with the
6290 # class of the object that failed to be cast.
6291 EXPORT_PC()
6292 movl offObject_clazz(rINST_FULL),%ecx # ecx<- obj->clazz
6293 movl $.LstrClassCastException,%eax
6294 movl offClassObject_descriptor(%ecx),%ecx
6295 movl %eax,OUT_ARG0(%esp) # arg0<- message
6296 movl %ecx,OUT_ARG1(%esp) # arg1<- obj->clazz->descriptor
6297 SPILL(rPC)
6298 call dvmThrowExceptionWithClassMessage
6299 UNSPILL(rPC)
6300 jmp common_exceptionThrown
6301
6302 /*
6303 * Resolution required. This is the least-likely path, and we're
6304 * going to have to recreate some data.
6305 *
6306 * rINST_FULL holds object
6307 */
6308.LOP_CHECK_CAST_resolve:
6309 GET_GLUE(%ecx)
6310 EXPORT_PC()
6311 movzwl 2(rPC),%eax # eax<- BBBB
6312 movl offGlue_method(%ecx),%ecx # ecx<- glue->method
6313 movl %eax,OUT_ARG1(%esp) # arg1<- BBBB
6314 movl offMethod_clazz(%ecx),%ecx # ecx<- metho->clazz
6315 movl $0,OUT_ARG2(%esp) # arg2<- false
6316 movl %ecx,OUT_ARG0(%esp) # arg0<- method->clazz
6317 SPILL(rPC)
6318 call dvmResolveClass # eax<- resolved ClassObject ptr
6319 UNSPILL(rPC)
6320 testl %eax,%eax # got null?
6321 je common_exceptionThrown # yes, handle exception
6322 movl offObject_clazz(rINST_FULL),%ecx # ecx<- obj->clazz
6323 jmp .LOP_CHECK_CAST_resolved # pick up where we left off
6324
6325/* continuation for OP_INSTANCE_OF */
6326
6327 /*
6328 * Trivial test failed, need to perform full check. This is common.
6329 * eax holds obj->clazz
6330 * ecx holds class resolved from BBBB
6331 * rINST_HI has BA
6332 * rPC already spilled
6333 */
6334.LOP_INSTANCE_OF_fullcheck:
6335 movl %eax,OUT_ARG0(%esp)
6336 movl %ecx,OUT_ARG1(%esp)
6337 call dvmInstanceofNonTrivial # eax<- boolean result
6338 # fall through to OP_INSTANCE_OF_store
6339
6340 /*
6341 * eax holds boolean result
6342 * rINST_HI holds BA
6343 */
6344.LOP_INSTANCE_OF_store:
6345 UNSPILL(rPC)
6346 movzbl rINST_HI,%ecx # ecx<- BA
6347 FETCH_INST_WORD(2)
6348 andb $0xf,%cl # ecl<- A
6349 ADVANCE_PC(2)
6350 SET_VREG(%eax,%ecx) # vA<- eax
6351 GOTO_NEXT
6352
6353 /*
6354 * Trivial test succeeded, save and bail.
6355 * r9 holds A
6356 */
6357.LOP_INSTANCE_OF_trivial:
6358 UNSPILL(rPC)
6359 movzbl rINST_HI,%ecx # ecx<- BA
6360 FETCH_INST_WORD(2)
6361 andb $0xf,%cl # ecl<- A
6362 ADVANCE_PC(2)
6363 movl $1,%eax
6364 SET_VREG(%eax,%ecx) # vA<- true
6365 GOTO_NEXT
6366
6367 /*
6368 * Resolution required. This is the least-likely path.
6369 *
6370 * rPC holds BBBB
6371 * rINST_HI holds BA
6372 */
6373.LOP_INSTANCE_OF_resolve:
6374 movl rPC,OUT_ARG1(%esp) # arg1<- BBBB
6375 GET_GLUE(%ecx)
6376 UNSPILL(rPC)
6377 movl offGlue_method(%ecx),%ecx
6378 movl $1,OUT_ARG2(%esp) # arg2<- true
6379 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
6380 EXPORT_PC()
6381 movl %ecx,OUT_ARG0(%esp) # arg0<- method->clazz
6382 call dvmResolveClass # eax<- resolved ClassObject ptr
6383 UNSPILL(rPC)
6384 testl %eax,%eax # success?
6385 je common_exceptionThrown # no, handle exception
6386/* Now, we need to sync up with fast path. We need eax to
6387 * hold the obj->clazz, and ecx to hold the resolved class
6388 */
6389 movl %eax,%ecx # ecx<- resolved class
6390 movzbl rINST_HI,%eax # eax<- BA
6391 sarl $4,%eax # eax<- B
6392 GET_VREG(%eax,%eax) # eax<- vB (obj)
6393 movl offObject_clazz(%eax),%eax # eax<- obj->clazz
6394 jmp .LOP_INSTANCE_OF_resolved
6395
6396
6397/* continuation for OP_NEW_INSTANCE */
6398
6399.LOP_NEW_INSTANCE_initialized: # on entry, ecx<- class
Andy McFaddenb51ea112009-05-08 16:50:17 -07006400 /* TODO: remove test for interface/abstract, now done in verifier */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08006401 testl $(ACC_INTERFACE|ACC_ABSTRACT),offClassObject_accessFlags(%ecx)
6402 movl $ALLOC_DONT_TRACK,OUT_ARG1(%esp)
6403 jne .LOP_NEW_INSTANCE_abstract
6404.LOP_NEW_INSTANCE_finish: # ecx=class
6405 movl %ecx,OUT_ARG0(%esp)
6406 call dvmAllocObject # eax<- new object
6407 UNSPILL(rPC)
6408 movl rINST_FULL,%ecx
6409 FETCH_INST_WORD(2)
6410 testl %eax,%eax # success?
6411 je common_exceptionThrown # no, bail out
6412 SET_VREG(%eax,%ecx)
6413 ADVANCE_PC(2)
6414 GOTO_NEXT
6415
6416 /*
6417 * Class initialization required.
6418 *
6419 * ecx holds class object
6420 */
6421.LOP_NEW_INSTANCE_needinit:
6422 SPILL_TMP(%ecx) # save object
6423 movl %ecx,OUT_ARG0(%esp)
6424 call dvmInitClass # initialize class
6425 UNSPILL_TMP(%ecx) # restore object
6426 testl %eax,%eax # success?
6427 jne .LOP_NEW_INSTANCE_initialized # success, continue
6428 UNSPILL(rPC) # failed, restore PC
6429 jmp common_exceptionThrown # go deal with init exception
6430
6431 /*
6432 * Resolution required. This is the least-likely path.
6433 *
6434 */
6435.LOP_NEW_INSTANCE_resolve:
6436 GET_GLUE(%ecx)
6437 movzwl 2(rPC),%eax
6438 movl offGlue_method(%ecx),%ecx # ecx<- glue->method
6439 movl %eax,OUT_ARG1(%esp)
6440 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
6441 movl $0,OUT_ARG2(%esp)
6442 movl %ecx,OUT_ARG0(%esp)
6443 call dvmResolveClass # call(clazz,off,flags)
6444 movl %eax,%ecx # ecx<- resolved ClassObject ptr
6445 testl %ecx,%ecx # success?
6446 jne .LOP_NEW_INSTANCE_resolved # good to go
6447 UNSPILL(rPC)
6448 jmp common_exceptionThrown # no, handle exception
6449
6450 /*
Andy McFaddenb51ea112009-05-08 16:50:17 -07006451 * TODO: remove this
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08006452 * We can't instantiate an abstract class or interface, so throw an
6453 * InstantiationError with the class descriptor as the message.
6454 *
6455 * ecx holds class object
6456 */
6457.LOP_NEW_INSTANCE_abstract:
6458 movl offClassObject_descriptor(%ecx),%eax
6459 movl $.LstrInstantiationError,OUT_ARG0(%esp)
6460 movl %eax,OUT_ARG1(%esp)
6461 call dvmThrowExceptionWithClassMessage
6462 UNSPILL(rPC)
6463 jmp common_exceptionThrown
6464
6465
6466
6467
6468/* continuation for OP_NEW_ARRAY */
6469
6470 /*
6471 * Resolve class. (This is an uncommon case.)
6472 * ecx holds class (null here)
6473 * eax holds array length (vB)
6474 */
6475.LOP_NEW_ARRAY_resolve:
6476 GET_GLUE(%ecx)
6477 SPILL_TMP(%eax) # save array length
6478 movl offGlue_method(%ecx),%ecx # ecx<- glue->method
6479 movzwl 2(rPC),%eax # eax<- CCCC
6480 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
6481 movl %eax,OUT_ARG1(%esp)
6482 movl $0,OUT_ARG2(%esp)
6483 movl %ecx,OUT_ARG0(%esp)
6484 SPILL(rPC)
6485 call dvmResolveClass # eax<- call(clazz,ref,flag)
6486 UNSPILL(rPC)
6487 movl %eax,%ecx
6488 UNSPILL_TMP(%eax)
6489 testl %ecx,%ecx # successful resolution?
6490 je common_exceptionThrown # no, bail.
6491# fall through to OP_NEW_ARRAY_finish
6492
6493 /*
6494 * Finish allocation
6495 *
6496 * ecx holds class
6497 * eax holds array length (vB)
6498 */
6499.LOP_NEW_ARRAY_finish:
6500 movl %ecx,OUT_ARG0(%esp)
6501 movl %eax,OUT_ARG1(%esp)
6502 movl $ALLOC_DONT_TRACK,OUT_ARG2(%esp)
6503 SPILL(rPC)
6504 call dvmAllocArrayByClass # eax<- call(clazz,length,flags)
6505 UNSPILL(rPC)
6506 testl %eax,%eax # failed?
6507 je common_exceptionThrown # yup - go handle
6508 movl rINST_FULL,%ecx
6509 FETCH_INST_WORD(2)
6510 SET_VREG(%eax,%ecx)
6511 ADVANCE_PC(2)
6512 GOTO_NEXT
6513
6514
6515/* continuation for OP_FILLED_NEW_ARRAY */
6516
6517.LOP_FILLED_NEW_ARRAY_more:
6518 movl offMethod_clazz(%eax),%eax # eax<- method->clazz
6519 movl %eax,OUT_ARG0(%esp) # arg0<- clazz
6520 call dvmResolveClass # eax<- call(clazz,ref,flag)
6521 UNSPILL(rPC)
6522 testl %eax,%eax # null?
6523 je common_exceptionThrown # yes, handle it
6524
6525 # note: fall through to .LOP_FILLED_NEW_ARRAY_continue
6526
6527 /*
6528 * On entry:
6529 * eax holds array class [r0]
6530 * rINST_FULL holds AA or BB [r10]
6531 * ecx is scratch
6532 * rPC is valid, but has been spilled
6533 */
6534.LOP_FILLED_NEW_ARRAY_continue:
6535 movl offClassObject_descriptor(%eax),%ecx # ecx<- arrayClass->descriptor
6536 movl $ALLOC_DONT_TRACK,OUT_ARG2(%esp) # arg2<- flags
6537 movzbl 1(%ecx),%ecx # ecx<- descriptor[1]
6538 movl %eax,OUT_ARG0(%esp) # arg0<- arrayClass
6539 cmpb $'I',%cl # supported?
6540 je 1f
6541 cmpb $'L',%cl
6542 je 1f
6543 cmpb $'[',%cl
6544 jne .LOP_FILLED_NEW_ARRAY_notimpl # no, not handled yet
65451:
6546 .if (!0)
6547 SPILL_TMP(rINST_FULL) # save copy, need "B" later
6548 sarl $4,rINST_FULL
6549 .endif
6550 movl rINST_FULL,OUT_ARG1(%esp) # arg1<- A or AA (length)
6551 call dvmAllocArrayByClass # eax<- call(arrayClass, length, flags)
6552 UNSPILL(rPC)
6553 GET_GLUE(%ecx)
6554 testl %eax,%eax # alloc successful?
6555 je common_exceptionThrown # no, handle exception
6556 movl %eax,offGlue_retval(%ecx) # retval.l<- new array
6557 movzwl 4(rPC),%ecx # ecx<- FEDC or CCCC
6558 leal offArrayObject_contents(%eax),%eax # eax<- newArray->contents
6559
6560/* at this point:
6561 * eax is pointer to tgt
6562 * rINST_FULL is length
6563 * ecx is FEDC or CCCC
6564 * TMP_SPILL is BA
6565 * rPC is valid, but spilled
6566 * We now need to copy values from registers into the array
6567 */
6568
6569 .if 0
6570 # set up src pointer
6571 SPILL(rFP) # esi
6572 SPILL(rIBASE) # edi
6573 movl %eax,%edi # set up dst ptr
6574 leal (rFP,%ecx,4),%esi # set up src ptr
6575 movl rINST_FULL,%ecx # load count register
6576 FETCH_INST_WORD(3)
6577 rep
6578 movsd
6579 UNSPILL(rIBASE)
6580 UNSPILL(rFP)
6581 .else
6582 testl rINST_FULL,rINST_FULL
6583 je 4f
6584 UNSPILL_TMP(rPC)
6585 andl $0x0f,rPC # rPC<- 0000000A
6586 sall $16,rPC # rPC<- 000A0000
6587 orl %ecx,rPC # rpc<- 000AFEDC
65883:
6589 movl $0xf,%ecx
6590 andl rPC,%ecx # ecx<- next reg to load
6591 GET_VREG(%ecx,%ecx)
6592 shrl $4,rPC
6593 leal 4(%eax),%eax
6594 movl %ecx,-4(%eax)
6595 sub $1,rINST_FULL
6596 jne 3b
65974:
6598 UNSPILL(rPC)
6599 FETCH_INST_WORD(3)
6600 .endif
6601
6602 ADVANCE_PC(3)
6603 GOTO_NEXT
6604
6605
6606 /*
6607 * Throw an exception indicating that we have not implemented this
6608 * mode of filled-new-array.
6609 */
6610.LOP_FILLED_NEW_ARRAY_notimpl:
6611 movl $.LstrInternalError,%eax
6612 movl %eax,OUT_ARG0(%esp)
6613 movl $.LstrFilledNewArrayNotImpl,%eax
6614 movl %eax,OUT_ARG1(%esp)
6615 call dvmThrowException
6616 UNSPILL(rPC)
6617 jmp common_exceptionThrown
6618
6619
6620/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
6621
6622.LOP_FILLED_NEW_ARRAY_RANGE_more:
6623 movl offMethod_clazz(%eax),%eax # eax<- method->clazz
6624 movl %eax,OUT_ARG0(%esp) # arg0<- clazz
6625 call dvmResolveClass # eax<- call(clazz,ref,flag)
6626 UNSPILL(rPC)
6627 testl %eax,%eax # null?
6628 je common_exceptionThrown # yes, handle it
6629
6630 # note: fall through to .LOP_FILLED_NEW_ARRAY_RANGE_continue
6631
6632 /*
6633 * On entry:
6634 * eax holds array class [r0]
6635 * rINST_FULL holds AA or BB [r10]
6636 * ecx is scratch
6637 * rPC is valid, but has been spilled
6638 */
6639.LOP_FILLED_NEW_ARRAY_RANGE_continue:
6640 movl offClassObject_descriptor(%eax),%ecx # ecx<- arrayClass->descriptor
6641 movl $ALLOC_DONT_TRACK,OUT_ARG2(%esp) # arg2<- flags
6642 movzbl 1(%ecx),%ecx # ecx<- descriptor[1]
6643 movl %eax,OUT_ARG0(%esp) # arg0<- arrayClass
6644 cmpb $'I',%cl # supported?
6645 je 1f
6646 cmpb $'L',%cl
6647 je 1f
6648 cmpb $'[',%cl
6649 jne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl # no, not handled yet
66501:
6651 .if (!1)
6652 SPILL_TMP(rINST_FULL) # save copy, need "B" later
6653 sarl $4,rINST_FULL
6654 .endif
6655 movl rINST_FULL,OUT_ARG1(%esp) # arg1<- A or AA (length)
6656 call dvmAllocArrayByClass # eax<- call(arrayClass, length, flags)
6657 UNSPILL(rPC)
6658 GET_GLUE(%ecx)
6659 testl %eax,%eax # alloc successful?
6660 je common_exceptionThrown # no, handle exception
6661 movl %eax,offGlue_retval(%ecx) # retval.l<- new array
6662 movzwl 4(rPC),%ecx # ecx<- FEDC or CCCC
6663 leal offArrayObject_contents(%eax),%eax # eax<- newArray->contents
6664
6665/* at this point:
6666 * eax is pointer to tgt
6667 * rINST_FULL is length
6668 * ecx is FEDC or CCCC
6669 * TMP_SPILL is BA
6670 * rPC is valid, but spilled
6671 * We now need to copy values from registers into the array
6672 */
6673
6674 .if 1
6675 # set up src pointer
6676 SPILL(rFP) # esi
6677 SPILL(rIBASE) # edi
6678 movl %eax,%edi # set up dst ptr
6679 leal (rFP,%ecx,4),%esi # set up src ptr
6680 movl rINST_FULL,%ecx # load count register
6681 FETCH_INST_WORD(3)
6682 rep
6683 movsd
6684 UNSPILL(rIBASE)
6685 UNSPILL(rFP)
6686 .else
6687 testl rINST_FULL,rINST_FULL
6688 je 4f
6689 UNSPILL_TMP(rPC)
6690 andl $0x0f,rPC # rPC<- 0000000A
6691 sall $16,rPC # rPC<- 000A0000
6692 orl %ecx,rPC # rpc<- 000AFEDC
66933:
6694 movl $0xf,%ecx
6695 andl rPC,%ecx # ecx<- next reg to load
6696 GET_VREG(%ecx,%ecx)
6697 shrl $4,rPC
6698 leal 4(%eax),%eax
6699 movl %ecx,-4(%eax)
6700 sub $1,rINST_FULL
6701 jne 3b
67024:
6703 UNSPILL(rPC)
6704 FETCH_INST_WORD(3)
6705 .endif
6706
6707 ADVANCE_PC(3)
6708 GOTO_NEXT
6709
6710
6711 /*
6712 * Throw an exception indicating that we have not implemented this
6713 * mode of filled-new-array.
6714 */
6715.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
6716 movl $.LstrInternalError,%eax
6717 movl %eax,OUT_ARG0(%esp)
6718 movl $.LstrFilledNewArrayNotImpl,%eax
6719 movl %eax,OUT_ARG1(%esp)
6720 call dvmThrowException
6721 UNSPILL(rPC)
6722 jmp common_exceptionThrown
6723
6724
6725/* continuation for OP_CMPL_FLOAT */
6726
6727.LOP_CMPL_FLOAT_isNaN:
6728 movl $-1,%ecx
6729 jmp .LOP_CMPL_FLOAT_finish
6730
6731/* continuation for OP_CMPG_FLOAT */
6732
6733.LOP_CMPG_FLOAT_isNaN:
6734 movl $1,%ecx
6735 jmp .LOP_CMPG_FLOAT_finish
6736
6737/* continuation for OP_CMPL_DOUBLE */
6738
6739.LOP_CMPL_DOUBLE_isNaN:
6740 movl $-1,%ecx
6741 jmp .LOP_CMPL_DOUBLE_finish
6742
6743/* continuation for OP_CMPG_DOUBLE */
6744
6745.LOP_CMPG_DOUBLE_isNaN:
6746 movl $1,%ecx
6747 jmp .LOP_CMPG_DOUBLE_finish
6748
6749/* continuation for OP_CMP_LONG */
6750
6751.LOP_CMP_LONG_bigger:
6752 UNSPILL(rPC)
6753 movl $1,%ecx
6754 jmp .LOP_CMP_LONG_finish
6755.LOP_CMP_LONG_smaller:
6756 UNSPILL(rPC)
6757 movl $-1,%ecx
6758.LOP_CMP_LONG_finish:
6759 SET_VREG(%ecx,rINST_FULL)
6760 FETCH_INST_WORD(2)
6761 ADVANCE_PC(2)
6762 GOTO_NEXT
6763
6764/* continuation for OP_AGET_WIDE */
6765
6766.LOP_AGET_WIDE_finish:
6767 leal offArrayObject_contents(%eax,%ecx,8),%eax
6768 movl (%eax),%ecx
6769 movl 4(%eax),%eax
6770 SET_VREG_WORD(%ecx,rINST_FULL,0)
6771 SET_VREG_WORD(%eax,rINST_FULL,1)
6772 FETCH_INST_WORD(2)
6773 ADVANCE_PC(2)
6774 GOTO_NEXT
6775
6776
6777/* continuation for OP_APUT_WIDE */
6778
6779.LOP_APUT_WIDE_finish:
6780 leal offArrayObject_contents(%eax,%ecx,8),%eax
6781 GET_VREG_WORD(%ecx,rINST_FULL,0)
6782 GET_VREG_WORD(rINST_FULL,rINST_FULL,1)
6783 movl rINST_FULL,4(%eax)
6784 FETCH_INST_WORD(2)
6785 movl %ecx,(%eax)
6786 ADVANCE_PC(2)
6787 GOTO_NEXT
6788
6789
6790/* continuation for OP_APUT_OBJECT */
6791
6792 /* On entry:
6793 * eax<- array object
6794 * ecx<- index
6795 * rINST_FULL<- vAA
6796 */
6797.LOP_APUT_OBJECT_continue:
6798 leal offArrayObject_contents(%eax,%ecx,4),%ecx
6799 testl rINST_FULL,rINST_FULL # storing null reference?
6800 je .LOP_APUT_OBJECT_skip_check
6801 SPILL(rPC)
6802 SPILL_TMP(%ecx)
6803 movl offObject_clazz(%eax),%eax # eax<- arrayObj->clazz
6804 movl offObject_clazz(rINST_FULL),%ecx # ecx<- obj->clazz
6805 movl %eax,OUT_ARG1(%esp)
6806 movl %ecx,OUT_ARG0(%esp)
6807 call dvmCanPutArrayElement # test object type vs. array type
6808 UNSPILL(rPC)
6809 UNSPILL_TMP(%ecx)
6810 testl %eax,%eax
6811 je common_errArrayStore
6812
6813.LOP_APUT_OBJECT_skip_check:
6814 movl rINST_FULL,(%ecx)
6815 FETCH_INST_WORD(2)
6816 ADVANCE_PC(2)
6817 GOTO_NEXT
6818
6819
6820/* continuation for OP_IGET */
6821
6822
6823.LOP_IGET_resolve:
6824 EXPORT_PC()
6825 SPILL(rPC)
6826 movl offGlue_method(rIBASE),rPC # rPC<- current method
6827 UNSPILL(rIBASE)
6828 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz
6829 SPILL_TMP(%ecx) # save object pointer across call
6830 movl rPC,OUT_ARG0(%esp) # pass in method->clazz
6831 call dvmResolveInstField # ... to dvmResolveInstField
6832 UNSPILL_TMP(%ecx)
6833 UNSPILL(rPC)
6834 testl %eax,%eax # ... which returns InstrField ptr
6835 jne .LOP_IGET_finish
6836 jmp common_exceptionThrown
6837
6838.LOP_IGET_finish:
6839 /*
6840 * Currently:
6841 * eax holds resolved field
6842 * ecx holds object
6843 * rIBASE is scratch, but needs to be unspilled
6844 * rINST_FULL holds A
6845 */
6846 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
6847 UNSPILL(rIBASE)
6848 testl %ecx,%ecx # object null?
6849 je common_errNullObject # object was null
6850 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits)
6851 movl rINST_FULL,%eax # eax<- A
6852 FETCH_INST_WORD(2)
6853 SET_VREG(%ecx,%eax)
6854 ADVANCE_PC(2)
6855 GOTO_NEXT
6856
6857
6858/* continuation for OP_IGET_WIDE */
6859
6860
6861.LOP_IGET_WIDE_resolve:
6862 EXPORT_PC()
6863 SPILL(rPC)
6864 movl offGlue_method(rIBASE),rPC # rPC<- current method
6865 UNSPILL(rIBASE)
6866 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz
6867 SPILL_TMP(%ecx) # save object pointer across call
6868 movl rPC,OUT_ARG0(%esp) # pass in method->clazz
6869 call dvmResolveInstField # ... to dvmResolveInstField
6870 UNSPILL_TMP(%ecx)
6871 UNSPILL(rPC)
6872 testl %eax,%eax # ... which returns InstrField ptr
6873 jne .LOP_IGET_WIDE_finish
6874 jmp common_exceptionThrown
6875
6876.LOP_IGET_WIDE_finish:
6877 /*
6878 * Currently:
6879 * eax holds resolved field
6880 * ecx holds object
6881 * rIBASE is scratch, but needs to be unspilled
6882 * rINST_FULL holds A
6883 */
6884 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
6885 UNSPILL(rIBASE)
6886 testl %ecx,%ecx # object null?
6887 je common_errNullObject # object was null
6888 leal (%ecx,%eax,1),%eax # eax<- address of field
6889 movl (%eax),%ecx # ecx<- lsw
6890 movl 4(%eax),%eax # eax<- msw
6891 SET_VREG_WORD(%ecx,rINST_FULL,0)
6892 SET_VREG_WORD(%eax,rINST_FULL,1)
6893 FETCH_INST_WORD(2)
6894 ADVANCE_PC(2)
6895 GOTO_NEXT
6896
6897
6898/* continuation for OP_IGET_OBJECT */
6899
6900
6901.LOP_IGET_OBJECT_resolve:
6902 EXPORT_PC()
6903 SPILL(rPC)
6904 movl offGlue_method(rIBASE),rPC # rPC<- current method
6905 UNSPILL(rIBASE)
6906 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz
6907 SPILL_TMP(%ecx) # save object pointer across call
6908 movl rPC,OUT_ARG0(%esp) # pass in method->clazz
6909 call dvmResolveInstField # ... to dvmResolveInstField
6910 UNSPILL_TMP(%ecx)
6911 UNSPILL(rPC)
6912 testl %eax,%eax # ... which returns InstrField ptr
6913 jne .LOP_IGET_OBJECT_finish
6914 jmp common_exceptionThrown
6915
6916.LOP_IGET_OBJECT_finish:
6917 /*
6918 * Currently:
6919 * eax holds resolved field
6920 * ecx holds object
6921 * rIBASE is scratch, but needs to be unspilled
6922 * rINST_FULL holds A
6923 */
6924 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
6925 UNSPILL(rIBASE)
6926 testl %ecx,%ecx # object null?
6927 je common_errNullObject # object was null
6928 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits)
6929 movl rINST_FULL,%eax # eax<- A
6930 FETCH_INST_WORD(2)
6931 SET_VREG(%ecx,%eax)
6932 ADVANCE_PC(2)
6933 GOTO_NEXT
6934
6935
6936/* continuation for OP_IGET_BOOLEAN */
6937
6938
6939.LOP_IGET_BOOLEAN_resolve:
6940 EXPORT_PC()
6941 SPILL(rPC)
6942 movl offGlue_method(rIBASE),rPC # rPC<- current method
6943 UNSPILL(rIBASE)
6944 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz
6945 SPILL_TMP(%ecx) # save object pointer across call
6946 movl rPC,OUT_ARG0(%esp) # pass in method->clazz
6947 call dvmResolveInstField # ... to dvmResolveInstField
6948 UNSPILL_TMP(%ecx)
6949 UNSPILL(rPC)
6950 testl %eax,%eax # ... which returns InstrField ptr
6951 jne .LOP_IGET_BOOLEAN_finish
6952 jmp common_exceptionThrown
6953
6954.LOP_IGET_BOOLEAN_finish:
6955 /*
6956 * Currently:
6957 * eax holds resolved field
6958 * ecx holds object
6959 * rIBASE is scratch, but needs to be unspilled
6960 * rINST_FULL holds A
6961 */
6962 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
6963 UNSPILL(rIBASE)
6964 testl %ecx,%ecx # object null?
6965 je common_errNullObject # object was null
6966 movzbl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits)
6967 movl rINST_FULL,%eax # eax<- A
6968 FETCH_INST_WORD(2)
6969 SET_VREG(%ecx,%eax)
6970 ADVANCE_PC(2)
6971 GOTO_NEXT
6972
6973
6974/* continuation for OP_IGET_BYTE */
6975
6976
6977.LOP_IGET_BYTE_resolve:
6978 EXPORT_PC()
6979 SPILL(rPC)
6980 movl offGlue_method(rIBASE),rPC # rPC<- current method
6981 UNSPILL(rIBASE)
6982 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz
6983 SPILL_TMP(%ecx) # save object pointer across call
6984 movl rPC,OUT_ARG0(%esp) # pass in method->clazz
6985 call dvmResolveInstField # ... to dvmResolveInstField
6986 UNSPILL_TMP(%ecx)
6987 UNSPILL(rPC)
6988 testl %eax,%eax # ... which returns InstrField ptr
6989 jne .LOP_IGET_BYTE_finish
6990 jmp common_exceptionThrown
6991
6992.LOP_IGET_BYTE_finish:
6993 /*
6994 * Currently:
6995 * eax holds resolved field
6996 * ecx holds object
6997 * rIBASE is scratch, but needs to be unspilled
6998 * rINST_FULL holds A
6999 */
7000 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7001 UNSPILL(rIBASE)
7002 testl %ecx,%ecx # object null?
7003 je common_errNullObject # object was null
7004 movsbl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits)
7005 movl rINST_FULL,%eax # eax<- A
7006 FETCH_INST_WORD(2)
7007 SET_VREG(%ecx,%eax)
7008 ADVANCE_PC(2)
7009 GOTO_NEXT
7010
7011
7012/* continuation for OP_IGET_CHAR */
7013
7014
7015.LOP_IGET_CHAR_resolve:
7016 EXPORT_PC()
7017 SPILL(rPC)
7018 movl offGlue_method(rIBASE),rPC # rPC<- current method
7019 UNSPILL(rIBASE)
7020 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz
7021 SPILL_TMP(%ecx) # save object pointer across call
7022 movl rPC,OUT_ARG0(%esp) # pass in method->clazz
7023 call dvmResolveInstField # ... to dvmResolveInstField
7024 UNSPILL_TMP(%ecx)
7025 UNSPILL(rPC)
7026 testl %eax,%eax # ... which returns InstrField ptr
7027 jne .LOP_IGET_CHAR_finish
7028 jmp common_exceptionThrown
7029
7030.LOP_IGET_CHAR_finish:
7031 /*
7032 * Currently:
7033 * eax holds resolved field
7034 * ecx holds object
7035 * rIBASE is scratch, but needs to be unspilled
7036 * rINST_FULL holds A
7037 */
7038 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7039 UNSPILL(rIBASE)
7040 testl %ecx,%ecx # object null?
7041 je common_errNullObject # object was null
7042 movzwl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits)
7043 movl rINST_FULL,%eax # eax<- A
7044 FETCH_INST_WORD(2)
7045 SET_VREG(%ecx,%eax)
7046 ADVANCE_PC(2)
7047 GOTO_NEXT
7048
7049
7050/* continuation for OP_IGET_SHORT */
7051
7052
7053.LOP_IGET_SHORT_resolve:
7054 EXPORT_PC()
7055 SPILL(rPC)
7056 movl offGlue_method(rIBASE),rPC # rPC<- current method
7057 UNSPILL(rIBASE)
7058 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz
7059 SPILL_TMP(%ecx) # save object pointer across call
7060 movl rPC,OUT_ARG0(%esp) # pass in method->clazz
7061 call dvmResolveInstField # ... to dvmResolveInstField
7062 UNSPILL_TMP(%ecx)
7063 UNSPILL(rPC)
7064 testl %eax,%eax # ... which returns InstrField ptr
7065 jne .LOP_IGET_SHORT_finish
7066 jmp common_exceptionThrown
7067
7068.LOP_IGET_SHORT_finish:
7069 /*
7070 * Currently:
7071 * eax holds resolved field
7072 * ecx holds object
7073 * rIBASE is scratch, but needs to be unspilled
7074 * rINST_FULL holds A
7075 */
7076 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7077 UNSPILL(rIBASE)
7078 testl %ecx,%ecx # object null?
7079 je common_errNullObject # object was null
7080 movswl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits)
7081 movl rINST_FULL,%eax # eax<- A
7082 FETCH_INST_WORD(2)
7083 SET_VREG(%ecx,%eax)
7084 ADVANCE_PC(2)
7085 GOTO_NEXT
7086
7087
7088/* continuation for OP_IPUT */
7089
7090
7091.LOP_IPUT_resolve:
7092 EXPORT_PC()
7093 SPILL(rPC)
7094 movl offGlue_method(rIBASE),rPC # rPC<- current method
7095 UNSPILL(rIBASE)
7096 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz
7097 SPILL_TMP(%ecx) # save object pointer across call
7098 movl rPC,OUT_ARG0(%esp) # pass in method->clazz
7099 call dvmResolveInstField # ... to dvmResolveInstField
7100 UNSPILL_TMP(%ecx)
7101 UNSPILL(rPC)
7102 testl %eax,%eax # ... which returns InstrField ptr
7103 jne .LOP_IPUT_finish
7104 jmp common_exceptionThrown
7105
7106.LOP_IPUT_finish:
7107 /*
7108 * Currently:
7109 * eax holds resolved field
7110 * ecx holds object
7111 * rIBASE is scratch, but needs to be unspilled
7112 * rINST_FULL holds A
7113 */
7114 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A]
7115 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7116 UNSPILL(rIBASE)
7117 testl %ecx,%ecx # object null?
7118 je common_errNullObject # object was null
7119 movl rINST_FULL,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits)
7120 FETCH_INST_WORD(2)
7121 ADVANCE_PC(2)
7122 GOTO_NEXT
7123
7124/* continuation for OP_IPUT_WIDE */
7125
7126
7127.LOP_IPUT_WIDE_resolve:
7128 EXPORT_PC()
7129 SPILL(rPC)
7130 movl offGlue_method(rIBASE),rPC # rPC<- current method
7131 UNSPILL(rIBASE)
7132 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz
7133 SPILL_TMP(%ecx) # save object pointer across call
7134 movl rPC,OUT_ARG0(%esp) # pass in method->clazz
7135 call dvmResolveInstField # ... to dvmResolveInstField
7136 UNSPILL_TMP(%ecx)
7137 UNSPILL(rPC)
7138 testl %eax,%eax # ... which returns InstrField ptr
7139 jne .LOP_IPUT_WIDE_finish
7140 jmp common_exceptionThrown
7141
7142.LOP_IPUT_WIDE_finish:
7143 /*
7144 * Currently:
7145 * eax holds resolved field
7146 * ecx holds object
7147 * rIBASE is scratch, but needs to be unspilled
7148 * rINST_FULL holds A
7149 */
7150 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7151 UNSPILL(rIBASE)
7152 testl %ecx,%ecx # object null?
7153 je common_errNullObject # object was null
7154 leal (%ecx,%eax,1),%eax # eax<- address of field
7155 GET_VREG_WORD(%ecx,rINST_FULL,0) # ecx<- lsw
7156 GET_VREG_WORD(rINST_FULL,rINST_FULL,1) # rINST_FULL<- msw
7157 movl rINST_FULL,4(%eax)
7158 FETCH_INST_WORD(2)
7159 movl %ecx,(%eax)
7160 ADVANCE_PC(2)
7161 GOTO_NEXT
7162
7163/* continuation for OP_IPUT_OBJECT */
7164
7165
7166.LOP_IPUT_OBJECT_resolve:
7167 EXPORT_PC()
7168 SPILL(rPC)
7169 movl offGlue_method(rIBASE),rPC # rPC<- current method
7170 UNSPILL(rIBASE)
7171 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz
7172 SPILL_TMP(%ecx) # save object pointer across call
7173 movl rPC,OUT_ARG0(%esp) # pass in method->clazz
7174 call dvmResolveInstField # ... to dvmResolveInstField
7175 UNSPILL_TMP(%ecx)
7176 UNSPILL(rPC)
7177 testl %eax,%eax # ... which returns InstrField ptr
7178 jne .LOP_IPUT_OBJECT_finish
7179 jmp common_exceptionThrown
7180
7181.LOP_IPUT_OBJECT_finish:
7182 /*
7183 * Currently:
7184 * eax holds resolved field
7185 * ecx holds object
7186 * rIBASE is scratch, but needs to be unspilled
7187 * rINST_FULL holds A
7188 */
7189 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A]
7190 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7191 UNSPILL(rIBASE)
7192 testl %ecx,%ecx # object null?
7193 je common_errNullObject # object was null
7194 movl rINST_FULL,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits)
7195 FETCH_INST_WORD(2)
7196 ADVANCE_PC(2)
7197 GOTO_NEXT
7198
7199/* continuation for OP_IPUT_BOOLEAN */
7200
7201
7202.LOP_IPUT_BOOLEAN_resolve:
7203 EXPORT_PC()
7204 SPILL(rPC)
7205 movl offGlue_method(rIBASE),rPC # rPC<- current method
7206 UNSPILL(rIBASE)
7207 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz
7208 SPILL_TMP(%ecx) # save object pointer across call
7209 movl rPC,OUT_ARG0(%esp) # pass in method->clazz
7210 call dvmResolveInstField # ... to dvmResolveInstField
7211 UNSPILL_TMP(%ecx)
7212 UNSPILL(rPC)
7213 testl %eax,%eax # ... which returns InstrField ptr
7214 jne .LOP_IPUT_BOOLEAN_finish
7215 jmp common_exceptionThrown
7216
7217.LOP_IPUT_BOOLEAN_finish:
7218 /*
7219 * Currently:
7220 * eax holds resolved field
7221 * ecx holds object
7222 * rIBASE is scratch, but needs to be unspilled
7223 * rINST_FULL holds A
7224 */
7225 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A]
7226 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7227 UNSPILL(rIBASE)
7228 testl %ecx,%ecx # object null?
7229 je common_errNullObject # object was null
7230 movb rINST_LO,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits)
7231 FETCH_INST_WORD(2)
7232 ADVANCE_PC(2)
7233 GOTO_NEXT
7234
7235/* continuation for OP_IPUT_BYTE */
7236
7237
7238.LOP_IPUT_BYTE_resolve:
7239 EXPORT_PC()
7240 SPILL(rPC)
7241 movl offGlue_method(rIBASE),rPC # rPC<- current method
7242 UNSPILL(rIBASE)
7243 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz
7244 SPILL_TMP(%ecx) # save object pointer across call
7245 movl rPC,OUT_ARG0(%esp) # pass in method->clazz
7246 call dvmResolveInstField # ... to dvmResolveInstField
7247 UNSPILL_TMP(%ecx)
7248 UNSPILL(rPC)
7249 testl %eax,%eax # ... which returns InstrField ptr
7250 jne .LOP_IPUT_BYTE_finish
7251 jmp common_exceptionThrown
7252
7253.LOP_IPUT_BYTE_finish:
7254 /*
7255 * Currently:
7256 * eax holds resolved field
7257 * ecx holds object
7258 * rIBASE is scratch, but needs to be unspilled
7259 * rINST_FULL holds A
7260 */
7261 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A]
7262 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7263 UNSPILL(rIBASE)
7264 testl %ecx,%ecx # object null?
7265 je common_errNullObject # object was null
7266 movb rINST_LO,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits)
7267 FETCH_INST_WORD(2)
7268 ADVANCE_PC(2)
7269 GOTO_NEXT
7270
7271/* continuation for OP_IPUT_CHAR */
7272
7273
7274.LOP_IPUT_CHAR_resolve:
7275 EXPORT_PC()
7276 SPILL(rPC)
7277 movl offGlue_method(rIBASE),rPC # rPC<- current method
7278 UNSPILL(rIBASE)
7279 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz
7280 SPILL_TMP(%ecx) # save object pointer across call
7281 movl rPC,OUT_ARG0(%esp) # pass in method->clazz
7282 call dvmResolveInstField # ... to dvmResolveInstField
7283 UNSPILL_TMP(%ecx)
7284 UNSPILL(rPC)
7285 testl %eax,%eax # ... which returns InstrField ptr
7286 jne .LOP_IPUT_CHAR_finish
7287 jmp common_exceptionThrown
7288
7289.LOP_IPUT_CHAR_finish:
7290 /*
7291 * Currently:
7292 * eax holds resolved field
7293 * ecx holds object
7294 * rIBASE is scratch, but needs to be unspilled
7295 * rINST_FULL holds A
7296 */
7297 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A]
7298 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7299 UNSPILL(rIBASE)
7300 testl %ecx,%ecx # object null?
7301 je common_errNullObject # object was null
7302 movw rINST,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits)
7303 FETCH_INST_WORD(2)
7304 ADVANCE_PC(2)
7305 GOTO_NEXT
7306
7307/* continuation for OP_IPUT_SHORT */
7308
7309
7310.LOP_IPUT_SHORT_resolve:
7311 EXPORT_PC()
7312 SPILL(rPC)
7313 movl offGlue_method(rIBASE),rPC # rPC<- current method
7314 UNSPILL(rIBASE)
7315 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz
7316 SPILL_TMP(%ecx) # save object pointer across call
7317 movl rPC,OUT_ARG0(%esp) # pass in method->clazz
7318 call dvmResolveInstField # ... to dvmResolveInstField
7319 UNSPILL_TMP(%ecx)
7320 UNSPILL(rPC)
7321 testl %eax,%eax # ... which returns InstrField ptr
7322 jne .LOP_IPUT_SHORT_finish
7323 jmp common_exceptionThrown
7324
7325.LOP_IPUT_SHORT_finish:
7326 /*
7327 * Currently:
7328 * eax holds resolved field
7329 * ecx holds object
7330 * rIBASE is scratch, but needs to be unspilled
7331 * rINST_FULL holds A
7332 */
7333 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A]
7334 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
7335 UNSPILL(rIBASE)
7336 testl %ecx,%ecx # object null?
7337 je common_errNullObject # object was null
7338 movw rINST,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits)
7339 FETCH_INST_WORD(2)
7340 ADVANCE_PC(2)
7341 GOTO_NEXT
7342
7343/* continuation for OP_SGET */
7344
7345 /*
7346 * Go resolve the field
7347 */
7348.LOP_SGET_resolve:
7349 GET_GLUE(%ecx)
7350 movzwl 2(rPC),%eax # eax<- field ref BBBB
7351 movl offGlue_method(%ecx),%ecx # ecx<- current method
7352 EXPORT_PC() # could throw, need to export
7353 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7354 SPILL(rPC)
7355 movl %eax,OUT_ARG1(%esp)
7356 movl %ecx,OUT_ARG0(%esp)
7357 call dvmResolveStaticField # eax<- resolved StaticField ptr
7358 UNSPILL(rPC)
7359 testl %eax,%eax
7360 jne .LOP_SGET_finish # success, continue
7361 jmp common_exceptionThrown # no, handle exception
7362
7363
7364/* continuation for OP_SGET_WIDE */
7365
7366 /*
7367 * Go resolve the field
7368 */
7369.LOP_SGET_WIDE_resolve:
7370 GET_GLUE(%ecx)
7371 movzwl 2(rPC),%eax # eax<- field ref BBBB
7372 movl offGlue_method(%ecx),%ecx # ecx<- current method
7373 EXPORT_PC() # could throw, need to export
7374 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7375 SPILL(rPC)
7376 movl %eax,OUT_ARG1(%esp)
7377 movl %ecx,OUT_ARG0(%esp)
7378 call dvmResolveStaticField # eax<- resolved StaticField ptr
7379 UNSPILL(rPC)
7380 testl %eax,%eax
7381 jne .LOP_SGET_WIDE_finish # success, continue
7382 jmp common_exceptionThrown # no, handle exception
7383
7384
7385/* continuation for OP_SGET_OBJECT */
7386
7387 /*
7388 * Go resolve the field
7389 */
7390.LOP_SGET_OBJECT_resolve:
7391 GET_GLUE(%ecx)
7392 movzwl 2(rPC),%eax # eax<- field ref BBBB
7393 movl offGlue_method(%ecx),%ecx # ecx<- current method
7394 EXPORT_PC() # could throw, need to export
7395 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7396 SPILL(rPC)
7397 movl %eax,OUT_ARG1(%esp)
7398 movl %ecx,OUT_ARG0(%esp)
7399 call dvmResolveStaticField # eax<- resolved StaticField ptr
7400 UNSPILL(rPC)
7401 testl %eax,%eax
7402 jne .LOP_SGET_OBJECT_finish # success, continue
7403 jmp common_exceptionThrown # no, handle exception
7404
7405
7406/* continuation for OP_SGET_BOOLEAN */
7407
7408 /*
7409 * Go resolve the field
7410 */
7411.LOP_SGET_BOOLEAN_resolve:
7412 GET_GLUE(%ecx)
7413 movzwl 2(rPC),%eax # eax<- field ref BBBB
7414 movl offGlue_method(%ecx),%ecx # ecx<- current method
7415 EXPORT_PC() # could throw, need to export
7416 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7417 SPILL(rPC)
7418 movl %eax,OUT_ARG1(%esp)
7419 movl %ecx,OUT_ARG0(%esp)
7420 call dvmResolveStaticField # eax<- resolved StaticField ptr
7421 UNSPILL(rPC)
7422 testl %eax,%eax
7423 jne .LOP_SGET_BOOLEAN_finish # success, continue
7424 jmp common_exceptionThrown # no, handle exception
7425
7426
7427/* continuation for OP_SGET_BYTE */
7428
7429 /*
7430 * Go resolve the field
7431 */
7432.LOP_SGET_BYTE_resolve:
7433 GET_GLUE(%ecx)
7434 movzwl 2(rPC),%eax # eax<- field ref BBBB
7435 movl offGlue_method(%ecx),%ecx # ecx<- current method
7436 EXPORT_PC() # could throw, need to export
7437 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7438 SPILL(rPC)
7439 movl %eax,OUT_ARG1(%esp)
7440 movl %ecx,OUT_ARG0(%esp)
7441 call dvmResolveStaticField # eax<- resolved StaticField ptr
7442 UNSPILL(rPC)
7443 testl %eax,%eax
7444 jne .LOP_SGET_BYTE_finish # success, continue
7445 jmp common_exceptionThrown # no, handle exception
7446
7447
7448/* continuation for OP_SGET_CHAR */
7449
7450 /*
7451 * Go resolve the field
7452 */
7453.LOP_SGET_CHAR_resolve:
7454 GET_GLUE(%ecx)
7455 movzwl 2(rPC),%eax # eax<- field ref BBBB
7456 movl offGlue_method(%ecx),%ecx # ecx<- current method
7457 EXPORT_PC() # could throw, need to export
7458 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7459 SPILL(rPC)
7460 movl %eax,OUT_ARG1(%esp)
7461 movl %ecx,OUT_ARG0(%esp)
7462 call dvmResolveStaticField # eax<- resolved StaticField ptr
7463 UNSPILL(rPC)
7464 testl %eax,%eax
7465 jne .LOP_SGET_CHAR_finish # success, continue
7466 jmp common_exceptionThrown # no, handle exception
7467
7468
7469/* continuation for OP_SGET_SHORT */
7470
7471 /*
7472 * Go resolve the field
7473 */
7474.LOP_SGET_SHORT_resolve:
7475 GET_GLUE(%ecx)
7476 movzwl 2(rPC),%eax # eax<- field ref BBBB
7477 movl offGlue_method(%ecx),%ecx # ecx<- current method
7478 EXPORT_PC() # could throw, need to export
7479 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7480 SPILL(rPC)
7481 movl %eax,OUT_ARG1(%esp)
7482 movl %ecx,OUT_ARG0(%esp)
7483 call dvmResolveStaticField # eax<- resolved StaticField ptr
7484 UNSPILL(rPC)
7485 testl %eax,%eax
7486 jne .LOP_SGET_SHORT_finish # success, continue
7487 jmp common_exceptionThrown # no, handle exception
7488
7489
7490/* continuation for OP_SPUT */
7491
7492 /*
7493 * Go resolve the field
7494 */
7495.LOP_SPUT_resolve:
7496 GET_GLUE(%ecx)
7497 movzwl 2(rPC),%eax # eax<- field ref BBBB
7498 movl offGlue_method(%ecx),%ecx # ecx<- current method
7499 EXPORT_PC() # could throw, need to export
7500 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7501 SPILL(rPC)
7502 movl %eax,OUT_ARG1(%esp)
7503 movl %ecx,OUT_ARG0(%esp)
7504 call dvmResolveStaticField # eax<- resolved StaticField ptr
7505 UNSPILL(rPC)
7506 testl %eax,%eax
7507 jne .LOP_SPUT_finish # success, continue
7508 jmp common_exceptionThrown # no, handle exception
7509
7510
7511/* continuation for OP_SPUT_WIDE */
7512
7513 /*
7514 * Go resolve the field
7515 */
7516.LOP_SPUT_WIDE_resolve:
7517 GET_GLUE(%ecx)
7518 movzwl 2(rPC),%eax # eax<- field ref BBBB
7519 movl offGlue_method(%ecx),%ecx # ecx<- current method
7520 EXPORT_PC() # could throw, need to export
7521 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7522 SPILL(rPC)
7523 movl %eax,OUT_ARG1(%esp)
7524 movl %ecx,OUT_ARG0(%esp)
7525 call dvmResolveStaticField # eax<- resolved StaticField ptr
7526 UNSPILL(rPC)
7527 testl %eax,%eax
7528 jne .LOP_SPUT_WIDE_finish # success, continue
7529 jmp common_exceptionThrown # no, handle exception
7530
7531
7532/* continuation for OP_SPUT_OBJECT */
7533
7534 /*
7535 * Go resolve the field
7536 */
7537.LOP_SPUT_OBJECT_resolve:
7538 GET_GLUE(%ecx)
7539 movzwl 2(rPC),%eax # eax<- field ref BBBB
7540 movl offGlue_method(%ecx),%ecx # ecx<- current method
7541 EXPORT_PC() # could throw, need to export
7542 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7543 SPILL(rPC)
7544 movl %eax,OUT_ARG1(%esp)
7545 movl %ecx,OUT_ARG0(%esp)
7546 call dvmResolveStaticField # eax<- resolved StaticField ptr
7547 UNSPILL(rPC)
7548 testl %eax,%eax
7549 jne .LOP_SPUT_OBJECT_finish # success, continue
7550 jmp common_exceptionThrown # no, handle exception
7551
7552
7553/* continuation for OP_SPUT_BOOLEAN */
7554
7555 /*
7556 * Go resolve the field
7557 */
7558.LOP_SPUT_BOOLEAN_resolve:
7559 GET_GLUE(%ecx)
7560 movzwl 2(rPC),%eax # eax<- field ref BBBB
7561 movl offGlue_method(%ecx),%ecx # ecx<- current method
7562 EXPORT_PC() # could throw, need to export
7563 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7564 SPILL(rPC)
7565 movl %eax,OUT_ARG1(%esp)
7566 movl %ecx,OUT_ARG0(%esp)
7567 call dvmResolveStaticField # eax<- resolved StaticField ptr
7568 UNSPILL(rPC)
7569 testl %eax,%eax
7570 jne .LOP_SPUT_BOOLEAN_finish # success, continue
7571 jmp common_exceptionThrown # no, handle exception
7572
7573
7574/* continuation for OP_SPUT_BYTE */
7575
7576 /*
7577 * Go resolve the field
7578 */
7579.LOP_SPUT_BYTE_resolve:
7580 GET_GLUE(%ecx)
7581 movzwl 2(rPC),%eax # eax<- field ref BBBB
7582 movl offGlue_method(%ecx),%ecx # ecx<- current method
7583 EXPORT_PC() # could throw, need to export
7584 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7585 SPILL(rPC)
7586 movl %eax,OUT_ARG1(%esp)
7587 movl %ecx,OUT_ARG0(%esp)
7588 call dvmResolveStaticField # eax<- resolved StaticField ptr
7589 UNSPILL(rPC)
7590 testl %eax,%eax
7591 jne .LOP_SPUT_BYTE_finish # success, continue
7592 jmp common_exceptionThrown # no, handle exception
7593
7594
7595/* continuation for OP_SPUT_CHAR */
7596
7597 /*
7598 * Go resolve the field
7599 */
7600.LOP_SPUT_CHAR_resolve:
7601 GET_GLUE(%ecx)
7602 movzwl 2(rPC),%eax # eax<- field ref BBBB
7603 movl offGlue_method(%ecx),%ecx # ecx<- current method
7604 EXPORT_PC() # could throw, need to export
7605 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7606 SPILL(rPC)
7607 movl %eax,OUT_ARG1(%esp)
7608 movl %ecx,OUT_ARG0(%esp)
7609 call dvmResolveStaticField # eax<- resolved StaticField ptr
7610 UNSPILL(rPC)
7611 testl %eax,%eax
7612 jne .LOP_SPUT_CHAR_finish # success, continue
7613 jmp common_exceptionThrown # no, handle exception
7614
7615
7616/* continuation for OP_SPUT_SHORT */
7617
7618 /*
7619 * Go resolve the field
7620 */
7621.LOP_SPUT_SHORT_resolve:
7622 GET_GLUE(%ecx)
7623 movzwl 2(rPC),%eax # eax<- field ref BBBB
7624 movl offGlue_method(%ecx),%ecx # ecx<- current method
7625 EXPORT_PC() # could throw, need to export
7626 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7627 SPILL(rPC)
7628 movl %eax,OUT_ARG1(%esp)
7629 movl %ecx,OUT_ARG0(%esp)
7630 call dvmResolveStaticField # eax<- resolved StaticField ptr
7631 UNSPILL(rPC)
7632 testl %eax,%eax
7633 jne .LOP_SPUT_SHORT_finish # success, continue
7634 jmp common_exceptionThrown # no, handle exception
7635
7636
7637/* continuation for OP_INVOKE_VIRTUAL */
7638
7639
7640.LOP_INVOKE_VIRTUAL_more:
7641 movl offMethod_clazz(%eax),%eax # ecx<- method->clazz
7642 movl %eax,OUT_ARG0(%esp) # arg0<- clazz
7643 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags
7644 call dvmResolveMethod # eax<- call(clazz, ref, flags)
7645 UNSPILL(rPC)
7646 testl %eax,%eax # got null?
7647 jne .LOP_INVOKE_VIRTUAL_continue # no, continue
7648 jmp common_exceptionThrown # yes, handle exception
7649
7650 /* At this point:
7651 * eax = resolved base method
7652 * ecx = scratch
7653 */
7654.LOP_INVOKE_VIRTUAL_continue:
7655 movzwl 4(rPC),%ecx # ecx<- GFED or CCCC
7656 .if (!0)
7657 andl $0xf,%ecx # ecx<- D (or stays CCCC)
7658 .endif
7659 GET_VREG(%ecx,%ecx) # ecx<- "this"
7660 movzwl offMethod_methodIndex(%eax),%eax # eax<- baseMethod->methodIndex
7661 testl %ecx,%ecx # null this?
7662 je common_errNullObject # go if so
7663 movl offObject_clazz(%ecx),%ecx # ecx<- thisPtr->clazz
7664 movl offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable
7665 movl (%ecx,%eax,4),%eax # eax<- vtable[methodIndex]
Johnnie Birchc4080f62009-02-10 15:41:06 -08007666 jmp common_invokeMethodNoRange
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08007667
7668
7669/* continuation for OP_INVOKE_SUPER */
7670
7671 /*
7672 * At this point:
7673 * ecx = resolved base method [r0]
7674 * eax = method->clazz [r9]
7675 */
7676.LOP_INVOKE_SUPER_continue:
7677 movl offClassObject_super(%eax),%eax # eax<- method->clazz->super
7678 movzwl offMethod_methodIndex(%ecx),%ecx # ecx<- baseMthod->methodIndex
7679 cmpl offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount)
7680 jae .LOP_INVOKE_SUPER_nsm # method not present in superclass
7681 movl offClassObject_vtable(%eax),%eax # eax<- ...clazz->super->vtable
7682 movl (%eax,%ecx,4),%eax # eax<- vtable[methodIndex]
Johnnie Birchc4080f62009-02-10 15:41:06 -08007683 jmp common_invokeMethodNoRange
7684
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08007685
7686 /* At this point:
7687 * ecx = null (needs to be resolved base method)
7688 * eax = method->clazz
7689 */
7690.LOP_INVOKE_SUPER_resolve:
7691 SPILL_TMP(%eax) # method->clazz
7692 movl %eax,OUT_ARG0(%esp) # arg0<- method->clazz
7693 movzwl 2(rPC),%ecx # ecx<- BBBB
7694 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- resolver method type
7695 movl %ecx,OUT_ARG1(%esp) # arg1<- ref
7696 SPILL(rPC)
7697 call dvmResolveMethod # eax<- call(clazz, ref, flags)
7698 UNSPILL(rPC)
7699 testl %eax,%eax # got null?
7700 movl %eax,%ecx # ecx<- resolved base method
7701 UNSPILL_TMP(%eax) # restore method->clazz
7702 jne .LOP_INVOKE_SUPER_continue # good to go - continue
7703 jmp common_exceptionThrown # handle exception
7704
7705 /*
7706 * Throw a NoSuchMethodError with the method name as the message.
7707 * ecx = resolved base method
7708 */
7709.LOP_INVOKE_SUPER_nsm:
7710 movl offMethod_name(%ecx),%eax
7711 mov %eax,OUT_ARG1(%esp)
7712 jmp common_errNoSuchMethod
7713
7714/* continuation for OP_INVOKE_DIRECT */
7715
7716 /*
7717 * On entry:
7718 * TMP_SPILL <- "this" register
7719 * Things a bit ugly on this path, but it's the less
7720 * frequent one. We'll have to do some reloading.
7721 */
7722.LOP_INVOKE_DIRECT_resolve:
7723 SPILL_TMP(%ecx)
7724 GET_GLUE(%ecx)
7725 UNSPILL(rPC)
7726 movl offGlue_method(%ecx),%ecx # ecx<- glue->method
7727 movzwl 2(rPC),%eax # reference (BBBB or CCCC)
7728 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7729 movl $METHOD_DIRECT,OUT_ARG2(%esp)
7730 movl %eax,OUT_ARG1(%esp)
7731 movl %ecx,OUT_ARG0(%esp)
7732 call dvmResolveMethod # eax<- call(clazz, ref, flags)
7733 UNSPILL_TMP(%ecx)
7734 testl %eax,%eax
7735 jne .LOP_INVOKE_DIRECT_finish
7736 UNSPILL(rPC)
7737 jmp common_exceptionThrown
7738
7739/* continuation for OP_INVOKE_STATIC */
7740
7741.LOP_INVOKE_STATIC_continue:
7742 movl $METHOD_STATIC,%eax
7743 movl %eax,OUT_ARG2(%esp) # arg2<- flags
7744 SPILL(rPC)
7745 call dvmResolveMethod # call(clazz,ref,flags)
7746 UNSPILL(rPC)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08007747 testl %eax,%eax # got null?
Johnnie Birchc4080f62009-02-10 15:41:06 -08007748 jne common_invokeMethodNoRange
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08007749 jmp common_exceptionThrown
7750
7751
7752/* continuation for OP_INVOKE_INTERFACE */
7753
7754.LOP_INVOKE_INTERFACE_continue:
7755 call dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex)
7756 UNSPILL(rPC)
7757 testl %eax,%eax
7758 je common_exceptionThrown
Johnnie Birchc4080f62009-02-10 15:41:06 -08007759 jmp common_invokeMethodNoRange
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08007760
7761
7762/* continuation for OP_INVOKE_VIRTUAL_RANGE */
7763
7764
7765.LOP_INVOKE_VIRTUAL_RANGE_more:
7766 movl offMethod_clazz(%eax),%eax # ecx<- method->clazz
7767 movl %eax,OUT_ARG0(%esp) # arg0<- clazz
7768 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags
7769 call dvmResolveMethod # eax<- call(clazz, ref, flags)
7770 UNSPILL(rPC)
7771 testl %eax,%eax # got null?
7772 jne .LOP_INVOKE_VIRTUAL_RANGE_continue # no, continue
7773 jmp common_exceptionThrown # yes, handle exception
7774
7775 /* At this point:
7776 * eax = resolved base method
7777 * ecx = scratch
7778 */
7779.LOP_INVOKE_VIRTUAL_RANGE_continue:
7780 movzwl 4(rPC),%ecx # ecx<- GFED or CCCC
7781 .if (!1)
7782 andl $0xf,%ecx # ecx<- D (or stays CCCC)
7783 .endif
7784 GET_VREG(%ecx,%ecx) # ecx<- "this"
7785 movzwl offMethod_methodIndex(%eax),%eax # eax<- baseMethod->methodIndex
7786 testl %ecx,%ecx # null this?
7787 je common_errNullObject # go if so
7788 movl offObject_clazz(%ecx),%ecx # ecx<- thisPtr->clazz
7789 movl offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable
7790 movl (%ecx,%eax,4),%eax # eax<- vtable[methodIndex]
Johnnie Birchc4080f62009-02-10 15:41:06 -08007791 jmp common_invokeMethodRange
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08007792
7793
7794/* continuation for OP_INVOKE_SUPER_RANGE */
7795
7796 /*
7797 * At this point:
7798 * ecx = resolved base method [r0]
7799 * eax = method->clazz [r9]
7800 */
7801.LOP_INVOKE_SUPER_RANGE_continue:
7802 movl offClassObject_super(%eax),%eax # eax<- method->clazz->super
7803 movzwl offMethod_methodIndex(%ecx),%ecx # ecx<- baseMthod->methodIndex
7804 cmpl offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount)
7805 jae .LOP_INVOKE_SUPER_RANGE_nsm # method not present in superclass
7806 movl offClassObject_vtable(%eax),%eax # eax<- ...clazz->super->vtable
7807 movl (%eax,%ecx,4),%eax # eax<- vtable[methodIndex]
Johnnie Birchc4080f62009-02-10 15:41:06 -08007808 jmp common_invokeMethodRange
7809
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08007810
7811 /* At this point:
7812 * ecx = null (needs to be resolved base method)
7813 * eax = method->clazz
7814 */
7815.LOP_INVOKE_SUPER_RANGE_resolve:
7816 SPILL_TMP(%eax) # method->clazz
7817 movl %eax,OUT_ARG0(%esp) # arg0<- method->clazz
7818 movzwl 2(rPC),%ecx # ecx<- BBBB
7819 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- resolver method type
7820 movl %ecx,OUT_ARG1(%esp) # arg1<- ref
7821 SPILL(rPC)
7822 call dvmResolveMethod # eax<- call(clazz, ref, flags)
7823 UNSPILL(rPC)
7824 testl %eax,%eax # got null?
7825 movl %eax,%ecx # ecx<- resolved base method
7826 UNSPILL_TMP(%eax) # restore method->clazz
7827 jne .LOP_INVOKE_SUPER_RANGE_continue # good to go - continue
7828 jmp common_exceptionThrown # handle exception
7829
7830 /*
7831 * Throw a NoSuchMethodError with the method name as the message.
7832 * ecx = resolved base method
7833 */
7834.LOP_INVOKE_SUPER_RANGE_nsm:
7835 movl offMethod_name(%ecx),%eax
7836 mov %eax,OUT_ARG1(%esp)
7837 jmp common_errNoSuchMethod
7838
7839/* continuation for OP_INVOKE_DIRECT_RANGE */
7840
7841 /*
7842 * On entry:
7843 * TMP_SPILL <- "this" register
7844 * Things a bit ugly on this path, but it's the less
7845 * frequent one. We'll have to do some reloading.
7846 */
7847.LOP_INVOKE_DIRECT_RANGE_resolve:
7848 SPILL_TMP(%ecx)
7849 GET_GLUE(%ecx)
7850 UNSPILL(rPC)
7851 movl offGlue_method(%ecx),%ecx # ecx<- glue->method
7852 movzwl 2(rPC),%eax # reference (BBBB or CCCC)
7853 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7854 movl $METHOD_DIRECT,OUT_ARG2(%esp)
7855 movl %eax,OUT_ARG1(%esp)
7856 movl %ecx,OUT_ARG0(%esp)
7857 call dvmResolveMethod # eax<- call(clazz, ref, flags)
7858 UNSPILL_TMP(%ecx)
7859 testl %eax,%eax
7860 jne .LOP_INVOKE_DIRECT_RANGE_finish
7861 UNSPILL(rPC)
7862 jmp common_exceptionThrown
7863
7864/* continuation for OP_INVOKE_STATIC_RANGE */
7865
7866.LOP_INVOKE_STATIC_RANGE_continue:
7867 movl $METHOD_STATIC,%eax
7868 movl %eax,OUT_ARG2(%esp) # arg2<- flags
7869 SPILL(rPC)
7870 call dvmResolveMethod # call(clazz,ref,flags)
7871 UNSPILL(rPC)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08007872 testl %eax,%eax # got null?
Johnnie Birchc4080f62009-02-10 15:41:06 -08007873 jne common_invokeMethodRange
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08007874 jmp common_exceptionThrown
7875
7876
7877/* continuation for OP_INVOKE_INTERFACE_RANGE */
7878
7879.LOP_INVOKE_INTERFACE_RANGE_continue:
7880 call dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex)
7881 UNSPILL(rPC)
7882 testl %eax,%eax
7883 je common_exceptionThrown
Johnnie Birchc4080f62009-02-10 15:41:06 -08007884 jmp common_invokeMethodRange
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08007885
7886
7887/* continuation for OP_FLOAT_TO_INT */
7888
7889
7890.LOP_FLOAT_TO_INT_continue:
7891 .if 0
7892 movl $0x80000000,%eax
7893 xorl 4(rFP,%ecx,4),%eax
7894 orl (rFP,%ecx,4),%eax
7895 .else
7896 cmpl $0x80000000,(rFP,%ecx,4)
7897 .endif
7898 je .LOP_FLOAT_TO_INT_special_case # fix up result
7899
7900.LOP_FLOAT_TO_INT_finish:
7901 ADVANCE_PC(1)
7902 GOTO_NEXT
7903
7904.LOP_FLOAT_TO_INT_special_case:
7905 fnstsw %ax
7906 sahf
7907 jp .LOP_FLOAT_TO_INT_isNaN
7908 adcl $-1,(rFP,%ecx,4)
7909 .if 0
7910 adcl $-1,4(rFP,%ecx,4)
7911 .endif
7912 jmp .LOP_FLOAT_TO_INT_finish
7913.LOP_FLOAT_TO_INT_isNaN:
7914 movl $0,(rFP,%ecx,4)
7915 .if 0
7916 movl $0,4(rFP,%ecx,4)
7917 .endif
7918 jmp .LOP_FLOAT_TO_INT_finish
7919
7920/* continuation for OP_FLOAT_TO_LONG */
7921
7922
7923.LOP_FLOAT_TO_LONG_continue:
7924 .if 1
7925 movl $0x80000000,%eax
7926 xorl 4(rFP,%ecx,4),%eax
7927 orl (rFP,%ecx,4),%eax
7928 .else
7929 cmpl $0x80000000,(rFP,%ecx,4)
7930 .endif
7931 je .LOP_FLOAT_TO_LONG_special_case # fix up result
7932
7933.LOP_FLOAT_TO_LONG_finish:
7934 ADVANCE_PC(1)
7935 GOTO_NEXT
7936
7937.LOP_FLOAT_TO_LONG_special_case:
7938 fnstsw %ax
7939 sahf
7940 jp .LOP_FLOAT_TO_LONG_isNaN
7941 adcl $-1,(rFP,%ecx,4)
7942 .if 1
7943 adcl $-1,4(rFP,%ecx,4)
7944 .endif
7945 jmp .LOP_FLOAT_TO_LONG_finish
7946.LOP_FLOAT_TO_LONG_isNaN:
7947 movl $0,(rFP,%ecx,4)
7948 .if 1
7949 movl $0,4(rFP,%ecx,4)
7950 .endif
7951 jmp .LOP_FLOAT_TO_LONG_finish
7952
7953/* continuation for OP_DOUBLE_TO_INT */
7954
7955
7956.LOP_DOUBLE_TO_INT_continue:
7957 .if 0
7958 movl $0x80000000,%eax
7959 xorl 4(rFP,%ecx,4),%eax
7960 orl (rFP,%ecx,4),%eax
7961 .else
7962 cmpl $0x80000000,(rFP,%ecx,4)
7963 .endif
7964 je .LOP_DOUBLE_TO_INT_special_case # fix up result
7965
7966.LOP_DOUBLE_TO_INT_finish:
7967 ADVANCE_PC(1)
7968 GOTO_NEXT
7969
7970.LOP_DOUBLE_TO_INT_special_case:
7971 fnstsw %ax
7972 sahf
7973 jp .LOP_DOUBLE_TO_INT_isNaN
7974 adcl $-1,(rFP,%ecx,4)
7975 .if 0
7976 adcl $-1,4(rFP,%ecx,4)
7977 .endif
7978 jmp .LOP_DOUBLE_TO_INT_finish
7979.LOP_DOUBLE_TO_INT_isNaN:
7980 movl $0,(rFP,%ecx,4)
7981 .if 0
7982 movl $0,4(rFP,%ecx,4)
7983 .endif
7984 jmp .LOP_DOUBLE_TO_INT_finish
7985
7986/* continuation for OP_DOUBLE_TO_LONG */
7987
7988
7989.LOP_DOUBLE_TO_LONG_continue:
7990 .if 1
7991 movl $0x80000000,%eax
7992 xorl 4(rFP,%ecx,4),%eax
7993 orl (rFP,%ecx,4),%eax
7994 .else
7995 cmpl $0x80000000,(rFP,%ecx,4)
7996 .endif
7997 je .LOP_DOUBLE_TO_LONG_special_case # fix up result
7998
7999.LOP_DOUBLE_TO_LONG_finish:
8000 ADVANCE_PC(1)
8001 GOTO_NEXT
8002
8003.LOP_DOUBLE_TO_LONG_special_case:
8004 fnstsw %ax
8005 sahf
8006 jp .LOP_DOUBLE_TO_LONG_isNaN
8007 adcl $-1,(rFP,%ecx,4)
8008 .if 1
8009 adcl $-1,4(rFP,%ecx,4)
8010 .endif
8011 jmp .LOP_DOUBLE_TO_LONG_finish
8012.LOP_DOUBLE_TO_LONG_isNaN:
8013 movl $0,(rFP,%ecx,4)
8014 .if 1
8015 movl $0,4(rFP,%ecx,4)
8016 .endif
8017 jmp .LOP_DOUBLE_TO_LONG_finish
8018
8019/* continuation for OP_DIV_INT */
8020.LOP_DIV_INT_continue_div:
8021 cltd
8022 idivl %ecx
8023.LOP_DIV_INT_finish_div:
8024 movzbl rINST_HI,%ecx # ecl<- AA
8025 SET_VREG(%eax,%ecx)
8026 UNSPILL(rPC)
8027 FETCH_INST_WORD(2)
8028 ADVANCE_PC(2)
8029 GOTO_NEXT
8030
8031/* continuation for OP_REM_INT */
8032.LOP_REM_INT_continue_div:
8033 cltd
8034 idivl %ecx
8035.LOP_REM_INT_finish_div:
8036 movzbl rINST_HI,%ecx # ecl<- AA
8037 SET_VREG(%edx,%ecx)
8038 UNSPILL(rPC)
8039 FETCH_INST_WORD(2)
8040 ADVANCE_PC(2)
8041 GOTO_NEXT
8042
8043/* continuation for OP_MUL_LONG */
8044
8045.LOP_MUL_LONG_continue:
8046 leal (%ecx,%edx),%edx # full result now in %edx:%eax
8047 movzbl rINST_HI,%ecx # ecx<- A
8048 movl %edx,4(rFP,%ecx,4) # v[B+1]<- %edx
8049 UNSPILL(rPC) # restore rPC/%edx
8050 FETCH_INST_WORD(2)
8051 UNSPILL(rIBASE)
8052 movl %eax,(rFP,%ecx,4) # v[B]<- %eax
8053 ADVANCE_PC(2)
8054 GOTO_NEXT
8055
8056
8057/* continuation for OP_DIV_LONG */
8058
8059.LOP_DIV_LONG_continue:
8060 call __divdi3
8061.LOP_DIV_LONG_finish:
8062 movzbl rINST_HI,%ecx
8063 SET_VREG_WORD(rPC,%ecx,1)
8064 UNSPILL(rPC)
8065 SET_VREG_WORD(%eax,%ecx,0)
8066 FETCH_INST_WORD(2)
8067 ADVANCE_PC(2)
8068 GOTO_NEXT
8069
8070.LOP_DIV_LONG_check_zero:
8071 testl rPC,rPC
8072 jne .LOP_DIV_LONG_notSpecial
8073 UNSPILL(rPC)
8074 jmp common_errDivideByZero
8075.LOP_DIV_LONG_check_neg1:
8076 testl rPC,%eax
8077 jne .LOP_DIV_LONG_notSpecial
8078 GET_VREG_WORD(rPC,%ecx,0)
8079 GET_VREG_WORD(%ecx,%ecx,1)
8080 testl rPC,rPC
8081 jne .LOP_DIV_LONG_notSpecial1
8082 cmpl $0x80000000,%ecx
8083 jne .LOP_DIV_LONG_notSpecial1
8084 /* minint / -1, return minint on div, 0 on rem */
8085 xorl %eax,%eax
8086 movl $0x80000000,%edx
8087 jmp .LOP_DIV_LONG_finish
8088
8089
8090
8091
8092/* continuation for OP_REM_LONG */
8093
8094.LOP_REM_LONG_continue:
8095 call __moddi3
8096.LOP_REM_LONG_finish:
8097 movzbl rINST_HI,%ecx
8098 SET_VREG_WORD(rPC,%ecx,1)
8099 UNSPILL(rPC)
8100 SET_VREG_WORD(%eax,%ecx,0)
8101 FETCH_INST_WORD(2)
8102 ADVANCE_PC(2)
8103 GOTO_NEXT
8104
8105.LOP_REM_LONG_check_zero:
8106 testl rPC,rPC
8107 jne .LOP_REM_LONG_notSpecial
8108 UNSPILL(rPC)
8109 jmp common_errDivideByZero
8110.LOP_REM_LONG_check_neg1:
8111 testl rPC,%eax
8112 jne .LOP_REM_LONG_notSpecial
8113 GET_VREG_WORD(rPC,%ecx,0)
8114 GET_VREG_WORD(%ecx,%ecx,1)
8115 testl rPC,rPC
8116 jne .LOP_REM_LONG_notSpecial1
8117 cmpl $0x80000000,%ecx
8118 jne .LOP_REM_LONG_notSpecial1
8119 /* minint / -1, return minint on div, 0 on rem */
8120 xorl %eax,%eax
8121 movl $0,%edx
8122 jmp .LOP_REM_LONG_finish
8123
8124
8125
8126
8127/* continuation for OP_SHL_LONG */
8128
8129.LOP_SHL_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_SHR_LONG */
8135
8136
8137.LOP_SHR_LONG_finish:
8138 SET_VREG_WORD(%eax,%ecx,0) # v[AA+0]<- eax
8139 ADVANCE_PC(2)
8140 GOTO_NEXT
8141
8142/* continuation for OP_USHR_LONG */
8143
8144
8145.LOP_USHR_LONG_finish:
8146 SET_VREG_WORD(%eax,%ecx,0) # v[BB+0]<- eax
8147 FETCH_INST_WORD(2)
8148 ADVANCE_PC(2)
8149 GOTO_NEXT
8150
8151/* continuation for OP_DIV_INT_2ADDR */
8152.LOP_DIV_INT_2ADDR_continue_div2addr:
8153 cltd
8154 idivl %ecx
8155.LOP_DIV_INT_2ADDR_finish_div2addr:
8156 SET_VREG(%eax,rINST_FULL)
8157 UNSPILL(rPC)
8158 FETCH_INST_WORD(1)
8159 ADVANCE_PC(1)
8160 GOTO_NEXT
8161
8162/* continuation for OP_REM_INT_2ADDR */
8163.LOP_REM_INT_2ADDR_continue_div2addr:
8164 cltd
8165 idivl %ecx
8166.LOP_REM_INT_2ADDR_finish_div2addr:
8167 SET_VREG(%edx,rINST_FULL)
8168 UNSPILL(rPC)
8169 FETCH_INST_WORD(1)
8170 ADVANCE_PC(1)
8171 GOTO_NEXT
8172
8173/* continuation for OP_MUL_LONG_2ADDR */
8174
8175.LOP_MUL_LONG_2ADDR_continue:
8176 leal (%ecx,%edx),%edx # full result now in %edx:%eax
8177 movl %edx,4(rIBASE) # v[A+1]<- %edx
8178 UNSPILL(rPC) # restore rPC/%edx
8179 FETCH_INST_WORD(1)
8180 movl %eax,(rIBASE) # v[A]<- %eax
8181 UNSPILL(rFP)
8182 UNSPILL(rIBASE)
8183 ADVANCE_PC(1)
8184 GOTO_NEXT
8185
8186
8187/* continuation for OP_DIV_LONG_2ADDR */
8188
8189.LOP_DIV_LONG_2ADDR_continue:
8190 movl %eax,OUT_ARG3(%esp)
8191 movl rPC,OUT_ARG0(%esp)
8192 movl %ecx,OUT_ARG1(%esp)
8193 call __divdi3
8194.LOP_DIV_LONG_2ADDR_finish:
8195 movl rINST_FULL,%ecx
8196 SET_VREG_WORD(rPC,%ecx,1)
8197 UNSPILL(rPC)
8198 SET_VREG_WORD(%eax,%ecx,0)
8199 FETCH_INST_WORD(1)
8200 ADVANCE_PC(1)
8201 GOTO_NEXT
8202
8203.LOP_DIV_LONG_2ADDR_check_zero:
8204 testl rPC,rPC
8205 jne .LOP_DIV_LONG_2ADDR_notSpecial
8206 UNSPILL(rPC)
8207 jmp common_errDivideByZero
8208.LOP_DIV_LONG_2ADDR_check_neg1:
8209 testl rPC,%eax
8210 jne .LOP_DIV_LONG_2ADDR_notSpecial
8211 GET_VREG_WORD(rPC,rINST_FULL,0)
8212 GET_VREG_WORD(%ecx,rINST_FULL,1)
8213 testl rPC,rPC
8214 jne .LOP_DIV_LONG_2ADDR_notSpecial1
8215 cmpl $0x80000000,%ecx
8216 jne .LOP_DIV_LONG_2ADDR_notSpecial1
8217 /* minint / -1, return minint on div, 0 on rem */
8218 xorl %eax,%eax
8219 movl $0x80000000,%edx
8220 jmp .LOP_DIV_LONG_2ADDR_finish
8221
8222
8223/* continuation for OP_REM_LONG_2ADDR */
8224
8225.LOP_REM_LONG_2ADDR_continue:
8226 movl %eax,OUT_ARG3(%esp)
8227 movl rPC,OUT_ARG0(%esp)
8228 movl %ecx,OUT_ARG1(%esp)
8229 call __moddi3
8230.LOP_REM_LONG_2ADDR_finish:
8231 movl rINST_FULL,%ecx
8232 SET_VREG_WORD(rPC,%ecx,1)
8233 UNSPILL(rPC)
8234 SET_VREG_WORD(%eax,%ecx,0)
8235 FETCH_INST_WORD(1)
8236 ADVANCE_PC(1)
8237 GOTO_NEXT
8238
8239.LOP_REM_LONG_2ADDR_check_zero:
8240 testl rPC,rPC
8241 jne .LOP_REM_LONG_2ADDR_notSpecial
8242 UNSPILL(rPC)
8243 jmp common_errDivideByZero
8244.LOP_REM_LONG_2ADDR_check_neg1:
8245 testl rPC,%eax
8246 jne .LOP_REM_LONG_2ADDR_notSpecial
8247 GET_VREG_WORD(rPC,rINST_FULL,0)
8248 GET_VREG_WORD(%ecx,rINST_FULL,1)
8249 testl rPC,rPC
8250 jne .LOP_REM_LONG_2ADDR_notSpecial1
8251 cmpl $0x80000000,%ecx
8252 jne .LOP_REM_LONG_2ADDR_notSpecial1
8253 /* minint / -1, return minint on div, 0 on rem */
8254 xorl %eax,%eax
8255 movl $0,%edx
8256 jmp .LOP_REM_LONG_2ADDR_finish
8257
8258
8259/* continuation for OP_SHL_LONG_2ADDR */
8260
8261
8262.LOP_SHL_LONG_2ADDR_finish:
8263 SET_VREG_WORD(%eax,rINST_FULL,0) # v[AA+0]<- eax
8264 FETCH_INST_WORD(1)
8265 ADVANCE_PC(1)
8266 GOTO_NEXT
8267
8268/* continuation for OP_SHR_LONG_2ADDR */
8269
8270
8271.LOP_SHR_LONG_2ADDR_finish:
8272 SET_VREG_WORD(%eax,rINST_FULL,0) # v[AA+0]<- eax
8273 FETCH_INST_WORD(1)
8274 ADVANCE_PC(1)
8275 GOTO_NEXT
8276
8277/* continuation for OP_USHR_LONG_2ADDR */
8278
8279
8280.LOP_USHR_LONG_2ADDR_finish:
8281 SET_VREG_WORD(%eax,rINST_FULL,0) # v[AA+0]<- eax
8282 FETCH_INST_WORD(1)
8283 ADVANCE_PC(1)
8284 GOTO_NEXT
8285
8286/* continuation for OP_DIV_INT_LIT16 */
8287.LOP_DIV_INT_LIT16_continue_div:
8288 cltd
8289 idivl %ecx
8290.LOP_DIV_INT_LIT16_finish_div:
8291 SET_VREG(%eax,rINST_FULL)
8292 UNSPILL(rPC)
8293 FETCH_INST_WORD(2)
8294 ADVANCE_PC(2)
8295 GOTO_NEXT
8296
8297/* continuation for OP_REM_INT_LIT16 */
8298.LOP_REM_INT_LIT16_continue_div:
8299 cltd
8300 idivl %ecx
8301.LOP_REM_INT_LIT16_finish_div:
8302 SET_VREG(%edx,rINST_FULL)
8303 UNSPILL(rPC)
8304 FETCH_INST_WORD(2)
8305 ADVANCE_PC(2)
8306 GOTO_NEXT
8307
8308/* continuation for OP_DIV_INT_LIT8 */
8309.LOP_DIV_INT_LIT8_continue_div:
8310 cltd
8311 idivl %ecx
8312.LOP_DIV_INT_LIT8_finish_div:
8313 SET_VREG(%eax,rINST_FULL)
8314 UNSPILL(rPC)
8315 FETCH_INST_WORD(2)
8316 ADVANCE_PC(2)
8317 GOTO_NEXT
8318
8319/* continuation for OP_REM_INT_LIT8 */
8320.LOP_REM_INT_LIT8_continue_div:
8321 cltd
8322 idivl %ecx
8323.LOP_REM_INT_LIT8_finish_div:
8324 SET_VREG(%edx,rINST_FULL)
8325 UNSPILL(rPC)
8326 FETCH_INST_WORD(2)
8327 ADVANCE_PC(2)
8328 GOTO_NEXT
8329
8330/* continuation for OP_EXECUTE_INLINE */
8331
8332.LOP_EXECUTE_INLINE_continue:
8333 /*
8334 * Extract args, call function.
8335 * ecx = #of args (0-4)
8336 * eax = call index
8337 * @esp = return addr
8338 * esp is -4 from normal
8339 *
8340 * Go ahead and load all 4 args, even if not used.
8341 */
8342 movzwl 4(rPC),rPC
8343
8344 movl $0xf,%ecx
8345 andl rPC,%ecx
8346 GET_VREG(%ecx,%ecx)
8347 sarl $4,rPC
8348 movl %ecx,4+OUT_ARG0(%esp)
8349
8350 movl $0xf,%ecx
8351 andl rPC,%ecx
8352 GET_VREG(%ecx,%ecx)
8353 sarl $4,rPC
8354 movl %ecx,4+OUT_ARG1(%esp)
8355
8356 movl $0xf,%ecx
8357 andl rPC,%ecx
8358 GET_VREG(%ecx,%ecx)
8359 sarl $4,rPC
8360 movl %ecx,4+OUT_ARG2(%esp)
8361
8362 movl $0xf,%ecx
8363 andl rPC,%ecx
8364 GET_VREG(%ecx,%ecx)
8365 sarl $4,rPC
8366 movl %ecx,4+OUT_ARG3(%esp)
8367
8368 sall $4,%eax # index *= sizeof(table entry)
8369 jmp *gDvmInlineOpsTable(%eax)
8370 # will return to caller of .LOP_EXECUTE_INLINE_continue
8371
8372
8373 .size dvmAsmSisterStart, .-dvmAsmSisterStart
8374 .global dvmAsmSisterEnd
8375dvmAsmSisterEnd:
8376
8377/* File: x86/entry.S */
8378/*
8379 * Copyright (C) 2008 The Android Open Source Project
8380 *
8381 * Licensed under the Apache License, Version 2.0 (the "License");
8382 * you may not use this file except in compliance with the License.
8383 * You may obtain a copy of the License at
8384 *
8385 * http://www.apache.org/licenses/LICENSE-2.0
8386 *
8387 * Unless required by applicable law or agreed to in writing, software
8388 * distributed under the License is distributed on an "AS IS" BASIS,
8389 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8390 * See the License for the specific language governing permissions and
8391 * limitations under the License.
8392 */
8393
8394
8395 .text
8396 .global dvmMterpStdRun
8397 .type dvmMterpStdRun, %function
8398/*
8399 * bool dvmMterpStdRun(MterpGlue* glue)
8400 *
8401 * Interpreter entry point. Returns changeInterp.
8402 *
8403 */
8404dvmMterpStdRun:
8405 push %ebp
8406 movl %esp,%ebp
8407 push %edi
8408 push %esi
8409 push %ebx
8410
8411/* at this point, stack is misaligned by 1 word
8412 We're allocating spill space for 6 words, plus
8413 outgoing argument (5 words) and local variables
8414 (4 words) - 15 words or 60 bytes total. See
8415 diagram in header.S
8416*/
8417 subl $60,%esp
8418
8419/* Set up "named" registers */
8420 movl IN_ARG0(%ebp),%ecx
8421 movl %ecx,rGLUE_SPILL(%ebp)
8422 LOAD_PC_FROM_GLUE(%ecx)
8423 LOAD_FP_FROM_GLUE(%ecx)
8424 movl $dvmAsmInstructionStart,rIBASE
8425
8426/* Remember %esp for future "longjmp" */
8427 movl %esp,offGlue_bailPtr(%ecx)
8428
8429/* How to start? */
8430 movb offGlue_entryPoint(%ecx),%al
8431
8432/* Normal start? */
8433 cmpb $kInterpEntryInstr,%al
8434 jne .Lnot_instr
8435
8436 /* Normal case: start executing the instruction at rPC */
8437 FETCH_INST()
8438 GOTO_NEXT
8439
8440.Lnot_instr:
8441 /* Reset to normal case */
8442 movb $kInterpEntryInstr,offGlue_entryPoint(%ecx)
8443 cmpb $kInterpEntryReturn,%al
8444 je common_returnFromMethod
8445 cmpb $kInterpEntryThrow,%al
8446 je common_exceptionThrown
8447 movzx %al,%eax
8448 movl %eax,OUT_ARG1(%esp)
8449 movl $.LstrBadEntryPoint,OUT_ARG0(%esp)
8450 call printf
8451 call dvmAbort
8452 /* Not reached */
8453
8454
8455 .global dvmMterpStdBail
8456 .type dvmMterpStdBail, %function
8457/*
8458 * void dvmMterpStdBail(MterpGlue* glue, bool changeInterp)
8459 *
8460 * Restore the stack pointer and PC from the save point established on entry.
8461 * This is essentially the same as a longjmp, but should be cheaper. The
8462 * last instruction causes us to return to whoever called dvmMterpStdRun.
8463 *
8464 * We're not going to build a standard frame here, so the arg accesses will
8465 * look a little strange.
8466 *
8467 * On entry:
8468 * esp+4 (arg0) MterpGlue* glue
8469 * esp+8 (arg1) bool changeInterp
8470 */
8471dvmMterpStdBail:
8472 movl 4(%esp),%ecx # grab glue
8473 movl 8(%esp),%eax # changeInterp to return reg
8474 movl offGlue_bailPtr(%ecx),%esp # Stack back to normal
8475 addl $60,%esp # Strip dvmMterpStdRun's frame
8476 pop %ebx
8477 pop %esi
8478 pop %edi
8479 pop %ebp
8480 ret # return to dvmMterpStdRun's caller
8481
8482
8483/*
8484 * Strings
8485 */
8486 .section .rodata
8487.LstrBadEntryPoint:
8488 .asciz "Bad entry point %d\n"
8489
8490/* File: x86/footer.S */
8491/*
8492 * Copyright (C) 2008 The Android Open Source Project
8493 *
8494 * Licensed under the Apache License, Version 2.0 (the "License");
8495 * you may not use this file except in compliance with the License.
8496 * You may obtain a copy of the License at
8497 *
8498 * http://www.apache.org/licenses/LICENSE-2.0
8499 *
8500 * Unless required by applicable law or agreed to in writing, software
8501 * distributed under the License is distributed on an "AS IS" BASIS,
8502 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8503 * See the License for the specific language governing permissions and
8504 * limitations under the License.
8505 */
8506/*
8507 * Common subroutines and data.
8508 */
8509
8510/*
8511 * Common code when a backwards branch is taken
8512 *
8513 * On entry:
8514 * ebx (a.k.a. rINST_FULL) -> PC adjustment in 16-bit words
8515 */
8516common_backwardBranch:
8517 GET_GLUE(%ecx)
Johnnie Birchc4080f62009-02-10 15:41:06 -08008518 call common_periodicChecks # Note: expects rPC to be preserved
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08008519 ADVANCE_PC_INDEXED(rINST_FULL)
8520 FETCH_INST()
8521 GOTO_NEXT
8522
Johnnie Birchc4080f62009-02-10 15:41:06 -08008523
8524
8525/*
8526 * Common code for method invocation with range.
8527 *
8528 * On entry:
8529 * eax = Method* methodToCall
8530 * rINST trashed, must reload
8531 */
8532
8533common_invokeMethodRange:
8534.LinvokeNewRange:
8535
8536 /*
8537 * prepare to copy args to "outs" area of current frame
8538 */
8539
8540 movzbl 1(rPC),rINST_FULL # rINST_FULL<- AA
8541 movzwl 4(rPC), %ecx # %ecx<- CCCC
8542 SPILL(rPC)
8543 SAVEAREA_FROM_FP(%edx,rFP) # %edx<- &StackSaveArea
8544 test rINST_FULL, rINST_FULL
8545 movl rINST_FULL, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- AA
8546 jz .LinvokeArgsDone # no args; jump to args done
8547
8548
8549 /*
8550 * %eax=methodToCall, %ecx=CCCC, LOCAL0_OFFSET(%ebp)=count, %edx=&outs (&stackSaveArea)
8551 * (very few methods have > 10 args; could unroll for common cases)
8552 */
8553
8554 movl %ebx, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- save %ebx
8555 lea (rFP, %ecx, 4), %ecx # %ecx<- &vCCCC
8556 shll $2, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- offset
8557 subl LOCAL0_OFFSET(%ebp), %edx # %edx<- update &outs
8558 shrl $2, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- offset
85591:
8560 movl (%ecx), %ebx # %ebx<- vCCCC
8561 lea 4(%ecx), %ecx # %ecx<- &vCCCC++
8562 subl $1, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET<- LOCAL0_OFFSET--
8563 movl %ebx, (%edx) # *outs<- vCCCC
8564 lea 4(%edx), %edx # outs++
8565 jne 1b # loop if count (LOCAL0_OFFSET(%ebp)) not zero
8566 movl LOCAL1_OFFSET(%ebp), %ebx # %ebx<- restore %ebx
8567 jmp .LinvokeArgsDone # continue
8568
8569 /*
8570 * %eax is "Method* methodToCall", the method we're trying to call
8571 * prepare to copy args to "outs" area of current frame
8572 */
8573
8574common_invokeMethodNoRange:
8575.LinvokeNewNoRange:
8576 movzbl 1(rPC),rINST_FULL # rINST_FULL<- BA
8577 SPILL(rPC)
8578 movl rINST_FULL, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- BA
8579 shrl $4, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- B
8580 je .LinvokeArgsDone # no args; jump to args done
8581 movzwl 4(rPC), %ecx # %ecx<- GFED
8582 SAVEAREA_FROM_FP(%edx,rFP) # %edx<- &StackSaveArea
8583
8584 /*
8585 * %eax=methodToCall, %ecx=GFED, LOCAL0_OFFSET(%ebp)=count, %edx=outs
8586 */
8587
8588.LinvokeNonRange:
8589 cmp $2, LOCAL0_OFFSET(%ebp) # compare LOCAL0_OFFSET(%ebp) to 2
8590 movl %ecx, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- GFED
8591 jl 1f # handle 1 arg
8592 je 2f # handle 2 args
8593 cmp $4, LOCAL0_OFFSET(%ebp) # compare LOCAL0_OFFSET(%ebp) to 4
8594 jl 3f # handle 3 args
8595 je 4f # handle 4 args
85965:
8597 andl $15, rINST_FULL # rINST<- A
8598 lea -4(%edx), %edx # %edx<- update &outs; &outs--
8599 movl (rFP, rINST_FULL, 4), %ecx # %ecx<- vA
8600 movl %ecx, (%edx) # *outs<- vA
8601 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED
86024:
8603 shr $12, %ecx # %ecx<- G
8604 lea -4(%edx), %edx # %edx<- update &outs; &outs--
8605 movl (rFP, %ecx, 4), %ecx # %ecx<- vG
8606 movl %ecx, (%edx) # *outs<- vG
8607 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED
86083:
8609 and $0x0f00, %ecx # %ecx<- 0F00
8610 shr $8, %ecx # %ecx<- F
8611 lea -4(%edx), %edx # %edx<- update &outs; &outs--
8612 movl (rFP, %ecx, 4), %ecx # %ecx<- vF
8613 movl %ecx, (%edx) # *outs<- vF
8614 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED
86152:
8616 and $0x00f0, %ecx # %ecx<- 00E0
8617 shr $4, %ecx # %ecx<- E
8618 lea -4(%edx), %edx # %edx<- update &outs; &outs--
8619 movl (rFP, %ecx, 4), %ecx # %ecx<- vE
8620 movl %ecx, (%edx) # *outs<- vE
8621 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED
86221:
8623 and $0x000f, %ecx # %ecx<- 000D
8624 movl (rFP, %ecx, 4), %ecx # %ecx<- vD
8625 movl %ecx, -4(%edx) # *--outs<- vD
86260:
8627
8628 /*
8629 * %eax is "Method* methodToCall", the method we're trying to call
8630 * find space for the new stack frame, check for overflow
8631 */
8632
8633.LinvokeArgsDone:
8634 movzwl offMethod_registersSize(%eax), %edx # %edx<- methodToCall->regsSize
8635 movzwl offMethod_outsSize(%eax), %ecx # %ecx<- methodToCall->outsSize
8636 movl %eax, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET<- methodToCall
8637 shl $2, %edx # %edx<- update offset
8638 SAVEAREA_FROM_FP(%eax,rFP) # %eax<- &StackSaveArea
8639 subl %edx, %eax # %eax<- newFP; (old savearea - regsSize)
8640 GET_GLUE(%edx) # %edx<- pMterpGlue
8641 movl %eax, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- &outs
8642 subl $sizeofStackSaveArea, %eax # %eax<- newSaveArea (stack save area using newFP)
8643 movl offGlue_interpStackEnd(%edx), %edx # %edx<- glue->interpStackEnd
8644 movl %edx, LOCAL2_OFFSET(%ebp) # LOCAL2_OFFSET<- glue->interpStackEnd
8645 shl $2, %ecx # %ecx<- update offset for outsSize
8646 movl %eax, %edx # %edx<- newSaveArea
8647 sub %ecx, %eax # %eax<- bottom; (newSaveArea - outsSize)
8648 cmp LOCAL2_OFFSET(%ebp), %eax # compare interpStackEnd and bottom
8649 movl LOCAL0_OFFSET(%ebp), %eax # %eax<- restore methodToCall
8650 jl .LstackOverflow # handle frame overflow
8651
8652 /*
8653 * set up newSaveArea
8654 */
8655
8656#ifdef EASY_GDB
8657 SAVEAREA_FROM_FP(%ecx,rFP) # %ecx<- &StackSaveArea
8658 movl %ecx, offStackSaveArea_prevSave(%edx) # newSaveArea->prevSave<- &outs
8659#endif
8660 movl rFP, offStackSaveArea_prevFrame(%edx) # newSaveArea->prevFrame<- rFP
8661 movl rPC_SPILL(%ebp), %ecx
8662 movl %ecx, offStackSaveArea_savedPc(%edx) # newSaveArea->savedPc<- rPC
8663 testl $ACC_NATIVE, offMethod_accessFlags(%eax) # check for native call
8664 movl %eax, offStackSaveArea_method(%edx) # newSaveArea->method<- method to call
8665 jne .LinvokeNative # handle native call
8666
8667 /*
8668 * Update "glue" values for the new method
8669 * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFp
8670 */
8671
8672 movl offMethod_clazz(%eax), %edx # %edx<- method->clazz
8673 GET_GLUE(%ecx) # %ecx<- pMterpGlue
8674 movl offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex
8675 movl %eax, offGlue_method(%ecx) # glue->method<- methodToCall
8676 movl %edx, offGlue_methodClassDex(%ecx) # glue->methodClassDex<- method->clazz->pDvmDex
8677 movl offMethod_insns(%eax), rPC # rPC<- methodToCall->insns
8678 movl offGlue_self(%ecx), %eax # %eax<- glue->self
8679 movl LOCAL1_OFFSET(%ebp), rFP # rFP<- newFP
8680 movl rFP, offThread_curFrame(%eax) # glue->self->curFrame<- newFP
8681 FETCH_INST()
8682 GOTO_NEXT # jump to methodToCall->insns
8683
8684 /*
8685 * Prep for the native call
8686 * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFP, %edx=newSaveArea
8687 */
8688
8689.LinvokeNative:
8690 GET_GLUE(%ecx) # %ecx<- pMterpGlue
8691 movl %eax, OUT_ARG1(%esp) # push parameter methodToCall
8692 movl offGlue_self(%ecx), %ecx # %ecx<- glue->self
8693 movl offThread_jniLocal_nextEntry(%ecx), %eax # %eax<- glue->self->thread->refNext
8694 movl %eax, offStackSaveArea_localRefTop(%edx) # newSaveArea->localRefTop<- refNext
8695 movl %edx, OUT_ARG4(%esp) # save newSaveArea
8696 movl LOCAL1_OFFSET(%ebp), %edx # %edx<- newFP
8697 movl %edx, offThread_curFrame(%ecx) # glue->self->curFrame<- newFP
8698 movl %ecx, OUT_ARG3(%esp) # save glue->self
8699 movl %ecx, OUT_ARG2(%esp) # push parameter glue->self
8700 GET_GLUE(%ecx) # %ecx<- pMterpGlue
8701 movl OUT_ARG1(%esp), %eax # %eax<- methodToCall
8702 lea offGlue_retval(%ecx), %ecx # %ecx<- &retval
8703 movl %ecx, OUT_ARG0(%esp) # push parameter pMterpGlue
8704 push %edx # push parameter newFP
8705
8706 call *offMethod_nativeFunc(%eax) # call methodToCall->nativeFunc
8707 lea 4(%esp), %esp
8708 movl OUT_ARG4(%esp), %ecx # %ecx<- newSaveArea
8709 movl OUT_ARG3(%esp), %eax # %eax<- glue->self
8710 movl offStackSaveArea_localRefTop(%ecx), %edx # %edx<- newSaveArea->localRefTop
8711 cmp $0, offThread_exception(%eax) # check for exception
8712 movl rFP, offThread_curFrame(%eax) # glue->self->curFrame<- rFP
8713 movl %edx, offThread_jniLocal_nextEntry(%eax) # glue->self<- newSaveArea->localRefTop
8714 UNSPILL(rPC)
8715 jne common_exceptionThrown # handle exception
8716 FETCH_INST_WORD(3)
8717 ADVANCE_PC(3)
8718 GOTO_NEXT # jump to next instruction
8719
8720.LstackOverflow:
8721 GET_GLUE(%eax) # %eax<- pMterpGlue
8722 movl offGlue_self(%eax), %eax # %eax<- glue->self
8723 movl %eax, OUT_ARG0(%esp) # push parameter self
8724 call dvmHandleStackOverflow # call: (Thread* self)
8725 UNSPILL(rPC) # return: void
8726 jmp common_exceptionThrown # handle exception
8727
8728
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08008729/*
8730 * Common invoke code (old-style).
8731 * TUNING: Rewrite along lines of new armv5 code?
8732 *
8733 * On entry:
8734 * eax = Method* methodToCall
8735 * ecx = bool methodCallRange
8736 * rINST trashed, must reload
8737 */
8738common_invokeOld:
8739 movl %ecx,OUT_ARG1(%esp) # arg1<- methodCallRange
8740 GET_GLUE(%ecx)
8741 movzwl (rPC),rINST_FULL # recover rINST
8742 movl %eax,OUT_ARG2(%esp) # arg2<- method
8743 movzwl 4(rPC),%eax # eax<- GFED or CCCC
8744 SAVE_PC_TO_GLUE(%ecx)
8745 SAVE_FP_TO_GLUE(%ecx)
8746 movzbl rINST_HI,rINST_FULL
8747 movl rINST_FULL,OUT_ARG3(%esp)# arg3<- AA
8748 movl %ecx,OUT_ARG0(%esp) # arg0<- GLUE
8749 movl %eax,OUT_ARG4(%esp) # arg4<- GFED/CCCC
8750 call dvmMterp_invokeMethod
8751 jmp common_resumeAfterGlueCall
8752
8753
8754/*
8755 * Do we need the thread to be suspended or have debugger/profiling activity?
8756 *
8757 * On entry:
8758 * ebx -> PC adjustment in 16-bit words (must be preserved)
8759 * ecx -> GLUE pointer
8760 *
8761 * Note: A call will normally kill %eax, rPC/%edx and %ecx. To
8762 * streamline the normal case, this routine will preserve rPC and
8763 * %ecx in addition to the normal caller save regs. The save/restore
8764 * is a bit ugly, but will happen in the relatively uncommon path.
8765 * TUNING: Might be worthwhile to inline this.
8766 * TODO: Basic-block style Jit will need a hook here as well. Fold it into
8767 * the suspendCount check so we can get both in 1 shot.
8768 */
8769common_periodicChecks:
8770 movl offGlue_pSelfSuspendCount(%ecx),%eax # eax <- &suspendCount
8771 cmpl $0,(%eax)
8772 jne 1f
8773
8774#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
8775#if defined(WITH_DEBUGGER)
8776 movl offGlue_pDebuggerActive(%ecx),%eax # eax <- &DebuggerActive
8777#endif
8778#if defined(WITH_PROFILER)
8779 movl offGlue_pActiveProfilers(%ecx),%ecx # ecx <- &ActiveProfilers
8780#endif
8781#if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
8782 movzbl (%eax),%eax # eax <- debuggerActive (boolean)
8783 orl (%ecx),%eax # eax <- debuggerActive || activeProfilers
8784#elif defined(WITH_DEBUGGER)
8785 movzbl (%eax),%eax # eax <- debuggerActive (boolean)
8786#elif defined(WITH_PROFILER)
8787 movl (%ecx),%eax # eax <= activeProfilers
8788#endif
8789 GET_GLUE(%ecx) # restore rGLUE
8790 testl %eax,%eax
8791 jne 3f # one or both active - switch interp
8792#endif
8793
8794 ret
8795
8796 /* Check for suspend */
87971:
8798 /* At this point, the return pointer to the caller of
8799 * common_periodicChecks is on the top of stack. We need to preserve
8800 * rPC(edx) and GLUE(ecx). We'll spill rPC, and reload GLUE.
8801 * The outgoing profile is:
8802 * bool dvmCheckSuspendPending(Thread* self)
8803 * Because we reached here via a call, go ahead and build a new frame.
8804 */
The Android Open Source Project99409882009-03-18 22:20:24 -07008805 EXPORT_PC() # need for precise GC
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08008806 movl offGlue_self(%ecx),%eax # eax<- glue->self
8807 SPILL(rPC) # save edx
8808 push %ebp
8809 movl %esp,%ebp
8810 subl $24,%esp
8811 movl %eax,OUT_ARG0(%esp)
8812 call dvmCheckSuspendPending
8813 addl $24,%esp
8814 pop %ebp
8815 UNSPILL(rPC)
8816 GET_GLUE(%ecx)
8817 ret
8818
8819 /* Switch interpreters */
8820 /* Note: %ebx contains the 16-bit word offset to be applied to rPC to
8821 * "complete" the interpretation of backwards branches. In effect, we
8822 * are completing the interpretation of the branch instruction here,
8823 * and the new interpreter will resume interpretation at the branch
8824 * target. However, a switch request recognized during the handling
8825 * of a return from method instruction results in an immediate abort,
8826 * and the new interpreter will resume by re-interpreting the return
8827 * instruction.
8828 */
88293:
8830 leal (rPC,%ebx,2),rPC # adjust pc to show target
8831 GET_GLUE(%ecx) # bail expect GLUE already loaded
8832 movl $1,rINST_FULL # set changeInterp to true
8833 jmp common_gotoBail
8834
8835
8836/*
8837 * Common code for handling a return instruction
8838 */
8839common_returnFromMethod:
8840 GET_GLUE(%ecx)
8841 /* Set entry mode in case we bail */
8842 movb $kInterpEntryReturn,offGlue_entryPoint(%ecx)
8843 xorl rINST_FULL,rINST_FULL # zero offset in case we switch interps
8844 call common_periodicChecks # Note: expects %ecx to be preserved
8845
8846 SAVEAREA_FROM_FP(%eax,rFP) # eax<- saveArea (old)
8847 movl offStackSaveArea_prevFrame(%eax),rFP # rFP<- prevFrame
8848 movl (offStackSaveArea_method-sizeofStackSaveArea)(rFP),rINST_FULL
8849 cmpl $0,rINST_FULL # break?
8850 je common_gotoBail # break frame, bail out completely
8851
8852 movl offStackSaveArea_savedPc(%eax),rPC # pc<- saveArea->savedPC
8853 movl offGlue_self(%ecx),%eax # eax<- self
8854 movl rINST_FULL,offGlue_method(%ecx) # glue->method = newSave->meethod
8855 movl rFP,offThread_curFrame(%eax) # self->curFrame = fp
8856 movl offMethod_clazz(rINST_FULL),%eax # eax<- method->clazz
8857 FETCH_INST_WORD(3)
8858 movl offClassObject_pDvmDex(%eax),%eax # eax<- method->clazz->pDvmDex
8859 ADVANCE_PC(3)
8860 movl %eax,offGlue_methodClassDex(%ecx)
8861 /* not bailing - restore entry mode to default */
8862 movb $kInterpEntryInstr,offGlue_entryPoint(%ecx)
8863 GOTO_NEXT
8864
8865/*
8866 * Prepare to strip the current frame and "longjump" back to caller of
8867 * dvmMterpStdRun.
8868 *
8869 * on entry:
8870 * rINST_FULL holds changeInterp
8871 * ecx holds glue pointer
8872 *
8873 * expected profile: dvmMterpStdBail(MterpGlue *glue, bool changeInterp)
8874 */
8875common_gotoBail:
8876 SAVE_PC_TO_GLUE(%ecx) # export state to glue
8877 SAVE_FP_TO_GLUE(%ecx)
8878 movl %ecx,OUT_ARG0(%esp) # glue in arg0
8879 movl rINST_FULL,OUT_ARG1(%esp) # changeInterp in arg1
8880 call dvmMterpStdBail # bail out....
8881
8882
8883/*
8884 * After returning from a "glued" function, pull out the updated values
8885 * and start executing at the next instruction.
8886 */
8887 common_resumeAfterGlueCall:
8888 GET_GLUE(%ecx)
8889 LOAD_PC_FROM_GLUE(%ecx)
8890 LOAD_FP_FROM_GLUE(%ecx)
8891 FETCH_INST()
8892 GOTO_NEXT
8893
8894/*
8895 * Integer divide or mod by zero
8896 */
8897common_errDivideByZero:
8898 EXPORT_PC()
8899 movl $.LstrArithmeticException,%eax
8900 movl %eax,OUT_ARG0(%esp)
8901 movl $.LstrDivideByZero,%eax
8902 movl %eax,OUT_ARG1(%esp)
8903 SPILL(rPC)
8904 call dvmThrowException
8905 UNSPILL(rPC)
8906 jmp common_exceptionThrown
8907
8908/*
8909 * Attempt to allocate an array with a negative size.
8910 */
8911common_errNegativeArraySize:
8912 EXPORT_PC()
8913 movl $.LstrNegativeArraySizeException,%eax
8914 movl %eax,OUT_ARG0(%esp)
8915 xorl %eax,%eax
8916 movl %eax,OUT_ARG1(%esp)
8917 SPILL(rPC)
8918 call dvmThrowException
8919 UNSPILL(rPC)
8920 jmp common_exceptionThrown
8921
8922/*
8923 * Attempt to allocate an array with a negative size.
8924 */
8925common_errNoSuchMethod:
8926
8927 EXPORT_PC()
8928 movl $.LstrNoSuchMethodError,%eax
8929 movl %eax,OUT_ARG0(%esp)
8930 xorl %eax,%eax
8931 movl %eax,OUT_ARG1(%esp)
8932 SPILL(rPC)
8933 call dvmThrowException
8934 UNSPILL(rPC)
8935 jmp common_exceptionThrown
8936
8937/*
8938 * Hit a null object when we weren't expecting one. Export the PC, throw a
8939 * NullPointerException and goto the exception processing code.
8940 */
8941common_errNullObject:
8942 EXPORT_PC()
8943 movl $.LstrNullPointerException,%eax
8944 movl %eax,OUT_ARG0(%esp)
8945 xorl %eax,%eax
8946 movl %eax,OUT_ARG1(%esp)
8947 SPILL(rPC)
8948 call dvmThrowException
8949 UNSPILL(rPC)
8950 jmp common_exceptionThrown
8951
8952/*
8953 * Array index exceeds max.
8954 */
8955common_errArrayIndex:
8956 EXPORT_PC()
8957 movl $.LstrArrayIndexException,%eax
8958 movl %eax,OUT_ARG0(%esp)
8959 xorl %eax,%eax
8960 movl %eax,OUT_ARG1(%esp)
8961 SPILL(rPC)
8962 call dvmThrowException
8963 UNSPILL(rPC)
8964 jmp common_exceptionThrown
8965/*
8966 * Invalid array value.
8967 */
8968common_errArrayStore:
8969 EXPORT_PC()
8970 movl $.LstrArrayStoreException,%eax
8971 movl %eax,OUT_ARG0(%esp)
8972 xorl %eax,%eax
8973 movl %eax,OUT_ARG1(%esp)
8974 SPILL(rPC)
8975 call dvmThrowException
8976 UNSPILL(rPC)
8977 jmp common_exceptionThrown
8978
8979/*
8980 * Somebody has thrown an exception. Handle it.
8981 *
8982 * If the exception processing code returns to us (instead of falling
8983 * out of the interpreter), continue with whatever the next instruction
8984 * now happens to be.
8985 *
8986 * This does not return.
8987 */
8988common_exceptionThrown:
8989 GET_GLUE(%ecx)
8990 SAVE_PC_TO_GLUE(%ecx)
8991 SAVE_FP_TO_GLUE(%ecx)
8992 movl %ecx,OUT_ARG0(%esp)
8993 call dvmMterp_exceptionThrown
8994 jmp common_resumeAfterGlueCall
8995
8996common_abort:
8997 movl $0xdeadf00d,%eax
8998 call *%eax
8999
9000
9001/*
9002 * Strings
9003 */
9004
9005 .section .rodata
9006.LstrNullPointerException:
9007 .asciz "Ljava/lang/NullPointerException;"
9008.LstrArithmeticException:
9009 .asciz "Ljava/lang/ArithmeticException;"
9010.LstrDivideByZero:
9011 .asciz "divide by zero"
9012.LstrArrayIndexException:
9013 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;"
9014.LstrArrayStoreException:
9015 .asciz "Ljava/lang/ArrayStoreException;"
9016.LstrNegativeArraySizeException:
9017 .asciz "Ljava/lang/NegativeArraySizeException;"
9018.LstrInstantiationError:
9019 .asciz "Ljava/lang/InstantiationError;"
9020.LstrClassCastException:
9021 .asciz "Ljava/lang/ClassCastException;"
9022.LstrNoSuchMethodError:
9023 .asciz "Ljava/lang/NoSuchMethodError;"
9024.LstrInternalError:
9025 .asciz "Ljava/lang/InternalError;"
9026.LstrFilledNewArrayNotImpl:
9027 .asciz "filled-new-array only implemented for 'int'"
9028
9029