diff --git a/llvm/lib/Target/M68k/M68kISelLowering.cpp b/llvm/lib/Target/M68k/M68kISelLowering.cpp --- a/llvm/lib/Target/M68k/M68kISelLowering.cpp +++ b/llvm/lib/Target/M68k/M68kISelLowering.cpp @@ -73,16 +73,16 @@ setTruncStoreAction(MVT::i32, MVT::i8, Expand); setTruncStoreAction(MVT::i16, MVT::i8, Expand); - setOperationAction(ISD::MUL, MVT::i8, Promote); - setOperationAction(ISD::MUL, MVT::i16, Legal); + setOperationAction({ISD::MUL, ISD::SDIV, ISD::UDIV}, MVT::i8, Promote); + setOperationAction({ISD::MUL, ISD::SDIV, ISD::UDIV}, MVT::i16, Legal); if (Subtarget.atLeastM68020()) - setOperationAction(ISD::MUL, MVT::i32, Legal); + setOperationAction({ISD::MUL, ISD::SDIV, ISD::UDIV}, MVT::i32, Legal); else - setOperationAction(ISD::MUL, MVT::i32, LibCall); + setOperationAction({ISD::MUL, ISD::SDIV, ISD::UDIV}, MVT::i32, LibCall); setOperationAction(ISD::MUL, MVT::i64, LibCall); for (auto OP : - {ISD::SDIV, ISD::UDIV, ISD::SREM, ISD::UREM, ISD::UDIVREM, ISD::SDIVREM, + {ISD::SREM, ISD::UREM, ISD::UDIVREM, ISD::SDIVREM, ISD::MULHS, ISD::MULHU, ISD::UMUL_LOHI, ISD::SMUL_LOHI}) { setOperationAction(OP, MVT::i8, Promote); setOperationAction(OP, MVT::i16, Legal); diff --git a/llvm/lib/Target/M68k/M68kInstrArithmetic.td b/llvm/lib/Target/M68k/M68kInstrArithmetic.td --- a/llvm/lib/Target/M68k/M68kInstrArithmetic.td +++ b/llvm/lib/Target/M68k/M68kInstrArithmetic.td @@ -589,6 +589,22 @@ ); } +// $dreg <- $dreg op $dreg +class MxDiMuOp_DD_Long CMD, bit SIGNED = false> + : MxInst<(outs MxDRD32:$dst), (ins MxDRD32:$src, MxDRD32:$opd), MN#"\t$opd, $dst", []> { + let Inst = (ascend + (descend CMD, + /*MODE*/0b000, /*REGISTER*/(operand "$opd", 3)), + (descend 0b0, + // REGISTER + (operand "$dst", 3), + !if(SIGNED, 0b1, 0b0), + /*SIZE*/0b0, 0b0000000, + // Dr REGISTER + 0b000) + ); +} + // $reg <- $reg op $imm class MxDiMuOp_DI CMD, bit SIGNED = false, MxOperand DST, MxOperand OPD> @@ -618,6 +634,9 @@ defm DIV : MxDiMuOp<"div", 0x8>; +def SDIVd32d32 : MxDiMuOp_DD_Long<"divs.l", 0x131, /*SIGNED*/true>; +def UDIVd32d32 : MxDiMuOp_DD_Long<"divu.l", 0x131, /*SIGNED*/false>; + // This is used to cast immediates to 16-bits for operations which don't // support smaller immediate sizes. def as_i16imm : SDNodeXForm; +// RR i32 +def : Pat<(sdiv i32:$dst, i32:$opd), (SDIVd32d32 $dst, $opd)>; + +def : Pat<(udiv i32:$dst, i32:$opd), (UDIVd32d32 $dst, $opd)>; + + // RI i8 def : Pat<(sdiv i8:$dst, MximmSExt8:$opd), (EXTRACT_SUBREG @@ -712,6 +737,9 @@ defm MUL : MxDiMuOp<"mul", 0xC, 1>; +def SMULd32d32 : MxDiMuOp_DD_Long<"muls.l", 0x130, /*SIGNED*/true>; +def UMULd32d32 : MxDiMuOp_DD_Long<"mulu.l", 0x130, /*SIGNED*/false>; + // RR def : Pat<(mul i16:$dst, i16:$opd), (EXTRACT_SUBREG @@ -728,6 +756,8 @@ (LSR32di (LSR32di (UMULd32d16 (MOVXd32d16 $dst), $opd), 8), 8), MxSubRegIndex16Lo)>; +def : Pat<(mul i32:$dst, i32:$opd), (SMULd32d32 $dst, $opd)>; + // RI def : Pat<(mul i16:$dst, MximmSExt16:$opd), diff --git a/llvm/test/CodeGen/M68k/Arith/mul_div_32.ll b/llvm/test/CodeGen/M68k/Arith/mul_div_32.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/M68k/Arith/mul_div_32.ll @@ -0,0 +1,38 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 +; RUN: llc < %s -mtriple=m68k-linux --mcpu M68020 | FileCheck %s + +define i32 @mul32(i32 %A, i32 %B) { +; CHECK-LABEL: mul32: +; CHECK: .cfi_startproc +; CHECK-NEXT: ; %bb.0: +; CHECK-NEXT: move.l (8,%sp), %d1 +; CHECK-NEXT: move.l (4,%sp), %d0 +; CHECK-NEXT: muls.l %d1, %d0 +; CHECK-NEXT: rts + %mul = mul i32 %A, %B + ret i32 %mul +} + +define i32 @sdiv_32(i32 %A, i32 %B) { +; CHECK-LABEL: sdiv_32: +; CHECK: .cfi_startproc +; CHECK-NEXT: ; %bb.0: +; CHECK-NEXT: move.l (8,%sp), %d1 +; CHECK-NEXT: move.l (4,%sp), %d0 +; CHECK-NEXT: divs.l %d1, %d0 +; CHECK-NEXT: rts + %div = sdiv i32 %A, %B + ret i32 %div +} + +define i32 @udiv32(i32 %A, i32 %B) { +; CHECK-LABEL: udiv32: +; CHECK: .cfi_startproc +; CHECK-NEXT: ; %bb.0: +; CHECK-NEXT: move.l (8,%sp), %d1 +; CHECK-NEXT: move.l (4,%sp), %d0 +; CHECK-NEXT: divu.l %d1, %d0 +; CHECK-NEXT: rts + %div = udiv i32 %A, %B + ret i32 %div +} diff --git a/llvm/test/MC/M68k/Arith/Classes/MxDiMu.s b/llvm/test/MC/M68k/Arith/Classes/MxDiMu.s --- a/llvm/test/MC/M68k/Arith/Classes/MxDiMu.s +++ b/llvm/test/MC/M68k/Arith/Classes/MxDiMu.s @@ -12,6 +12,12 @@ ; CHECK: divu #-1, %d0 ; CHECK-SAME: encoding: [0x80,0xfc,0xff,0xff] divu #-1, %d0 +; CHECK: divs.l %d1, %d0 +; CHECK-SAME: encoding: [0x4c,0x41,0x08,0x00] +divs.l %d1, %d0 +; CHECK: divu.l %d1, %d0 +; CHECK-SAME: encoding: [0x4c,0x41,0x00,0x00] +divu.l %d1, %d0 ; CHECK: muls %d1, %d0 ; CHECK-SAME: encoding: [0xc1,0xc1] muls %d1, %d0 @@ -24,3 +30,9 @@ ; CHECK: mulu #-1, %d0 ; CHECK-SAME: encoding: [0xc0,0xfc,0xff,0xff] mulu #-1, %d0 +; CHECK: muls.l %d1, %d0 +; CHECK-SAME: encoding: [0x4c,0x01,0x08,0x00] +muls.l %d1, %d0 +; CHECK: mulu.l %d1, %d0 +; CHECK-SAME: encoding: [0x4c,0x01,0x00,0x00] +mulu.l %d1, %d0