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