| author | |
| committer | |
| log | a00d69ea4a8c6e21ca99daa10d3b324609f3ef24 |
| tree | 6bbd589fb83ee38da6438ef2977c767693912cfa |
| parent | b6d7f63f34bbdb7c67abecbcd47389d2a3d28743 |
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 | 1351 | try self.genLoad(reg, reg, i13, 0, ty.abiSize(self.target.*)); |
| 1352 | 1352 | }, |
| 1353 | 1353 | .stack_offset => |off| { |
| 1354 | const simm13 = math.cast(u12, off) catch | |
| 1354 | const biased_offset = off + abi.stack_bias; | |
| 1355 | const simm13 = math.cast(i13, biased_offset) catch | |
| 1355 | 1356 | return self.fail("TODO larger stack offsets", .{}); |
| 1356 | 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 | 1382 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 1382 | 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 | 1391 | .memory, .stack_offset => return self.fail("TODO implement memcpy", .{}), |
| 1386 | 1392 | } |
| 1387 | 1393 | } |
| 1388 | 1394 | |
| 1395 | fn 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 | ||
| 1389 | 1459 | fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { |
| 1390 | 1460 | if (typed_value.val.isUndef()) |
| 1391 | 1461 | return MCValue{ .undef = {} }; |
src/arch/sparcv9/Emit.zig+13| ... | ... | @@ -76,6 +76,11 @@ pub fn emitMir( |
| 76 | 76 | |
| 77 | 77 | .sllx => @panic("TODO implement sparcv9 sllx"), |
| 78 | 78 | |
| 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 | 84 | .sub => try emit.mirArithmetic3Op(inst), |
| 80 | 85 | |
| 81 | 86 | .tcc => try emit.mirTrap(inst), |
| ... | ... | @@ -170,6 +175,10 @@ fn mirArithmetic3Op(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 170 | 175 | .@"or" => try emit.writeInstruction(Instruction.@"or"(i13, rs1, imm, rd)), |
| 171 | 176 | .save => try emit.writeInstruction(Instruction.save(i13, rs1, imm, rd)), |
| 172 | 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 | 182 | .sub => try emit.writeInstruction(Instruction.sub(i13, rs1, imm, rd)), |
| 174 | 183 | else => unreachable, |
| 175 | 184 | } |
| ... | ... | @@ -185,6 +194,10 @@ fn mirArithmetic3Op(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 185 | 194 | .@"or" => try emit.writeInstruction(Instruction.@"or"(Register, rs1, rs2, rd)), |
| 186 | 195 | .save => try emit.writeInstruction(Instruction.save(Register, rs1, rs2, rd)), |
| 187 | 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 | 201 | .sub => try emit.writeInstruction(Instruction.sub(Register, rs1, rs2, rd)), |
| 189 | 202 | else => unreachable, |
| 190 | 203 | } |
src/arch/sparcv9/Mir.zig+10| ... | ... | @@ -94,6 +94,16 @@ pub const Inst = struct { |
| 94 | 94 | // TODO add other operations. |
| 95 | 95 | sllx, |
| 96 | 96 | |
| 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 | 107 | /// A.56 Subtract |
| 98 | 108 | /// Those uses the arithmetic_3op field. |
| 99 | 109 | // TODO add other operations. |
src/arch/sparcv9/abi.zig+5| ... | ... | @@ -1,6 +1,11 @@ |
| 1 | 1 | const bits = @import("bits.zig"); |
| 2 | 2 | const Register = bits.Register; |
| 3 | 3 | |
| 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. | |
| 7 | pub const stack_bias = 2047; | |
| 8 | ||
| 4 | 9 | // There are no callee-preserved registers since the windowing |
| 5 | 10 | // mechanism already takes care of them. |
| 6 | 11 | // 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 | 1059 | return format2a(0b100, imm, rd); |
| 1060 | 1060 | } |
| 1061 | 1061 | |
| 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 | 1094 | pub fn sub(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction { |
| 1063 | 1095 | return switch (s2) { |
| 1064 | 1096 | Register => format3a(0b10, 0b00_0100, rs1, rs2, rd), |