Skip to content

Commit

Permalink
[PARISC] import necessary bits of libgcc.a
Browse files Browse the repository at this point in the history
Currently we're hacking libs-y to include libgcc.a, but this has
unforeseen consequences since the userspace libgcc is linked with fpregs
enabled. We need the kernel to stop using fpregs in an uncontrolled manner
to implement lazy fpu state saves.

Signed-off-by: Kyle McMartin <kyle@mcmartin.ca>
  • Loading branch information
Kyle McMartin authored and Kyle McMartin committed Oct 18, 2007
1 parent 6f7d998 commit efb80e7
Show file tree
Hide file tree
Showing 31 changed files with 4,628 additions and 24 deletions.
2 changes: 1 addition & 1 deletion arch/parisc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ kernel-y := mm/ kernel/ math-emu/ kernel/init_task.o
kernel-$(CONFIG_HPUX) += hpux/

core-y += $(addprefix arch/parisc/, $(kernel-y))
libs-y += arch/parisc/lib/ `$(CC) -print-libgcc-file-name`
libs-y += arch/parisc/lib/

drivers-$(CONFIG_OPROFILE) += arch/parisc/oprofile/

Expand Down
22 changes: 0 additions & 22 deletions arch/parisc/kernel/parisc_ksyms.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,31 +122,9 @@ EXPORT_SYMBOL($$divI_12);
EXPORT_SYMBOL($$divI_14);
EXPORT_SYMBOL($$divI_15);

extern void __ashrdi3(void);
extern void __ashldi3(void);
extern void __lshrdi3(void);
extern void __muldi3(void);

EXPORT_SYMBOL(__ashrdi3);
EXPORT_SYMBOL(__ashldi3);
EXPORT_SYMBOL(__lshrdi3);
EXPORT_SYMBOL(__muldi3);

asmlinkage void * __canonicalize_funcptr_for_compare(void *);
EXPORT_SYMBOL(__canonicalize_funcptr_for_compare);

#ifdef CONFIG_64BIT
extern void __divdi3(void);
extern void __udivdi3(void);
extern void __umoddi3(void);
extern void __moddi3(void);

EXPORT_SYMBOL(__divdi3);
EXPORT_SYMBOL(__udivdi3);
EXPORT_SYMBOL(__umoddi3);
EXPORT_SYMBOL(__moddi3);
#endif

#ifndef CONFIG_64BIT
extern void $$dyncall(void);
EXPORT_SYMBOL($$dyncall);
Expand Down
2 changes: 1 addition & 1 deletion arch/parisc/lib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

lib-y := lusercopy.o bitops.o checksum.o io.o memset.o fixup.o memcpy.o

obj-y := iomap.o
obj-y := libgcc/ milli/ iomap.o
4 changes: 4 additions & 0 deletions arch/parisc/lib/libgcc/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
obj-y := __ashldi3.o __ashrdi3.o __clzsi2.o __divdi3.o __divsi3.o \
__lshrdi3.o __moddi3.o __modsi3.o __udivdi3.o \
__udivmoddi4.o __udivmodsi4.o __udivsi3.o \
__umoddi3.o __umodsi3.o __muldi3.o __umulsidi3.o
19 changes: 19 additions & 0 deletions arch/parisc/lib/libgcc/__ashldi3.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include "libgcc.h"

u64 __ashldi3(u64 v, int cnt)
{
int c = cnt & 31;
u32 vl = (u32) v;
u32 vh = (u32) (v >> 32);

if (cnt & 32) {
vh = (vl << c);
vl = 0;
} else {
vh = (vh << c) + (vl >> (32 - c));
vl = (vl << c);
}

return ((u64) vh << 32) + vl;
}
EXPORT_SYMBOL(__ashldi3);
19 changes: 19 additions & 0 deletions arch/parisc/lib/libgcc/__ashrdi3.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include "libgcc.h"

u64 __ashrdi3(u64 v, int cnt)
{
int c = cnt & 31;
u32 vl = (u32) v;
u32 vh = (u32) (v >> 32);

if (cnt & 32) {
vl = ((s32) vh >> c);
vh = (s32) vh >> 31;
} else {
vl = (vl >> c) + (vh << (32 - c));
vh = ((s32) vh >> c);
}

return ((u64) vh << 32) + vl;
}
EXPORT_SYMBOL(__ashrdi3);
30 changes: 30 additions & 0 deletions arch/parisc/lib/libgcc/__clzsi2.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include "libgcc.h"

u32 __clzsi2(u32 v)
{
int p = 31;

if (v & 0xffff0000) {
p -= 16;
v >>= 16;
}
if (v & 0xff00) {
p -= 8;
v >>= 8;
}
if (v & 0xf0) {
p -= 4;
v >>= 4;
}
if (v & 0xc) {
p -= 2;
v >>= 2;
}
if (v & 0x2) {
p -= 1;
v >>= 1;
}

return p;
}
EXPORT_SYMBOL(__clzsi2);
23 changes: 23 additions & 0 deletions arch/parisc/lib/libgcc/__divdi3.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include "libgcc.h"

s64 __divdi3(s64 num, s64 den)
{
int minus = 0;
s64 v;

if (num < 0) {
num = -num;
minus = 1;
}
if (den < 0) {
den = -den;
minus ^= 1;
}

v = __udivmoddi4(num, den, NULL);
if (minus)
v = -v;

return v;
}
EXPORT_SYMBOL(__divdi3);
23 changes: 23 additions & 0 deletions arch/parisc/lib/libgcc/__divsi3.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include "libgcc.h"

