| ... | @@ -26,6 +26,8 @@ fn __clzsi2_generic(a: i32) callconv(.C) i32 { | ... | @@ -26,6 +26,8 @@ fn __clzsi2_generic(a: i32) callconv(.C) i32 { |
| 26 | } | 26 | } |
| 27 | | 27 | |
| 28 | fn __clzsi2_thumb1() callconv(.Naked) void { | 28 | fn __clzsi2_thumb1() callconv(.Naked) void { |
| | 29 | @setRuntimeSafety(false); |
| | 30 | |
| 29 | // Similar to the generic version with the last two rounds replaced by a LUT | 31 | // Similar to the generic version with the last two rounds replaced by a LUT |
| 30 | asm volatile ( | 32 | asm volatile ( |
| 31 | \\ movs r1, #32 | 33 | \\ movs r1, #32 |
| ... | @@ -58,6 +60,8 @@ fn __clzsi2_thumb1() callconv(.Naked) void { | ... | @@ -58,6 +60,8 @@ fn __clzsi2_thumb1() callconv(.Naked) void { |
| 58 | } | 60 | } |
| 59 | | 61 | |
| 60 | fn __clzsi2_arm32() callconv(.Naked) void { | 62 | fn __clzsi2_arm32() callconv(.Naked) void { |
| | 63 | @setRuntimeSafety(false); |
| | 64 | |
| 61 | asm volatile ( | 65 | asm volatile ( |
| 62 | \\ // Assumption: n != 0 | 66 | \\ // Assumption: n != 0 |
| 63 | \\ // r0: n | 67 | \\ // r0: n |
| ... | @@ -104,13 +108,22 @@ fn __clzsi2_arm32() callconv(.Naked) void { | ... | @@ -104,13 +108,22 @@ fn __clzsi2_arm32() callconv(.Naked) void { |
| 104 | unreachable; | 108 | unreachable; |
| 105 | } | 109 | } |
| 106 | | 110 | |
| 107 | pub const __clzsi2 = switch (std.Target.current.cpu.arch) { | 111 | pub const __clzsi2 = impl: { |
| 108 | .arm, .armeb => if (std.Target.arm.featureSetHas(std.Target.current.cpu.features, .noarm)) | 112 | switch (std.Target.current.cpu.arch) { |
| 109 | __clzsi2_thumb1 | 113 | .arm, .armeb, .thumb, .thumbeb => { |
| 110 | else | 114 | const use_thumb1 = |
| 111 | __clzsi2_arm32, | 115 | (std.Target.current.cpu.arch.isThumb() or |
| 112 | .thumb, .thumbeb => __clzsi2_thumb1, | 116 | std.Target.arm.featureSetHas(std.Target.current.cpu.features, .noarm)) and |
| 113 | else => __clzsi2_generic, | 117 | !std.Target.arm.featureSetHas(std.Target.current.cpu.features, .thumb2); |
| | 118 | |
| | 119 | if (use_thumb1) break :impl __clzsi2_thumb1 |
| | 120 | // From here on we're either targeting Thumb2 or ARM. |
| | 121 | else if (!std.Target.current.cpu.arch.isThumb()) break :impl __clzsi2_arm32 |
| | 122 | // Use the generic implementation otherwise. |
| | 123 | else break :impl __clzsi2_generic; |
| | 124 | }, |
| | 125 | else => break :impl __clzsi2_generic, |
| | 126 | } |
| 114 | }; | 127 | }; |
| 115 | | 128 | |
| 116 | test "test clzsi2" { | 129 | test "test clzsi2" { |