aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjoachimschmidt557 <joachim.schmidt557@outlook.com>2022-01-13 17:45:19 +0100
committerJakub Konka <kubkon@jakubkonka.com>2022-01-14 00:46:07 +0100
commit7e76aab98abe94e01cfd8b01ce288360ed67dbc7 (patch)
tree8a6f96e1edca471e5571f60be72e5c3b659cd37d
parente945619728110affb389402ff1ce06d65470cdd2 (diff)
downloadzig-7e76aab98abe94e01cfd8b01ce288360ed67dbc7.tar.gz
zig-7e76aab98abe94e01cfd8b01ce288360ed67dbc7.zip
stage2 AArch64: split ldr/str into {ldr,str}_register and _immediate
-rw-r--r--src/arch/aarch64/Emit.zig80
-rw-r--r--src/arch/aarch64/Mir.zig66
-rw-r--r--src/arch/aarch64/bits.zig96
3 files changed, 132 insertions, 110 deletions
diff --git a/src/arch/aarch64/Emit.zig b/src/arch/aarch64/Emit.zig
index d51618b2f0..3528bae709 100644
--- a/src/arch/aarch64/Emit.zig
+++ b/src/arch/aarch64/Emit.zig
@@ -112,12 +112,19 @@ pub fn emitMir(
.strb_stack => try emit.mirLoadStoreStack(inst),
.strh_stack => try emit.mirLoadStoreStack(inst),
- .ldr => try emit.mirLoadStoreRegister(inst),
- .ldrb => try emit.mirLoadStoreRegister(inst),
- .ldrh => try emit.mirLoadStoreRegister(inst),
- .str => try emit.mirLoadStoreRegister(inst),
- .strb => try emit.mirLoadStoreRegister(inst),
- .strh => try emit.mirLoadStoreRegister(inst),
+ .ldr_register => try emit.mirLoadStoreRegisterRegister(inst),
+ .ldrb_register => try emit.mirLoadStoreRegisterRegister(inst),
+ .ldrh_register => try emit.mirLoadStoreRegisterRegister(inst),
+ .str_register => try emit.mirLoadStoreRegisterRegister(inst),
+ .strb_register => try emit.mirLoadStoreRegisterRegister(inst),
+ .strh_register => try emit.mirLoadStoreRegisterRegister(inst),
+
+ .ldr_immediate => try emit.mirLoadStoreRegisterImmediate(inst),
+ .ldrb_immediate => try emit.mirLoadStoreRegisterImmediate(inst),
+ .ldrh_immediate => try emit.mirLoadStoreRegisterImmediate(inst),
+ .str_immediate => try emit.mirLoadStoreRegisterImmediate(inst),
+ .strb_immediate => try emit.mirLoadStoreRegisterImmediate(inst),
+ .strh_immediate => try emit.mirLoadStoreRegisterImmediate(inst),
.mov_register => try emit.mirMoveRegister(inst),
.mov_to_from_sp => try emit.mirMoveRegister(inst),
@@ -737,41 +744,38 @@ fn mirLoadStoreStack(emit: *Emit, inst: Mir.Inst.Index) !void {
}
}
-fn mirLoadStoreRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
+fn mirLoadStoreRegisterImmediate(emit: *Emit, inst: Mir.Inst.Index) !void {
const tag = emit.mir.instructions.items(.tag)[inst];
- const load_store_register = emit.mir.instructions.items(.data)[inst].load_store_register;
+ const load_store_register_immediate = emit.mir.instructions.items(.data)[inst].load_store_register_immediate;
+ const rt = load_store_register_immediate.rt;
+ const rn = load_store_register_immediate.rn;
+ const offset = Instruction.LoadStoreOffset{ .immediate = load_store_register_immediate.offset };
switch (tag) {
- .ldr => try emit.writeInstruction(Instruction.ldr(
- load_store_register.rt,
- load_store_register.rn,
- load_store_register.offset,
- )),
- .ldrb => try emit.writeInstruction(Instruction.ldrb(
- load_store_register.rt,
- load_store_register.rn,
- load_store_register.offset,
- )),
- .ldrh => try emit.writeInstruction(Instruction.ldrh(
- load_store_register.rt,
- load_store_register.rn,
- load_store_register.offset,
- )),
- .str => try emit.writeInstruction(Instruction.str(
- load_store_register.rt,
- load_store_register.rn,
- load_store_register.offset,
- )),
- .strb => try emit.writeInstruction(Instruction.strb(
- load_store_register.rt,
- load_store_register.rn,
- load_store_register.offset,
- )),
- .strh => try emit.writeInstruction(Instruction.strh(
- load_store_register.rt,
- load_store_register.rn,
- load_store_register.offset,
- )),
+ .ldr_immediate => try emit.writeInstruction(Instruction.ldr(rt, rn, offset)),
+ .ldrb_immediate => try emit.writeInstruction(Instruction.ldrb(rt, rn, offset)),
+ .ldrh_immediate => try emit.writeInstruction(Instruction.ldrh(rt, rn, offset)),
+ .str_immediate => try emit.writeInstruction(Instruction.str(rt, rn, offset)),
+ .strb_immediate => try emit.writeInstruction(Instruction.strb(rt, rn, offset)),
+ .strh_immediate => try emit.writeInstruction(Instruction.strh(rt, rn, offset)),
+ else => unreachable,
+ }
+}
+
+fn mirLoadStoreRegisterRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
+ const tag = emit.mir.instructions.items(.tag)[inst];
+ const load_store_register_register = emit.mir.instructions.items(.data)[inst].load_store_register_register;
+ const rt = load_store_register_register.rt;
+ const rn = load_store_register_register.rn;
+ const offset = Instruction.LoadStoreOffset{ .register = load_store_register_register.offset };
+
+ switch (tag) {
+ .ldr_register => try emit.writeInstruction(Instruction.ldr(rt, rn, offset)),
+ .ldrb_register => try emit.writeInstruction(Instruction.ldrb(rt, rn, offset)),
+ .ldrh_register => try emit.writeInstruction(Instruction.ldrh(rt, rn, offset)),
+ .str_register => try emit.writeInstruction(Instruction.str(rt, rn, offset)),
+ .strb_register => try emit.writeInstruction(Instruction.strb(rt, rn, offset)),
+ .strh_register => try emit.writeInstruction(Instruction.strh(rt, rn, offset)),
else => unreachable,
}
}
diff --git a/src/arch/aarch64/Mir.zig b/src/arch/aarch64/Mir.zig
index 213dfa7716..5b232a08c0 100644
--- a/src/arch/aarch64/Mir.zig
+++ b/src/arch/aarch64/Mir.zig
@@ -58,19 +58,22 @@ pub const Inst = struct {
ldp,
/// Pseudo-instruction: Load from stack
ldr_stack,
- /// Load Register
- // TODO: split into ldr_immediate and ldr_register
- ldr,
+ /// Load Register (immediate)
+ ldr_immediate,
+ /// Load Register (register)
+ ldr_register,
/// Pseudo-instruction: Load byte from stack
ldrb_stack,
- /// Load Register Byte
- // TODO: split into ldrb_immediate and ldrb_register
- ldrb,
+ /// Load Register Byte (immediate)
+ ldrb_immediate,
+ /// Load Register Byte (register)
+ ldrb_register,
/// Pseudo-instruction: Load halfword from stack
ldrh_stack,
- /// Load Register Halfword
- // TODO: split into ldrh_immediate and ldrh_register
- ldrh,
+ /// Load Register Halfword (immediate)
+ ldrh_immediate,
+ /// Load Register Halfword (register)
+ ldrh_register,
/// Move (to/from SP)
mov_to_from_sp,
/// Move (register)
@@ -91,19 +94,22 @@ pub const Inst = struct {
stp,
/// Pseudo-instruction: Store to stack
str_stack,
- /// Store Register
- // TODO: split into str_immediate and str_register
- str,
+ /// Store Register (immediate)
+ str_immediate,
+ /// Store Register (register)
+ str_register,
/// Pseudo-instruction: Store byte to stack
strb_stack,
- /// Store Register Byte
- // TODO: split into strb_immediate and strb_register
- strb,
+ /// Store Register Byte (immediate)
+ strb_immediate,
+ /// Store Register Byte (register)
+ strb_register,
/// Pseudo-instruction: Store halfword to stack
strh_stack,
- /// Store Register Halfword
- // TODO: split into strh_immediate and strh_register
- strh,
+ /// Store Register Halfword (immediate)
+ strh_immediate,
+ /// Store Register Halfword (register)
+ strh_register,
/// Subtract (immediate)
sub_immediate,
/// Supervisor Call
@@ -195,13 +201,21 @@ pub const Inst = struct {
rm: Register,
cond: bits.Instruction.Condition,
},
- /// Two registers and a LoadStoreOffset
+ /// Two registers and a LoadStoreOffsetImmediate
///
/// Used by e.g. str_register
- load_store_register: struct {
+ load_store_register_immediate: struct {
rt: Register,
rn: Register,
- offset: bits.Instruction.LoadStoreOffset,
+ offset: bits.Instruction.LoadStoreOffsetImmediate,
+ },
+ /// Two registers and a LoadStoreOffsetRegister
+ ///
+ /// Used by e.g. str_register
+ load_store_register_register: struct {
+ rt: Register,
+ rn: Register,
+ offset: bits.Instruction.LoadStoreOffsetRegister,
},
/// A registers and a stack offset
///
@@ -230,11 +244,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(Inst) == 8);
- // }
- // }
+ comptime {
+ if (builtin.mode != .Debug) {
+ assert(@sizeOf(Data) == 8);
+ }
+ }
};
pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void {
diff --git a/src/arch/aarch64/bits.zig b/src/arch/aarch64/bits.zig
index 97c84f538a..10eb919cb9 100644
--- a/src/arch/aarch64/bits.zig
+++ b/src/arch/aarch64/bits.zig
@@ -521,69 +521,73 @@ pub const Instruction = union(enum) {
};
}
+ pub const LoadStoreOffsetImmediate = union(enum) {
+ post_index: i9,
+ pre_index: i9,
+ unsigned: u12,
+ };
+
+ pub const LoadStoreOffsetRegister = struct {
+ rm: u5,
+ shift: union(enum) {
+ uxtw: u2,
+ lsl: u2,
+ sxtw: u2,
+ sxtx: u2,
+ },
+ };
+
/// 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.
pub const LoadStoreOffset = union(enum) {
- Immediate: union(enum) {
- PostIndex: i9,
- PreIndex: i9,
- Unsigned: u12,
- },
- Register: struct {
- rm: u5,
- shift: union(enum) {
- Uxtw: u2,
- Lsl: u2,
- Sxtw: u2,
- Sxtx: u2,
- },
- },
+ immediate: LoadStoreOffsetImmediate,
+ register: LoadStoreOffsetRegister,
pub const none = LoadStoreOffset{
- .Immediate = .{ .Unsigned = 0 },
+ .immediate = .{ .unsigned = 0 },
};
pub fn toU12(self: LoadStoreOffset) u12 {
return switch (self) {
- .Immediate => |imm_type| switch (imm_type) {
- .PostIndex => |v| (@intCast(u12, @bitCast(u9, v)) << 2) + 1,
- .PreIndex => |v| (@intCast(u12, @bitCast(u9, v)) << 2) + 3,
- .Unsigned => |v| v,
+ .immediate => |imm_type| switch (imm_type) {
+ .post_index => |v| (@intCast(u12, @bitCast(u9, v)) << 2) + 1,
+ .pre_index => |v| (@intCast(u12, @bitCast(u9, v)) << 2) + 3,
+ .unsigned => |v| v,
},
- .Register => |r| switch (r.shift) {
- .Uxtw => |v| (@intCast(u12, r.rm) << 6) + (@intCast(u12, v) << 2) + 16 + 2050,
- .Lsl => |v| (@intCast(u12, r.rm) << 6) + (@intCast(u12, v) << 2) + 24 + 2050,
- .Sxtw => |v| (@intCast(u12, r.rm) << 6) + (@intCast(u12, v) << 2) + 48 + 2050,
- .Sxtx => |v| (@intCast(u12, r.rm) << 6) + (@intCast(u12, v) << 2) + 56 + 2050,
+ .register => |r| switch (r.shift) {
+ .uxtw => |v| (@intCast(u12, r.rm) << 6) + (@intCast(u12, v) << 2) + 16 + 2050,
+ .lsl => |v| (@intCast(u12, r.rm) << 6) + (@intCast(u12, v) << 2) + 24 + 2050,
+ .sxtw => |v| (@intCast(u12, r.rm) << 6) + (@intCast(u12, v) << 2) + 48 + 2050,
+ .sxtx => |v| (@intCast(u12, r.rm) << 6) + (@intCast(u12, v) << 2) + 56 + 2050,
},
};
}
pub fn imm(offset: u12) LoadStoreOffset {
return .{
- .Immediate = .{ .Unsigned = offset },
+ .immediate = .{ .unsigned = offset },
};
}
pub fn imm_post_index(offset: i9) LoadStoreOffset {
return .{
- .Immediate = .{ .PostIndex = offset },
+ .immediate = .{ .post_index = offset },
};
}
pub fn imm_pre_index(offset: i9) LoadStoreOffset {
return .{
- .Immediate = .{ .PreIndex = offset },
+ .immediate = .{ .pre_index = offset },
};
}
pub fn reg(rm: Register) LoadStoreOffset {
return .{
- .Register = .{
+ .register = .{
.rm = rm.id(),
.shift = .{
- .Lsl = 0,
+ .lsl = 0,
},
},
};
@@ -592,10 +596,10 @@ pub const Instruction = union(enum) {
pub fn reg_uxtw(rm: Register, shift: u2) LoadStoreOffset {
assert(rm.size() == 32 and (shift == 0 or shift == 2));
return .{
- .Register = .{
+ .register = .{
.rm = rm.id(),
.shift = .{
- .Uxtw = shift,
+ .uxtw = shift,
},
},
};
@@ -604,10 +608,10 @@ pub const Instruction = union(enum) {
pub fn reg_lsl(rm: Register, shift: u2) LoadStoreOffset {
assert(rm.size() == 64 and (shift == 0 or shift == 3));
return .{
- .Register = .{
+ .register = .{
.rm = rm.id(),
.shift = .{
- .Lsl = shift,
+ .lsl = shift,
},
},
};
@@ -616,10 +620,10 @@ pub const Instruction = union(enum) {
pub fn reg_sxtw(rm: Register, shift: u2) LoadStoreOffset {
assert(rm.size() == 32 and (shift == 0 or shift == 2));
return .{
- .Register = .{
+ .register = .{
.rm = rm.id(),
.shift = .{
- .Sxtw = shift,
+ .sxtw = shift,
},
},
};
@@ -628,10 +632,10 @@ pub const Instruction = union(enum) {
pub fn reg_sxtx(rm: Register, shift: u2) LoadStoreOffset {
assert(rm.size() == 64 and (shift == 0 or shift == 3));
return .{
- .Register = .{
+ .register = .{
.rm = rm.id(),
.shift = .{
- .Sxtx = shift,
+ .sxtx = shift,
},
},
};
@@ -663,8 +667,8 @@ pub const Instruction = union(enum) {
const off = offset.toU12();
const op1: u2 = blk: {
switch (offset) {
- .Immediate => |imm| switch (imm) {
- .Unsigned => break :blk 0b01,
+ .immediate => |imm| switch (imm) {
+ .unsigned => break :blk 0b01,
else => {},
},
else => {},
@@ -1023,26 +1027,26 @@ pub const Instruction = union(enum) {
pub const LoadStorePairOffset = struct {
encoding: enum(u2) {
- PostIndex = 0b01,
- Signed = 0b10,
- PreIndex = 0b11,
+ post_index = 0b01,
+ signed = 0b10,
+ pre_index = 0b11,
},
offset: i9,
pub fn none() LoadStorePairOffset {
- return .{ .encoding = .Signed, .offset = 0 };
+ return .{ .encoding = .signed, .offset = 0 };
}
pub fn post_index(imm: i9) LoadStorePairOffset {
- return .{ .encoding = .PostIndex, .offset = imm };
+ return .{ .encoding = .post_index, .offset = imm };
}
pub fn pre_index(imm: i9) LoadStorePairOffset {
- return .{ .encoding = .PreIndex, .offset = imm };
+ return .{ .encoding = .pre_index, .offset = imm };
}
pub fn signed(imm: i9) LoadStorePairOffset {
- return .{ .encoding = .Signed, .offset = imm };
+ return .{ .encoding = .signed, .offset = imm };
}
};