| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | package riscv |
| |
|
| | import ( |
| | "cmd/internal/obj" |
| | "cmd/internal/objabi" |
| | "cmd/internal/src" |
| | "cmd/internal/sys" |
| | "fmt" |
| | "internal/abi" |
| | "internal/buildcfg" |
| | "log" |
| | "math" |
| | "math/bits" |
| | "strings" |
| | ) |
| |
|
| | func buildop(ctxt *obj.Link) {} |
| |
|
| | func jalToSym(ctxt *obj.Link, p *obj.Prog, lr int16) { |
| | switch p.As { |
| | case obj.ACALL, obj.AJMP, obj.ARET: |
| | default: |
| | ctxt.Diag("unexpected Prog in jalToSym: %v", p) |
| | return |
| | } |
| |
|
| | p.As = AJAL |
| | p.Mark |= NEED_JAL_RELOC |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = lr |
| | p.Reg = obj.REG_NONE |
| | } |
| |
|
| | |
| | |
| | func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { |
| | insData, err := instructionDataForAs(p.As) |
| | if err != nil { |
| | panic(fmt.Sprintf("failed to lookup instruction data for %v: %v", p.As, err)) |
| | } |
| |
|
| | |
| | if p.Reg == obj.REG_NONE { |
| | if insData.ternary { |
| | p.Reg = p.To.Reg |
| | } |
| | } |
| |
|
| | |
| | |
| | if p.From.Type == obj.TYPE_CONST { |
| | switch p.As { |
| | case ACSUB: |
| | p.As, p.From.Offset = ACADDI, -p.From.Offset |
| | case ACSUBW: |
| | p.As, p.From.Offset = ACADDIW, -p.From.Offset |
| | case ASUB: |
| | p.As, p.From.Offset = AADDI, -p.From.Offset |
| | case ASUBW: |
| | p.As, p.From.Offset = AADDIW, -p.From.Offset |
| | default: |
| | if insData.immForm != obj.AXXX { |
| | p.As = insData.immForm |
| | } |
| | } |
| | } |
| |
|
| | switch p.As { |
| | case obj.AJMP: |
| | |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = REG_ZERO |
| |
|
| | switch p.To.Type { |
| | case obj.TYPE_BRANCH: |
| | p.As = AJAL |
| | case obj.TYPE_MEM: |
| | switch p.To.Name { |
| | case obj.NAME_NONE: |
| | p.As = AJALR |
| | case obj.NAME_EXTERN, obj.NAME_STATIC: |
| | |
| | default: |
| | ctxt.Diag("unsupported name %d for %v", p.To.Name, p) |
| | } |
| | default: |
| | panic(fmt.Sprintf("unhandled type %+v", p.To.Type)) |
| | } |
| |
|
| | case obj.ACALL: |
| | switch p.To.Type { |
| | case obj.TYPE_MEM: |
| | |
| | case obj.TYPE_REG: |
| | p.As = AJALR |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = REG_LR |
| | default: |
| | ctxt.Diag("unknown destination type %+v in CALL: %v", p.To.Type, p) |
| | } |
| |
|
| | case obj.AUNDEF: |
| | p.As = AEBREAK |
| |
|
| | case AFMVXS: |
| | |
| | p.As = AFMVXW |
| |
|
| | case AFMVSX: |
| | |
| | p.As = AFMVWX |
| |
|
| | case ASCALL: |
| | |
| | p.As = AECALL |
| |
|
| | case ASBREAK: |
| | |
| | p.As = AEBREAK |
| |
|
| | case AMOV: |
| | if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE && p.From.Reg == obj.REG_NONE && int64(int32(p.From.Offset)) != p.From.Offset { |
| | if isShiftConst(p.From.Offset) { |
| | break |
| | } |
| | |
| | p.From.Type = obj.TYPE_MEM |
| | p.From.Sym = ctxt.Int64Sym(p.From.Offset) |
| | p.From.Name = obj.NAME_EXTERN |
| | p.From.Offset = 0 |
| | } |
| |
|
| | case AMOVF: |
| | if p.From.Type == obj.TYPE_FCONST && p.From.Name == obj.NAME_NONE && p.From.Reg == obj.REG_NONE { |
| | f64 := p.From.Val.(float64) |
| | f32 := float32(f64) |
| | if math.Float32bits(f32) == 0 { |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = REG_ZERO |
| | break |
| | } |
| | p.From.Type = obj.TYPE_MEM |
| | p.From.Sym = ctxt.Float32Sym(f32) |
| | p.From.Name = obj.NAME_EXTERN |
| | p.From.Offset = 0 |
| | } |
| |
|
| | case AMOVD: |
| | if p.From.Type == obj.TYPE_FCONST && p.From.Name == obj.NAME_NONE && p.From.Reg == obj.REG_NONE { |
| | f64 := p.From.Val.(float64) |
| | if math.Float64bits(f64) == 0 { |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = REG_ZERO |
| | break |
| | } |
| | p.From.Type = obj.TYPE_MEM |
| | p.From.Sym = ctxt.Float64Sym(f64) |
| | p.From.Name = obj.NAME_EXTERN |
| | p.From.Offset = 0 |
| | } |
| | } |
| |
|
| | if ctxt.Flag_dynlink { |
| | rewriteToUseGot(ctxt, p, newprog) |
| | } |
| | } |
| |
|
| | |
| | func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { |
| | |
| | |
| | |
| | if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() { |
| | |
| | |
| | if p.As != AMOV { |
| | ctxt.Diag("don't know how to handle TYPE_ADDR in %v with -dynlink", p) |
| | } |
| | if p.To.Type != obj.TYPE_REG { |
| | ctxt.Diag("don't know how to handle LD instruction to non-register in %v with -dynlink", p) |
| | } |
| | p.From.Type = obj.TYPE_MEM |
| | p.From.Name = obj.NAME_GOTREF |
| | if p.From.Offset != 0 { |
| | q := obj.Appendp(p, newprog) |
| | q.As = AADD |
| | q.From.Type = obj.TYPE_CONST |
| | q.From.Offset = p.From.Offset |
| | q.To = p.To |
| | p.From.Offset = 0 |
| | } |
| |
|
| | } |
| |
|
| | if p.GetFrom3() != nil && p.GetFrom3().Name == obj.NAME_EXTERN { |
| | ctxt.Diag("don't know how to handle %v with -dynlink", p) |
| | } |
| |
|
| | var source *obj.Addr |
| | |
| | |
| | |
| | if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() { |
| | if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() { |
| | ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p) |
| | } |
| | source = &p.From |
| | } else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() { |
| | source = &p.To |
| | } else { |
| | return |
| | } |
| | if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP { |
| | return |
| | } |
| | if source.Sym.Type == objabi.STLSBSS { |
| | return |
| | } |
| | if source.Type != obj.TYPE_MEM { |
| | ctxt.Diag("don't know how to handle %v with -dynlink", p) |
| | } |
| | p1 := obj.Appendp(p, newprog) |
| | p1.As = AMOV |
| | p1.From.Type = obj.TYPE_MEM |
| | p1.From.Sym = source.Sym |
| | p1.From.Name = obj.NAME_GOTREF |
| | p1.To.Type = obj.TYPE_REG |
| | p1.To.Reg = REG_TMP |
| |
|
| | p2 := obj.Appendp(p1, newprog) |
| | p2.As = p.As |
| | p2.From = p.From |
| | p2.To = p.To |
| | if p.From.Name == obj.NAME_EXTERN { |
| | p2.From.Reg = REG_TMP |
| | p2.From.Name = obj.NAME_NONE |
| | p2.From.Sym = nil |
| | } else if p.To.Name == obj.NAME_EXTERN { |
| | p2.To.Reg = REG_TMP |
| | p2.To.Name = obj.NAME_NONE |
| | p2.To.Sym = nil |
| | } else { |
| | return |
| | } |
| | obj.Nopout(p) |
| |
|
| | } |
| |
|
| | |
| | func addrToReg(a obj.Addr) int16 { |
| | switch a.Name { |
| | case obj.NAME_PARAM, obj.NAME_AUTO: |
| | return REG_SP |
| | } |
| | return a.Reg |
| | } |
| |
|
| | |
| | func movToLoad(mnemonic obj.As) obj.As { |
| | switch mnemonic { |
| | case AMOV: |
| | return ALD |
| | case AMOVB: |
| | return ALB |
| | case AMOVH: |
| | return ALH |
| | case AMOVW: |
| | return ALW |
| | case AMOVBU: |
| | return ALBU |
| | case AMOVHU: |
| | return ALHU |
| | case AMOVWU: |
| | return ALWU |
| | case AMOVF: |
| | return AFLW |
| | case AMOVD: |
| | return AFLD |
| | default: |
| | panic(fmt.Sprintf("%+v is not a MOV", mnemonic)) |
| | } |
| | } |
| |
|
| | |
| | func movToStore(mnemonic obj.As) obj.As { |
| | switch mnemonic { |
| | case AMOV: |
| | return ASD |
| | case AMOVB: |
| | return ASB |
| | case AMOVH: |
| | return ASH |
| | case AMOVW: |
| | return ASW |
| | case AMOVF: |
| | return AFSW |
| | case AMOVD: |
| | return AFSD |
| | default: |
| | panic(fmt.Sprintf("%+v is not a MOV", mnemonic)) |
| | } |
| | } |
| |
|
| | |
| | |
| | func markRelocs(p *obj.Prog) { |
| | switch p.As { |
| | case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD: |
| | switch { |
| | case p.From.Type == obj.TYPE_ADDR && p.To.Type == obj.TYPE_REG: |
| | switch p.From.Name { |
| | case obj.NAME_EXTERN, obj.NAME_STATIC: |
| | p.Mark |= NEED_PCREL_ITYPE_RELOC |
| | case obj.NAME_GOTREF: |
| | p.Mark |= NEED_GOT_PCREL_ITYPE_RELOC |
| | } |
| | case p.From.Type == obj.TYPE_MEM && p.To.Type == obj.TYPE_REG: |
| | switch p.From.Name { |
| | case obj.NAME_EXTERN, obj.NAME_STATIC: |
| | p.Mark |= NEED_PCREL_ITYPE_RELOC |
| | case obj.NAME_GOTREF: |
| | p.Mark |= NEED_GOT_PCREL_ITYPE_RELOC |
| | } |
| | case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_MEM: |
| | switch p.To.Name { |
| | case obj.NAME_EXTERN, obj.NAME_STATIC: |
| | p.Mark |= NEED_PCREL_STYPE_RELOC |
| | } |
| | } |
| | } |
| | } |
| |
|
| | |
| | func InvertBranch(as obj.As) obj.As { |
| | switch as { |
| | case ABEQ: |
| | return ABNE |
| | case ABEQZ: |
| | return ABNEZ |
| | case ABGE: |
| | return ABLT |
| | case ABGEU: |
| | return ABLTU |
| | case ABGEZ: |
| | return ABLTZ |
| | case ABGT: |
| | return ABLE |
| | case ABGTU: |
| | return ABLEU |
| | case ABGTZ: |
| | return ABLEZ |
| | case ABLE: |
| | return ABGT |
| | case ABLEU: |
| | return ABGTU |
| | case ABLEZ: |
| | return ABGTZ |
| | case ABLT: |
| | return ABGE |
| | case ABLTU: |
| | return ABGEU |
| | case ABLTZ: |
| | return ABGEZ |
| | case ABNE: |
| | return ABEQ |
| | case ABNEZ: |
| | return ABEQZ |
| | case ACBEQZ: |
| | return ACBNEZ |
| | case ACBNEZ: |
| | return ACBEQZ |
| | default: |
| | panic("InvertBranch: not a branch") |
| | } |
| | } |
| |
|
| | |
| | |
| | func containsCall(sym *obj.LSym) bool { |
| | |
| | for p := sym.Func().Text; p != nil; p = p.Link { |
| | switch p.As { |
| | case obj.ACALL: |
| | return true |
| | case ACJALR, AJAL, AJALR: |
| | if p.From.Type == obj.TYPE_REG && p.From.Reg == REG_LR { |
| | return true |
| | } |
| | } |
| | } |
| |
|
| | return false |
| | } |
| |
|
| | |
| | |
| | func setPCs(p *obj.Prog, pc int64, compress bool) int64 { |
| | for ; p != nil; p = p.Link { |
| | p.Pc = pc |
| | for _, ins := range instructionsForProg(p, compress) { |
| | pc += int64(ins.length()) |
| | } |
| |
|
| | if p.As == obj.APCALIGN { |
| | alignedValue := p.From.Offset |
| | v := pcAlignPadLength(pc, alignedValue) |
| | pc += int64(v) |
| | } |
| | } |
| | return pc |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | func stackOffset(a *obj.Addr, stacksize int64) { |
| | switch a.Name { |
| | case obj.NAME_AUTO: |
| | |
| | a.Offset += stacksize |
| | case obj.NAME_PARAM: |
| | |
| | a.Offset += stacksize + 8 |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { |
| | if cursym.Func().Text == nil || cursym.Func().Text.Link == nil { |
| | return |
| | } |
| |
|
| | |
| | text := cursym.Func().Text |
| | if text.As != obj.ATEXT { |
| | ctxt.Diag("preprocess: found symbol that does not start with TEXT directive") |
| | return |
| | } |
| |
|
| | stacksize := text.To.Offset |
| | if stacksize == -8 { |
| | |
| | text.From.Sym.Set(obj.AttrNoFrame, true) |
| | stacksize = 0 |
| | } |
| | if stacksize < 0 { |
| | ctxt.Diag("negative frame size %d - did you mean NOFRAME?", stacksize) |
| | } |
| | if text.From.Sym.NoFrame() { |
| | if stacksize != 0 { |
| | ctxt.Diag("NOFRAME functions must have a frame size of 0, not %d", stacksize) |
| | } |
| | } |
| |
|
| | if !containsCall(cursym) { |
| | text.From.Sym.Set(obj.AttrLeaf, true) |
| | if stacksize == 0 { |
| | |
| | text.From.Sym.Set(obj.AttrNoFrame, true) |
| | } |
| | } |
| |
|
| | |
| | if !text.From.Sym.NoFrame() { |
| | stacksize += ctxt.Arch.FixedFrameSize |
| | } |
| |
|
| | cursym.Func().Args = text.To.Val.(int32) |
| | cursym.Func().Locals = int32(stacksize) |
| |
|
| | prologue := text |
| |
|
| | if !cursym.Func().Text.From.Sym.NoSplit() { |
| | prologue = stacksplit(ctxt, prologue, cursym, newprog, stacksize) |
| | } |
| |
|
| | q := prologue |
| |
|
| | if stacksize != 0 { |
| | prologue = ctxt.StartUnsafePoint(prologue, newprog) |
| |
|
| | |
| | prologue = obj.Appendp(prologue, newprog) |
| | prologue.As = AMOV |
| | prologue.Pos = q.Pos |
| | prologue.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR} |
| | prologue.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: -stacksize} |
| |
|
| | |
| | prologue = obj.Appendp(prologue, newprog) |
| | prologue.As = AADDI |
| | prologue.Pos = q.Pos |
| | prologue.Pos = prologue.Pos.WithXlogue(src.PosPrologueEnd) |
| | prologue.From = obj.Addr{Type: obj.TYPE_CONST, Offset: -stacksize} |
| | prologue.Reg = REG_SP |
| | prologue.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP} |
| | prologue.Spadj = int32(stacksize) |
| |
|
| | prologue = ctxt.EndUnsafePoint(prologue, newprog, -1) |
| |
|
| | |
| | |
| | |
| | |
| | |
| | prologue = obj.Appendp(prologue, newprog) |
| | prologue.As = AMOV |
| | prologue.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR} |
| | prologue.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 0} |
| | } |
| |
|
| | |
| | for p := cursym.Func().Text; p != nil; p = p.Link { |
| | stackOffset(&p.From, stacksize) |
| | stackOffset(&p.To, stacksize) |
| | } |
| |
|
| | |
| | for p := cursym.Func().Text; p != nil; p = p.Link { |
| | switch p.As { |
| | case obj.AGETCALLERPC: |
| | if cursym.Leaf() { |
| | |
| | p.As = AMOV |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = REG_LR |
| | } else { |
| | |
| | p.As = AMOV |
| | p.From.Type = obj.TYPE_MEM |
| | p.From.Reg = REG_SP |
| | } |
| |
|
| | case obj.ACALL: |
| | switch p.To.Type { |
| | case obj.TYPE_MEM: |
| | jalToSym(ctxt, p, REG_LR) |
| | } |
| |
|
| | case obj.AJMP: |
| | switch p.To.Type { |
| | case obj.TYPE_MEM: |
| | switch p.To.Name { |
| | case obj.NAME_EXTERN, obj.NAME_STATIC: |
| | jalToSym(ctxt, p, REG_ZERO) |
| | } |
| | } |
| |
|
| | case obj.ARET: |
| | |
| | retJMP := p.To.Sym |
| |
|
| | if stacksize != 0 { |
| | |
| | p.As = AMOV |
| | p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 0} |
| | p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR} |
| | p = obj.Appendp(p, newprog) |
| |
|
| | p.As = AADDI |
| | p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: stacksize} |
| | p.Reg = REG_SP |
| | p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP} |
| | p.Spadj = int32(-stacksize) |
| | p = obj.Appendp(p, newprog) |
| | } |
| |
|
| | if retJMP != nil { |
| | p.As = obj.ARET |
| | p.To.Sym = retJMP |
| | jalToSym(ctxt, p, REG_ZERO) |
| | } else { |
| | p.As = AJALR |
| | p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO} |
| | p.Reg = obj.REG_NONE |
| | p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR} |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | p.Spadj = int32(stacksize) |
| |
|
| | case AADDI: |
| | |
| | if p.To.Type == obj.TYPE_REG && p.To.Reg == REG_SP && p.From.Type == obj.TYPE_CONST { |
| | p.Spadj = int32(-p.From.Offset) |
| | } |
| | } |
| |
|
| | if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.Spadj == 0 { |
| | f := cursym.Func() |
| | if f.FuncFlag&abi.FuncFlagSPWrite == 0 { |
| | f.FuncFlag |= abi.FuncFlagSPWrite |
| | if ctxt.Debugvlog || !ctxt.IsAsm { |
| | ctxt.Logf("auto-SPWRITE: %s %v\n", cursym.Name, p) |
| | if !ctxt.IsAsm { |
| | ctxt.Diag("invalid auto-SPWRITE in non-assembly") |
| | ctxt.DiagFlush() |
| | log.Fatalf("bad SPWRITE") |
| | } |
| | } |
| | } |
| | } |
| | } |
| |
|
| | var callCount int |
| | for p := cursym.Func().Text; p != nil; p = p.Link { |
| | markRelocs(p) |
| | if p.Mark&NEED_JAL_RELOC == NEED_JAL_RELOC { |
| | callCount++ |
| | } |
| | } |
| | const callTrampSize = 8 |
| | maxTrampSize := int64(callCount * callTrampSize) |
| |
|
| | |
| | |
| | |
| | |
| | for { |
| | big, rescan := false, false |
| | maxPC := setPCs(cursym.Func().Text, 0, ctxt.CompressInstructions) |
| | if maxPC+maxTrampSize > (1 << 20) { |
| | big = true |
| | } |
| |
|
| | for p := cursym.Func().Text; p != nil; p = p.Link { |
| | switch p.As { |
| | case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ, ACBEQZ, ACBNEZ, ACJ: |
| | if p.To.Type != obj.TYPE_BRANCH { |
| | ctxt.Diag("%v: instruction with branch-like opcode lacks destination", p) |
| | break |
| | } |
| | offset := p.To.Target().Pc - p.Pc |
| | if offset < -4096 || 4096 <= offset { |
| | |
| | jmp := obj.Appendp(p, newprog) |
| | jmp.As = AJAL |
| | jmp.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO} |
| | jmp.To = obj.Addr{Type: obj.TYPE_BRANCH} |
| | jmp.To.SetTarget(p.To.Target()) |
| |
|
| | p.As = InvertBranch(p.As) |
| | p.To.SetTarget(jmp.Link) |
| |
|
| | |
| | |
| | rescan = true |
| | } |
| | case AJAL: |
| | |
| | if p.To.Target() == nil { |
| | if !big { |
| | break |
| | } |
| | |
| | |
| | jmp := obj.Appendp(p, newprog) |
| | jmp.As = AJALR |
| | jmp.From = p.From |
| | jmp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP} |
| |
|
| | p.As = AAUIPC |
| | p.Mark = (p.Mark &^ NEED_JAL_RELOC) | NEED_CALL_RELOC |
| | p.AddRestSource(obj.Addr{Type: obj.TYPE_CONST, Offset: p.To.Offset, Sym: p.To.Sym}) |
| | p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: 0} |
| | p.Reg = obj.REG_NONE |
| | p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP} |
| |
|
| | rescan = true |
| | break |
| | } |
| | offset := p.To.Target().Pc - p.Pc |
| | if offset < -(1<<20) || (1<<20) <= offset { |
| | |
| | |
| | |
| | jmp := obj.Appendp(p, newprog) |
| | jmp.As = AJALR |
| | jmp.From = p.From |
| | jmp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP} |
| |
|
| | |
| | |
| | p.As = AAUIPC |
| | p.From = obj.Addr{Type: obj.TYPE_BRANCH, Sym: p.From.Sym} |
| | p.From.SetTarget(p.To.Target()) |
| | p.Reg = obj.REG_NONE |
| | p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP} |
| |
|
| | rescan = true |
| | } |
| | } |
| | } |
| |
|
| | |
| | |
| | if ctxt.Errors > 0 { |
| | return |
| | } |
| | if !rescan { |
| | break |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | for p := cursym.Func().Text; p != nil; p = p.Link { |
| | switch p.As { |
| | case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ, ACBEQZ, ACBNEZ, ACJ: |
| | switch p.To.Type { |
| | case obj.TYPE_BRANCH: |
| | p.To.Type, p.To.Offset = obj.TYPE_CONST, p.To.Target().Pc-p.Pc |
| | case obj.TYPE_MEM: |
| | if ctxt.Errors == 0 { |
| | |
| | panic("unhandled type") |
| | } |
| | } |
| |
|
| | case AJAL: |
| | |
| | if p.To.Target() != nil { |
| | p.To.Type, p.To.Offset = obj.TYPE_CONST, p.To.Target().Pc-p.Pc |
| | } |
| |
|
| | case AAUIPC: |
| | if p.From.Type == obj.TYPE_BRANCH { |
| | low, high, err := Split32BitImmediate(p.From.Target().Pc - p.Pc) |
| | if err != nil { |
| | ctxt.Diag("%v: jump displacement %d too large", p, p.To.Target().Pc-p.Pc) |
| | } |
| | p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: high, Sym: cursym} |
| | p.Link.To.Offset = low |
| | } |
| |
|
| | case obj.APCALIGN: |
| | alignedValue := p.From.Offset |
| | if (alignedValue&(alignedValue-1) != 0) || 4 > alignedValue || alignedValue > 2048 { |
| | ctxt.Diag("alignment value of an instruction must be a power of two and in the range [4, 2048], got %d\n", alignedValue) |
| | } |
| | |
| | if int32(alignedValue) > cursym.Func().Align { |
| | cursym.Func().Align = int32(alignedValue) |
| | } |
| | } |
| | } |
| |
|
| | |
| | for p := cursym.Func().Text; p != nil; p = p.Link { |
| | for _, ins := range instructionsForProg(p, ctxt.CompressInstructions) { |
| | ins.validate(ctxt) |
| | } |
| | } |
| | } |
| |
|
| | func pcAlignPadLength(pc int64, alignedValue int64) int { |
| | return int(-pc & (alignedValue - 1)) |
| | } |
| |
|
| | func stacksplit(ctxt *obj.Link, p *obj.Prog, cursym *obj.LSym, newprog obj.ProgAlloc, framesize int64) *obj.Prog { |
| | |
| | if framesize == 0 { |
| | return p |
| | } |
| |
|
| | if ctxt.Flag_maymorestack != "" { |
| | |
| | const frameSize = 16 |
| | p = ctxt.StartUnsafePoint(p, newprog) |
| |
|
| | |
| | |
| | p = cursym.Func().SpillRegisterArgs(p, newprog) |
| |
|
| | |
| | p = obj.Appendp(p, newprog) |
| | p.As = AMOV |
| | p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR} |
| | p.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: -frameSize} |
| | |
| | p = obj.Appendp(p, newprog) |
| | p.As = AADDI |
| | p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: -frameSize} |
| | p.Reg = REG_SP |
| | p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP} |
| | p.Spadj = frameSize |
| | |
| | p = obj.Appendp(p, newprog) |
| | p.As = AMOV |
| | p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_CTXT} |
| | p.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 8} |
| |
|
| | |
| | p = obj.Appendp(p, newprog) |
| | p.As = obj.ACALL |
| | p.To.Type = obj.TYPE_BRANCH |
| | |
| | p.To.Sym = ctxt.LookupABI(ctxt.Flag_maymorestack, cursym.ABI()) |
| | jalToSym(ctxt, p, REG_X5) |
| |
|
| | |
| |
|
| | |
| | p = obj.Appendp(p, newprog) |
| | p.As = AMOV |
| | p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 8} |
| | p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_CTXT} |
| | |
| | p = obj.Appendp(p, newprog) |
| | p.As = AMOV |
| | p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 0} |
| | p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR} |
| | |
| | p = obj.Appendp(p, newprog) |
| | p.As = AADDI |
| | p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: frameSize} |
| | p.Reg = REG_SP |
| | p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP} |
| | p.Spadj = -frameSize |
| |
|
| | |
| | p = cursym.Func().UnspillRegisterArgs(p, newprog) |
| | p = ctxt.EndUnsafePoint(p, newprog, -1) |
| | } |
| |
|
| | |
| | startPred := p |
| |
|
| | |
| | p = obj.Appendp(p, newprog) |
| | p.As = AMOV |
| | p.From.Type = obj.TYPE_MEM |
| | p.From.Reg = REGG |
| | p.From.Offset = 2 * int64(ctxt.Arch.PtrSize) |
| | if cursym.CFunc() { |
| | p.From.Offset = 3 * int64(ctxt.Arch.PtrSize) |
| | } |
| | p.To.Type = obj.TYPE_REG |
| | p.To.Reg = REG_X6 |
| |
|
| | |
| | |
| | |
| | |
| | p = ctxt.StartUnsafePoint(p, newprog) |
| |
|
| | var to_done, to_more *obj.Prog |
| |
|
| | if framesize <= abi.StackSmall { |
| | |
| | |
| | |
| | p = obj.Appendp(p, newprog) |
| | p.As = ABLTU |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = REG_X6 |
| | p.Reg = REG_SP |
| | p.To.Type = obj.TYPE_BRANCH |
| | to_done = p |
| | } else { |
| | |
| | offset := framesize - abi.StackSmall |
| | if framesize > abi.StackBig { |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | p = obj.Appendp(p, newprog) |
| | p.As = AMOV |
| | p.From.Type = obj.TYPE_CONST |
| | p.From.Offset = offset |
| | p.To.Type = obj.TYPE_REG |
| | p.To.Reg = REG_X7 |
| |
|
| | p = obj.Appendp(p, newprog) |
| | p.As = ABLTU |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = REG_SP |
| | p.Reg = REG_X7 |
| | p.To.Type = obj.TYPE_BRANCH |
| | to_more = p |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | p = obj.Appendp(p, newprog) |
| | p.As = AADDI |
| | p.From.Type = obj.TYPE_CONST |
| | p.From.Offset = -offset |
| | p.Reg = REG_SP |
| | p.To.Type = obj.TYPE_REG |
| | p.To.Reg = REG_X7 |
| |
|
| | p = obj.Appendp(p, newprog) |
| | p.As = ABLTU |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = REG_X6 |
| | p.Reg = REG_X7 |
| | p.To.Type = obj.TYPE_BRANCH |
| | to_done = p |
| | } |
| |
|
| | |
| | |
| | p = ctxt.EmitEntryStackMap(cursym, p, newprog) |
| | p = cursym.Func().SpillRegisterArgs(p, newprog) |
| |
|
| | |
| | p = obj.Appendp(p, newprog) |
| | p.As = obj.ACALL |
| | p.To.Type = obj.TYPE_BRANCH |
| |
|
| | if cursym.CFunc() { |
| | p.To.Sym = ctxt.Lookup("runtime.morestackc") |
| | } else if !cursym.Func().Text.From.Sym.NeedCtxt() { |
| | p.To.Sym = ctxt.Lookup("runtime.morestack_noctxt") |
| | } else { |
| | p.To.Sym = ctxt.Lookup("runtime.morestack") |
| | } |
| | if to_more != nil { |
| | to_more.To.SetTarget(p) |
| | } |
| | jalToSym(ctxt, p, REG_X5) |
| |
|
| | |
| | p = ctxt.EndUnsafePoint(p, newprog, -1) |
| | p = cursym.Func().UnspillRegisterArgs(p, newprog) |
| |
|
| | |
| | p = obj.Appendp(p, newprog) |
| | p.As = AJAL |
| | p.To = obj.Addr{Type: obj.TYPE_BRANCH} |
| | p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO} |
| | p.To.SetTarget(startPred.Link) |
| |
|
| | |
| | p = obj.Appendp(p, newprog) |
| | p.As = obj.ANOP |
| | to_done.To.SetTarget(p) |
| |
|
| | return p |
| | } |
| |
|
| | |
| | func signExtend(val int64, bit uint) int64 { |
| | return val << (64 - bit) >> (64 - bit) |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | func Split32BitImmediate(imm int64) (low, high int64, err error) { |
| | if err := immIFits(imm, 32); err != nil { |
| | return 0, 0, err |
| | } |
| |
|
| | |
| | if err := immIFits(imm, 12); err == nil { |
| | return imm, 0, nil |
| | } |
| |
|
| | high = imm >> 12 |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | if imm&(1<<11) != 0 { |
| | high++ |
| | } |
| |
|
| | low = signExtend(imm, 12) |
| | high = signExtend(high, 20) |
| |
|
| | return low, high, nil |
| | } |
| |
|
| | func regVal(r, min, max uint32) uint32 { |
| | if r < min || r > max { |
| | panic(fmt.Sprintf("register out of range, want %d <= %d <= %d", min, r, max)) |
| | } |
| | return r - min |
| | } |
| |
|
| | |
| | func regCI(r uint32) uint32 { |
| | return regVal(r, REG_X8, REG_X15) |
| | } |
| |
|
| | |
| | func regCF(r uint32) uint32 { |
| | return regVal(r, REG_F8, REG_F15) |
| | } |
| |
|
| | |
| | func regI(r uint32) uint32 { |
| | return regVal(r, REG_X0, REG_X31) |
| | } |
| |
|
| | |
| | func regF(r uint32) uint32 { |
| | return regVal(r, REG_F0, REG_F31) |
| | } |
| |
|
| | |
| | func regV(r uint32) uint32 { |
| | return regVal(r, REG_V0, REG_V31) |
| | } |
| |
|
| | |
| | |
| | func immEven(x int64) error { |
| | if x&1 != 0 { |
| | return fmt.Errorf("immediate %#x is not a multiple of two", x) |
| | } |
| | return nil |
| | } |
| |
|
| | func immFits(x int64, nbits uint, signed bool) error { |
| | label := "unsigned" |
| | min, max := int64(0), int64(1)<<nbits-1 |
| | if signed { |
| | label = "signed" |
| | sbits := nbits - 1 |
| | min, max = int64(-1)<<sbits, int64(1)<<sbits-1 |
| | } |
| | if x < min || x > max { |
| | if nbits <= 16 { |
| | return fmt.Errorf("%s immediate %d must be in range [%d, %d] (%d bits)", label, x, min, max, nbits) |
| | } |
| | return fmt.Errorf("%s immediate %#x must be in range [%#x, %#x] (%d bits)", label, x, min, max, nbits) |
| | } |
| | return nil |
| | } |
| |
|
| | |
| | |
| | func immIFits(x int64, nbits uint) error { |
| | return immFits(x, nbits, true) |
| | } |
| |
|
| | |
| | func immI(as obj.As, imm int64, nbits uint) uint32 { |
| | if err := immIFits(imm, nbits); err != nil { |
| | panic(fmt.Sprintf("%v: %v", as, err)) |
| | } |
| | return uint32(imm) & ((1 << nbits) - 1) |
| | } |
| |
|
| | func wantImmI(ctxt *obj.Link, ins *instruction, imm int64, nbits uint) { |
| | if err := immIFits(imm, nbits); err != nil { |
| | ctxt.Diag("%v: %v", ins, err) |
| | } |
| | } |
| |
|
| | |
| | |
| | func immUFits(x int64, nbits uint) error { |
| | return immFits(x, nbits, false) |
| | } |
| |
|
| | |
| | func immU(as obj.As, imm int64, nbits uint) uint32 { |
| | if err := immUFits(imm, nbits); err != nil { |
| | panic(fmt.Sprintf("%v: %v", as, err)) |
| | } |
| | return uint32(imm) & ((1 << nbits) - 1) |
| | } |
| |
|
| | func wantImmU(ctxt *obj.Link, ins *instruction, imm int64, nbits uint) { |
| | if err := immUFits(imm, nbits); err != nil { |
| | ctxt.Diag("%v: %v", ins, err) |
| | } |
| | } |
| |
|
| | func isScaledImmI(imm int64, nbits uint, scale int64) bool { |
| | return immFits(imm, nbits, true) == nil && imm%scale == 0 |
| | } |
| |
|
| | func isScaledImmU(imm int64, nbits uint, scale int64) bool { |
| | return immFits(imm, nbits, false) == nil && imm%scale == 0 |
| | } |
| |
|
| | func wantScaledImm(ctxt *obj.Link, ins *instruction, imm int64, nbits uint, scale int64, signed bool) { |
| | if err := immFits(imm, nbits, signed); err != nil { |
| | ctxt.Diag("%v: %v", ins, err) |
| | return |
| | } |
| | if imm%scale != 0 { |
| | ctxt.Diag("%v: unsigned immediate %d must be a multiple of %d", ins, imm, scale) |
| | } |
| | } |
| |
|
| | func wantScaledImmI(ctxt *obj.Link, ins *instruction, imm int64, nbits uint, scale int64) { |
| | wantScaledImm(ctxt, ins, imm, nbits, scale, true) |
| | } |
| |
|
| | func wantScaledImmU(ctxt *obj.Link, ins *instruction, imm int64, nbits uint, scale int64) { |
| | wantScaledImm(ctxt, ins, imm, nbits, scale, false) |
| | } |
| |
|
| | func wantReg(ctxt *obj.Link, ins *instruction, pos string, descr string, r, min, max uint32) { |
| | if r < min || r > max { |
| | var suffix string |
| | if r != obj.REG_NONE { |
| | suffix = fmt.Sprintf(" but got non-%s register %s", descr, RegName(int(r))) |
| | } |
| | ctxt.Diag("%v: expected %s register in %s position%s", ins, descr, pos, suffix) |
| | } |
| | } |
| |
|
| | func wantNoneReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) { |
| | if r != obj.REG_NONE { |
| | ctxt.Diag("%v: expected no register in %s but got register %s", ins, pos, RegName(int(r))) |
| | } |
| | } |
| |
|
| | |
| | func wantIntReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) { |
| | wantReg(ctxt, ins, pos, "integer", r, REG_X0, REG_X31) |
| | } |
| |
|
| | func isIntPrimeReg(r uint32) bool { |
| | return r >= REG_X8 && r <= REG_X15 |
| | } |
| |
|
| | |
| | |
| | func wantIntPrimeReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) { |
| | wantReg(ctxt, ins, pos, "integer prime", r, REG_X8, REG_X15) |
| | } |
| |
|
| | |
| | func wantFloatReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) { |
| | wantReg(ctxt, ins, pos, "float", r, REG_F0, REG_F31) |
| | } |
| |
|
| | func isFloatPrimeReg(r uint32) bool { |
| | return r >= REG_F8 && r <= REG_F15 |
| | } |
| |
|
| | |
| | |
| | func wantFloatPrimeReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) { |
| | wantReg(ctxt, ins, pos, "float prime", r, REG_F8, REG_F15) |
| | } |
| |
|
| | |
| | func wantVectorReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) { |
| | wantReg(ctxt, ins, pos, "vector", r, REG_V0, REG_V31) |
| | } |
| |
|
| | |
| | func wantEvenOffset(ctxt *obj.Link, ins *instruction, offset int64) { |
| | if err := immEven(offset); err != nil { |
| | ctxt.Diag("%v: %v", ins, err) |
| | } |
| | } |
| |
|
| | func validateCA(ctxt *obj.Link, ins *instruction) { |
| | wantIntPrimeReg(ctxt, ins, "rd", ins.rd) |
| | if ins.rd != ins.rs1 { |
| | ctxt.Diag("%v: rd must be the same as rs1", ins) |
| | } |
| | wantIntPrimeReg(ctxt, ins, "rs2", ins.rs2) |
| | } |
| |
|
| | func validateCB(ctxt *obj.Link, ins *instruction) { |
| | if (ins.as == ACSRAI || ins.as == ACSRLI) && ins.imm == 0 { |
| | ctxt.Diag("%v: immediate cannot be zero", ins) |
| | } else if ins.as == ACSRAI || ins.as == ACSRLI { |
| | wantImmU(ctxt, ins, ins.imm, 6) |
| | } else if ins.as == ACBEQZ || ins.as == ACBNEZ { |
| | wantImmI(ctxt, ins, ins.imm, 9) |
| | } else { |
| | wantImmI(ctxt, ins, ins.imm, 6) |
| | } |
| | if ins.as == ACBEQZ || ins.as == ACBNEZ { |
| | wantNoneReg(ctxt, ins, "rd", ins.rd) |
| | wantIntPrimeReg(ctxt, ins, "rs1", ins.rs1) |
| | } else { |
| | wantIntPrimeReg(ctxt, ins, "rd", ins.rd) |
| | if ins.rd != ins.rs1 { |
| | ctxt.Diag("%v: rd must be the same as rs1", ins) |
| | } |
| | } |
| | wantNoneReg(ctxt, ins, "rs2", ins.rs2) |
| | } |
| |
|
| | func validateCI(ctxt *obj.Link, ins *instruction) { |
| | if ins.as != ACNOP && ins.rd == REG_X0 { |
| | ctxt.Diag("%v: cannot use register X0 in rd", ins) |
| | } |
| | if ins.as == ACLUI && ins.rd == REG_X2 { |
| | ctxt.Diag("%v: cannot use register SP/X2 in rd", ins) |
| | } |
| | if ins.as != ACLI && ins.as != ACLUI && ins.as != ACLWSP && ins.as != ACLDSP && ins.as != ACFLDSP && ins.rd != ins.rs1 { |
| | ctxt.Diag("%v: rd must be the same as rs1", ins) |
| | } |
| | if ins.as == ACADDI16SP && ins.rd != REG_SP { |
| | ctxt.Diag("%v: rd must be SP/X2", ins) |
| | } |
| | if (ins.as == ACLWSP || ins.as == ACLDSP || ins.as == ACFLDSP) && ins.rs2 != REG_SP { |
| | ctxt.Diag("%v: rs2 must be SP/X2", ins) |
| | } |
| | if (ins.as == ACADDI || ins.as == ACADDI16SP || ins.as == ACLUI || ins.as == ACSLLI) && ins.imm == 0 { |
| | ctxt.Diag("%v: immediate cannot be zero", ins) |
| | } else if ins.as == ACSLLI { |
| | wantImmU(ctxt, ins, ins.imm, 6) |
| | } else if ins.as == ACLWSP { |
| | wantScaledImmU(ctxt, ins, ins.imm, 8, 4) |
| | } else if ins.as == ACLDSP || ins.as == ACFLDSP { |
| | wantScaledImmU(ctxt, ins, ins.imm, 9, 8) |
| | } else if ins.as == ACADDI16SP { |
| | wantScaledImmI(ctxt, ins, ins.imm, 10, 16) |
| | } else { |
| | wantImmI(ctxt, ins, ins.imm, 6) |
| | } |
| | switch ins.as { |
| | case ACNOP, ACADDI, ACADDIW, ACSLLI: |
| | wantIntReg(ctxt, ins, "rd", ins.rd) |
| | wantIntReg(ctxt, ins, "rs1", ins.rs1) |
| | wantNoneReg(ctxt, ins, "rs2", ins.rs2) |
| | case ACLWSP, ACLDSP: |
| | wantIntReg(ctxt, ins, "rd", ins.rd) |
| | wantNoneReg(ctxt, ins, "rs1", ins.rs1) |
| | wantIntReg(ctxt, ins, "rs2", ins.rs2) |
| | case ACFLDSP: |
| | wantFloatReg(ctxt, ins, "rd", ins.rd) |
| | wantNoneReg(ctxt, ins, "rs1", ins.rs1) |
| | wantIntReg(ctxt, ins, "rs2", ins.rs2) |
| | case ACADDI16SP: |
| | wantIntReg(ctxt, ins, "rd", ins.rd) |
| | wantIntReg(ctxt, ins, "rs1", ins.rs1) |
| | wantNoneReg(ctxt, ins, "rs2", ins.rs2) |
| | default: |
| | wantIntReg(ctxt, ins, "rd", ins.rd) |
| | wantNoneReg(ctxt, ins, "rs1", ins.rs1) |
| | wantNoneReg(ctxt, ins, "rs2", ins.rs2) |
| | } |
| | } |
| |
|
| | func validateCIW(ctxt *obj.Link, ins *instruction) { |
| | wantScaledImmU(ctxt, ins, ins.imm, 10, 4) |
| | wantIntPrimeReg(ctxt, ins, "rd", ins.rd) |
| | wantIntReg(ctxt, ins, "rs1", ins.rs1) |
| | wantNoneReg(ctxt, ins, "rs2", ins.rs2) |
| | if ins.imm == 0 { |
| | ctxt.Diag("%v: immediate cannot be zero", ins) |
| | } |
| | if ins.rs1 != REG_SP { |
| | ctxt.Diag("%v: SP/X2 must be in rs1", ins) |
| | } |
| | } |
| |
|
| | func validateCJ(ctxt *obj.Link, ins *instruction) { |
| | wantEvenOffset(ctxt, ins, ins.imm) |
| | wantImmI(ctxt, ins, ins.imm, 12) |
| | if ins.as != ACJ { |
| | wantNoneReg(ctxt, ins, "rd", ins.rd) |
| | wantIntReg(ctxt, ins, "rs1", ins.rs1) |
| | wantIntReg(ctxt, ins, "rs2", ins.rs2) |
| | if ins.rs1 == REG_X0 { |
| | ctxt.Diag("%v: cannot use register X0 in rs1", ins) |
| | } |
| | } |
| | } |
| |
|
| | func validateCL(ctxt *obj.Link, ins *instruction) { |
| | if ins.as == ACLW { |
| | wantScaledImmU(ctxt, ins, ins.imm, 7, 4) |
| | } else if ins.as == ACLD || ins.as == ACFLD { |
| | wantScaledImmU(ctxt, ins, ins.imm, 8, 8) |
| | } else { |
| | wantImmI(ctxt, ins, ins.imm, 5) |
| | } |
| | if ins.as == ACFLD { |
| | wantFloatPrimeReg(ctxt, ins, "rd", ins.rd) |
| | } else { |
| | wantIntPrimeReg(ctxt, ins, "rd", ins.rd) |
| | } |
| | wantIntPrimeReg(ctxt, ins, "rs1", ins.rs1) |
| | wantNoneReg(ctxt, ins, "rs2", ins.rs2) |
| | } |
| |
|
| | func validateCR(ctxt *obj.Link, ins *instruction) { |
| | switch ins.as { |
| | case ACJR, ACJALR: |
| | wantNoneReg(ctxt, ins, "rd", ins.rd) |
| | wantIntReg(ctxt, ins, "rs1", ins.rs1) |
| | wantNoneReg(ctxt, ins, "rs2", ins.rs2) |
| | if ins.rs1 == REG_X0 { |
| | ctxt.Diag("%v: cannot use register X0 in rs1", ins) |
| | } |
| | case ACMV: |
| | wantIntReg(ctxt, ins, "rd", ins.rd) |
| | wantNoneReg(ctxt, ins, "rs1", ins.rs1) |
| | wantIntReg(ctxt, ins, "rs2", ins.rs2) |
| | if ins.rd == REG_X0 { |
| | ctxt.Diag("%v: cannot use register X0 in rd", ins) |
| | } |
| | if ins.rs2 == REG_X0 { |
| | ctxt.Diag("%v: cannot use register X0 in rs2", ins) |
| | } |
| | case ACEBREAK: |
| | wantNoneReg(ctxt, ins, "rd", ins.rd) |
| | wantNoneReg(ctxt, ins, "rs1", ins.rs1) |
| | wantNoneReg(ctxt, ins, "rs2", ins.rs2) |
| | case ACADD: |
| | wantIntReg(ctxt, ins, "rd", ins.rd) |
| | if ins.rd == REG_X0 { |
| | ctxt.Diag("%v: cannot use register X0 in rd", ins) |
| | } |
| | if ins.rd != ins.rs1 { |
| | ctxt.Diag("%v: rd must be the same as rs1", ins) |
| | } |
| | wantIntReg(ctxt, ins, "rs2", ins.rs2) |
| | if ins.rs2 == REG_X0 { |
| | ctxt.Diag("%v: cannot use register X0 in rs2", ins) |
| | } |
| | } |
| | } |
| |
|
| | func validateCS(ctxt *obj.Link, ins *instruction) { |
| | if ins.as == ACSW { |
| | wantScaledImmU(ctxt, ins, ins.imm, 7, 4) |
| | } else if ins.as == ACSD || ins.as == ACFSD { |
| | wantScaledImmU(ctxt, ins, ins.imm, 8, 8) |
| | } else { |
| | wantImmI(ctxt, ins, ins.imm, 5) |
| | } |
| | wantNoneReg(ctxt, ins, "rd", ins.rd) |
| | wantIntPrimeReg(ctxt, ins, "rs1", ins.rs1) |
| | if ins.as == ACFSD { |
| | wantFloatPrimeReg(ctxt, ins, "rs2", ins.rs2) |
| | } else { |
| | wantIntPrimeReg(ctxt, ins, "rs2", ins.rs2) |
| | } |
| | } |
| |
|
| | func validateCSS(ctxt *obj.Link, ins *instruction) { |
| | if ins.rd != REG_SP { |
| | ctxt.Diag("%v: rd must be SP/X2", ins) |
| | } |
| | if ins.as == ACSWSP { |
| | wantScaledImmU(ctxt, ins, ins.imm, 8, 4) |
| | } else if ins.as == ACSDSP || ins.as == ACFSDSP { |
| | wantScaledImmU(ctxt, ins, ins.imm, 9, 8) |
| | } else { |
| | wantImmI(ctxt, ins, ins.imm, 6) |
| | } |
| | wantNoneReg(ctxt, ins, "rs1", ins.rs1) |
| | if ins.as == ACFSDSP { |
| | wantFloatReg(ctxt, ins, "rs2", ins.rs2) |
| | } else { |
| | wantIntReg(ctxt, ins, "rs2", ins.rs2) |
| | } |
| | } |
| |
|
| | func validateRII(ctxt *obj.Link, ins *instruction) { |
| | wantIntReg(ctxt, ins, "rd", ins.rd) |
| | wantIntReg(ctxt, ins, "rs1", ins.rs1) |
| | wantNoneReg(ctxt, ins, "rs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateRIII(ctxt *obj.Link, ins *instruction) { |
| | wantIntReg(ctxt, ins, "rd", ins.rd) |
| | wantIntReg(ctxt, ins, "rs1", ins.rs1) |
| | wantIntReg(ctxt, ins, "rs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateRFFF(ctxt *obj.Link, ins *instruction) { |
| | wantFloatReg(ctxt, ins, "rd", ins.rd) |
| | wantFloatReg(ctxt, ins, "rs1", ins.rs1) |
| | wantFloatReg(ctxt, ins, "rs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateRFFFF(ctxt *obj.Link, ins *instruction) { |
| | wantFloatReg(ctxt, ins, "rd", ins.rd) |
| | wantFloatReg(ctxt, ins, "rs1", ins.rs1) |
| | wantFloatReg(ctxt, ins, "rs2", ins.rs2) |
| | wantFloatReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateRFFI(ctxt *obj.Link, ins *instruction) { |
| | wantIntReg(ctxt, ins, "rd", ins.rd) |
| | wantFloatReg(ctxt, ins, "rs1", ins.rs1) |
| | wantFloatReg(ctxt, ins, "rs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateRFI(ctxt *obj.Link, ins *instruction) { |
| | wantIntReg(ctxt, ins, "rd", ins.rd) |
| | wantNoneReg(ctxt, ins, "rs1", ins.rs1) |
| | wantFloatReg(ctxt, ins, "rs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateRFV(ctxt *obj.Link, ins *instruction) { |
| | wantVectorReg(ctxt, ins, "vd", ins.rd) |
| | wantNoneReg(ctxt, ins, "rs1", ins.rs1) |
| | wantFloatReg(ctxt, ins, "rs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateRFF(ctxt *obj.Link, ins *instruction) { |
| | wantFloatReg(ctxt, ins, "rd", ins.rd) |
| | wantNoneReg(ctxt, ins, "rs1", ins.rs1) |
| | wantFloatReg(ctxt, ins, "rs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateRIF(ctxt *obj.Link, ins *instruction) { |
| | wantFloatReg(ctxt, ins, "rd", ins.rd) |
| | wantNoneReg(ctxt, ins, "rs1", ins.rs1) |
| | wantIntReg(ctxt, ins, "rs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateRIV(ctxt *obj.Link, ins *instruction) { |
| | wantVectorReg(ctxt, ins, "vd", ins.rd) |
| | wantNoneReg(ctxt, ins, "rs1", ins.rs1) |
| | wantIntReg(ctxt, ins, "rs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateRVF(ctxt *obj.Link, ins *instruction) { |
| | wantFloatReg(ctxt, ins, "rd", ins.rd) |
| | wantNoneReg(ctxt, ins, "rs1", ins.rs1) |
| | wantVectorReg(ctxt, ins, "vs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateRVFV(ctxt *obj.Link, ins *instruction) { |
| | wantVectorReg(ctxt, ins, "vd", ins.rd) |
| | wantFloatReg(ctxt, ins, "rs1", ins.rs1) |
| | wantVectorReg(ctxt, ins, "vs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateRVI(ctxt *obj.Link, ins *instruction) { |
| | wantIntReg(ctxt, ins, "rd", ins.rd) |
| | wantNoneReg(ctxt, ins, "rs1", ins.rs1) |
| | wantVectorReg(ctxt, ins, "vs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateRVIV(ctxt *obj.Link, ins *instruction) { |
| | wantVectorReg(ctxt, ins, "vd", ins.rd) |
| | wantIntReg(ctxt, ins, "rs1", ins.rs1) |
| | wantVectorReg(ctxt, ins, "vs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateRVV(ctxt *obj.Link, ins *instruction) { |
| | wantVectorReg(ctxt, ins, "vd", ins.rd) |
| | wantNoneReg(ctxt, ins, "rs1", ins.rs1) |
| | wantVectorReg(ctxt, ins, "vs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateRVVi(ctxt *obj.Link, ins *instruction) { |
| | wantImmI(ctxt, ins, ins.imm, 5) |
| | wantVectorReg(ctxt, ins, "vd", ins.rd) |
| | wantNoneReg(ctxt, ins, "rs1", ins.rs1) |
| | wantVectorReg(ctxt, ins, "vs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateRVVu(ctxt *obj.Link, ins *instruction) { |
| | wantImmU(ctxt, ins, ins.imm, 5) |
| | wantVectorReg(ctxt, ins, "vd", ins.rd) |
| | wantNoneReg(ctxt, ins, "rs1", ins.rs1) |
| | wantVectorReg(ctxt, ins, "vs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateRVVV(ctxt *obj.Link, ins *instruction) { |
| | wantVectorReg(ctxt, ins, "vd", ins.rd) |
| | wantVectorReg(ctxt, ins, "vs1", ins.rs1) |
| | wantVectorReg(ctxt, ins, "vs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateIII(ctxt *obj.Link, ins *instruction) { |
| | wantImmI(ctxt, ins, ins.imm, 12) |
| | wantIntReg(ctxt, ins, "rd", ins.rd) |
| | wantIntReg(ctxt, ins, "rs1", ins.rs1) |
| | wantNoneReg(ctxt, ins, "rs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateIF(ctxt *obj.Link, ins *instruction) { |
| | wantImmI(ctxt, ins, ins.imm, 12) |
| | wantFloatReg(ctxt, ins, "rd", ins.rd) |
| | wantIntReg(ctxt, ins, "rs1", ins.rs1) |
| | wantNoneReg(ctxt, ins, "rs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateIV(ctxt *obj.Link, ins *instruction) { |
| | wantVectorReg(ctxt, ins, "vd", ins.rd) |
| | wantIntReg(ctxt, ins, "rs1", ins.rs1) |
| | wantNoneReg(ctxt, ins, "rs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateIIIV(ctxt *obj.Link, ins *instruction) { |
| | wantVectorReg(ctxt, ins, "vd", ins.rd) |
| | wantIntReg(ctxt, ins, "rs1", ins.rs1) |
| | wantIntReg(ctxt, ins, "rs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateIVIV(ctxt *obj.Link, ins *instruction) { |
| | wantVectorReg(ctxt, ins, "vd", ins.rd) |
| | wantIntReg(ctxt, ins, "rs1", ins.rs1) |
| | wantVectorReg(ctxt, ins, "vs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateSI(ctxt *obj.Link, ins *instruction) { |
| | wantImmI(ctxt, ins, ins.imm, 12) |
| | wantIntReg(ctxt, ins, "rd", ins.rd) |
| | wantIntReg(ctxt, ins, "rs1", ins.rs1) |
| | wantNoneReg(ctxt, ins, "rs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateSF(ctxt *obj.Link, ins *instruction) { |
| | wantImmI(ctxt, ins, ins.imm, 12) |
| | wantIntReg(ctxt, ins, "rd", ins.rd) |
| | wantFloatReg(ctxt, ins, "rs1", ins.rs1) |
| | wantNoneReg(ctxt, ins, "rs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateSV(ctxt *obj.Link, ins *instruction) { |
| | wantIntReg(ctxt, ins, "rd", ins.rd) |
| | wantVectorReg(ctxt, ins, "vs1", ins.rs1) |
| | wantNoneReg(ctxt, ins, "rs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateSVII(ctxt *obj.Link, ins *instruction) { |
| | wantVectorReg(ctxt, ins, "vd", ins.rd) |
| | wantIntReg(ctxt, ins, "rs1", ins.rs1) |
| | wantIntReg(ctxt, ins, "rs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateSVIV(ctxt *obj.Link, ins *instruction) { |
| | wantVectorReg(ctxt, ins, "vd", ins.rd) |
| | wantIntReg(ctxt, ins, "rs1", ins.rs1) |
| | wantVectorReg(ctxt, ins, "vs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateB(ctxt *obj.Link, ins *instruction) { |
| | |
| | |
| | wantEvenOffset(ctxt, ins, ins.imm) |
| | wantImmI(ctxt, ins, ins.imm, 13) |
| | wantNoneReg(ctxt, ins, "rd", ins.rd) |
| | wantIntReg(ctxt, ins, "rs1", ins.rs1) |
| | wantIntReg(ctxt, ins, "rs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateU(ctxt *obj.Link, ins *instruction) { |
| | wantImmI(ctxt, ins, ins.imm, 20) |
| | wantIntReg(ctxt, ins, "rd", ins.rd) |
| | wantNoneReg(ctxt, ins, "rs1", ins.rs1) |
| | wantNoneReg(ctxt, ins, "rs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateJ(ctxt *obj.Link, ins *instruction) { |
| | |
| | |
| | wantEvenOffset(ctxt, ins, ins.imm) |
| | wantImmI(ctxt, ins, ins.imm, 21) |
| | wantIntReg(ctxt, ins, "rd", ins.rd) |
| | wantNoneReg(ctxt, ins, "rs1", ins.rs1) |
| | wantNoneReg(ctxt, ins, "rs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateVsetvli(ctxt *obj.Link, ins *instruction) { |
| | wantImmU(ctxt, ins, ins.imm, 11) |
| | wantIntReg(ctxt, ins, "rd", ins.rd) |
| | wantIntReg(ctxt, ins, "rs1", ins.rs1) |
| | wantNoneReg(ctxt, ins, "rs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateVsetivli(ctxt *obj.Link, ins *instruction) { |
| | wantImmU(ctxt, ins, ins.imm, 10) |
| | wantIntReg(ctxt, ins, "rd", ins.rd) |
| | wantImmU(ctxt, ins, int64(ins.rs1), 5) |
| | wantNoneReg(ctxt, ins, "rs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateVsetvl(ctxt *obj.Link, ins *instruction) { |
| | wantIntReg(ctxt, ins, "rd", ins.rd) |
| | wantIntReg(ctxt, ins, "rs1", ins.rs1) |
| | wantIntReg(ctxt, ins, "rs2", ins.rs2) |
| | wantNoneReg(ctxt, ins, "rs3", ins.rs3) |
| | } |
| |
|
| | func validateRaw(ctxt *obj.Link, ins *instruction) { |
| | |
| | |
| | wantImmU(ctxt, ins, ins.imm, 32) |
| | } |
| |
|
| | |
| | |
| | func compressedEncoding(as obj.As) uint32 { |
| | enc := encode(as) |
| | if enc == nil { |
| | panic("compressedEncoding: could not encode instruction") |
| | } |
| |
|
| | |
| | |
| | op := uint32(0) |
| | switch as { |
| | case ACSUB: |
| | op = 0b100011<<10 | 0b00<<5 |
| | case ACXOR: |
| | op = 0b100011<<10 | 0b01<<5 |
| | case ACOR: |
| | op = 0b100011<<10 | 0b10<<5 |
| | case ACAND: |
| | op = 0b100011<<10 | 0b11<<5 |
| | case ACSUBW: |
| | op = 0b100111<<10 | 0b00<<5 |
| | case ACADDW: |
| | op = 0b100111<<10 | 0b01<<5 |
| | case ACBEQZ: |
| | op = 0b110 << 13 |
| | case ACBNEZ: |
| | op = 0b111 << 13 |
| | case ACANDI: |
| | op = 0b100<<13 | 0b10<<10 |
| | case ACSRAI: |
| | op = 0b100<<13 | 0b01<<10 |
| | case ACSRLI: |
| | op = 0b100<<13 | 0b00<<10 |
| | case ACLI: |
| | op = 0b010 << 13 |
| | case ACLUI: |
| | op = 0b011 << 13 |
| | case ACLWSP: |
| | op = 0b010 << 13 |
| | case ACLDSP: |
| | op = 0b011 << 13 |
| | case ACFLDSP: |
| | op = 0b001 << 13 |
| | case ACADDIW: |
| | op = 0b001 << 13 |
| | case ACADDI16SP: |
| | op = 0b011 << 13 |
| | case ACADDI4SPN: |
| | op = 0b000 << 13 |
| | case ACJ: |
| | op = 0b101 << 13 |
| | case ACLW: |
| | op = 0b010 << 13 |
| | case ACLD: |
| | op = 0b011 << 13 |
| | case ACFLD: |
| | op = 0b001 << 13 |
| | case ACJR: |
| | op = 0b1000 << 12 |
| | case ACMV: |
| | op = 0b1000 << 12 |
| | case ACEBREAK: |
| | op = 0b1001 << 12 |
| | case ACJALR: |
| | op = 0b1001 << 12 |
| | case ACADD: |
| | op = 0b1001 << 12 |
| | case ACSW: |
| | op = 0b110 << 13 |
| | case ACSD: |
| | op = 0b111 << 13 |
| | case ACFSD: |
| | op = 0b101 << 13 |
| | case ACSWSP: |
| | op = 0b110 << 13 |
| | case ACSDSP: |
| | op = 0b111 << 13 |
| | case ACFSDSP: |
| | op = 0b101 << 13 |
| | } |
| |
|
| | return op | enc.opcode |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | func encodeBitPattern(imm uint32, pattern []int) uint32 { |
| | outImm := uint32(0) |
| | for _, bit := range pattern { |
| | outImm = outImm<<1 | (imm>>bit)&1 |
| | } |
| | return outImm |
| | } |
| |
|
| | |
| | func encodeCA(ins *instruction) uint32 { |
| | return compressedEncoding(ins.as) | regCI(ins.rd)<<7 | regCI(ins.rs2)<<2 |
| | } |
| |
|
| | |
| | func encodeCBImmediate(imm uint32) uint32 { |
| | |
| | bits := encodeBitPattern(imm, []int{8, 4, 3, 7, 6, 2, 1, 5}) |
| | return (bits>>5)<<10 | (bits&0x1f)<<2 |
| | } |
| |
|
| | |
| | func encodeCB(ins *instruction) uint32 { |
| | imm := uint32(0) |
| | if ins.as == ACBEQZ || ins.as == ACBNEZ { |
| | imm = immI(ins.as, ins.imm, 9) |
| | imm = encodeBitPattern(imm, []int{8, 4, 3, 7, 6, 2, 1, 5}) |
| | } else if ins.as == ACANDI { |
| | imm = immI(ins.as, ins.imm, 6) |
| | imm = (imm>>5)<<7 | imm&0x1f |
| | } else if ins.as == ACSRAI || ins.as == ACSRLI { |
| | imm = immU(ins.as, ins.imm, 6) |
| | imm = (imm>>5)<<7 | imm&0x1f |
| | } |
| | return compressedEncoding(ins.as) | (imm>>5)<<10 | regCI(ins.rs1)<<7 | (imm&0x1f)<<2 |
| | } |
| |
|
| | |
| | func encodeCI(ins *instruction) uint32 { |
| | imm := uint32(ins.imm) |
| | if ins.as == ACLWSP { |
| | |
| | imm = encodeBitPattern(imm, []int{5, 4, 3, 2, 7, 6}) |
| | } else if ins.as == ACLDSP || ins.as == ACFLDSP { |
| | |
| | imm = encodeBitPattern(imm, []int{5, 4, 3, 8, 7, 6}) |
| | } else if ins.as == ACADDI16SP { |
| | |
| | imm = encodeBitPattern(imm, []int{9, 4, 6, 8, 7, 5}) |
| | } |
| | rd := uint32(0) |
| | if ins.as == ACFLDSP { |
| | rd = regF(ins.rd) |
| | } else { |
| | rd = regI(ins.rd) |
| | } |
| | return compressedEncoding(ins.as) | ((imm>>5)&0x1)<<12 | rd<<7 | (imm&0x1f)<<2 |
| | } |
| |
|
| | |
| | func encodeCIW(ins *instruction) uint32 { |
| | imm := uint32(ins.imm) |
| | if ins.as == ACADDI4SPN { |
| | |
| | imm = encodeBitPattern(imm, []int{5, 4, 9, 8, 7, 6, 2, 3}) |
| | } |
| | return compressedEncoding(ins.as) | imm<<5 | regCI(ins.rd)<<2 |
| | } |
| |
|
| | |
| | func encodeCJImmediate(imm uint32) uint32 { |
| | |
| | bits := encodeBitPattern(imm, []int{11, 4, 9, 8, 10, 6, 7, 3, 2, 1, 5}) |
| | return bits << 2 |
| | } |
| |
|
| | |
| | func encodeCJ(ins *instruction) uint32 { |
| | return compressedEncoding(ins.as) | encodeCJImmediate(uint32(ins.imm)) |
| | } |
| |
|
| | |
| | func encodeCL(ins *instruction) uint32 { |
| | imm := uint32(ins.imm) |
| | if ins.as == ACLW { |
| | |
| | imm = encodeBitPattern(imm, []int{5, 4, 3, 2, 6}) |
| | } else if ins.as == ACLD || ins.as == ACFLD { |
| | |
| | imm = encodeBitPattern(imm, []int{5, 4, 3, 7, 6}) |
| | } |
| | rd := uint32(0) |
| | if ins.as == ACFLD { |
| | rd = regCF(ins.rd) |
| | } else { |
| | rd = regCI(ins.rd) |
| | } |
| | return compressedEncoding(ins.as) | (imm>>2)<<10 | regCI(ins.rs1)<<7 | (imm&0x3)<<5 | rd<<2 |
| | } |
| |
|
| | |
| | func encodeCR(ins *instruction) uint32 { |
| | rs1, rs2 := uint32(0), uint32(0) |
| | switch ins.as { |
| | case ACJR, ACJALR: |
| | rs1 = regI(ins.rs1) |
| | case ACMV: |
| | rs1, rs2 = regI(ins.rd), regI(ins.rs2) |
| | case ACADD: |
| | rs1, rs2 = regI(ins.rs1), regI(ins.rs2) |
| | } |
| | return compressedEncoding(ins.as) | rs1<<7 | rs2<<2 |
| | } |
| |
|
| | |
| | func encodeCS(ins *instruction) uint32 { |
| | imm := uint32(ins.imm) |
| | if ins.as == ACSW { |
| | |
| | imm = encodeBitPattern(imm, []int{5, 4, 3, 2, 6}) |
| | } else if ins.as == ACSD || ins.as == ACFSD { |
| | |
| | imm = encodeBitPattern(imm, []int{5, 4, 3, 7, 6}) |
| | } |
| | rs2 := uint32(0) |
| | if ins.as == ACFSD { |
| | rs2 = regCF(ins.rs2) |
| | } else { |
| | rs2 = regCI(ins.rs2) |
| | } |
| | return compressedEncoding(ins.as) | ((imm>>2)&0x7)<<10 | regCI(ins.rs1)<<7 | (imm&3)<<5 | rs2<<2 |
| | } |
| |
|
| | |
| | func encodeCSS(ins *instruction) uint32 { |
| | imm := uint32(ins.imm) |
| | if ins.as == ACSWSP { |
| | |
| | imm = encodeBitPattern(imm, []int{5, 4, 3, 2, 7, 6}) |
| | } else if ins.as == ACSDSP || ins.as == ACFSDSP { |
| | |
| | imm = encodeBitPattern(imm, []int{5, 4, 3, 8, 7, 6}) |
| | } |
| | rs2 := uint32(0) |
| | if ins.as == ACFSDSP { |
| | rs2 = regF(ins.rs2) |
| | } else { |
| | rs2 = regI(ins.rs2) |
| | } |
| | return compressedEncoding(ins.as) | imm<<7 | rs2<<2 |
| | } |
| |
|
| | |
| | func encodeR(as obj.As, rs1, rs2, rd, funct3, funct7 uint32) uint32 { |
| | enc := encode(as) |
| | if enc == nil { |
| | panic("encodeR: could not encode instruction") |
| | } |
| | if enc.rs1 != 0 && rs1 != 0 { |
| | panic("encodeR: instruction uses rs1, but rs1 is nonzero") |
| | } |
| | if enc.rs2 != 0 && rs2 != 0 { |
| | panic("encodeR: instruction uses rs2, but rs2 is nonzero") |
| | } |
| | funct3 |= enc.funct3 |
| | funct7 |= enc.funct7 |
| | rs1 |= enc.rs1 |
| | rs2 |= enc.rs2 |
| | return funct7<<25 | rs2<<20 | rs1<<15 | funct3<<12 | rd<<7 | enc.opcode |
| | } |
| |
|
| | |
| | func encodeR4(as obj.As, rs1, rs2, rs3, rd, funct3, funct2 uint32) uint32 { |
| | enc := encode(as) |
| | if enc == nil { |
| | panic("encodeR4: could not encode instruction") |
| | } |
| | if enc.rs2 != 0 { |
| | panic("encodeR4: instruction uses rs2") |
| | } |
| | funct2 |= enc.funct7 |
| | if funct2&^3 != 0 { |
| | panic("encodeR4: funct2 requires more than 2 bits") |
| | } |
| | return rs3<<27 | funct2<<25 | rs2<<20 | rs1<<15 | enc.funct3<<12 | funct3<<12 | rd<<7 | enc.opcode |
| | } |
| |
|
| | func encodeRII(ins *instruction) uint32 { |
| | return encodeR(ins.as, regI(ins.rs1), 0, regI(ins.rd), ins.funct3, ins.funct7) |
| | } |
| |
|
| | func encodeRIII(ins *instruction) uint32 { |
| | return encodeR(ins.as, regI(ins.rs1), regI(ins.rs2), regI(ins.rd), ins.funct3, ins.funct7) |
| | } |
| |
|
| | func encodeRFFF(ins *instruction) uint32 { |
| | return encodeR(ins.as, regF(ins.rs1), regF(ins.rs2), regF(ins.rd), ins.funct3, ins.funct7) |
| | } |
| |
|
| | func encodeRFFFF(ins *instruction) uint32 { |
| | return encodeR4(ins.as, regF(ins.rs1), regF(ins.rs2), regF(ins.rs3), regF(ins.rd), ins.funct3, ins.funct7) |
| | } |
| |
|
| | func encodeRFFI(ins *instruction) uint32 { |
| | return encodeR(ins.as, regF(ins.rs1), regF(ins.rs2), regI(ins.rd), ins.funct3, ins.funct7) |
| | } |
| |
|
| | func encodeRFI(ins *instruction) uint32 { |
| | return encodeR(ins.as, regF(ins.rs2), 0, regI(ins.rd), ins.funct3, ins.funct7) |
| | } |
| |
|
| | func encodeRFF(ins *instruction) uint32 { |
| | return encodeR(ins.as, regF(ins.rs2), 0, regF(ins.rd), ins.funct3, ins.funct7) |
| | } |
| |
|
| | func encodeRFV(ins *instruction) uint32 { |
| | return encodeR(ins.as, regF(ins.rs2), 0, regV(ins.rd), ins.funct3, ins.funct7) |
| | } |
| |
|
| | func encodeRIF(ins *instruction) uint32 { |
| | return encodeR(ins.as, regI(ins.rs2), 0, regF(ins.rd), ins.funct3, ins.funct7) |
| | } |
| |
|
| | func encodeRIV(ins *instruction) uint32 { |
| | return encodeR(ins.as, regI(ins.rs2), 0, regV(ins.rd), ins.funct3, ins.funct7) |
| | } |
| |
|
| | func encodeRVF(ins *instruction) uint32 { |
| | return encodeR(ins.as, 0, regV(ins.rs2), regF(ins.rd), ins.funct3, ins.funct7) |
| | } |
| |
|
| | func encodeRVFV(ins *instruction) uint32 { |
| | return encodeR(ins.as, regF(ins.rs1), regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7) |
| | } |
| |
|
| | func encodeRVI(ins *instruction) uint32 { |
| | return encodeR(ins.as, 0, regV(ins.rs2), regI(ins.rd), ins.funct3, ins.funct7) |
| | } |
| |
|
| | func encodeRVIV(ins *instruction) uint32 { |
| | return encodeR(ins.as, regI(ins.rs1), regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7) |
| | } |
| |
|
| | func encodeRVV(ins *instruction) uint32 { |
| | return encodeR(ins.as, 0, regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7) |
| | } |
| |
|
| | func encodeRVVi(ins *instruction) uint32 { |
| | return encodeR(ins.as, immI(ins.as, ins.imm, 5), regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7) |
| | } |
| |
|
| | func encodeRVVu(ins *instruction) uint32 { |
| | return encodeR(ins.as, immU(ins.as, ins.imm, 5), regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7) |
| | } |
| |
|
| | func encodeRVVV(ins *instruction) uint32 { |
| | return encodeR(ins.as, regV(ins.rs1), regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7) |
| | } |
| |
|
| | |
| | func encodeI(as obj.As, rs1, rd, imm, funct7 uint32) uint32 { |
| | enc := encode(as) |
| | if enc == nil { |
| | panic("encodeI: could not encode instruction") |
| | } |
| | imm |= uint32(enc.csr) |
| | return funct7<<25 | imm<<20 | rs1<<15 | enc.funct3<<12 | rd<<7 | enc.opcode |
| | } |
| |
|
| | func encodeIII(ins *instruction) uint32 { |
| | return encodeI(ins.as, regI(ins.rs1), regI(ins.rd), uint32(ins.imm), 0) |
| | } |
| |
|
| | func encodeIF(ins *instruction) uint32 { |
| | return encodeI(ins.as, regI(ins.rs1), regF(ins.rd), uint32(ins.imm), 0) |
| | } |
| |
|
| | func encodeIV(ins *instruction) uint32 { |
| | return encodeI(ins.as, regI(ins.rs1), regV(ins.rd), uint32(ins.imm), ins.funct7) |
| | } |
| |
|
| | func encodeIIIV(ins *instruction) uint32 { |
| | return encodeI(ins.as, regI(ins.rs1), regV(ins.rd), regI(ins.rs2), ins.funct7) |
| | } |
| |
|
| | func encodeIVIV(ins *instruction) uint32 { |
| | return encodeI(ins.as, regI(ins.rs1), regV(ins.rd), regV(ins.rs2), ins.funct7) |
| | } |
| |
|
| | |
| | func encodeS(as obj.As, rs1, rs2, imm, funct7 uint32) uint32 { |
| | enc := encode(as) |
| | if enc == nil { |
| | panic("encodeS: could not encode instruction") |
| | } |
| | if enc.rs2 != 0 && rs2 != 0 { |
| | panic("encodeS: instruction uses rs2, but rs2 was nonzero") |
| | } |
| | rs2 |= enc.rs2 |
| | imm |= uint32(enc.csr) &^ 0x1f |
| | return funct7<<25 | (imm>>5)<<25 | rs2<<20 | rs1<<15 | enc.funct3<<12 | (imm&0x1f)<<7 | enc.opcode |
| | } |
| |
|
| | func encodeSI(ins *instruction) uint32 { |
| | return encodeS(ins.as, regI(ins.rd), regI(ins.rs1), uint32(ins.imm), 0) |
| | } |
| |
|
| | func encodeSF(ins *instruction) uint32 { |
| | return encodeS(ins.as, regI(ins.rd), regF(ins.rs1), uint32(ins.imm), 0) |
| | } |
| |
|
| | func encodeSV(ins *instruction) uint32 { |
| | return encodeS(ins.as, regI(ins.rd), 0, regV(ins.rs1), ins.funct7) |
| | } |
| |
|
| | func encodeSVII(ins *instruction) uint32 { |
| | return encodeS(ins.as, regI(ins.rs1), regI(ins.rs2), regV(ins.rd), ins.funct7) |
| | } |
| |
|
| | func encodeSVIV(ins *instruction) uint32 { |
| | return encodeS(ins.as, regI(ins.rs1), regV(ins.rs2), regV(ins.rd), ins.funct7) |
| | } |
| |
|
| | |
| | func encodeBImmediate(imm uint32) uint32 { |
| | return (imm>>12)<<31 | ((imm>>5)&0x3f)<<25 | ((imm>>1)&0xf)<<8 | ((imm>>11)&0x1)<<7 |
| | } |
| |
|
| | |
| | func encodeB(ins *instruction) uint32 { |
| | imm := immI(ins.as, ins.imm, 13) |
| | rs2 := regI(ins.rs1) |
| | rs1 := regI(ins.rs2) |
| | enc := encode(ins.as) |
| | if enc == nil { |
| | panic("encodeB: could not encode instruction") |
| | } |
| | return encodeBImmediate(imm) | rs2<<20 | rs1<<15 | enc.funct3<<12 | enc.opcode |
| | } |
| |
|
| | |
| | func encodeU(ins *instruction) uint32 { |
| | |
| | |
| | |
| | |
| | imm := immI(ins.as, ins.imm, 20) |
| | rd := regI(ins.rd) |
| | enc := encode(ins.as) |
| | if enc == nil { |
| | panic("encodeU: could not encode instruction") |
| | } |
| | return imm<<12 | rd<<7 | enc.opcode |
| | } |
| |
|
| | |
| | func encodeJImmediate(imm uint32) uint32 { |
| | return (imm>>20)<<31 | ((imm>>1)&0x3ff)<<21 | ((imm>>11)&0x1)<<20 | ((imm>>12)&0xff)<<12 |
| | } |
| |
|
| | |
| | func encodeJ(ins *instruction) uint32 { |
| | imm := immI(ins.as, ins.imm, 21) |
| | rd := regI(ins.rd) |
| | enc := encode(ins.as) |
| | if enc == nil { |
| | panic("encodeJ: could not encode instruction") |
| | } |
| | return encodeJImmediate(imm) | rd<<7 | enc.opcode |
| | } |
| |
|
| | func encodeVset(as obj.As, rs1, rs2, rd uint32) uint32 { |
| | enc := encode(as) |
| | if enc == nil { |
| | panic("encodeVset: could not encode instruction") |
| | } |
| | return enc.funct7<<25 | rs2<<20 | rs1<<15 | enc.funct3<<12 | rd<<7 | enc.opcode |
| | } |
| |
|
| | func encodeVsetvli(ins *instruction) uint32 { |
| | vtype := immU(ins.as, ins.imm, 11) |
| | return encodeVset(ins.as, regI(ins.rs1), vtype, regI(ins.rd)) |
| | } |
| |
|
| | func encodeVsetivli(ins *instruction) uint32 { |
| | vtype := immU(ins.as, ins.imm, 10) |
| | avl := immU(ins.as, int64(ins.rs1), 5) |
| | return encodeVset(ins.as, avl, vtype, regI(ins.rd)) |
| | } |
| |
|
| | func encodeVsetvl(ins *instruction) uint32 { |
| | return encodeVset(ins.as, regI(ins.rs1), regI(ins.rs2), regI(ins.rd)) |
| | } |
| |
|
| | func encodeRawIns(ins *instruction) uint32 { |
| | |
| | |
| | return immU(ins.as, ins.imm, 32) |
| | } |
| |
|
| | func EncodeBImmediate(imm int64) (int64, error) { |
| | if err := immIFits(imm, 13); err != nil { |
| | return 0, err |
| | } |
| | if err := immEven(imm); err != nil { |
| | return 0, err |
| | } |
| | return int64(encodeBImmediate(uint32(imm))), nil |
| | } |
| |
|
| | func EncodeCBImmediate(imm int64) (int64, error) { |
| | if err := immIFits(imm, 9); err != nil { |
| | return 0, err |
| | } |
| | if err := immEven(imm); err != nil { |
| | return 0, err |
| | } |
| | return int64(encodeCBImmediate(uint32(imm))), nil |
| | } |
| |
|
| | func EncodeCJImmediate(imm int64) (int64, error) { |
| | if err := immIFits(imm, 12); err != nil { |
| | return 0, err |
| | } |
| | if err := immEven(imm); err != nil { |
| | return 0, err |
| | } |
| | return int64(encodeCJImmediate(uint32(imm))), nil |
| | } |
| |
|
| | func EncodeIImmediate(imm int64) (int64, error) { |
| | if err := immIFits(imm, 12); err != nil { |
| | return 0, err |
| | } |
| | return imm << 20, nil |
| | } |
| |
|
| | func EncodeJImmediate(imm int64) (int64, error) { |
| | if err := immIFits(imm, 21); err != nil { |
| | return 0, err |
| | } |
| | if err := immEven(imm); err != nil { |
| | return 0, err |
| | } |
| | return int64(encodeJImmediate(uint32(imm))), nil |
| | } |
| |
|
| | func EncodeSImmediate(imm int64) (int64, error) { |
| | if err := immIFits(imm, 12); err != nil { |
| | return 0, err |
| | } |
| | return ((imm >> 5) << 25) | ((imm & 0x1f) << 7), nil |
| | } |
| |
|
| | func EncodeUImmediate(imm int64) (int64, error) { |
| | if err := immIFits(imm, 20); err != nil { |
| | return 0, err |
| | } |
| | return imm << 12, nil |
| | } |
| |
|
| | func EncodeVectorType(vsew, vlmul, vtail, vmask int64) (int64, error) { |
| | vsewSO := SpecialOperand(vsew) |
| | if vsewSO < SPOP_E8 || vsewSO > SPOP_E64 { |
| | return -1, fmt.Errorf("invalid vector selected element width %q", vsewSO) |
| | } |
| | vlmulSO := SpecialOperand(vlmul) |
| | if vlmulSO < SPOP_M1 || vlmulSO > SPOP_MF8 { |
| | return -1, fmt.Errorf("invalid vector register group multiplier %q", vlmulSO) |
| | } |
| | vtailSO := SpecialOperand(vtail) |
| | if vtailSO != SPOP_TA && vtailSO != SPOP_TU { |
| | return -1, fmt.Errorf("invalid vector tail policy %q", vtailSO) |
| | } |
| | vmaskSO := SpecialOperand(vmask) |
| | if vmaskSO != SPOP_MA && vmaskSO != SPOP_MU { |
| | return -1, fmt.Errorf("invalid vector mask policy %q", vmaskSO) |
| | } |
| | vtype := vmaskSO.encode()<<7 | vtailSO.encode()<<6 | vsewSO.encode()<<3 | vlmulSO.encode() |
| | return int64(vtype), nil |
| | } |
| |
|
| | type encoding struct { |
| | encode func(*instruction) uint32 |
| | validate func(*obj.Link, *instruction) |
| | length int |
| | } |
| |
|
| | var ( |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | rIIIEncoding = encoding{encode: encodeRIII, validate: validateRIII, length: 4} |
| | rIIEncoding = encoding{encode: encodeRII, validate: validateRII, length: 4} |
| | rFFFEncoding = encoding{encode: encodeRFFF, validate: validateRFFF, length: 4} |
| | rFFFFEncoding = encoding{encode: encodeRFFFF, validate: validateRFFFF, length: 4} |
| | rFFIEncoding = encoding{encode: encodeRFFI, validate: validateRFFI, length: 4} |
| | rFIEncoding = encoding{encode: encodeRFI, validate: validateRFI, length: 4} |
| | rFVEncoding = encoding{encode: encodeRFV, validate: validateRFV, length: 4} |
| | rIFEncoding = encoding{encode: encodeRIF, validate: validateRIF, length: 4} |
| | rIVEncoding = encoding{encode: encodeRIV, validate: validateRIV, length: 4} |
| | rFFEncoding = encoding{encode: encodeRFF, validate: validateRFF, length: 4} |
| | rVFEncoding = encoding{encode: encodeRVF, validate: validateRVF, length: 4} |
| | rVFVEncoding = encoding{encode: encodeRVFV, validate: validateRVFV, length: 4} |
| | rVIEncoding = encoding{encode: encodeRVI, validate: validateRVI, length: 4} |
| | rVIVEncoding = encoding{encode: encodeRVIV, validate: validateRVIV, length: 4} |
| | rVVEncoding = encoding{encode: encodeRVV, validate: validateRVV, length: 4} |
| | rVViEncoding = encoding{encode: encodeRVVi, validate: validateRVVi, length: 4} |
| | rVVuEncoding = encoding{encode: encodeRVVu, validate: validateRVVu, length: 4} |
| | rVVVEncoding = encoding{encode: encodeRVVV, validate: validateRVVV, length: 4} |
| |
|
| | iIIEncoding = encoding{encode: encodeIII, validate: validateIII, length: 4} |
| | iFEncoding = encoding{encode: encodeIF, validate: validateIF, length: 4} |
| | iVEncoding = encoding{encode: encodeIV, validate: validateIV, length: 4} |
| | iIIVEncoding = encoding{encode: encodeIIIV, validate: validateIIIV, length: 4} |
| | iVIVEncoding = encoding{encode: encodeIVIV, validate: validateIVIV, length: 4} |
| |
|
| | sIEncoding = encoding{encode: encodeSI, validate: validateSI, length: 4} |
| | sFEncoding = encoding{encode: encodeSF, validate: validateSF, length: 4} |
| | sVEncoding = encoding{encode: encodeSV, validate: validateSV, length: 4} |
| | sVIIEncoding = encoding{encode: encodeSVII, validate: validateSVII, length: 4} |
| | sVIVEncoding = encoding{encode: encodeSVIV, validate: validateSVIV, length: 4} |
| |
|
| | bEncoding = encoding{encode: encodeB, validate: validateB, length: 4} |
| | uEncoding = encoding{encode: encodeU, validate: validateU, length: 4} |
| | jEncoding = encoding{encode: encodeJ, validate: validateJ, length: 4} |
| |
|
| | |
| | caEncoding = encoding{encode: encodeCA, validate: validateCA, length: 2} |
| | cbEncoding = encoding{encode: encodeCB, validate: validateCB, length: 2} |
| | ciEncoding = encoding{encode: encodeCI, validate: validateCI, length: 2} |
| | ciwEncoding = encoding{encode: encodeCIW, validate: validateCIW, length: 2} |
| | cjEncoding = encoding{encode: encodeCJ, validate: validateCJ, length: 2} |
| | clEncoding = encoding{encode: encodeCL, validate: validateCL, length: 2} |
| | crEncoding = encoding{encode: encodeCR, validate: validateCR, length: 2} |
| | csEncoding = encoding{encode: encodeCS, validate: validateCS, length: 2} |
| | cssEncoding = encoding{encode: encodeCSS, validate: validateCSS, length: 2} |
| |
|
| | |
| | vsetvliEncoding = encoding{encode: encodeVsetvli, validate: validateVsetvli, length: 4} |
| | vsetivliEncoding = encoding{encode: encodeVsetivli, validate: validateVsetivli, length: 4} |
| | vsetvlEncoding = encoding{encode: encodeVsetvl, validate: validateVsetvl, length: 4} |
| |
|
| | |
| | rawEncoding = encoding{encode: encodeRawIns, validate: validateRaw, length: 4} |
| |
|
| | |
| | pseudoOpEncoding = encoding{encode: nil, validate: func(*obj.Link, *instruction) {}, length: 0} |
| |
|
| | |
| | |
| | badEncoding = encoding{encode: func(*instruction) uint32 { return 0 }, validate: func(*obj.Link, *instruction) {}, length: 0} |
| | ) |
| |
|
| | |
| | type instructionData struct { |
| | enc encoding |
| | immForm obj.As |
| | ternary bool |
| | } |
| |
|
| | |
| | |
| | |
| | var instructions = [ALAST & obj.AMask]instructionData{ |
| | |
| | |
| | |
| |
|
| | |
| | AADDI & obj.AMask: {enc: iIIEncoding, ternary: true}, |
| | ASLTI & obj.AMask: {enc: iIIEncoding, ternary: true}, |
| | ASLTIU & obj.AMask: {enc: iIIEncoding, ternary: true}, |
| | AANDI & obj.AMask: {enc: iIIEncoding, ternary: true}, |
| | AORI & obj.AMask: {enc: iIIEncoding, ternary: true}, |
| | AXORI & obj.AMask: {enc: iIIEncoding, ternary: true}, |
| | ASLLI & obj.AMask: {enc: iIIEncoding, ternary: true}, |
| | ASRLI & obj.AMask: {enc: iIIEncoding, ternary: true}, |
| | ASRAI & obj.AMask: {enc: iIIEncoding, ternary: true}, |
| | ALUI & obj.AMask: {enc: uEncoding}, |
| | AAUIPC & obj.AMask: {enc: uEncoding}, |
| | AADD & obj.AMask: {enc: rIIIEncoding, immForm: AADDI, ternary: true}, |
| | ASLT & obj.AMask: {enc: rIIIEncoding, immForm: ASLTI, ternary: true}, |
| | ASLTU & obj.AMask: {enc: rIIIEncoding, immForm: ASLTIU, ternary: true}, |
| | AAND & obj.AMask: {enc: rIIIEncoding, immForm: AANDI, ternary: true}, |
| | AOR & obj.AMask: {enc: rIIIEncoding, immForm: AORI, ternary: true}, |
| | AXOR & obj.AMask: {enc: rIIIEncoding, immForm: AXORI, ternary: true}, |
| | ASLL & obj.AMask: {enc: rIIIEncoding, immForm: ASLLI, ternary: true}, |
| | ASRL & obj.AMask: {enc: rIIIEncoding, immForm: ASRLI, ternary: true}, |
| | ASUB & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | ASRA & obj.AMask: {enc: rIIIEncoding, immForm: ASRAI, ternary: true}, |
| |
|
| | |
| | AJAL & obj.AMask: {enc: jEncoding}, |
| | AJALR & obj.AMask: {enc: iIIEncoding}, |
| | ABEQ & obj.AMask: {enc: bEncoding}, |
| | ABNE & obj.AMask: {enc: bEncoding}, |
| | ABLT & obj.AMask: {enc: bEncoding}, |
| | ABLTU & obj.AMask: {enc: bEncoding}, |
| | ABGE & obj.AMask: {enc: bEncoding}, |
| | ABGEU & obj.AMask: {enc: bEncoding}, |
| |
|
| | |
| | ALW & obj.AMask: {enc: iIIEncoding}, |
| | ALWU & obj.AMask: {enc: iIIEncoding}, |
| | ALH & obj.AMask: {enc: iIIEncoding}, |
| | ALHU & obj.AMask: {enc: iIIEncoding}, |
| | ALB & obj.AMask: {enc: iIIEncoding}, |
| | ALBU & obj.AMask: {enc: iIIEncoding}, |
| | ASW & obj.AMask: {enc: sIEncoding}, |
| | ASH & obj.AMask: {enc: sIEncoding}, |
| | ASB & obj.AMask: {enc: sIEncoding}, |
| |
|
| | |
| | AFENCE & obj.AMask: {enc: iIIEncoding}, |
| |
|
| | |
| | AADDIW & obj.AMask: {enc: iIIEncoding, ternary: true}, |
| | ASLLIW & obj.AMask: {enc: iIIEncoding, ternary: true}, |
| | ASRLIW & obj.AMask: {enc: iIIEncoding, ternary: true}, |
| | ASRAIW & obj.AMask: {enc: iIIEncoding, ternary: true}, |
| | AADDW & obj.AMask: {enc: rIIIEncoding, immForm: AADDIW, ternary: true}, |
| | ASLLW & obj.AMask: {enc: rIIIEncoding, immForm: ASLLIW, ternary: true}, |
| | ASRLW & obj.AMask: {enc: rIIIEncoding, immForm: ASRLIW, ternary: true}, |
| | ASUBW & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | ASRAW & obj.AMask: {enc: rIIIEncoding, immForm: ASRAIW, ternary: true}, |
| |
|
| | |
| | ALD & obj.AMask: {enc: iIIEncoding}, |
| | ASD & obj.AMask: {enc: sIEncoding}, |
| |
|
| | |
| | ACSRRC & obj.AMask: {enc: iIIEncoding, immForm: ACSRRCI}, |
| | ACSRRCI & obj.AMask: {enc: iIIEncoding}, |
| | ACSRRS & obj.AMask: {enc: iIIEncoding, immForm: ACSRRSI}, |
| | ACSRRSI & obj.AMask: {enc: iIIEncoding}, |
| | ACSRRW & obj.AMask: {enc: iIIEncoding, immForm: ACSRRWI}, |
| | ACSRRWI & obj.AMask: {enc: iIIEncoding}, |
| |
|
| | |
| | ACZERONEZ & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | ACZEROEQZ & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| |
|
| | |
| | AMUL & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | AMULH & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | AMULHU & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | AMULHSU & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | AMULW & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | ADIV & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | ADIVU & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | AREM & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | AREMU & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | ADIVW & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | ADIVUW & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | AREMW & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | AREMUW & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| |
|
| | |
| | ALRW & obj.AMask: {enc: rIIIEncoding}, |
| | ALRD & obj.AMask: {enc: rIIIEncoding}, |
| | ASCW & obj.AMask: {enc: rIIIEncoding}, |
| | ASCD & obj.AMask: {enc: rIIIEncoding}, |
| |
|
| | |
| | AAMOSWAPW & obj.AMask: {enc: rIIIEncoding}, |
| | AAMOSWAPD & obj.AMask: {enc: rIIIEncoding}, |
| | AAMOADDW & obj.AMask: {enc: rIIIEncoding}, |
| | AAMOADDD & obj.AMask: {enc: rIIIEncoding}, |
| | AAMOANDW & obj.AMask: {enc: rIIIEncoding}, |
| | AAMOANDD & obj.AMask: {enc: rIIIEncoding}, |
| | AAMOORW & obj.AMask: {enc: rIIIEncoding}, |
| | AAMOORD & obj.AMask: {enc: rIIIEncoding}, |
| | AAMOXORW & obj.AMask: {enc: rIIIEncoding}, |
| | AAMOXORD & obj.AMask: {enc: rIIIEncoding}, |
| | AAMOMAXW & obj.AMask: {enc: rIIIEncoding}, |
| | AAMOMAXD & obj.AMask: {enc: rIIIEncoding}, |
| | AAMOMAXUW & obj.AMask: {enc: rIIIEncoding}, |
| | AAMOMAXUD & obj.AMask: {enc: rIIIEncoding}, |
| | AAMOMINW & obj.AMask: {enc: rIIIEncoding}, |
| | AAMOMIND & obj.AMask: {enc: rIIIEncoding}, |
| | AAMOMINUW & obj.AMask: {enc: rIIIEncoding}, |
| | AAMOMINUD & obj.AMask: {enc: rIIIEncoding}, |
| |
|
| | |
| | AFLW & obj.AMask: {enc: iFEncoding}, |
| | AFSW & obj.AMask: {enc: sFEncoding}, |
| |
|
| | |
| | AFADDS & obj.AMask: {enc: rFFFEncoding}, |
| | AFSUBS & obj.AMask: {enc: rFFFEncoding}, |
| | AFMULS & obj.AMask: {enc: rFFFEncoding}, |
| | AFDIVS & obj.AMask: {enc: rFFFEncoding}, |
| | AFMINS & obj.AMask: {enc: rFFFEncoding}, |
| | AFMAXS & obj.AMask: {enc: rFFFEncoding}, |
| | AFSQRTS & obj.AMask: {enc: rFFFEncoding}, |
| | AFMADDS & obj.AMask: {enc: rFFFFEncoding}, |
| | AFMSUBS & obj.AMask: {enc: rFFFFEncoding}, |
| | AFNMSUBS & obj.AMask: {enc: rFFFFEncoding}, |
| | AFNMADDS & obj.AMask: {enc: rFFFFEncoding}, |
| |
|
| | |
| | AFCVTWS & obj.AMask: {enc: rFIEncoding}, |
| | AFCVTLS & obj.AMask: {enc: rFIEncoding}, |
| | AFCVTSW & obj.AMask: {enc: rIFEncoding}, |
| | AFCVTSL & obj.AMask: {enc: rIFEncoding}, |
| | AFCVTWUS & obj.AMask: {enc: rFIEncoding}, |
| | AFCVTLUS & obj.AMask: {enc: rFIEncoding}, |
| | AFCVTSWU & obj.AMask: {enc: rIFEncoding}, |
| | AFCVTSLU & obj.AMask: {enc: rIFEncoding}, |
| | AFSGNJS & obj.AMask: {enc: rFFFEncoding}, |
| | AFSGNJNS & obj.AMask: {enc: rFFFEncoding}, |
| | AFSGNJXS & obj.AMask: {enc: rFFFEncoding}, |
| | AFMVXW & obj.AMask: {enc: rFIEncoding}, |
| | AFMVWX & obj.AMask: {enc: rIFEncoding}, |
| |
|
| | |
| | AFEQS & obj.AMask: {enc: rFFIEncoding}, |
| | AFLTS & obj.AMask: {enc: rFFIEncoding}, |
| | AFLES & obj.AMask: {enc: rFFIEncoding}, |
| |
|
| | |
| | AFCLASSS & obj.AMask: {enc: rFIEncoding}, |
| |
|
| | |
| | AFLD & obj.AMask: {enc: iFEncoding}, |
| | AFSD & obj.AMask: {enc: sFEncoding}, |
| |
|
| | |
| | AFADDD & obj.AMask: {enc: rFFFEncoding}, |
| | AFSUBD & obj.AMask: {enc: rFFFEncoding}, |
| | AFMULD & obj.AMask: {enc: rFFFEncoding}, |
| | AFDIVD & obj.AMask: {enc: rFFFEncoding}, |
| | AFMIND & obj.AMask: {enc: rFFFEncoding}, |
| | AFMAXD & obj.AMask: {enc: rFFFEncoding}, |
| | AFSQRTD & obj.AMask: {enc: rFFFEncoding}, |
| | AFMADDD & obj.AMask: {enc: rFFFFEncoding}, |
| | AFMSUBD & obj.AMask: {enc: rFFFFEncoding}, |
| | AFNMSUBD & obj.AMask: {enc: rFFFFEncoding}, |
| | AFNMADDD & obj.AMask: {enc: rFFFFEncoding}, |
| |
|
| | |
| | AFCVTWD & obj.AMask: {enc: rFIEncoding}, |
| | AFCVTLD & obj.AMask: {enc: rFIEncoding}, |
| | AFCVTDW & obj.AMask: {enc: rIFEncoding}, |
| | AFCVTDL & obj.AMask: {enc: rIFEncoding}, |
| | AFCVTWUD & obj.AMask: {enc: rFIEncoding}, |
| | AFCVTLUD & obj.AMask: {enc: rFIEncoding}, |
| | AFCVTDWU & obj.AMask: {enc: rIFEncoding}, |
| | AFCVTDLU & obj.AMask: {enc: rIFEncoding}, |
| | AFCVTSD & obj.AMask: {enc: rFFEncoding}, |
| | AFCVTDS & obj.AMask: {enc: rFFEncoding}, |
| | AFSGNJD & obj.AMask: {enc: rFFFEncoding}, |
| | AFSGNJND & obj.AMask: {enc: rFFFEncoding}, |
| | AFSGNJXD & obj.AMask: {enc: rFFFEncoding}, |
| | AFMVXD & obj.AMask: {enc: rFIEncoding}, |
| | AFMVDX & obj.AMask: {enc: rIFEncoding}, |
| |
|
| | |
| | AFEQD & obj.AMask: {enc: rFFIEncoding}, |
| | AFLTD & obj.AMask: {enc: rFFIEncoding}, |
| | AFLED & obj.AMask: {enc: rFFIEncoding}, |
| |
|
| | |
| | AFCLASSD & obj.AMask: {enc: rFIEncoding}, |
| |
|
| | |
| | |
| | |
| |
|
| | |
| | ACLWSP & obj.AMask: {enc: ciEncoding}, |
| | ACLDSP & obj.AMask: {enc: ciEncoding}, |
| | ACFLDSP & obj.AMask: {enc: ciEncoding}, |
| | ACSWSP & obj.AMask: {enc: cssEncoding}, |
| | ACSDSP & obj.AMask: {enc: cssEncoding}, |
| | ACFSDSP & obj.AMask: {enc: cssEncoding}, |
| |
|
| | |
| | ACLW & obj.AMask: {enc: clEncoding}, |
| | ACLD & obj.AMask: {enc: clEncoding}, |
| | ACFLD & obj.AMask: {enc: clEncoding}, |
| | ACSW & obj.AMask: {enc: csEncoding}, |
| | ACSD & obj.AMask: {enc: csEncoding}, |
| | ACFSD & obj.AMask: {enc: csEncoding}, |
| |
|
| | |
| | ACJ & obj.AMask: {enc: cjEncoding}, |
| | ACJR & obj.AMask: {enc: crEncoding}, |
| | ACJALR & obj.AMask: {enc: crEncoding}, |
| | ACBEQZ & obj.AMask: {enc: cbEncoding}, |
| | ACBNEZ & obj.AMask: {enc: cbEncoding}, |
| |
|
| | |
| | ACLI & obj.AMask: {enc: ciEncoding}, |
| | ACLUI & obj.AMask: {enc: ciEncoding}, |
| |
|
| | |
| | ACADDI & obj.AMask: {enc: ciEncoding, ternary: true}, |
| | ACADDIW & obj.AMask: {enc: ciEncoding, ternary: true}, |
| | ACADDI16SP & obj.AMask: {enc: ciEncoding, ternary: true}, |
| | ACADDI4SPN & obj.AMask: {enc: ciwEncoding, ternary: true}, |
| | ACSLLI & obj.AMask: {enc: ciEncoding, ternary: true}, |
| | ACSRLI & obj.AMask: {enc: cbEncoding, ternary: true}, |
| | ACSRAI & obj.AMask: {enc: cbEncoding, ternary: true}, |
| | ACANDI & obj.AMask: {enc: cbEncoding, ternary: true}, |
| |
|
| | |
| | ACMV & obj.AMask: {enc: crEncoding}, |
| | ACADD & obj.AMask: {enc: crEncoding, immForm: ACADDI, ternary: true}, |
| | ACAND & obj.AMask: {enc: caEncoding, immForm: ACANDI, ternary: true}, |
| | ACOR & obj.AMask: {enc: caEncoding, ternary: true}, |
| | ACXOR & obj.AMask: {enc: caEncoding, ternary: true}, |
| | ACSUB & obj.AMask: {enc: caEncoding, ternary: true}, |
| | ACADDW & obj.AMask: {enc: caEncoding, immForm: ACADDIW, ternary: true}, |
| | ACSUBW & obj.AMask: {enc: caEncoding, ternary: true}, |
| |
|
| | |
| | ACNOP & obj.AMask: {enc: ciEncoding}, |
| |
|
| | |
| | ACEBREAK & obj.AMask: {enc: crEncoding}, |
| |
|
| | |
| | |
| | |
| |
|
| | |
| | AADDUW & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | ASH1ADD & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | ASH1ADDUW & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | ASH2ADD & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | ASH2ADDUW & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | ASH3ADD & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | ASH3ADDUW & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | ASLLIUW & obj.AMask: {enc: iIIEncoding, ternary: true}, |
| |
|
| | |
| | AANDN & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | ACLZ & obj.AMask: {enc: rIIEncoding}, |
| | ACLZW & obj.AMask: {enc: rIIEncoding}, |
| | ACPOP & obj.AMask: {enc: rIIEncoding}, |
| | ACPOPW & obj.AMask: {enc: rIIEncoding}, |
| | ACTZ & obj.AMask: {enc: rIIEncoding}, |
| | ACTZW & obj.AMask: {enc: rIIEncoding}, |
| | AMAX & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | AMAXU & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | AMIN & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | AMINU & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | AORN & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | ASEXTB & obj.AMask: {enc: rIIEncoding}, |
| | ASEXTH & obj.AMask: {enc: rIIEncoding}, |
| | AXNOR & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | AZEXTH & obj.AMask: {enc: rIIEncoding}, |
| |
|
| | |
| | AROL & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | AROLW & obj.AMask: {enc: rIIIEncoding, ternary: true}, |
| | AROR & obj.AMask: {enc: rIIIEncoding, immForm: ARORI, ternary: true}, |
| | ARORI & obj.AMask: {enc: iIIEncoding, ternary: true}, |
| | ARORIW & obj.AMask: {enc: iIIEncoding, ternary: true}, |
| | ARORW & obj.AMask: {enc: rIIIEncoding, immForm: ARORIW, ternary: true}, |
| | AORCB & obj.AMask: {enc: rIIEncoding}, |
| | AREV8 & obj.AMask: {enc: rIIEncoding}, |
| |
|
| | |
| | ABCLR & obj.AMask: {enc: rIIIEncoding, immForm: ABCLRI, ternary: true}, |
| | ABCLRI & obj.AMask: {enc: iIIEncoding, ternary: true}, |
| | ABEXT & obj.AMask: {enc: rIIIEncoding, immForm: ABEXTI, ternary: true}, |
| | ABEXTI & obj.AMask: {enc: iIIEncoding, ternary: true}, |
| | ABINV & obj.AMask: {enc: rIIIEncoding, immForm: ABINVI, ternary: true}, |
| | ABINVI & obj.AMask: {enc: iIIEncoding, ternary: true}, |
| | ABSET & obj.AMask: {enc: rIIIEncoding, immForm: ABSETI, ternary: true}, |
| | ABSETI & obj.AMask: {enc: iIIEncoding, ternary: true}, |
| |
|
| | |
| | |
| | |
| |
|
| | |
| | AVSETVLI & obj.AMask: {enc: vsetvliEncoding, immForm: AVSETIVLI}, |
| | AVSETIVLI & obj.AMask: {enc: vsetivliEncoding}, |
| | AVSETVL & obj.AMask: {enc: vsetvlEncoding}, |
| |
|
| | |
| | AVLE8V & obj.AMask: {enc: iVEncoding}, |
| | AVLE16V & obj.AMask: {enc: iVEncoding}, |
| | AVLE32V & obj.AMask: {enc: iVEncoding}, |
| | AVLE64V & obj.AMask: {enc: iVEncoding}, |
| | AVSE8V & obj.AMask: {enc: sVEncoding}, |
| | AVSE16V & obj.AMask: {enc: sVEncoding}, |
| | AVSE32V & obj.AMask: {enc: sVEncoding}, |
| | AVSE64V & obj.AMask: {enc: sVEncoding}, |
| | AVLMV & obj.AMask: {enc: iVEncoding}, |
| | AVSMV & obj.AMask: {enc: sVEncoding}, |
| |
|
| | |
| | AVLSE8V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSE16V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSE32V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSE64V & obj.AMask: {enc: iIIVEncoding}, |
| | AVSSE8V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSE16V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSE32V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSE64V & obj.AMask: {enc: sVIIEncoding}, |
| |
|
| | |
| | AVLUXEI8V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXEI16V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXEI32V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXEI64V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXEI8V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXEI16V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXEI32V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXEI64V & obj.AMask: {enc: iVIVEncoding}, |
| | AVSUXEI8V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXEI16V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXEI32V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXEI64V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXEI8V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXEI16V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXEI32V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXEI64V & obj.AMask: {enc: sVIVEncoding}, |
| |
|
| | |
| | AVLE8FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLE16FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLE32FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLE64FFV & obj.AMask: {enc: iVEncoding}, |
| |
|
| | |
| | AVLSEG2E8V & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG3E8V & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG4E8V & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG5E8V & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG6E8V & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG7E8V & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG8E8V & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG2E16V & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG3E16V & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG4E16V & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG5E16V & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG6E16V & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG7E16V & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG8E16V & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG2E32V & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG3E32V & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG4E32V & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG5E32V & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG6E32V & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG7E32V & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG8E32V & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG2E64V & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG3E64V & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG4E64V & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG5E64V & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG6E64V & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG7E64V & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG8E64V & obj.AMask: {enc: iVEncoding}, |
| | AVSSEG2E8V & obj.AMask: {enc: sVEncoding}, |
| | AVSSEG3E8V & obj.AMask: {enc: sVEncoding}, |
| | AVSSEG4E8V & obj.AMask: {enc: sVEncoding}, |
| | AVSSEG5E8V & obj.AMask: {enc: sVEncoding}, |
| | AVSSEG6E8V & obj.AMask: {enc: sVEncoding}, |
| | AVSSEG7E8V & obj.AMask: {enc: sVEncoding}, |
| | AVSSEG8E8V & obj.AMask: {enc: sVEncoding}, |
| | AVSSEG2E16V & obj.AMask: {enc: sVEncoding}, |
| | AVSSEG3E16V & obj.AMask: {enc: sVEncoding}, |
| | AVSSEG4E16V & obj.AMask: {enc: sVEncoding}, |
| | AVSSEG5E16V & obj.AMask: {enc: sVEncoding}, |
| | AVSSEG6E16V & obj.AMask: {enc: sVEncoding}, |
| | AVSSEG7E16V & obj.AMask: {enc: sVEncoding}, |
| | AVSSEG8E16V & obj.AMask: {enc: sVEncoding}, |
| | AVSSEG2E32V & obj.AMask: {enc: sVEncoding}, |
| | AVSSEG3E32V & obj.AMask: {enc: sVEncoding}, |
| | AVSSEG4E32V & obj.AMask: {enc: sVEncoding}, |
| | AVSSEG5E32V & obj.AMask: {enc: sVEncoding}, |
| | AVSSEG6E32V & obj.AMask: {enc: sVEncoding}, |
| | AVSSEG7E32V & obj.AMask: {enc: sVEncoding}, |
| | AVSSEG8E32V & obj.AMask: {enc: sVEncoding}, |
| | AVSSEG2E64V & obj.AMask: {enc: sVEncoding}, |
| | AVSSEG3E64V & obj.AMask: {enc: sVEncoding}, |
| | AVSSEG4E64V & obj.AMask: {enc: sVEncoding}, |
| | AVSSEG5E64V & obj.AMask: {enc: sVEncoding}, |
| | AVSSEG6E64V & obj.AMask: {enc: sVEncoding}, |
| | AVSSEG7E64V & obj.AMask: {enc: sVEncoding}, |
| | AVSSEG8E64V & obj.AMask: {enc: sVEncoding}, |
| | AVLSEG2E8FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG3E8FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG4E8FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG5E8FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG6E8FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG7E8FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG8E8FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG2E16FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG3E16FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG4E16FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG5E16FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG6E16FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG7E16FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG8E16FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG2E32FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG3E32FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG4E32FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG5E32FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG6E32FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG7E32FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG8E32FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG2E64FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG3E64FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG4E64FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG5E64FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG6E64FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG7E64FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLSEG8E64FFV & obj.AMask: {enc: iVEncoding}, |
| | AVLSSEG2E8V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSSEG3E8V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSSEG4E8V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSSEG5E8V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSSEG6E8V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSSEG7E8V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSSEG8E8V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSSEG2E16V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSSEG3E16V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSSEG4E16V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSSEG5E16V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSSEG6E16V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSSEG7E16V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSSEG8E16V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSSEG2E32V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSSEG3E32V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSSEG4E32V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSSEG5E32V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSSEG6E32V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSSEG7E32V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSSEG8E32V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSSEG2E64V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSSEG3E64V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSSEG4E64V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSSEG5E64V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSSEG6E64V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSSEG7E64V & obj.AMask: {enc: iIIVEncoding}, |
| | AVLSSEG8E64V & obj.AMask: {enc: iIIVEncoding}, |
| | AVSSSEG2E8V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSSEG3E8V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSSEG4E8V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSSEG5E8V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSSEG6E8V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSSEG7E8V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSSEG8E8V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSSEG2E16V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSSEG3E16V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSSEG4E16V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSSEG5E16V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSSEG6E16V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSSEG7E16V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSSEG8E16V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSSEG2E32V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSSEG3E32V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSSEG4E32V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSSEG5E32V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSSEG6E32V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSSEG7E32V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSSEG8E32V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSSEG2E64V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSSEG3E64V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSSEG4E64V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSSEG5E64V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSSEG6E64V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSSEG7E64V & obj.AMask: {enc: sVIIEncoding}, |
| | AVSSSEG8E64V & obj.AMask: {enc: sVIIEncoding}, |
| | AVLOXSEG2EI8V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXSEG3EI8V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXSEG4EI8V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXSEG5EI8V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXSEG6EI8V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXSEG7EI8V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXSEG8EI8V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXSEG2EI16V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXSEG3EI16V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXSEG4EI16V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXSEG5EI16V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXSEG6EI16V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXSEG7EI16V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXSEG8EI16V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXSEG2EI32V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXSEG3EI32V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXSEG4EI32V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXSEG5EI32V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXSEG6EI32V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXSEG7EI32V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXSEG8EI32V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXSEG2EI64V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXSEG3EI64V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXSEG4EI64V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXSEG5EI64V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXSEG6EI64V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXSEG7EI64V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLOXSEG8EI64V & obj.AMask: {enc: iVIVEncoding}, |
| | AVSOXSEG2EI8V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXSEG3EI8V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXSEG4EI8V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXSEG5EI8V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXSEG6EI8V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXSEG7EI8V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXSEG8EI8V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXSEG2EI16V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXSEG3EI16V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXSEG4EI16V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXSEG5EI16V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXSEG6EI16V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXSEG7EI16V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXSEG8EI16V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXSEG2EI32V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXSEG3EI32V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXSEG4EI32V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXSEG5EI32V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXSEG6EI32V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXSEG7EI32V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXSEG8EI32V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXSEG2EI64V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXSEG3EI64V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXSEG4EI64V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXSEG5EI64V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXSEG6EI64V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXSEG7EI64V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSOXSEG8EI64V & obj.AMask: {enc: sVIVEncoding}, |
| | AVLUXSEG2EI8V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXSEG3EI8V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXSEG4EI8V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXSEG5EI8V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXSEG6EI8V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXSEG7EI8V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXSEG8EI8V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXSEG2EI16V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXSEG3EI16V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXSEG4EI16V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXSEG5EI16V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXSEG6EI16V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXSEG7EI16V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXSEG8EI16V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXSEG2EI32V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXSEG3EI32V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXSEG4EI32V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXSEG5EI32V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXSEG6EI32V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXSEG7EI32V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXSEG8EI32V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXSEG2EI64V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXSEG3EI64V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXSEG4EI64V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXSEG5EI64V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXSEG6EI64V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXSEG7EI64V & obj.AMask: {enc: iVIVEncoding}, |
| | AVLUXSEG8EI64V & obj.AMask: {enc: iVIVEncoding}, |
| | AVSUXSEG2EI8V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXSEG3EI8V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXSEG4EI8V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXSEG5EI8V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXSEG6EI8V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXSEG7EI8V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXSEG8EI8V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXSEG2EI16V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXSEG3EI16V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXSEG4EI16V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXSEG5EI16V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXSEG6EI16V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXSEG7EI16V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXSEG8EI16V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXSEG2EI32V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXSEG3EI32V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXSEG4EI32V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXSEG5EI32V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXSEG6EI32V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXSEG7EI32V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXSEG8EI32V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXSEG2EI64V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXSEG3EI64V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXSEG4EI64V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXSEG5EI64V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXSEG6EI64V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXSEG7EI64V & obj.AMask: {enc: sVIVEncoding}, |
| | AVSUXSEG8EI64V & obj.AMask: {enc: sVIVEncoding}, |
| |
|
| | |
| | AVL1RE8V & obj.AMask: {enc: iVEncoding}, |
| | AVL1RE16V & obj.AMask: {enc: iVEncoding}, |
| | AVL1RE32V & obj.AMask: {enc: iVEncoding}, |
| | AVL1RE64V & obj.AMask: {enc: iVEncoding}, |
| | AVL2RE8V & obj.AMask: {enc: iVEncoding}, |
| | AVL2RE16V & obj.AMask: {enc: iVEncoding}, |
| | AVL2RE32V & obj.AMask: {enc: iVEncoding}, |
| | AVL2RE64V & obj.AMask: {enc: iVEncoding}, |
| | AVL4RE8V & obj.AMask: {enc: iVEncoding}, |
| | AVL4RE16V & obj.AMask: {enc: iVEncoding}, |
| | AVL4RE32V & obj.AMask: {enc: iVEncoding}, |
| | AVL4RE64V & obj.AMask: {enc: iVEncoding}, |
| | AVL8RE8V & obj.AMask: {enc: iVEncoding}, |
| | AVL8RE16V & obj.AMask: {enc: iVEncoding}, |
| | AVL8RE32V & obj.AMask: {enc: iVEncoding}, |
| | AVL8RE64V & obj.AMask: {enc: iVEncoding}, |
| | AVS1RV & obj.AMask: {enc: sVEncoding}, |
| | AVS2RV & obj.AMask: {enc: sVEncoding}, |
| | AVS4RV & obj.AMask: {enc: sVEncoding}, |
| | AVS8RV & obj.AMask: {enc: sVEncoding}, |
| |
|
| | |
| | AVADDVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVADDVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVADDVI & obj.AMask: {enc: rVViEncoding}, |
| | AVSUBVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVSUBVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVRSUBVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVRSUBVI & obj.AMask: {enc: rVViEncoding}, |
| |
|
| | |
| | AVWADDUVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVWADDUVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVWSUBUVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVWSUBUVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVWADDVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVWADDVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVWSUBVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVWSUBVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVWADDUWV & obj.AMask: {enc: rVVVEncoding}, |
| | AVWADDUWX & obj.AMask: {enc: rVIVEncoding}, |
| | AVWSUBUWV & obj.AMask: {enc: rVVVEncoding}, |
| | AVWSUBUWX & obj.AMask: {enc: rVIVEncoding}, |
| | AVWADDWV & obj.AMask: {enc: rVVVEncoding}, |
| | AVWADDWX & obj.AMask: {enc: rVIVEncoding}, |
| | AVWSUBWV & obj.AMask: {enc: rVVVEncoding}, |
| | AVWSUBWX & obj.AMask: {enc: rVIVEncoding}, |
| |
|
| | |
| | AVZEXTVF2 & obj.AMask: {enc: rVVEncoding}, |
| | AVSEXTVF2 & obj.AMask: {enc: rVVEncoding}, |
| | AVZEXTVF4 & obj.AMask: {enc: rVVEncoding}, |
| | AVSEXTVF4 & obj.AMask: {enc: rVVEncoding}, |
| | AVZEXTVF8 & obj.AMask: {enc: rVVEncoding}, |
| | AVSEXTVF8 & obj.AMask: {enc: rVVEncoding}, |
| |
|
| | |
| | AVADCVVM & obj.AMask: {enc: rVVVEncoding}, |
| | AVADCVXM & obj.AMask: {enc: rVIVEncoding}, |
| | AVADCVIM & obj.AMask: {enc: rVViEncoding}, |
| | AVMADCVVM & obj.AMask: {enc: rVVVEncoding}, |
| | AVMADCVXM & obj.AMask: {enc: rVIVEncoding}, |
| | AVMADCVIM & obj.AMask: {enc: rVViEncoding}, |
| | AVMADCVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVMADCVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVMADCVI & obj.AMask: {enc: rVViEncoding}, |
| | AVSBCVVM & obj.AMask: {enc: rVVVEncoding}, |
| | AVSBCVXM & obj.AMask: {enc: rVIVEncoding}, |
| | AVMSBCVVM & obj.AMask: {enc: rVVVEncoding}, |
| | AVMSBCVXM & obj.AMask: {enc: rVIVEncoding}, |
| | AVMSBCVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVMSBCVX & obj.AMask: {enc: rVIVEncoding}, |
| |
|
| | |
| | AVANDVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVANDVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVANDVI & obj.AMask: {enc: rVViEncoding}, |
| | AVORVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVORVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVORVI & obj.AMask: {enc: rVViEncoding}, |
| | AVXORVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVXORVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVXORVI & obj.AMask: {enc: rVViEncoding}, |
| |
|
| | |
| | AVSLLVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVSLLVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVSLLVI & obj.AMask: {enc: rVVuEncoding}, |
| | AVSRLVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVSRLVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVSRLVI & obj.AMask: {enc: rVVuEncoding}, |
| | AVSRAVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVSRAVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVSRAVI & obj.AMask: {enc: rVVuEncoding}, |
| |
|
| | |
| | AVNSRLWV & obj.AMask: {enc: rVVVEncoding}, |
| | AVNSRLWX & obj.AMask: {enc: rVIVEncoding}, |
| | AVNSRLWI & obj.AMask: {enc: rVVuEncoding}, |
| | AVNSRAWV & obj.AMask: {enc: rVVVEncoding}, |
| | AVNSRAWX & obj.AMask: {enc: rVIVEncoding}, |
| | AVNSRAWI & obj.AMask: {enc: rVVuEncoding}, |
| |
|
| | |
| | AVMSEQVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVMSEQVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVMSEQVI & obj.AMask: {enc: rVViEncoding}, |
| | AVMSNEVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVMSNEVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVMSNEVI & obj.AMask: {enc: rVViEncoding}, |
| | AVMSLTUVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVMSLTUVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVMSLTVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVMSLTVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVMSLEUVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVMSLEUVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVMSLEUVI & obj.AMask: {enc: rVViEncoding}, |
| | AVMSLEVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVMSLEVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVMSLEVI & obj.AMask: {enc: rVViEncoding}, |
| | AVMSGTUVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVMSGTUVI & obj.AMask: {enc: rVViEncoding}, |
| | AVMSGTVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVMSGTVI & obj.AMask: {enc: rVViEncoding}, |
| |
|
| | |
| | AVMINUVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVMINUVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVMINVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVMINVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVMAXUVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVMAXUVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVMAXVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVMAXVX & obj.AMask: {enc: rVIVEncoding}, |
| |
|
| | |
| | AVMULVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVMULVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVMULHVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVMULHVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVMULHUVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVMULHUVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVMULHSUVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVMULHSUVX & obj.AMask: {enc: rVIVEncoding}, |
| |
|
| | |
| | AVDIVUVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVDIVUVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVDIVVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVDIVVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVREMUVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVREMUVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVREMVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVREMVX & obj.AMask: {enc: rVIVEncoding}, |
| |
|
| | |
| | AVWMULVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVWMULVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVWMULUVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVWMULUVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVWMULSUVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVWMULSUVX & obj.AMask: {enc: rVIVEncoding}, |
| |
|
| | |
| | AVMACCVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVMACCVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVNMSACVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVNMSACVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVMADDVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVMADDVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVNMSUBVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVNMSUBVX & obj.AMask: {enc: rVIVEncoding}, |
| |
|
| | |
| | AVWMACCUVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVWMACCUVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVWMACCVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVWMACCVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVWMACCSUVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVWMACCSUVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVWMACCUSVX & obj.AMask: {enc: rVIVEncoding}, |
| |
|
| | |
| | AVMERGEVVM & obj.AMask: {enc: rVVVEncoding}, |
| | AVMERGEVXM & obj.AMask: {enc: rVIVEncoding}, |
| | AVMERGEVIM & obj.AMask: {enc: rVViEncoding}, |
| |
|
| | |
| | AVMVVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVMVVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVMVVI & obj.AMask: {enc: rVViEncoding}, |
| |
|
| | |
| | AVSADDUVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVSADDUVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVSADDUVI & obj.AMask: {enc: rVViEncoding}, |
| | AVSADDVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVSADDVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVSADDVI & obj.AMask: {enc: rVViEncoding}, |
| | AVSSUBUVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVSSUBUVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVSSUBVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVSSUBVX & obj.AMask: {enc: rVIVEncoding}, |
| |
|
| | |
| | AVAADDUVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVAADDUVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVAADDVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVAADDVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVASUBUVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVASUBUVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVASUBVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVASUBVX & obj.AMask: {enc: rVIVEncoding}, |
| |
|
| | |
| | AVSMULVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVSMULVX & obj.AMask: {enc: rVIVEncoding}, |
| |
|
| | |
| | AVSSRLVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVSSRLVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVSSRLVI & obj.AMask: {enc: rVVuEncoding}, |
| | AVSSRAVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVSSRAVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVSSRAVI & obj.AMask: {enc: rVVuEncoding}, |
| |
|
| | |
| | AVNCLIPUWV & obj.AMask: {enc: rVVVEncoding}, |
| | AVNCLIPUWX & obj.AMask: {enc: rVIVEncoding}, |
| | AVNCLIPUWI & obj.AMask: {enc: rVVuEncoding}, |
| | AVNCLIPWV & obj.AMask: {enc: rVVVEncoding}, |
| | AVNCLIPWX & obj.AMask: {enc: rVIVEncoding}, |
| | AVNCLIPWI & obj.AMask: {enc: rVVuEncoding}, |
| |
|
| | |
| | AVFADDVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVFADDVF & obj.AMask: {enc: rVFVEncoding}, |
| | AVFSUBVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVFSUBVF & obj.AMask: {enc: rVFVEncoding}, |
| | AVFRSUBVF & obj.AMask: {enc: rVFVEncoding}, |
| |
|
| | |
| | AVFWADDVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVFWADDVF & obj.AMask: {enc: rVFVEncoding}, |
| | AVFWSUBVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVFWSUBVF & obj.AMask: {enc: rVFVEncoding}, |
| | AVFWADDWV & obj.AMask: {enc: rVVVEncoding}, |
| | AVFWADDWF & obj.AMask: {enc: rVFVEncoding}, |
| | AVFWSUBWV & obj.AMask: {enc: rVVVEncoding}, |
| | AVFWSUBWF & obj.AMask: {enc: rVFVEncoding}, |
| |
|
| | |
| | AVFMULVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVFMULVF & obj.AMask: {enc: rVFVEncoding}, |
| | AVFDIVVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVFDIVVF & obj.AMask: {enc: rVFVEncoding}, |
| | AVFRDIVVF & obj.AMask: {enc: rVFVEncoding}, |
| |
|
| | |
| | AVFWMULVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVFWMULVF & obj.AMask: {enc: rVFVEncoding}, |
| |
|
| | |
| | AVFMACCVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVFMACCVF & obj.AMask: {enc: rVFVEncoding}, |
| | AVFNMACCVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVFNMACCVF & obj.AMask: {enc: rVFVEncoding}, |
| | AVFMSACVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVFMSACVF & obj.AMask: {enc: rVFVEncoding}, |
| | AVFNMSACVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVFNMSACVF & obj.AMask: {enc: rVFVEncoding}, |
| | AVFMADDVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVFMADDVF & obj.AMask: {enc: rVFVEncoding}, |
| | AVFNMADDVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVFNMADDVF & obj.AMask: {enc: rVFVEncoding}, |
| | AVFMSUBVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVFMSUBVF & obj.AMask: {enc: rVFVEncoding}, |
| | AVFNMSUBVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVFNMSUBVF & obj.AMask: {enc: rVFVEncoding}, |
| |
|
| | |
| | AVFWMACCVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVFWMACCVF & obj.AMask: {enc: rVFVEncoding}, |
| | AVFWNMACCVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVFWNMACCVF & obj.AMask: {enc: rVFVEncoding}, |
| | AVFWMSACVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVFWMSACVF & obj.AMask: {enc: rVFVEncoding}, |
| | AVFWNMSACVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVFWNMSACVF & obj.AMask: {enc: rVFVEncoding}, |
| |
|
| | |
| | AVFSQRTV & obj.AMask: {enc: rVVEncoding}, |
| |
|
| | |
| | AVFRSQRT7V & obj.AMask: {enc: rVVEncoding}, |
| |
|
| | |
| | AVFREC7V & obj.AMask: {enc: rVVEncoding}, |
| |
|
| | |
| | AVFMINVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVFMINVF & obj.AMask: {enc: rVFVEncoding}, |
| | AVFMAXVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVFMAXVF & obj.AMask: {enc: rVFVEncoding}, |
| |
|
| | |
| | AVFSGNJVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVFSGNJVF & obj.AMask: {enc: rVFVEncoding}, |
| | AVFSGNJNVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVFSGNJNVF & obj.AMask: {enc: rVFVEncoding}, |
| | AVFSGNJXVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVFSGNJXVF & obj.AMask: {enc: rVFVEncoding}, |
| |
|
| | |
| | AVMFEQVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVMFEQVF & obj.AMask: {enc: rVFVEncoding}, |
| | AVMFNEVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVMFNEVF & obj.AMask: {enc: rVFVEncoding}, |
| | AVMFLTVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVMFLTVF & obj.AMask: {enc: rVFVEncoding}, |
| | AVMFLEVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVMFLEVF & obj.AMask: {enc: rVFVEncoding}, |
| | AVMFGTVF & obj.AMask: {enc: rVFVEncoding}, |
| | AVMFGEVF & obj.AMask: {enc: rVFVEncoding}, |
| |
|
| | |
| | AVFCLASSV & obj.AMask: {enc: rVVEncoding}, |
| |
|
| | |
| | AVFMERGEVFM & obj.AMask: {enc: rVFVEncoding}, |
| |
|
| | |
| | AVFMVVF & obj.AMask: {enc: rVFVEncoding}, |
| |
|
| | |
| | AVFCVTXUFV & obj.AMask: {enc: rVVEncoding}, |
| | AVFCVTXFV & obj.AMask: {enc: rVVEncoding}, |
| | AVFCVTRTZXUFV & obj.AMask: {enc: rVVEncoding}, |
| | AVFCVTRTZXFV & obj.AMask: {enc: rVVEncoding}, |
| | AVFCVTFXUV & obj.AMask: {enc: rVVEncoding}, |
| | AVFCVTFXV & obj.AMask: {enc: rVVEncoding}, |
| |
|
| | |
| | AVFWCVTXUFV & obj.AMask: {enc: rVVEncoding}, |
| | AVFWCVTXFV & obj.AMask: {enc: rVVEncoding}, |
| | AVFWCVTRTZXUFV & obj.AMask: {enc: rVVEncoding}, |
| | AVFWCVTRTZXFV & obj.AMask: {enc: rVVEncoding}, |
| | AVFWCVTFXUV & obj.AMask: {enc: rVVEncoding}, |
| | AVFWCVTFXV & obj.AMask: {enc: rVVEncoding}, |
| | AVFWCVTFFV & obj.AMask: {enc: rVVEncoding}, |
| |
|
| | |
| | AVFNCVTXUFW & obj.AMask: {enc: rVVEncoding}, |
| | AVFNCVTXFW & obj.AMask: {enc: rVVEncoding}, |
| | AVFNCVTRTZXUFW & obj.AMask: {enc: rVVEncoding}, |
| | AVFNCVTRTZXFW & obj.AMask: {enc: rVVEncoding}, |
| | AVFNCVTFXUW & obj.AMask: {enc: rVVEncoding}, |
| | AVFNCVTFXW & obj.AMask: {enc: rVVEncoding}, |
| | AVFNCVTFFW & obj.AMask: {enc: rVVEncoding}, |
| | AVFNCVTRODFFW & obj.AMask: {enc: rVVEncoding}, |
| |
|
| | |
| | AVREDSUMVS & obj.AMask: {enc: rVVVEncoding}, |
| | AVREDMAXUVS & obj.AMask: {enc: rVVVEncoding}, |
| | AVREDMAXVS & obj.AMask: {enc: rVVVEncoding}, |
| | AVREDMINUVS & obj.AMask: {enc: rVVVEncoding}, |
| | AVREDMINVS & obj.AMask: {enc: rVVVEncoding}, |
| | AVREDANDVS & obj.AMask: {enc: rVVVEncoding}, |
| | AVREDORVS & obj.AMask: {enc: rVVVEncoding}, |
| | AVREDXORVS & obj.AMask: {enc: rVVVEncoding}, |
| |
|
| | |
| | AVWREDSUMUVS & obj.AMask: {enc: rVVVEncoding}, |
| | AVWREDSUMVS & obj.AMask: {enc: rVVVEncoding}, |
| |
|
| | |
| | AVFREDOSUMVS & obj.AMask: {enc: rVVVEncoding}, |
| | AVFREDUSUMVS & obj.AMask: {enc: rVVVEncoding}, |
| | AVFREDMAXVS & obj.AMask: {enc: rVVVEncoding}, |
| | AVFREDMINVS & obj.AMask: {enc: rVVVEncoding}, |
| |
|
| | |
| | AVFWREDOSUMVS & obj.AMask: {enc: rVVVEncoding}, |
| | AVFWREDUSUMVS & obj.AMask: {enc: rVVVEncoding}, |
| |
|
| | |
| | AVMANDMM & obj.AMask: {enc: rVVVEncoding}, |
| | AVMNANDMM & obj.AMask: {enc: rVVVEncoding}, |
| | AVMANDNMM & obj.AMask: {enc: rVVVEncoding}, |
| | AVMXORMM & obj.AMask: {enc: rVVVEncoding}, |
| | AVMORMM & obj.AMask: {enc: rVVVEncoding}, |
| | AVMNORMM & obj.AMask: {enc: rVVVEncoding}, |
| | AVMORNMM & obj.AMask: {enc: rVVVEncoding}, |
| | AVMXNORMM & obj.AMask: {enc: rVVVEncoding}, |
| | AVCPOPM & obj.AMask: {enc: rVIEncoding}, |
| | AVFIRSTM & obj.AMask: {enc: rVIEncoding}, |
| | AVMSBFM & obj.AMask: {enc: rVVEncoding}, |
| | AVMSIFM & obj.AMask: {enc: rVVEncoding}, |
| | AVMSOFM & obj.AMask: {enc: rVVEncoding}, |
| | AVIOTAM & obj.AMask: {enc: rVVEncoding}, |
| | AVIDV & obj.AMask: {enc: rVVEncoding}, |
| |
|
| | |
| | AVMVXS & obj.AMask: {enc: rVIEncoding}, |
| | AVMVSX & obj.AMask: {enc: rIVEncoding}, |
| |
|
| | |
| | AVFMVFS & obj.AMask: {enc: rVFEncoding}, |
| | AVFMVSF & obj.AMask: {enc: rFVEncoding}, |
| |
|
| | |
| | AVSLIDEUPVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVSLIDEUPVI & obj.AMask: {enc: rVVuEncoding}, |
| | AVSLIDEDOWNVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVSLIDEDOWNVI & obj.AMask: {enc: rVVuEncoding}, |
| | AVSLIDE1UPVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVFSLIDE1UPVF & obj.AMask: {enc: rVFVEncoding}, |
| | AVSLIDE1DOWNVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVFSLIDE1DOWNVF & obj.AMask: {enc: rVFVEncoding}, |
| |
|
| | |
| | AVRGATHERVV & obj.AMask: {enc: rVVVEncoding}, |
| | AVRGATHEREI16VV & obj.AMask: {enc: rVVVEncoding}, |
| | AVRGATHERVX & obj.AMask: {enc: rVIVEncoding}, |
| | AVRGATHERVI & obj.AMask: {enc: rVVuEncoding}, |
| |
|
| | |
| | AVCOMPRESSVM & obj.AMask: {enc: rVVVEncoding}, |
| |
|
| | |
| | AVMV1RV & obj.AMask: {enc: rVVEncoding}, |
| | AVMV2RV & obj.AMask: {enc: rVVEncoding}, |
| | AVMV4RV & obj.AMask: {enc: rVVEncoding}, |
| | AVMV8RV & obj.AMask: {enc: rVVEncoding}, |
| |
|
| | |
| | |
| | |
| |
|
| | |
| | AECALL & obj.AMask: {enc: iIIEncoding}, |
| | AEBREAK & obj.AMask: {enc: iIIEncoding}, |
| |
|
| | |
| | AWORD & obj.AMask: {enc: rawEncoding}, |
| |
|
| | |
| | obj.AFUNCDATA: {enc: pseudoOpEncoding}, |
| | obj.APCDATA: {enc: pseudoOpEncoding}, |
| | obj.ATEXT: {enc: pseudoOpEncoding}, |
| | obj.ANOP: {enc: pseudoOpEncoding}, |
| | obj.APCALIGN: {enc: pseudoOpEncoding}, |
| | } |
| |
|
| | |
| | func instructionDataForAs(as obj.As) (*instructionData, error) { |
| | if base := as &^ obj.AMask; base != obj.ABaseRISCV && base != 0 { |
| | return nil, fmt.Errorf("%v is not a RISC-V instruction", as) |
| | } |
| | asi := as & obj.AMask |
| | if int(asi) >= len(instructions) { |
| | return nil, fmt.Errorf("bad RISC-V instruction %v", as) |
| | } |
| | return &instructions[asi], nil |
| | } |
| |
|
| | |
| | func encodingForAs(as obj.As) (*encoding, error) { |
| | insData, err := instructionDataForAs(as) |
| | if err != nil { |
| | return &badEncoding, err |
| | } |
| | if insData.enc.validate == nil { |
| | return &badEncoding, fmt.Errorf("no encoding for instruction %s", as) |
| | } |
| | return &insData.enc, nil |
| | } |
| |
|
| | |
| | |
| | func splitShiftConst(v int64) (imm int64, lsh int, rsh int, ok bool) { |
| | |
| | lsh = bits.TrailingZeros64(uint64(v)) |
| | c := v >> lsh |
| | if int64(int32(c)) == c { |
| | return c, lsh, 0, true |
| | } |
| |
|
| | |
| | rsh = bits.LeadingZeros64(uint64(v)) |
| | ones := bits.OnesCount64((uint64(v) >> lsh) >> 11) |
| | c = signExtend(1<<11|((v>>lsh)&0x7ff), 12) |
| | if rsh+ones+lsh+11 == 64 { |
| | if lsh > 0 || c != -1 { |
| | lsh += rsh |
| | } |
| | return c, lsh, rsh, true |
| | } |
| |
|
| | return 0, 0, 0, false |
| | } |
| |
|
| | |
| | |
| | func isShiftConst(v int64) bool { |
| | _, lsh, rsh, ok := splitShiftConst(v) |
| | return ok && (lsh > 0 || rsh > 0) |
| | } |
| |
|
| | type instruction struct { |
| | p *obj.Prog |
| | as obj.As |
| | rd uint32 |
| | rs1 uint32 |
| | rs2 uint32 |
| | rs3 uint32 |
| | imm int64 |
| | funct3 uint32 |
| | funct7 uint32 |
| | } |
| |
|
| | func (ins *instruction) String() string { |
| | if ins.p == nil { |
| | return ins.as.String() |
| | } |
| | var suffix string |
| | if ins.p.As != ins.as { |
| | suffix = fmt.Sprintf(" (%v)", ins.as) |
| | } |
| | return fmt.Sprintf("%v%v", ins.p, suffix) |
| | } |
| |
|
| | func (ins *instruction) encode() (uint32, error) { |
| | enc, err := encodingForAs(ins.as) |
| | if err != nil { |
| | return 0, err |
| | } |
| | if enc.length <= 0 { |
| | return 0, fmt.Errorf("%v: encoding called for a pseudo instruction", ins.as) |
| | } |
| | return enc.encode(ins), nil |
| | } |
| |
|
| | func (ins *instruction) length() int { |
| | enc, err := encodingForAs(ins.as) |
| | if err != nil { |
| | return 0 |
| | } |
| | return enc.length |
| | } |
| |
|
| | func (ins *instruction) validate(ctxt *obj.Link) { |
| | enc, err := encodingForAs(ins.as) |
| | if err != nil { |
| | ctxt.Diag("%v", err) |
| | return |
| | } |
| | enc.validate(ctxt, ins) |
| | } |
| |
|
| | func (ins *instruction) usesRegTmp() bool { |
| | return ins.rd == REG_TMP || ins.rs1 == REG_TMP || ins.rs2 == REG_TMP |
| | } |
| |
|
| | func (ins *instruction) compress() { |
| | switch ins.as { |
| | case ALW: |
| | if ins.rd != REG_X0 && ins.rs1 == REG_SP && isScaledImmU(ins.imm, 8, 4) { |
| | ins.as, ins.rs1, ins.rs2 = ACLWSP, obj.REG_NONE, ins.rs1 |
| | } else if isIntPrimeReg(ins.rd) && isIntPrimeReg(ins.rs1) && isScaledImmU(ins.imm, 7, 4) { |
| | ins.as = ACLW |
| | } |
| |
|
| | case ALD: |
| | if ins.rs1 == REG_SP && ins.rd != REG_X0 && isScaledImmU(ins.imm, 9, 8) { |
| | ins.as, ins.rs1, ins.rs2 = ACLDSP, obj.REG_NONE, ins.rs1 |
| | } else if isIntPrimeReg(ins.rd) && isIntPrimeReg(ins.rs1) && isScaledImmU(ins.imm, 8, 8) { |
| | ins.as = ACLD |
| | } |
| |
|
| | case AFLD: |
| | if ins.rs1 == REG_SP && isScaledImmU(ins.imm, 9, 8) { |
| | ins.as, ins.rs1, ins.rs2 = ACFLDSP, obj.REG_NONE, ins.rs1 |
| | } else if isFloatPrimeReg(ins.rd) && isIntPrimeReg(ins.rs1) && isScaledImmU(ins.imm, 8, 8) { |
| | ins.as = ACFLD |
| | } |
| |
|
| | case ASW: |
| | if ins.rd == REG_SP && isScaledImmU(ins.imm, 8, 4) { |
| | ins.as, ins.rs1, ins.rs2 = ACSWSP, obj.REG_NONE, ins.rs1 |
| | } else if isIntPrimeReg(ins.rd) && isIntPrimeReg(ins.rs1) && isScaledImmU(ins.imm, 7, 4) { |
| | ins.as, ins.rd, ins.rs1, ins.rs2 = ACSW, obj.REG_NONE, ins.rd, ins.rs1 |
| | } |
| |
|
| | case ASD: |
| | if ins.rd == REG_SP && isScaledImmU(ins.imm, 9, 8) { |
| | ins.as, ins.rs1, ins.rs2 = ACSDSP, obj.REG_NONE, ins.rs1 |
| | } else if isIntPrimeReg(ins.rd) && isIntPrimeReg(ins.rs1) && isScaledImmU(ins.imm, 8, 8) { |
| | ins.as, ins.rd, ins.rs1, ins.rs2 = ACSD, obj.REG_NONE, ins.rd, ins.rs1 |
| | } |
| |
|
| | case AFSD: |
| | if ins.rd == REG_SP && isScaledImmU(ins.imm, 9, 8) { |
| | ins.as, ins.rs1, ins.rs2 = ACFSDSP, obj.REG_NONE, ins.rs1 |
| | } else if isIntPrimeReg(ins.rd) && isFloatPrimeReg(ins.rs1) && isScaledImmU(ins.imm, 8, 8) { |
| | ins.as, ins.rd, ins.rs1, ins.rs2 = ACFSD, obj.REG_NONE, ins.rd, ins.rs1 |
| | } |
| |
|
| | case AADDI: |
| | if ins.rd == REG_SP && ins.rs1 == REG_SP && ins.imm != 0 && isScaledImmI(ins.imm, 10, 16) { |
| | ins.as = ACADDI16SP |
| | } else if ins.rd != REG_X0 && ins.rd == ins.rs1 && ins.imm != 0 && immIFits(ins.imm, 6) == nil { |
| | ins.as = ACADDI |
| | } else if isIntPrimeReg(ins.rd) && ins.rs1 == REG_SP && ins.imm != 0 && isScaledImmU(ins.imm, 10, 4) { |
| | ins.as = ACADDI4SPN |
| | } else if ins.rd != REG_X0 && ins.rs1 == REG_X0 && immIFits(ins.imm, 6) == nil { |
| | ins.as, ins.rs1 = ACLI, obj.REG_NONE |
| | } else if ins.rd != REG_X0 && ins.rs1 != REG_X0 && ins.imm == 0 { |
| | ins.as, ins.rs1, ins.rs2 = ACMV, obj.REG_NONE, ins.rs1 |
| | } else if ins.rd == REG_X0 && ins.rs1 == REG_X0 && ins.imm == 0 { |
| | ins.as, ins.rs1 = ACNOP, ins.rd |
| | } |
| |
|
| | case AADDIW: |
| | if ins.rd == ins.rs1 && immIFits(ins.imm, 6) == nil { |
| | ins.as = ACADDIW |
| | } |
| |
|
| | case ALUI: |
| | if ins.rd != REG_X0 && ins.rd != REG_SP && ins.imm != 0 && immIFits(ins.imm, 6) == nil { |
| | ins.as = ACLUI |
| | } |
| |
|
| | case ASLLI: |
| | if ins.rd != REG_X0 && ins.rd == ins.rs1 && ins.imm != 0 { |
| | ins.as = ACSLLI |
| | } |
| |
|
| | case ASRLI: |
| | if isIntPrimeReg(ins.rd) && ins.rd == ins.rs1 && ins.imm != 0 { |
| | ins.as = ACSRLI |
| | } |
| |
|
| | case ASRAI: |
| | if isIntPrimeReg(ins.rd) && ins.rd == ins.rs1 && ins.imm != 0 { |
| | ins.as = ACSRAI |
| | } |
| |
|
| | case AANDI: |
| | if isIntPrimeReg(ins.rd) && ins.rd == ins.rs1 && immIFits(ins.imm, 6) == nil { |
| | ins.as = ACANDI |
| | } |
| |
|
| | case AADD: |
| | if ins.rd != REG_X0 && ins.rd == ins.rs1 && ins.rs2 != REG_X0 { |
| | ins.as = ACADD |
| | } else if ins.rd != REG_X0 && ins.rd == ins.rs2 && ins.rs1 != REG_X0 { |
| | ins.as, ins.rs1, ins.rs2 = ACADD, ins.rs2, ins.rs1 |
| | } else if ins.rd != REG_X0 && ins.rs1 == REG_X0 && ins.rs2 != REG_X0 { |
| | ins.as = ACMV |
| | } |
| |
|
| | case AADDW: |
| | if isIntPrimeReg(ins.rd) && ins.rd == ins.rs1 && isIntPrimeReg(ins.rs2) { |
| | ins.as = ACADDW |
| | } else if isIntPrimeReg(ins.rd) && isIntPrimeReg(ins.rs1) && ins.rd == ins.rs2 { |
| | ins.as, ins.rs1, ins.rs2 = ACADDW, ins.rs2, ins.rs1 |
| | } |
| |
|
| | case ASUB: |
| | if isIntPrimeReg(ins.rd) && ins.rd == ins.rs1 && isIntPrimeReg(ins.rs2) { |
| | ins.as = ACSUB |
| | } |
| |
|
| | case ASUBW: |
| | if isIntPrimeReg(ins.rd) && ins.rd == ins.rs1 && isIntPrimeReg(ins.rs2) { |
| | ins.as = ACSUBW |
| | } |
| |
|
| | case AAND: |
| | if isIntPrimeReg(ins.rd) && ins.rd == ins.rs1 && isIntPrimeReg(ins.rs2) { |
| | ins.as = ACAND |
| | } else if isIntPrimeReg(ins.rd) && isIntPrimeReg(ins.rs1) && ins.rd == ins.rs2 { |
| | ins.as, ins.rs1, ins.rs2 = ACAND, ins.rs2, ins.rs1 |
| | } |
| |
|
| | case AOR: |
| | if isIntPrimeReg(ins.rd) && ins.rd == ins.rs1 && isIntPrimeReg(ins.rs2) { |
| | ins.as = ACOR |
| | } else if isIntPrimeReg(ins.rd) && isIntPrimeReg(ins.rs1) && ins.rd == ins.rs2 { |
| | ins.as, ins.rs1, ins.rs2 = ACOR, ins.rs2, ins.rs1 |
| | } |
| |
|
| | case AXOR: |
| | if isIntPrimeReg(ins.rd) && ins.rd == ins.rs1 && isIntPrimeReg(ins.rs2) { |
| | ins.as = ACXOR |
| | } else if isIntPrimeReg(ins.rd) && isIntPrimeReg(ins.rs1) && ins.rd == ins.rs2 { |
| | ins.as, ins.rs1, ins.rs2 = ACXOR, ins.rs2, ins.rs1 |
| | } |
| |
|
| | case AEBREAK: |
| | ins.as, ins.rd, ins.rs1 = ACEBREAK, obj.REG_NONE, obj.REG_NONE |
| | } |
| | } |
| |
|
| | |
| | func instructionForProg(p *obj.Prog) *instruction { |
| | ins := &instruction{ |
| | as: p.As, |
| | rd: uint32(p.To.Reg), |
| | rs1: uint32(p.Reg), |
| | rs2: uint32(p.From.Reg), |
| | imm: p.From.Offset, |
| | } |
| | if len(p.RestArgs) == 1 { |
| | ins.rs3 = uint32(p.RestArgs[0].Reg) |
| | } |
| | return ins |
| | } |
| |
|
| | |
| | |
| | |
| | func instructionsForOpImmediate(p *obj.Prog, as obj.As, rs int16) []*instruction { |
| | |
| | ins := instructionForProg(p) |
| | ins.as, ins.rs1, ins.rs2 = as, uint32(rs), obj.REG_NONE |
| |
|
| | low, high, err := Split32BitImmediate(ins.imm) |
| | if err != nil { |
| | p.Ctxt.Diag("%v: constant %d too large: %v", p, ins.imm, err) |
| | return nil |
| | } |
| | if high == 0 { |
| | return []*instruction{ins} |
| | } |
| |
|
| | |
| | |
| | if p.Spadj == 0 && ins.as == AADDI && ins.imm >= -(1<<12) && ins.imm < 1<<12-1 { |
| | imm0 := ins.imm / 2 |
| | imm1 := ins.imm - imm0 |
| |
|
| | |
| | |
| | ins.imm = imm0 |
| | insADDI := &instruction{as: AADDI, rd: ins.rd, rs1: ins.rd, imm: imm1} |
| | return []*instruction{ins, insADDI} |
| | } |
| |
|
| | |
| | |
| | |
| | insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high} |
| | insADDIW := &instruction{as: AADDIW, rd: REG_TMP, rs1: REG_TMP, imm: low} |
| | switch ins.as { |
| | case AADDI: |
| | ins.as = AADD |
| | case AANDI: |
| | ins.as = AAND |
| | case AORI: |
| | ins.as = AOR |
| | case AXORI: |
| | ins.as = AXOR |
| | default: |
| | p.Ctxt.Diag("unsupported immediate instruction %v for splitting", p) |
| | return nil |
| | } |
| | ins.rs2 = REG_TMP |
| | if low == 0 { |
| | return []*instruction{insLUI, ins} |
| | } |
| | return []*instruction{insLUI, insADDIW, ins} |
| | } |
| |
|
| | |
| | |
| | |
| | func instructionsForLoad(p *obj.Prog, as obj.As, rs int16) []*instruction { |
| | if p.From.Type != obj.TYPE_MEM { |
| | p.Ctxt.Diag("%v requires memory for source", p) |
| | return nil |
| | } |
| |
|
| | switch as { |
| | case ALD, ALB, ALH, ALW, ALBU, ALHU, ALWU, AFLW, AFLD: |
| | default: |
| | p.Ctxt.Diag("%v: unknown load instruction %v", p, as) |
| | return nil |
| | } |
| |
|
| | |
| | ins := instructionForProg(p) |
| | ins.as, ins.rs1, ins.rs2 = as, uint32(rs), obj.REG_NONE |
| | ins.imm = p.From.Offset |
| |
|
| | low, high, err := Split32BitImmediate(ins.imm) |
| | if err != nil { |
| | p.Ctxt.Diag("%v: constant %d too large", p, ins.imm) |
| | return nil |
| | } |
| | if high == 0 { |
| | return []*instruction{ins} |
| | } |
| |
|
| | |
| | |
| | |
| | insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high} |
| | insADD := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: ins.rs1} |
| | ins.rs1, ins.imm = REG_TMP, low |
| |
|
| | return []*instruction{insLUI, insADD, ins} |
| | } |
| |
|
| | |
| | |
| | |
| | func instructionsForStore(p *obj.Prog, as obj.As, rd int16) []*instruction { |
| | if p.To.Type != obj.TYPE_MEM { |
| | p.Ctxt.Diag("%v requires memory for destination", p) |
| | return nil |
| | } |
| |
|
| | switch as { |
| | case ASW, ASH, ASB, ASD, AFSW, AFSD: |
| | default: |
| | p.Ctxt.Diag("%v: unknown store instruction %v", p, as) |
| | return nil |
| | } |
| |
|
| | |
| | ins := instructionForProg(p) |
| | ins.as, ins.rd, ins.rs1, ins.rs2 = as, uint32(rd), uint32(p.From.Reg), obj.REG_NONE |
| | ins.imm = p.To.Offset |
| |
|
| | low, high, err := Split32BitImmediate(ins.imm) |
| | if err != nil { |
| | p.Ctxt.Diag("%v: constant %d too large", p, ins.imm) |
| | return nil |
| | } |
| | if high == 0 { |
| | return []*instruction{ins} |
| | } |
| |
|
| | |
| | |
| | |
| | insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high} |
| | insADD := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: ins.rd} |
| | ins.rd, ins.imm = REG_TMP, low |
| |
|
| | return []*instruction{insLUI, insADD, ins} |
| | } |
| |
|
| | func instructionsForTLS(p *obj.Prog, ins *instruction) []*instruction { |
| | insAddTP := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: REG_TP} |
| |
|
| | var inss []*instruction |
| | if p.Ctxt.Flag_shared { |
| | |
| | |
| | insAUIPC := &instruction{as: AAUIPC, rd: REG_TMP} |
| | insLoadTLSOffset := &instruction{as: ALD, rd: REG_TMP, rs1: REG_TMP} |
| | inss = []*instruction{insAUIPC, insLoadTLSOffset, insAddTP, ins} |
| | } else { |
| | |
| | |
| | |
| | |
| | |
| | insLUI := &instruction{as: ALUI, rd: REG_TMP} |
| | insADDIW := &instruction{as: AADDIW, rd: REG_TMP, rs1: REG_TMP} |
| | inss = []*instruction{insLUI, insADDIW, insAddTP, ins} |
| | } |
| | return inss |
| | } |
| |
|
| | func instructionsForTLSLoad(p *obj.Prog) []*instruction { |
| | if p.From.Sym.Type != objabi.STLSBSS { |
| | p.Ctxt.Diag("%v: %v is not a TLS symbol", p, p.From.Sym) |
| | return nil |
| | } |
| |
|
| | ins := instructionForProg(p) |
| | ins.as, ins.rs1, ins.rs2, ins.imm = movToLoad(p.As), REG_TMP, obj.REG_NONE, 0 |
| |
|
| | return instructionsForTLS(p, ins) |
| | } |
| |
|
| | func instructionsForTLSStore(p *obj.Prog) []*instruction { |
| | if p.To.Sym.Type != objabi.STLSBSS { |
| | p.Ctxt.Diag("%v: %v is not a TLS symbol", p, p.To.Sym) |
| | return nil |
| | } |
| |
|
| | ins := instructionForProg(p) |
| | ins.as, ins.rd, ins.rs1, ins.rs2, ins.imm = movToStore(p.As), REG_TMP, uint32(p.From.Reg), obj.REG_NONE, 0 |
| |
|
| | return instructionsForTLS(p, ins) |
| | } |
| |
|
| | |
| | |
| | func instructionsForMOV(p *obj.Prog) []*instruction { |
| | ins := instructionForProg(p) |
| | inss := []*instruction{ins} |
| |
|
| | if p.Reg != 0 { |
| | p.Ctxt.Diag("%v: illegal MOV instruction", p) |
| | return nil |
| | } |
| |
|
| | switch { |
| | case p.From.Type == obj.TYPE_CONST && p.To.Type == obj.TYPE_REG: |
| | |
| | if p.As != AMOV { |
| | p.Ctxt.Diag("%v: unsupported constant load", p) |
| | return nil |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | var insSLLI, insSRLI *instruction |
| | if err := immIFits(ins.imm, 32); err != nil { |
| | if c, lsh, rsh, ok := splitShiftConst(ins.imm); ok { |
| | ins.imm = c |
| | if lsh > 0 { |
| | insSLLI = &instruction{as: ASLLI, rd: ins.rd, rs1: ins.rd, imm: int64(lsh)} |
| | } |
| | if rsh > 0 { |
| | insSRLI = &instruction{as: ASRLI, rd: ins.rd, rs1: ins.rd, imm: int64(rsh)} |
| | } |
| | } |
| | } |
| |
|
| | low, high, err := Split32BitImmediate(ins.imm) |
| | if err != nil { |
| | p.Ctxt.Diag("%v: constant %d too large: %v", p, ins.imm, err) |
| | return nil |
| | } |
| |
|
| | |
| | ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, REG_ZERO, obj.REG_NONE, low |
| |
|
| | |
| | if high != 0 { |
| | |
| | |
| | insLUI := &instruction{as: ALUI, rd: ins.rd, imm: high} |
| | inss = []*instruction{insLUI} |
| | if low != 0 { |
| | ins.as, ins.rs1 = AADDIW, ins.rd |
| | inss = append(inss, ins) |
| | } |
| | } |
| | if insSLLI != nil { |
| | inss = append(inss, insSLLI) |
| | } |
| | if insSRLI != nil { |
| | inss = append(inss, insSRLI) |
| | } |
| |
|
| | case p.From.Type == obj.TYPE_CONST && p.To.Type != obj.TYPE_REG: |
| | p.Ctxt.Diag("%v: constant load must target register", p) |
| | return nil |
| |
|
| | case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_REG: |
| | |
| | switch p.As { |
| | case AMOV: |
| | |
| | ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, uint32(p.From.Reg), obj.REG_NONE, 0 |
| | case AMOVW: |
| | |
| | ins.as, ins.rs1, ins.rs2, ins.imm = AADDIW, uint32(p.From.Reg), obj.REG_NONE, 0 |
| | case AMOVBU: |
| | |
| | ins.as, ins.rs1, ins.rs2, ins.imm = AANDI, uint32(p.From.Reg), obj.REG_NONE, 255 |
| | case AMOVF: |
| | |
| | |
| | |
| | if ins.rs2 >= REG_X0 && ins.rs2 <= REG_X31 && ins.rd >= REG_F0 && ins.rd <= REG_F31 { |
| | ins.as = AFMVWX |
| | } else if ins.rs2 >= REG_F0 && ins.rs2 <= REG_F31 && ins.rd >= REG_X0 && ins.rd <= REG_X31 { |
| | ins.as = AFMVXW |
| | } else { |
| | ins.as, ins.rs1 = AFSGNJS, uint32(p.From.Reg) |
| | } |
| | case AMOVD: |
| | |
| | |
| | |
| | if ins.rs2 >= REG_X0 && ins.rs2 <= REG_X31 && ins.rd >= REG_F0 && ins.rd <= REG_F31 { |
| | ins.as = AFMVDX |
| | } else if ins.rs2 >= REG_F0 && ins.rs2 <= REG_F31 && ins.rd >= REG_X0 && ins.rd <= REG_X31 { |
| | ins.as = AFMVXD |
| | } else { |
| | ins.as, ins.rs1 = AFSGNJD, uint32(p.From.Reg) |
| | } |
| | case AMOVB, AMOVH: |
| | if buildcfg.GORISCV64 >= 22 { |
| | |
| | ins.as, ins.rs1, ins.rs2 = ASEXTB, uint32(p.From.Reg), obj.REG_NONE |
| | if p.As == AMOVH { |
| | ins.as = ASEXTH |
| | } |
| | } else { |
| | |
| | ins.as, ins.rs1, ins.rs2 = ASLLI, uint32(p.From.Reg), obj.REG_NONE |
| | if p.As == AMOVB { |
| | ins.imm = 56 |
| | } else if p.As == AMOVH { |
| | ins.imm = 48 |
| | } |
| | ins2 := &instruction{as: ASRAI, rd: ins.rd, rs1: ins.rd, imm: ins.imm} |
| | inss = append(inss, ins2) |
| | } |
| | case AMOVHU, AMOVWU: |
| | if buildcfg.GORISCV64 >= 22 { |
| | |
| | ins.as, ins.rs1, ins.rs2, ins.imm = AZEXTH, uint32(p.From.Reg), obj.REG_NONE, 0 |
| | if p.As == AMOVWU { |
| | ins.as, ins.rs2 = AADDUW, REG_ZERO |
| | } |
| | } else { |
| | |
| | ins.as, ins.rs1, ins.rs2 = ASLLI, uint32(p.From.Reg), obj.REG_NONE |
| | if p.As == AMOVHU { |
| | ins.imm = 48 |
| | } else if p.As == AMOVWU { |
| | ins.imm = 32 |
| | } |
| | ins2 := &instruction{as: ASRLI, rd: ins.rd, rs1: ins.rd, imm: ins.imm} |
| | inss = append(inss, ins2) |
| | } |
| | } |
| |
|
| | case p.From.Type == obj.TYPE_MEM && p.To.Type == obj.TYPE_REG: |
| | |
| | switch p.From.Name { |
| | case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE: |
| | |
| | inss = instructionsForLoad(p, movToLoad(p.As), addrToReg(p.From)) |
| |
|
| | case obj.NAME_EXTERN, obj.NAME_STATIC, obj.NAME_GOTREF: |
| | if p.From.Sym.Type == objabi.STLSBSS { |
| | return instructionsForTLSLoad(p) |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | addrReg := ins.rd |
| | if addrReg < REG_X0 || addrReg > REG_X31 { |
| | addrReg = REG_TMP |
| | } |
| | insAUIPC := &instruction{as: AAUIPC, rd: addrReg} |
| | ins.as, ins.rs1, ins.rs2, ins.imm = movToLoad(p.As), addrReg, obj.REG_NONE, 0 |
| | inss = []*instruction{insAUIPC, ins} |
| |
|
| | default: |
| | p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p) |
| | return nil |
| | } |
| |
|
| | case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_MEM: |
| | |
| | switch p.As { |
| | case AMOVBU, AMOVHU, AMOVWU: |
| | p.Ctxt.Diag("%v: unsupported unsigned store", p) |
| | return nil |
| | } |
| | switch p.To.Name { |
| | case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE: |
| | |
| | inss = instructionsForStore(p, movToStore(p.As), addrToReg(p.To)) |
| |
|
| | case obj.NAME_EXTERN, obj.NAME_STATIC: |
| | if p.To.Sym.Type == objabi.STLSBSS { |
| | return instructionsForTLSStore(p) |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | insAUIPC := &instruction{as: AAUIPC, rd: REG_TMP} |
| | ins.as, ins.rd, ins.rs1, ins.rs2, ins.imm = movToStore(p.As), REG_TMP, uint32(p.From.Reg), obj.REG_NONE, 0 |
| | inss = []*instruction{insAUIPC, ins} |
| |
|
| | default: |
| | p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p) |
| | return nil |
| | } |
| |
|
| | case p.From.Type == obj.TYPE_ADDR && p.To.Type == obj.TYPE_REG: |
| | |
| | if p.As != AMOV { |
| | p.Ctxt.Diag("%v: unsupported address load", p) |
| | return nil |
| | } |
| | switch p.From.Name { |
| | case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE: |
| | inss = instructionsForOpImmediate(p, AADDI, addrToReg(p.From)) |
| |
|
| | case obj.NAME_EXTERN, obj.NAME_STATIC: |
| | |
| | |
| | |
| | |
| | |
| | insAUIPC := &instruction{as: AAUIPC, rd: ins.rd} |
| | ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, ins.rd, obj.REG_NONE, 0 |
| | inss = []*instruction{insAUIPC, ins} |
| |
|
| | default: |
| | p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p) |
| | return nil |
| | } |
| |
|
| | case p.From.Type == obj.TYPE_ADDR && p.To.Type != obj.TYPE_REG: |
| | p.Ctxt.Diag("%v: address load must target register", p) |
| | return nil |
| |
|
| | default: |
| | p.Ctxt.Diag("%v: unsupported MOV", p) |
| | return nil |
| | } |
| |
|
| | return inss |
| | } |
| |
|
| | |
| | func instructionsForRotate(p *obj.Prog, ins *instruction) []*instruction { |
| | if buildcfg.GORISCV64 >= 22 { |
| | |
| | return []*instruction{ins} |
| | } |
| |
|
| | switch ins.as { |
| | case AROL, AROLW, AROR, ARORW: |
| | |
| | |
| | sllOp, srlOp := ASLL, ASRL |
| | if ins.as == AROLW || ins.as == ARORW { |
| | sllOp, srlOp = ASLLW, ASRLW |
| | } |
| | shift1, shift2 := sllOp, srlOp |
| | if ins.as == AROR || ins.as == ARORW { |
| | shift1, shift2 = shift2, shift1 |
| | } |
| | return []*instruction{ |
| | &instruction{as: ASUB, rs1: REG_ZERO, rs2: ins.rs2, rd: REG_TMP}, |
| | &instruction{as: shift2, rs1: ins.rs1, rs2: REG_TMP, rd: REG_TMP}, |
| | &instruction{as: shift1, rs1: ins.rs1, rs2: ins.rs2, rd: ins.rd}, |
| | &instruction{as: AOR, rs1: REG_TMP, rs2: ins.rd, rd: ins.rd}, |
| | } |
| |
|
| | case ARORI, ARORIW: |
| | |
| | sllOp, srlOp := ASLLI, ASRLI |
| | sllImm := int64(int8(-ins.imm) & 63) |
| | if ins.as == ARORIW { |
| | sllOp, srlOp = ASLLIW, ASRLIW |
| | sllImm = int64(int8(-ins.imm) & 31) |
| | } |
| | return []*instruction{ |
| | &instruction{as: srlOp, rs1: ins.rs1, rd: REG_TMP, imm: ins.imm}, |
| | &instruction{as: sllOp, rs1: ins.rs1, rd: ins.rd, imm: sllImm}, |
| | &instruction{as: AOR, rs1: REG_TMP, rs2: ins.rd, rd: ins.rd}, |
| | } |
| |
|
| | default: |
| | p.Ctxt.Diag("%v: unknown rotation", p) |
| | return nil |
| | } |
| | } |
| |
|
| | |
| | func instructionsForMinMax(p *obj.Prog, ins *instruction) []*instruction { |
| | if buildcfg.GORISCV64 >= 22 { |
| | |
| | return []*instruction{ins} |
| | } |
| |
|
| | |
| | if ins.rs1 == ins.rs2 { |
| | ins.as, ins.rs2, ins.imm = AADDI, obj.REG_NONE, 0 |
| | return []*instruction{ins} |
| | } |
| |
|
| | |
| | |
| | if ins.rs1 == ins.rd { |
| | ins.rs1, ins.rs2 = ins.rs2, ins.rs1 |
| | } |
| | sltReg1, sltReg2 := ins.rs2, ins.rs1 |
| |
|
| | |
| | |
| | switch ins.as { |
| | case AMIN: |
| | ins.as = ASLT |
| | case AMAX: |
| | ins.as, sltReg1, sltReg2 = ASLT, sltReg2, sltReg1 |
| | case AMINU: |
| | ins.as = ASLTU |
| | case AMAXU: |
| | ins.as, sltReg1, sltReg2 = ASLTU, sltReg2, sltReg1 |
| | } |
| | return []*instruction{ |
| | &instruction{as: ins.as, rs1: sltReg1, rs2: sltReg2, rd: REG_TMP}, |
| | &instruction{as: ASUB, rs1: REG_ZERO, rs2: REG_TMP, rd: REG_TMP}, |
| | &instruction{as: AXOR, rs1: ins.rs1, rs2: ins.rs2, rd: ins.rd}, |
| | &instruction{as: AAND, rs1: REG_TMP, rs2: ins.rd, rd: ins.rd}, |
| | &instruction{as: AXOR, rs1: ins.rs1, rs2: ins.rd, rd: ins.rd}, |
| | } |
| | } |
| |
|
| | |
| | func instructionsForProg(p *obj.Prog, compress bool) []*instruction { |
| | ins := instructionForProg(p) |
| | inss := []*instruction{ins} |
| |
|
| | if ins.as == AVSETVLI || ins.as == AVSETIVLI { |
| | if len(p.RestArgs) != 4 { |
| | p.Ctxt.Diag("incorrect number of arguments for instruction") |
| | return nil |
| | } |
| | } else if len(p.RestArgs) > 1 { |
| | p.Ctxt.Diag("too many source registers") |
| | return nil |
| | } |
| |
|
| | switch ins.as { |
| | case ACJALR, AJAL, AJALR: |
| | ins.rd, ins.rs1, ins.rs2 = uint32(p.From.Reg), uint32(p.To.Reg), obj.REG_NONE |
| | ins.imm = p.To.Offset |
| |
|
| | case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ: |
| | switch ins.as { |
| | case ABEQZ: |
| | ins.as, ins.rs1, ins.rs2 = ABEQ, REG_ZERO, uint32(p.From.Reg) |
| | case ABGEZ: |
| | ins.as, ins.rs1, ins.rs2 = ABGE, REG_ZERO, uint32(p.From.Reg) |
| | case ABGT: |
| | ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), uint32(p.Reg) |
| | case ABGTU: |
| | ins.as, ins.rs1, ins.rs2 = ABLTU, uint32(p.From.Reg), uint32(p.Reg) |
| | case ABGTZ: |
| | ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), REG_ZERO |
| | case ABLE: |
| | ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), uint32(p.Reg) |
| | case ABLEU: |
| | ins.as, ins.rs1, ins.rs2 = ABGEU, uint32(p.From.Reg), uint32(p.Reg) |
| | case ABLEZ: |
| | ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), REG_ZERO |
| | case ABLTZ: |
| | ins.as, ins.rs1, ins.rs2 = ABLT, REG_ZERO, uint32(p.From.Reg) |
| | case ABNEZ: |
| | ins.as, ins.rs1, ins.rs2 = ABNE, REG_ZERO, uint32(p.From.Reg) |
| | } |
| | ins.imm = p.To.Offset |
| |
|
| | case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD: |
| | inss = instructionsForMOV(p) |
| |
|
| | case ALW, ALWU, ALH, ALHU, ALB, ALBU, ALD, AFLW, AFLD: |
| | inss = instructionsForLoad(p, ins.as, p.From.Reg) |
| |
|
| | case ASW, ASH, ASB, ASD, AFSW, AFSD: |
| | inss = instructionsForStore(p, ins.as, p.To.Reg) |
| |
|
| | case ALRW, ALRD: |
| | |
| | ins.funct7 = 2 |
| | ins.rs1, ins.rs2 = uint32(p.From.Reg), REG_ZERO |
| |
|
| | case AADDI, AANDI, AORI, AXORI: |
| | inss = instructionsForOpImmediate(p, ins.as, p.Reg) |
| |
|
| | case ASCW, ASCD: |
| | |
| | ins.funct7 = 1 |
| | ins.rd, ins.rs1, ins.rs2 = uint32(p.RegTo2), uint32(p.To.Reg), uint32(p.From.Reg) |
| |
|
| | case AAMOSWAPW, AAMOSWAPD, AAMOADDW, AAMOADDD, AAMOANDW, AAMOANDD, AAMOORW, AAMOORD, |
| | AAMOXORW, AAMOXORD, AAMOMINW, AAMOMIND, AAMOMINUW, AAMOMINUD, AAMOMAXW, AAMOMAXD, AAMOMAXUW, AAMOMAXUD: |
| | |
| | ins.funct7 = 3 |
| | ins.rd, ins.rs1, ins.rs2 = uint32(p.RegTo2), uint32(p.To.Reg), uint32(p.From.Reg) |
| |
|
| | case AECALL, AEBREAK: |
| | insEnc := encode(p.As) |
| | if p.To.Type == obj.TYPE_NONE { |
| | ins.rd = REG_ZERO |
| | } |
| | ins.rs1 = REG_ZERO |
| | ins.imm = insEnc.csr |
| |
|
| | case ARDCYCLE, ARDTIME, ARDINSTRET: |
| | ins.as = ACSRRS |
| | if p.To.Type == obj.TYPE_NONE { |
| | ins.rd = REG_ZERO |
| | } |
| | ins.rs1 = REG_ZERO |
| | switch p.As { |
| | case ARDCYCLE: |
| | ins.imm = -1024 |
| | case ARDTIME: |
| | ins.imm = -1023 |
| | case ARDINSTRET: |
| | ins.imm = -1022 |
| | } |
| |
|
| | case ACSRRC, ACSRRCI, ACSRRS, ACSRRSI, ACSRRW, ACSRRWI: |
| | if len(p.RestArgs) == 0 || p.RestArgs[0].Type != obj.TYPE_SPECIAL { |
| | p.Ctxt.Diag("%v: missing CSR name", p) |
| | return nil |
| | } |
| | if p.From.Type == obj.TYPE_CONST { |
| | imm := p.From.Offset |
| | if imm < 0 || imm >= 32 { |
| | p.Ctxt.Diag("%v: immediate out of range 0 to 31", p) |
| | return nil |
| | } |
| | ins.rs1 = uint32(imm) + REG_ZERO |
| | } else if p.From.Type == obj.TYPE_REG { |
| | ins.rs1 = uint32(p.From.Reg) |
| | } else { |
| | p.Ctxt.Diag("%v: integer register or immediate expected for 1st operand", p) |
| | return nil |
| | } |
| | if p.To.Type != obj.TYPE_REG { |
| | p.Ctxt.Diag("%v: needs an integer register output", p) |
| | return nil |
| | } |
| | csrNum := SpecialOperand(p.RestArgs[0].Offset).encode() |
| | if csrNum >= 1<<12 { |
| | p.Ctxt.Diag("%v: unknown CSR", p) |
| | return nil |
| | } |
| | if _, ok := CSRs[uint16(csrNum)]; !ok { |
| | p.Ctxt.Diag("%v: unknown CSR", p) |
| | return nil |
| | } |
| | ins.imm = int64(csrNum) |
| | if ins.imm > 2047 { |
| | ins.imm -= 4096 |
| | } |
| | ins.rs2 = obj.REG_NONE |
| |
|
| | case AFENCE: |
| | ins.rd, ins.rs1, ins.rs2 = REG_ZERO, REG_ZERO, obj.REG_NONE |
| | ins.imm = 0x0ff |
| |
|
| | case AFCVTWS, AFCVTLS, AFCVTWUS, AFCVTLUS, AFCVTWD, AFCVTLD, AFCVTWUD, AFCVTLUD: |
| | |
| | if p.Scond&rmSuffixBit == 0 { |
| | ins.funct3 = uint32(RM_RTZ) |
| | } else { |
| | ins.funct3 = uint32(p.Scond &^ rmSuffixBit) |
| | } |
| |
|
| | case AFNES, AFNED: |
| | |
| | if p.To.Type != obj.TYPE_REG { |
| | p.Ctxt.Diag("%v needs an integer register output", p) |
| | return nil |
| | } |
| | if ins.as == AFNES { |
| | ins.as = AFEQS |
| | } else { |
| | ins.as = AFEQD |
| | } |
| | ins2 := &instruction{ |
| | as: AXORI, |
| | rd: ins.rd, |
| | rs1: ins.rd, |
| | imm: 1, |
| | } |
| | inss = append(inss, ins2) |
| |
|
| | case AFSQRTS, AFSQRTD: |
| | |
| | |
| | ins.rs1 = uint32(p.From.Reg) |
| | ins.rs2 = REG_F0 |
| |
|
| | case AFMADDS, AFMSUBS, AFNMADDS, AFNMSUBS, |
| | AFMADDD, AFMSUBD, AFNMADDD, AFNMSUBD: |
| | |
| | |
| | ins.rs1, ins.rs2 = ins.rs2, ins.rs1 |
| |
|
| | case ANEG, ANEGW: |
| | |
| | ins.as = ASUB |
| | if p.As == ANEGW { |
| | ins.as = ASUBW |
| | } |
| | ins.rs1 = REG_ZERO |
| | if ins.rd == obj.REG_NONE { |
| | ins.rd = ins.rs2 |
| | } |
| |
|
| | case ANOT: |
| | |
| | ins.as = AXORI |
| | ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE |
| | if ins.rd == obj.REG_NONE { |
| | ins.rd = ins.rs1 |
| | } |
| | ins.imm = -1 |
| |
|
| | case ASEQZ: |
| | |
| | ins.as = ASLTIU |
| | ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE |
| | ins.imm = 1 |
| |
|
| | case ASNEZ: |
| | |
| | ins.as = ASLTU |
| | ins.rs1 = REG_ZERO |
| |
|
| | case AFABSS: |
| | |
| | ins.as = AFSGNJXS |
| | ins.rs1 = uint32(p.From.Reg) |
| |
|
| | case AFABSD: |
| | |
| | ins.as = AFSGNJXD |
| | ins.rs1 = uint32(p.From.Reg) |
| |
|
| | case AFNEGS: |
| | |
| | ins.as = AFSGNJNS |
| | ins.rs1 = uint32(p.From.Reg) |
| |
|
| | case AFNEGD: |
| | |
| | ins.as = AFSGNJND |
| | ins.rs1 = uint32(p.From.Reg) |
| |
|
| | case ACLW, ACLD, ACFLD: |
| | ins.rs1, ins.rs2 = ins.rs2, obj.REG_NONE |
| |
|
| | case ACSW, ACSD, ACFSD: |
| | ins.rs1, ins.rd = ins.rd, obj.REG_NONE |
| | ins.imm = p.To.Offset |
| |
|
| | case ACSWSP, ACSDSP, ACFSDSP: |
| | ins.imm = p.To.Offset |
| |
|
| | case ACANDI, ACSRLI, ACSRAI: |
| | ins.rs1, ins.rd = ins.rd, ins.rs1 |
| |
|
| | case ACBEQZ, ACBNEZ: |
| | ins.rd, ins.rs1, ins.rs2 = obj.REG_NONE, uint32(p.From.Reg), obj.REG_NONE |
| | ins.imm = p.To.Offset |
| |
|
| | case ACJR: |
| | ins.rd, ins.rs1 = obj.REG_NONE, uint32(p.To.Reg) |
| |
|
| | case ACJ: |
| | ins.imm = p.To.Offset |
| |
|
| | case ACNOP: |
| | ins.rd, ins.rs1 = REG_ZERO, REG_ZERO |
| |
|
| | case AROL, AROLW, AROR, ARORW: |
| | inss = instructionsForRotate(p, ins) |
| |
|
| | case ARORI: |
| | if ins.imm < 0 || ins.imm > 63 { |
| | p.Ctxt.Diag("%v: immediate out of range 0 to 63", p) |
| | } |
| | inss = instructionsForRotate(p, ins) |
| |
|
| | case ARORIW: |
| | if ins.imm < 0 || ins.imm > 31 { |
| | p.Ctxt.Diag("%v: immediate out of range 0 to 31", p) |
| | } |
| | inss = instructionsForRotate(p, ins) |
| |
|
| | case ASLLI, ASRLI, ASRAI: |
| | if ins.imm < 0 || ins.imm > 63 { |
| | p.Ctxt.Diag("%v: immediate out of range 0 to 63", p) |
| | } |
| |
|
| | case ASLLIW, ASRLIW, ASRAIW: |
| | if ins.imm < 0 || ins.imm > 31 { |
| | p.Ctxt.Diag("%v: immediate out of range 0 to 31", p) |
| | } |
| |
|
| | case ACLZ, ACLZW, ACTZ, ACTZW, ACPOP, ACPOPW, ASEXTB, ASEXTH, AZEXTH: |
| | ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE |
| |
|
| | case AORCB, AREV8: |
| | ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE |
| |
|
| | case AANDN, AORN: |
| | if buildcfg.GORISCV64 >= 22 { |
| | |
| | break |
| | } |
| | |
| | |
| | bitwiseOp, notReg := AAND, ins.rd |
| | if ins.as == AORN { |
| | bitwiseOp = AOR |
| | } |
| | if ins.rs1 == notReg { |
| | notReg = REG_TMP |
| | } |
| | inss = []*instruction{ |
| | &instruction{as: AXORI, rs1: ins.rs2, rs2: obj.REG_NONE, rd: notReg, imm: -1}, |
| | &instruction{as: bitwiseOp, rs1: ins.rs1, rs2: notReg, rd: ins.rd}, |
| | } |
| |
|
| | case AXNOR: |
| | if buildcfg.GORISCV64 >= 22 { |
| | |
| | break |
| | } |
| | |
| | ins.as = AXOR |
| | inss = append(inss, &instruction{as: AXORI, rs1: ins.rd, rs2: obj.REG_NONE, rd: ins.rd, imm: -1}) |
| |
|
| | case AMIN, AMAX, AMINU, AMAXU: |
| | inss = instructionsForMinMax(p, ins) |
| |
|
| | case AVSETVLI, AVSETIVLI: |
| | ins.rs1, ins.rs2 = ins.rs2, obj.REG_NONE |
| | vtype, err := EncodeVectorType(p.RestArgs[0].Offset, p.RestArgs[1].Offset, p.RestArgs[2].Offset, p.RestArgs[3].Offset) |
| | if err != nil { |
| | p.Ctxt.Diag("%v: %v", p, err) |
| | } |
| | ins.imm = vtype |
| | if ins.as == AVSETIVLI { |
| | if p.From.Type != obj.TYPE_CONST { |
| | p.Ctxt.Diag("%v: expected immediate value", p) |
| | } |
| | ins.rs1 = uint32(p.From.Offset) |
| | } |
| |
|
| | case AVLE8V, AVLE16V, AVLE32V, AVLE64V, AVSE8V, AVSE16V, AVSE32V, AVSE64V, AVLE8FFV, AVLE16FFV, AVLE32FFV, AVLE64FFV, AVLMV, AVSMV, |
| | AVLSEG2E8V, AVLSEG3E8V, AVLSEG4E8V, AVLSEG5E8V, AVLSEG6E8V, AVLSEG7E8V, AVLSEG8E8V, |
| | AVLSEG2E16V, AVLSEG3E16V, AVLSEG4E16V, AVLSEG5E16V, AVLSEG6E16V, AVLSEG7E16V, AVLSEG8E16V, |
| | AVLSEG2E32V, AVLSEG3E32V, AVLSEG4E32V, AVLSEG5E32V, AVLSEG6E32V, AVLSEG7E32V, AVLSEG8E32V, |
| | AVLSEG2E64V, AVLSEG3E64V, AVLSEG4E64V, AVLSEG5E64V, AVLSEG6E64V, AVLSEG7E64V, AVLSEG8E64V, |
| | AVSSEG2E8V, AVSSEG3E8V, AVSSEG4E8V, AVSSEG5E8V, AVSSEG6E8V, AVSSEG7E8V, AVSSEG8E8V, |
| | AVSSEG2E16V, AVSSEG3E16V, AVSSEG4E16V, AVSSEG5E16V, AVSSEG6E16V, AVSSEG7E16V, AVSSEG8E16V, |
| | AVSSEG2E32V, AVSSEG3E32V, AVSSEG4E32V, AVSSEG5E32V, AVSSEG6E32V, AVSSEG7E32V, AVSSEG8E32V, |
| | AVSSEG2E64V, AVSSEG3E64V, AVSSEG4E64V, AVSSEG5E64V, AVSSEG6E64V, AVSSEG7E64V, AVSSEG8E64V, |
| | AVLSEG2E8FFV, AVLSEG3E8FFV, AVLSEG4E8FFV, AVLSEG5E8FFV, AVLSEG6E8FFV, AVLSEG7E8FFV, AVLSEG8E8FFV, |
| | AVLSEG2E16FFV, AVLSEG3E16FFV, AVLSEG4E16FFV, AVLSEG5E16FFV, AVLSEG6E16FFV, AVLSEG7E16FFV, AVLSEG8E16FFV, |
| | AVLSEG2E32FFV, AVLSEG3E32FFV, AVLSEG4E32FFV, AVLSEG5E32FFV, AVLSEG6E32FFV, AVLSEG7E32FFV, AVLSEG8E32FFV, |
| | AVLSEG2E64FFV, AVLSEG3E64FFV, AVLSEG4E64FFV, AVLSEG5E64FFV, AVLSEG6E64FFV, AVLSEG7E64FFV, AVLSEG8E64FFV: |
| | |
| | switch { |
| | case ins.rs1 == obj.REG_NONE: |
| | ins.funct7 |= 1 |
| | case ins.rs1 != REG_V0: |
| | p.Ctxt.Diag("%v: invalid vector mask register", p) |
| | } |
| | ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE |
| |
|
| | case AVLSE8V, AVLSE16V, AVLSE32V, AVLSE64V, |
| | AVLUXEI8V, AVLUXEI16V, AVLUXEI32V, AVLUXEI64V, AVLOXEI8V, AVLOXEI16V, AVLOXEI32V, AVLOXEI64V, |
| | AVLSSEG2E8V, AVLSSEG3E8V, AVLSSEG4E8V, AVLSSEG5E8V, AVLSSEG6E8V, AVLSSEG7E8V, AVLSSEG8E8V, |
| | AVLSSEG2E16V, AVLSSEG3E16V, AVLSSEG4E16V, AVLSSEG5E16V, AVLSSEG6E16V, AVLSSEG7E16V, AVLSSEG8E16V, |
| | AVLSSEG2E32V, AVLSSEG3E32V, AVLSSEG4E32V, AVLSSEG5E32V, AVLSSEG6E32V, AVLSSEG7E32V, AVLSSEG8E32V, |
| | AVLSSEG2E64V, AVLSSEG3E64V, AVLSSEG4E64V, AVLSSEG5E64V, AVLSSEG6E64V, AVLSSEG7E64V, AVLSSEG8E64V, |
| | AVLOXSEG2EI8V, AVLOXSEG3EI8V, AVLOXSEG4EI8V, AVLOXSEG5EI8V, AVLOXSEG6EI8V, AVLOXSEG7EI8V, AVLOXSEG8EI8V, |
| | AVLOXSEG2EI16V, AVLOXSEG3EI16V, AVLOXSEG4EI16V, AVLOXSEG5EI16V, AVLOXSEG6EI16V, AVLOXSEG7EI16V, AVLOXSEG8EI16V, |
| | AVLOXSEG2EI32V, AVLOXSEG3EI32V, AVLOXSEG4EI32V, AVLOXSEG5EI32V, AVLOXSEG6EI32V, AVLOXSEG7EI32V, AVLOXSEG8EI32V, |
| | AVLOXSEG2EI64V, AVLOXSEG3EI64V, AVLOXSEG4EI64V, AVLOXSEG5EI64V, AVLOXSEG6EI64V, AVLOXSEG7EI64V, AVLOXSEG8EI64V, |
| | AVLUXSEG2EI8V, AVLUXSEG3EI8V, AVLUXSEG4EI8V, AVLUXSEG5EI8V, AVLUXSEG6EI8V, AVLUXSEG7EI8V, AVLUXSEG8EI8V, |
| | AVLUXSEG2EI16V, AVLUXSEG3EI16V, AVLUXSEG4EI16V, AVLUXSEG5EI16V, AVLUXSEG6EI16V, AVLUXSEG7EI16V, AVLUXSEG8EI16V, |
| | AVLUXSEG2EI32V, AVLUXSEG3EI32V, AVLUXSEG4EI32V, AVLUXSEG5EI32V, AVLUXSEG6EI32V, AVLUXSEG7EI32V, AVLUXSEG8EI32V, |
| | AVLUXSEG2EI64V, AVLUXSEG3EI64V, AVLUXSEG4EI64V, AVLUXSEG5EI64V, AVLUXSEG6EI64V, AVLUXSEG7EI64V, AVLUXSEG8EI64V: |
| | |
| | switch { |
| | case ins.rs3 == obj.REG_NONE: |
| | ins.funct7 |= 1 |
| | case ins.rs3 != REG_V0: |
| | p.Ctxt.Diag("%v: invalid vector mask register", p) |
| | } |
| | ins.rs1, ins.rs2, ins.rs3 = ins.rs2, ins.rs1, obj.REG_NONE |
| |
|
| | case AVSSE8V, AVSSE16V, AVSSE32V, AVSSE64V, |
| | AVSUXEI8V, AVSUXEI16V, AVSUXEI32V, AVSUXEI64V, AVSOXEI8V, AVSOXEI16V, AVSOXEI32V, AVSOXEI64V, |
| | AVSSSEG2E8V, AVSSSEG3E8V, AVSSSEG4E8V, AVSSSEG5E8V, AVSSSEG6E8V, AVSSSEG7E8V, AVSSSEG8E8V, |
| | AVSSSEG2E16V, AVSSSEG3E16V, AVSSSEG4E16V, AVSSSEG5E16V, AVSSSEG6E16V, AVSSSEG7E16V, AVSSSEG8E16V, |
| | AVSSSEG2E32V, AVSSSEG3E32V, AVSSSEG4E32V, AVSSSEG5E32V, AVSSSEG6E32V, AVSSSEG7E32V, AVSSSEG8E32V, |
| | AVSSSEG2E64V, AVSSSEG3E64V, AVSSSEG4E64V, AVSSSEG5E64V, AVSSSEG6E64V, AVSSSEG7E64V, AVSSSEG8E64V, |
| | AVSOXSEG2EI8V, AVSOXSEG3EI8V, AVSOXSEG4EI8V, AVSOXSEG5EI8V, AVSOXSEG6EI8V, AVSOXSEG7EI8V, AVSOXSEG8EI8V, |
| | AVSOXSEG2EI16V, AVSOXSEG3EI16V, AVSOXSEG4EI16V, AVSOXSEG5EI16V, AVSOXSEG6EI16V, AVSOXSEG7EI16V, AVSOXSEG8EI16V, |
| | AVSOXSEG2EI32V, AVSOXSEG3EI32V, AVSOXSEG4EI32V, AVSOXSEG5EI32V, AVSOXSEG6EI32V, AVSOXSEG7EI32V, AVSOXSEG8EI32V, |
| | AVSOXSEG2EI64V, AVSOXSEG3EI64V, AVSOXSEG4EI64V, AVSOXSEG5EI64V, AVSOXSEG6EI64V, AVSOXSEG7EI64V, AVSOXSEG8EI64V, |
| | AVSUXSEG2EI8V, AVSUXSEG3EI8V, AVSUXSEG4EI8V, AVSUXSEG5EI8V, AVSUXSEG6EI8V, AVSUXSEG7EI8V, AVSUXSEG8EI8V, |
| | AVSUXSEG2EI16V, AVSUXSEG3EI16V, AVSUXSEG4EI16V, AVSUXSEG5EI16V, AVSUXSEG6EI16V, AVSUXSEG7EI16V, AVSUXSEG8EI16V, |
| | AVSUXSEG2EI32V, AVSUXSEG3EI32V, AVSUXSEG4EI32V, AVSUXSEG5EI32V, AVSUXSEG6EI32V, AVSUXSEG7EI32V, AVSUXSEG8EI32V, |
| | AVSUXSEG2EI64V, AVSUXSEG3EI64V, AVSUXSEG4EI64V, AVSUXSEG5EI64V, AVSUXSEG6EI64V, AVSUXSEG7EI64V, AVSUXSEG8EI64V: |
| | |
| | switch { |
| | case ins.rs3 == obj.REG_NONE: |
| | ins.funct7 |= 1 |
| | case ins.rs3 != REG_V0: |
| | p.Ctxt.Diag("%v: invalid vector mask register", p) |
| | } |
| | ins.rd, ins.rs1, ins.rs2, ins.rs3 = ins.rs2, ins.rd, ins.rs1, obj.REG_NONE |
| |
|
| | case AVL1RV, AVL1RE8V, AVL1RE16V, AVL1RE32V, AVL1RE64V, AVL2RV, AVL2RE8V, AVL2RE16V, AVL2RE32V, AVL2RE64V, |
| | AVL4RV, AVL4RE8V, AVL4RE16V, AVL4RE32V, AVL4RE64V, AVL8RV, AVL8RE8V, AVL8RE16V, AVL8RE32V, AVL8RE64V: |
| | switch ins.as { |
| | case AVL1RV: |
| | ins.as = AVL1RE8V |
| | case AVL2RV: |
| | ins.as = AVL2RE8V |
| | case AVL4RV: |
| | ins.as = AVL4RE8V |
| | case AVL8RV: |
| | ins.as = AVL8RE8V |
| | } |
| | if ins.rs1 != obj.REG_NONE { |
| | p.Ctxt.Diag("%v: too many operands for instruction", p) |
| | } |
| | ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE |
| |
|
| | case AVS1RV, AVS2RV, AVS4RV, AVS8RV: |
| | if ins.rs1 != obj.REG_NONE { |
| | p.Ctxt.Diag("%v: too many operands for instruction", p) |
| | } |
| | ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE |
| |
|
| | case AVADDVV, AVADDVX, AVSUBVV, AVSUBVX, AVRSUBVX, AVWADDUVV, AVWADDUVX, AVWSUBUVV, AVWSUBUVX, |
| | AVWADDVV, AVWADDVX, AVWSUBVV, AVWSUBVX, AVWADDUWV, AVWADDUWX, AVWSUBUWV, AVWSUBUWX, |
| | AVWADDWV, AVWADDWX, AVWSUBWV, AVWSUBWX, AVANDVV, AVANDVX, AVORVV, AVORVX, AVXORVV, AVXORVX, |
| | AVSLLVV, AVSLLVX, AVSRLVV, AVSRLVX, AVSRAVV, AVSRAVX, |
| | AVMSEQVV, AVMSEQVX, AVMSNEVV, AVMSNEVX, AVMSLTUVV, AVMSLTUVX, AVMSLTVV, AVMSLTVX, |
| | AVMSLEUVV, AVMSLEUVX, AVMSLEVV, AVMSLEVX, AVMSGTUVX, AVMSGTVX, |
| | AVMINUVV, AVMINUVX, AVMINVV, AVMINVX, AVMAXUVV, AVMAXUVX, AVMAXVV, AVMAXVX, |
| | AVMULVV, AVMULVX, AVMULHVV, AVMULHVX, AVMULHUVV, AVMULHUVX, AVMULHSUVV, AVMULHSUVX, |
| | AVDIVUVV, AVDIVUVX, AVDIVVV, AVDIVVX, AVREMUVV, AVREMUVX, AVREMVV, AVREMVX, |
| | AVWMULVV, AVWMULVX, AVWMULUVV, AVWMULUVX, AVWMULSUVV, AVWMULSUVX, AVNSRLWV, AVNSRLWX, AVNSRAWV, AVNSRAWX, |
| | AVSADDUVV, AVSADDUVX, AVSADDUVI, AVSADDVV, AVSADDVX, AVSADDVI, AVSSUBUVV, AVSSUBUVX, AVSSUBVV, AVSSUBVX, |
| | AVAADDUVV, AVAADDUVX, AVAADDVV, AVAADDVX, AVASUBUVV, AVASUBUVX, AVASUBVV, AVASUBVX, |
| | AVSMULVV, AVSMULVX, AVSSRLVV, AVSSRLVX, AVSSRLVI, AVSSRAVV, AVSSRAVX, AVSSRAVI, |
| | AVNCLIPUWV, AVNCLIPUWX, AVNCLIPUWI, AVNCLIPWV, AVNCLIPWX, AVNCLIPWI, |
| | AVFADDVV, AVFADDVF, AVFSUBVV, AVFSUBVF, AVFRSUBVF, |
| | AVFWADDVV, AVFWADDVF, AVFWSUBVV, AVFWSUBVF, AVFWADDWV, AVFWADDWF, AVFWSUBWV, AVFWSUBWF, |
| | AVFMULVV, AVFMULVF, AVFDIVVV, AVFDIVVF, AVFRDIVVF, AVFWMULVV, AVFWMULVF, |
| | AVFMINVV, AVFMINVF, AVFMAXVV, AVFMAXVF, |
| | AVFSGNJVV, AVFSGNJVF, AVFSGNJNVV, AVFSGNJNVF, AVFSGNJXVV, AVFSGNJXVF, |
| | AVMFEQVV, AVMFEQVF, AVMFNEVV, AVMFNEVF, AVMFLTVV, AVMFLTVF, AVMFLEVV, AVMFLEVF, AVMFGTVF, AVMFGEVF, |
| | AVREDSUMVS, AVREDMAXUVS, AVREDMAXVS, AVREDMINUVS, AVREDMINVS, AVREDANDVS, AVREDORVS, AVREDXORVS, |
| | AVWREDSUMUVS, AVWREDSUMVS, AVFREDOSUMVS, AVFREDUSUMVS, AVFREDMAXVS, AVFREDMINVS, AVFWREDOSUMVS, AVFWREDUSUMVS, |
| | AVSLIDEUPVX, AVSLIDEDOWNVX, AVSLIDE1UPVX, AVFSLIDE1UPVF, AVSLIDE1DOWNVX, AVFSLIDE1DOWNVF, |
| | AVRGATHERVV, AVRGATHEREI16VV, AVRGATHERVX: |
| | |
| | switch { |
| | case ins.rs3 == obj.REG_NONE: |
| | ins.funct7 |= 1 |
| | case ins.rs3 != REG_V0: |
| | p.Ctxt.Diag("%v: invalid vector mask register", p) |
| | } |
| | ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg), obj.REG_NONE |
| |
|
| | case AVFMACCVV, AVFMACCVF, AVFNMACCVV, AVFNMACCVF, AVFMSACVV, AVFMSACVF, AVFNMSACVV, AVFNMSACVF, |
| | AVFMADDVV, AVFMADDVF, AVFNMADDVV, AVFNMADDVF, AVFMSUBVV, AVFMSUBVF, AVFNMSUBVV, AVFNMSUBVF, |
| | AVFWMACCVV, AVFWMACCVF, AVFWNMACCVV, AVFWNMACCVF, AVFWMSACVV, AVFWMSACVF, AVFWNMSACVV, AVFWNMSACVF, |
| | AVMACCVV, AVMACCVX, AVNMSACVV, AVNMSACVX, AVMADDVV, AVMADDVX, AVNMSUBVV, AVNMSUBVX, |
| | AVWMACCUVV, AVWMACCUVX, AVWMACCVV, AVWMACCVX, AVWMACCSUVV, AVWMACCSUVX, AVWMACCUSVX: |
| | switch { |
| | case ins.rs3 == obj.REG_NONE: |
| | ins.funct7 |= 1 |
| | case ins.rs3 != REG_V0: |
| | p.Ctxt.Diag("%v: invalid vector mask register", p) |
| | } |
| | ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), uint32(p.Reg), uint32(p.From.Reg), obj.REG_NONE |
| |
|
| | case AVADDVI, AVRSUBVI, AVANDVI, AVORVI, AVXORVI, AVMSEQVI, AVMSNEVI, AVMSLEUVI, AVMSLEVI, AVMSGTUVI, AVMSGTVI, |
| | AVSLLVI, AVSRLVI, AVSRAVI, AVNSRLWI, AVNSRAWI, AVRGATHERVI, AVSLIDEUPVI, AVSLIDEDOWNVI: |
| | |
| | switch { |
| | case ins.rs3 == obj.REG_NONE: |
| | ins.funct7 |= 1 |
| | case ins.rs3 != REG_V0: |
| | p.Ctxt.Diag("%v: invalid vector mask register", p) |
| | } |
| | ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), obj.REG_NONE, uint32(p.Reg), obj.REG_NONE |
| |
|
| | case AVZEXTVF2, AVSEXTVF2, AVZEXTVF4, AVSEXTVF4, AVZEXTVF8, AVSEXTVF8, AVFSQRTV, AVFRSQRT7V, AVFREC7V, AVFCLASSV, |
| | AVFCVTXUFV, AVFCVTXFV, AVFCVTRTZXUFV, AVFCVTRTZXFV, AVFCVTFXUV, AVFCVTFXV, |
| | AVFWCVTXUFV, AVFWCVTXFV, AVFWCVTRTZXUFV, AVFWCVTRTZXFV, AVFWCVTFXUV, AVFWCVTFXV, AVFWCVTFFV, |
| | AVFNCVTXUFW, AVFNCVTXFW, AVFNCVTRTZXUFW, AVFNCVTRTZXFW, AVFNCVTFXUW, AVFNCVTFXW, AVFNCVTFFW, AVFNCVTRODFFW: |
| | |
| | switch { |
| | case ins.rs1 == obj.REG_NONE: |
| | ins.funct7 |= 1 |
| | case ins.rs1 != REG_V0: |
| | p.Ctxt.Diag("%v: invalid vector mask register", p) |
| | } |
| | ins.rs1 = obj.REG_NONE |
| |
|
| | case AVMVVV, AVMVVX: |
| | if ins.rs1 != obj.REG_NONE { |
| | p.Ctxt.Diag("%v: too many operands for instruction", p) |
| | } |
| | ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), REG_V0 |
| |
|
| | case AVMVVI: |
| | if ins.rs1 != obj.REG_NONE { |
| | p.Ctxt.Diag("%v: too many operands for instruction", p) |
| | } |
| | ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), obj.REG_NONE, REG_V0 |
| |
|
| | case AVFMVVF: |
| | ins.funct7 |= 1 |
| | ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), REG_V0 |
| |
|
| | case AVADCVIM, AVADCVVM, AVADCVXM, AVSBCVVM, AVSBCVXM: |
| | if ins.rd == REG_V0 { |
| | p.Ctxt.Diag("%v: invalid destination register V0", p) |
| | } |
| | fallthrough |
| |
|
| | case AVMADCVVM, AVMADCVXM, AVMSBCVVM, AVMSBCVXM, AVMADCVIM, AVMERGEVVM, AVMERGEVXM, AVMERGEVIM, AVFMERGEVFM: |
| | if ins.rs3 != REG_V0 { |
| | p.Ctxt.Diag("%v: invalid vector mask register", p) |
| | } |
| | ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg), obj.REG_NONE |
| |
|
| | case AVMADCVV, AVMADCVX, AVMSBCVV, AVMSBCVX, AVMADCVI: |
| | ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg) |
| |
|
| | case AVNEGV, AVWCVTXXV, AVWCVTUXXV, AVNCVTXXW: |
| | |
| | switch { |
| | case ins.rs1 == obj.REG_NONE: |
| | ins.funct7 |= 1 |
| | case ins.rs1 != REG_V0: |
| | p.Ctxt.Diag("%v: invalid vector mask register", p) |
| | } |
| | switch ins.as { |
| | case AVNEGV: |
| | ins.as = AVRSUBVX |
| | case AVWCVTXXV: |
| | ins.as = AVWADDVX |
| | case AVWCVTUXXV: |
| | ins.as = AVWADDUVX |
| | case AVNCVTXXW: |
| | ins.as = AVNSRLWX |
| | } |
| | ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), REG_X0, uint32(p.From.Reg) |
| |
|
| | case AVNOTV: |
| | |
| | switch { |
| | case ins.rs1 == obj.REG_NONE: |
| | ins.funct7 |= 1 |
| | case ins.rs1 != REG_V0: |
| | p.Ctxt.Diag("%v: invalid vector mask register", p) |
| | } |
| | ins.as = AVXORVI |
| | ins.rd, ins.rs1, ins.rs2, ins.imm = uint32(p.To.Reg), obj.REG_NONE, uint32(p.From.Reg), -1 |
| |
|
| | case AVMSGTVV, AVMSGTUVV, AVMSGEVV, AVMSGEUVV, AVMFGTVV, AVMFGEVV: |
| | |
| | switch { |
| | case ins.rs3 == obj.REG_NONE: |
| | ins.funct7 |= 1 |
| | case ins.rs3 != REG_V0: |
| | p.Ctxt.Diag("%v: invalid vector mask register", p) |
| | } |
| | switch ins.as { |
| | case AVMSGTVV: |
| | ins.as = AVMSLTVV |
| | case AVMSGTUVV: |
| | ins.as = AVMSLTUVV |
| | case AVMSGEVV: |
| | ins.as = AVMSLEVV |
| | case AVMSGEUVV: |
| | ins.as = AVMSLEUVV |
| | case AVMFGTVV: |
| | ins.as = AVMFLTVV |
| | case AVMFGEVV: |
| | ins.as = AVMFLEVV |
| | } |
| | ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), uint32(p.Reg), uint32(p.From.Reg), obj.REG_NONE |
| |
|
| | case AVMSLTVI, AVMSLTUVI, AVMSGEVI, AVMSGEUVI: |
| | |
| | switch { |
| | case ins.rs3 == obj.REG_NONE: |
| | ins.funct7 |= 1 |
| | case ins.rs3 != REG_V0: |
| | p.Ctxt.Diag("%v: invalid vector mask register", p) |
| | } |
| | switch ins.as { |
| | case AVMSLTVI: |
| | ins.as = AVMSLEVI |
| | case AVMSLTUVI: |
| | ins.as = AVMSLEUVI |
| | case AVMSGEVI: |
| | ins.as = AVMSGTVI |
| | case AVMSGEUVI: |
| | ins.as = AVMSGTUVI |
| | } |
| | ins.rd, ins.rs1, ins.rs2, ins.rs3, ins.imm = uint32(p.To.Reg), obj.REG_NONE, uint32(p.Reg), obj.REG_NONE, ins.imm-1 |
| |
|
| | case AVFABSV, AVFNEGV: |
| | |
| | switch { |
| | case ins.rs1 == obj.REG_NONE: |
| | ins.funct7 |= 1 |
| | case ins.rs1 != REG_V0: |
| | p.Ctxt.Diag("%v: invalid vector mask register", p) |
| | } |
| | switch ins.as { |
| | case AVFABSV: |
| | ins.as = AVFSGNJXVV |
| | case AVFNEGV: |
| | ins.as = AVFSGNJNVV |
| | } |
| | ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.From.Reg) |
| |
|
| | case AVMANDMM, AVMNANDMM, AVMANDNMM, AVMXORMM, AVMORMM, AVMNORMM, AVMORNMM, AVMXNORMM, AVMMVM, AVMNOTM, AVCOMPRESSVM: |
| | ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg) |
| | switch ins.as { |
| | case AVMMVM: |
| | ins.as, ins.rs2 = AVMANDMM, ins.rs1 |
| | case AVMNOTM: |
| | ins.as, ins.rs2 = AVMNANDMM, ins.rs1 |
| | } |
| |
|
| | case AVMCLRM, AVMSETM: |
| | ins.rd, ins.rs1, ins.rs2 = uint32(p.From.Reg), uint32(p.From.Reg), uint32(p.From.Reg) |
| | switch ins.as { |
| | case AVMCLRM: |
| | ins.as = AVMXORMM |
| | case AVMSETM: |
| | ins.as = AVMXNORMM |
| | } |
| |
|
| | case AVCPOPM, AVFIRSTM, AVMSBFM, AVMSIFM, AVMSOFM, AVIOTAM: |
| | |
| | switch { |
| | case ins.rs1 == obj.REG_NONE: |
| | ins.funct7 |= 1 |
| | case ins.rs1 != REG_V0: |
| | p.Ctxt.Diag("%v: invalid vector mask register", p) |
| | } |
| | ins.rs1 = obj.REG_NONE |
| |
|
| | case AVIDV: |
| | |
| | switch { |
| | case ins.rd == obj.REG_NONE: |
| | ins.funct7 |= 1 |
| | case ins.rd != obj.REG_NONE && ins.rs2 != REG_V0: |
| | p.Ctxt.Diag("%v: invalid vector mask register", p) |
| | } |
| | if ins.rd == obj.REG_NONE { |
| | ins.rd = uint32(p.From.Reg) |
| | } |
| | ins.rs1, ins.rs2 = obj.REG_NONE, REG_V0 |
| | } |
| |
|
| | |
| | |
| | |
| | if compress && p.Mark&NEED_RELOC == 0 { |
| | for _, ins := range inss { |
| | ins.compress() |
| | } |
| | } |
| |
|
| | for _, ins := range inss { |
| | ins.p = p |
| | } |
| |
|
| | return inss |
| | } |
| |
|
| | |
| | |
| | func assemble(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { |
| | if ctxt.Retpoline { |
| | ctxt.Diag("-spectre=ret not supported on riscv") |
| | ctxt.Retpoline = false |
| | } |
| |
|
| | |
| | |
| | if ctxt.Errors > 0 { |
| | return |
| | } |
| |
|
| | for p := cursym.Func().Text; p != nil; p = p.Link { |
| | switch p.As { |
| | case AJAL: |
| | if p.Mark&NEED_JAL_RELOC == NEED_JAL_RELOC { |
| | cursym.AddRel(ctxt, obj.Reloc{ |
| | Type: objabi.R_RISCV_JAL, |
| | Off: int32(p.Pc), |
| | Siz: 4, |
| | Sym: p.To.Sym, |
| | Add: p.To.Offset, |
| | }) |
| | } |
| |
|
| | case ACJALR, AJALR: |
| | if p.To.Sym != nil { |
| | ctxt.Diag("%v: unexpected AJALR with to symbol", p) |
| | } |
| |
|
| | case AAUIPC, AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD: |
| | var addr *obj.Addr |
| | var rt objabi.RelocType |
| | if p.Mark&NEED_CALL_RELOC == NEED_CALL_RELOC { |
| | rt = objabi.R_RISCV_CALL |
| | addr = &p.From |
| | } else if p.Mark&NEED_PCREL_ITYPE_RELOC == NEED_PCREL_ITYPE_RELOC { |
| | rt = objabi.R_RISCV_PCREL_ITYPE |
| | addr = &p.From |
| | } else if p.Mark&NEED_PCREL_STYPE_RELOC == NEED_PCREL_STYPE_RELOC { |
| | rt = objabi.R_RISCV_PCREL_STYPE |
| | addr = &p.To |
| | } else if p.Mark&NEED_GOT_PCREL_ITYPE_RELOC == NEED_GOT_PCREL_ITYPE_RELOC { |
| | rt = objabi.R_RISCV_GOT_PCREL_ITYPE |
| | addr = &p.From |
| | } else { |
| | break |
| | } |
| | if p.As == AAUIPC { |
| | if p.Link == nil { |
| | ctxt.Diag("AUIPC needing PC-relative reloc missing following instruction") |
| | break |
| | } |
| | addr = &p.RestArgs[0].Addr |
| | } |
| | if addr.Sym == nil { |
| | ctxt.Diag("PC-relative relocation missing symbol") |
| | break |
| | } |
| | if addr.Sym.Type == objabi.STLSBSS { |
| | if ctxt.Flag_shared { |
| | rt = objabi.R_RISCV_TLS_IE |
| | } else { |
| | rt = objabi.R_RISCV_TLS_LE |
| | } |
| | } |
| |
|
| | cursym.AddRel(ctxt, obj.Reloc{ |
| | Type: rt, |
| | Off: int32(p.Pc), |
| | Siz: 8, |
| | Sym: addr.Sym, |
| | Add: addr.Offset, |
| | }) |
| |
|
| | case obj.APCALIGN: |
| | alignedValue := p.From.Offset |
| | v := pcAlignPadLength(p.Pc, alignedValue) |
| | offset := p.Pc |
| | for ; v >= 4; v -= 4 { |
| | |
| | cursym.WriteBytes(ctxt, offset, []byte{0x13, 0x00, 0x00, 0x00}) |
| | offset += 4 |
| | } |
| | if v == 2 { |
| | |
| | cursym.WriteBytes(ctxt, offset, []byte{0x01, 0x00}) |
| | offset += 2 |
| | } else if v != 0 { |
| | ctxt.Diag("bad PCALIGN pad length") |
| | } |
| | continue |
| | } |
| |
|
| | offset := p.Pc |
| | for _, ins := range instructionsForProg(p, ctxt.CompressInstructions) { |
| | if ic, err := ins.encode(); err == nil { |
| | cursym.WriteInt(ctxt, offset, ins.length(), int64(ic)) |
| | offset += int64(ins.length()) |
| | } |
| | if ins.usesRegTmp() { |
| | p.Mark |= USES_REG_TMP |
| | } |
| | } |
| | } |
| |
|
| | obj.MarkUnsafePoints(ctxt, cursym.Func().Text, newprog, isUnsafePoint, nil) |
| | } |
| |
|
| | func isUnsafePoint(p *obj.Prog) bool { |
| | return p.Mark&USES_REG_TMP == USES_REG_TMP || p.From.Reg == REG_TMP || p.To.Reg == REG_TMP || p.Reg == REG_TMP |
| | } |
| |
|
| | func ParseSuffix(prog *obj.Prog, cond string) (err error) { |
| | switch prog.As { |
| | case AFCVTWS, AFCVTLS, AFCVTWUS, AFCVTLUS, AFCVTWD, AFCVTLD, AFCVTWUD, AFCVTLUD: |
| | prog.Scond, err = rmSuffixEncode(strings.TrimPrefix(cond, ".")) |
| | } |
| | return |
| | } |
| |
|
| | var LinkRISCV64 = obj.LinkArch{ |
| | Arch: sys.ArchRISCV64, |
| | Init: buildop, |
| | Preprocess: preprocess, |
| | Assemble: assemble, |
| | Progedit: progedit, |
| | UnaryDst: unaryDst, |
| | DWARFRegisters: RISCV64DWARFRegisters, |
| | } |
| |
|