| ... | @@ -2,204 +2,36 @@ | ... | @@ -2,204 +2,36 @@ |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const is_test = builtin.is_test; | 3 | const is_test = builtin.is_test; |
| 4 | | 4 | |
| 5 | const use_thumb_1 = usesThumb1(builtin.arch); | | |
| 6 | | | |
| 7 | const __divmodsi4 = @import("int.zig").__divmodsi4; | 5 | const __divmodsi4 = @import("int.zig").__divmodsi4; |
| 8 | const __udivmodsi4 = @import("int.zig").__udivmodsi4; | 6 | const __udivmodsi4 = @import("int.zig").__udivmodsi4; |
| 9 | const __divmoddi4 = @import("int.zig").__divmoddi4; | 7 | const __divmoddi4 = @import("int.zig").__divmoddi4; |
| 10 | const __udivmoddi4 = @import("int.zig").__udivmoddi4; | 8 | const __udivmoddi4 = @import("int.zig").__udivmoddi4; |
| 11 | | 9 | |
| 12 | fn usesThumb1(arch: builtin.Arch) bool { | 10 | extern fn memset(dest: ?[*]u8, c: u8, n: usize) ?[*]u8; |
| 13 | return switch (arch) { | 11 | extern fn memcpy(noalias dest: ?[*]u8, noalias src: ?[*]const u8, n: usize) ?[*]u8; |
| 14 | .arm => |sub_arch| switch (sub_arch) { | 12 | extern fn memmove(dest: ?[*]u8, src: ?[*]const u8, n: usize) ?[*]u8; |
| 15 | .v6m => true, | | |
| 16 | else => false, | | |
| 17 | }, | | |
| 18 | .armeb => |sub_arch| switch (sub_arch) { | | |
| 19 | .v6m => true, | | |
| 20 | else => false, | | |
| 21 | }, | | |
| 22 | .thumb => |sub_arch| switch (sub_arch) { | | |
| 23 | .v5, | | |
| 24 | .v5te, | | |
| 25 | .v4t, | | |
| 26 | .v6, | | |
| 27 | .v6m, | | |
| 28 | .v6k, | | |
| 29 | => true, | | |
| 30 | else => false, | | |
| 31 | }, | | |
| 32 | .thumbeb => |sub_arch| switch (sub_arch) { | | |
| 33 | .v5, | | |
| 34 | .v5te, | | |
| 35 | .v4t, | | |
| 36 | .v6, | | |
| 37 | .v6m, | | |
| 38 | .v6k, | | |
| 39 | => true, | | |
| 40 | else => false, | | |
| 41 | }, | | |
| 42 | else => false, | | |
| 43 | }; | | |
| 44 | } | | |
| 45 | | | |
| 46 | test "usesThumb1" { | | |
| 47 | testing.expect(usesThumb1(builtin.Arch{ .arm = .v6m })); | | |
| 48 | testing.expect(!usesThumb1(builtin.Arch{ .arm = .v5 })); | | |
| 49 | //etc. | | |
| 50 | | | |
| 51 | testing.expect(usesThumb1(builtin.Arch{ .armeb = .v6m })); | | |
| 52 | testing.expect(!usesThumb1(builtin.Arch{ .armeb = .v5 })); | | |
| 53 | //etc. | | |
| 54 | | | |
| 55 | testing.expect(usesThumb1(builtin.Arch{ .thumb = .v5 })); | | |
| 56 | testing.expect(usesThumb1(builtin.Arch{ .thumb = .v5te })); | | |
| 57 | testing.expect(usesThumb1(builtin.Arch{ .thumb = .v4t })); | | |
| 58 | testing.expect(usesThumb1(builtin.Arch{ .thumb = .v6 })); | | |
| 59 | testing.expect(usesThumb1(builtin.Arch{ .thumb = .v6k })); | | |
| 60 | testing.expect(usesThumb1(builtin.Arch{ .thumb = .v6m })); | | |
| 61 | testing.expect(!usesThumb1(builtin.Arch{ .thumb = .v6t2 })); | | |
| 62 | //etc. | | |
| 63 | | | |
| 64 | testing.expect(usesThumb1(builtin.Arch{ .thumbeb = .v5 })); | | |
| 65 | testing.expect(usesThumb1(builtin.Arch{ .thumbeb = .v5te })); | | |
| 66 | testing.expect(usesThumb1(builtin.Arch{ .thumbeb = .v4t })); | | |
| 67 | testing.expect(usesThumb1(builtin.Arch{ .thumbeb = .v6 })); | | |
| 68 | testing.expect(usesThumb1(builtin.Arch{ .thumbeb = .v6k })); | | |
| 69 | testing.expect(usesThumb1(builtin.Arch{ .thumbeb = .v6m })); | | |
| 70 | testing.expect(!usesThumb1(builtin.Arch{ .thumbeb = .v6t2 })); | | |
| 71 | //etc. | | |
| 72 | | | |
| 73 | testing.expect(!usesThumb1(builtin.Arch{ .aarch64 = .v8 })); | | |
| 74 | testing.expect(!usesThumb1(builtin.Arch{ .aarch64_be = .v8 })); | | |
| 75 | testing.expect(!usesThumb1(builtin.Arch.x86_64)); | | |
| 76 | testing.expect(!usesThumb1(builtin.Arch.riscv32)); | | |
| 77 | //etc. | | |
| 78 | } | | |
| 79 | | | |
| 80 | const use_thumb_1_pre_armv6 = usesThumb1PreArmv6(builtin.arch); | | |
| 81 | | | |
| 82 | fn usesThumb1PreArmv6(arch: builtin.Arch) bool { | | |
| 83 | return switch (arch) { | | |
| 84 | .thumb => |sub_arch| switch (sub_arch) { | | |
| 85 | .v5, .v5te, .v4t => true, | | |
| 86 | else => false, | | |
| 87 | }, | | |
| 88 | .thumbeb => |sub_arch| switch (sub_arch) { | | |
| 89 | .v5, .v5te, .v4t => true, | | |
| 90 | else => false, | | |
| 91 | }, | | |
| 92 | else => false, | | |
| 93 | }; | | |
| 94 | } | | |
| 95 | | | |
| 96 | pub fn __aeabi_memcpy() callconv(.Naked) noreturn { | | |
| 97 | @setRuntimeSafety(false); | | |
| 98 | if (use_thumb_1) { | | |
| 99 | asm volatile ( | | |
| 100 | \\ push {r7, lr} | | |
| 101 | \\ bl memcpy | | |
| 102 | \\ pop {r7, pc} | | |
| 103 | ); | | |
| 104 | } else { | | |
| 105 | asm volatile ( | | |
| 106 | \\ b memcpy | | |
| 107 | ); | | |
| 108 | } | | |
| 109 | unreachable; | | |
| 110 | } | | |
| 111 | | 13 | |
| 112 | pub fn __aeabi_memmove() callconv(.Naked) noreturn { | 14 | pub fn __aeabi_memcpy(dest: [*]u8, src: [*]u8, n: usize) callconv(.AAPCS) void { |
| 113 | @setRuntimeSafety(false); | 15 | @setRuntimeSafety(false); |
| 114 | if (use_thumb_1) { | 16 | _ = memcpy(dest, src, n); |
| 115 | asm volatile ( | | |
| 116 | \\ push {r7, lr} | | |
| 117 | \\ bl memmove | | |
| 118 | \\ pop {r7, pc} | | |
| 119 | ); | | |
| 120 | } else { | | |
| 121 | asm volatile ( | | |
| 122 | \\ b memmove | | |
| 123 | ); | | |
| 124 | } | | |
| 125 | unreachable; | | |
| 126 | } | 17 | } |
| 127 | | 18 | |
| 128 | pub fn __aeabi_memset() callconv(.Naked) noreturn { | 19 | pub fn __aeabi_memmove(dest: [*]u8, src: [*]u8, n: usize) callconv(.AAPCS) void { |
| 129 | @setRuntimeSafety(false); | 20 | @setRuntimeSafety(false); |
| 130 | if (use_thumb_1_pre_armv6) { | 21 | _ = memmove(dest, src, n); |
| 131 | asm volatile ( | | |
| 132 | \\ eors r1, r2 | | |
| 133 | \\ eors r2, r1 | | |
| 134 | \\ eors r1, r2 | | |
| 135 | \\ push {r7, lr} | | |
| 136 | \\ b memset | | |
| 137 | \\ pop {r7, pc} | | |
| 138 | ); | | |
| 139 | } else if (use_thumb_1) { | | |
| 140 | asm volatile ( | | |
| 141 | \\ mov r3, r1 | | |
| 142 | \\ mov r1, r2 | | |
| 143 | \\ mov r2, r3 | | |
| 144 | \\ push {r7, lr} | | |
| 145 | \\ b memset | | |
| 146 | \\ pop {r7, pc} | | |
| 147 | ); | | |
| 148 | } else { | | |
| 149 | asm volatile ( | | |
| 150 | \\ mov r3, r1 | | |
| 151 | \\ mov r1, r2 | | |
| 152 | \\ mov r2, r3 | | |
| 153 | \\ b memset | | |
| 154 | ); | | |
| 155 | } | | |
| 156 | unreachable; | | |
| 157 | } | 22 | } |
| 158 | | 23 | |
| 159 | pub fn __aeabi_memclr() callconv(.Naked) noreturn { | 24 | pub fn __aeabi_memset(dest: [*]u8, n: usize, c: u8) callconv(.AAPCS) void { |
| 160 | @setRuntimeSafety(false); | 25 | @setRuntimeSafety(false); |
| 161 | if (use_thumb_1_pre_armv6) { | 26 | // This is dentical to the standard `memset` definition but with the last |
| 162 | asm volatile ( | 27 | // two arguments swapped |
| 163 | \\ adds r2, r1, #0 | 28 | _ = memset(dest, c, n); |
| 164 | \\ movs r1, #0 | | |
| 165 | \\ push {r7, lr} | | |
| 166 | \\ bl memset | | |
| 167 | \\ pop {r7, pc} | | |
| 168 | ); | | |
| 169 | } else if (use_thumb_1) { | | |
| 170 | asm volatile ( | | |
| 171 | \\ mov r2, r1 | | |
| 172 | \\ movs r1, #0 | | |
| 173 | \\ push {r7, lr} | | |
| 174 | \\ bl memset | | |
| 175 | \\ pop {r7, pc} | | |
| 176 | ); | | |
| 177 | } else { | | |
| 178 | asm volatile ( | | |
| 179 | \\ mov r2, r1 | | |
| 180 | \\ movs r1, #0 | | |
| 181 | \\ b memset | | |
| 182 | ); | | |
| 183 | } | | |
| 184 | unreachable; | | |
| 185 | } | 29 | } |
| 186 | | 30 | |
| 187 | pub fn __aeabi_memcmp() callconv(.Naked) noreturn { | 31 | pub fn __aeabi_memclr(dest: [*]u8, n: usize) callconv(.AAPCS) void { |
| 188 | @setRuntimeSafety(false); | 32 | @setRuntimeSafety(false); |
| 189 | if (use_thumb_1) { | 33 | _ = memset(dest, 0, n); |
| 190 | asm volatile ( | | |
| 191 | \\ push {r7, lr} | | |
| 192 | \\ bl memcmp | | |
| 193 | \\ pop {r7, pc} | | |
| 194 | ); | | |
| 195 | } else { | | |
| 196 | asm volatile ( | | |
| 197 | \\ b memcmp | | |
| 198 | ); | | |
| 199 | } | | |
| 200 | unreachable; | | |
| 201 | } | 34 | } |
| 202 | | | |
| 203 | pub fn __aeabi_unwind_cpp_pr0() callconv(.C) void { | 35 | pub fn __aeabi_unwind_cpp_pr0() callconv(.C) void { |
| 204 | unreachable; | 36 | unreachable; |
| 205 | } | 37 | } |