1%def fbinop(instr=""): 2 /* 3 * Generic 32-bit binary float operation. 4 * 5 * For: add-fp, sub-fp, mul-fp, div-fp, rem-fp 6 */ 7 8 /* binop vAA, vBB, vCC */ 9 FETCH(a0, 1) # a0 <- CCBB 10 GET_OPA(rOBJ) # rOBJ <- AA 11 srl a3, a0, 8 # a3 <- CC 12 and a2, a0, 255 # a2 <- BB 13 GET_VREG_F(fa1, a3) # a1 <- vCC 14 GET_VREG_F(fa0, a2) # a0 <- vBB 15 16 FETCH_ADVANCE_INST(2) # advance rPC, load rINST 17 $instr # f0 = result 18 GET_INST_OPCODE(t0) # extract opcode from rINST 19 SET_VREG_F_GOTO(fv0, rOBJ, t0) # vAA <- fv0 20 21%def fbinop2addr(instr=""): 22 /* 23 * Generic 32-bit "/2addr" binary operation. Provide an "instr" 24 * that specifies an instruction that performs "fv0 = fa0 op fa1". 25 * This could be an MIPS instruction or a function call. 26 * 27 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, 28 * div-float/2addr, rem-float/2addr 29 */ 30 /* binop/2addr vA, vB */ 31 GET_OPA4(rOBJ) # rOBJ <- A+ 32 GET_OPB(a3) # a3 <- B 33 GET_VREG_F(fa0, rOBJ) 34 GET_VREG_F(fa1, a3) 35 FETCH_ADVANCE_INST(1) # advance rPC, load rINST 36 37 $instr 38 GET_INST_OPCODE(t0) # extract opcode from rINST 39 SET_VREG_F_GOTO(fv0, rOBJ, t0) # vA <- result 40 41%def fbinopWide(instr=""): 42 /* 43 * Generic 64-bit floating-point binary operation. Provide an "instr" 44 * line that specifies an instruction that performs "fv0 = fa0 op fa1". 45 * This could be an MIPS instruction or a function call. 46 * 47 * for: add-double, sub-double, mul-double, div-double, 48 * rem-double 49 * 50 */ 51 /* binop vAA, vBB, vCC */ 52 FETCH(a0, 1) # a0 <- CCBB 53 GET_OPA(rOBJ) # rOBJ <- AA 54 and a2, a0, 255 # a2 <- BB 55 srl a3, a0, 8 # a3 <- CC 56 EAS2(a2, rFP, a2) # a2 <- &fp[BB] 57 EAS2(t1, rFP, a3) # a3 <- &fp[CC] 58 LOAD64_F(fa0, fa0f, a2) 59 LOAD64_F(fa1, fa1f, t1) 60 61 FETCH_ADVANCE_INST(2) # advance rPC, load rINST 62 $instr 63 GET_INST_OPCODE(t0) # extract opcode from rINST 64 SET_VREG64_F_GOTO(fv0, fv0f, rOBJ, t0) # vAA/vAA+1 <- fv0 65 66%def fbinopWide2addr(instr=""): 67 /* 68 * Generic 64-bit floating-point "/2addr" binary operation. 69 * Provide an "instr" line that specifies an instruction that 70 * performs "fv0 = fa0 op fa1". 71 * This could be an MIPS instruction or a function call. 72 * 73 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 74 * div-double/2addr, rem-double/2addr 75 */ 76 /* binop/2addr vA, vB */ 77 GET_OPA4(rOBJ) # rOBJ <- A+ 78 GET_OPB(a1) # a1 <- B 79 EAS2(a1, rFP, a1) # a1 <- &fp[B] 80 EAS2(t0, rFP, rOBJ) # t0 <- &fp[A] 81 LOAD64_F(fa0, fa0f, t0) 82 LOAD64_F(fa1, fa1f, a1) 83 84 FETCH_ADVANCE_INST(1) # advance rPC, load rINST 85 $instr 86 GET_INST_OPCODE(t0) # extract opcode from rINST 87 SET_VREG64_F_GOTO(fv0, fv0f, rOBJ, t0) # vA/vA+1 <- fv0 88 89%def funop(instr=""): 90 /* 91 * Generic 32-bit floating-point unary operation. Provide an "instr" 92 * line that specifies an instruction that performs "fv0 = op fa0". 93 * This could be a MIPS instruction or a function call. 94 * 95 * for: int-to-float 96 */ 97 /* unop vA, vB */ 98 GET_OPB(a3) # a3 <- B 99 GET_OPA4(rOBJ) # rOBJ <- A+ 100 GET_VREG_F(fa0, a3) 101 FETCH_ADVANCE_INST(1) # advance rPC, load rINST 102 $instr 103 GET_INST_OPCODE(t1) # extract opcode from rINST 104 SET_VREG_F_GOTO(fv0, rOBJ, t1) # vA <- fv0 105 106%def funopWider(instr=""): 107 /* 108 * Generic 32bit-to-64bit floating-point unary operation. Provide an "instr" 109 * line that specifies an instruction that performs "fv0 = op fa0". 110 * 111 * For: int-to-double, float-to-double 112 */ 113 /* unop vA, vB */ 114 GET_OPA4(rOBJ) # rOBJ <- A+ 115 GET_OPB(a3) # a3 <- B 116 GET_VREG_F(fa0, a3) 117 FETCH_ADVANCE_INST(1) # advance rPC, load rINST 118 $instr 119 GET_INST_OPCODE(t0) # extract opcode from rINST 120 SET_VREG64_F_GOTO(fv0, fv0f, rOBJ, t0) # vA/vA+1 <- fv0 121 122%def op_add_double(): 123% fbinopWide(instr="add.d fv0, fa0, fa1") 124 125%def op_add_double_2addr(): 126% fbinopWide2addr(instr="add.d fv0, fa0, fa1") 127 128%def op_add_float(): 129% fbinop(instr="add.s fv0, fa0, fa1") 130 131%def op_add_float_2addr(): 132% fbinop2addr(instr="add.s fv0, fa0, fa1") 133 134%def op_cmpg_double(): 135% op_cmpl_double(gt_bias="1") 136 137%def op_cmpg_float(): 138% op_cmpl_float(gt_bias="1") 139 140%def op_cmpl_double(gt_bias="0"): 141 /* 142 * Compare two floating-point values. Puts 0(==), 1(>), or -1(<) 143 * into the destination register based on the comparison results. 144 * 145 * For: cmpl-double, cmpg-double 146 */ 147 /* op vAA, vBB, vCC */ 148 149 FETCH(a0, 1) # a0 <- CCBB 150 and rOBJ, a0, 255 # rOBJ <- BB 151 srl t0, a0, 8 # t0 <- CC 152 EAS2(rOBJ, rFP, rOBJ) # rOBJ <- &fp[BB] 153 EAS2(t0, rFP, t0) # t0 <- &fp[CC] 154 LOAD64_F(ft0, ft0f, rOBJ) 155 LOAD64_F(ft1, ft1f, t0) 156#ifdef MIPS32REVGE6 157 cmp.eq.d ft2, ft0, ft1 158 li rTEMP, 0 159 bc1nez ft2, 1f # done if vBB == vCC (ordered) 160 .if $gt_bias 161 cmp.lt.d ft2, ft0, ft1 162 li rTEMP, -1 163 bc1nez ft2, 1f # done if vBB < vCC (ordered) 164 li rTEMP, 1 # vBB > vCC or unordered 165 .else 166 cmp.lt.d ft2, ft1, ft0 167 li rTEMP, 1 168 bc1nez ft2, 1f # done if vBB > vCC (ordered) 169 li rTEMP, -1 # vBB < vCC or unordered 170 .endif 171#else 172 c.eq.d fcc0, ft0, ft1 173 li rTEMP, 0 174 bc1t fcc0, 1f # done if vBB == vCC (ordered) 175 .if $gt_bias 176 c.olt.d fcc0, ft0, ft1 177 li rTEMP, -1 178 bc1t fcc0, 1f # done if vBB < vCC (ordered) 179 li rTEMP, 1 # vBB > vCC or unordered 180 .else 181 c.olt.d fcc0, ft1, ft0 182 li rTEMP, 1 183 bc1t fcc0, 1f # done if vBB > vCC (ordered) 184 li rTEMP, -1 # vBB < vCC or unordered 185 .endif 186#endif 1871: 188 GET_OPA(rOBJ) 189 FETCH_ADVANCE_INST(2) # advance rPC, load rINST 190 GET_INST_OPCODE(t0) # extract opcode from rINST 191 SET_VREG_GOTO(rTEMP, rOBJ, t0) # vAA <- rTEMP 192 193%def op_cmpl_float(gt_bias="0"): 194 /* 195 * Compare two floating-point values. Puts 0(==), 1(>), or -1(<) 196 * into the destination register based on the comparison results. 197 * 198 * for: cmpl-float, cmpg-float 199 */ 200 /* op vAA, vBB, vCC */ 201 202 FETCH(a0, 1) # a0 <- CCBB 203 and a2, a0, 255 # a2 <- BB 204 srl a3, a0, 8 205 GET_VREG_F(ft0, a2) 206 GET_VREG_F(ft1, a3) 207#ifdef MIPS32REVGE6 208 cmp.eq.s ft2, ft0, ft1 209 li rTEMP, 0 210 bc1nez ft2, 1f # done if vBB == vCC (ordered) 211 .if $gt_bias 212 cmp.lt.s ft2, ft0, ft1 213 li rTEMP, -1 214 bc1nez ft2, 1f # done if vBB < vCC (ordered) 215 li rTEMP, 1 # vBB > vCC or unordered 216 .else 217 cmp.lt.s ft2, ft1, ft0 218 li rTEMP, 1 219 bc1nez ft2, 1f # done if vBB > vCC (ordered) 220 li rTEMP, -1 # vBB < vCC or unordered 221 .endif 222#else 223 c.eq.s fcc0, ft0, ft1 224 li rTEMP, 0 225 bc1t fcc0, 1f # done if vBB == vCC (ordered) 226 .if $gt_bias 227 c.olt.s fcc0, ft0, ft1 228 li rTEMP, -1 229 bc1t fcc0, 1f # done if vBB < vCC (ordered) 230 li rTEMP, 1 # vBB > vCC or unordered 231 .else 232 c.olt.s fcc0, ft1, ft0 233 li rTEMP, 1 234 bc1t fcc0, 1f # done if vBB > vCC (ordered) 235 li rTEMP, -1 # vBB < vCC or unordered 236 .endif 237#endif 2381: 239 GET_OPA(rOBJ) 240 FETCH_ADVANCE_INST(2) # advance rPC, load rINST 241 GET_INST_OPCODE(t0) # extract opcode from rINST 242 SET_VREG_GOTO(rTEMP, rOBJ, t0) # vAA <- rTEMP 243 244%def op_div_double(): 245% fbinopWide(instr="div.d fv0, fa0, fa1") 246 247%def op_div_double_2addr(): 248% fbinopWide2addr(instr="div.d fv0, fa0, fa1") 249 250%def op_div_float(): 251% fbinop(instr="div.s fv0, fa0, fa1") 252 253%def op_div_float_2addr(): 254% fbinop2addr(instr="div.s fv0, fa0, fa1") 255 256%def op_double_to_float(): 257% unopNarrower(instr="cvt.s.d fv0, fa0") 258 259%def op_double_to_int(): 260 /* 261 * double-to-int 262 * 263 * We have to clip values to int min/max per the specification. The 264 * expected common case is a "reasonable" value that converts directly 265 * to modest integer. The EABI convert function isn't doing this for us 266 * for pre-R6. 267 */ 268 /* unop vA, vB */ 269 GET_OPB(a3) # a3 <- B 270 GET_OPA4(rOBJ) # rOBJ <- A+ 271 EAS2(a3, rFP, a3) # a3 <- &fp[B] 272 LOAD64_F(fa0, fa0f, a3) 273 FETCH_ADVANCE_INST(1) # advance rPC, load rINST 274#ifndef MIPS32REVGE6 275 li t0, INT_MIN_AS_DOUBLE_HIGH 276 mtc1 zero, fa1 277 MOVE_TO_FPU_HIGH(t0, fa1, fa1f) 278 c.ole.d fcc0, fa1, fa0 279#endif 280 GET_INST_OPCODE(t1) # extract opcode from rINST 281#ifndef MIPS32REVGE6 282 bc1t fcc0, 1f # if INT_MIN <= vB, proceed to truncation 283 c.eq.d fcc0, fa0, fa0 284 mtc1 zero, fa0 285 MOVE_TO_FPU_HIGH(zero, fa0, fa0f) 286 movt.d fa0, fa1, fcc0 # fa0 = ordered(vB) ? INT_MIN_AS_DOUBLE : 0 2871: 288#endif 289 trunc.w.d fa0, fa0 290 SET_VREG_F_GOTO(fa0, rOBJ, t1) # vA <- result 291 292%def op_double_to_long(): 293 /* 294 * double-to-long 295 * 296 * We have to clip values to long min/max per the specification. The 297 * expected common case is a "reasonable" value that converts directly 298 * to modest integer. The EABI convert function isn't doing this for us 299 * for pre-R6. 300 */ 301 /* unop vA, vB */ 302 GET_OPA4(rOBJ) # rOBJ <- A+ 303 GET_OPB(a3) # a3 <- B 304 EAS2(a3, rFP, a3) # a3 <- &fp[B] 305 LOAD64_F(fa0, fa0f, a3) 306 FETCH_ADVANCE_INST(1) # advance rPC, load rINST 307 308#ifdef MIPS32REVGE6 309 GET_INST_OPCODE(t1) # extract opcode from rINST 310 trunc.l.d fa0, fa0 311 SET_VREG64_F_GOTO(fa0, fa0f, rOBJ, t1) # vA <- result 312#else 313 c.eq.d fcc0, fa0, fa0 314 li rRESULT0, 0 315 li rRESULT1, 0 316 bc1f fcc0, .L${opcode}_get_opcode 317 318 li t0, LONG_MIN_AS_DOUBLE_HIGH 319 mtc1 zero, fa1 320 MOVE_TO_FPU_HIGH(t0, fa1, fa1f) 321 c.ole.d fcc0, fa0, fa1 322 li rRESULT1, LONG_MIN_HIGH 323 bc1t fcc0, .L${opcode}_get_opcode 324 325 neg.d fa1, fa1 326 c.ole.d fcc0, fa1, fa0 327 nor rRESULT0, rRESULT0, zero 328 nor rRESULT1, rRESULT1, zero 329 bc1t fcc0, .L${opcode}_get_opcode 330 331 JAL(__fixdfdi) 332 GET_INST_OPCODE(t1) # extract opcode from rINST 333 b .L${opcode}_set_vreg 334#endif 335%def op_double_to_long_helper_code(): 336 337#ifndef MIPS32REVGE6 338.Lop_double_to_long_get_opcode: 339 GET_INST_OPCODE(t1) # extract opcode from rINST 340.Lop_double_to_long_set_vreg: 341 SET_VREG64_GOTO(rRESULT0, rRESULT1, rOBJ, t1) # vA/vA+1 <- v0/v1 342#endif 343 344%def op_float_to_double(): 345% funopWider(instr="cvt.d.s fv0, fa0") 346 347%def op_float_to_int(): 348 /* 349 * float-to-int 350 * 351 * We have to clip values to int min/max per the specification. The 352 * expected common case is a "reasonable" value that converts directly 353 * to modest integer. The EABI convert function isn't doing this for us 354 * for pre-R6. 355 */ 356 /* unop vA, vB */ 357 GET_OPB(a3) # a3 <- B 358 GET_OPA4(rOBJ) # rOBJ <- A+ 359 GET_VREG_F(fa0, a3) 360 FETCH_ADVANCE_INST(1) # advance rPC, load rINST 361 362#ifndef MIPS32REVGE6 363 li t0, INT_MIN_AS_FLOAT 364 mtc1 t0, fa1 365 c.ole.s fcc0, fa1, fa0 366#endif 367 GET_INST_OPCODE(t1) # extract opcode from rINST 368#ifndef MIPS32REVGE6 369 bc1t fcc0, 1f # if INT_MIN <= vB, proceed to truncation 370 c.eq.s fcc0, fa0, fa0 371 mtc1 zero, fa0 372 movt.s fa0, fa1, fcc0 # fa0 = ordered(vB) ? INT_MIN_AS_FLOAT : 0 3731: 374#endif 375 trunc.w.s fa0, fa0 376 SET_VREG_F_GOTO(fa0, rOBJ, t1) # vA <- result 377 378%def op_float_to_long(): 379 /* 380 * float-to-long 381 * 382 * We have to clip values to long min/max per the specification. The 383 * expected common case is a "reasonable" value that converts directly 384 * to modest integer. The EABI convert function isn't doing this for us 385 * for pre-R6. 386 */ 387 /* unop vA, vB */ 388 GET_OPA4(rOBJ) # rOBJ <- A+ 389 GET_OPB(a3) # a3 <- B 390 GET_VREG_F(fa0, a3) 391 FETCH_ADVANCE_INST(1) # advance rPC, load rINST 392 393#ifdef MIPS32REVGE6 394 GET_INST_OPCODE(t1) # extract opcode from rINST 395 trunc.l.s fa0, fa0 396 SET_VREG64_F_GOTO(fa0, fa0f, rOBJ, t1) # vA <- result 397#else 398 c.eq.s fcc0, fa0, fa0 399 li rRESULT0, 0 400 li rRESULT1, 0 401 bc1f fcc0, .L${opcode}_get_opcode 402 403 li t0, LONG_MIN_AS_FLOAT 404 mtc1 t0, fa1 405 c.ole.s fcc0, fa0, fa1 406 li rRESULT1, LONG_MIN_HIGH 407 bc1t fcc0, .L${opcode}_get_opcode 408 409 neg.s fa1, fa1 410 c.ole.s fcc0, fa1, fa0 411 nor rRESULT0, rRESULT0, zero 412 nor rRESULT1, rRESULT1, zero 413 bc1t fcc0, .L${opcode}_get_opcode 414 415 JAL(__fixsfdi) 416 GET_INST_OPCODE(t1) # extract opcode from rINST 417 b .L${opcode}_set_vreg 418#endif 419%def op_float_to_long_helper_code(): 420 421#ifndef MIPS32REVGE6 422.Lop_float_to_long_get_opcode: 423 GET_INST_OPCODE(t1) # extract opcode from rINST 424.Lop_float_to_long_set_vreg: 425 SET_VREG64_GOTO(rRESULT0, rRESULT1, rOBJ, t1) # vA/vA+1 <- v0/v1 426#endif 427 428%def op_int_to_double(): 429% funopWider(instr="cvt.d.w fv0, fa0") 430 431%def op_int_to_float(): 432% funop(instr="cvt.s.w fv0, fa0") 433 434%def op_long_to_double(): 435 /* 436 * long-to-double 437 */ 438 /* unop vA, vB */ 439 GET_OPA4(rOBJ) # rOBJ <- A+ 440 GET_OPB(a3) # a3 <- B 441 EAS2(a3, rFP, a3) # a3 <- &fp[B] 442 443#ifdef MIPS32REVGE6 444 LOAD64_F(fv0, fv0f, a3) 445 FETCH_ADVANCE_INST(1) # advance rPC, load rINST 446 cvt.d.l fv0, fv0 447#else 448 LOAD64(rARG0, rARG1, a3) 449 FETCH_ADVANCE_INST(1) # advance rPC, load rINST 450 JAL(__floatdidf) # a0/a1 <- op, a2-a3 changed 451#endif 452 453 GET_INST_OPCODE(t0) # extract opcode from rINST 454 SET_VREG64_F_GOTO(fv0, fv0f, rOBJ, t0) # vA/vA+1 <- result 455 456%def op_long_to_float(): 457 /* 458 * long-to-float 459 */ 460 /* unop vA, vB */ 461 GET_OPB(a3) # a3 <- B 462 GET_OPA4(rOBJ) # rOBJ <- A+ 463 EAS2(a3, rFP, a3) # a3 <- &fp[B] 464 465#ifdef MIPS32REVGE6 466 LOAD64_F(fv0, fv0f, a3) 467 FETCH_ADVANCE_INST(1) # advance rPC, load rINST 468 cvt.s.l fv0, fv0 469#else 470 LOAD64(rARG0, rARG1, a3) 471 FETCH_ADVANCE_INST(1) # advance rPC, load rINST 472 JAL(__floatdisf) 473#endif 474 475 GET_INST_OPCODE(t0) # extract opcode from rINST 476 SET_VREG_F_GOTO(fv0, rOBJ, t0) # vA <- fv0 477 478%def op_mul_double(): 479% fbinopWide(instr="mul.d fv0, fa0, fa1") 480 481%def op_mul_double_2addr(): 482% fbinopWide2addr(instr="mul.d fv0, fa0, fa1") 483 484%def op_mul_float(): 485% fbinop(instr="mul.s fv0, fa0, fa1") 486 487%def op_mul_float_2addr(): 488% fbinop2addr(instr="mul.s fv0, fa0, fa1") 489 490%def op_neg_double(): 491% unopWide(instr="addu a1, a1, 0x80000000") 492 493%def op_neg_float(): 494% unop(instr="addu a0, a0, 0x80000000") 495 496%def op_rem_double(): 497% fbinopWide(instr="JAL(fmod)") 498 499%def op_rem_double_2addr(): 500% fbinopWide2addr(instr="JAL(fmod)") 501 502%def op_rem_float(): 503% fbinop(instr="JAL(fmodf)") 504 505%def op_rem_float_2addr(): 506% fbinop2addr(instr="JAL(fmodf)") 507 508%def op_sub_double(): 509% fbinopWide(instr="sub.d fv0, fa0, fa1") 510 511%def op_sub_double_2addr(): 512% fbinopWide2addr(instr="sub.d fv0, fa0, fa1") 513 514%def op_sub_float(): 515% fbinop(instr="sub.s fv0, fa0, fa1") 516 517%def op_sub_float_2addr(): 518% fbinop2addr(instr="sub.s fv0, fa0, fa1") 519