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 LOAD_rSELF_methodClassDex(a3) # a3 <- pDvmDex 12 FETCH(a1, 1) # a1 <- BBBB 13 LOAD_base_offDvmDex_pResClasses(a3, a3) # a3 <- pDvmDex->pResClasses 14 EXPORT_PC() # need for resolve and alloc 15 LOAD_eas2(a0, a3, a1) # a0 <- resolved class 16 GET_OPA(rOBJ) # rOBJ <- AA or BA 17 # already resolved? 18 bnez a0, .L${opcode}_continue # yes, continue on 19 LOAD_rSELF_method(a3) # a3 <- self->method 20 li a2, 0 # a2 <- false 21 LOAD_base_offMethod_clazz(a0, a3) # a0 <- method->clazz 22 JAL(dvmResolveClass) # v0 <- call(clazz, ref) 23 move a0, v0 24 # got null? 25 beqz v0, common_exceptionThrown # yes, handle exception 26 b .L${opcode}_continue 27 %break 28 29 /* 30 * On entry: 31 * a0 holds array class 32 * rOBJ holds AA or BA 33 */ 34 .L${opcode}_continue: 35 LOAD_base_offClassObject_descriptor(a3, a0) # a3 <- arrayClass->descriptor 36 li a2, ALLOC_DONT_TRACK # a2 <- alloc flags 37 lbu rINST, 1(a3) # rINST <- descriptor[1] 38 .if $isrange 39 move a1, rOBJ # a1 <- AA (length) 40 .else 41 srl a1, rOBJ, 4 # rOBJ <- B (length) 42 .endif 43 seq t0, rINST, 'I' # array of ints? 44 seq t1, rINST, 'L' # array of objects? 45 or t0, t1 46 seq t1, rINST, '[' # array of arrays? 47 or t0, t1 48 move rBIX, a1 # save length in rBIX 49 beqz t0, .L${opcode}_notimpl # no, not handled yet 50 JAL(dvmAllocArrayByClass) # v0 <- call(arClass, length, flags) 51 # null return? 52 beqz v0, common_exceptionThrown # alloc failed, handle exception 53 54 FETCH(a1, 2) # a1 <- FEDC or CCCC 55 sw v0, offThread_retval(rSELF) # retval.l <- new array 56 sw rINST, (offThread_retval+4)(rSELF) # retval.h <- type 57 addu a0, v0, offArrayObject_contents # a0 <- newArray->contents 58 subu rBIX, rBIX, 1 # length--, check for neg 59 FETCH_ADVANCE_INST(3) # advance to next instr, load rINST 60 bltz rBIX, 2f # was zero, bail 61 62 # copy values from registers into the array 63 # a0=array, a1=CCCC/FEDC, t0=length (from AA or B), rOBJ=AA/BA 64 move t0, rBIX 65 .if $isrange 66 EAS2(a2, rFP, a1) # a2 <- &fp[CCCC] 67 1: 68 lw a3, 0(a2) # a3 <- *a2++ 69 addu a2, 4 70 subu t0, t0, 1 # count-- 71 sw a3, (a0) # *contents++ = vX 72 addu a0, 4 73 bgez t0, 1b 74 75 # continue at 2 76 .else 77 slt t1, t0, 4 # length was initially 5? 78 and a2, rOBJ, 15 # a2 <- A 79 bnez t1, 1f # <= 4 args, branch 80 GET_VREG(a3, a2) # a3 <- vA 81 subu t0, t0, 1 # count-- 82 sw a3, 16(a0) # contents[4] = vA 83 1: 84 and a2, a1, 15 # a2 <- F/E/D/C 85 GET_VREG(a3, a2) # a3 <- vF/vE/vD/vC 86 srl a1, a1, 4 # a1 <- next reg in low 4 87 subu t0, t0, 1 # count-- 88 sw a3, 0(a0) # *contents++ = vX 89 addu a0, a0, 4 90 bgez t0, 1b 91 # continue at 2 92 .endif 93 94 2: 95 lw a0, offThread_retval(rSELF) # a0 <- object 96 lw a1, (offThread_retval+4)(rSELF) # a1 <- type 97 seq t1, a1, 'I' # Is int array? 98 bnez t1, 3f 99 lw a2, offThread_cardTable(rSELF) # a2 <- card table base 100 srl t3, a0, GC_CARD_SHIFT 101 addu t2, a2, t3 102 sb a2, (t2) 103 3: 104 GET_INST_OPCODE(t0) # ip <- opcode from rINST 105 GOTO_OPCODE(t0) # execute it 106 107 108 /* 109 * Throw an exception indicating that we have not implemented this 110 * mode of filled-new-array. 111 */ 112 .L${opcode}_notimpl: 113 la a0, .LstrFilledNewArrayNotImpl 114 JAL(dvmThrowInternalError) 115 b common_exceptionThrown 116 117 /* 118 * Ideally we'd only define this once, but depending on layout we can 119 * exceed the range of the load above. 120 */ 121