aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam/arith_instrs.tab
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/beam/arith_instrs.tab')
-rw-r--r--erts/emulator/beam/arith_instrs.tab80
1 files changed, 43 insertions, 37 deletions
diff --git a/erts/emulator/beam/arith_instrs.tab b/erts/emulator/beam/arith_instrs.tab
index 91fe21e161..67cd7c6a2a 100644
--- a/erts/emulator/beam/arith_instrs.tab
+++ b/erts/emulator/beam/arith_instrs.tab
@@ -226,16 +226,12 @@ i_bsr := shift.setup_bsr.execute;
shift.head() {
Eterm Op1, Op2;
Sint shift_left_count;
- Sint ires;
- Eterm* bigp;
- Eterm tmp_big[2];
- Uint BIF;
}
shift.setup_bsr(Src1, Src2) {
Op1 = $Src1;
Op2 = $Src2;
- BIF = BIF_bsr_2;
+ shift_left_count = 0;
if (is_small(Op2)) {
shift_left_count = -signed_val(Op2);
} else if (is_big(Op2)) {
@@ -245,15 +241,13 @@ shift.setup_bsr(Src1, Src2) {
*/
shift_left_count = make_small(bignum_header_is_neg(*big_val(Op2)) ?
MAX_SMALL : MIN_SMALL);
- } else {
- shift_left_count = 0;
}
}
shift.setup_bsl(Src1, Src2) {
Op1 = $Src1;
Op2 = $Src2;
- BIF = BIF_bsl_2;
+ shift_left_count = 0;
if (is_small(Op2)) {
shift_left_count = signed_val(Op2);
} else if (is_big(Op2)) {
@@ -271,66 +265,65 @@ shift.setup_bsl(Src1, Src2) {
*/
shift_left_count = MAX_SMALL;
}
- } else {
- shift_left_count = 0;
}
}
shift.execute(Fail, Live, Dst) {
+ Uint big_words_needed;
+
if (is_small(Op1)) {
- ires = signed_val(Op1);
- if (shift_left_count == 0 || ires == 0) {
+ Sint int_res = signed_val(Op1);
+ if (shift_left_count == 0 || int_res == 0) {
if (is_not_integer(Op2)) {
- c_p->freason = BADARITH;
- $BIF_ERROR_ARITY_2($Fail, BIF, Op1, Op2);
+ goto shift_error;
}
- if (ires == 0) {
+ if (int_res == 0) {
$Dst = Op1;
$NEXT0();
}
} else if (shift_left_count < 0) { /* Right shift */
+ Eterm bsr_res;
shift_left_count = -shift_left_count;
if (shift_left_count >= SMALL_BITS-1) {
- $Dst = (ires < 0) ? SMALL_MINUS_ONE : SMALL_ZERO;
+ bsr_res = (int_res < 0) ? SMALL_MINUS_ONE : SMALL_ZERO;
} else {
- $Dst = make_small(ires >> shift_left_count);
+ bsr_res = make_small(int_res >> shift_left_count);
}
+ $Dst = bsr_res;
$NEXT0();
} else if (shift_left_count < SMALL_BITS-1) { /* Left shift */
- if ((ires > 0 &&
- ((~(Uint)0 << ((SMALL_BITS-1)-shift_left_count)) &
- ires) == 0) ||
- ((~(Uint)0 << ((SMALL_BITS-1)-shift_left_count)) &
- ~ires) == 0) {
- $Dst = make_small(ires << shift_left_count);
+ if ((int_res > 0 &&
+ ((~(Uint)0 << ((SMALL_BITS-1)-shift_left_count)) & int_res) == 0) ||
+ ((~(Uint)0 << ((SMALL_BITS-1)-shift_left_count)) & ~int_res) == 0) {
+ $Dst = make_small(int_res << shift_left_count);
$NEXT0();
}
}
- ires = 1; /* big_size(small_to_big(Op1)) */
+ big_words_needed = 1; /* big_size(small_to_big(Op1)) */
goto big_shift;
} else if (is_big(Op1)) {
if (shift_left_count == 0) {
if (is_not_integer(Op2)) {
- c_p->freason = BADARITH;
- $BIF_ERROR_ARITY_2($Fail, BIF, Op1, Op2);
+ goto shift_error;
}
$Dst = Op1;
$NEXT0();
}
- ires = big_size(Op1);
+ big_words_needed = big_size(Op1);
big_shift:
if (shift_left_count > 0) { /* Left shift. */
- ires += (shift_left_count / D_EXP);
+ big_words_needed += (shift_left_count / D_EXP);
} else { /* Right shift. */
- if (ires <= (-shift_left_count / D_EXP)) {
- ires = 3; /* ??? */
+ if (big_words_needed <= (-shift_left_count / D_EXP)) {
+ big_words_needed = 3; /* ??? */
} else {
- ires -= (-shift_left_count / D_EXP);
+ big_words_needed -= (-shift_left_count / D_EXP);
}
}
{
- ires = BIG_NEED_SIZE(ires+1);
+ Eterm tmp_big[2];
+ Sint big_need_size = BIG_NEED_SIZE(big_words_needed+1);
/*
* Slightly conservative check the size to avoid
@@ -338,15 +331,14 @@ shift.execute(Fail, Live, Dst) {
* clearly would overflow the arity in the header
* word.
*/
- if (ires-8 > BIG_ARITY_MAX) {
+ if (big_need_size-8 > BIG_ARITY_MAX) {
$SYSTEM_LIMIT($Fail);
}
- $GC_TEST_PRESERVE(ires+1, $Live, Op1);
+ $GC_TEST_PRESERVE(big_need_size+1, $Live, Op1);
if (is_small(Op1)) {
Op1 = small_to_big(signed_val(Op1), tmp_big);
}
- bigp = HTOP;
- Op1 = big_lshift(Op1, shift_left_count, bigp);
+ Op1 = big_lshift(Op1, shift_left_count, HTOP);
if (is_big(Op1)) {
HTOP += bignum_header_arity(*HTOP) + 1;
}
@@ -369,8 +361,22 @@ shift.execute(Fail, Live, Dst) {
/*
* One or more non-integer arguments.
*/
+ shift_error:
c_p->freason = BADARITH;
- $BIF_ERROR_ARITY_2($Fail, BIF, Op1, Op2);
+ if ($Fail) {
+ $FAIL($Fail);
+ } else {
+ reg[0] = Op1;
+ reg[1] = Op2;
+ SWAPOUT;
+ if (I[0] == (BeamInstr) OpCode(i_bsl_ssjtd)) {
+ I = handle_error(c_p, I, reg, &bif_export[BIF_bsl_2]->info.mfa);
+ } else {
+ ASSERT(I[0] == (BeamInstr) OpCode(i_bsr_ssjtd));
+ I = handle_error(c_p, I, reg, &bif_export[BIF_bsr_2]->info.mfa);
+ }
+ goto post_error_handling;
+ }
}
i_int_bnot(Fail, Src, Live, Dst) {