1*795d594fSAndroid Build Coastguard Worker// Note: Floating point operations must follow IEEE 754 rules, using round-to-nearest and gradual 2*795d594fSAndroid Build Coastguard Worker// underflow, except where stated otherwise. 3*795d594fSAndroid Build Coastguard Worker 4*795d594fSAndroid Build Coastguard Worker// 5*795d594fSAndroid Build Coastguard Worker// floating-point comparators vAA, vBB, vCC 6*795d594fSAndroid Build Coastguard Worker// Note: Perform the indicated floating point comparison, setting a to 0 if b == c, 1 if b > c, or 7*795d594fSAndroid Build Coastguard Worker// -1 if b < c. The "bias" listed indicates how NaN comparisons are treated: "gt bias" instructions 8*795d594fSAndroid Build Coastguard Worker// return 1 for NaN comparisons, and "lt bias" instructions return -1. 9*795d594fSAndroid Build Coastguard Worker// 10*795d594fSAndroid Build Coastguard Worker 11*795d594fSAndroid Build Coastguard Worker// cmpl-float vAA, vBB, vCC 12*795d594fSAndroid Build Coastguard Worker// Format 23x: AA|2d CC|BB 13*795d594fSAndroid Build Coastguard Worker// LT bias, if NaN then vAA := -1 14*795d594fSAndroid Build Coastguard Worker%def op_cmpl_float(is_double=False): 15*795d594fSAndroid Build Coastguard Worker FETCH t1, count=1 // t1 := CC|BB 16*795d594fSAndroid Build Coastguard Worker srliw t0, xINST, 8 // t0 := AA 17*795d594fSAndroid Build Coastguard Worker srliw t2, t1, 8 // t2 := CC 18*795d594fSAndroid Build Coastguard Worker andi t1, t1, 0xFF // t1 := BB 19*795d594fSAndroid Build Coastguard Worker% get_vreg_float("ft1", "t1", is_double=is_double) # ft1 := fp[BB] 20*795d594fSAndroid Build Coastguard Worker% get_vreg_float("ft2", "t2", is_double=is_double) # ft2 := fp[CC] 21*795d594fSAndroid Build Coastguard Worker // Note: Formula "((FLE r,l) - 1) + (FLT r,l)" lifted from compiler. 22*795d594fSAndroid Build Coastguard Worker% precision = "d" if is_double else "s" 23*795d594fSAndroid Build Coastguard Worker fle.${precision} t1, ft2, ft1 24*795d594fSAndroid Build Coastguard Worker flt.${precision} t2, ft2, ft1 25*795d594fSAndroid Build Coastguard Worker addi t1, t1, -1 26*795d594fSAndroid Build Coastguard Worker add t2, t2, t1 27*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 28*795d594fSAndroid Build Coastguard Worker% set_vreg("t2", "t0", z0="t1") # fp[AA] := result 29*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE t0 30*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE t0 31*795d594fSAndroid Build Coastguard Worker 32*795d594fSAndroid Build Coastguard Worker// cmpg-float vvAA, vBB, vCC 33*795d594fSAndroid Build Coastguard Worker// Format 23x: AA|2e CC|BB 34*795d594fSAndroid Build Coastguard Worker// GT bias, if NaN then vAA := 1 35*795d594fSAndroid Build Coastguard Worker%def op_cmpg_float(is_double=False): 36*795d594fSAndroid Build Coastguard Worker FETCH t1, count=1 // t1 := CC|BB 37*795d594fSAndroid Build Coastguard Worker srliw t0, xINST, 8 // t0 := AA 38*795d594fSAndroid Build Coastguard Worker srliw t2, t1, 8 // t2 := CC 39*795d594fSAndroid Build Coastguard Worker andi t1, t1, 0xFF // t1 := BB 40*795d594fSAndroid Build Coastguard Worker% get_vreg_float("ft1", "t1", is_double=is_double) # ft1 := fp[BB] 41*795d594fSAndroid Build Coastguard Worker% get_vreg_float("ft2", "t2", is_double=is_double) # ft2 := fp[CC] 42*795d594fSAndroid Build Coastguard Worker // Note: Formula "((FLE l,r) ^ 1) - (FLT l,r)" lifted from compiler. 43*795d594fSAndroid Build Coastguard Worker% precision = "d" if is_double else "s" 44*795d594fSAndroid Build Coastguard Worker fle.${precision} t1, ft1, ft2 45*795d594fSAndroid Build Coastguard Worker flt.${precision} t2, ft1, ft2 46*795d594fSAndroid Build Coastguard Worker xori t1, t1, 1 47*795d594fSAndroid Build Coastguard Worker sub t2, t1, t2 48*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 49*795d594fSAndroid Build Coastguard Worker% set_vreg("t2", "t0", z0="t1") # fp[AA] := result 50*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE t0 51*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE t0 52*795d594fSAndroid Build Coastguard Worker 53*795d594fSAndroid Build Coastguard Worker// cmpl-double vAA, vBB, vCC 54*795d594fSAndroid Build Coastguard Worker// Format 23x: AA|2f CC|BB 55*795d594fSAndroid Build Coastguard Worker// LT bias, if NaN then vAA := -1 56*795d594fSAndroid Build Coastguard Worker%def op_cmpl_double(): 57*795d594fSAndroid Build Coastguard Worker% op_cmpl_float(is_double=True) 58*795d594fSAndroid Build Coastguard Worker 59*795d594fSAndroid Build Coastguard Worker// cmpg-double vAA, vBB, vCC 60*795d594fSAndroid Build Coastguard Worker// Format 23x: AA|30 CC|BB 61*795d594fSAndroid Build Coastguard Worker// Note: Formula "((FLE l,r) ^ 1) - (FLT l,r)" lifted from compiler. 62*795d594fSAndroid Build Coastguard Worker// GT bias, if NaN then vAA := 1 63*795d594fSAndroid Build Coastguard Worker%def op_cmpg_double(): 64*795d594fSAndroid Build Coastguard Worker% op_cmpg_float(is_double=True) 65*795d594fSAndroid Build Coastguard Worker 66*795d594fSAndroid Build Coastguard Worker// 67*795d594fSAndroid Build Coastguard Worker// funop vA, vB 68*795d594fSAndroid Build Coastguard Worker// Format 12x: B|A|op 69*795d594fSAndroid Build Coastguard Worker// 70*795d594fSAndroid Build Coastguard Worker 71*795d594fSAndroid Build Coastguard Worker// neg-float vA, vB 72*795d594fSAndroid Build Coastguard Worker// Format 12x: B|A|7f 73*795d594fSAndroid Build Coastguard Worker%def op_neg_float(): 74*795d594fSAndroid Build Coastguard Worker% generic_funop(instr="fneg.s ft0, ft0", dst="s", src="s") 75*795d594fSAndroid Build Coastguard Worker 76*795d594fSAndroid Build Coastguard Worker// neg-double vA, vB 77*795d594fSAndroid Build Coastguard Worker// Format 12x: B|A|80 78*795d594fSAndroid Build Coastguard Worker%def op_neg_double(): 79*795d594fSAndroid Build Coastguard Worker% generic_funop(instr="fneg.d ft0, ft0", dst="d", src="d") 80*795d594fSAndroid Build Coastguard Worker 81*795d594fSAndroid Build Coastguard Worker// int-to-float vA, vB 82*795d594fSAndroid Build Coastguard Worker// Format 12x: B|A|82 83*795d594fSAndroid Build Coastguard Worker// Note: Conversion of int32 to float, using round-to-nearest. This loses precision for some values. 84*795d594fSAndroid Build Coastguard Worker// Note: For ties, the IEEE 754-2008 standard defaults to "roundTiesToEven" for binary floats. 85*795d594fSAndroid Build Coastguard Worker%def op_int_to_float(): 86*795d594fSAndroid Build Coastguard Worker% generic_funop(instr="fcvt.s.w ft0, t1, rne", dst="s", src="w") 87*795d594fSAndroid Build Coastguard Worker 88*795d594fSAndroid Build Coastguard Worker// int-to-double vA, vB 89*795d594fSAndroid Build Coastguard Worker// Format 12x: B|A|83 90*795d594fSAndroid Build Coastguard Worker// Note: Conversion of int32 to double. 91*795d594fSAndroid Build Coastguard Worker%def op_int_to_double(): 92*795d594fSAndroid Build Coastguard Worker% generic_funop(instr="fcvt.d.w ft0, t1", dst="d", src="w") 93*795d594fSAndroid Build Coastguard Worker 94*795d594fSAndroid Build Coastguard Worker// long-to-float vA, vB 95*795d594fSAndroid Build Coastguard Worker// Format 12x: B|A|85 96*795d594fSAndroid Build Coastguard Worker// Note: Conversion of int64 to float, using round-to-nearest. This loses precision for some values. 97*795d594fSAndroid Build Coastguard Worker// Note: For ties, the IEEE 754-2008 standard defaults to "roundTiesToEven" for binary floats. 98*795d594fSAndroid Build Coastguard Worker%def op_long_to_float(): 99*795d594fSAndroid Build Coastguard Worker% generic_funop(instr="fcvt.s.l ft0, t1, rne", dst="s", src="l") 100*795d594fSAndroid Build Coastguard Worker 101*795d594fSAndroid Build Coastguard Worker// long-to-double vA, vB 102*795d594fSAndroid Build Coastguard Worker// Format 12x: B|A|86 103*795d594fSAndroid Build Coastguard Worker// Note: Conversion of int64 to double, using round-to-nearest. This loses precision for some values. 104*795d594fSAndroid Build Coastguard Worker// Note: For ties, the IEEE 754-2008 standard defaults to "roundTiesToEven" for binary floats. 105*795d594fSAndroid Build Coastguard Worker%def op_long_to_double(): 106*795d594fSAndroid Build Coastguard Worker% generic_funop(instr="fcvt.d.l ft0, t1, rne", dst="d", src="l") 107*795d594fSAndroid Build Coastguard Worker 108*795d594fSAndroid Build Coastguard Worker// float-to-int vA, vB 109*795d594fSAndroid Build Coastguard Worker// Format 12x: B|A|87 110*795d594fSAndroid Build Coastguard Worker// Note: Conversion of float to int32, using round-toward-zero. NaN and -0.0 (negative zero) 111*795d594fSAndroid Build Coastguard Worker// convert to the integer 0. Infinities and values with too large a magnitude to be represented 112*795d594fSAndroid Build Coastguard Worker// get converted to either 0x7fffffff or -0x80000000 depending on sign. 113*795d594fSAndroid Build Coastguard Worker// 114*795d594fSAndroid Build Coastguard Worker// FCVT.W.S RTZ has the following behavior: 115*795d594fSAndroid Build Coastguard Worker// - NaN rounds to 0x7ffffff - requires check and set to zero. 116*795d594fSAndroid Build Coastguard Worker// - negative zero rounds to zero - matches dex spec. 117*795d594fSAndroid Build Coastguard Worker// - pos inf rounds to 0x7fffffff - matches dex spec. 118*795d594fSAndroid Build Coastguard Worker// - neg inf rounds to 0x80000000 - matches dex spec. 119*795d594fSAndroid Build Coastguard Worker%def op_float_to_int(): 120*795d594fSAndroid Build Coastguard Worker% generic_funop(instr="fcvt.w.s t1, ft0, rtz", dst="w", src="s", nan_zeroed=True) 121*795d594fSAndroid Build Coastguard Worker 122*795d594fSAndroid Build Coastguard Worker// float-to-long vA, vB 123*795d594fSAndroid Build Coastguard Worker// Format 12x: B|A|88 124*795d594fSAndroid Build Coastguard Worker// Note: Conversion of float to int64, using round-toward-zero. The same special case rules as for 125*795d594fSAndroid Build Coastguard Worker// float-to-int apply here, except that out-of-range values get converted to either 126*795d594fSAndroid Build Coastguard Worker// 0x7fffffffffffffff or -0x8000000000000000 depending on sign. 127*795d594fSAndroid Build Coastguard Worker// 128*795d594fSAndroid Build Coastguard Worker// FCVT.L.S RTZ has the following behavior: 129*795d594fSAndroid Build Coastguard Worker// - NaN rounds to 0x7fffffffffffffff - requires check and set to zero. 130*795d594fSAndroid Build Coastguard Worker// - negative zero rounds to zero - matches dex spec. 131*795d594fSAndroid Build Coastguard Worker// - pos inf rounds to 0x7fffffffffffffff - matches dex spec. 132*795d594fSAndroid Build Coastguard Worker// - neg inf rounds to 0x8000000000000000 - matches dex spec. 133*795d594fSAndroid Build Coastguard Worker%def op_float_to_long(): 134*795d594fSAndroid Build Coastguard Worker% generic_funop(instr="fcvt.l.s t1, ft0, rtz", dst="l", src="s", nan_zeroed=True) 135*795d594fSAndroid Build Coastguard Worker 136*795d594fSAndroid Build Coastguard Worker// float-to-double vA, vB 137*795d594fSAndroid Build Coastguard Worker// Format 12x: B|A|89 138*795d594fSAndroid Build Coastguard Worker// Note: Conversion of float to double, preserving the value exactly. 139*795d594fSAndroid Build Coastguard Worker%def op_float_to_double(): 140*795d594fSAndroid Build Coastguard Worker% generic_funop(instr="fcvt.d.s ft0, ft0", dst="d", src="s") 141*795d594fSAndroid Build Coastguard Worker 142*795d594fSAndroid Build Coastguard Worker// double-to-int vA, vB 143*795d594fSAndroid Build Coastguard Worker// Format 12x: B|A|8a 144*795d594fSAndroid Build Coastguard Worker// Note: Conversion of double to int32, using round-toward-zero. The same special case rules as for 145*795d594fSAndroid Build Coastguard Worker// float-to-int apply here. 146*795d594fSAndroid Build Coastguard Worker%def op_double_to_int(): 147*795d594fSAndroid Build Coastguard Worker% generic_funop(instr="fcvt.w.d t1, ft0, rtz", dst="w", src="d", nan_zeroed=True) 148*795d594fSAndroid Build Coastguard Worker 149*795d594fSAndroid Build Coastguard Worker// double-to-long vA, vB 150*795d594fSAndroid Build Coastguard Worker// Format 12x: B|A|8b 151*795d594fSAndroid Build Coastguard Worker// Note: Conversion of double to int64, using round-toward-zero. The same special case rules as for 152*795d594fSAndroid Build Coastguard Worker// float-to-long apply here. 153*795d594fSAndroid Build Coastguard Worker%def op_double_to_long(): 154*795d594fSAndroid Build Coastguard Worker% generic_funop(instr="fcvt.l.d t1, ft0, rtz", dst="l", src="d", nan_zeroed=True) 155*795d594fSAndroid Build Coastguard Worker 156*795d594fSAndroid Build Coastguard Worker// double-to-float vA, vB 157*795d594fSAndroid Build Coastguard Worker// Format 12x: B|A|8c 158*795d594fSAndroid Build Coastguard Worker// Note: Conversion of double to float, using round-to-nearest. This loses precision for some values. 159*795d594fSAndroid Build Coastguard Worker// Note: For ties, the IEEE 754-2008 standard defaults to "roundTiesToEven" for binary floats. 160*795d594fSAndroid Build Coastguard Worker%def op_double_to_float(): 161*795d594fSAndroid Build Coastguard Worker% generic_funop(instr="fcvt.s.d ft0, ft0, rne", dst="s", src="d") 162*795d594fSAndroid Build Coastguard Worker 163*795d594fSAndroid Build Coastguard Worker// unop boilerplate 164*795d594fSAndroid Build Coastguard Worker// instr: operand held in t1 or ft0, result written to t1 or ft0. 165*795d594fSAndroid Build Coastguard Worker// instr must not clobber t2. 166*795d594fSAndroid Build Coastguard Worker// dst: one of w (int32), l (int64), s (float), d (double) 167*795d594fSAndroid Build Coastguard Worker// src: one of w (int32), l (int64), s (float), d (double) 168*795d594fSAndroid Build Coastguard Worker// Clobbers: ft0, t0, t1, t2 169*795d594fSAndroid Build Coastguard Worker%def generic_funop(instr, dst, src, nan_zeroed=False): 170*795d594fSAndroid Build Coastguard Worker srliw t0, xINST, 12 // t0 := B 171*795d594fSAndroid Build Coastguard Worker srliw t2, xINST, 8 // t2 := B|A 172*795d594fSAndroid Build Coastguard Worker 173*795d594fSAndroid Build Coastguard Worker% if src == "w": 174*795d594fSAndroid Build Coastguard Worker% get_vreg("t1", "t0") # t1 := fp[B] 175*795d594fSAndroid Build Coastguard Worker% elif src == "l": 176*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE t1, t0 // t1 := fp[B] 177*795d594fSAndroid Build Coastguard Worker% elif src == "s": 178*795d594fSAndroid Build Coastguard Worker% get_vreg_float("ft0", "t0") # ft0 := fp[B] 179*795d594fSAndroid Build Coastguard Worker% elif src == "d": 180*795d594fSAndroid Build Coastguard Worker GET_VREG_DOUBLE ft0, t0 // ft0 := fp[B] 181*795d594fSAndroid Build Coastguard Worker% else: 182*795d594fSAndroid Build Coastguard Worker% assert false, src 183*795d594fSAndroid Build Coastguard Worker%#: 184*795d594fSAndroid Build Coastguard Worker and t2, t2, 0xF // t2 := A 185*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 1 // advance xPC, load xINST 186*795d594fSAndroid Build Coastguard Worker% if nan_zeroed: 187*795d594fSAndroid Build Coastguard Worker // Okay to clobber T1. It is not read if nan_zeroed=True. 188*795d594fSAndroid Build Coastguard Worker fclass.${src} t1, ft0 // fclass.s or fclass.d on the source register ft0 189*795d594fSAndroid Build Coastguard Worker sltiu t1, t1, 0x100 // t1 := 0 if NaN, per dex spec. Skip the conversion. 190*795d594fSAndroid Build Coastguard Worker beqz t1, 1f 191*795d594fSAndroid Build Coastguard Worker%#: 192*795d594fSAndroid Build Coastguard Worker $instr // read operand (from t1|ft0), write result (to t1|ft0) 193*795d594fSAndroid Build Coastguard Worker // do not clobber t2! 194*795d594fSAndroid Build Coastguard Worker1: 195*795d594fSAndroid Build Coastguard Worker 196*795d594fSAndroid Build Coastguard Worker% if dst == "w": 197*795d594fSAndroid Build Coastguard Worker% set_vreg("t1", "t2", z0="t0") # fp[A] := t1 198*795d594fSAndroid Build Coastguard Worker% elif dst == "l": 199*795d594fSAndroid Build Coastguard Worker SET_VREG_WIDE t1, t2, z0=t0 // fp[A] := t1 200*795d594fSAndroid Build Coastguard Worker% elif dst == "s": 201*795d594fSAndroid Build Coastguard Worker% set_vreg_float("ft0", "t2", z0="t0") # fp[A] := ft0 202*795d594fSAndroid Build Coastguard Worker% elif dst == "d": 203*795d594fSAndroid Build Coastguard Worker SET_VREG_DOUBLE ft0, t2, z0=t0 // fp[B] := ft0 204*795d594fSAndroid Build Coastguard Worker% else: 205*795d594fSAndroid Build Coastguard Worker% assert false, dst 206*795d594fSAndroid Build Coastguard Worker%#: 207*795d594fSAndroid Build Coastguard Worker 208*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE t0 // t0 holds next opcode 209*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE t0 // continue to next 210*795d594fSAndroid Build Coastguard Worker 211*795d594fSAndroid Build Coastguard Worker// 212*795d594fSAndroid Build Coastguard Worker// fbinop vAA, vBB, vCC 213*795d594fSAndroid Build Coastguard Worker// Format 23x: AA|op CC|BB 214*795d594fSAndroid Build Coastguard Worker// 215*795d594fSAndroid Build Coastguard Worker 216*795d594fSAndroid Build Coastguard Worker// add-float vAA, vBB, vCC 217*795d594fSAndroid Build Coastguard Worker// Format 23x: AA|a6 CC|BB 218*795d594fSAndroid Build Coastguard Worker%def op_add_float(): 219*795d594fSAndroid Build Coastguard Worker% generic_fbinop(instr="fadd.s fa0, fa0, fa1, rne") 220*795d594fSAndroid Build Coastguard Worker 221*795d594fSAndroid Build Coastguard Worker// sub-float vAA, vBB, vCC 222*795d594fSAndroid Build Coastguard Worker// Format 23x: AA|a7 CC|BB 223*795d594fSAndroid Build Coastguard Worker%def op_sub_float(): 224*795d594fSAndroid Build Coastguard Worker% generic_fbinop(instr="fsub.s fa0, fa0, fa1, rne") 225*795d594fSAndroid Build Coastguard Worker 226*795d594fSAndroid Build Coastguard Worker// mul-float vAA, vBB, vCC 227*795d594fSAndroid Build Coastguard Worker// Format 23x: AA|a8 CC|BB 228*795d594fSAndroid Build Coastguard Worker%def op_mul_float(): 229*795d594fSAndroid Build Coastguard Worker% generic_fbinop(instr="fmul.s fa0, fa0, fa1, rne") 230*795d594fSAndroid Build Coastguard Worker 231*795d594fSAndroid Build Coastguard Worker// div-float vAA, vBB, vCC 232*795d594fSAndroid Build Coastguard Worker// Format 23x: AA|a9 CC|BB 233*795d594fSAndroid Build Coastguard Worker%def op_div_float(): 234*795d594fSAndroid Build Coastguard Worker% generic_fbinop(instr="fdiv.s fa0, fa0, fa1, rne") 235*795d594fSAndroid Build Coastguard Worker 236*795d594fSAndroid Build Coastguard Worker// rem-float vAA, vBB, vCC 237*795d594fSAndroid Build Coastguard Worker// Format 23x: AA|aa CC|BB 238*795d594fSAndroid Build Coastguard Worker// Note: Floating point remainder after division. This function is different than IEEE 754 remainder 239*795d594fSAndroid Build Coastguard Worker// and is defined as result == a - roundTowardZero(a / b) * b. 240*795d594fSAndroid Build Coastguard Worker// Note: RISC-V does not offer floating point remainder; use fmodf in libm. 241*795d594fSAndroid Build Coastguard Worker%def op_rem_float(): 242*795d594fSAndroid Build Coastguard Worker% generic_fbinop(instr="call fmodf") 243*795d594fSAndroid Build Coastguard Worker 244*795d594fSAndroid Build Coastguard Worker// add-double vAA, vBB, vCC 245*795d594fSAndroid Build Coastguard Worker// Format 23x: AA|ab CC|BB 246*795d594fSAndroid Build Coastguard Worker%def op_add_double(): 247*795d594fSAndroid Build Coastguard Worker% generic_fbinop(instr="fadd.d fa0, fa0, fa1, rne", is_double=True) 248*795d594fSAndroid Build Coastguard Worker 249*795d594fSAndroid Build Coastguard Worker// sub-double vAA, vBB, vCC 250*795d594fSAndroid Build Coastguard Worker// Format 23x: AA|ac CC|BB 251*795d594fSAndroid Build Coastguard Worker%def op_sub_double(): 252*795d594fSAndroid Build Coastguard Worker% generic_fbinop(instr="fsub.d fa0, fa0, fa1, rne", is_double=True) 253*795d594fSAndroid Build Coastguard Worker 254*795d594fSAndroid Build Coastguard Worker// mul-double vAA, vBB, vCC 255*795d594fSAndroid Build Coastguard Worker// Format 23x: AA|ad CC|BB 256*795d594fSAndroid Build Coastguard Worker%def op_mul_double(): 257*795d594fSAndroid Build Coastguard Worker% generic_fbinop(instr="fmul.d fa0, fa0, fa1, rne", is_double=True) 258*795d594fSAndroid Build Coastguard Worker 259*795d594fSAndroid Build Coastguard Worker// div-double vAA, vBB, vCC 260*795d594fSAndroid Build Coastguard Worker// Format 23x: AA|ae CC|BB 261*795d594fSAndroid Build Coastguard Worker%def op_div_double(): 262*795d594fSAndroid Build Coastguard Worker% generic_fbinop(instr="fdiv.d fa0, fa0, fa1, rne", is_double=True) 263*795d594fSAndroid Build Coastguard Worker 264*795d594fSAndroid Build Coastguard Worker// rem-double vAA, vBB, vCC 265*795d594fSAndroid Build Coastguard Worker// Format 23x: AA|af CC|BB 266*795d594fSAndroid Build Coastguard Worker// Note: Floating point remainder after division. This function is different than IEEE 754 remainder 267*795d594fSAndroid Build Coastguard Worker// and is defined as result == a - roundTowardZero(a / b) * b. 268*795d594fSAndroid Build Coastguard Worker// Note: RISC-V does not offer floating point remainder; use fmod in libm. 269*795d594fSAndroid Build Coastguard Worker%def op_rem_double(): 270*795d594fSAndroid Build Coastguard Worker% generic_fbinop(instr="call fmod", is_double=True) 271*795d594fSAndroid Build Coastguard Worker 272*795d594fSAndroid Build Coastguard Worker// fbinop boilerplate 273*795d594fSAndroid Build Coastguard Worker// instr: operands held in fa0 and fa1, result written to fa0 274*795d594fSAndroid Build Coastguard Worker// instr may be a libm call, so: 275*795d594fSAndroid Build Coastguard Worker// - avoid caller-save state across instr; s11 is used instead. 276*795d594fSAndroid Build Coastguard Worker// - fa0 and fa1 are used instead of ft0 and ft1. 277*795d594fSAndroid Build Coastguard Worker// 278*795d594fSAndroid Build Coastguard Worker// The is_double flag ensures vregs are read and written in 64-bit widths. 279*795d594fSAndroid Build Coastguard Worker// Clobbers: t0, t1, fa0, fa1, s11 280*795d594fSAndroid Build Coastguard Worker%def generic_fbinop(instr, is_double=False): 281*795d594fSAndroid Build Coastguard Worker FETCH t0, count=1 // t0 := CC|BB 282*795d594fSAndroid Build Coastguard Worker srliw s11, xINST, 8 // s11 := AA 283*795d594fSAndroid Build Coastguard Worker srliw t1, t0, 8 // t1 := CC 284*795d594fSAndroid Build Coastguard Worker and t0, t0, 0xFF // t0 := BB 285*795d594fSAndroid Build Coastguard Worker% get_vreg_float("fa1", "t1", is_double=is_double) 286*795d594fSAndroid Build Coastguard Worker // fa1 := fp[CC] 287*795d594fSAndroid Build Coastguard Worker% get_vreg_float("fa0", "t0", is_double=is_double) 288*795d594fSAndroid Build Coastguard Worker // fa0 := fp[BB] 289*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 // advance xPC, load xINST 290*795d594fSAndroid Build Coastguard Worker $instr // read fa0 and fa1, write result to fa0. 291*795d594fSAndroid Build Coastguard Worker // instr may be a function call. 292*795d594fSAndroid Build Coastguard Worker% set_vreg_float("fa0", "s11", z0="t0", is_double=is_double) 293*795d594fSAndroid Build Coastguard Worker // fp[AA] := fa0 294*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE t0 // t0 holds next opcode 295*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE t0 // continue to next 296*795d594fSAndroid Build Coastguard Worker 297*795d594fSAndroid Build Coastguard Worker// 298*795d594fSAndroid Build Coastguard Worker// fbinop/2addr vA, vB 299*795d594fSAndroid Build Coastguard Worker// Format 12x: B|A|op 300*795d594fSAndroid Build Coastguard Worker// 301*795d594fSAndroid Build Coastguard Worker 302*795d594fSAndroid Build Coastguard Worker// add-float/2addr vA, vB 303*795d594fSAndroid Build Coastguard Worker// Format 12x: B|A|c6 304*795d594fSAndroid Build Coastguard Worker%def op_add_float_2addr(): 305*795d594fSAndroid Build Coastguard Worker% generic_fbinop_2addr(instr="fadd.s fa0, fa0, fa1") 306*795d594fSAndroid Build Coastguard Worker 307*795d594fSAndroid Build Coastguard Worker// sub-float/2addr vA, vB 308*795d594fSAndroid Build Coastguard Worker// Format 12x: B|A|c7 309*795d594fSAndroid Build Coastguard Worker%def op_sub_float_2addr(): 310*795d594fSAndroid Build Coastguard Worker% generic_fbinop_2addr(instr="fsub.s fa0, fa0, fa1") 311*795d594fSAndroid Build Coastguard Worker 312*795d594fSAndroid Build Coastguard Worker// mul-float/2addr vA, vB 313*795d594fSAndroid Build Coastguard Worker// Format 12x: B|A|c8 314*795d594fSAndroid Build Coastguard Worker%def op_mul_float_2addr(): 315*795d594fSAndroid Build Coastguard Worker% generic_fbinop_2addr(instr="fmul.s fa0, fa0, fa1") 316*795d594fSAndroid Build Coastguard Worker 317*795d594fSAndroid Build Coastguard Worker// div-float/2addr vA, vB 318*795d594fSAndroid Build Coastguard Worker// Format 12x: B|A|c9 319*795d594fSAndroid Build Coastguard Worker%def op_div_float_2addr(): 320*795d594fSAndroid Build Coastguard Worker% generic_fbinop_2addr(instr="fdiv.s fa0, fa0, fa1") 321*795d594fSAndroid Build Coastguard Worker 322*795d594fSAndroid Build Coastguard Worker// rem-float/2addr vA, vB 323*795d594fSAndroid Build Coastguard Worker// Format 12x: B|A|ca 324*795d594fSAndroid Build Coastguard Worker// Note: Floating point remainder after division. This function is different than IEEE 754 remainder 325*795d594fSAndroid Build Coastguard Worker// and is defined as result == a - roundTowardZero(a / b) * b. 326*795d594fSAndroid Build Coastguard Worker// Note: RISC-V does not offer floating point remainder; use fmodf in libm. 327*795d594fSAndroid Build Coastguard Worker%def op_rem_float_2addr(): 328*795d594fSAndroid Build Coastguard Worker% generic_fbinop_2addr(instr="call fmodf") 329*795d594fSAndroid Build Coastguard Worker 330*795d594fSAndroid Build Coastguard Worker// add-double/2addr vA, vB 331*795d594fSAndroid Build Coastguard Worker// Format 12x: B|A|cb 332*795d594fSAndroid Build Coastguard Worker%def op_add_double_2addr(): 333*795d594fSAndroid Build Coastguard Worker% generic_fbinop_2addr(instr="fadd.d fa0, fa0, fa1", is_double=True) 334*795d594fSAndroid Build Coastguard Worker 335*795d594fSAndroid Build Coastguard Worker// sub-double/2addr vA, vB 336*795d594fSAndroid Build Coastguard Worker// Format 12x: B|A|cc 337*795d594fSAndroid Build Coastguard Worker%def op_sub_double_2addr(): 338*795d594fSAndroid Build Coastguard Worker% generic_fbinop_2addr(instr="fsub.d fa0, fa0, fa1", is_double=True) 339*795d594fSAndroid Build Coastguard Worker 340*795d594fSAndroid Build Coastguard Worker// mul-double/2addr vA, vB 341*795d594fSAndroid Build Coastguard Worker// Format 12x: B|A|cd 342*795d594fSAndroid Build Coastguard Worker%def op_mul_double_2addr(): 343*795d594fSAndroid Build Coastguard Worker% generic_fbinop_2addr(instr="fmul.d fa0, fa0, fa1", is_double=True) 344*795d594fSAndroid Build Coastguard Worker 345*795d594fSAndroid Build Coastguard Worker// div-double/2addr vA, vB 346*795d594fSAndroid Build Coastguard Worker// Format 12x: B|A|ce 347*795d594fSAndroid Build Coastguard Worker%def op_div_double_2addr(): 348*795d594fSAndroid Build Coastguard Worker% generic_fbinop_2addr(instr="fdiv.d fa0, fa0, fa1", is_double=True) 349*795d594fSAndroid Build Coastguard Worker 350*795d594fSAndroid Build Coastguard Worker// rem-double/2addr vA, vB 351*795d594fSAndroid Build Coastguard Worker// Format 12x: B|A|cf 352*795d594fSAndroid Build Coastguard Worker// Note: Floating point remainder after division. This function is different than IEEE 754 remainder 353*795d594fSAndroid Build Coastguard Worker// and is defined as result == a - roundTowardZero(a / b) * b. 354*795d594fSAndroid Build Coastguard Worker// Note: RISC-V does not offer floating point remainder; use fmod in libm. 355*795d594fSAndroid Build Coastguard Worker%def op_rem_double_2addr(): 356*795d594fSAndroid Build Coastguard Worker% generic_fbinop_2addr(instr="call fmod", is_double=True) 357*795d594fSAndroid Build Coastguard Worker 358*795d594fSAndroid Build Coastguard Worker// fbinop/2addr boilerplate 359*795d594fSAndroid Build Coastguard Worker// instr: operands held in fa0 and fa1, result written to fa0 360*795d594fSAndroid Build Coastguard Worker// instr may be a libm call, so: 361*795d594fSAndroid Build Coastguard Worker// - avoid caller-save state across instr; s11 is used instead. 362*795d594fSAndroid Build Coastguard Worker// - use fa0 and fa1 instead of ft0 and ft1. 363*795d594fSAndroid Build Coastguard Worker// 364*795d594fSAndroid Build Coastguard Worker// The is_double flag ensures vregs are read and written in 64-bit widths. 365*795d594fSAndroid Build Coastguard Worker// Clobbers: t0, t1, fa0, fa1, s11 366*795d594fSAndroid Build Coastguard Worker%def generic_fbinop_2addr(instr, is_double=False): 367*795d594fSAndroid Build Coastguard Worker srliw t0, xINST, 8 // t0 := B|A 368*795d594fSAndroid Build Coastguard Worker srliw t1, xINST, 12 // t1 := B 369*795d594fSAndroid Build Coastguard Worker and t0, t0, 0xF // t0 := A 370*795d594fSAndroid Build Coastguard Worker% get_vreg_float("fa1", "t1", is_double=is_double) 371*795d594fSAndroid Build Coastguard Worker // fa1 := fp[B] 372*795d594fSAndroid Build Coastguard Worker mv s11, t0 // s11 := A 373*795d594fSAndroid Build Coastguard Worker% get_vreg_float("fa0", "t0", is_double=is_double) 374*795d594fSAndroid Build Coastguard Worker // fa0 := fp[A] 375*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 1 // advance xPC, load xINST 376*795d594fSAndroid Build Coastguard Worker $instr // read fa0 and f1, write result to fa0. 377*795d594fSAndroid Build Coastguard Worker // instr may be a function call. 378*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE t1 // t1 holds next opcode 379*795d594fSAndroid Build Coastguard Worker% set_vreg_float("fa0", "s11", z0="t0", is_double=is_double) 380*795d594fSAndroid Build Coastguard Worker // fp[A] := fa0 381*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE t1 // continue to next 382