1*795d594fSAndroid Build Coastguard Worker// return-void 2*795d594fSAndroid Build Coastguard Worker// Format 10x: 00|0e 3*795d594fSAndroid Build Coastguard Worker%def op_return_void(): 4*795d594fSAndroid Build Coastguard Worker% op_return(is_void=True) 5*795d594fSAndroid Build Coastguard Worker 6*795d594fSAndroid Build Coastguard Worker 7*795d594fSAndroid Build Coastguard Worker// return vAA 8*795d594fSAndroid Build Coastguard Worker// Format 11x: AA|0f 9*795d594fSAndroid Build Coastguard Worker// Clobbers: t0 10*795d594fSAndroid Build Coastguard Worker%def op_return(is_object=False, is_void=False, is_wide=False): 11*795d594fSAndroid Build Coastguard Worker% if is_void: 12*795d594fSAndroid Build Coastguard Worker // Thread fence for constructor 13*795d594fSAndroid Build Coastguard Worker fence w, w 14*795d594fSAndroid Build Coastguard Worker% else: 15*795d594fSAndroid Build Coastguard Worker srliw t0, xINST, 8 // t0 := AA 16*795d594fSAndroid Build Coastguard Worker% if is_wide: 17*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE a0, t0 // a0 := fp[AA:AA+1] 18*795d594fSAndroid Build Coastguard Worker // The method may return to compiled code, so also place result in fa0. 19*795d594fSAndroid Build Coastguard Worker fmv.d.x fa0, a0 20*795d594fSAndroid Build Coastguard Worker% elif is_object: 21*795d594fSAndroid Build Coastguard Worker GET_VREG_OBJECT a0, t0 // a0 := refs[AA] 22*795d594fSAndroid Build Coastguard Worker% else: 23*795d594fSAndroid Build Coastguard Worker% get_vreg("a0", "t0") # a0 := fp[AA] 24*795d594fSAndroid Build Coastguard Worker // The method may return to compiled code, so also place result in fa0. 25*795d594fSAndroid Build Coastguard Worker fmv.w.x fa0, a0 26*795d594fSAndroid Build Coastguard Worker%#: 27*795d594fSAndroid Build Coastguard Worker 28*795d594fSAndroid Build Coastguard Worker CFI_REMEMBER_STATE 29*795d594fSAndroid Build Coastguard Worker ld sp, -8(xREFS) // caller's interpreted frame pointer 30*795d594fSAndroid Build Coastguard Worker .cfi_def_cfa sp, NTERP_SIZE_SAVE_CALLEE_SAVES 31*795d594fSAndroid Build Coastguard Worker RESTORE_NTERP_SAVE_CALLEE_SAVES 32*795d594fSAndroid Build Coastguard Worker DECREASE_FRAME NTERP_SIZE_SAVE_CALLEE_SAVES 33*795d594fSAndroid Build Coastguard Worker ret 34*795d594fSAndroid Build Coastguard Worker // Since opcode handlers are merely labeled asm chunks within ExecuteNterpImpl's FDE, we must 35*795d594fSAndroid Build Coastguard Worker // restate the correct CFA rule for subsequent handlers. It is initially stated when setting up 36*795d594fSAndroid Build Coastguard Worker // the nterp frame (setup_nterp_frame). 37*795d594fSAndroid Build Coastguard Worker .cfi_restore_state 38*795d594fSAndroid Build Coastguard Worker CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, NTERP_SIZE_SAVE_CALLEE_SAVES 39*795d594fSAndroid Build Coastguard Worker 40*795d594fSAndroid Build Coastguard Worker// return-wide vAA 41*795d594fSAndroid Build Coastguard Worker// Format 11x: AA|10 42*795d594fSAndroid Build Coastguard Worker%def op_return_wide(): 43*795d594fSAndroid Build Coastguard Worker% op_return(is_wide=True) 44*795d594fSAndroid Build Coastguard Worker 45*795d594fSAndroid Build Coastguard Worker// return-object vAA 46*795d594fSAndroid Build Coastguard Worker// Format 11x: AA|11 47*795d594fSAndroid Build Coastguard Worker%def op_return_object(): 48*795d594fSAndroid Build Coastguard Worker% op_return(is_object=True) 49*795d594fSAndroid Build Coastguard Worker 50*795d594fSAndroid Build Coastguard Worker// throw vAA 51*795d594fSAndroid Build Coastguard Worker// Format 11x: AA|27 52*795d594fSAndroid Build Coastguard Worker// Throw the indicated exception. 53*795d594fSAndroid Build Coastguard Worker%def op_throw(): 54*795d594fSAndroid Build Coastguard Worker EXPORT_PC 55*795d594fSAndroid Build Coastguard Worker srliw t0, xINST, 8 // t0 := AA 56*795d594fSAndroid Build Coastguard Worker GET_VREG_OBJECT a0, t0 // a0 := exception object 57*795d594fSAndroid Build Coastguard Worker mv a1, xSELF 58*795d594fSAndroid Build Coastguard Worker call art_quick_deliver_exception // args a0, a1 59*795d594fSAndroid Build Coastguard Worker unimp 60*795d594fSAndroid Build Coastguard Worker 61*795d594fSAndroid Build Coastguard Worker// goto +AA 62*795d594fSAndroid Build Coastguard Worker// Format 10t: AA|28 63*795d594fSAndroid Build Coastguard Worker// Unconditionally jump to the indicated instruction. 64*795d594fSAndroid Build Coastguard Worker// Note: The branch offset must not be 0. 65*795d594fSAndroid Build Coastguard Worker%def op_goto(): 66*795d594fSAndroid Build Coastguard Worker srliw t0, xINST, 8 // t0 := AA (zext) 67*795d594fSAndroid Build Coastguard Worker sext.b t0, t0 // t0 := +AA (sext) 68*795d594fSAndroid Build Coastguard Worker BRANCH units=t0 69*795d594fSAndroid Build Coastguard Worker 70*795d594fSAndroid Build Coastguard Worker// goto/16 +AAAA 71*795d594fSAndroid Build Coastguard Worker// Format 20t: 00|29 AAAA 72*795d594fSAndroid Build Coastguard Worker// Unconditionally jump to the indicated instruction. 73*795d594fSAndroid Build Coastguard Worker// Note: The branch offset must not be 0. 74*795d594fSAndroid Build Coastguard Worker%def op_goto_16(): 75*795d594fSAndroid Build Coastguard Worker FETCH t0, 1, signed=1 // t0 := +AAAA (sext) 76*795d594fSAndroid Build Coastguard Worker BRANCH units=t0 77*795d594fSAndroid Build Coastguard Worker 78*795d594fSAndroid Build Coastguard Worker// goto/32 +AAAAAAAA 79*795d594fSAndroid Build Coastguard Worker// Format 30t: 00|2a AAAA(lo) AAAA(hi) 80*795d594fSAndroid Build Coastguard Worker// Unconditionally jump to the indicated instruction. 81*795d594fSAndroid Build Coastguard Worker%def op_goto_32(): 82*795d594fSAndroid Build Coastguard Worker FETCH t0, 1, signed=1, width=32 // t0 := +AAAAAAAA (sext) 83*795d594fSAndroid Build Coastguard Worker BRANCH units=t0 84*795d594fSAndroid Build Coastguard Worker 85*795d594fSAndroid Build Coastguard Worker// packed-switch vAA, +BBBBBBBB 86*795d594fSAndroid Build Coastguard Worker// Format 31t: AA|2b BBBB(lo) BBBB(hi) 87*795d594fSAndroid Build Coastguard Worker// Jump to a new instruction based on the value in the given register, using a table of offsets 88*795d594fSAndroid Build Coastguard Worker// corresponding to each value in a particular integral range, or fall through to the next 89*795d594fSAndroid Build Coastguard Worker// instruction if there is no match. 90*795d594fSAndroid Build Coastguard Worker%def op_packed_switch(is_packed=True): 91*795d594fSAndroid Build Coastguard Worker srliw t0, xINST, 8 // t0 := AA 92*795d594fSAndroid Build Coastguard Worker FETCH t1, count=1, signed=1, width=32 // t1 := +BBBBBBBB (sext) 93*795d594fSAndroid Build Coastguard Worker% get_vreg("a1", "t0") # a1 := vAA 94*795d594fSAndroid Build Coastguard Worker sh1add a0, t1, xPC // a0 := +BBBBBBBB * 2 + xPC 95*795d594fSAndroid Build Coastguard Worker% if is_packed: 96*795d594fSAndroid Build Coastguard Worker call NterpDoPackedSwitch // args a0 (switchData), a1 (value) 97*795d594fSAndroid Build Coastguard Worker% else: 98*795d594fSAndroid Build Coastguard Worker call NterpDoSparseSwitch // args a0 (switchData), a1 (value) 99*795d594fSAndroid Build Coastguard Worker%#: 100*795d594fSAndroid Build Coastguard Worker BRANCH units=a0 101*795d594fSAndroid Build Coastguard Worker 102*795d594fSAndroid Build Coastguard Worker// sparse-switch vAA, +BBBBBBBB 103*795d594fSAndroid Build Coastguard Worker// Format 31t: AA|2c BBBB(lo) BBBB(hi) 104*795d594fSAndroid Build Coastguard Worker// Jump to a new instruction based on the value in the given register, using an ordered table of 105*795d594fSAndroid Build Coastguard Worker// value-offset pairs, or fall through to the next instruction if there is no match. 106*795d594fSAndroid Build Coastguard Worker%def op_sparse_switch(): 107*795d594fSAndroid Build Coastguard Worker% op_packed_switch(is_packed=False) 108*795d594fSAndroid Build Coastguard Worker 109*795d594fSAndroid Build Coastguard Worker// cmp-long vAA, vBB, vCC 110*795d594fSAndroid Build Coastguard Worker// Format 23x: AA|31 CC|BB 111*795d594fSAndroid Build Coastguard Worker%def op_cmp_long(): 112*795d594fSAndroid Build Coastguard Worker FETCH t1, count=1 // t1 := CC|BB 113*795d594fSAndroid Build Coastguard Worker srliw t0, xINST, 8 // t0 := AA 114*795d594fSAndroid Build Coastguard Worker srliw t2, t1, 8 // t2 := CC 115*795d594fSAndroid Build Coastguard Worker andi t1, t1, 0xFF // t1 := BB 116*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE t1, t1 // t1 := fp[BB] 117*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE t2, t2 // t2 := fp[CC] 118*795d594fSAndroid Build Coastguard Worker // Note: Formula "(SLT r,l) - (SLT l,r)" lifted from compiler. 119*795d594fSAndroid Build Coastguard Worker slt t3, t1, t2 120*795d594fSAndroid Build Coastguard Worker slt t4, t2, t1 121*795d594fSAndroid Build Coastguard Worker sub t4, t4, t3 122*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 123*795d594fSAndroid Build Coastguard Worker% set_vreg("t4", "t0", z0="t1") # fp[AA] := t4 124*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE t0 125*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE t0 126*795d594fSAndroid Build Coastguard Worker 127*795d594fSAndroid Build Coastguard Worker// Common helper for if-test. 128*795d594fSAndroid Build Coastguard Worker// Format 22t: B|A|op CCCC 129*795d594fSAndroid Build Coastguard Worker%def bincmp(op): 130*795d594fSAndroid Build Coastguard Worker srliw t0, xINST, 8 // t0 := B|A 131*795d594fSAndroid Build Coastguard Worker srliw t1, xINST, 12 // t1 := B 132*795d594fSAndroid Build Coastguard Worker andi t0, t0, 0xF // t0 := A 133*795d594fSAndroid Build Coastguard Worker% get_vreg("t0", "t0") # t0 := vA 134*795d594fSAndroid Build Coastguard Worker% get_vreg("t1", "t1") # t1 := vB 135*795d594fSAndroid Build Coastguard Worker b${op} t0, t1, .L${opcode}_branch 136*795d594fSAndroid Build Coastguard Worker 137*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 138*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE t2 139*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE t2 140*795d594fSAndroid Build Coastguard Worker 141*795d594fSAndroid Build Coastguard Worker.L${opcode}_branch: 142*795d594fSAndroid Build Coastguard Worker FETCH t2, count=1, signed=1 // t2 := +CCCC (sext) 143*795d594fSAndroid Build Coastguard Worker BRANCH units=t2 144*795d594fSAndroid Build Coastguard Worker 145*795d594fSAndroid Build Coastguard Worker// if-eq vA, vB, +CCCC 146*795d594fSAndroid Build Coastguard Worker// Format 22t: B|A|32 CCCC 147*795d594fSAndroid Build Coastguard Worker// Branch to the given destination if the given two registers' values compare as specified. 148*795d594fSAndroid Build Coastguard Worker// Note: The branch offset must not be 0. 149*795d594fSAndroid Build Coastguard Worker%def op_if_eq(): 150*795d594fSAndroid Build Coastguard Worker% bincmp(op="eq") 151*795d594fSAndroid Build Coastguard Worker 152*795d594fSAndroid Build Coastguard Worker// if-ne vA, vB, +CCCC 153*795d594fSAndroid Build Coastguard Worker// Format 22t: B|A|33 CCCC 154*795d594fSAndroid Build Coastguard Worker// Branch to the given destination if the given two registers' values compare as specified. 155*795d594fSAndroid Build Coastguard Worker// Note: The branch offset must not be 0. 156*795d594fSAndroid Build Coastguard Worker%def op_if_ne(): 157*795d594fSAndroid Build Coastguard Worker% bincmp(op="ne") 158*795d594fSAndroid Build Coastguard Worker 159*795d594fSAndroid Build Coastguard Worker// if-lt vA, vB, +CCCC 160*795d594fSAndroid Build Coastguard Worker// Format 22t: B|A|34 CCCC 161*795d594fSAndroid Build Coastguard Worker// Branch to the given destination if the given two registers' values compare as specified. 162*795d594fSAndroid Build Coastguard Worker// Note: The branch offset must not be 0. 163*795d594fSAndroid Build Coastguard Worker%def op_if_lt(): 164*795d594fSAndroid Build Coastguard Worker% bincmp(op="lt") 165*795d594fSAndroid Build Coastguard Worker 166*795d594fSAndroid Build Coastguard Worker// if-ge vA, vB, +CCCC 167*795d594fSAndroid Build Coastguard Worker// Format 22t: B|A|35 CCCC 168*795d594fSAndroid Build Coastguard Worker// Branch to the given destination if the given two registers' values compare as specified. 169*795d594fSAndroid Build Coastguard Worker// Note: The branch offset must not be 0. 170*795d594fSAndroid Build Coastguard Worker%def op_if_ge(): 171*795d594fSAndroid Build Coastguard Worker% bincmp(op="ge") 172*795d594fSAndroid Build Coastguard Worker 173*795d594fSAndroid Build Coastguard Worker// if-gt vA, vB, +CCCC 174*795d594fSAndroid Build Coastguard Worker// Format 22t: B|A|36 CCCC 175*795d594fSAndroid Build Coastguard Worker// Branch to the given destination if the given two registers' values compare as specified. 176*795d594fSAndroid Build Coastguard Worker// Note: The branch offset must not be 0. 177*795d594fSAndroid Build Coastguard Worker%def op_if_gt(): 178*795d594fSAndroid Build Coastguard Worker% bincmp(op="gt") 179*795d594fSAndroid Build Coastguard Worker 180*795d594fSAndroid Build Coastguard Worker// if-le vA, vB, +CCCC 181*795d594fSAndroid Build Coastguard Worker// Format 22t: B|A|37 CCCC 182*795d594fSAndroid Build Coastguard Worker// Branch to the given destination if the given two registers' values compare as specified. 183*795d594fSAndroid Build Coastguard Worker// Note: The branch offset must not be 0. 184*795d594fSAndroid Build Coastguard Worker%def op_if_le(): 185*795d594fSAndroid Build Coastguard Worker% bincmp(op="le") 186*795d594fSAndroid Build Coastguard Worker 187*795d594fSAndroid Build Coastguard Worker// Common helper for if-testz. 188*795d594fSAndroid Build Coastguard Worker// Format 21t: AA|op BBBB 189*795d594fSAndroid Build Coastguard Worker%def zcmp(op): 190*795d594fSAndroid Build Coastguard Worker srliw t0, xINST, 8 // t0 := AA 191*795d594fSAndroid Build Coastguard Worker% get_vreg("t0", "t0") # t0 := vAA 192*795d594fSAndroid Build Coastguard Worker b${op} t0, .L${opcode}_branch 193*795d594fSAndroid Build Coastguard Worker 194*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 195*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE t1 196*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE t1 197*795d594fSAndroid Build Coastguard Worker 198*795d594fSAndroid Build Coastguard Worker.L${opcode}_branch: 199*795d594fSAndroid Build Coastguard Worker FETCH t1, count=1, signed=1 // t1 := +BBBB (sext) 200*795d594fSAndroid Build Coastguard Worker BRANCH units=t1 201*795d594fSAndroid Build Coastguard Worker 202*795d594fSAndroid Build Coastguard Worker// if-eqz vAA, +BBBB 203*795d594fSAndroid Build Coastguard Worker// Format 21t: AA|38 BBBB 204*795d594fSAndroid Build Coastguard Worker// Branch to the given destination if the given register's value compares with 0 as specified. 205*795d594fSAndroid Build Coastguard Worker// Note: The branch offset must not be 0. 206*795d594fSAndroid Build Coastguard Worker%def op_if_eqz(): 207*795d594fSAndroid Build Coastguard Worker% zcmp(op="eqz") 208*795d594fSAndroid Build Coastguard Worker 209*795d594fSAndroid Build Coastguard Worker// if-nez vAA, +BBBB 210*795d594fSAndroid Build Coastguard Worker// Format 21t: AA|39 BBBB 211*795d594fSAndroid Build Coastguard Worker// Branch to the given destination if the given register's value compares with 0 as specified. 212*795d594fSAndroid Build Coastguard Worker// Note: The branch offset must not be 0. 213*795d594fSAndroid Build Coastguard Worker%def op_if_nez(): 214*795d594fSAndroid Build Coastguard Worker% zcmp(op="nez") 215*795d594fSAndroid Build Coastguard Worker 216*795d594fSAndroid Build Coastguard Worker// if-ltz vAA, +BBBB 217*795d594fSAndroid Build Coastguard Worker// Format 21t: AA|3a BBBB 218*795d594fSAndroid Build Coastguard Worker// Branch to the given destination if the given register's value compares with 0 as specified. 219*795d594fSAndroid Build Coastguard Worker// Note: The branch offset must not be 0. 220*795d594fSAndroid Build Coastguard Worker%def op_if_ltz(): 221*795d594fSAndroid Build Coastguard Worker% zcmp(op="ltz") 222*795d594fSAndroid Build Coastguard Worker 223*795d594fSAndroid Build Coastguard Worker// if-gez vAA, +BBBB 224*795d594fSAndroid Build Coastguard Worker// Format 21t: AA|3b BBBB 225*795d594fSAndroid Build Coastguard Worker// Branch to the given destination if the given register's value compares with 0 as specified. 226*795d594fSAndroid Build Coastguard Worker// Note: The branch offset must not be 0. 227*795d594fSAndroid Build Coastguard Worker%def op_if_gez(): 228*795d594fSAndroid Build Coastguard Worker% zcmp(op="gez") 229*795d594fSAndroid Build Coastguard Worker 230*795d594fSAndroid Build Coastguard Worker// if-gtz vAA, +BBBB 231*795d594fSAndroid Build Coastguard Worker// Format 21t: AA|3c BBBB 232*795d594fSAndroid Build Coastguard Worker// Branch to the given destination if the given register's value compares with 0 as specified. 233*795d594fSAndroid Build Coastguard Worker// Note: The branch offset must not be 0. 234*795d594fSAndroid Build Coastguard Worker%def op_if_gtz(): 235*795d594fSAndroid Build Coastguard Worker% zcmp(op="gtz") 236*795d594fSAndroid Build Coastguard Worker 237*795d594fSAndroid Build Coastguard Worker// if-lez vAA, +BBBB 238*795d594fSAndroid Build Coastguard Worker// Format 21t: AA|3d BBBB 239*795d594fSAndroid Build Coastguard Worker// Branch to the given destination if the given register's value compares with 0 as specified. 240*795d594fSAndroid Build Coastguard Worker// Note: The branch offset must not be 0. 241*795d594fSAndroid Build Coastguard Worker%def op_if_lez(): 242*795d594fSAndroid Build Coastguard Worker% zcmp(op="lez") 243*795d594fSAndroid Build Coastguard Worker 244