| ... | @@ -236,6 +236,11 @@ const InnerError = error{ | ... | @@ -236,6 +236,11 @@ const InnerError = error{ |
| 236 | }; | 236 | }; |
| 237 | | 237 | |
| 238 | fn Function(comptime arch: std.Target.Cpu.Arch) type { | 238 | fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| | 239 | const writeInt = switch (arch.endian()) { |
| | 240 | .Little => mem.writeIntLittle, |
| | 241 | .Big => mem.writeIntBig, |
| | 242 | }; |
| | 243 | |
| 239 | return struct { | 244 | return struct { |
| 240 | gpa: *Allocator, | 245 | gpa: *Allocator, |
| 241 | bin_file: *link.File, | 246 | bin_file: *link.File, |
| ... | @@ -565,14 +570,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -565,14 +570,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 565 | try self.dbgSetEpilogueBegin(); | 570 | try self.dbgSetEpilogueBegin(); |
| 566 | } | 571 | } |
| 567 | }, | 572 | }, |
| 568 | .arm => { | 573 | .arm, .armeb => { |
| 569 | const cc = self.fn_type.fnCallingConvention(); | 574 | const cc = self.fn_type.fnCallingConvention(); |
| 570 | if (cc != .Naked) { | 575 | if (cc != .Naked) { |
| 571 | // push {fp, lr} | 576 | // push {fp, lr} |
| 572 | // mov fp, sp | 577 | // mov fp, sp |
| 573 | // sub sp, sp, #reloc | 578 | // sub sp, sp, #reloc |
| 574 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.push(.al, .{ .fp, .lr }).toU32()); | 579 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.push(.al, .{ .fp, .lr }).toU32()); |
| 575 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.mov(.al, .fp, Instruction.Operand.reg(.sp, Instruction.Operand.Shift.none)).toU32()); | 580 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.mov(.al, .fp, Instruction.Operand.reg(.sp, Instruction.Operand.Shift.none)).toU32()); |
| 576 | const backpatch_reloc = self.code.items.len; | 581 | const backpatch_reloc = self.code.items.len; |
| 577 | try self.code.resize(backpatch_reloc + 4); | 582 | try self.code.resize(backpatch_reloc + 4); |
| 578 | | 583 | |
| ... | @@ -584,7 +589,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -584,7 +589,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 584 | const stack_end = self.max_end_stack; | 589 | const stack_end = self.max_end_stack; |
| 585 | const aligned_stack_end = mem.alignForward(stack_end, self.stack_align); | 590 | const aligned_stack_end = mem.alignForward(stack_end, self.stack_align); |
| 586 | if (Instruction.Operand.fromU32(@intCast(u32, aligned_stack_end))) |op| { | 591 | if (Instruction.Operand.fromU32(@intCast(u32, aligned_stack_end))) |op| { |
| 587 | mem.writeIntLittle(u32, self.code.items[backpatch_reloc..][0..4], Instruction.sub(.al, .sp, .sp, op).toU32()); | 592 | writeInt(u32, self.code.items[backpatch_reloc..][0..4], Instruction.sub(.al, .sp, .sp, op).toU32()); |
| 588 | } else { | 593 | } else { |
| 589 | return self.fail(self.src, "TODO ARM: allow larger stacks", .{}); | 594 | return self.fail(self.src, "TODO ARM: allow larger stacks", .{}); |
| 590 | } | 595 | } |
| ... | @@ -607,10 +612,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -607,10 +612,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 607 | // the space because there may be | 612 | // the space because there may be |
| 608 | // other jumps we already relocated to | 613 | // other jumps we already relocated to |
| 609 | // the address. Instead, insert a nop | 614 | // the address. Instead, insert a nop |
| 610 | mem.writeIntLittle(u32, self.code.items[jmp_reloc..][0..4], Instruction.nop().toU32()); | 615 | writeInt(u32, self.code.items[jmp_reloc..][0..4], Instruction.nop().toU32()); |
| 611 | } else { | 616 | } else { |
| 612 | if (math.cast(i26, amt)) |offset| { | 617 | if (math.cast(i26, amt)) |offset| { |
| 613 | mem.writeIntLittle(u32, self.code.items[jmp_reloc..][0..4], Instruction.b(.al, offset).toU32()); | 618 | writeInt(u32, self.code.items[jmp_reloc..][0..4], Instruction.b(.al, offset).toU32()); |
| 614 | } else |err| { | 619 | } else |err| { |
| 615 | return self.fail(self.src, "exitlude jump is too large", .{}); | 620 | return self.fail(self.src, "exitlude jump is too large", .{}); |
| 616 | } | 621 | } |
| ... | @@ -619,8 +624,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -619,8 +624,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 619 | | 624 | |
| 620 | // mov sp, fp | 625 | // mov sp, fp |
| 621 | // pop {fp, pc} | 626 | // pop {fp, pc} |
| 622 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.mov(.al, .sp, Instruction.Operand.reg(.fp, Instruction.Operand.Shift.none)).toU32()); | 627 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.mov(.al, .sp, Instruction.Operand.reg(.fp, Instruction.Operand.Shift.none)).toU32()); |
| 623 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.pop(.al, .{ .fp, .pc }).toU32()); | 628 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.pop(.al, .{ .fp, .pc }).toU32()); |
| 624 | } else { | 629 | } else { |
| 625 | try self.dbgSetPrologueEnd(); | 630 | try self.dbgSetPrologueEnd(); |
| 626 | try self.genBody(self.mod_fn.analysis.success); | 631 | try self.genBody(self.mod_fn.analysis.success); |
| ... | @@ -1372,11 +1377,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -1372,11 +1377,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1372 | var instr = Instruction{ .condition = .always, .input0 = .zero, .input1 = .zero, .modify_flags = false, .output = .discard, .command = .undefined1 }; | 1377 | var instr = Instruction{ .condition = .always, .input0 = .zero, .input1 = .zero, .modify_flags = false, .output = .discard, .command = .undefined1 }; |
| 1373 | mem.writeIntLittle(u16, self.code.items[self.code.items.len - 2 ..][0..2], @bitCast(u16, instr)); | 1378 | mem.writeIntLittle(u16, self.code.items[self.code.items.len - 2 ..][0..2], @bitCast(u16, instr)); |
| 1374 | }, | 1379 | }, |
| 1375 | .arm => { | 1380 | .arm, .armeb => { |
| 1376 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.bkpt(0).toU32()); | 1381 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.bkpt(0).toU32()); |
| 1377 | }, | | |
| 1378 | .armeb => { | | |
| 1379 | mem.writeIntBig(u32, try self.code.addManyAsArray(4), Instruction.bkpt(0).toU32()); | | |
| 1380 | }, | 1382 | }, |
| 1381 | else => return self.fail(src, "TODO implement @breakpoint() for {}", .{self.target.cpu.arch}), | 1383 | else => return self.fail(src, "TODO implement @breakpoint() for {}", .{self.target.cpu.arch}), |
| 1382 | } | 1384 | } |
| ... | @@ -1520,7 +1522,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -1520,7 +1522,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1520 | return self.fail(inst.base.src, "TODO implement calling runtime known function pointer", .{}); | 1522 | return self.fail(inst.base.src, "TODO implement calling runtime known function pointer", .{}); |
| 1521 | } | 1523 | } |
| 1522 | }, | 1524 | }, |
| 1523 | .arm => { | 1525 | .arm, .armeb => { |
| 1524 | for (info.args) |mc_arg, arg_i| { | 1526 | for (info.args) |mc_arg, arg_i| { |
| 1525 | const arg = inst.args[arg_i]; | 1527 | const arg = inst.args[arg_i]; |
| 1526 | const arg_mcv = try self.resolveInst(inst.args[arg_i]); | 1528 | const arg_mcv = try self.resolveInst(inst.args[arg_i]); |
| ... | @@ -1569,10 +1571,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -1569,10 +1571,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1569 | // TODO: add Instruction.supportedOn | 1571 | // TODO: add Instruction.supportedOn |
| 1570 | // function for ARM | 1572 | // function for ARM |
| 1571 | if (Target.arm.featureSetHas(self.target.cpu.features, .has_v5t)) { | 1573 | if (Target.arm.featureSetHas(self.target.cpu.features, .has_v5t)) { |
| 1572 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.blx(.al, .lr).toU32()); | 1574 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.blx(.al, .lr).toU32()); |
| 1573 | } else { | 1575 | } else { |
| 1574 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.mov(.al, .lr, Instruction.Operand.reg(.pc, Instruction.Operand.Shift.none)).toU32()); | 1576 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.mov(.al, .lr, Instruction.Operand.reg(.pc, Instruction.Operand.Shift.none)).toU32()); |
| 1575 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.bx(.al, .lr).toU32()); | 1577 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.bx(.al, .lr).toU32()); |
| 1576 | } | 1578 | } |
| 1577 | } else { | 1579 | } else { |
| 1578 | return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{}); | 1580 | return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{}); |
| ... | @@ -1692,7 +1694,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -1692,7 +1694,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1692 | .riscv64 => { | 1694 | .riscv64 => { |
| 1693 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.jalr(.zero, 0, .ra).toU32()); | 1695 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.jalr(.zero, 0, .ra).toU32()); |
| 1694 | }, | 1696 | }, |
| 1695 | .arm => { | 1697 | .arm, .armeb => { |
| 1696 | // Just add space for an instruction, patch this later | 1698 | // Just add space for an instruction, patch this later |
| 1697 | try self.code.resize(self.code.items.len + 4); | 1699 | try self.code.resize(self.code.items.len + 4); |
| 1698 | try self.exitlude_jump_relocs.append(self.gpa, self.code.items.len - 4); | 1700 | try self.exitlude_jump_relocs.append(self.gpa, self.code.items.len - 4); |
| ... | @@ -1961,9 +1963,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -1961,9 +1963,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1961 | mem.writeIntLittle(i32, self.code.addManyAsArrayAssumeCapacity(4), delta); | 1963 | mem.writeIntLittle(i32, self.code.addManyAsArrayAssumeCapacity(4), delta); |
| 1962 | } | 1964 | } |
| 1963 | }, | 1965 | }, |
| 1964 | .arm => { | 1966 | .arm, .armeb => { |
| 1965 | if (math.cast(i26, @intCast(i32, index) - @intCast(i32, self.code.items.len))) |delta| { | 1967 | if (math.cast(i26, @intCast(i32, index) - @intCast(i32, self.code.items.len))) |delta| { |
| 1966 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.b(.al, delta).toU32()); | 1968 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.b(.al, delta).toU32()); |
| 1967 | } else |err| { | 1969 | } else |err| { |
| 1968 | return self.fail(src, "TODO: enable larger branch offset", .{}); | 1970 | return self.fail(src, "TODO: enable larger branch offset", .{}); |
| 1969 | } | 1971 | } |
| ... | @@ -2082,7 +2084,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -2082,7 +2084,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2082 | return self.fail(inst.base.src, "TODO implement support for more SPU II assembly instructions", .{}); | 2084 | return self.fail(inst.base.src, "TODO implement support for more SPU II assembly instructions", .{}); |
| 2083 | } | 2085 | } |
| 2084 | }, | 2086 | }, |
| 2085 | .arm => { | 2087 | .arm, .armeb => { |
| 2086 | for (inst.inputs) |input, i| { | 2088 | for (inst.inputs) |input, i| { |
| 2087 | if (input.len < 3 or input[0] != '{' or input[input.len - 1] != '}') { | 2089 | if (input.len < 3 or input[0] != '{' or input[input.len - 1] != '}') { |
| 2088 | return self.fail(inst.base.src, "unrecognized asm input constraint: '{}'", .{input}); | 2090 | return self.fail(inst.base.src, "unrecognized asm input constraint: '{}'", .{input}); |
| ... | @@ -2095,7 +2097,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -2095,7 +2097,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2095 | } | 2097 | } |
| 2096 | | 2098 | |
| 2097 | if (mem.eql(u8, inst.asm_source, "svc #0")) { | 2099 | if (mem.eql(u8, inst.asm_source, "svc #0")) { |
| 2098 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.svc(.al, 0).toU32()); | 2100 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.svc(.al, 0).toU32()); |
| 2099 | } else { | 2101 | } else { |
| 2100 | return self.fail(inst.base.src, "TODO implement support for more arm assembly instructions", .{}); | 2102 | return self.fail(inst.base.src, "TODO implement support for more arm assembly instructions", .{}); |
| 2101 | } | 2103 | } |
| ... | @@ -2224,7 +2226,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -2224,7 +2226,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2224 | | 2226 | |
| 2225 | fn genSetStack(self: *Self, src: usize, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void { | 2227 | fn genSetStack(self: *Self, src: usize, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void { |
| 2226 | switch (arch) { | 2228 | switch (arch) { |
| 2227 | .arm => switch (mcv) { | 2229 | .arm, .armeb => switch (mcv) { |
| 2228 | .dead => unreachable, | 2230 | .dead => unreachable, |
| 2229 | .ptr_stack_offset => unreachable, | 2231 | .ptr_stack_offset => unreachable, |
| 2230 | .ptr_embedded_in_code => unreachable, | 2232 | .ptr_embedded_in_code => unreachable, |
| ... | @@ -2257,7 +2259,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -2257,7 +2259,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2257 | .register => |reg| { | 2259 | .register => |reg| { |
| 2258 | // TODO: strb, strh | 2260 | // TODO: strb, strh |
| 2259 | if (stack_offset <= math.maxInt(u12)) { | 2261 | if (stack_offset <= math.maxInt(u12)) { |
| 2260 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.str(.al, reg, .fp, .{ | 2262 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.str(.al, reg, .fp, .{ |
| 2261 | .offset = Instruction.Offset.imm(@intCast(u12, stack_offset)), | 2263 | .offset = Instruction.Offset.imm(@intCast(u12, stack_offset)), |
| 2262 | .positive = false, | 2264 | .positive = false, |
| 2263 | }).toU32()); | 2265 | }).toU32()); |
| ... | @@ -2371,7 +2373,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -2371,7 +2373,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2371 | | 2373 | |
| 2372 | fn genSetReg(self: *Self, src: usize, reg: Register, mcv: MCValue) InnerError!void { | 2374 | fn genSetReg(self: *Self, src: usize, reg: Register, mcv: MCValue) InnerError!void { |
| 2373 | switch (arch) { | 2375 | switch (arch) { |
| 2374 | .arm => switch (mcv) { | 2376 | .arm, .armeb => switch (mcv) { |
| 2375 | .dead => unreachable, | 2377 | .dead => unreachable, |
| 2376 | .ptr_stack_offset => unreachable, | 2378 | .ptr_stack_offset => unreachable, |
| 2377 | .ptr_embedded_in_code => unreachable, | 2379 | .ptr_embedded_in_code => unreachable, |
| ... | @@ -2386,15 +2388,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -2386,15 +2388,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2386 | if (x > math.maxInt(u32)) return self.fail(src, "ARM registers are 32-bit wide", .{}); | 2388 | if (x > math.maxInt(u32)) return self.fail(src, "ARM registers are 32-bit wide", .{}); |
| 2387 | | 2389 | |
| 2388 | if (Instruction.Operand.fromU32(@intCast(u32, x))) |op| { | 2390 | if (Instruction.Operand.fromU32(@intCast(u32, x))) |op| { |
| 2389 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.mov(.al, reg, op).toU32()); | 2391 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.mov(.al, reg, op).toU32()); |
| 2390 | } else if (Instruction.Operand.fromU32(~@intCast(u32, x))) |op| { | 2392 | } else if (Instruction.Operand.fromU32(~@intCast(u32, x))) |op| { |
| 2391 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.mvn(.al, reg, op).toU32()); | 2393 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.mvn(.al, reg, op).toU32()); |
| 2392 | } else if (x <= math.maxInt(u16)) { | 2394 | } else if (x <= math.maxInt(u16)) { |
| 2393 | if (Target.arm.featureSetHas(self.target.cpu.features, .has_v7)) { | 2395 | if (Target.arm.featureSetHas(self.target.cpu.features, .has_v7)) { |
| 2394 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.movw(.al, reg, @intCast(u16, x)).toU32()); | 2396 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.movw(.al, reg, @intCast(u16, x)).toU32()); |
| 2395 | } else { | 2397 | } else { |
| 2396 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.mov(.al, reg, Instruction.Operand.imm(@truncate(u8, x), 0)).toU32()); | 2398 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.mov(.al, reg, Instruction.Operand.imm(@truncate(u8, x), 0)).toU32()); |
| 2397 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.orr(.al, reg, reg, Instruction.Operand.imm(@truncate(u8, x >> 8), 12)).toU32()); | 2399 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.orr(.al, reg, reg, Instruction.Operand.imm(@truncate(u8, x >> 8), 12)).toU32()); |
| 2398 | } | 2400 | } |
| 2399 | } else { | 2401 | } else { |
| 2400 | // TODO write constant to code and load | 2402 | // TODO write constant to code and load |
| ... | @@ -2403,18 +2405,18 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -2403,18 +2405,18 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2403 | // immediate: 0xaaaabbbb | 2405 | // immediate: 0xaaaabbbb |
| 2404 | // movw reg, #0xbbbb | 2406 | // movw reg, #0xbbbb |
| 2405 | // movt reg, #0xaaaa | 2407 | // movt reg, #0xaaaa |
| 2406 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.movw(.al, reg, @truncate(u16, x)).toU32()); | 2408 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.movw(.al, reg, @truncate(u16, x)).toU32()); |
| 2407 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.movt(.al, reg, @truncate(u16, x >> 16)).toU32()); | 2409 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.movt(.al, reg, @truncate(u16, x >> 16)).toU32()); |
| 2408 | } else { | 2410 | } else { |
| 2409 | // immediate: 0xaabbccdd | 2411 | // immediate: 0xaabbccdd |
| 2410 | // mov reg, #0xaa | 2412 | // mov reg, #0xaa |
| 2411 | // orr reg, reg, #0xbb, 24 | 2413 | // orr reg, reg, #0xbb, 24 |
| 2412 | // orr reg, reg, #0xcc, 16 | 2414 | // orr reg, reg, #0xcc, 16 |
| 2413 | // orr reg, reg, #0xdd, 8 | 2415 | // orr reg, reg, #0xdd, 8 |
| 2414 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.mov(.al, reg, Instruction.Operand.imm(@truncate(u8, x), 0)).toU32()); | 2416 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.mov(.al, reg, Instruction.Operand.imm(@truncate(u8, x), 0)).toU32()); |
| 2415 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.orr(.al, reg, reg, Instruction.Operand.imm(@truncate(u8, x >> 8), 12)).toU32()); | 2417 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.orr(.al, reg, reg, Instruction.Operand.imm(@truncate(u8, x >> 8), 12)).toU32()); |
| 2416 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.orr(.al, reg, reg, Instruction.Operand.imm(@truncate(u8, x >> 16), 8)).toU32()); | 2418 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.orr(.al, reg, reg, Instruction.Operand.imm(@truncate(u8, x >> 16), 8)).toU32()); |
| 2417 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.orr(.al, reg, reg, Instruction.Operand.imm(@truncate(u8, x >> 24), 4)).toU32()); | 2419 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.orr(.al, reg, reg, Instruction.Operand.imm(@truncate(u8, x >> 24), 4)).toU32()); |
| 2418 | } | 2420 | } |
| 2419 | } | 2421 | } |
| 2420 | }, | 2422 | }, |
| ... | @@ -2424,19 +2426,19 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -2424,19 +2426,19 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2424 | return; | 2426 | return; |
| 2425 | | 2427 | |
| 2426 | // mov reg, src_reg | 2428 | // mov reg, src_reg |
| 2427 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.mov(.al, reg, Instruction.Operand.reg(src_reg, Instruction.Operand.Shift.none)).toU32()); | 2429 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.mov(.al, reg, Instruction.Operand.reg(src_reg, Instruction.Operand.Shift.none)).toU32()); |
| 2428 | }, | 2430 | }, |
| 2429 | .memory => |addr| { | 2431 | .memory => |addr| { |
| 2430 | // The value is in memory at a hard-coded address. | 2432 | // The value is in memory at a hard-coded address. |
| 2431 | // If the type is a pointer, it means the pointer address is at this memory location. | 2433 | // If the type is a pointer, it means the pointer address is at this memory location. |
| 2432 | try self.genSetReg(src, reg, .{ .immediate = addr }); | 2434 | try self.genSetReg(src, reg, .{ .immediate = addr }); |
| 2433 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.ldr(.al, reg, reg, .{ .offset = Instruction.Offset.none }).toU32()); | 2435 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.ldr(.al, reg, reg, .{ .offset = Instruction.Offset.none }).toU32()); |
| 2434 | }, | 2436 | }, |
| 2435 | .stack_offset => |unadjusted_off| { | 2437 | .stack_offset => |unadjusted_off| { |
| 2436 | // TODO: ldrb, ldrh | 2438 | // TODO: ldrb, ldrh |
| 2437 | // TODO: maybe addressing from sp instead of fp | 2439 | // TODO: maybe addressing from sp instead of fp |
| 2438 | if (unadjusted_off <= math.maxInt(u12)) { | 2440 | if (unadjusted_off <= math.maxInt(u12)) { |
| 2439 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.ldr(.al, reg, .fp, .{ | 2441 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.ldr(.al, reg, .fp, .{ |
| 2440 | .offset = Instruction.Offset.imm(@intCast(u12, unadjusted_off)), | 2442 | .offset = Instruction.Offset.imm(@intCast(u12, unadjusted_off)), |
| 2441 | .positive = false, | 2443 | .positive = false, |
| 2442 | }).toU32()); | 2444 | }).toU32()); |
| ... | @@ -2898,7 +2900,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -2898,7 +2900,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2898 | else => return self.fail(src, "TODO implement function parameters for {} on x86_64", .{cc}), | 2900 | else => return self.fail(src, "TODO implement function parameters for {} on x86_64", .{cc}), |
| 2899 | } | 2901 | } |
| 2900 | }, | 2902 | }, |
| 2901 | .arm => { | 2903 | .arm, .armeb => { |
| 2902 | switch (cc) { | 2904 | switch (cc) { |
| 2903 | .Naked => { | 2905 | .Naked => { |
| 2904 | assert(result.args.len == 0); | 2906 | assert(result.args.len == 0); |
| ... | @@ -2965,7 +2967,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -2965,7 +2967,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2965 | }, | 2967 | }, |
| 2966 | else => return self.fail(src, "TODO implement function return values for {}", .{cc}), | 2968 | else => return self.fail(src, "TODO implement function return values for {}", .{cc}), |
| 2967 | }, | 2969 | }, |
| 2968 | .arm => switch (cc) { | 2970 | .arm, .armeb => switch (cc) { |
| 2969 | .Naked => unreachable, | 2971 | .Naked => unreachable, |
| 2970 | .Unspecified, .C => { | 2972 | .Unspecified, .C => { |
| 2971 | const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*)); | 2973 | const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*)); |
| ... | @@ -3004,8 +3006,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -3004,8 +3006,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 3004 | .x86_64 => @import("codegen/x86_64.zig"), | 3006 | .x86_64 => @import("codegen/x86_64.zig"), |
| 3005 | .riscv64 => @import("codegen/riscv64.zig"), | 3007 | .riscv64 => @import("codegen/riscv64.zig"), |
| 3006 | .spu_2 => @import("codegen/spu-mk2.zig"), | 3008 | .spu_2 => @import("codegen/spu-mk2.zig"), |
| 3007 | .arm => @import("codegen/arm.zig"), | 3009 | .arm, .armeb => @import("codegen/arm.zig"), |
| 3008 | .armeb => @import("codegen/arm.zig"), | | |
| 3009 | else => struct { | 3010 | else => struct { |
| 3010 | pub const Register = enum { | 3011 | pub const Register = enum { |
| 3011 | dummy, | 3012 | dummy, |
| ... | @@ -3019,7 +3020,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -3019,7 +3020,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 3019 | }; | 3020 | }; |
| 3020 | | 3021 | |
| 3021 | /// An integer whose bits represent all the registers and whether they are free. | 3022 | /// An integer whose bits represent all the registers and whether they are free. |
| 3022 | const FreeRegInt = @Type(.{ .Int = .{ .is_signed = false, .bits = callee_preserved_regs.len } }); | 3023 | const FreeRegInt = std.meta.Int(.unsigned, callee_preserved_regs.len); |
| 3023 | | 3024 | |
| 3024 | fn parseRegName(name: []const u8) ?Register { | 3025 | fn parseRegName(name: []const u8) ?Register { |
| 3025 | if (@hasDecl(Register, "parseRegName")) { | 3026 | if (@hasDecl(Register, "parseRegName")) { |