@@ -1514,47 +1514,128 @@ term bif_erlang_bxor_2(Context *ctx, uint32_t fail_label, int live, term arg1, t
1514
1514
}
1515
1515
}
1516
1516
1517
- typedef int64_t (* bitshift_op )(int64_t a , avm_int_t b );
1518
-
1519
- static inline term bitshift_helper (Context * ctx , uint32_t fail_label , int live , term arg1 , term arg2 , bitshift_op op )
1517
+ static inline int32_t int32_bsr (int32_t n , unsigned int rshift )
1520
1518
{
1521
- UNUSED (live );
1519
+ return (int32_t ) ((n < 0 ) ? ~(~((uint32_t ) n ) >> rshift ) : (((uint32_t ) n ) >> rshift ));
1520
+ }
1522
1521
1523
- if (UNLIKELY (!term_is_any_integer (arg1 ) || !term_is_integer (arg2 ))) {
1524
- RAISE_ERROR_BIF (fail_label , BADARITH_ATOM );
1522
+ static inline bool int32_bsl_overflow (int32_t n , unsigned int lshift , int32_t * out )
1523
+ {
1524
+ //
1525
+ if ((n != 0 ) && (lshift > 64 )) {
1526
+ return true;
1525
1527
}
1528
+ //
1526
1529
1527
- int64_t a = term_maybe_unbox_int64 (arg1 );
1528
- avm_int_t b = term_to_int (arg2 );
1529
- int64_t result = op (a , b );
1530
-
1531
- #if BOXED_TERMS_REQUIRED_FOR_INT64 > 1
1532
- return make_maybe_boxed_int64 (ctx , fail_label , live , result );
1533
- #else
1534
- return make_maybe_boxed_int (ctx , fail_label , live , result );
1535
- #endif
1530
+ int32_t res = (int32_t ) (((uint32_t ) n ) << lshift );
1531
+ * out = res ;
1532
+ int32_t check = int32_bsr (res , lshift );
1533
+ return check != n ;
1536
1534
}
1537
1535
1538
- static inline int64_t bsl (int64_t a , avm_int_t b )
1536
+ static inline int64_t int64_bsr (int64_t n , unsigned int rshift )
1539
1537
{
1540
- // TODO check for overflow
1541
- return a << b ;
1538
+ return (int64_t ) ((n < 0 ) ? ~(~((uint64_t ) n ) >> rshift ) : (((uint64_t ) n ) >> rshift ));
1542
1539
}
1543
1540
1544
- term bif_erlang_bsl_2 ( Context * ctx , uint32_t fail_label , int live , term arg1 , term arg2 )
1541
+ static inline bool int64_bsl_overflow ( int64_t n , unsigned int lshift , int64_t * out )
1545
1542
{
1546
- return bitshift_helper (ctx , fail_label , live , arg1 , arg2 , bsl );
1543
+ //
1544
+ if ((n != 0 ) && (lshift > 64 )) {
1545
+ return true;
1546
+ }
1547
+ //
1548
+
1549
+ int64_t res = (int64_t ) (((uint64_t ) n ) << lshift );
1550
+ * out = res ;
1551
+ int64_t check = int64_bsr (res , lshift );
1552
+ return check != n ;
1547
1553
}
1548
1554
1549
- static inline int64_t bsr ( int64_t a , avm_int_t b )
1555
+ term bif_erlang_bsl_2 ( Context * ctx , uint32_t fail_label , int live , term arg1 , term arg2 )
1550
1556
{
1551
- // TODO check for underflow
1552
- return a >> b ;
1557
+ if (LIKELY (term_is_any_integer (arg1 ) && term_is_any_integer (arg2 ))) {
1558
+ size_t arg1_size = term_is_integer (arg1 ) ? 0 : term_boxed_size (arg1 );
1559
+ avm_int_t b = term_to_int (arg2 );
1560
+ if (arg1_size <= BOXED_TERMS_REQUIRED_FOR_INT64 ) {
1561
+ int64_t a = term_maybe_unbox_int64 (arg1 );
1562
+ //if (uint64_leading_zeros(a) >= b) {
1563
+ int64_t result ;
1564
+ if (!int64_bsl_overflow (a , b , & result )) {
1565
+ #if BOXED_TERMS_REQUIRED_FOR_INT64 > 1
1566
+ return make_maybe_boxed_int64 (ctx , fail_label , live , result );
1567
+ #else
1568
+ return make_maybe_boxed_int (ctx , fail_label , live , result );
1569
+ #endif
1570
+ } else {
1571
+ fprintf (stderr , "was with b: %i, with: " , (int ) b );
1572
+ term_display (stderr , arg1 , ctx );
1573
+ fprintf (stderr , "\n" );
1574
+ }
1575
+ }
1576
+
1577
+ intn_digit_t tmp_buf1 [INTN_INT64_LEN ];
1578
+ intn_digit_t tmp_buf2 [INTN_INT64_LEN ];
1579
+ intn_digit_t * m ;
1580
+ size_t m_len ;
1581
+ intn_integer_sign_t m_sign ;
1582
+ intn_digit_t * n ;
1583
+ size_t n_len ;
1584
+ intn_integer_sign_t n_sign ;
1585
+ args_to_bigint (arg1 , arg2 , tmp_buf1 , tmp_buf2 , & m , & m_len , & m_sign , & n , & n_len , & n_sign );
1586
+
1587
+ intn_digit_t bigres [INTN_MAX_RES_LEN ];
1588
+ size_t bigres_len ;
1589
+ bigres_len = intn_bsl (m , m_len , b , bigres );
1590
+ fprintf (stderr , "bigres: %i\n" , (int ) bigres_len );
1591
+
1592
+ return make_bigint (ctx , fail_label , live , bigres , bigres_len , m_sign );
1593
+ } else {
1594
+ RAISE_ERROR_BIF (fail_label , BADARITH_ATOM );
1595
+ }
1553
1596
}
1554
1597
1555
1598
term bif_erlang_bsr_2 (Context * ctx , uint32_t fail_label , int live , term arg1 , term arg2 )
1556
1599
{
1557
- return bitshift_helper (ctx , fail_label , live , arg1 , arg2 , bsr );
1600
+ if (LIKELY (term_is_any_integer (arg1 ) && term_is_any_integer (arg2 ))) {
1601
+ size_t arg1_size = term_is_integer (arg1 ) ? 0 : term_boxed_size (arg1 );
1602
+
1603
+ avm_int_t b = term_to_int (arg2 );
1604
+
1605
+ fprintf (stderr , "going to do b: %i, with: " , (int ) b );
1606
+ term_display (stderr , arg1 , ctx );
1607
+ fprintf (stderr , "\n" );
1608
+
1609
+ if (arg1_size <= BOXED_TERMS_REQUIRED_FOR_INT64 ) {
1610
+ uint64_t a = (uint64_t ) term_maybe_unbox_int64 (arg1 );
1611
+ int64_t result = (int64_t ) (a >> b ); //FIX THIS
1612
+
1613
+ #if BOXED_TERMS_REQUIRED_FOR_INT64 > 1
1614
+ return make_maybe_boxed_int64 (ctx , fail_label , live , result );
1615
+ #else
1616
+ return make_maybe_boxed_int (ctx , fail_label , live , result );
1617
+ #endif
1618
+ }
1619
+
1620
+ intn_digit_t tmp_buf1 [INTN_INT64_LEN ];
1621
+ intn_digit_t tmp_buf2 [INTN_INT64_LEN ];
1622
+ intn_digit_t * m ;
1623
+ size_t m_len ;
1624
+ intn_integer_sign_t m_sign ;
1625
+ intn_digit_t * n ;
1626
+ size_t n_len ;
1627
+ intn_integer_sign_t n_sign ;
1628
+ args_to_bigint (arg1 , arg2 , tmp_buf1 , tmp_buf2 , & m , & m_len , & m_sign , & n , & n_len , & n_sign );
1629
+
1630
+ intn_digit_t bigres [INTN_MAX_RES_LEN ];
1631
+ size_t bigres_len ;
1632
+ //intn_bsl(m, m_len, b, bigres, &bigres_len); //FIXME TODO CHANGE ME
1633
+ abort ();
1634
+
1635
+ return make_bigint (ctx , fail_label , live , bigres , bigres_len , m_sign );
1636
+ } else {
1637
+ RAISE_ERROR_BIF (fail_label , BADARITH_ATOM );
1638
+ }
1558
1639
}
1559
1640
1560
1641
term bif_erlang_bnot_1 (Context * ctx , uint32_t fail_label , int live , term arg1 )
0 commit comments