s32 __divsi3(s32 num, s32 den)
{
int minus = 0;
s32 v;

if (num < 0) {
num = -num;
minus = 1;
}
if (den < 0) {
den = -den;
minus ^= 1;
}

v = __udivmodsi4(num, den, NULL);
if (minus)
v = -v;

return v;
}
EXPORT_SYMBOL(__divsi3);
19 changes: 19 additions & 0 deletions arch/parisc/lib/libgcc/__lshrdi3.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include "libgcc.h"

u64 __lshrdi3(u64 v, int cnt)
{
int c = cnt & 31;
u32 vl = (u32) v;
u32 vh = (u32) (v >> 32);

if (cnt & 32) {
vl = (vh >> c);
vh = 0;
} else {
vl = (vl >> c) + (vh << (32 - c));
vh = (vh >> c);
}

return ((u64) vh << 32) + vl;
}
EXPORT_SYMBOL(__lshrdi3);
23 changes: 23 additions & 0 deletions arch/parisc/lib/libgcc/__moddi3.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include "libgcc.h"

s64 __moddi3(s64 num, s64 den)
{
int minus = 0;
s64 v;

if (num < 0) {
num = -num;
minus = 1;
}
if (den < 0) {
den = -den;
minus ^= 1;
}

(void)__udivmoddi4(num, den, (u64 *) & v);
if (minus)
v = -v;

return v;
}
EXPORT_SYMBOL(__moddi3);
23 changes: 23 additions & 0 deletions arch/parisc/lib/libgcc/__modsi3.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include "libgcc.h"

s32 __modsi3(s32 num, s32 den)
{
int minus = 0;
s32 v;

if (num < 0) {
num = -num;
minus = 1;
}
if (den < 0) {
den = -den;
minus ^= 1;
}

(void)__udivmodsi4(num, den, (u32 *) & v);
if (minus)
v = -v;

return v;
}
EXPORT_SYMBOL(__modsi3);
22 changes: 22 additions & 0 deletions arch/parisc/lib/libgcc/__muldi3.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include "libgcc.h"

union DWunion {
struct {
s32 high;
s32 low;
} s;
s64 ll;
};

s64 __muldi3(s64 u, s64 v)
{
const union DWunion uu = { .ll = u };
const union DWunion vv = { .ll = v };
union DWunion w = { .ll = __umulsidi3(uu.s.low, vv.s.low) };

w.s.high += ((u32)uu.s.low * (u32)vv.s.high
+ (u32)uu.s.high * (u32)vv.s.low);

return w.ll;
}
EXPORT_SYMBOL(__muldi3);
7 changes: 7 additions & 0 deletions arch/parisc/lib/libgcc/__udivdi3.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include "libgcc.h"

u64 __udivdi3(u64 num, u64 den)
{
return __udivmoddi4(num, den, NULL);
}
EXPORT_SYMBOL(__udivdi3);
31 changes: 31 additions & 0 deletions arch/parisc/lib/libgcc/__udivmoddi4.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include "libgcc.h"

u64 __udivmoddi4(u64 num, u64 den, u64 * rem_p)
{
u64 quot = 0, qbit = 1;

if (den == 0) {
BUG();
}

/* Left-justify denominator and count shift */
while ((s64) den >= 0) {
den <<= 1;
qbit <<= 1;
}

while (qbit) {
if (den <= num) {
num -= den;
quot += qbit;
}
den >>= 1;
qbit >>= 1;
}

if (rem_p)
*rem_p = num;

return quot;
}
EXPORT_SYMBOL(__udivmoddi4);
31 changes: 31 additions & 0 deletions arch/parisc/lib/libgcc/__udivmodsi4.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include "libgcc.h"

u32 __udivmodsi4(u32 num, u32 den, u32 * rem_p)
{
u32 quot = 0, qbit = 1;

if (den == 0) {
BUG();
}

/* Left-justify denominator and count shift */
while ((s32) den >= 0) {
den <<= 1;
qbit <<= 1;
}

while (qbit) {
if (den <= num) {
num -= den;
quot += qbit;
}
den >>= 1;
qbit >>= 1;
}

if (rem_p)
*rem_p = num;

return quot;
}
EXPORT_SYMBOL(__udivmodsi4);
7 changes: 7 additions & 0 deletions arch/parisc/lib/libgcc/__udivsi3.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include "libgcc.h"

u32 __udivsi3(u32 num, u32 den)
{
return __udivmodsi4(num, den, NULL);
}
EXPORT_SYMBOL(__udivsi3);
10 changes: 10 additions & 0 deletions arch/parisc/lib/libgcc/__umoddi3.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include "libgcc.h"

u64 __umoddi3(u64 num, u64 den)
{
u64 v;

(void)__udivmoddi4(num, den, &v);
return v;
}
EXPORT_SYMBOL(__umoddi3);
10 changes: 10 additions & 0 deletions arch/parisc/lib/libgcc/__umodsi3.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include "libgcc.h"

u32 __umodsi3(u32 num, u32 den)
{
u32 v;

(void)__udivmodsi4(num, den, &v);
return v;
}
EXPORT_SYMBOL(__umodsi3);
Loading

0 comments on commit efb80e7

Please sign in to comment.