/* Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * File: OP_FILLED_NEW_ARRAY.S * * Code: Constructs and fills an array with the given data. Provides * * For: float-to-int * * Description: Construct an array of the given type and size, * filling it with the supplied contents. The type * must be an array type. The array's contents * must be single-word. The constructed instance * is stored as a result in the same way that the * method invocation instructions store their results, * so the constructed instance must be moved to a * register with a subsequent move-result-object * instruction. * * Format: B|A|op CCCC G|F|E|D (35c) * AA|op BBBB CCCC (3rc) (range) * * Syntax: [B=5] op {vD, vE, vF, vG, vA}, vtaboff@CCCC * [B=4] op {vD, vE, vF, vG}, vtaboff@CCCC * [B=3] op {vD, vE, vF}, vtaboff@CCCC * [B=2] op {vD, vE}, vtaboff@CCCC * [B=1] op {vD}, vtaboff@CCCC * * op {vCCCC .. vNNNN}, meth@BBBB * op {vCCCC .. vNNNN}, type@BBBB */ %default { "isrange":"0" } movl rGLUE, %edx # %edx<- MterpGlue pointer movl offGlue_methodClassDex(%edx), %edx # %edx<- glue->methodClassDex movl offDvmDex_pResClasses(%edx), %edx # %edx<- glue->methodClassDex->pResClasses FETCH 1, %ecx # %ecx<- BBBB EXPORT_PC movl (%edx, %ecx, 4), %eax # %eax<- possibly resolved class cmp $$0, %eax # %eax<- check if already resolved jne .L${opcode}_continue jmp .L${opcode}_break %break .L${opcode}_break: movl $$0, -8(%esp) # push parameter false movl %ecx, -12(%esp) # push parameter BBBB movl rGLUE, %edx # %edx<- MterpGlue pointer movl offGlue_method(%edx), %edx # %edx<- glue->method movl offMethod_clazz(%edx), %edx # %edx<- glue->method->clazz movl %edx, -16(%esp) # push parameter glue->method->clazz lea -16(%esp), %esp call dvmResolveClass # call: (const ClassObject* referrer, u4 classIdx, # bool fromUnverifiedConstant) # return: ClassObject* lea 16(%esp), %esp cmp $$0, %eax # check for null return je common_exceptionThrown # handle exception /* * On entry: * %eax holds array class * rINST holds BA or AA */ .L${opcode}_continue: movl offClassObject_descriptor(%eax), %eax # %eax<- arrayClass->descriptor movzbl 1(%eax), %eax # %eax<- descriptor[1] cmpb $$'I', %al # check if array of ints je 1f cmpb $$'L', %al je 1f cmpb $$'[', %al jne .L${opcode}_notimpl # jump to not implemented 1: movl %eax, sReg0 # save type movl rINST, -12(%esp) # push parameter length movl %eax, -16(%esp) # push parameter descriptor[1] movl $$ALLOC_DONT_TRACK, -8(%esp) # push parameter to allocate flags .if (!$isrange) shrl $$4, -12(%esp) # parameter length is B .endif lea -16(%esp), %esp call dvmAllocPrimitiveArray # call: (char type, size_t length, int allocFlags) # return: ArrayObject* lea 16(%esp), %esp cmp $$0, %eax # check for null return je common_exceptionThrown # handle exception FETCH 2, %edx # %edx<- FEDC or CCCC movl rGLUE, %ecx # %ecx<- MterpGlue pointer movl %eax, offGlue_retval(%ecx) # retval<- new array lea offArrayObject_contents(%eax), %eax # %eax<- newArray->contents subl $$1, -12(%esp) # length--; check for negative js 2f # if length was zero, finish /* * copy values from registers into the array * %eax=array, %edx=CCCC/FEDC, -12(%esp)=length (from AA or B), rINST=AA/BA */ .if $isrange lea (rFP, %edx, 4), %ecx # %ecx<- &fpp[CCCC] 1: movl (%ecx), %edx # %edx<- %ecx++ lea 4(%ecx), %ecx # %ecx++ movl %edx, (%eax) # *contents<- vX lea 4(%eax), %eax # %eax++; contents++ subl $$1, -12(%esp) # length-- jns 1b # or continue at 2 .else cmp $$4, -12(%esp) # check length jne 1f # has four args and $$15, rINST # rINST<- A GET_VREG rINST # rINST<- vA subl $$1, -12(%esp) # count-- movl rINST, 16(%eax) # contents[4]<- vA 1: movl %edx, %ecx # %ecx<- %edx; ecx for temp andl $$15, %ecx # %ecx<- G/F/E/D GET_VREG %ecx # %ecx<- vG/vF/vE/vD shr $$4, %edx # %edx<- put next reg in low 4 subl $$1, -12(%esp) # count-- movl %ecx, (%eax) # *contents<- vX lea 4(%eax), %eax # %eax++; contents++ jns 1b # or continue at 2 .endif 2: cmpb $$'I', sReg0 # check for int array je 3f movl rGLUE, %ecx # %ecx<- MterpGlue pointer movl offGlue_retval(%ecx), %eax # Object head movl offGlue_cardTable(%ecx), %ecx # card table base shrl $$GC_CARD_SHIFT, %eax # convert to card num movb %cl,(%ecx, %eax) # mark card based on object head 3: FINISH 3 # jump to next instruction /* * Throw an exception to indicate this mode of filled-new-array * has not been implemented. */ .L${opcode}_notimpl: movl $$.LstrInternalError, -8(%esp) movl $$.LstrFilledNewArrayNotImpl, -4(%esp) lea -8(%esp), %esp call dvmThrowException # call: (const char* exceptionDescriptor, # const char* msg) # return: void lea 8(%esp), %esp jmp common_exceptionThrown .if (!$isrange) # define in one or the other, not both .LstrFilledNewArrayNotImpl: .asciz "filled-new-array only implemented for 'int'" .LstrInternalError: .asciz "Ljava/lang/InternalError;" .endif