diff options
author | Helge Deller <deller@gmx.de> | 2022-08-09 18:57:45 +0200 |
---|---|---|
committer | Helge Deller <deller@gmx.de> | 2022-08-09 18:57:45 +0200 |
commit | 8f54e58cd151b4e80db27d1a068a6f7fbfa5b3b3 (patch) | |
tree | 994a10681279f965cc90536e0918419035679730 | |
parent | 73a408ab69d238e8e69a48fb0a6ae51ef237ac0c (diff) | |
download | palo-8f54e58cd151b4e80db27d1a068a6f7fbfa5b3b3.tar.gz |
ipl: Enable FPU and remove workarounds
It turns out, that the FPU isn't initialized by firmware, which is
why the floating point instructions in libgcc's __udivdi3, __umoddi3
and __muldi3 routines simply hangs the machine.
This patch enables the FPU at bootup and thus we can drop the
current work-arounds.
Signed-off-by: Helge Deller <deller@gmx.de>
-rw-r--r-- | ipl/Makefile | 4 | ||||
-rw-r--r-- | ipl/bootloader.h | 1 | ||||
-rw-r--r-- | ipl/ext2.c | 16 | ||||
-rw-r--r-- | ipl/ipl.c | 9 | ||||
-rw-r--r-- | ipl/pdc_misc.c | 14 | ||||
-rw-r--r-- | ipl/vsprintf.c | 29 |
6 files changed, 32 insertions, 41 deletions
diff --git a/ipl/Makefile b/ipl/Makefile index 3409868..2254887 100644 --- a/ipl/Makefile +++ b/ipl/Makefile @@ -28,7 +28,6 @@ CROSS_COMPILE := $(call cc-cross-prefix, \ CC = ${CROSS_COMPILE}gcc AR = ar LD = ${CROSS_COMPILE}ld -OBJDUMP = ${CROSS_COMPILE}objdump ifneq ("$(wildcard /etc/debian_version)","") BLDINFO := $(shell echo https://parisc.wiki.kernel.org - `dpkg-parsechangelog -l../debian/changelog -SDate`) @@ -40,7 +39,7 @@ endif VPATH=../lib:. AFLAGS = -I../lib -CFLAGS = -DIPL_LOADER -I. -I../lib -I../include -O2 -mdisable-fpregs -Wall -fno-delete-null-pointer-checks -fno-builtin -mpa-risc-1-0 +CFLAGS = -DIPL_LOADER -I. -I../lib -I../include -O2 -mdisable-fpregs -Wall -fno-delete-null-pointer-checks -fno-builtin LDFLAGS = -N --section-start .init=0x60000 -e '$$START$$' all: iplelf @@ -50,7 +49,6 @@ iplelf: crt0.o ipl.a $(CC) $(CFLAGS) -c -o build.o build.c -rm -f build.c $(LD) $(LDFLAGS) -o iplelf crt0.o ipl.a build.o `$(CC) -print-libgcc-file-name` - $(OBJDUMP) -t iplelf | grep -E '__udivdi3|__umoddi3|__muldi3' && (echo "ERROR: Can not use __udivdi3 or __umoddi3 in palo ipl code" && false) || true ipl.a: $(OFILES) $(AR) rv ipl.a $? diff --git a/ipl/bootloader.h b/ipl/bootloader.h index af4733f..c6a9f18 100644 --- a/ipl/bootloader.h +++ b/ipl/bootloader.h @@ -27,6 +27,7 @@ int pdc_os_bits(); int pdc_iodc_bootin(__u64 devaddr, char *memaddr, unsigned size); int pdc_read_conspath(unsigned char *memaddr); int pdc_do_reset(void); +int pdc_coproc_cfg(); int pdc_model_sysmodel(char *name); typedef void (*describe_t)(int fd, int *bufalign, int *blocksize); @@ -64,27 +64,15 @@ static struct inode_table_entry { #undef DEBUG #define Debug 0 -/* div_blocksize() and mul_blocksize() are trivial functions to avoid 64-bit - __udivdi3 and __muldi3 millicode routines. They only work because the ext2 - blocksize is a multiple of 2 */ static __u64 div_blocksize(__u64 devaddr, unsigned blocksize) { - while (blocksize > 1) { - devaddr >>= 1; - blocksize >>= 1; - } - return devaddr; + return devaddr / blocksize; } static __u64 mul_blocksize(__u64 devaddr, unsigned blocksize) { - while (blocksize > 1) { - devaddr <<= 1; - blocksize >>= 1; - } - return devaddr; + return devaddr * blocksize; } - static struct ext3_extent_header *ext3_extent_header(struct ext2_inode *i) { return (struct ext3_extent_header *)&i->i_block[0]; @@ -519,6 +519,7 @@ iplmain(int is_interactive, char *initialstackptr, int started_wide) struct firstblock f; int blocked_bootdev; int wide; + int ccr_functional; int kern_part, rd_part; char kern_name[128], rd_name[128]; char kern_fullname[128+10]; @@ -543,6 +544,14 @@ iplmain(int is_interactive, char *initialstackptr, int started_wide) printf("palo loaded at %p-%p.\n", &_start, &_end); } + ccr_functional = pdc_coproc_cfg(); + if (ccr_functional) + asm("mtctl %0,%1" : : "r" (ccr_functional), "i" (10)); + else { + printf("No functional FPUs found - stopping.\n"); + while (1) ; + } + disk_2gb_limit = pdc_bootdisk_2GB_limit(); printf("Boot limited to sectors below 2GB: %s\n", disk_2gb_limit ? "YES":"NO"); diff --git a/ipl/pdc_misc.c b/ipl/pdc_misc.c index b2296da..12c4613 100644 --- a/ipl/pdc_misc.c +++ b/ipl/pdc_misc.c @@ -221,6 +221,20 @@ pdc_os_bits() } int +pdc_coproc_cfg(void) +{ + int r; + + r = firmware_call(mem_pdc, PDC_COPROC, PDC_COPROC_CFG, pdc_result); + convert_from_wide(pdc_result); + if (r == PDC_OK) { + return pdc_result[0]; /* ccr_functional */ + } else { + return 0; + } +} + +int pdc_model_sysmodel(char *name) { int r; diff --git a/ipl/vsprintf.c b/ipl/vsprintf.c index 052511a..4a7a060 100644 --- a/ipl/vsprintf.c +++ b/ipl/vsprintf.c @@ -36,17 +36,10 @@ static int skip_atoi(const char **s) #define SPECIAL 32 /* 0x */ #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ -/* inline on "unsigned long", not "long long" to avoid using __umoddi3 and __udivdi3 */ -#define do_div_long(n,base) ({ \ +#define do_div(n,base) ({ \ int __res; \ -__res = ((unsigned long) n) % (unsigned) base; \ -n = ((unsigned long) n) / (unsigned) base; \ -__res; }) - -#define do_div_hex(n) ({ \ -unsigned long __res; \ -__res = ((unsigned long) n) & 0x0f; \ -n >>= 4; \ +__res = ((unsigned long long) n) % (unsigned) base; \ +n = ((unsigned long long) n) / (unsigned) base; \ __res; }) static char * number(char * str, unsigned long long num, int base, int size, int precision @@ -86,12 +79,8 @@ static char * number(char * str, unsigned long long num, int base, int size, int i = 0; if (num == 0) tmp[i++]='0'; - else while (num != 0) { - if (base == 16) - tmp[i++] = digits[do_div_hex(num)]; - else - tmp[i++] = digits[do_div_long(num,base)]; - } + else while (num != 0) + tmp[i++] = digits[do_div(num,base)]; if (i > precision) precision = i; size -= precision; @@ -288,14 +277,6 @@ again: num = va_arg(args, int); else num = va_arg(args, unsigned int); - /* workaround to output all integers > 32bit as hex. Avoids millicode routines */ - if (num >> 32) { - if (base != 16) { // append hex symbol "0x" - *str++ = '0'; - *str++ = 'x'; - } - base = 16; - } str = number(str, num, base, field_width, precision, flags); } *str = '\0'; |