1 %default { "isrange":"0" } 2 %verify "executed" 3 %verify "unimplemented array type" 4 /* 5 * Create a new array with elements filled from registers. 6 * 7 * for: filled-new-array, filled-new-array/range 8 */ 9 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 10 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 11 movl rSELF,%eax 12 movl offThread_methodClassDex(%eax),%eax # eax<- pDvmDex 13 movzwl 2(rPC),%ecx # ecx<- BBBB 14 movl offDvmDex_pResClasses(%eax),%eax # eax<- pDvmDex->pResClasses 15 SPILL(rIBASE) # preserve rIBASE 16 movl (%eax,%ecx,4),%eax # eax<- resolved class 17 EXPORT_PC 18 testl %eax,%eax # already resolved? 19 jne .L${opcode}_continue # yes, continue 20 # less frequent path, so we'll redo some work 21 movl rSELF,%eax 22 movl $$0,OUT_ARG2(%esp) # arg2<- false 23 movl %ecx,OUT_ARG1(%esp) # arg1<- BBBB 24 movl offThread_method(%eax),%eax # eax<- self->method 25 movl offMethod_clazz(%eax),%eax # eax<- method->clazz 26 movl %eax,OUT_ARG0(%esp) # arg0<- clazz 27 call dvmResolveClass # eax<- call(clazz,ref,flag) 28 testl %eax,%eax # null? 29 je common_exceptionThrown # yes, handle it 30 31 # note: fall through to .L${opcode}_continue 32 33 /* 34 * On entry: 35 * eax holds array class [r0] 36 * rINST holds AA or BB [r10] 37 * ecx is scratch 38 */ 39 .L${opcode}_continue: 40 movl offClassObject_descriptor(%eax),%ecx # ecx<- arrayClass->descriptor 41 movl $$ALLOC_DONT_TRACK,OUT_ARG2(%esp) # arg2<- flags 42 movzbl 1(%ecx),%ecx # ecx<- descriptor[1] 43 movl %eax,OUT_ARG0(%esp) # arg0<- arrayClass 44 movl rSELF,%eax 45 cmpb $$'I',%cl # supported? 46 je 1f 47 cmpb $$'L',%cl 48 je 1f 49 cmpb $$'[',%cl 50 jne .L${opcode}_notimpl # no, not handled yet 51 1: 52 movl %ecx,offThread_retval+4(%eax) # save type 53 .if (!$isrange) 54 SPILL_TMP1(rINST) # save copy, need "B" later 55 sarl $$4,rINST 56 .endif 57 movl rINST,OUT_ARG1(%esp) # arg1<- A or AA (length) 58 call dvmAllocArrayByClass # eax<- call(arrayClass, length, flags) 59 movl rSELF,%ecx 60 testl %eax,%eax # alloc successful? 61 je common_exceptionThrown # no, handle exception 62 movl %eax,offThread_retval(%ecx) # retval.l<- new array 63 movzwl 4(rPC),%ecx # ecx<- FEDC or CCCC 64 leal offArrayObject_contents(%eax),%eax # eax<- newArray->contents 65 66 /* at this point: 67 * eax is pointer to tgt 68 * rINST is length 69 * ecx is FEDC or CCCC 70 * TMP_SPILL1 is BA 71 * We now need to copy values from registers into the array 72 */ 73 74 .if $isrange 75 # set up src pointer 76 SPILL_TMP2(%esi) 77 SPILL_TMP3(%edi) 78 leal (rFP,%ecx,4),%esi # set up src ptr 79 movl %eax,%edi # set up dst ptr 80 movl rINST,%ecx # load count register 81 rep 82 movsd 83 UNSPILL_TMP2(%esi) 84 UNSPILL_TMP3(%edi) 85 movl rSELF,%ecx 86 movl offThread_retval+4(%ecx),%eax # eax<- type 87 .else 88 testl rINST,rINST 89 je 4f 90 UNSPILL_TMP1(rIBASE) # restore "BA" 91 andl $$0x0f,rIBASE # rIBASE<- 0000000A 92 sall $$16,rIBASE # rIBASE<- 000A0000 93 orl %ecx,rIBASE # rIBASE<- 000AFEDC 94 3: 95 movl $$0xf,%ecx 96 andl rIBASE,%ecx # ecx<- next reg to load 97 GET_VREG_R %ecx %ecx 98 shrl $$4,rIBASE 99 leal 4(%eax),%eax 100 movl %ecx,-4(%eax) 101 sub $$1,rINST 102 jne 3b 103 4: 104 movl rSELF,%ecx 105 movl offThread_retval+4(%ecx),%eax # eax<- type 106 .endif 107 108 cmpb $$'I',%al # Int array? 109 je 5f # skip card mark if so 110 movl offThread_retval(%ecx),%eax # eax<- object head 111 movl offThread_cardTable(%ecx),%ecx # card table base 112 shrl $$GC_CARD_SHIFT,%eax # convert to card num 113 movb %cl,(%ecx,%eax) # mark card based on object head 114 5: 115 UNSPILL(rIBASE) # restore rIBASE 116 FETCH_INST_OPCODE 3 %ecx 117 ADVANCE_PC 3 118 GOTO_NEXT_R %ecx 119 120 121 /* 122 * Throw an exception indicating that we have not implemented this 123 * mode of filled-new-array. 124 */ 125 .L${opcode}_notimpl: 126 movl $$.LstrFilledNewArrayNotImplA,%eax 127 movl %eax,OUT_ARG0(%esp) 128 call dvmThrowInternalError 129 jmp common_exceptionThrown 130