diff --git a/src/cmd/asm/internal/asm/testdata/riscvenc.s b/src/cmd/asm/internal/asm/testdata/riscvenc.s index 21d1c40d9d8..3e9319954be 100644 --- a/src/cmd/asm/internal/asm/testdata/riscvenc.s +++ b/src/cmd/asm/internal/asm/testdata/riscvenc.s @@ -282,3 +282,25 @@ start: // real address and updates the immediates for both instructions. CALL asmtest(SB) // 970f0000 JMP asmtest(SB) // 970f0000 + + SEQZ X15, X15 // 93b71700 + SNEZ X15, X15 // b337f000 + + // F extension + FNEGS F0, F1 // d3100020 + + // TODO(jsing): FNES gets encoded as FEQS+XORI - this should + // be handled as a single *obj.Prog so that the full two + // instruction encoding is tested here. + FNES F0, F1, X7 // d3a300a0 + + // D extension + FNEGD F0, F1 // d3100022 + FEQD F0, F1, X5 // d3a200a2 + FLTD F0, F1, X5 // d39200a2 + FLED F0, F1, X5 // d38200a2 + + // TODO(jsing): FNED gets encoded as FEQD+XORI - this should + // be handled as a single *obj.Prog so that the full two + // instruction encoding is tested here. + FNED F0, F1, X5 // d3a200a2 diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index e539683d351..903b2a0eeb7 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -221,6 +221,27 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { case AFCVTWS, AFCVTLS, AFCVTWUS, AFCVTLUS, AFCVTWD, AFCVTLD, AFCVTWUD, AFCVTLUD: // Set the rounding mode in funct3 to round to zero. p.Scond = 1 + + case ASEQZ: + // SEQZ rs, rd -> SLTIU $1, rs, rd + p.As = ASLTIU + p.Reg = p.From.Reg + p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: 1} + + case ASNEZ: + // SNEZ rs, rd -> SLTU rs, x0, rd + p.As = ASLTU + p.Reg = REG_ZERO + + case AFNEGS: + // FNEGS rs, rd -> FSGNJNS rs, rs, rd + p.As = AFSGNJNS + p.Reg = p.From.Reg + + case AFNEGD: + // FNEGD rs, rd -> FSGNJND rs, rs, rd + p.As = AFSGNJND + p.Reg = p.From.Reg } } @@ -595,6 +616,37 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { jalrToSym(ctxt, p, newprog, REG_ZERO) } } + + // Replace FNE[SD] with FEQ[SD] and NOT. + case AFNES: + if p.To.Type != obj.TYPE_REG { + ctxt.Diag("progedit: FNES needs an integer register output") + } + dst := p.To.Reg + p.As = AFEQS + p = obj.Appendp(p, newprog) + + p.As = AXORI // [bit] xor 1 = not [bit] + p.From.Type = obj.TYPE_CONST + p.From.Offset = 1 + p.Reg = dst + p.To.Type = obj.TYPE_REG + p.To.Reg = dst + + case AFNED: + if p.To.Type != obj.TYPE_REG { + ctxt.Diag("progedit: FNED needs an integer register output") + } + dst := p.To.Reg + p.As = AFEQD + p = obj.Appendp(p, newprog) + + p.As = AXORI // [bit] xor 1 = not [bit] + p.From.Type = obj.TYPE_CONST + p.From.Offset = 1 + p.Reg = dst + p.To.Type = obj.TYPE_REG + p.To.Reg = dst } }