blob: d5ad327f655dd2675be568b0c24acb68809448e4 [file] [log] [blame]
/*
* Copyright (C) 1989-2013 Free Software Foundation, Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include "libgcc2.h"
DWtype
__ashldi3(DWtype u, shift_count_type b)
{
if (b == 0)
return u;
const DWunion uu = {.ll = u};
const shift_count_type bm = W_TYPE_SIZE - b;
DWunion w;
if (bm <= 0) {
w.s.low = 0;
w.s.high = (UWtype)uu.s.low << -bm;
} else {
const UWtype carries = (UWtype) uu.s.low >> bm;
w.s.low = (UWtype)uu.s.low << b;
w.s.high = ((UWtype)uu.s.high << b) | carries;
}
return w.ll;
}
DWtype
__ashrdi3(DWtype u, shift_count_type b)
{
if (b == 0)
return u;
const DWunion uu = {.ll = u};
const shift_count_type bm = W_TYPE_SIZE - b;
DWunion w;
if (bm <= 0) {
/* w.s.high = 1..1 or 0..0 */
w.s.high = uu.s.high >> (W_TYPE_SIZE - 1);
w.s.low = uu.s.high >> -bm;
} else {
const UWtype carries = (UWtype) uu.s.high << bm;
w.s.high = uu.s.high >> b;
w.s.low = ((UWtype)uu.s.low >> b) | carries;
}
return w.ll;
}
DWtype
__lshrdi3(DWtype u, shift_count_type b)
{
if (b == 0)
return u;
const DWunion uu = {.ll = u};
const shift_count_type bm = W_TYPE_SIZE - b;
DWunion w;
if (bm <= 0) {
w.s.high = 0;
w.s.low = (UWtype)uu.s.high >> -bm;
} else {
const UWtype carries = (UWtype)uu.s.high << bm;
w.s.high = (UWtype)uu.s.high >> b;
w.s.low = ((UWtype)uu.s.low >> b) | carries;
}
return w.ll;
}
unsigned long
udivmodsi4(unsigned long num, unsigned long den, int modwanted)
{
unsigned long bit = 1;
unsigned long res = 0;
while (den < num && bit && !(den & (1L<<31))) {
den <<= 1;
bit <<= 1;
}
while (bit) {
if (num >= den) {
num -= den;
res |= bit;
}
bit >>= 1;
den >>= 1;
}
if (modwanted)
return num;
return res;
}
long
__divsi3(long a, long b)
{
int neg = 0;
long res;
if (a < 0) {
a = -a;
neg = !neg;
}
if (b < 0) {
b = -b;
neg = !neg;
}
res = udivmodsi4(a, b, 0);
if (neg)
res = -res;
return res;
}
long
__modsi3(long a, long b)
{
int neg = 0;
long res;
if (a < 0) {
a = -a;
neg = 1;
}
if (b < 0)
b = -b;
res = udivmodsi4(a, b, 1);
if (neg)
res = -res;
return res;
}
long
__udivsi3(long a, long b)
{
return udivmodsi4(a, b, 0);
}
long
__umodsi3(long a, long b)
{
return udivmodsi4(a, b, 1);
}