mirror of
https://github.com/ziglang/zig.git
synced 2026-01-10 09:25:11 +00:00
stage2 ARM: reduce Mir.Inst.Data to 8 bytes
This commit is contained in:
parent
139b731d82
commit
528008a981
@ -118,8 +118,6 @@ pub const Inst = struct {
|
||||
/// All instructions have a 8-byte payload, which is contained within
|
||||
/// this union. `Tag` determines which union field is active, as well as
|
||||
/// how to interpret the data within.
|
||||
// TODO flatten down Data (remove use of tagged unions) to make it
|
||||
// 8 bytes only
|
||||
pub const Data = union {
|
||||
/// No additional data
|
||||
///
|
||||
@ -231,11 +229,11 @@ pub const Inst = struct {
|
||||
|
||||
// Make sure we don't accidentally make instructions bigger than expected.
|
||||
// Note that in Debug builds, Zig is allowed to insert a secret field for safety checks.
|
||||
// comptime {
|
||||
// if (builtin.mode != .Debug) {
|
||||
// assert(@sizeOf(Data) == 8);
|
||||
// }
|
||||
// }
|
||||
comptime {
|
||||
if (builtin.mode != .Debug) {
|
||||
assert(@sizeOf(Data) == 8);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void {
|
||||
|
||||
@ -469,6 +469,23 @@ pub const Instruction = union(enum) {
|
||||
}
|
||||
};
|
||||
|
||||
pub const AddressingMode = enum {
|
||||
/// [<Rn>, <offset>]
|
||||
///
|
||||
/// Address = Rn + offset
|
||||
offset,
|
||||
/// [<Rn>, <offset>]!
|
||||
///
|
||||
/// Address = Rn + offset
|
||||
/// Rn = Rn + offset
|
||||
pre_index,
|
||||
/// [<Rn>], <offset>
|
||||
///
|
||||
/// Address = Rn
|
||||
/// Rn = Rn + offset
|
||||
post_index,
|
||||
};
|
||||
|
||||
/// Represents the offset operand of a load or store
|
||||
/// instruction. Data can be loaded from memory with either an
|
||||
/// immediate offset or an offset that is stored in some register.
|
||||
@ -730,10 +747,9 @@ pub const Instruction = union(enum) {
|
||||
rd: Register,
|
||||
rn: Register,
|
||||
offset: Offset,
|
||||
pre_index: bool,
|
||||
mode: AddressingMode,
|
||||
positive: bool,
|
||||
byte_word: u1,
|
||||
write_back: bool,
|
||||
load_store: u1,
|
||||
) Instruction {
|
||||
return Instruction{
|
||||
@ -743,10 +759,16 @@ pub const Instruction = union(enum) {
|
||||
.rd = rd.id(),
|
||||
.offset = offset.toU12(),
|
||||
.load_store = load_store,
|
||||
.write_back = @boolToInt(write_back),
|
||||
.write_back = switch (mode) {
|
||||
.offset => 0b0,
|
||||
.pre_index, .post_index => 0b1,
|
||||
},
|
||||
.byte_word = byte_word,
|
||||
.up_down = @boolToInt(positive),
|
||||
.pre_post = @boolToInt(pre_index),
|
||||
.pre_post = switch (mode) {
|
||||
.offset, .pre_index => 0b1,
|
||||
.post_index => 0b0,
|
||||
},
|
||||
.imm = @boolToInt(offset != .immediate),
|
||||
},
|
||||
};
|
||||
@ -754,9 +776,8 @@ pub const Instruction = union(enum) {
|
||||
|
||||
fn extraLoadStore(
|
||||
cond: Condition,
|
||||
pre_index: bool,
|
||||
mode: AddressingMode,
|
||||
positive: bool,
|
||||
write_back: bool,
|
||||
o1: u1,
|
||||
op2: u2,
|
||||
rn: Register,
|
||||
@ -780,10 +801,16 @@ pub const Instruction = union(enum) {
|
||||
.rt = rt.id(),
|
||||
.rn = rn.id(),
|
||||
.o1 = o1,
|
||||
.write_back = @boolToInt(write_back),
|
||||
.write_back = switch (mode) {
|
||||
.offset => 0b0,
|
||||
.pre_index, .post_index => 0b1,
|
||||
},
|
||||
.imm = @boolToInt(offset == .immediate),
|
||||
.up_down = @boolToInt(positive),
|
||||
.pre_index = @boolToInt(pre_index),
|
||||
.pre_index = switch (mode) {
|
||||
.offset, .pre_index => 0b1,
|
||||
.post_index => 0b0,
|
||||
},
|
||||
.cond = @enumToInt(cond),
|
||||
},
|
||||
};
|
||||
@ -1091,51 +1118,49 @@ pub const Instruction = union(enum) {
|
||||
// Single data transfer
|
||||
|
||||
pub const OffsetArgs = struct {
|
||||
pre_index: bool = true,
|
||||
mode: AddressingMode = .offset,
|
||||
positive: bool = true,
|
||||
offset: Offset,
|
||||
write_back: bool = false,
|
||||
};
|
||||
|
||||
pub fn ldr(cond: Condition, rd: Register, rn: Register, args: OffsetArgs) Instruction {
|
||||
return singleDataTransfer(cond, rd, rn, args.offset, args.pre_index, args.positive, 0, args.write_back, 1);
|
||||
return singleDataTransfer(cond, rd, rn, args.offset, args.mode, args.positive, 0, 1);
|
||||
}
|
||||
|
||||
pub fn ldrb(cond: Condition, rd: Register, rn: Register, args: OffsetArgs) Instruction {
|
||||
return singleDataTransfer(cond, rd, rn, args.offset, args.pre_index, args.positive, 1, args.write_back, 1);
|
||||
return singleDataTransfer(cond, rd, rn, args.offset, args.mode, args.positive, 1, 1);
|
||||
}
|
||||
|
||||
pub fn str(cond: Condition, rd: Register, rn: Register, args: OffsetArgs) Instruction {
|
||||
return singleDataTransfer(cond, rd, rn, args.offset, args.pre_index, args.positive, 0, args.write_back, 0);
|
||||
return singleDataTransfer(cond, rd, rn, args.offset, args.mode, args.positive, 0, 0);
|
||||
}
|
||||
|
||||
pub fn strb(cond: Condition, rd: Register, rn: Register, args: OffsetArgs) Instruction {
|
||||
return singleDataTransfer(cond, rd, rn, args.offset, args.pre_index, args.positive, 1, args.write_back, 0);
|
||||
return singleDataTransfer(cond, rd, rn, args.offset, args.mode, args.positive, 1, 0);
|
||||
}
|
||||
|
||||
// Extra load/store
|
||||
|
||||
pub const ExtraLoadStoreOffsetArgs = struct {
|
||||
pre_index: bool = true,
|
||||
mode: AddressingMode = .offset,
|
||||
positive: bool = true,
|
||||
offset: ExtraLoadStoreOffset,
|
||||
write_back: bool = false,
|
||||
};
|
||||
|
||||
pub fn strh(cond: Condition, rt: Register, rn: Register, args: ExtraLoadStoreOffsetArgs) Instruction {
|
||||
return extraLoadStore(cond, args.pre_index, args.positive, args.write_back, 0b0, 0b01, rn, rt, args.offset);
|
||||
return extraLoadStore(cond, args.mode, args.positive, 0b0, 0b01, rn, rt, args.offset);
|
||||
}
|
||||
|
||||
pub fn ldrh(cond: Condition, rt: Register, rn: Register, args: ExtraLoadStoreOffsetArgs) Instruction {
|
||||
return extraLoadStore(cond, args.pre_index, args.positive, args.write_back, 0b1, 0b01, rn, rt, args.offset);
|
||||
return extraLoadStore(cond, args.mode, args.positive, 0b1, 0b01, rn, rt, args.offset);
|
||||
}
|
||||
|
||||
pub fn ldrsh(cond: Condition, rt: Register, rn: Register, args: ExtraLoadStoreOffsetArgs) Instruction {
|
||||
return extraLoadStore(cond, args.pre_index, args.positive, args.write_back, 0b1, 0b11, rn, rt, args.offset);
|
||||
return extraLoadStore(cond, args.mode, args.positive, 0b1, 0b11, rn, rt, args.offset);
|
||||
}
|
||||
|
||||
pub fn ldrsb(cond: Condition, rt: Register, rn: Register, args: ExtraLoadStoreOffsetArgs) Instruction {
|
||||
return extraLoadStore(cond, args.pre_index, args.positive, args.write_back, 0b1, 0b10, rn, rt, args.offset);
|
||||
return extraLoadStore(cond, args.mode, args.positive, 0b1, 0b10, rn, rt, args.offset);
|
||||
}
|
||||
|
||||
// Block data transfer
|
||||
@ -1234,10 +1259,9 @@ pub const Instruction = union(enum) {
|
||||
} else if (args.len == 1) {
|
||||
const reg = args[0];
|
||||
return ldr(cond, reg, .sp, .{
|
||||
.pre_index = false,
|
||||
.mode = .post_index,
|
||||
.positive = true,
|
||||
.offset = Offset.imm(4),
|
||||
.write_back = false,
|
||||
});
|
||||
} else {
|
||||
var register_list: u16 = 0;
|
||||
@ -1259,10 +1283,9 @@ pub const Instruction = union(enum) {
|
||||
} else if (args.len == 1) {
|
||||
const reg = args[0];
|
||||
return str(cond, reg, .sp, .{
|
||||
.pre_index = true,
|
||||
.mode = .pre_index,
|
||||
.positive = false,
|
||||
.offset = Offset.imm(4),
|
||||
.write_back = true,
|
||||
});
|
||||
} else {
|
||||
var register_list: u16 = 0;
|
||||
@ -1447,10 +1470,9 @@ test "aliases" {
|
||||
.{ // pop { r6 }
|
||||
.actual = Instruction.pop(.al, .{.r6}),
|
||||
.expected = Instruction.ldr(.al, .r6, .sp, .{
|
||||
.pre_index = false,
|
||||
.mode = .post_index,
|
||||
.positive = true,
|
||||
.offset = Instruction.Offset.imm(4),
|
||||
.write_back = false,
|
||||
}),
|
||||
},
|
||||
.{ // pop { r1, r5 }
|
||||
@ -1460,10 +1482,9 @@ test "aliases" {
|
||||
.{ // push { r3 }
|
||||
.actual = Instruction.push(.al, .{.r3}),
|
||||
.expected = Instruction.str(.al, .r3, .sp, .{
|
||||
.pre_index = true,
|
||||
.mode = .pre_index,
|
||||
.positive = false,
|
||||
.offset = Instruction.Offset.imm(4),
|
||||
.write_back = true,
|
||||
}),
|
||||
},
|
||||
.{ // push { r0, r2 }
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user