%default { "isrange":"0" } %verify "executed" %verify "unimplemented array type" /* * Create a new array with elements filled from registers. * * for: filled-new-array, filled-new-array/range */ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ GET_GLUE(%eax) movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA or BA movl offGlue_methodClassDex(%eax),%eax # eax<- pDvmDex movzwl 2(rPC),%ecx # ecx<- BBBB movl offDvmDex_pResClasses(%eax),%eax # eax<- pDvmDex->pResClasses SPILL(rPC) movl (%eax,%ecx,4),%eax # eax<- resolved class EXPORT_PC() testl %eax,%eax # already resolved? jne .L${opcode}_continue # yes, continue # less frequent path, so we'll redo some work GET_GLUE(%eax) movl $$0,OUT_ARG2(%esp) # arg2<- false movl %ecx,OUT_ARG1(%esp) # arg1<- BBBB movl offGlue_method(%eax),%eax # eax<- glue->method jmp .L${opcode}_more %break .L${opcode}_more: movl offMethod_clazz(%eax),%eax # eax<- method->clazz movl %eax,OUT_ARG0(%esp) # arg0<- clazz call dvmResolveClass # eax<- call(clazz,ref,flag) UNSPILL(rPC) testl %eax,%eax # null? je common_exceptionThrown # yes, handle it # note: fall through to .L${opcode}_continue /* * On entry: * eax holds array class [r0] * rINST_FULL holds AA or BB [r10] * ecx is scratch * rPC is valid, but has been spilled */ .L${opcode}_continue: movl offClassObject_descriptor(%eax),%ecx # ecx<- arrayClass->descriptor movl $$ALLOC_DONT_TRACK,OUT_ARG2(%esp) # arg2<- flags movzbl 1(%ecx),%ecx # ecx<- descriptor[1] movl %eax,OUT_ARG0(%esp) # arg0<- arrayClass cmpb $$'I',%cl # supported? je 1f cmpb $$'L',%cl je 1f cmpb $$'[',%cl jne .L${opcode}_notimpl # no, not handled yet 1: .if (!$isrange) SPILL_TMP(rINST_FULL) # save copy, need "B" later sarl $$4,rINST_FULL .endif movl rINST_FULL,OUT_ARG1(%esp) # arg1<- A or AA (length) call dvmAllocArrayByClass # eax<- call(arrayClass, length, flags) UNSPILL(rPC) GET_GLUE(%ecx) testl %eax,%eax # alloc successful? je common_exceptionThrown # no, handle exception movl %eax,offGlue_retval(%ecx) # retval.l<- new array movzwl 4(rPC),%ecx # ecx<- FEDC or CCCC leal offArrayObject_contents(%eax),%eax # eax<- newArray->contents /* at this point: * eax is pointer to tgt * rINST_FULL is length * ecx is FEDC or CCCC * TMP_SPILL is BA * rPC is valid, but spilled * We now need to copy values from registers into the array */ .if $isrange # set up src pointer SPILL(rFP) # esi SPILL(rIBASE) # edi movl %eax,%edi # set up dst ptr leal (rFP,%ecx,4),%esi # set up src ptr movl rINST_FULL,%ecx # load count register FETCH_INST_WORD(3) rep movsd UNSPILL(rIBASE) UNSPILL(rFP) .else testl rINST_FULL,rINST_FULL je 4f UNSPILL_TMP(rPC) andl $$0x0f,rPC # rPC<- 0000000A sall $$16,rPC # rPC<- 000A0000 orl %ecx,rPC # rpc<- 000AFEDC 3: movl $$0xf,%ecx andl rPC,%ecx # ecx<- next reg to load GET_VREG(%ecx,%ecx) shrl $$4,rPC leal 4(%eax),%eax movl %ecx,-4(%eax) sub $$1,rINST_FULL jne 3b 4: UNSPILL(rPC) FETCH_INST_WORD(3) .endif ADVANCE_PC(3) GOTO_NEXT /* * Throw an exception indicating that we have not implemented this * mode of filled-new-array. */ .L${opcode}_notimpl: movl $$.LstrInternalError,%eax movl %eax,OUT_ARG0(%esp) movl $$.LstrFilledNewArrayNotImpl,%eax movl %eax,OUT_ARG1(%esp) call dvmThrowException UNSPILL(rPC) jmp common_exceptionThrown