Created
February 9, 2020 14:56
-
-
Save mlarouche/7b966b42a8ddd844cb610c3fa16189b0 to your computer and use it in GitHub Desktop.
__divsi3 and __udivsi3 issues on Thumb1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const GBA = @import("gba").GBA; | |
const LCD = @import("gba").LCD; | |
const Debug = @import("gba").Debug; | |
const builtin = @import("std").builtin; | |
const TypeInfo = builtin.TypeInfo; | |
const alignForward = @import("std").mem.alignForward; | |
export var gameHeader linksection(".gbaheader") = GBA.Header.setup("FIXEDPOINT", "AODE", "00", 0); | |
pub fn FixedPoint(comptime isSigned: bool, comptime integral: comptime_int, comptime fractional: comptime_int) type { | |
return packed struct { | |
storage: StorageType = undefined, | |
const StorageType = @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = isSigned, .bits = integral + fractional } }); | |
const UnsignedStorageType = @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = false, .bits = integral + fractional } }); | |
const IntegerType = @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = isSigned, .bits = alignForward(integral + fractional, 8) } }); | |
const UnsignedIntegerType = @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = false, .bits = alignForward(integral + fractional, 8) } }); | |
const MaxIntegerType = if (isSigned) i32 else u32; | |
const Shift = fractional; | |
const Scale = 1 << fractional; | |
const IntegralMask = (1 << integral) - 1; | |
const FractionalMask = (1 << fractional) - 1; | |
const Self = @This(); | |
pub inline fn fromInt(value: IntegerType) Self { | |
return Self{ | |
.storage = @truncate(StorageType, value << Shift), | |
}; | |
} | |
pub inline fn fromF32(comptime value: f32) Self { | |
return Self{ | |
.storage = @floatToInt(StorageType, value * @intToFloat(f32, Scale)), | |
}; | |
} | |
pub inline fn setInt(self: *Self, value: IntegerType) void { | |
self.storage = @truncate(StorageType, value << Shift); | |
} | |
pub inline fn setF32(self: *Self, comptime value: f32) void { | |
self.storage = @floatToInt(StorageType, value * Scale); | |
} | |
pub inline fn integral(self: Self) UnsignedIntegerType { | |
return @intCast(UnsignedIntegerType, (@bitCast(UnsignedStorageType, self.storage) >> Shift) & (IntegralMask)); | |
} | |
pub inline fn fractional(self: Self) UnsignedIntegerType { | |
return @intCast(UnsignedIntegerType, @bitCast(UnsignedStorageType, self.storage) & FractionalMask); | |
} | |
pub inline fn toF32(self: Self) f32 { | |
return @intToFloat(f32, self.storage) / Scale; | |
} | |
pub inline fn add(left: Self, right: Self) Self { | |
return Self{ | |
.storage = left.storage + right.storage, | |
}; | |
} | |
pub inline fn addSelf(left: *Self, right: Self) void { | |
left.storage = left.storage + right.storage; | |
} | |
pub inline fn sub(left: Self, right: Self) Self { | |
return Self{ | |
.storage = left.storage - right.storage, | |
}; | |
} | |
pub inline fn subSelf(left: *Self, right: Self) void { | |
left.storage = left.storage - right.storage; | |
} | |
pub inline fn mul(left: Self, right: Self) Self { | |
return Self{ | |
.storage = @truncate(StorageType, (@intCast(MaxIntegerType, left.storage) * @intCast(MaxIntegerType, right.storage)) >> Shift), | |
}; | |
} | |
pub inline fn mulSelf(left: *Self, right: Self) void { | |
left.storage = @truncate(StorageType, (@intCast(MaxIntegerType, left.storage) * @intCast(MaxIntegerType, right.storage)) >> Shift); | |
} | |
pub inline fn div(left: Self, right: Self) Self { | |
return Self{ | |
.storage = @truncate(StorageType, @divTrunc(@intCast(MaxIntegerType, left.storage) * Scale, @intCast(MaxIntegerType, right.storage))), | |
}; | |
} | |
pub inline fn divSelf(left: *Self, right: Self) void { | |
left.storage = @truncate(StorageType, @divTrunc(@intCast(MaxIntegerType, left.storage) * Scale, @intCast(MaxIntegerType, right.storage))); | |
} | |
pub const toInt = comptime if (isSigned) toIntSigned else toIntUnsigned; | |
fn toIntUnsigned(self: Self) IntegerType { | |
return self.storage >> Shift; | |
} | |
fn toIntSigned(self: Self) IntegerType { | |
return @divFloor(self.storage, Scale); | |
} | |
}; | |
} | |
var origin:i16 = 0; | |
pub fn main() noreturn { | |
LCD.setupDisplayControl(.{ | |
.objVramCharacterMapping = .OneDimension, | |
.objectLayer = .Show, | |
}); | |
Debug.init(); | |
const MyFixedPoint = FixedPoint(true, 8, 8); | |
var originPtr = @ptrCast(*volatile i16, &origin); | |
originPtr.* = 8; | |
var fixed:MyFixedPoint = MyFixedPoint.fromInt(originPtr.*); | |
Debug.print("fixed={}", .{fixed.storage}) catch unreachable; | |
var fixed2 = MyFixedPoint.fromF32(2.5); | |
Debug.print("fixed2={}", .{fixed2.storage}) catch unreachable; | |
var result = fixed.div(fixed2); | |
Debug.print("result={}.{} / {}", .{result.toInt(), result.fractional(), result.storage}) catch unreachable; | |
while (true) {} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const builtin = @import("std").builtin; | |
const TypeInfo = builtin.TypeInfo; | |
const alignForward = @import("std").mem.alignForward; | |
const std = @import("std"); | |
pub fn FixedPoint(comptime isSigned: bool, comptime integral: comptime_int, comptime fractional: comptime_int) type { | |
return packed struct { | |
storage: StorageType = undefined, | |
const StorageType = @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = isSigned, .bits = integral + fractional } }); | |
const UnsignedStorageType = @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = false, .bits = integral + fractional } }); | |
const IntegerType = @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = isSigned, .bits = alignForward(integral + fractional, 8) } }); | |
const UnsignedIntegerType = @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = false, .bits = alignForward(integral + fractional, 8) } }); | |
const MaxIntegerType = if (isSigned) i32 else u32; | |
const Shift = fractional; | |
const Scale = 1 << fractional; | |
const IntegralMask = (1 << integral) - 1; | |
const FractionalMask = (1 << fractional) - 1; | |
const Self = @This(); | |
pub inline fn fromInt(value: IntegerType) Self { | |
return Self{ | |
.storage = @truncate(StorageType, value << Shift), | |
}; | |
} | |
pub inline fn fromF32(comptime value: f32) Self { | |
return Self{ | |
.storage = @floatToInt(StorageType, value * @intToFloat(f32, Scale)), | |
}; | |
} | |
pub inline fn setInt(self: *Self, value: IntegerType) void { | |
self.storage = @truncate(StorageType, value << Shift); | |
} | |
pub inline fn setF32(self: *Self, comptime value: f32) void { | |
self.storage = @floatToInt(StorageType, value * Scale); | |
} | |
pub inline fn integral(self: Self) UnsignedIntegerType { | |
return @intCast(UnsignedIntegerType, (@bitCast(UnsignedStorageType, self.storage) >> Shift) & (IntegralMask)); | |
} | |
pub inline fn fractional(self: Self) UnsignedIntegerType { | |
return @intCast(UnsignedIntegerType, @bitCast(UnsignedStorageType, self.storage) & FractionalMask); | |
} | |
pub inline fn toF32(self: Self) f32 { | |
return @intToFloat(f32, self.storage) / Scale; | |
} | |
pub inline fn add(left: Self, right: Self) Self { | |
return Self{ | |
.storage = left.storage + right.storage, | |
}; | |
} | |
pub inline fn addSelf(left: *Self, right: Self) void { | |
left.storage = left.storage + right.storage; | |
} | |
pub inline fn sub(left: Self, right: Self) Self { | |
return Self{ | |
.storage = left.storage - right.storage, | |
}; | |
} | |
pub inline fn subSelf(left: *Self, right: Self) void { | |
left.storage = left.storage - right.storage; | |
} | |
pub inline fn mul(left: Self, right: Self) Self { | |
return Self{ | |
.storage = @truncate(StorageType, (@intCast(MaxIntegerType, left.storage) * @intCast(MaxIntegerType, right.storage)) >> Shift), | |
}; | |
} | |
pub inline fn mulSelf(left: *Self, right: Self) void { | |
left.storage = @truncate(StorageType, (@intCast(MaxIntegerType, left.storage) * @intCast(MaxIntegerType, right.storage)) >> Shift); | |
} | |
pub inline fn div(left: Self, right: Self) Self { | |
return Self{ | |
.storage = @truncate(StorageType, @divTrunc(@intCast(MaxIntegerType, left.storage) * Scale, @intCast(MaxIntegerType, right.storage))), | |
}; | |
} | |
pub inline fn divSelf(left: *Self, right: Self) void { | |
left.storage = @truncate(StorageType, @divTrunc(@intCast(MaxIntegerType, left.storage) * Scale, @intCast(MaxIntegerType, right.storage))); | |
} | |
pub const toInt = comptime if (isSigned) toIntSigned else toIntUnsigned; | |
fn toIntUnsigned(self: Self) IntegerType { | |
return self.storage >> Shift; | |
} | |
fn toIntSigned(self: Self) IntegerType { | |
return @divFloor(self.storage, Scale); | |
} | |
}; | |
} | |
var origin:i16 = 0; | |
pub fn main() void { | |
const MyFixedPoint = FixedPoint(true, 8, 8); | |
var originPtr = @ptrCast(*volatile i16, &origin); | |
originPtr.* = 8; | |
var fixed:MyFixedPoint = MyFixedPoint.fromInt(originPtr.*); | |
std.debug.warn("fixed={}\n", .{fixed.storage}); | |
var fixed2 = MyFixedPoint.fromF32(2.5); | |
std.debug.warn("fixed2={}\n", .{fixed2.storage}); | |
var result = fixed.div(fixed2); | |
std.debug.warn("result={}.{} / {}\n", .{result.toInt(), result.fractional(), result.storage}); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fixed=2048 | |
fixed2=640 | |
result=3.51 / 819 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[INFO] GBA Debug: fixed=2048 | |
[INFO] GBA Debug: fixed2=640 | |
[INFO] GBA Debug: result=0.127 / 127 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment