Skip to content
This repository was archived by the owner on Jun 20, 2019. It is now read-only.

Commit 8e9a539

Browse files
authored
Merge pull request #744 from jpf91/aarch64
Finish AArch64 port
2 parents 3329c94 + 5006619 commit 8e9a539

File tree

16 files changed

+373
-303
lines changed

16 files changed

+373
-303
lines changed

gcc/testsuite/gdc.dg/link.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// { dg-do link { target arm*-*-* i?86-*-* x86_64-*-* } }
1+
// { dg-do link { target arm*-*-* aarch64-*-* i?86-*-* x86_64-*-* } }
22

33
/******************************************/
44

gcc/testsuite/gdc.test/runnable/argufilem.d

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// Requires TypeInfo based vararg support
2+
// { dg-skip-if "" { aarch64*-*-* } }
13
// EXTRA_SOURCES: imports/argufile.d
24

35
// NOTE: The bug only works when main.d and argufile.d are put in

gcc/testsuite/gdc.test/runnable/test23.d

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,10 @@ void test17()
384384
{
385385
"vldr d0, %1; vstr d0, %0;" : "=m" (g) : "m" (f), : "d0";
386386
}
387+
else version(AArch64) asm
388+
{
389+
"ldr d0, %1; str d0, %0;" : "=m" (g) : "m" (f), : "d0";
390+
}
387391
else static assert(false, "ASM code not implemented for this architecture");
388392
}
389393
else

gcc/testsuite/gdc.test/runnable/test36.d

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ extern (Windows):
4242
{
4343
"str sp,%0" : "=m" esp : : ;
4444
}
45+
else version(AArch64) asm
46+
{
47+
"mov x0,sp; str w0,%0" : "=m" esp : : "x0";
48+
}
4549
else static assert(false, "ASM code not implemented for this architecture");
4650
}
4751
else asm
@@ -74,6 +78,10 @@ int main()
7478
{
7579
"str sp,%0" : "=m" esp : : ;
7680
}
81+
else version(AArch64) asm
82+
{
83+
"mov x0,sp; str w0,%0" : "=m" esp : : "x0";
84+
}
7785
else static assert(false, "ASM code not implemented for this architecture");
7886
}
7987
else asm
@@ -97,6 +105,10 @@ int main()
97105
{
98106
"str sp,%0" : "=m" esp : : ;
99107
}
108+
else version(AArch64) asm
109+
{
110+
"mov x0,sp; str w0,%0" : "=m" esp : : "x0";
111+
}
100112
else static assert(false, "ASM code not implemented for this architecture");
101113
}
102114
else asm

