authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-12-09 01:21:30-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-12-09 01:21:30-07:00
logda9542c0af1955c54fba4a9466d43d94290e36c9
tree9ef28d462909b46d5f250c69814913dd7e6e68b0
parent04d44db6cc764c1fceca27fe8f0d3651142ba5f3

tools/gen_stubs: add aarch64 and output preprocessor directives

Now it outputs libc.S which can be assembled with zig, and the small differences per-architecture are handled with preprocessor directives. There is also now a set of blacklisted symbols which contains compiler-rt.

1 files changed, 515 insertions(+), 68 deletions(-)

tools/gen_stubs.zig+515-68
...@@ -1,15 +1,25 @@...@@ -1,15 +1,25 @@
1//! Example usage:1//! Example usage:
2//! ./gen_stubs /path/to/musl/build-all2//! ./gen_stubs /path/to/musl/build-all >libc.S
3//!3//!
4//! The directory 'build-all' is expected to contain these subdirectories:4//! The directory 'build-all' is expected to contain these subdirectories:
5//! arm i386 mips mips64 powerpc powerpc64 riscv64 x86_645//! arm i386 mips mips64 powerpc powerpc64 riscv64 x86_64
6//!6//!
7//! ...each with 'lib/libc.so' inside of them.7//! ...each with 'lib/libc.so' inside of them.
8//!
9//! When building the resulting libc.S file, these defines are required:
10//! * `-DPTR64`: when the architecture is 64-bit
11//! * One of the following, corresponding to the CPU architecture:
12//! - `-DARCH_riscv64`
13//! - `-DARCH_mips`
14//! - `-DARCH_i386`
15//! - `-DARCH_x86_64`
16//! - `-DARCH_powerpc`
17//! - `-DARCH_powerpc64`
18//! - `-DARCH_aarch64`
819
9// TODO: pick the best index to put them into instead of at the end20// TODO: pick the best index to put them into instead of at the end
10// - e.g. find a common previous symbol and put it after that one21// - e.g. find a common previous symbol and put it after that one
11// - they definitely need to go into the correct section22// - they definitely need to go into the correct section
12// TODO: emit MultiSyms to use the preprocessor
1323
14const std = @import("std");24const std = @import("std");
15const builtin = std.builtin;25const builtin = std.builtin;
...@@ -18,9 +28,9 @@ const log = std.log;...@@ -18,9 +28,9 @@ const log = std.log;
18const elf = std.elf;28const elf = std.elf;
19const native_endian = @import("builtin").target.cpu.arch.endian();29const native_endian = @import("builtin").target.cpu.arch.endian();
2030
21const arches: [6]std.Target.Cpu.Arch = blk: {31const arches: [7]std.Target.Cpu.Arch = blk: {
22 var result: [6]std.Target.Cpu.Arch = undefined;32 var result: [7]std.Target.Cpu.Arch = undefined;
23 for (.{ .riscv64, .mips, .i386, .x86_64, .powerpc, .powerpc64 }) |arch| {33 for (.{ .riscv64, .mips, .i386, .x86_64, .powerpc, .powerpc64, .aarch64 }) |arch| {
24 result[archIndex(arch)] = arch;34 result[archIndex(arch)] = arch;
25 }35 }
26 break :blk result;36 break :blk result;
...@@ -29,16 +39,129 @@ const arches: [6]std.Target.Cpu.Arch = blk: {...@@ -29,16 +39,129 @@ const arches: [6]std.Target.Cpu.Arch = blk: {
29const MultiSym = struct {39const MultiSym = struct {
30 size: [arches.len]u64,40 size: [arches.len]u64,
31 present: [arches.len]bool,41 present: [arches.len]bool,
42 binding: [arches.len]u4,
32 section: u16,43 section: u16,
33 ty: u4,44 ty: u4,
34 binding: u4,
35 visib: elf.STV,45 visib: elf.STV,
46
47 fn allPresent(ms: MultiSym) bool {
48 for (arches) |_, i| {
49 if (!ms.present[i]) {
50 return false;
51 }
52 }
53 return true;
54 }
55
56 fn is32Only(ms: MultiSym) bool {
57 return ms.present[archIndex(.riscv64)] == false and
58 ms.present[archIndex(.mips)] == true and
59 ms.present[archIndex(.i386)] == true and
60 ms.present[archIndex(.x86_64)] == false and
61 ms.present[archIndex(.powerpc)] == true and
62 ms.present[archIndex(.powerpc64)] == false and
63 ms.present[archIndex(.aarch64)] == false;
64 }
65
66 fn commonSize(ms: MultiSym) ?u64 {
67 var size: ?u64 = null;
68 for (arches) |_, i| {
69 if (!ms.present[i]) continue;
70 if (size) |s| {
71 if (ms.size[i] != s) {
72 return null;
73 }
74 } else {
75 size = ms.size[i];
76 }
77 }
78 return size.?;
79 }
80
81 fn commonBinding(ms: MultiSym) ?u4 {
82 var binding: ?u4 = null;
83 for (arches) |_, i| {
84 if (!ms.present[i]) continue;
85 if (binding) |b| {
86 if (ms.binding[i] != b) {
87 return null;
88 }
89 } else {
90 binding = ms.binding[i];
91 }
92 }
93 return binding.?;
94 }
95
96 fn isPtrSize(ms: MultiSym) bool {
97 const map = .{
98 .{ .riscv64, 8 },
99 .{ .mips, 4 },
100 .{ .i386, 4 },
101 .{ .x86_64, 8 },
102 .{ .powerpc, 4 },
103 .{ .powerpc64, 8 },
104 .{ .aarch64, 8 },
105 };
106 inline for (map) |item| {
107 const arch = item[0];
108 const size = item[1];
109 const arch_index = archIndex(arch);
110 if (ms.present[arch_index] and ms.size[arch_index] != size) {
111 return false;
112 }
113 }
114 return true;
115 }
116
117 fn isPtr2Size(ms: MultiSym) bool {
118 const map = .{
119 .{ .riscv64, 16 },
120 .{ .mips, 8 },
121 .{ .i386, 8 },
122 .{ .x86_64, 16 },
123 .{ .powerpc, 8 },
124 .{ .powerpc64, 16 },
125 .{ .aarch64, 16 },
126 };
127 inline for (map) |item| {
128 const arch = item[0];
129 const size = item[1];
130 const arch_index = archIndex(arch);
131 if (ms.present[arch_index] and ms.size[arch_index] != size) {
132 return false;
133 }
134 }
135 return true;
136 }
137
138 fn isWeak64(ms: MultiSym) bool {
139 const map = .{
140 .{ .riscv64, 2 },
141 .{ .mips, 1 },
142 .{ .i386, 1 },
143 .{ .x86_64, 2 },
144 .{ .powerpc, 1 },
145 .{ .powerpc64, 2 },
146 .{ .aarch64, 2 },
147 };
148 inline for (map) |item| {
149 const arch = item[0];
150 const binding = item[1];
151 const arch_index = archIndex(arch);
152 if (ms.present[arch_index] and ms.binding[arch_index] != binding) {
153 return false;
154 }
155 }
156 return true;
157 }
36};158};
37159
38const Parse = struct {160const Parse = struct {
39 arena: mem.Allocator,161 arena: mem.Allocator,
40 sym_table: *std.StringArrayHashMap(MultiSym),162 sym_table: *std.StringArrayHashMap(MultiSym),
41 sections: *std.StringArrayHashMap(void),163 sections: *std.StringArrayHashMap(void),
164 blacklist: std.StringArrayHashMap(void),
42 elf_bytes: []align(@alignOf(elf.Elf64_Ehdr)) u8,165 elf_bytes: []align(@alignOf(elf.Elf64_Ehdr)) u8,
43 header: elf.Header,166 header: elf.Header,
44 arch: std.Target.Cpu.Arch,167 arch: std.Target.Cpu.Arch,
...@@ -54,6 +177,15 @@ pub fn main() !void {...@@ -54,6 +177,15 @@ pub fn main() !void {
54177
55 var build_all_dir = try std.fs.cwd().openDir(build_all_path, .{});178 var build_all_dir = try std.fs.cwd().openDir(build_all_path, .{});
56179
180 var sym_table = std.StringArrayHashMap(MultiSym).init(arena);
181 var sections = std.StringArrayHashMap(void).init(arena);
182 var blacklist = std.StringArrayHashMap(void).init(arena);
183
184 try blacklist.ensureUnusedCapacity(blacklisted_symbols.len);
185 for (blacklisted_symbols) |name| {
186 blacklist.putAssumeCapacityNoClobber(name, {});
187 }
188
57 for (arches) |arch| {189 for (arches) |arch| {
58 const libc_so_path = try std.fmt.allocPrint(arena, "{s}/lib/libc.so", .{@tagName(arch)});190 const libc_so_path = try std.fmt.allocPrint(arena, "{s}/lib/libc.so", .{@tagName(arch)});
59191
...@@ -68,13 +200,11 @@ pub fn main() !void {...@@ -68,13 +200,11 @@ pub fn main() !void {
68 );200 );
69 const header = try elf.Header.parse(elf_bytes[0..@sizeOf(elf.Elf64_Ehdr)]);201 const header = try elf.Header.parse(elf_bytes[0..@sizeOf(elf.Elf64_Ehdr)]);
70202
71 var sym_table = std.StringArrayHashMap(MultiSym).init(arena);
72 var sections = std.StringArrayHashMap(void).init(arena);
73
74 const parse: Parse = .{203 const parse: Parse = .{
75 .arena = arena,204 .arena = arena,
76 .sym_table = &sym_table,205 .sym_table = &sym_table,
77 .sections = &sections,206 .sections = &sections,
207 .blacklist = blacklist,
78 .elf_bytes = elf_bytes,208 .elf_bytes = elf_bytes,
79 .header = header,209 .header = header,
80 .arch = arch,210 .arch = arch,
...@@ -93,50 +223,132 @@ pub fn main() !void {...@@ -93,50 +223,132 @@ pub fn main() !void {
93 }223 }
94224
95 const stdout = std.io.getStdOut().writer();225 const stdout = std.io.getStdOut().writer();
96 _ = stdout;226 try stdout.writeAll(
97227 \\#ifdef PTR64
98 //var prev_section: u16 = 0;228 \\#define WEAK64 .weak
99 //for (all_syms) |sym| {229 \\#define PTR_SIZE_BYTES 8
100 // const this_section = s(sym.st_shndx);230 \\#define PTR2_SIZE_BYTES 16
101 // if (this_section != prev_section) {231 \\#else
102 // prev_section = this_section;232 \\#define WEAK64 .globl
103 // const sh_name = mem.sliceTo(shstrtab[s(shdrs[this_section].sh_name)..], 0);233 \\#define PTR_SIZE_BYTES 4
104 // try stdout.print("{s}\n", .{sh_name});234 \\#define PTR2_SIZE_BYTES 8
105 // }235 \\#endif
106236 \\
107 // switch (binding) {237 );
108 // elf.STB_GLOBAL => {238
109 // try stdout.print(".globl {s}\n", .{name});239 var prev_section: u16 = std.math.maxInt(u16);
110 // },240 var prev_pp_state: enum { none, ptr32, special } = .none;
111 // elf.STB_WEAK => {241 for (sym_table.values()) |multi_sym, sym_index| {
112 // try stdout.print(".weak {s}\n", .{name});242 const name = sym_table.keys()[sym_index];
113 // },243
114 // else => unreachable,244 if (multi_sym.section != prev_section) {
115 // }245 prev_section = multi_sym.section;
116246 const sh_name = sections.keys()[multi_sym.section];
117 // switch (ty) {247 try stdout.print("{s}\n", .{sh_name});
118 // elf.STT_NOTYPE => {},248 }
119 // elf.STT_FUNC => {249
120 // try stdout.print(".type {s}, %function;\n", .{name});250 if (multi_sym.allPresent()) {
121 // // omitting the size is OK for functions251 switch (prev_pp_state) {
122 // },252 .none => {},
123 // elf.STT_OBJECT => {253 .ptr32, .special => {
124 // try stdout.print(".type {s}, %object;\n", .{name});254 try stdout.writeAll("#endif\n");
125 // if (size != 0) {255 prev_pp_state = .none;
126 // try stdout.print(".size {s}, {d}\n", .{ name, size });256 },
127 // }257 }
128 // },258 } else if (multi_sym.is32Only()) {
129 // else => unreachable,259 switch (prev_pp_state) {
130 // }260 .none => {
131261 try stdout.writeAll("#ifdef PTR32\n");
132 // switch (visib) {262 prev_pp_state = .ptr32;
133 // .DEFAULT => {},263 },
134 // .PROTECTED => try stdout.print(".protected {s}\n", .{name}),264 .special => {
135 // .INTERNAL, .HIDDEN => unreachable,265 try stdout.writeAll("#endif\n#ifdef PTR32\n");
136 // }266 prev_pp_state = .ptr32;
137267 },
138 // try stdout.print("{s}:\n", .{name});268 .ptr32 => {},
139 //}269 }
270 } else {
271 switch (prev_pp_state) {
272 .none => {},
273 .special, .ptr32 => {
274 try stdout.writeAll("#endif\n");
275 },
276 }
277 prev_pp_state = .special;
278
279 var first = true;
280 try stdout.writeAll("#if ");
281
282 for (arches) |arch, i| {
283 if (multi_sym.present[i]) continue;
284
285 if (!first) try stdout.writeAll(" && ");
286 first = false;
287 try stdout.print("!defined(ARCH_{s})", .{@tagName(arch)});
288 }
289
290 try stdout.writeAll("\n");
291 }
292
293 if (multi_sym.commonBinding()) |binding| {
294 switch (binding) {
295 elf.STB_GLOBAL => {
296 try stdout.print(".globl {s}\n", .{name});
297 },
298 elf.STB_WEAK => {
299 try stdout.print(".weak {s}\n", .{name});
300 },
301 else => unreachable,
302 }
303 } else if (multi_sym.isWeak64()) {
304 try stdout.print("WEAK64 {s}\n", .{name});
305 } else {
306 for (arches) |arch, i| {
307 log.info("symbol '{s}' binding on {s}: {d}", .{
308 name, @tagName(arch), multi_sym.binding[i],
309 });
310 }
311 }
312
313 switch (multi_sym.ty) {
314 elf.STT_NOTYPE => {},
315 elf.STT_FUNC => {
316 try stdout.print(".type {s}, %function;\n", .{name});
317 // omitting the size is OK for functions
318 },
319 elf.STT_OBJECT => {
320 try stdout.print(".type {s}, %object;\n", .{name});
321 if (multi_sym.commonSize()) |size| {
322 try stdout.print(".size {s}, {d}\n", .{ name, size });
323 } else if (multi_sym.isPtrSize()) {
324 try stdout.print(".size {s}, PTR_SIZE_BYTES\n", .{name});
325 } else if (multi_sym.isPtr2Size()) {
326 try stdout.print(".size {s}, PTR2_SIZE_BYTES\n", .{name});
327 } else {
328 for (arches) |arch, i| {
329 log.info("symbol '{s}' size on {s}: {d}", .{
330 name, @tagName(arch), multi_sym.size[i],
331 });
332 }
333 //try stdout.print(".size {s}, {d}\n", .{ name, size });
334 }
335 },
336 else => unreachable,
337 }
338
339 switch (multi_sym.visib) {
340 .DEFAULT => {},
341 .PROTECTED => try stdout.print(".protected {s}\n", .{name}),
342 .INTERNAL, .HIDDEN => unreachable,
343 }
344
345 try stdout.print("{s}:\n", .{name});
346 }
347
348 switch (prev_pp_state) {
349 .none => {},
350 .ptr32, .special => try stdout.writeAll("#endif\n"),
351 }
140}352}
141353
142fn parseElf(parse: Parse, comptime is_64: bool, comptime endian: builtin.Endian) !void {354fn parseElf(parse: Parse, comptime is_64: bool, comptime endian: builtin.Endian) !void {
...@@ -205,9 +417,10 @@ fn parseElf(parse: Parse, comptime is_64: bool, comptime endian: builtin.Endian)...@@ -205,9 +417,10 @@ fn parseElf(parse: Parse, comptime is_64: bool, comptime endian: builtin.Endian)
205 const visib = @intToEnum(elf.STV, @truncate(u2, sym.st_other));417 const visib = @intToEnum(elf.STV, @truncate(u2, sym.st_other));
206 const size = s(sym.st_size);418 const size = s(sym.st_size);
207419
420 if (parse.blacklist.contains(name)) continue;
421
208 if (size == 0) {422 if (size == 0) {
209 log.warn("{s}: symbol '{s}' has size 0", .{ @tagName(parse.arch), name });423 log.warn("{s}: symbol '{s}' has size 0", .{ @tagName(parse.arch), name });
210 continue;
211 }424 }
212425
213 switch (binding) {426 switch (binding) {
...@@ -245,26 +458,50 @@ fn parseElf(parse: Parse, comptime is_64: bool, comptime endian: builtin.Endian)...@@ -245,26 +458,50 @@ fn parseElf(parse: Parse, comptime is_64: bool, comptime endian: builtin.Endian)
245 if (gop.value_ptr.section != section_index_map[this_section]) {458 if (gop.value_ptr.section != section_index_map[this_section]) {
246 const sh_name = mem.sliceTo(shstrtab[s(shdrs[this_section].sh_name)..], 0);459 const sh_name = mem.sliceTo(shstrtab[s(shdrs[this_section].sh_name)..], 0);
247 fatal("symbol '{s}' in arch {s} is in section {s} but in arch {s} is in section {s}", .{460 fatal("symbol '{s}' in arch {s} is in section {s} but in arch {s} is in section {s}", .{
248 name, @tagName(parse.arch), sh_name,461 name,
249 archSetName(gop.value_ptr.present), parse.sections.keys()[gop.value_ptr.section],462 @tagName(parse.arch),
463 sh_name,
464 archSetName(gop.value_ptr.present),
465 parse.sections.keys()[gop.value_ptr.section],
250 });466 });
251 }467 }
252 if (gop.value_ptr.ty != ty) {468 if (gop.value_ptr.ty != ty) blk: {
469 if (ty == elf.STT_NOTYPE) {
470 log.warn("symbol '{s}' in arch {s} has type {d} but in arch {s} has type {d}. going with the one that is not STT_NOTYPE", .{
471 name,
472 @tagName(parse.arch),
473 ty,
474 archSetName(gop.value_ptr.present),
475 gop.value_ptr.ty,
476 });
477 break :blk;
478 }
479 if (gop.value_ptr.ty == elf.STT_NOTYPE) {
480 log.warn("symbol '{s}' in arch {s} has type {d} but in arch {s} has type {d}. going with the one that is not STT_NOTYPE", .{
481 name,
482 @tagName(parse.arch),
483 ty,
484 archSetName(gop.value_ptr.present),
485 gop.value_ptr.ty,
486 });
487 gop.value_ptr.ty = ty;
488 break :blk;
489 }
253 fatal("symbol '{s}' in arch {s} has type {d} but in arch {s} has type {d}", .{490 fatal("symbol '{s}' in arch {s} has type {d} but in arch {s} has type {d}", .{
254 name, @tagName(parse.arch), ty,491 name,
255 archSetName(gop.value_ptr.present), gop.value_ptr.ty,492 @tagName(parse.arch),
256 });493 ty,
257 }494 archSetName(gop.value_ptr.present),
258 if (gop.value_ptr.binding != binding) {495 gop.value_ptr.ty,
259 fatal("symbol '{s}' in arch {s} has binding {d} but in arch {s} has binding {d}", .{
260 name, @tagName(parse.arch), binding,
261 archSetName(gop.value_ptr.present), gop.value_ptr.binding,
262 });496 });
263 }497 }
264 if (gop.value_ptr.visib != visib) {498 if (gop.value_ptr.visib != visib) {
265 fatal("symbol '{s}' in arch {s} has visib {s} but in arch {s} has visib {s}", .{499 fatal("symbol '{s}' in arch {s} has visib {s} but in arch {s} has visib {s}", .{
266 name, @tagName(parse.arch), @tagName(visib),500 name,
267 archSetName(gop.value_ptr.present), @tagName(gop.value_ptr.visib),501 @tagName(parse.arch),
502 @tagName(visib),
503 archSetName(gop.value_ptr.present),
504 @tagName(gop.value_ptr.visib),
268 });505 });
269 }506 }
270 } else {507 } else {
...@@ -272,13 +509,14 @@ fn parseElf(parse: Parse, comptime is_64: bool, comptime endian: builtin.Endian)...@@ -272,13 +509,14 @@ fn parseElf(parse: Parse, comptime is_64: bool, comptime endian: builtin.Endian)
272 .present = [1]bool{false} ** arches.len,509 .present = [1]bool{false} ** arches.len,
273 .section = section_index_map[this_section],510 .section = section_index_map[this_section],
274 .ty = ty,511 .ty = ty,
275 .binding = binding,512 .binding = [1]u4{0} ** arches.len,
276 .visib = visib,513 .visib = visib,
277 .size = [1]u64{0} ** arches.len,514 .size = [1]u64{0} ** arches.len,
278 };515 };
279 }516 }
280 gop.value_ptr.present[archIndex(parse.arch)] = true;517 gop.value_ptr.present[archIndex(parse.arch)] = true;
281 gop.value_ptr.size[archIndex(parse.arch)] = size;518 gop.value_ptr.size[archIndex(parse.arch)] = size;
519 gop.value_ptr.binding[archIndex(parse.arch)] = binding;
282 }520 }
283}521}
284522
...@@ -291,6 +529,7 @@ fn archIndex(arch: std.Target.Cpu.Arch) u8 {...@@ -291,6 +529,7 @@ fn archIndex(arch: std.Target.Cpu.Arch) u8 {
291 .x86_64 => 3,529 .x86_64 => 3,
292 .powerpc => 4,530 .powerpc => 4,
293 .powerpc64 => 5,531 .powerpc64 => 5,
532 .aarch64 => 6,
294 else => unreachable,533 else => unreachable,
295 // zig fmt: on534 // zig fmt: on
296 };535 };
...@@ -309,3 +548,211 @@ fn fatal(comptime format: []const u8, args: anytype) noreturn {...@@ -309,3 +548,211 @@ fn fatal(comptime format: []const u8, args: anytype) noreturn {
309 log.err(format, args);548 log.err(format, args);
310 std.process.exit(1);549 std.process.exit(1);
311}550}
551
552const blacklisted_symbols = [_][]const u8{
553 "__adddf3",
554 "__addkf3",
555 "__addsf3",
556 "__addtf3",
557 "__ashldi3",
558 "__ashlti3",
559 "__ashrdi3",
560 "__ashrti3",
561 "__atomic_compare_exchange",
562 "__atomic_compare_exchange_1",
563 "__atomic_compare_exchange_2",
564 "__atomic_compare_exchange_4",
565 "__atomic_compare_exchange_8",
566 "__atomic_exchange",
567 "__atomic_exchange_1",
568 "__atomic_exchange_2",
569 "__atomic_exchange_4",
570 "__atomic_exchange_8",
571 "__atomic_fetch_add_1",
572 "__atomic_fetch_add_2",
573 "__atomic_fetch_add_4",
574 "__atomic_fetch_add_8",
575 "__atomic_fetch_and_1",
576 "__atomic_fetch_and_2",
577 "__atomic_fetch_and_4",
578 "__atomic_fetch_and_8",
579 "__atomic_fetch_nand_1",
580 "__atomic_fetch_nand_2",
581 "__atomic_fetch_nand_4",
582 "__atomic_fetch_nand_8",
583 "__atomic_fetch_or_1",
584 "__atomic_fetch_or_2",
585 "__atomic_fetch_or_4",
586 "__atomic_fetch_or_8",
587 "__atomic_fetch_sub_1",
588 "__atomic_fetch_sub_2",
589 "__atomic_fetch_sub_4",
590 "__atomic_fetch_sub_8",
591 "__atomic_fetch_xor_1",
592 "__atomic_fetch_xor_2",
593 "__atomic_fetch_xor_4",
594 "__atomic_fetch_xor_8",
595 "__atomic_load",
596 "__atomic_load_1",
597 "__atomic_load_2",
598 "__atomic_load_4",
599 "__atomic_load_8",
600 "__atomic_store",
601 "__atomic_store_1",
602 "__atomic_store_2",
603 "__atomic_store_4",
604 "__atomic_store_8",
605 "__clear_cache",
606 "__clzdi2",
607 "__clzsi2",
608 "__clzti2",
609 "__cmpdf2",
610 "__cmpsf2",
611 "__cmptf2",
612 "__ctzdi2",
613 "__ctzsi2",
614 "__ctzti2",
615 "__divdf3",
616 "__divdi3",
617 "__divkf3",
618 "__divmoddi4",
619 "__divmodsi4",
620 "__divsf3",
621 "__divsi3",
622 "__divtf3",
623 "__divti3",
624 "__dlstart",
625 "__eqdf2",
626 "__eqkf2",
627 "__eqsf2",
628 "__eqtf2",
629 "__extenddfkf2",
630 "__extenddftf2",
631 "__extendhfsf2",
632 "__extendhftf2",
633 "__extendsfdf2",
634 "__extendsfkf2",
635 "__extendsftf2",
636 "__ffsdi2",
637 "__ffssi2",
638 "__ffsti2",
639 "__fixdfdi",
640 "__fixdfsi",
641 "__fixdfti",
642 "__fixkfdi",
643 "__fixkfsi",
644 "__fixsfdi",
645 "__fixsfsi",
646 "__fixsfti",
647 "__fixtfdi",
648 "__fixtfsi",
649 "__fixtfti",
650 "__fixunsdfdi",
651 "__fixunsdfsi",
652 "__fixunsdfti",
653 "__fixunskfdi",
654 "__fixunskfsi",
655 "__fixunssfdi",
656 "__fixunssfsi",
657 "__fixunssfti",
658 "__fixunstfdi",
659 "__fixunstfsi",
660 "__fixunstfti",
661 "__floatdidf",
662 "__floatdikf",
663 "__floatdisf",
664 "__floatditf",
665 "__floatsidf",
666 "__floatsikf",
667 "__floatsisf",
668 "__floatsitf",
669 "__floattidf",
670 "__floattisf",
671 "__floattitf",
672 "__floatundidf",
673 "__floatundikf",
674 "__floatundisf",
675 "__floatunditf",
676 "__floatunsidf",
677 "__floatunsikf",
678 "__floatunsisf",
679 "__floatunsitf",
680 "__floatuntidf",
681 "__floatuntisf",
682 "__floatuntitf",
683 "__gedf2",
684 "__gekf2",
685 "__gesf2",
686 "__getf2",
687 "__gnu_f2h_ieee",
688 "__gnu_h2f_ieee",
689 "__gtdf2",
690 "__gtkf2",
691 "__gtsf2",
692 "__gttf2",
693 "__ledf2",
694 "__lekf2",
695 "__lesf2",
696 "__letf2",
697 "__lshrdi3",
698 "__lshrti3",
699 "__ltdf2",
700 "__ltkf2",
701 "__ltsf2",
702 "__lttf2",
703 "__moddi3",
704 "__modsi3",
705 "__modti3",
706 "__muldc3",
707 "__muldf3",
708 "__muldi3",
709 "__mulkf3",
710 "__mulodi4",
711 "__muloti4",
712 "__mulsc3",
713 "__mulsf3",
714 "__mulsi3",
715 "__multc3",
716 "__multf3",
717 "__multi3",
718 "__mulxc3",
719 "__nedf2",
720 "__negdf2",
721 "__negsf2",
722 "__nekf2",
723 "__nesf2",
724 "__netf2",
725 "__paritydi2",
726 "__paritysi2",
727 "__parityti2",
728 "__popcountdi2",
729 "__popcountsi2",
730 "__popcountti2",
731 "__subdf3",
732 "__subkf3",
733 "__subsf3",
734 "__subtf3",
735 "__truncdfhf2",
736 "__truncdfsf2",
737 "__trunckfdf2",
738 "__trunckfsf2",
739 "__truncsfhf2",
740 "__trunctfdf2",
741 "__trunctfhf2",
742 "__trunctfsf2",
743 "__udivdi3",
744 "__udivmoddi4",
745 "__udivmodsi4",
746 "__udivmodti4",
747 "__udivsi3",
748 "__udivti3",
749 "__umoddi3",
750 "__umodsi3",
751 "__umodti3",
752 "__unorddf2",
753 "__unordkf2",
754 "__unordsf2",
755 "__unordtf2",
756 "__zig_probe_stack",
757 "fmaq",
758};