summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHelge Deller <deller@gmx.de>2022-08-09 18:57:45 +0200
committerHelge Deller <deller@gmx.de>2022-08-09 18:57:45 +0200
commit8f54e58cd151b4e80db27d1a068a6f7fbfa5b3b3 (patch)
tree994a10681279f965cc90536e0918419035679730
parent73a408ab69d238e8e69a48fb0a6ae51ef237ac0c (diff)
downloadpalo-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/Makefile4
-rw-r--r--ipl/bootloader.h1
-rw-r--r--ipl/ext2.c16
-rw-r--r--ipl/ipl.c9
-rw-r--r--ipl/pdc_misc.c14
-rw-r--r--ipl/vsprintf.c29
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);
diff --git a/ipl/ext2.c b/ipl/ext2.c
index 6add1a0..8d3ac42 100644
--- a/ipl/ext2.c
+++ b/ipl/ext2.c
@@ -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];
diff --git a/ipl/ipl.c b/ipl/ipl.c
index 22abca6..f6fe251 100644
--- a/ipl/ipl.c
+++ b/ipl/ipl.c
@@ -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';