mirror of
https://github.com/ziglang/zig.git
synced 2025-12-18 12:13:20 +00:00
stage2 AArch64: implement strb and strh
This commit is contained in:
parent
501b4aff99
commit
e088a17f56
@ -3111,7 +3111,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
|||||||
const adj_off = stack_offset + abi_size;
|
const adj_off = stack_offset + abi_size;
|
||||||
|
|
||||||
switch (abi_size) {
|
switch (abi_size) {
|
||||||
4, 8 => {
|
1, 2, 4, 8 => {
|
||||||
const offset = if (math.cast(i9, adj_off)) |imm|
|
const offset = if (math.cast(i9, adj_off)) |imm|
|
||||||
Instruction.LoadStoreOffset.imm_post_index(-imm)
|
Instruction.LoadStoreOffset.imm_post_index(-imm)
|
||||||
else |_|
|
else |_|
|
||||||
@ -3121,8 +3121,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
|||||||
.aarch64_32 => .w29,
|
.aarch64_32 => .w29,
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
|
const str = switch (abi_size) {
|
||||||
|
1 => Instruction.strb,
|
||||||
|
2 => Instruction.strh,
|
||||||
|
4, 8 => Instruction.str,
|
||||||
|
else => unreachable, // unexpected abi size
|
||||||
|
};
|
||||||
|
|
||||||
writeInt(u32, try self.code.addManyAsArray(4), Instruction.str(reg, rn, .{
|
writeInt(u32, try self.code.addManyAsArray(4), str(reg, rn, .{
|
||||||
.offset = offset,
|
.offset = offset,
|
||||||
}).toU32());
|
}).toU32());
|
||||||
},
|
},
|
||||||
|
|||||||
@ -484,7 +484,23 @@ pub const Instruction = union(enum) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fn loadStoreRegister(rt: Register, rn: Register, offset: LoadStoreOffset, load: bool) Instruction {
|
/// Which kind of load/store to perform
|
||||||
|
const LoadStoreVariant = enum {
|
||||||
|
/// 32-bit or 64-bit
|
||||||
|
normal,
|
||||||
|
/// 16-bit
|
||||||
|
half,
|
||||||
|
/// 8-bit
|
||||||
|
byte,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn loadStoreRegister(
|
||||||
|
rt: Register,
|
||||||
|
rn: Register,
|
||||||
|
offset: LoadStoreOffset,
|
||||||
|
variant: LoadStoreVariant,
|
||||||
|
load: bool,
|
||||||
|
) Instruction {
|
||||||
const off = offset.toU12();
|
const off = offset.toU12();
|
||||||
const op1: u2 = blk: {
|
const op1: u2 = blk: {
|
||||||
switch (offset) {
|
switch (offset) {
|
||||||
@ -497,35 +513,27 @@ pub const Instruction = union(enum) {
|
|||||||
break :blk 0b00;
|
break :blk 0b00;
|
||||||
};
|
};
|
||||||
const opc: u2 = if (load) 0b01 else 0b00;
|
const opc: u2 = if (load) 0b01 else 0b00;
|
||||||
switch (rt.size()) {
|
return Instruction{
|
||||||
32 => {
|
.LoadStoreRegister = .{
|
||||||
return Instruction{
|
.rt = rt.id(),
|
||||||
.LoadStoreRegister = .{
|
.rn = rn.id(),
|
||||||
.rt = rt.id(),
|
.offset = off,
|
||||||
.rn = rn.id(),
|
.opc = opc,
|
||||||
.offset = offset.toU12(),
|
.op1 = op1,
|
||||||
.opc = opc,
|
.v = 0,
|
||||||
.op1 = op1,
|
.size = blk: {
|
||||||
.v = 0,
|
switch (variant) {
|
||||||
.size = 0b10,
|
.normal => switch (rt.size()) {
|
||||||
},
|
32 => break :blk 0b10,
|
||||||
};
|
64 => break :blk 0b11,
|
||||||
|
else => unreachable, // unexpected register size
|
||||||
|
},
|
||||||
|
.half => break :blk 0b01,
|
||||||
|
.byte => break :blk 0b00,
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
64 => {
|
};
|
||||||
return Instruction{
|
|
||||||
.LoadStoreRegister = .{
|
|
||||||
.rt = rt.id(),
|
|
||||||
.rn = rn.id(),
|
|
||||||
.offset = offset.toU12(),
|
|
||||||
.opc = opc,
|
|
||||||
.op1 = op1,
|
|
||||||
.v = 0,
|
|
||||||
.size = 0b11,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
else => unreachable, // unexpected register size
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn loadStorePairOfRegisters(
|
fn loadStorePairOfRegisters(
|
||||||
@ -748,7 +756,7 @@ pub const Instruction = union(enum) {
|
|||||||
|
|
||||||
pub fn ldr(rt: Register, args: LdrArgs) Instruction {
|
pub fn ldr(rt: Register, args: LdrArgs) Instruction {
|
||||||
switch (args) {
|
switch (args) {
|
||||||
.register => |info| return loadStoreRegister(rt, info.rn, info.offset, true),
|
.register => |info| return loadStoreRegister(rt, info.rn, info.offset, .normal, true),
|
||||||
.literal => |literal| return loadLiteral(rt, literal),
|
.literal => |literal| return loadLiteral(rt, literal),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -758,7 +766,15 @@ pub const Instruction = union(enum) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub fn str(rt: Register, rn: Register, args: StrArgs) Instruction {
|
pub fn str(rt: Register, rn: Register, args: StrArgs) Instruction {
|
||||||
return loadStoreRegister(rt, rn, args.offset, false);
|
return loadStoreRegister(rt, rn, args.offset, .normal, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn strh(rt: Register, rn: Register, args: StrArgs) Instruction {
|
||||||
|
return loadStoreRegister(rt, rn, args.offset, .half, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn strb(rt: Register, rn: Register, args: StrArgs) Instruction {
|
||||||
|
return loadStoreRegister(rt, rn, args.offset, .byte, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load or store pair of registers
|
// Load or store pair of registers
|
||||||
@ -996,6 +1012,14 @@ test "serialize instructions" {
|
|||||||
.inst = Instruction.str(.x2, .x1, .{ .offset = Instruction.LoadStoreOffset.reg(.x3) }),
|
.inst = Instruction.str(.x2, .x1, .{ .offset = Instruction.LoadStoreOffset.reg(.x3) }),
|
||||||
.expected = 0b11_111_0_00_00_1_00011_011_0_10_00001_00010,
|
.expected = 0b11_111_0_00_00_1_00011_011_0_10_00001_00010,
|
||||||
},
|
},
|
||||||
|
.{ // strh w0, [x1]
|
||||||
|
.inst = Instruction.strh(.w0, .x1, .{}),
|
||||||
|
.expected = 0b01_111_0_01_00_000000000000_00001_00000,
|
||||||
|
},
|
||||||
|
.{ // strb w8, [x9]
|
||||||
|
.inst = Instruction.strb(.w8, .x9, .{}),
|
||||||
|
.expected = 0b00_111_0_01_00_000000000000_01001_01000,
|
||||||
|
},
|
||||||
.{ // adr x2, #0x8
|
.{ // adr x2, #0x8
|
||||||
.inst = Instruction.adr(.x2, 0x8),
|
.inst = Instruction.adr(.x2, 0x8),
|
||||||
.expected = 0b0_00_10000_0000000000000000010_00010,
|
.expected = 0b0_00_10000_0000000000000000010_00010,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user