aboutsummaryrefslogtreecommitdiff
path: root/src/arch/x86_64/encoder.zig
diff options
context:
space:
mode:
authorJacob Young <jacobly0@users.noreply.github.com>2023-03-18 05:49:20 -0400
committerJakub Konka <kubkon@jakubkonka.com>2023-03-21 08:49:54 +0100
commitedd63f9abaa7dae1786a4cd91cc3031264bd3ef0 (patch)
tree2259ac328fe3d045d0a5ce318b55b611cff7da81 /src/arch/x86_64/encoder.zig
parentc865c8fb2a910e73e38192a8bd484935bae8f6fc (diff)
downloadzig-edd63f9abaa7dae1786a4cd91cc3031264bd3ef0.tar.gz
zig-edd63f9abaa7dae1786a4cd91cc3031264bd3ef0.zip
x86_64: reimplement inline memcpy and memset
Diffstat (limited to 'src/arch/x86_64/encoder.zig')
-rw-r--r--src/arch/x86_64/encoder.zig71
1 files changed, 33 insertions, 38 deletions
diff --git a/src/arch/x86_64/encoder.zig b/src/arch/x86_64/encoder.zig
index 7e29f95069..2a2d6ea031 100644
--- a/src/arch/x86_64/encoder.zig
+++ b/src/arch/x86_64/encoder.zig
@@ -15,10 +15,21 @@ pub const Instruction = struct {
op2: Operand = .none,
op3: Operand = .none,
op4: Operand = .none,
+ prefix: Prefix = .none,
encoding: Encoding,
pub const Mnemonic = Encoding.Mnemonic;
+ pub const Prefix = enum(u3) {
+ none,
+ lock,
+ rep,
+ repe,
+ repz,
+ repne,
+ repnz,
+ };
+
pub const Operand = union(enum) {
none,
reg: Register,
@@ -96,18 +107,16 @@ pub const Instruction = struct {
}
};
- pub fn new(mnemonic: Mnemonic, args: struct {
+ pub const Init = struct {
+ prefix: Prefix = .none,
op1: Operand = .none,
op2: Operand = .none,
op3: Operand = .none,
op4: Operand = .none,
- }) !Instruction {
- const encoding = (try Encoding.findByMnemonic(mnemonic, .{
- .op1 = args.op1,
- .op2 = args.op2,
- .op3 = args.op3,
- .op4 = args.op4,
- })) orelse {
+ };
+
+ pub fn new(mnemonic: Mnemonic, args: Init) !Instruction {
+ const encoding = (try Encoding.findByMnemonic(mnemonic, args)) orelse {
log.debug("no encoding found for: {s} {s} {s} {s} {s}", .{
@tagName(mnemonic),
@tagName(Encoding.Op.fromOperand(args.op1)),
@@ -119,6 +128,7 @@ pub const Instruction = struct {
};
log.debug("selected encoding: {}", .{encoding});
return .{
+ .prefix = args.prefix,
.op1 = args.op1,
.op2 = args.op2,
.op3 = args.op3,
@@ -128,6 +138,7 @@ pub const Instruction = struct {
}
pub fn fmtPrint(inst: Instruction, writer: anytype) !void {
+ if (inst.prefix != .none) try writer.print("{s} ", .{@tagName(inst.prefix)});
try writer.print("{s}", .{@tagName(inst.encoding.mnemonic)});
const ops = [_]struct { Operand, Encoding.Op }{
.{ inst.op1, inst.encoding.op1 },
@@ -215,6 +226,14 @@ pub const Instruction = struct {
const op_en = enc.op_en;
var legacy = LegacyPrefixes{};
+
+ switch (inst.prefix) {
+ .none => {},
+ .lock => legacy.prefix_f0 = true,
+ .repne, .repnz => legacy.prefix_f2 = true,
+ .rep, .repe, .repz => legacy.prefix_f3 = true,
+ }
+
if (enc.mode == .none) {
const bit_size = enc.operandBitSize();
if (bit_size == 16) {
@@ -811,15 +830,11 @@ const TestEncode = struct {
buffer: [32]u8 = undefined,
index: usize = 0,
- fn encode(enc: *TestEncode, mnemonic: Instruction.Mnemonic, args: struct {
- op1: Instruction.Operand = .none,
- op2: Instruction.Operand = .none,
- op3: Instruction.Operand = .none,
- op4: Instruction.Operand = .none,
- }) !void {
+ fn encode(enc: *TestEncode, mnemonic: Instruction.Mnemonic, args: Instruction.Init) !void {
var stream = std.io.fixedBufferStream(&enc.buffer);
var count_writer = std.io.countingWriter(stream.writer());
const inst = try Instruction.new(mnemonic, .{
+ .prefix = args.prefix,
.op1 = args.op1,
.op2 = args.op2,
.op3 = args.op3,
@@ -1447,18 +1462,8 @@ test "lower NP encoding" {
try expectEqualHexStrings("\x0f\x05", enc.code(), "syscall");
}
-fn invalidInstruction(mnemonic: Instruction.Mnemonic, args: struct {
- op1: Instruction.Operand = .none,
- op2: Instruction.Operand = .none,
- op3: Instruction.Operand = .none,
- op4: Instruction.Operand = .none,
-}) !void {
- const err = Instruction.new(mnemonic, .{
- .op1 = args.op1,
- .op2 = args.op2,
- .op3 = args.op3,
- .op4 = args.op4,
- });
+fn invalidInstruction(mnemonic: Instruction.Mnemonic, args: Instruction.Init) !void {
+ const err = Instruction.new(mnemonic, args);
try testing.expectError(error.InvalidInstruction, err);
}
@@ -1479,18 +1484,8 @@ test "invalid instruction" {
try invalidInstruction(.push, .{ .op1 = .{ .imm = Immediate.u(0x1000000000000000) } });
}
-fn cannotEncode(mnemonic: Instruction.Mnemonic, args: struct {
- op1: Instruction.Operand = .none,
- op2: Instruction.Operand = .none,
- op3: Instruction.Operand = .none,
- op4: Instruction.Operand = .none,
-}) !void {
- try testing.expectError(error.CannotEncode, Instruction.new(mnemonic, .{
- .op1 = args.op1,
- .op2 = args.op2,
- .op3 = args.op3,
- .op4 = args.op4,
- }));
+fn cannotEncode(mnemonic: Instruction.Mnemonic, args: Instruction.Init) !void {
+ try testing.expectError(error.CannotEncode, Instruction.new(mnemonic, args));
}
test "cannot encode" {