| ... | @@ -249,6 +249,37 @@ const Function = struct { | ... | @@ -249,6 +249,37 @@ const Function = struct { |
| 249 | .embedded_in_code => return self.fail(src, "TODO implement x86_64 genSetReg %rax = embedded_in_code", .{}), | 249 | .embedded_in_code => return self.fail(src, "TODO implement x86_64 genSetReg %rax = embedded_in_code", .{}), |
| 250 | .register => return self.fail(src, "TODO implement x86_64 genSetReg %rax = register", .{}), | 250 | .register => return self.fail(src, "TODO implement x86_64 genSetReg %rax = register", .{}), |
| 251 | }, | 251 | }, |
| | 252 | .rdx => switch (mcv) { |
| | 253 | .none, .unreach => unreachable, |
| | 254 | .immediate => |x| { |
| | 255 | // Setting the edx register zeroes the upper part of rdx, so if the number is small |
| | 256 | // enough, that is preferable. |
| | 257 | // Best case: zero |
| | 258 | // 31 d2 xor edx,edx |
| | 259 | if (x == 0) { |
| | 260 | return self.code.appendSlice(&[_]u8{ 0x31, 0xd2 }); |
| | 261 | } |
| | 262 | // Next best case: set edx with 4 bytes |
| | 263 | // ba 04 03 02 01 mov edx,0x1020304 |
| | 264 | if (x <= std.math.maxInt(u32)) { |
| | 265 | try self.code.resize(self.code.items.len + 5); |
| | 266 | self.code.items[self.code.items.len - 5] = 0xba; |
| | 267 | const imm_ptr = self.code.items[self.code.items.len - 4 ..][0..4]; |
| | 268 | mem.writeIntLittle(u32, imm_ptr, @intCast(u32, x)); |
| | 269 | return; |
| | 270 | } |
| | 271 | // Worst case: set rdx with 8 bytes |
| | 272 | // 48 ba 08 07 06 05 04 03 02 01 movabs rdx,0x0102030405060708 |
| | 273 | try self.code.resize(self.code.items.len + 10); |
| | 274 | self.code.items[self.code.items.len - 10] = 0x48; |
| | 275 | self.code.items[self.code.items.len - 9] = 0xba; |
| | 276 | const imm_ptr = self.code.items[self.code.items.len - 8 ..][0..8]; |
| | 277 | mem.writeIntLittle(u64, imm_ptr, x); |
| | 278 | return; |
| | 279 | }, |
| | 280 | .embedded_in_code => return self.fail(src, "TODO implement x86_64 genSetReg %rdx = embedded_in_code", .{}), |
| | 281 | .register => return self.fail(src, "TODO implement x86_64 genSetReg %rdx = register", .{}), |
| | 282 | }, |
| 252 | .rdi => switch (mcv) { | 283 | .rdi => switch (mcv) { |
| 253 | .none, .unreach => unreachable, | 284 | .none, .unreach => unreachable, |
| 254 | .immediate => |x| { | 285 | .immediate => |x| { |
| ... | @@ -305,12 +336,6 @@ const Function = struct { | ... | @@ -305,12 +336,6 @@ const Function = struct { |
| 305 | }, | 336 | }, |
| 306 | .register => return self.fail(src, "TODO implement x86_64 genSetReg %rsi = register", .{}), | 337 | .register => return self.fail(src, "TODO implement x86_64 genSetReg %rsi = register", .{}), |
| 307 | }, | 338 | }, |
| 308 | .rdx => switch (mcv) { | | |
| 309 | .none, .unreach => unreachable, | | |
| 310 | .immediate => return self.fail(src, "TODO implement x86_64 genSetReg %rdx = immediate", .{}), | | |
| 311 | .embedded_in_code => return self.fail(src, "TODO implement x86_64 genSetReg %rdx = embedded_in_code", .{}), | | |
| 312 | .register => return self.fail(src, "TODO implement x86_64 genSetReg %rdx = register", .{}), | | |
| 313 | }, | | |
| 314 | else => return self.fail(src, "TODO implement genSetReg for x86_64 '{}'", .{@tagName(reg)}), | 339 | else => return self.fail(src, "TODO implement genSetReg for x86_64 '{}'", .{@tagName(reg)}), |
| 315 | }, | 340 | }, |
| 316 | else => return self.fail(src, "TODO implement genSetReg for more architectures", .{}), | 341 | else => return self.fail(src, "TODO implement genSetReg for more architectures", .{}), |