gcc/testsuite/gdc.test/runnable/test4.d

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,16 @@ else version(ARM)
254254
assert(TRECT6.BottomRight.offsetof == 16);
255255
assert(TRECT6.foo2.offsetof == 24);
256256
}
257+
else version(AArch64)
258+
{
259+
assert(TRECT6.Left.offsetof == 8);
260+
assert(TRECT6.Top.offsetof == 12);
261+
assert(TRECT6.Right.offsetof == 16);
262+
assert(TRECT6.Bottom.offsetof == 20);
263+
assert(TRECT6.TopLeft.offsetof == 8);
264+
assert(TRECT6.BottomRight.offsetof == 16);
265+
assert(TRECT6.foo2.offsetof == 24);
266+
}
257267
else
258268
{
259269
assert(TRECT6.Left.offsetof == 4);

gcc/testsuite/gdc.test/runnable/test42.d

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4241,14 +4241,7 @@ int bug3809()
42414241
{
42424242
version(GNU)
42434243
{
4244-
version(X86)
4245-
asm { "nop"; }
4246-
else version(X86_64)
4247-
asm { "nop"; }
4248-
else version(ARM)
4249-
asm { "nop"; }
4250-
else
4251-
static assert(false, "ASM code not implemented for this architecture");
4244+
asm { ""; }
42524245
}
42534246
else
42544247
{
@@ -5701,7 +5694,11 @@ void testreal_to_ulong()
57015694
real adjust = 1.0L/real.epsilon;
57025695
u = r2ulong(adjust);
57035696
//writefln("%s %s", adjust, u);
5704-
static if(real.mant_dig == 64)
5697+
static if(real.mant_dig == 113)
5698+
assert(u == 18446744073709551615UL);
5699+
else static if(real.mant_dig == 106)
5700+
assert(u == 18446744073709551615UL);
5701+
else static if(real.mant_dig == 64)
57055702
assert(u == 9223372036854775808UL);
57065703
else static if(real.mant_dig == 53)
57075704
assert(u == 4503599627370496UL);

gcc/testsuite/gdc.test/runnable/testsafe.d

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -209,14 +209,7 @@ void inlineasm()
209209
{
210210
version(GNU)
211211
{
212-
version(X86)
213-
static assert(!__traits(compiles, { asm { "nop"; } }() ));
214-
else version(X86_64)
215-
static assert(!__traits(compiles, { asm { "nop"; } }() ));
216-
else version(ARM)
217-
static assert(!__traits(compiles, { asm { "nop"; } }() ));
218-
else
219-
static assert(false, "ASM code not implemented for this architecture");
212+
static assert(!__traits(compiles, { asm { ""; } }() ));
220213
}
221214
else
222215
static assert(!__traits(compiles, { asm { int 3; } }() ));

libphobos/libdruntime/core/internal/convert.d

Lines changed: 114 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,36 @@
1010
module core.internal.convert;
1111
import core.internal.traits : Unqual;
1212

13+
/+
14+
A @nogc function can allocate memory during CTFE.
15+
+/
16+
@nogc nothrow pure @trusted
17+
private ubyte[] ctfe_alloc()(size_t n)
18+
{
19+
if (!__ctfe)
20+
{
21+
assert(0, "CTFE only");
22+
}
23+
else
24+
{
25+
static ubyte[] alloc(size_t x) nothrow pure
26+
{
27+
if (__ctfe) // Needed to prevent _d_newarray from appearing in compiled prorgam.
28+
return new ubyte[x];
29+
else
30+
assert(0);
31+
}
32+
return (cast(ubyte[] function(size_t) @nogc nothrow pure) &alloc)(n);
33+
}
34+
}
35+
1336
@trusted pure nothrow
14-
const(ubyte)[] toUbyte(T)(ref T val) if (is(Unqual!T == float) || is(Unqual!T == double) || is(Unqual!T == real) ||
37+
const(ubyte)[] toUbyte(T)(const ref T val) if (is(Unqual!T == float) || is(Unqual!T == double) || is(Unqual!T == real) ||
1538
is(Unqual!T == ifloat) || is(Unqual!T == idouble) || is(Unqual!T == ireal))
1639
{
1740
static const(ubyte)[] reverse_(const(ubyte)[] arr)
1841
{
19-
ubyte[] buff = new ubyte[arr.length];
42+
ubyte[] buff = ctfe_alloc(arr.length);
2043
foreach (k, v; arr)
2144
{
2245
buff[$-k-1] = v;
@@ -31,17 +54,35 @@ const(ubyte)[] toUbyte(T)(ref T val) if (is(Unqual!T == float) || is(Unqual!T ==
3154
uint exp = parsed.exponent;
3255
uint sign = parsed.sign;
3356

34-
ubyte[T.sizeof] buff;
57+
ubyte[] buff = ctfe_alloc(T.sizeof);
3558
size_t off_bytes = 0;
3659
size_t off_bits = 0;
60+
// Quadruples won't fit in one ulong, so check for that.
61+
enum mantissaMax = FloatTraits!T.MANTISSA < ulong.sizeof*8 ?
62+
FloatTraits!T.MANTISSA : ulong.sizeof*8;
3763

38-
for (; off_bytes < FloatTraits!T.MANTISSA/8; ++off_bytes)
64+
for (; off_bytes < mantissaMax/8; ++off_bytes)
3965
{
4066
buff[off_bytes] = cast(ubyte)mantissa;
4167
mantissa >>= 8;
4268
}
43-
off_bits = FloatTraits!T.MANTISSA%8;
44-
buff[off_bytes] = cast(ubyte)mantissa;
69+
70+
static if (floatFormat!T == FloatFormat.Quadruple)
71+
{
72+
ulong mantissa2 = parsed.mantissa2;
73+
off_bytes--; // go back one, since mantissa only stored data in 56
74+
// bits, ie 7 bytes
75+
for(; off_bytes < FloatTraits!T.MANTISSA/8; ++off_bytes)
76+
{
77+
buff[off_bytes] = cast(ubyte)mantissa2;
78+
mantissa2 >>= 8;
79+
}
80+
}
81+
else
82+
{
83+
off_bits = FloatTraits!T.MANTISSA%8;
84+
buff[off_bytes] = cast(ubyte)mantissa;
85+
}
4586

4687
for (size_t i=0; i<FloatTraits!T.EXPONENT/8; ++i)
4788
{
@@ -60,7 +101,7 @@ const(ubyte)[] toUbyte(T)(ref T val) if (is(Unqual!T == float) || is(Unqual!T ==
60101

61102
version (LittleEndian)
62103
{
63-
return buff.dup;
104+
return buff;
64105
}
65106
else
66107
{
@@ -83,8 +124,8 @@ private Float parse(bool is_denormalized = false, T)(T x) if (is(Unqual!T == ifl
83124
private Float parse(bool is_denormalized = false, T:real)(T x_) if (floatFormat!T != FloatFormat.Real80)
84125
{
85126
Unqual!T x = x_;
86-
assert(floatFormat!T != FloatFormat.DoubleDouble && floatFormat!T != FloatFormat.Quadruple,
87-
"doubledouble and quadruple float formats are not supported in CTFE");
127+
static assert(floatFormat!T != FloatFormat.DoubleDouble,
128+
"doubledouble float format not supported in CTFE");
88129
if (x is cast(T)0.0) return FloatTraits!T.ZERO;
89130
if (x is cast(T)-0.0) return FloatTraits!T.NZERO;
90131
if (x is T.nan) return FloatTraits!T.NAN;
@@ -103,17 +144,38 @@ private Float parse(bool is_denormalized = false, T:real)(T x_) if (floatFormat!
103144
if (is_denormalized)
104145
return Float(0, 0, sign);
105146
else
106-
return Float(denormalizedMantissa(x), 0, sign);
147+
return denormalizedMantissa(x, sign);
107148
}
108149

109150
x2 /= binPow2(e);
110151

111152
static if (!is_denormalized)
112153
x2 -= 1.0;
113154

114-
x2 *= 2UL<<(FloatTraits!T.MANTISSA);
115-
ulong mant = shiftrRound(cast(ulong)x2);
116-
return Float(mant, exp, sign);
155+
static if (floatFormat!T == FloatFormat.Quadruple)
156+
{
157+
// Store the 112-bit mantissa in two ulongs, specifically the lower 56
158+
// bits of each, with the most significant bits in mantissa2. There's
159+
// an edge case exposed by the labeled test below, where only a subnormal
160+
// with the highest bit set being the 57th bit will "overflow" to the
161+
// 57th bit in mantissa2 with the following logic, but that special case
162+
// is handled by an additional check in denormalizedMantissa for
163+
// Quadruples below.
164+
165+
x2 *= 2UL<<(FloatTraits!T.MANTISSA - (ulong.sizeof - 1)*8 - 1);
166+
ulong mant2 = cast(ulong) x2;
167+
x2 -= mant2;
168+
169+
x2 *= 2UL<<((ulong.sizeof - 1)*8 - 1);
170+
ulong mant = cast(ulong) x2;
171+
return Float(mant, exp, sign, mant2);
172+
}
173+
else
174+
{
175+
x2 *= 2UL<<(FloatTraits!T.MANTISSA);
176+
ulong mant = shiftrRound(cast(ulong)x2);
177+
return Float(mant, exp, sign);
178+
}
117179
}
118180

119181
@safe pure nothrow
@@ -151,7 +213,7 @@ private Float parse(bool _ = false, T:real)(T x_) if (floatFormat!T == FloatForm
151213
uint exp = cast(uint)(e + EXPONENT_MED);
152214
if (!exp)
153215
{
154-
return Float(denormalizedMantissa(x), 0, sign);
216+
return denormalizedMantissa(x, sign);
155217
}
156218
int pow = (FloatTraits!T.MANTISSA-1-e);
157219
x *= binPow2((pow / EXPONENT_MED)*EXPONENT_MED); //To avoid overflow in 2.0L ^^ pow
@@ -165,6 +227,7 @@ private struct Float
165227
ulong mantissa;
166228
uint exponent;
167229
uint sign;
230+
ulong mantissa2;
168231
}
169232

170233
private template FloatTraits(T) if (floatFormat!T == FloatFormat.Float)
@@ -215,14 +278,14 @@ private template FloatTraits(T) if (floatFormat!T == FloatFormat.DoubleDouble) /
215278
enum NINF = Float(0, 0x7ff, 1);
216279
}
217280

218-
private template FloatTraits(T) if (floatFormat!T == FloatFormat.Quadruple) //Unsupported in CTFE
281+
private template FloatTraits(T) if (floatFormat!T == FloatFormat.Quadruple)
219282
{
220283
enum EXPONENT = 15;
221284
enum MANTISSA = 112;
222285
enum ZERO = Float(0, 0, 0);
223286
enum NZERO = Float(0, 0, 1);
224-
enum NAN = Float(-1, 0x7fff, 0);
225-
enum NNAN = Float(-1, 0x7fff, 1);
287+
enum NAN = Float(0, 0x7fff, 0, 0x80000000000000UL);
288+
enum NNAN = Float(0, 0x7fff, 1, 0x80000000000000UL);
226289
enum INF = Float(0, 0x7fff, 0);
227290
enum NINF = Float(0, 0x7fff, 1);
228291
}
@@ -291,21 +354,49 @@ private uint binLog2(T)(T x)
291354
}
292355

293356
@safe pure nothrow
294-
private ulong denormalizedMantissa(T)(T x) if (floatFormat!T == FloatFormat.Real80)
357+
private Float denormalizedMantissa(T)(T x, uint sign) if (floatFormat!T == FloatFormat.Real80)
295358
{
296359
x *= 2.0L^^FloatTraits!T.MANTISSA;
297360
auto fl = parse(x);
298361
uint pow = FloatTraits!T.MANTISSA - fl.exponent + 1;
299-
return fl.mantissa >> pow;
362+
return Float(fl.mantissa >> pow, 0, sign);
300363
}
301364

302365
@safe pure nothrow
303-
private ulong denormalizedMantissa(T)(T x) if (floatFormat!T != FloatFormat.Real80)
366+
private Float denormalizedMantissa(T)(T x, uint sign)
367+
if (floatFormat!T == FloatFormat.Float || floatFormat!T == FloatFormat.Double)
304368
{
305369
x *= 2.0L^^FloatTraits!T.MANTISSA;
306370
auto fl = parse!true(x);
307371
ulong mant = fl.mantissa >> (FloatTraits!T.MANTISSA - fl.exponent);
308-
return shiftrRound(mant);
372+
return Float(shiftrRound(mant), 0, sign);
373+
}
374+
375+
@safe pure nothrow
376+
private Float denormalizedMantissa(T)(T x, uint sign) if (floatFormat!T == FloatFormat.Quadruple)
377+
{
378+
x *= 2.0L^^FloatTraits!T.MANTISSA;
379+
auto fl = parse!true(x);
380+
uint offset = FloatTraits!T.MANTISSA - fl.exponent + 1;
381+
enum mantissaSize = (ulong.sizeof - 1) * 8;
382+
383+
if (offset < mantissaSize)
384+
{ // Create a new mantissa ulong with the trailing mantissa2 bits that
385+
// need to be shifted into mantissa, by shifting the needed bits left,
386+
// zeroing out the first byte, and then ORing it with mantissa shifted
387+
// right by offset.
388+
389+
ulong shiftedMantissa = ((fl.mantissa2 << (mantissaSize - offset)) &
390+
0x00FFFFFFFFFFFFFFUL) | fl.mantissa >> offset;
391+
return Float(shiftedMantissa, 0, sign, fl.mantissa2 >> offset);
392+
}
393+
else if (offset > mantissaSize)
394+
return Float(fl.mantissa2 >> offset - mantissaSize , 0, sign, 0);
395+
else
396+
// Handle special case mentioned in parse() above by zeroing out the
397+
// 57'th bit of mantissa2, "shifting" it into mantissa, and setting the
398+
// first bit of mantissa2.
399+
return Float(fl.mantissa2 & 0x00FFFFFFFFFFFFFFUL , 0, sign, 1);
309400
}
310401

311402
version (unittest)
@@ -403,6 +494,8 @@ version (unittest)
403494

404495
testNumberConvert!("real.min_normal/2");
405496
testNumberConvert!("real.min_normal/2UL^^63");
497+
// check subnormal storage edge case for Quadruple
498+
testNumberConvert!("real.min_normal/2UL^^56");
406499
//testNumberConvert!("real.min_normal/19"); // XGDC: ct[0] == 0, rt[0] == 27
407500
//testNumberConvert!("real.min_normal/17"); // XGDC: ct[0= == 128, rt[0] == 136
408501

0 commit comments

Comments
 (0)