authorgravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2022-04-21 04:52:50+07:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-05 19:34:04+02:00
loga00d69ea4a8c6e21ca99daa10d3b324609f3ef24
tree6bbd589fb83ee38da6438ef2977c767693912cfa
parentb6d7f63f34bbdb7c67abecbcd47389d2a3d28743

stage2: sparcv9: Implement basic stack load/stores


5 files changed, 132 insertions(+), 2 deletions(-)

src/arch/sparcv9/CodeGen.zig+72-2
...@@ -1351,7 +1351,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -1351,7 +1351,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
1351 try self.genLoad(reg, reg, i13, 0, ty.abiSize(self.target.*));1351 try self.genLoad(reg, reg, i13, 0, ty.abiSize(self.target.*));
1352 },1352 },
1353 .stack_offset => |off| {1353 .stack_offset => |off| {
1354 const simm13 = math.cast(u12, off) catch1354 const biased_offset = off + abi.stack_bias;
1355 const simm13 = math.cast(i13, biased_offset) catch
1355 return self.fail("TODO larger stack offsets", .{});1356 return self.fail("TODO larger stack offsets", .{});
1356 try self.genLoad(reg, .sp, i13, simm13, ty.abiSize(self.target.*));1357 try self.genLoad(reg, .sp, i13, simm13, ty.abiSize(self.target.*));
1357 },1358 },
...@@ -1381,11 +1382,80 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -1381,11 +1382,80 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
1381 const reg = try self.copyToTmpRegister(ty, mcv);1382 const reg = try self.copyToTmpRegister(ty, mcv);
1382 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });1383 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
1383 },1384 },
1384 .register => return self.fail("TODO implement storing types abi_size={}", .{abi_size}),1385 .register => |reg| {
1386 const biased_offset = stack_offset + abi.stack_bias;
1387 const simm13 = math.cast(i13, biased_offset) catch
1388 return self.fail("TODO larger stack offsets", .{});
1389 return self.genStore(reg, .sp, i13, simm13, abi_size);
1390 },
1385 .memory, .stack_offset => return self.fail("TODO implement memcpy", .{}),1391 .memory, .stack_offset => return self.fail("TODO implement memcpy", .{}),
1386 }1392 }
1387}1393}
13881394
1395fn genStore(self: *Self, value_reg: Register, addr_reg: Register, comptime off_type: type, off: off_type, abi_size: u64) !void {
1396 assert(off_type == Register or off_type == i13);
1397
1398 const is_imm = (off_type == i13);
1399 const rs2_or_imm = if (is_imm) .{ .imm = off } else .{ .rs2 = off };
1400
1401 switch (abi_size) {
1402 1 => {
1403 _ = try self.addInst(.{
1404 .tag = .stb,
1405 .data = .{
1406 .arithmetic_3op = .{
1407 .is_imm = is_imm,
1408 .rd = value_reg,
1409 .rs1 = addr_reg,
1410 .rs2_or_imm = rs2_or_imm,
1411 },
1412 },
1413 });
1414 },
1415 2 => {
1416 _ = try self.addInst(.{
1417 .tag = .sth,
1418 .data = .{
1419 .arithmetic_3op = .{
1420 .is_imm = is_imm,
1421 .rd = value_reg,
1422 .rs1 = addr_reg,
1423 .rs2_or_imm = rs2_or_imm,
1424 },
1425 },
1426 });
1427 },
1428 4 => {
1429 _ = try self.addInst(.{
1430 .tag = .stw,
1431 .data = .{
1432 .arithmetic_3op = .{
1433 .is_imm = is_imm,
1434 .rd = value_reg,
1435 .rs1 = addr_reg,
1436 .rs2_or_imm = rs2_or_imm,
1437 },
1438 },
1439 });
1440 },
1441 8 => {
1442 _ = try self.addInst(.{
1443 .tag = .stx,
1444 .data = .{
1445 .arithmetic_3op = .{
1446 .is_imm = is_imm,
1447 .rd = value_reg,
1448 .rs1 = addr_reg,
1449 .rs2_or_imm = rs2_or_imm,
1450 },
1451 },
1452 });
1453 },
1454 3, 5, 6, 7 => return self.fail("TODO: genLoad for more abi_sizes", .{}),
1455 else => unreachable,
1456 }
1457}
1458
1389fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {1459fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
1390 if (typed_value.val.isUndef())1460 if (typed_value.val.isUndef())
1391 return MCValue{ .undef = {} };1461 return MCValue{ .undef = {} };
src/arch/sparcv9/Emit.zig+13
...@@ -76,6 +76,11 @@ pub fn emitMir(...@@ -76,6 +76,11 @@ pub fn emitMir(
7676
77 .sllx => @panic("TODO implement sparcv9 sllx"),77 .sllx => @panic("TODO implement sparcv9 sllx"),
7878
79 .stb => try emit.mirArithmetic3Op(inst),
80 .sth => try emit.mirArithmetic3Op(inst),
81 .stw => try emit.mirArithmetic3Op(inst),
82 .stx => try emit.mirArithmetic3Op(inst),
83
79 .sub => try emit.mirArithmetic3Op(inst),84 .sub => try emit.mirArithmetic3Op(inst),
8085
81 .tcc => try emit.mirTrap(inst),86 .tcc => try emit.mirTrap(inst),
...@@ -170,6 +175,10 @@ fn mirArithmetic3Op(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -170,6 +175,10 @@ fn mirArithmetic3Op(emit: *Emit, inst: Mir.Inst.Index) !void {
170 .@"or" => try emit.writeInstruction(Instruction.@"or"(i13, rs1, imm, rd)),175 .@"or" => try emit.writeInstruction(Instruction.@"or"(i13, rs1, imm, rd)),
171 .save => try emit.writeInstruction(Instruction.save(i13, rs1, imm, rd)),176 .save => try emit.writeInstruction(Instruction.save(i13, rs1, imm, rd)),
172 .restore => try emit.writeInstruction(Instruction.restore(i13, rs1, imm, rd)),177 .restore => try emit.writeInstruction(Instruction.restore(i13, rs1, imm, rd)),
178 .stb => try emit.writeInstruction(Instruction.stb(i13, rs1, imm, rd)),
179 .sth => try emit.writeInstruction(Instruction.sth(i13, rs1, imm, rd)),
180 .stw => try emit.writeInstruction(Instruction.stw(i13, rs1, imm, rd)),
181 .stx => try emit.writeInstruction(Instruction.stx(i13, rs1, imm, rd)),
173 .sub => try emit.writeInstruction(Instruction.sub(i13, rs1, imm, rd)),182 .sub => try emit.writeInstruction(Instruction.sub(i13, rs1, imm, rd)),
174 else => unreachable,183 else => unreachable,
175 }184 }
...@@ -185,6 +194,10 @@ fn mirArithmetic3Op(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -185,6 +194,10 @@ fn mirArithmetic3Op(emit: *Emit, inst: Mir.Inst.Index) !void {
185 .@"or" => try emit.writeInstruction(Instruction.@"or"(Register, rs1, rs2, rd)),194 .@"or" => try emit.writeInstruction(Instruction.@"or"(Register, rs1, rs2, rd)),
186 .save => try emit.writeInstruction(Instruction.save(Register, rs1, rs2, rd)),195 .save => try emit.writeInstruction(Instruction.save(Register, rs1, rs2, rd)),
187 .restore => try emit.writeInstruction(Instruction.restore(Register, rs1, rs2, rd)),196 .restore => try emit.writeInstruction(Instruction.restore(Register, rs1, rs2, rd)),
197 .stb => try emit.writeInstruction(Instruction.stb(Register, rs1, rs2, rd)),
198 .sth => try emit.writeInstruction(Instruction.sth(Register, rs1, rs2, rd)),
199 .stw => try emit.writeInstruction(Instruction.stw(Register, rs1, rs2, rd)),
200 .stx => try emit.writeInstruction(Instruction.stx(Register, rs1, rs2, rd)),
188 .sub => try emit.writeInstruction(Instruction.sub(Register, rs1, rs2, rd)),201 .sub => try emit.writeInstruction(Instruction.sub(Register, rs1, rs2, rd)),
189 else => unreachable,202 else => unreachable,
190 }203 }
src/arch/sparcv9/Mir.zig+10
...@@ -94,6 +94,16 @@ pub const Inst = struct {...@@ -94,6 +94,16 @@ pub const Inst = struct {
94 // TODO add other operations.94 // TODO add other operations.
95 sllx,95 sllx,
9696
97 /// A.54 Store Integer
98 /// This uses the arithmetic_3op field.
99 /// Note that the std variant of this instruction is deprecated, so do not emit
100 /// it unless specifically requested (e.g. by inline assembly).
101 // TODO add other operations.
102 stb,
103 sth,
104 stw,
105 stx,
106
97 /// A.56 Subtract107 /// A.56 Subtract
98 /// Those uses the arithmetic_3op field.108 /// Those uses the arithmetic_3op field.
99 // TODO add other operations.109 // TODO add other operations.
src/arch/sparcv9/abi.zig+5
...@@ -1,6 +1,11 @@...@@ -1,6 +1,11 @@
1const bits = @import("bits.zig");1const bits = @import("bits.zig");
2const Register = bits.Register;2const Register = bits.Register;
33
4// On SPARCv9, %sp points to top of stack + stack bias,
5// and %fp points to top of previous frame + stack bias.
6// See: Registers and the Stack Frame, page 3P-8, SCD 2.4.1.
7pub const stack_bias = 2047;
8
4// There are no callee-preserved registers since the windowing9// There are no callee-preserved registers since the windowing
5// mechanism already takes care of them.10// mechanism already takes care of them.
6// We still need to preserve %o0-%o5, %g1, %g4, and %g5 before calling11// We still need to preserve %o0-%o5, %g1, %g4, and %g5 before calling
src/arch/sparcv9/bits.zig+32
...@@ -1059,6 +1059,38 @@ pub const Instruction = union(enum) {...@@ -1059,6 +1059,38 @@ pub const Instruction = union(enum) {
1059 return format2a(0b100, imm, rd);1059 return format2a(0b100, imm, rd);
1060 }1060 }
10611061
1062 pub fn stb(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
1063 return switch (s2) {
1064 Register => format3a(0b11, 0b00_0101, rs1, rs2, rd),
1065 i13 => format3b(0b11, 0b00_0101, rs1, rs2, rd),
1066 else => unreachable,
1067 };
1068 }
1069
1070 pub fn sth(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
1071 return switch (s2) {
1072 Register => format3a(0b11, 0b00_0110, rs1, rs2, rd),
1073 i13 => format3b(0b11, 0b00_0110, rs1, rs2, rd),
1074 else => unreachable,
1075 };
1076 }
1077
1078 pub fn stw(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
1079 return switch (s2) {
1080 Register => format3a(0b11, 0b00_0100, rs1, rs2, rd),
1081 i13 => format3b(0b11, 0b00_0100, rs1, rs2, rd),
1082 else => unreachable,
1083 };
1084 }
1085
1086 pub fn stx(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
1087 return switch (s2) {
1088 Register => format3a(0b11, 0b00_1110, rs1, rs2, rd),
1089 i13 => format3b(0b11, 0b00_1110, rs1, rs2, rd),
1090 else => unreachable,
1091 };
1092 }
1093
1062 pub fn sub(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {1094 pub fn sub(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
1063 return switch (s2) {1095 return switch (s2) {
1064 Register => format3a(0b10, 0b00_0100, rs1, rs2, rd),1096 Register => format3a(0b10, 0b00_0100, rs1, rs2, rd),