1%def bindiv(result="", second="", tmp="", wide="", suffix="", rem="0", ext="cdq"): 2/* 3 * 32-bit binary div/rem operation. Handles special case of op1=-1. 4 */ 5 /* div/rem vAA, vBB, vCC */ 6 movzbq 2(rPC), %rax # rax <- BB 7 movzbq 3(rPC), %rcx # rcx <- CC 8 .if $wide 9 GET_WIDE_VREG %rax, %rax # eax <- vBB 10 GET_WIDE_VREG $second, %rcx # ecx <- vCC 11 .else 12 GET_VREG %eax, %rax # eax <- vBB 13 GET_VREG $second, %rcx # ecx <- vCC 14 .endif 15 test${suffix} $second, $second 16 jz common_errDivideByZero 17 cmp${suffix} $$-1, $second 18 je 2f 19 cmp${suffix} $$2, $second 20 je 3f 21 $ext # rdx:rax <- sign-extended of rax 22 idiv${suffix} $second 231: 24 .if $wide 25 SET_WIDE_VREG $result, rINSTq # eax <- vBB 26 .else 27 SET_VREG $result, rINSTq # eax <- vBB 28 .endif 29 ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 302: 31 .if $rem 32 xor${suffix} $result, $result 33 .else 34 neg${suffix} $result 35 .endif 36 jmp 1b 373: 38 .if $rem 39 mov${suffix} $tmp, $result 40 .if $wide 41 shr${suffix} $$63, $result 42 .else 43 shr${suffix} $$31, $result 44 .endif 45 add${suffix} $tmp, $result 46 and${suffix} $$-2, $result 47 sub${suffix} $result, $tmp 48 mov${suffix} $tmp, $result 49 .else 50 mov${suffix} $result, $tmp 51 .if $wide 52 shr${suffix} $$63, $tmp 53 .else 54 shr${suffix} $$31, $tmp 55 .endif 56 add${suffix} $tmp, $result 57 sar${suffix} $result 58 .endif 59 jmp 1b 60 61%def bindiv2addr(result="", second="", tmp="", wide="", suffix="", rem="0", ext="cdq"): 62/* 63 * 32-bit binary div/rem operation. Handles special case of op1=-1. 64 */ 65 /* div/rem/2addr vA, vB */ 66 movl rINST, %ecx # rcx <- BA 67 sarl $$4, %ecx # rcx <- B 68 andb $$0xf, rINSTbl # rINST <- A 69 .if $wide 70 GET_WIDE_VREG %rax, rINSTq # eax <- vA 71 GET_WIDE_VREG $second, %rcx # ecx <- vB 72 .else 73 GET_VREG %eax, rINSTq # eax <- vA 74 GET_VREG $second, %rcx # ecx <- vB 75 .endif 76 test${suffix} $second, $second 77 jz common_errDivideByZero 78 cmp${suffix} $$-1, $second 79 je 2f 80 cmp${suffix} $$2, $second 81 je 3f 82 $ext # rdx:rax <- sign-extended of rax 83 idiv${suffix} $second 841: 85 .if $wide 86 SET_WIDE_VREG $result, rINSTq # vA <- result 87 .else 88 SET_VREG $result, rINSTq # vA <- result 89 .endif 90 ADVANCE_PC_FETCH_AND_GOTO_NEXT 1 912: 92 .if $rem 93 xor${suffix} $result, $result 94 .else 95 neg${suffix} $result 96 .endif 97 jmp 1b 983: 99 .if $rem 100 mov${suffix} $tmp, $result 101 .if $wide 102 shr${suffix} $$63, $result 103 .else 104 shr${suffix} $$31, $result 105 .endif 106 add${suffix} $tmp, $result 107 and${suffix} $$-2, $result 108 sub${suffix} $result, $tmp 109 mov${suffix} $tmp, $result 110 .else 111 mov${suffix} $result, $tmp 112 .if $wide 113 shr${suffix} $$63, $tmp 114 .else 115 shr${suffix} $$31, $tmp 116 .endif 117 add${suffix} $tmp, $result 118 sar${suffix} $result 119 .endif 120 jmp 1b 121 122%def bindivLit16(result="", rem="0"): 123/* 124 * 32-bit binary div/rem operation. Handles special case of op1=-1. 125 */ 126 /* div/rem/lit16 vA, vB, #+CCCC */ 127 /* Need A in rINST, ssssCCCC in ecx, vB in eax */ 128 movl rINST, %eax # rax <- 000000BA 129 sarl $$4, %eax # eax <- B 130 GET_VREG %eax, %rax # eax <- vB 131 movswl 2(rPC), %ecx # ecx <- ssssCCCC 132 andb $$0xf, rINSTbl # rINST <- A 133 testl %ecx, %ecx 134 jz common_errDivideByZero 135 cmpl $$-1, %ecx 136 je 2f 137 cdq # rax <- sign-extended of eax 138 idivl %ecx 1391: 140 SET_VREG $result, rINSTq # vA <- result 141 ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 1422: 143 .if $rem 144 xorl $result, $result 145 .else 146 negl $result 147 .endif 148 jmp 1b 149 150%def bindivLit8(result="", rem="0"): 151/* 152 * 32-bit div/rem "lit8" binary operation. Handles special case of 153 * op0=minint & op1=-1 154 */ 155 /* div/rem/lit8 vAA, vBB, #+CC */ 156 movzbq 2(rPC), %rax # eax <- BB 157 movsbl 3(rPC), %ecx # ecx <- ssssssCC 158 GET_VREG %eax, %rax # eax <- rBB 159 testl %ecx, %ecx 160 je common_errDivideByZero 161 cmpl $$-1, %ecx 162 je 2f 163 cdq # rax <- sign-extended of eax 164 idivl %ecx 1651: 166 SET_VREG $result, rINSTq # vA <- result 167 ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 1682: 169 .if $rem 170 xorl $result, $result 171 .else 172 negl $result 173 .endif 174 jmp 1b 175 176%def binop(result="%eax", instr=""): 177/* 178 * Generic 32-bit binary operation. Provide an "instr" line that 179 * specifies an instruction that performs "result = eax op (rFP,%ecx,4)". 180 * This could be an x86 instruction or a function call. (If the result 181 * comes back in a register other than eax, you can override "result".) 182 * 183 * For: add-int, sub-int, and-int, or-int, 184 * xor-int, shl-int, shr-int, ushr-int 185 */ 186 /* binop vAA, vBB, vCC */ 187 movzbq 2(rPC), %rax # rax <- BB 188 movzbq 3(rPC), %rcx # rcx <- CC 189 GET_VREG %eax, %rax # eax <- vBB 190 $instr VREG_ADDRESS(%rcx),%eax 191 SET_VREG $result, rINSTq 192 ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 193 194%def binop1(wide="0", instr=""): 195/* 196 * Generic 32-bit binary operation in which both operands loaded to 197 * registers (op0 in eax, op1 in ecx). 198 */ 199 /* binop vAA, vBB, vCC */ 200 movzbq 2(rPC), %rax # eax <- BB 201 movzbq 3(rPC), %rcx # ecx <- CC 202 GET_VREG %ecx, %rcx # eax <- vCC 203 .if $wide 204 GET_WIDE_VREG %rax, %rax # rax <- vBB 205 $instr # ex: addl %ecx,%eax 206 SET_WIDE_VREG %rax, rINSTq 207 .else 208 GET_VREG %eax, %rax # eax <- vBB 209 $instr # ex: addl %ecx,%eax 210 SET_VREG %eax, rINSTq 211 .endif 212 ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 213 214%def binop2addr(result="%eax", instr=""): 215/* 216 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 217 * that specifies an instruction that performs "result = r0 op r1". 218 * This could be an instruction or a function call. 219 * 220 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 221 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 222 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 223 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 224 */ 225 /* binop/2addr vA, vB */ 226 movl rINST, %ecx # rcx <- A+ 227 sarl $$4, rINST # rINST <- B 228 andb $$0xf, %cl # ecx <- A 229 GET_VREG %eax, rINSTq # eax <- vB 230 $instr %eax, VREG_ADDRESS(%rcx) 231 CLEAR_REF %rcx 232 ADVANCE_PC_FETCH_AND_GOTO_NEXT 1 233 234%def binopLit16(result="%eax", instr=""): 235/* 236 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 237 * that specifies an instruction that performs "result = eax op ecx". 238 * This could be an x86 instruction or a function call. (If the result 239 * comes back in a register other than eax, you can override "result".) 240 * 241 * For: add-int/lit16, rsub-int, 242 * and-int/lit16, or-int/lit16, xor-int/lit16 243 */ 244 /* binop/lit16 vA, vB, #+CCCC */ 245 movl rINST, %eax # rax <- 000000BA 246 sarl $$4, %eax # eax <- B 247 GET_VREG %eax, %rax # eax <- vB 248 andb $$0xf, rINSTbl # rINST <- A 249 movswl 2(rPC), %ecx # ecx <- ssssCCCC 250 $instr # for example: addl %ecx, %eax 251 SET_VREG $result, rINSTq 252 ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 253 254%def binopLit8(result="%eax", instr=""): 255/* 256 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 257 * that specifies an instruction that performs "result = eax op ecx". 258 * This could be an x86 instruction or a function call. (If the result 259 * comes back in a register other than r0, you can override "result".) 260 * 261 * For: add-int/lit8, rsub-int/lit8 262 * and-int/lit8, or-int/lit8, xor-int/lit8, 263 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 264 */ 265 /* binop/lit8 vAA, vBB, #+CC */ 266 movzbq 2(rPC), %rax # rax <- BB 267 movsbl 3(rPC), %ecx # rcx <- ssssssCC 268 GET_VREG %eax, %rax # eax <- rBB 269 $instr # ex: addl %ecx,%eax 270 SET_VREG $result, rINSTq 271 ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 272 273%def binopWide(instr=""): 274/* 275 * Generic 64-bit binary operation. 276 */ 277 /* binop vAA, vBB, vCC */ 278 movzbq 2(rPC), %rax # eax <- BB 279 movzbq 3(rPC), %rcx # ecx <- CC 280 GET_WIDE_VREG %rax, %rax # rax <- v[BB] 281 $instr VREG_ADDRESS(%rcx),%rax 282 SET_WIDE_VREG %rax, rINSTq # v[AA] <- rax 283 ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 284 285%def binopWide2addr(instr=""): 286/* 287 * Generic 64-bit binary operation. 288 */ 289 /* binop/2addr vA, vB */ 290 movl rINST, %ecx # rcx <- A+ 291 sarl $$4, rINST # rINST <- B 292 andb $$0xf, %cl # ecx <- A 293 GET_WIDE_VREG %rax, rINSTq # rax <- vB 294 $instr %rax,VREG_ADDRESS(%rcx) 295 CLEAR_WIDE_REF %rcx 296 ADVANCE_PC_FETCH_AND_GOTO_NEXT 1 297 298%def cvtfp_int(fp_suffix="", i_suffix="", max_const="", result_reg="", wide=""): 299/* On fp to int conversions, Java requires that 300 * if the result > maxint, it should be clamped to maxint. If it is less 301 * than minint, it should be clamped to minint. If it is a nan, the result 302 * should be zero. Further, the rounding mode is to truncate. 303 */ 304 /* float/double to int/long vA, vB */ 305 movl rINST, %ecx # rcx <- A+ 306 sarl $$4, rINST # rINST <- B 307 andb $$0xf, %cl # ecx <- A 308 GET_VREG_XMM${fp_suffix} %xmm0, rINSTq 309 mov${i_suffix} ${max_const}, ${result_reg} 310 cvtsi2s${fp_suffix}${i_suffix} ${result_reg}, %xmm1 311 comis${fp_suffix} %xmm1, %xmm0 312 jae 1f 313 jp 2f 314 cvtts${fp_suffix}2si${i_suffix} %xmm0, ${result_reg} 315 jmp 1f 3162: 317 xor${i_suffix} ${result_reg}, ${result_reg} 3181: 319 .if $wide 320 SET_WIDE_VREG ${result_reg}, %rcx 321 .else 322 SET_VREG ${result_reg}, %rcx 323 .endif 324 ADVANCE_PC_FETCH_AND_GOTO_NEXT 1 325 326%def shop2addr(wide="0", instr=""): 327/* 328 * Generic 32-bit "shift/2addr" operation. 329 */ 330 /* shift/2addr vA, vB */ 331 movl rINST, %ecx # ecx <- BA 332 sarl $$4, %ecx # ecx <- B 333 GET_VREG %ecx, %rcx # ecx <- vBB 334 andb $$0xf, rINSTbl # rINST <- A 335 .if $wide 336 GET_WIDE_VREG %rax, rINSTq # rax <- vAA 337 $instr # ex: sarl %cl, %eax 338 SET_WIDE_VREG %rax, rINSTq 339 .else 340 GET_VREG %eax, rINSTq # eax <- vAA 341 $instr # ex: sarl %cl, %eax 342 SET_VREG %eax, rINSTq 343 .endif 344 ADVANCE_PC_FETCH_AND_GOTO_NEXT 1 345 346%def unop(preinstr="", instr="", wide="0"): 347/* 348 * Generic 32/64-bit unary operation. Provide an "instr" line that 349 * specifies an instruction that performs "result = op eax". 350 */ 351 /* unop vA, vB */ 352 movl rINST, %ecx # rcx <- A+ 353 sarl $$4,rINST # rINST <- B 354 .if ${wide} 355 GET_WIDE_VREG %rax, rINSTq # rax <- vB 356 .else 357 GET_VREG %eax, rINSTq # eax <- vB 358 .endif 359 andb $$0xf,%cl # ecx <- A 360$preinstr 361$instr 362 .if ${wide} 363 SET_WIDE_VREG %rax, %rcx 364 .else 365 SET_VREG %eax, %rcx 366 .endif 367 ADVANCE_PC_FETCH_AND_GOTO_NEXT 1 368 369%def op_add_int(): 370% binop(instr="addl") 371 372%def op_add_int_2addr(): 373% binop2addr(instr="addl") 374 375%def op_add_int_lit16(): 376% binopLit16(instr="addl %ecx, %eax") 377 378%def op_add_int_lit8(): 379% binopLit8(instr="addl %ecx, %eax") 380 381%def op_add_long(): 382% binopWide(instr="addq") 383 384%def op_add_long_2addr(): 385% binopWide2addr(instr="addq") 386 387%def op_and_int(): 388% binop(instr="andl") 389 390%def op_and_int_2addr(): 391% binop2addr(instr="andl") 392 393%def op_and_int_lit16(): 394% binopLit16(instr="andl %ecx, %eax") 395 396%def op_and_int_lit8(): 397% binopLit8(instr="andl %ecx, %eax") 398 399%def op_and_long(): 400% binopWide(instr="andq") 401 402%def op_and_long_2addr(): 403% binopWide2addr(instr="andq") 404 405%def op_cmp_long(): 406/* 407 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 408 * register based on the results of the comparison. 409 */ 410 /* cmp-long vAA, vBB, vCC */ 411 movzbq 2(rPC), %rdx # edx <- BB 412 movzbq 3(rPC), %rcx # ecx <- CC 413 GET_WIDE_VREG %rdx, %rdx # rdx <- v[BB] 414 xorl %eax, %eax 415 xorl %edi, %edi 416 addb $$1, %al 417 movl $$-1, %esi 418 cmpq VREG_ADDRESS(%rcx), %rdx 419 cmovl %esi, %edi 420 cmovg %eax, %edi 421 SET_VREG %edi, rINSTq 422 ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 423 424%def op_div_int(): 425% bindiv(result="%eax", second="%ecx", tmp="%edx", wide="0", suffix="l") 426 427%def op_div_int_2addr(): 428% bindiv2addr(result="%eax", second="%ecx", tmp="%edx", wide="0", suffix="l") 429 430%def op_div_int_lit16(): 431% bindivLit16(result="%eax") 432 433%def op_div_int_lit8(): 434% bindivLit8(result="%eax") 435 436%def op_div_long(): 437% bindiv(result="%rax", second="%rcx", tmp="%rdx", wide="1", suffix="q", ext="cqo") 438 439%def op_div_long_2addr(): 440% bindiv2addr(result="%rax", second="%rcx", tmp="%rdx", wide="1", suffix="q", ext="cqo") 441 442%def op_int_to_byte(): 443% unop(instr="movsbl %al, %eax") 444 445%def op_int_to_char(): 446% unop(instr="movzwl %ax,%eax") 447 448%def op_int_to_long(): 449 /* int to long vA, vB */ 450 movzbq rINSTbl, %rax # rax <- +A 451 sarl $$4, %eax # eax <- B 452 andb $$0xf, rINSTbl # rINST <- A 453 movslq VREG_ADDRESS(%rax), %rax 454 SET_WIDE_VREG %rax, rINSTq # v[A] <- %rax 455 ADVANCE_PC_FETCH_AND_GOTO_NEXT 1 456 457 458%def op_int_to_short(): 459% unop(instr="movswl %ax, %eax") 460 461%def op_long_to_int(): 462/* we ignore the high word, making this equivalent to a 32-bit reg move */ 463% op_move() 464 465%def op_mul_int(): 466% binop(instr="imull") 467 468%def op_mul_int_2addr(): 469 /* mul vA, vB */ 470 movl rINST, %ecx # rcx <- A+ 471 sarl $$4, rINST # rINST <- B 472 andb $$0xf, %cl # ecx <- A 473 GET_VREG %eax, %rcx # eax <- vA 474 imull (rFP,rINSTq,4), %eax 475 SET_VREG %eax, %rcx 476 ADVANCE_PC_FETCH_AND_GOTO_NEXT 1 477 478%def op_mul_int_lit16(): 479% binopLit16(instr="imull %ecx, %eax") 480 481%def op_mul_int_lit8(): 482% binopLit8(instr="imull %ecx, %eax") 483 484%def op_mul_long(): 485% binopWide(instr="imulq") 486 487%def op_mul_long_2addr(): 488 /* mul vA, vB */ 489 movl rINST, %ecx # rcx <- A+ 490 sarl $$4, rINST # rINST <- B 491 andb $$0xf, %cl # ecx <- A 492 GET_WIDE_VREG %rax, %rcx # rax <- vA 493 imulq (rFP,rINSTq,4), %rax 494 SET_WIDE_VREG %rax, %rcx 495 ADVANCE_PC_FETCH_AND_GOTO_NEXT 1 496 497%def op_neg_int(): 498% unop(instr=" negl %eax") 499 500%def op_neg_long(): 501% unop(instr=" negq %rax", wide="1") 502 503%def op_not_int(): 504% unop(instr=" notl %eax") 505 506%def op_not_long(): 507% unop(instr=" notq %rax", wide="1") 508 509%def op_or_int(): 510% binop(instr="orl") 511 512%def op_or_int_2addr(): 513% binop2addr(instr="orl") 514 515%def op_or_int_lit16(): 516% binopLit16(instr="orl %ecx, %eax") 517 518%def op_or_int_lit8(): 519% binopLit8(instr="orl %ecx, %eax") 520 521%def op_or_long(): 522% binopWide(instr="orq") 523 524%def op_or_long_2addr(): 525% binopWide2addr(instr="orq") 526 527%def op_rem_int(): 528% bindiv(result="%edx", second="%ecx", tmp="%eax", wide="0", suffix="l", rem="1") 529 530%def op_rem_int_2addr(): 531% bindiv2addr(result="%edx", second="%ecx", tmp="%eax", wide="0", suffix="l", rem="1") 532 533%def op_rem_int_lit16(): 534% bindivLit16(result="%edx", rem="1") 535 536%def op_rem_int_lit8(): 537% bindivLit8(result="%edx", rem="1") 538 539%def op_rem_long(): 540% bindiv(result="%rdx", second="%rcx", tmp="%rax", wide="1", suffix="q", ext="cqo", rem="1") 541 542%def op_rem_long_2addr(): 543% bindiv2addr(result="%rdx", second="%rcx", tmp="%rax", wide="1", suffix="q", rem="1", ext="cqo") 544 545%def op_rsub_int(): 546/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ 547% binopLit16(instr="subl %eax, %ecx", result="%ecx") 548 549%def op_rsub_int_lit8(): 550% binopLit8(instr="subl %eax, %ecx", result="%ecx") 551 552%def op_shl_int(): 553% binop1(instr="sall %cl, %eax") 554 555%def op_shl_int_2addr(): 556% shop2addr(instr="sall %cl, %eax") 557 558%def op_shl_int_lit8(): 559% binopLit8(instr="sall %cl, %eax") 560 561%def op_shl_long(): 562% binop1(instr="salq %cl, %rax", wide="1") 563 564%def op_shl_long_2addr(): 565% shop2addr(instr="salq %cl, %rax", wide="1") 566 567%def op_shr_int(): 568% binop1(instr="sarl %cl, %eax") 569 570%def op_shr_int_2addr(): 571% shop2addr(instr="sarl %cl, %eax") 572 573%def op_shr_int_lit8(): 574% binopLit8(instr="sarl %cl, %eax") 575 576%def op_shr_long(): 577% binop1(instr="sarq %cl, %rax", wide="1") 578 579%def op_shr_long_2addr(): 580% shop2addr(instr="sarq %cl, %rax", wide="1") 581 582%def op_sub_int(): 583% binop(instr="subl") 584 585%def op_sub_int_2addr(): 586% binop2addr(instr="subl") 587 588%def op_sub_long(): 589% binopWide(instr="subq") 590 591%def op_sub_long_2addr(): 592% binopWide2addr(instr="subq") 593 594%def op_ushr_int(): 595% binop1(instr="shrl %cl, %eax") 596 597%def op_ushr_int_2addr(): 598% shop2addr(instr="shrl %cl, %eax") 599 600%def op_ushr_int_lit8(): 601% binopLit8(instr="shrl %cl, %eax") 602 603%def op_ushr_long(): 604% binop1(instr="shrq %cl, %rax", wide="1") 605 606%def op_ushr_long_2addr(): 607% shop2addr(instr="shrq %cl, %rax", wide="1") 608 609%def op_xor_int(): 610% binop(instr="xorl") 611 612%def op_xor_int_2addr(): 613% binop2addr(instr="xorl") 614 615%def op_xor_int_lit16(): 616% binopLit16(instr="xorl %ecx, %eax") 617 618%def op_xor_int_lit8(): 619% binopLit8(instr="xorl %ecx, %eax") 620 621%def op_xor_long(): 622% binopWide(instr="xorq") 623 624%def op_xor_long_2addr(): 625% binopWide2addr(instr="xorq") 626