1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
const std = @import("std");
const bits = @import("bits.zig");
const Register = bits.Register;
const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
// SPARCv9 SysV ABI stack constants.
// See: Registers and the Stack Frame, page 3P-8, SCD 2.4.1.
// The ABI specifies that %sp points to top of stack - stack bias,
// and %fp points to top of previous frame - stack bias.
pub const stack_bias = 2047;
// The first 128 bytes of the stack is reserved for register saving purposes.
// The ABI also requires to reserve space in the stack for the first six
// outgoing arguments, even though they are usually passed in registers.
// TODO Don't allocate the argument space in leaf functions
// TODO Save an RO copy of outgoing arguments in reserved area when building in Debug
// TODO Should we also save it in ReleaseSafe? Solaris and OpenBSD binaries seem to ship
// with argument copying enabled and it doesn't seem to give them big slowdowns so
// I guess it would be okay to do in ReleaseSafe?
pub const stack_reserved_area = 128 + 48;
// There are no callee-preserved registers since the windowing
// mechanism already takes care of them.
// We still need to preserve %o0-%o5, %g1, %g4, and %g5 before calling
// something, though, as those are shared with the callee and might be
// thrashed by it.
pub const caller_preserved_regs = [_]Register{ .o0, .o1, .o2, .o3, .o4, .o5, .g1, .g4, .g5 };
// Try to allocate i, l, o, then g sets of registers, in order of priority.
const allocatable_regs = [_]Register{
// zig fmt: off
.@"i0", .@"i1", .@"i2", .@"i3", .@"i4", .@"i5",
.l0, .l1, .l2, .l3, .l4, .l5, .l6, .l7,
.o0, .o1, .o2, .o3, .o4, .o5,
.g1, .g4, .g5,
// zig fmt: on
};
pub const c_abi_int_param_regs_caller_view = [_]Register{ .o0, .o1, .o2, .o3, .o4, .o5 };
pub const c_abi_int_param_regs_callee_view = [_]Register{ .@"i0", .@"i1", .@"i2", .@"i3", .@"i4", .@"i5" };
pub const c_abi_int_return_regs_caller_view = [_]Register{ .o0, .o1, .o2, .o3 };
pub const c_abi_int_return_regs_callee_view = [_]Register{ .@"i0", .@"i1", .@"i2", .@"i3" };
pub const RegisterManager = RegisterManagerFn(@import("CodeGen.zig"), Register, &allocatable_regs);
// Register classes
const RegisterBitSet = RegisterManager.RegisterBitSet;
pub const RegisterClass = struct {
pub const gp: RegisterBitSet = blk: {
var set = RegisterBitSet.initEmpty();
set.setRangeValue(.{
.start = 0,
.end = allocatable_regs.len,
}, true);
break :blk set;
};
};
|