| ... | @@ -975,6 +975,18 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -975,6 +975,18 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 975 | }; | 975 | }; |
| 976 | return try self.genX8664BinMath(&inst.base, inst.operand, &imm.base, 6, 0x30); | 976 | return try self.genX8664BinMath(&inst.base, inst.operand, &imm.base, 6, 0x30); |
| 977 | }, | 977 | }, |
| | 978 | .arm, .armeb => { |
| | 979 | var imm = ir.Inst.Constant{ |
| | 980 | .base = .{ |
| | 981 | .tag = .constant, |
| | 982 | .deaths = 0, |
| | 983 | .ty = inst.operand.ty, |
| | 984 | .src = inst.operand.src, |
| | 985 | }, |
| | 986 | .val = Value.initTag(.bool_true), |
| | 987 | }; |
| | 988 | return try self.genArmBinOp(&inst.base, inst.operand, &imm.base, .not); |
| | 989 | }, |
| 978 | else => return self.fail(inst.base.src, "TODO implement NOT for {}", .{self.target.cpu.arch}), | 990 | else => return self.fail(inst.base.src, "TODO implement NOT for {}", .{self.target.cpu.arch}), |
| 979 | } | 991 | } |
| 980 | } | 992 | } |
| ... | @@ -987,7 +999,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -987,7 +999,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 987 | .x86_64 => { | 999 | .x86_64 => { |
| 988 | return try self.genX8664BinMath(&inst.base, inst.lhs, inst.rhs, 0, 0x00); | 1000 | return try self.genX8664BinMath(&inst.base, inst.lhs, inst.rhs, 0, 0x00); |
| 989 | }, | 1001 | }, |
| 990 | .arm, .armeb => return try self.genArmBinArith(inst, .add), | 1002 | .arm, .armeb => return try self.genArmBinOp(&inst.base, inst.lhs, inst.rhs, .add), |
| 991 | else => return self.fail(inst.base.src, "TODO implement add for {}", .{self.target.cpu.arch}), | 1003 | else => return self.fail(inst.base.src, "TODO implement add for {}", .{self.target.cpu.arch}), |
| 992 | } | 1004 | } |
| 993 | } | 1005 | } |
| ... | @@ -1145,14 +1157,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -1145,14 +1157,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1145 | .x86_64 => { | 1157 | .x86_64 => { |
| 1146 | return try self.genX8664BinMath(&inst.base, inst.lhs, inst.rhs, 5, 0x28); | 1158 | return try self.genX8664BinMath(&inst.base, inst.lhs, inst.rhs, 5, 0x28); |
| 1147 | }, | 1159 | }, |
| 1148 | .arm, .armeb => return try self.genArmBinArith(inst, .sub), | 1160 | .arm, .armeb => return try self.genArmBinOp(&inst.base, inst.lhs, inst.rhs, .sub), |
| 1149 | else => return self.fail(inst.base.src, "TODO implement sub for {}", .{self.target.cpu.arch}), | 1161 | else => return self.fail(inst.base.src, "TODO implement sub for {}", .{self.target.cpu.arch}), |
| 1150 | } | 1162 | } |
| 1151 | } | 1163 | } |
| 1152 | | 1164 | |
| 1153 | fn genArmBinArith(self: *Self, inst: *ir.Inst.BinOp, op: ir.Inst.Tag) !MCValue { | 1165 | fn genArmBinOp(self: *Self, inst: *ir.Inst, op_lhs: *ir.Inst, op_rhs: *ir.Inst, op: ir.Inst.Tag) !MCValue { |
| 1154 | const lhs = try self.resolveInst(inst.lhs); | 1166 | const lhs = try self.resolveInst(op_lhs); |
| 1155 | const rhs = try self.resolveInst(inst.rhs); | 1167 | const rhs = try self.resolveInst(op_rhs); |
| 1156 | | 1168 | |
| 1157 | // Destination must be a register | 1169 | // Destination must be a register |
| 1158 | // Source may be register, memory or an immediate | 1170 | // Source may be register, memory or an immediate |
| ... | @@ -1160,9 +1172,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -1160,9 +1172,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1160 | // So there are two options: (lhs is src and rhs is dest) | 1172 | // So there are two options: (lhs is src and rhs is dest) |
| 1161 | // or (rhs is src and lhs is dest) | 1173 | // or (rhs is src and lhs is dest) |
| 1162 | const lhs_is_dest = blk: { | 1174 | const lhs_is_dest = blk: { |
| 1163 | if (self.reuseOperand(&inst.base, 0, lhs)) { | 1175 | if (self.reuseOperand(inst, 0, lhs)) { |
| 1164 | break :blk true; | 1176 | break :blk true; |
| 1165 | } else if (self.reuseOperand(&inst.base, 1, rhs)) { | 1177 | } else if (self.reuseOperand(inst, 1, rhs)) { |
| 1166 | break :blk false; | 1178 | break :blk false; |
| 1167 | } else { | 1179 | } else { |
| 1168 | break :blk lhs == .register; | 1180 | break :blk lhs == .register; |
| ... | @@ -1175,22 +1187,22 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -1175,22 +1187,22 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1175 | if (lhs_is_dest) { | 1187 | if (lhs_is_dest) { |
| 1176 | // LHS is the destination | 1188 | // LHS is the destination |
| 1177 | // RHS is the source | 1189 | // RHS is the source |
| 1178 | src_inst = inst.rhs; | 1190 | src_inst = op_rhs; |
| 1179 | src_mcv = rhs; | 1191 | src_mcv = rhs; |
| 1180 | dst_mcv = if (lhs != .register) try self.copyToNewRegister(&inst.base, lhs) else lhs; | 1192 | dst_mcv = if (lhs != .register) try self.copyToNewRegister(inst, lhs) else lhs; |
| 1181 | } else { | 1193 | } else { |
| 1182 | // RHS is the destination | 1194 | // RHS is the destination |
| 1183 | // LHS is the source | 1195 | // LHS is the source |
| 1184 | src_inst = inst.lhs; | 1196 | src_inst = op_lhs; |
| 1185 | src_mcv = lhs; | 1197 | src_mcv = lhs; |
| 1186 | dst_mcv = if (rhs != .register) try self.copyToNewRegister(&inst.base, rhs) else rhs; | 1198 | dst_mcv = if (rhs != .register) try self.copyToNewRegister(inst, rhs) else rhs; |
| 1187 | } | 1199 | } |
| 1188 | | 1200 | |
| 1189 | try self.genArmBinArithCode(inst.base.src, dst_mcv.register, src_mcv, lhs_is_dest, op); | 1201 | try self.genArmBinOpCode(inst.src, dst_mcv.register, src_mcv, lhs_is_dest, op); |
| 1190 | return dst_mcv; | 1202 | return dst_mcv; |
| 1191 | } | 1203 | } |
| 1192 | | 1204 | |
| 1193 | fn genArmBinArithCode( | 1205 | fn genArmBinOpCode( |
| 1194 | self: *Self, | 1206 | self: *Self, |
| 1195 | src: usize, | 1207 | src: usize, |
| 1196 | dst_reg: Register, | 1208 | dst_reg: Register, |
| ... | @@ -1234,7 +1246,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -1234,7 +1246,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1234 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.rsb(.al, dst_reg, dst_reg, operand).toU32()); | 1246 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.rsb(.al, dst_reg, dst_reg, operand).toU32()); |
| 1235 | } | 1247 | } |
| 1236 | }, | 1248 | }, |
| 1237 | else => unreachable, // not a binary arithmetic instruction | 1249 | .not => { |
| | 1250 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.eor(.al, dst_reg, dst_reg, operand).toU32()); |
| | 1251 | }, |
| | 1252 | else => unreachable, // not a binary instruction |
| 1238 | } | 1253 | } |
| 1239 | } | 1254 | } |
| 1240 | | 1255 | |