func intelArg()

in x86/x86asm/intel.go [341:483]


func intelArg(inst *Inst, pc uint64, symname SymLookup, arg Arg) string {
	switch a := arg.(type) {
	case Imm:
		if s, base := symname(uint64(a)); s != "" {
			suffix := ""
			if uint64(a) != base {
				suffix = fmt.Sprintf("%+d", uint64(a)-base)
			}
			return fmt.Sprintf("$%s%s", s, suffix)
		}
		if inst.Mode == 32 {
			return fmt.Sprintf("%#x", uint32(a))
		}
		if Imm(int32(a)) == a {
			return fmt.Sprintf("%#x", int64(a))
		}
		return fmt.Sprintf("%#x", uint64(a))
	case Mem:
		if a.Base == EIP {
			a.Base = RIP
		}
		prefix := ""
		switch inst.MemBytes {
		case 1:
			prefix = "byte "
		case 2:
			prefix = "word "
		case 4:
			prefix = "dword "
		case 8:
			prefix = "qword "
		case 16:
			prefix = "xmmword "
		case 32:
			prefix = "ymmword "
		}
		switch inst.Op {
		case INVLPG:
			prefix = "byte "
		case STOSB, MOVSB, CMPSB, LODSB, SCASB:
			prefix = "byte "
		case STOSW, MOVSW, CMPSW, LODSW, SCASW:
			prefix = "word "
		case STOSD, MOVSD, CMPSD, LODSD, SCASD:
			prefix = "dword "
		case STOSQ, MOVSQ, CMPSQ, LODSQ, SCASQ:
			prefix = "qword "
		case LAR:
			prefix = "word "
		case BOUND:
			if inst.Mode == 32 {
				prefix = "qword "
			} else {
				prefix = "dword "
			}
		case PREFETCHW, PREFETCHNTA, PREFETCHT0, PREFETCHT1, PREFETCHT2, CLFLUSH:
			prefix = "zmmword "
		}
		switch inst.Op {
		case MOVSB, MOVSW, MOVSD, MOVSQ, CMPSB, CMPSW, CMPSD, CMPSQ, STOSB, STOSW, STOSD, STOSQ, SCASB, SCASW, SCASD, SCASQ, LODSB, LODSW, LODSD, LODSQ:
			switch a.Base {
			case DI, EDI, RDI:
				if a.Segment == ES {
					a.Segment = 0
				}
			case SI, ESI, RSI:
				if a.Segment == DS {
					a.Segment = 0
				}
			}
		case LEA:
			a.Segment = 0
		default:
			switch a.Base {
			case SP, ESP, RSP, BP, EBP, RBP:
				if a.Segment == SS {
					a.Segment = 0
				}
			default:
				if a.Segment == DS {
					a.Segment = 0
				}
			}
		}

		if inst.Mode == 64 && a.Segment != FS && a.Segment != GS {
			a.Segment = 0
		}

		prefix += "ptr "
		if s, disp := memArgToSymbol(a, pc, inst.Len, symname); s != "" {
			suffix := ""
			if disp != 0 {
				suffix = fmt.Sprintf("%+d", disp)
			}
			return prefix + fmt.Sprintf("[%s%s]", s, suffix)
		}
		if a.Segment != 0 {
			prefix += strings.ToLower(a.Segment.String()) + ":"
		}
		prefix += "["
		if a.Base != 0 {
			prefix += intelArg(inst, pc, symname, a.Base)
		}
		if a.Scale != 0 && a.Index != 0 {
			if a.Base != 0 {
				prefix += "+"
			}
			prefix += fmt.Sprintf("%s*%d", intelArg(inst, pc, symname, a.Index), a.Scale)
		}
		if a.Disp != 0 {
			if prefix[len(prefix)-1] == '[' && (a.Disp >= 0 || int64(int32(a.Disp)) != a.Disp) {
				prefix += fmt.Sprintf("%#x", uint64(a.Disp))
			} else {
				prefix += fmt.Sprintf("%+#x", a.Disp)
			}
		}
		prefix += "]"
		return prefix
	case Rel:
		if pc == 0 {
			return fmt.Sprintf(".%+#x", int64(a))
		} else {
			addr := pc + uint64(inst.Len) + uint64(a)
			if s, base := symname(addr); s != "" && addr == base {
				return fmt.Sprintf("%s", s)
			} else {
				addr := pc + uint64(inst.Len) + uint64(a)
				return fmt.Sprintf("%#x", addr)
			}
		}
	case Reg:
		if int(a) < len(intelReg) && intelReg[a] != "" {
			switch inst.Op {
			case VMOVDQA, VMOVDQU, VMOVNTDQA, VMOVNTDQ:
				return strings.Replace(intelReg[a], "xmm", "ymm", -1)
			default:
				return intelReg[a]
			}
		}
	}
	return strings.ToLower(arg.String())
}