Skip to content

Instantly share code, notes, and snippets.

@mlarouche
Created February 9, 2020 14:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mlarouche/7b966b42a8ddd844cb610c3fa16189b0 to your computer and use it in GitHub Desktop.
Save mlarouche/7b966b42a8ddd844cb610c3fa16189b0 to your computer and use it in GitHub Desktop.
__divsi3 and __udivsi3 issues on Thumb1
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) {}
}
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});
}
fixed=2048
fixed2=640
result=3.51 / 819
[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