mirror of
				https://xff.cz/git/u-boot/
				synced 2025-10-31 18:35:42 +01:00 
			
		
		
		
	This way we may have very limited set of functions implemented so we save some space. Also it allows us to build U-Boot for any ARC core with the same one toolchain because we don't rely on pre-built libgcc. For example: * we may use little-endian toolchain but build U-Boot for ether endianess * we may use non-multilibbed uClibc toolchain but build U-Boot for whatever ARC CPU flavour that current GCC supports Private libgcc built from generic C implementation contributes only 144 bytes to .text section so we don't see significant degradation of size: --->8--- $ arc-linux-size u-boot.libgcc-prebuilt text data bss dec hex filename 222217 24912 214820 461949 70c7d u-boot.libgcc-prebuilt $ arc-linux-size u-boot.libgcc-private text data bss dec hex filename 222361 24912 214820 462093 70d0d u-boot.libgcc-private --->8--- Also I don't notice visible performance degradation compared to pre-built libgcc (where at least "*div*" functions are had-written in assembly) on typical operations of downloading 10Mb uImage over TFTP and bootm. Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
		
			
				
	
	
		
			162 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			162 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * 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);
 | |
| }
 |