hotspot/src/cpu/x86/vm/assembler_x86.cpp
int MacroAssembler::corrected_idivq(Register reg) {
{- -------------------------------------------
(1) (JVM の除算/剰余算は, 境界値での挙動が x86 とは異なるため, チェックが必要)
---------------------------------------- -}
// Full implementation of Java ldiv and lrem; checks for special
// case as described in JVM spec., p.243 & p.271. The function
// returns the (pc) offset of the idivl instruction - may be needed
// for implicit exceptions.
//
// normal case special case
//
// input : rax: dividend min_long
// reg: divisor (may not be eax/edx) -1
//
// output: rax: quotient (= rax idiv reg) min_long
// rdx: remainder (= rax irem reg) 0
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(reg != rax && reg != rdx, "reg cannot be rax or rdx register");
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
static const int64_t min_long = 0x8000000000000000;
Label normal_case, special_case;
{- -------------------------------------------
(1) コード生成:
「special case かどうかのチェックを行う.
結果に応じて, 以下の処理は2通りに分岐.」
---------------------------------------- -}
// check for special case
cmp64(rax, ExternalAddress((address) &min_long));
jcc(Assembler::notEqual, normal_case);
{- -------------------------------------------
(1) コード生成:
「special case 用の処理を行う.」
---------------------------------------- -}
xorl(rdx, rdx); // prepare rdx for possible special case (where
// remainder = 0)
cmpq(reg, -1);
jcc(Assembler::equal, special_case);
{- -------------------------------------------
(1) コード生成:
「normal case 用の処理を行う.」
---------------------------------------- -}
// handle normal case
bind(normal_case);
cdqq();
int idivq_offset = offset();
idivq(reg);
{- -------------------------------------------
(1) コード生成:
「(special case/normal case どちらもここで合流)」
---------------------------------------- -}
// normal and special case exit
bind(special_case);
{- -------------------------------------------
(1) リターン
---------------------------------------- -}
return idivq_offset;
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.