| ... | ... | @@ -26,6 +26,8 @@ fn __clzsi2_generic(a: i32) callconv(.C) i32 { |
| 26 | 26 | } |
| 27 | 27 | |
| 28 | 28 | fn __clzsi2_thumb1() callconv(.Naked) void { |
| 29 | @setRuntimeSafety(false); |
| 30 | |
| 29 | 31 | // Similar to the generic version with the last two rounds replaced by a LUT |
| 30 | 32 | asm volatile ( |
| 31 | 33 | \\ movs r1, #32 |
| ... | ... | @@ -58,6 +60,8 @@ fn __clzsi2_thumb1() callconv(.Naked) void { |
| 58 | 60 | } |
| 59 | 61 | |
| 60 | 62 | fn __clzsi2_arm32() callconv(.Naked) void { |
| 63 | @setRuntimeSafety(false); |
| 64 | |
| 61 | 65 | asm volatile ( |
| 62 | 66 | \\ // Assumption: n != 0 |
| 63 | 67 | \\ // r0: n |
| ... | ... | @@ -104,13 +108,22 @@ fn __clzsi2_arm32() callconv(.Naked) void { |
| 104 | 108 | unreachable; |
| 105 | 109 | } |
| 106 | 110 | |
| 107 | | pub const __clzsi2 = switch (std.Target.current.cpu.arch) { |
| 108 | | .arm, .armeb => if (std.Target.arm.featureSetHas(std.Target.current.cpu.features, .noarm)) |
| 109 | | __clzsi2_thumb1 |
| 110 | | else |
| 111 | | __clzsi2_arm32, |
| 112 | | .thumb, .thumbeb => __clzsi2_thumb1, |
| 113 | | else => __clzsi2_generic, |
| 111 | pub const __clzsi2 = impl: { |
| 112 | switch (std.Target.current.cpu.arch) { |
| 113 | .arm, .armeb, .thumb, .thumbeb => { |
| 114 | const use_thumb1 = |
| 115 | (std.Target.current.cpu.arch.isThumb() or |
| 116 | std.Target.arm.featureSetHas(std.Target.current.cpu.features, .noarm)) and |
| 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 | 129 | test "test clzsi2" { |