Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(67)

Side by Side Diff: x86asm/decode.go

Issue 95300044: code review 95300044: x86asm: basic 64-bit mode decoding (Closed)
Patch Set: diff -r 27604273fc7c https://code.google.com/p/rsc.x86/ Created 9 years, 10 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « x86asm/Makefile ('k') | x86asm/ext_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Go Authors. All rights reserved. 1 // Copyright 2014 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 // Table-driven decoding of x86 instructions. 5 // Table-driven decoding of x86 instructions.
6 6
7 package x86asm 7 package x86asm
8 8
9 import ( 9 import (
10 "encoding/binary" 10 "encoding/binary"
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 } 177 }
178 p := Prefix(b) 178 p := Prefix(b)
179 switch p { 179 switch p {
180 case PrefixDataSize: 180 case PrefixDataSize:
181 if mode == 16 { 181 if mode == 16 {
182 p = PrefixData32 182 p = PrefixData32
183 } else { 183 } else {
184 p = PrefixData16 184 p = PrefixData16
185 } 185 }
186 case PrefixAddrSize: 186 case PrefixAddrSize:
187 » » if mode == 16 { 187 » » if mode == 32 {
188 » » » p = PrefixAddr16
189 » » } else {
188 p = PrefixAddr32 190 p = PrefixAddr32
189 } else {
190 p = PrefixAddr16
191 } 191 }
192 } 192 }
193 » return Inst{Prefix: Prefixes{p}}, 1, nil 193 » // Note: using composite literal here confuses 'bundle' tool.
194 » inst := Inst{}
195 » inst.Prefix = Prefixes{p}
196 » return inst, 1, nil
194 } 197 }
195 198
196 // truncated reports a truncated instruction. 199 // truncated reports a truncated instruction.
197 // For now we use instPrefix but perhaps later we will return 200 // For now we use instPrefix but perhaps later we will return
198 // a specific error here. 201 // a specific error here.
199 func truncated(src []byte, mode int) (Inst, int, error) { 202 func truncated(src []byte, mode int) (Inst, int, error) {
200 // return Inst{}, len(src), ErrTruncated 203 // return Inst{}, len(src), ErrTruncated
201 return instPrefix(src[0], mode) // too long 204 return instPrefix(src[0], mode) // too long
202 } 205 }
203 206
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 // prefix decoding information 251 // prefix decoding information
249 pos = 0 // position reading src 252 pos = 0 // position reading src
250 nprefix = 0 // number of prefixes 253 nprefix = 0 // number of prefixes
251 lockIndex = -1 // index of LOCK prefix in src and inst.Pre fix 254 lockIndex = -1 // index of LOCK prefix in src and inst.Pre fix
252 repIndex = -1 // index of REP/REPN prefix in src and inst .Prefix 255 repIndex = -1 // index of REP/REPN prefix in src and inst .Prefix
253 segIndex = -1 // index of Group 2 prefix in src and inst. Prefix 256 segIndex = -1 // index of Group 2 prefix in src and inst. Prefix
254 dataSizeIndex = -1 // index of Group 3 prefix in src and inst. Prefix 257 dataSizeIndex = -1 // index of Group 3 prefix in src and inst. Prefix
255 addrSizeIndex = -1 // index of Group 4 prefix in src and inst. Prefix 258 addrSizeIndex = -1 // index of Group 4 prefix in src and inst. Prefix
256 rex Prefix // rex byte if present (or 0) 259 rex Prefix // rex byte if present (or 0)
257 rexUsed Prefix // bits used in rex byte 260 rexUsed Prefix // bits used in rex byte
261 rexIndex = -1 // index of rex byte
258 262
259 addrMode = mode // address mode (width in bits) 263 addrMode = mode // address mode (width in bits)
260 dataMode = mode // operand mode (width in bits) 264 dataMode = mode // operand mode (width in bits)
261 265
262 // decoded ModR/M fields 266 // decoded ModR/M fields
263 haveModrm bool 267 haveModrm bool
264 modrm int 268 modrm int
265 mod int 269 mod int
266 regop int 270 regop int
267 rm int 271 rm int
(...skipping 13 matching lines...) Expand all
281 imm int64 285 imm int64
282 imm8 int8 286 imm8 int8
283 immc int64 287 immc int64
284 288
285 // output 289 // output
286 opshift int 290 opshift int
287 inst Inst 291 inst Inst
288 narg int // number of arguments written to inst 292 narg int // number of arguments written to inst
289 ) 293 )
290 294
295 if mode == 64 {
296 dataMode = 32
297 }
298
291 // Prefixes are certainly the most complex and underspecified part of 299 // Prefixes are certainly the most complex and underspecified part of
292 // decoding x86 instructions. Although the manuals say things like 300 // decoding x86 instructions. Although the manuals say things like
293 // up to four prefixes, one from each group, nearly everyone seems to 301 // up to four prefixes, one from each group, nearly everyone seems to
294 // agree that in practice as many prefixes as possible, including multip le 302 // agree that in practice as many prefixes as possible, including multip le
295 // from a particular group or repetitions of a given prefix, can be used on 303 // from a particular group or repetitions of a given prefix, can be used on
296 // an instruction, provided the total instruction length including prefi xes 304 // an instruction, provided the total instruction length including prefi xes
297 // does not exceed the agreed-upon maximum of 15 bytes. 305 // does not exceed the agreed-upon maximum of 15 bytes.
298 // Everyone also agrees that if one of these prefixes is the LOCK prefix 306 // Everyone also agrees that if one of these prefixes is the LOCK prefix
299 // and the instruction is not one of the instructions that can be used w ith 307 // and the instruction is not one of the instructions that can be used w ith
300 // the LOCK prefix or if the destination is not a memory operand, 308 // the LOCK prefix or if the destination is not a memory operand,
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 dataMode = 16 378 dataMode = 16
371 p = PrefixData16 379 p = PrefixData16
372 } 380 }
373 if dataSizeIndex >= 0 { 381 if dataSizeIndex >= 0 {
374 inst.Prefix[dataSizeIndex] |= PrefixIgnored 382 inst.Prefix[dataSizeIndex] |= PrefixIgnored
375 } 383 }
376 dataSizeIndex = pos 384 dataSizeIndex = pos
377 385
378 // Group 4 - address size override 386 // Group 4 - address size override
379 case 0x67: 387 case 0x67:
380 » » » if mode == 16 { 388 » » » if mode == 32 {
381 » » » » addrMode = 32
382 » » » » p = PrefixAddr32
383 » » » } else if mode == 32 {
384 addrMode = 16 389 addrMode = 16
385 p = PrefixAddr16 390 p = PrefixAddr16
386 » » » } else if mode == 64 { 391 » » » } else {
387 addrMode = 32 392 addrMode = 32
388 p = PrefixAddr32 393 p = PrefixAddr32
389 } 394 }
390 if addrSizeIndex >= 0 { 395 if addrSizeIndex >= 0 {
391 inst.Prefix[addrSizeIndex] |= PrefixIgnored 396 inst.Prefix[addrSizeIndex] |= PrefixIgnored
392 } 397 }
393 addrSizeIndex = pos 398 addrSizeIndex = pos
394 } 399 }
395 400
396 if pos >= len(inst.Prefix) { 401 if pos >= len(inst.Prefix) {
397 return instPrefix(src[0], mode) // too long 402 return instPrefix(src[0], mode) // too long
398 } 403 }
399 404
400 inst.Prefix[pos] = p 405 inst.Prefix[pos] = p
401 } 406 }
402 407
403 // Read REX prefix. 408 // Read REX prefix.
404 if pos < len(src) && mode == 64 && Prefix(src[pos]).IsREX() { 409 if pos < len(src) && mode == 64 && Prefix(src[pos]).IsREX() {
405 rex = Prefix(src[pos]) 410 rex = Prefix(src[pos])
411 rexIndex = pos
412 if pos >= len(inst.Prefix) {
413 return instPrefix(src[0], mode) // too long
414 }
415 inst.Prefix[pos] = rex
406 pos++ 416 pos++
407 if rex&PrefixREXW != 0 { 417 if rex&PrefixREXW != 0 {
408 dataMode = 64 418 dataMode = 64
419 if dataSizeIndex >= 0 {
420 inst.Prefix[dataSizeIndex] |= PrefixIgnored
421 }
409 } 422 }
410 } 423 }
411 424
412 // Decode instruction stream, interpreting decoding instructions. 425 // Decode instruction stream, interpreting decoding instructions.
413 // opshift gives the shift to use when saving the next 426 // opshift gives the shift to use when saving the next
414 // opcode byte into inst.Opcode. 427 // opcode byte into inst.Opcode.
415 opshift = 24 428 opshift = 24
416 if decoderCover == nil { 429 if decoderCover == nil {
417 decoderCover = make([]bool, len(decoder)) 430 decoderCover = make([]bool, len(decoder))
418 } 431 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 mem = addr16[rm] 473 mem = addr16[rm]
461 if rm == 6 && mod == 0 { 474 if rm == 6 && mod == 0 {
462 mem.Base = 0 475 mem.Base = 0
463 } 476 }
464 477
465 // Consume disp16 if present. 478 // Consume disp16 if present.
466 if mod == 0 && rm == 6 || mod == 2 { 479 if mod == 0 && rm == 6 || mod == 2 {
467 if pos+2 > len(src) { 480 if pos+2 > len(src) {
468 return truncated(src, mo de) 481 return truncated(src, mo de)
469 } 482 }
470 » » » » » » mem.Disp = int32(binary.LittleEn dian.Uint16(src[pos:])) 483 » » » » » » mem.Disp = int64(binary.LittleEn dian.Uint16(src[pos:]))
471 pos += 2 484 pos += 2
472 } 485 }
473 486
474 // Consume disp8 if present. 487 // Consume disp8 if present.
475 if mod == 1 { 488 if mod == 1 {
476 if pos >= len(src) { 489 if pos >= len(src) {
477 return truncated(src, mo de) 490 return truncated(src, mo de)
478 } 491 }
479 » » » » » » mem.Disp = int32(int8(src[pos])) 492 » » » » » » mem.Disp = int64(int8(src[pos]))
480 pos++ 493 pos++
481 } 494 }
482 } 495 }
483 } else { 496 } else {
484 haveMem = mod != 3 497 haveMem = mod != 3
485 498
486 // 32-bit or 64-bit form 499 // 32-bit or 64-bit form
487 // Consume SIB encoding if present. 500 // Consume SIB encoding if present.
488 if rm == 4 && mod != 3 { 501 if rm == 4 && mod != 3 {
489 haveSIB = true 502 haveSIB = true
(...skipping 17 matching lines...) Expand all
507 rexUsed |= PrefixREXX 520 rexUsed |= PrefixREXX
508 index |= 8 521 index |= 8
509 } 522 }
510 523
511 mem.Scale = 1 << uint(scale) 524 mem.Scale = 1 << uint(scale)
512 if index == 4 { 525 if index == 4 {
513 // no mem.Index 526 // no mem.Index
514 } else { 527 } else {
515 mem.Index = baseRegForBits(addrM ode) + Reg(index) 528 mem.Index = baseRegForBits(addrM ode) + Reg(index)
516 } 529 }
517 » » » » » if base == 5 && mod == 0 { 530 » » » » » if base&7 == 5 && mod == 0 {
518 // no mem.Base 531 // no mem.Base
519 } else { 532 } else {
520 mem.Base = baseRegForBits(addrMo de) + Reg(base) 533 mem.Base = baseRegForBits(addrMo de) + Reg(base)
521 } 534 }
522 } else { 535 } else {
523 if rex&PrefixREXB != 0 { 536 if rex&PrefixREXB != 0 {
524 rexUsed |= PrefixREXB 537 rexUsed |= PrefixREXB
525 rm |= 8 538 rm |= 8
526 } 539 }
527 540 » » » » » if mod == 0 && rm&7 == 5 || rm&7 == 4 {
528 » » » » » if mod == 0 && rm == 5 || rm == 4 {
529 // base omitted 541 // base omitted
530 } else if mod != 3 { 542 } else if mod != 3 {
531 mem.Base = baseRegForBits(addrMo de) + Reg(rm) 543 mem.Base = baseRegForBits(addrMo de) + Reg(rm)
532 } 544 }
533 } 545 }
534 546
535 // Consume disp32 if present. 547 // Consume disp32 if present.
536 » » » » if mod == 0 && (rm == 5 || haveSIB && base == 5) || mod == 2 { 548 » » » » if mod == 0 && (rm&7 == 5 || haveSIB && base&7 = = 5) || mod == 2 {
537 if pos+4 > len(src) { 549 if pos+4 > len(src) {
538 return truncated(src, mode) 550 return truncated(src, mode)
539 } 551 }
540 » » » » » mem.Disp = int32(binary.LittleEndian.Uin t32(src[pos:])) 552 » » » » » mem.Disp = int64(binary.LittleEndian.Uin t32(src[pos:]))
541 pos += 4 553 pos += 4
542 } 554 }
543 555
544 // Consume disp8 if present. 556 // Consume disp8 if present.
545 if mod == 1 { 557 if mod == 1 {
546 if pos >= len(src) { 558 if pos >= len(src) {
547 return truncated(src, mode) 559 return truncated(src, mode)
548 } 560 }
549 » » » » » mem.Disp = int32(int8(src[pos])) 561 » » » » » mem.Disp = int64(int8(src[pos]))
550 pos++ 562 pos++
551 } 563 }
564
565 // In 64-bit, mod=0 rm=5 is PC-relative instead of just disp.
566 // See Vol 2A. Table 2-7.
567 if mode == 64 && mod == 0 && rm&7 == 5 {
568 if addrMode == 32 {
569 mem.Base = EIP
570 } else {
571 mem.Base = RIP
572 }
573 }
552 } 574 }
553 575
554 if segIndex >= 0 { 576 if segIndex >= 0 {
555 mem.Segment = prefixToSegment(inst.Prefix[segInd ex]) 577 mem.Segment = prefixToSegment(inst.Prefix[segInd ex])
556 } 578 }
557 } 579 }
558 580
559 // Execute single opcode. 581 // Execute single opcode.
560 switch decodeOp(x) { 582 switch decodeOp(x) {
561 default: 583 default:
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
633 if dataSizeIndex >= 0 { 655 if dataSizeIndex >= 0 {
634 inst.Prefix[dataSizeIndex] |= PrefixImpl icit 656 inst.Prefix[dataSizeIndex] |= PrefixImpl icit
635 } 657 }
636 pc = int(decoder[pc]) 658 pc = int(decoder[pc])
637 case 32: 659 case 32:
638 if dataSizeIndex >= 0 { 660 if dataSizeIndex >= 0 {
639 inst.Prefix[dataSizeIndex] |= PrefixImpl icit 661 inst.Prefix[dataSizeIndex] |= PrefixImpl icit
640 } 662 }
641 pc = int(decoder[pc+1]) 663 pc = int(decoder[pc+1])
642 case 64: 664 case 64:
665 rexUsed |= PrefixREXW
643 pc = int(decoder[pc+2]) 666 pc = int(decoder[pc+2])
644 } 667 }
645 668
646 case xCondAddrSize: 669 case xCondAddrSize:
647 switch addrMode { 670 switch addrMode {
648 case 16: 671 case 16:
649 if addrSizeIndex >= 0 { 672 if addrSizeIndex >= 0 {
650 inst.Prefix[addrSizeIndex] |= PrefixImpl icit 673 inst.Prefix[addrSizeIndex] |= PrefixImpl icit
651 } 674 }
652 pc = int(decoder[pc]) 675 pc = int(decoder[pc])
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
870 immc = int64(binary.LittleEndian.Uint16(src[pos:])) 893 immc = int64(binary.LittleEndian.Uint16(src[pos:]))
871 pos += 2 894 pos += 2
872 895
873 case xReadCm: 896 case xReadCm:
874 if addrMode == 16 { 897 if addrMode == 16 {
875 if pos+2 > len(src) { 898 if pos+2 > len(src) {
876 return truncated(src, mode) 899 return truncated(src, mode)
877 } 900 }
878 immc = int64(binary.LittleEndian.Uint16(src[pos: ])) 901 immc = int64(binary.LittleEndian.Uint16(src[pos: ]))
879 pos += 2 902 pos += 2
880 » » » } else { 903 » » » } else if addrMode == 32 {
881 if pos+4 > len(src) { 904 if pos+4 > len(src) {
882 return truncated(src, mode) 905 return truncated(src, mode)
883 } 906 }
884 immc = int64(binary.LittleEndian.Uint32(src[pos: ])) 907 immc = int64(binary.LittleEndian.Uint32(src[pos: ]))
885 pos += 4 908 pos += 4
909 } else {
910 if pos+8 > len(src) {
911 return truncated(src, mode)
912 }
913 immc = int64(binary.LittleEndian.Uint64(src[pos: ]))
914 pos += 8
886 } 915 }
887 case xReadCd: 916 case xReadCd:
888 if pos+4 > len(src) { 917 if pos+4 > len(src) {
889 return truncated(src, mode) 918 return truncated(src, mode)
890 } 919 }
891 immc = int64(binary.LittleEndian.Uint32(src[pos:])) 920 immc = int64(binary.LittleEndian.Uint32(src[pos:]))
892 pos += 4 921 pos += 4
893 922
894 case xReadCp: 923 case xReadCp:
895 if pos+6 > len(src) { 924 if pos+6 > len(src) {
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
990 inst.Args[narg+1] = Imm(immc & (1<<16 - 1)) 1019 inst.Args[narg+1] = Imm(immc & (1<<16 - 1))
991 narg += 2 1020 narg += 2
992 1021
993 case xArgPtr16colon32: 1022 case xArgPtr16colon32:
994 inst.Args[narg] = Imm(immc >> 32) 1023 inst.Args[narg] = Imm(immc >> 32)
995 inst.Args[narg+1] = Imm(immc & (1<<32 - 1)) 1024 inst.Args[narg+1] = Imm(immc & (1<<32 - 1))
996 narg += 2 1025 narg += 2
997 1026
998 case xArgMoffs8, xArgMoffs16, xArgMoffs32, xArgMoffs64: 1027 case xArgMoffs8, xArgMoffs16, xArgMoffs32, xArgMoffs64:
999 // TODO(rsc): Can address be 64 bits? 1028 // TODO(rsc): Can address be 64 bits?
1000 » » » mem = Mem{Disp: int32(immc)} 1029 » » » mem = Mem{Disp: int64(immc)}
1001 if segIndex >= 0 { 1030 if segIndex >= 0 {
1002 mem.Segment = prefixToSegment(inst.Prefix[segInd ex]) 1031 mem.Segment = prefixToSegment(inst.Prefix[segInd ex])
1003 inst.Prefix[segIndex] |= PrefixImplicit 1032 inst.Prefix[segIndex] |= PrefixImplicit
1004 } 1033 }
1005 inst.Args[narg] = mem 1034 inst.Args[narg] = mem
1006 inst.MemBytes = int(memBytes[decodeOp(x)]) 1035 inst.MemBytes = int(memBytes[decodeOp(x)])
1007 narg++ 1036 narg++
1008 1037
1009 » » case xArgR8, xArgR16, xArgR32, xArgR64, xArgXmm, xArgXmm1, xArgM m, xArgMm1, xArgDR0dashDR7, xArgTR0dashTR7: 1038 » » case xArgR8, xArgR16, xArgR32, xArgR64, xArgXmm, xArgXmm1, xArgD R0dashDR7:
1010 » » » inst.Args[narg] = baseReg[x] + Reg(regop) 1039 » » » base := baseReg[x]
1040 » » » index := Reg(regop)
1041 » » » if rex != 0 && base == AL && index >= 4 {
1042 » » » » rexUsed |= PrefixREX
1043 » » » » index -= 4
1044 » » » » base = SPB
1045 » » » }
1046 » » » inst.Args[narg] = base + index
1047 » » » narg++
1048
1049 » » case xArgMm, xArgMm1, xArgTR0dashTR7:
1050 » » » inst.Args[narg] = baseReg[x] + Reg(regop&7)
1011 narg++ 1051 narg++
1012 1052
1013 case xArgCR0dashCR7: 1053 case xArgCR0dashCR7:
1014 // AMD documents an extension that the LOCK prefix 1054 // AMD documents an extension that the LOCK prefix
1015 // can be used in place of a REX prefix in order to acce ss 1055 // can be used in place of a REX prefix in order to acce ss
1016 // CR8 from 32-bit mode. The LOCK prefix is allowed in 1056 // CR8 from 32-bit mode. The LOCK prefix is allowed in
1017 // all modes, provided the corresponding CPUID bit is se t. 1057 // all modes, provided the corresponding CPUID bit is se t.
1018 if lockIndex >= 0 { 1058 if lockIndex >= 0 {
1019 inst.Prefix[lockIndex] |= PrefixImplicit 1059 inst.Prefix[lockIndex] |= PrefixImplicit
1020 regop += 8 1060 regop += 8
1021 } 1061 }
1022 inst.Args[narg] = CR0 + Reg(regop) 1062 inst.Args[narg] = CR0 + Reg(regop)
1023 narg++ 1063 narg++
1024 1064
1025 case xArgSreg: 1065 case xArgSreg:
1066 regop &= 7
1026 if regop >= 6 { 1067 if regop >= 6 {
1027 inst.Op = 0 1068 inst.Op = 0
1028 break Decode 1069 break Decode
1029 } 1070 }
1030 inst.Args[narg] = ES + Reg(regop) 1071 inst.Args[narg] = ES + Reg(regop)
1031 narg++ 1072 narg++
1032 1073
1033 case xArgRmf16, xArgRmf32, xArgRmf64: 1074 case xArgRmf16, xArgRmf32, xArgRmf64:
1034 » » » inst.Args[narg] = baseReg[x] + Reg(modrm&07) 1075 » » » base := baseReg[x]
1076 » » » index := Reg(modrm & 07)
1077 » » » if rex&PrefixREXB != 0 {
1078 » » » » rexUsed |= PrefixREXB
1079 » » » » index += 8
1080 » » » }
1081 » » » inst.Args[narg] = base + index
1035 narg++ 1082 narg++
1036 1083
1037 case xArgR8op, xArgR16op, xArgR32op, xArgR64op, xArgSTi: 1084 case xArgR8op, xArgR16op, xArgR32op, xArgR64op, xArgSTi:
1038 n := inst.Opcode >> uint(opshift+8) & 07 1085 n := inst.Opcode >> uint(opshift+8) & 07
1039 » » » inst.Args[narg] = baseReg[x] + Reg(n) 1086 » » » base := baseReg[x]
1087 » » » index := Reg(n)
1088 » » » if rex&PrefixREXB != 0 && decodeOp(x) != xArgSTi {
1089 » » » » rexUsed |= PrefixREXB
1090 » » » » index += 8
1091 » » » }
1092 » » » if rex != 0 && base == AL && index >= 4 {
1093 » » » » rexUsed |= PrefixREX
1094 » » » » index -= 4
1095 » » » » base = SPB
1096 » » » }
1097 » » » inst.Args[narg] = base + index
1040 narg++ 1098 narg++
1041 1099
1042 case xArgRM8, xArgRM16, xArgRM32, xArgRM64, xArgR32M16, xArgR32M 8, xArgR64M16, 1100 case xArgRM8, xArgRM16, xArgRM32, xArgRM64, xArgR32M16, xArgR32M 8, xArgR64M16,
1043 xArgMmM32, xArgMmM64, xArgMm2M64, 1101 xArgMmM32, xArgMmM64, xArgMm2M64,
1044 xArgXmm2M16, xArgXmm2M32, xArgXmm2M64, xArgXmmM64, xArgX mmM128, xArgXmmM32, xArgXmm2M128: 1102 xArgXmm2M16, xArgXmm2M32, xArgXmm2M64, xArgXmmM64, xArgX mmM128, xArgXmmM32, xArgXmm2M128:
1045 if haveMem { 1103 if haveMem {
1046 inst.Args[narg] = mem 1104 inst.Args[narg] = mem
1047 inst.MemBytes = int(memBytes[decodeOp(x)]) 1105 inst.MemBytes = int(memBytes[decodeOp(x)])
1048 } else { 1106 } else {
1049 » » » » inst.Args[narg] = baseReg[x] + Reg(rm) 1107 » » » » base := baseReg[x]
1108 » » » » index := Reg(rm)
1109 » » » » switch decodeOp(x) {
1110 » » » » case xArgMmM32, xArgMmM64, xArgMm2M64:
1111 » » » » » // There are only 8 MMX registers, so th ese ignore the REX.X bit.
1112 » » » » » index &= 7
1113 » » » » case xArgRM8:
1114 » » » » » if rex != 0 && index >= 4 {
1115 » » » » » » rexUsed |= PrefixREX
1116 » » » » » » index -= 4
1117 » » » » » » base = SPB
1118 » » » » » }
1119 » » » » }
1120 » » » » inst.Args[narg] = base + index
1050 } 1121 }
1051 narg++ 1122 narg++
1052 1123
1053 » » case xArgMm2, xArgXmm2: // register only; TODO(rsc): Handle with tag modrm_regonly tag 1124 » » case xArgMm2: // register only; TODO(rsc): Handle with tag modrm _regonly tag
1054 if haveMem { 1125 if haveMem {
1055 inst.Op = 0 1126 inst.Op = 0
1056 break Decode 1127 break Decode
1128 }
1129 inst.Args[narg] = baseReg[x] + Reg(rm&7)
1130 narg++
1131
1132 case xArgXmm2: // register only; TODO(rsc): Handle with tag modr m_regonly tag
1133 if haveMem {
1134 inst.Op = 0
1135 break Decode
1057 } 1136 }
1058 inst.Args[narg] = baseReg[x] + Reg(rm) 1137 inst.Args[narg] = baseReg[x] + Reg(rm)
1059 narg++ 1138 narg++
1060 1139
1061 case xArgRel8: 1140 case xArgRel8:
1062 inst.Args[narg] = Rel(int8(immc)) 1141 inst.Args[narg] = Rel(int8(immc))
1063 narg++ 1142 narg++
1064 1143
1065 case xArgRel16: 1144 case xArgRel16:
1066 inst.Args[narg] = Rel(int16(immc)) 1145 inst.Args[narg] = Rel(int16(immc))
1067 narg++ 1146 narg++
1068 1147
1069 case xArgRel32: 1148 case xArgRel32:
1070 inst.Args[narg] = Rel(int32(immc)) 1149 inst.Args[narg] = Rel(int32(immc))
1071 narg++ 1150 narg++
1072 } 1151 }
1073 } 1152 }
1074 1153
1075 if inst.Op == 0 { 1154 if inst.Op == 0 {
1076 // Invalid instruction. 1155 // Invalid instruction.
1077 if nprefix > 0 { 1156 if nprefix > 0 {
1078 return instPrefix(src[0], mode) // invalid instruction 1157 return instPrefix(src[0], mode) // invalid instruction
1079 } 1158 }
1080 return Inst{}, pos, ErrUnrecognized 1159 return Inst{}, pos, ErrUnrecognized
1081 } 1160 }
1082 1161
1083 // Matched! Hooray! 1162 // Matched! Hooray!
1084 1163
1164 // 90 decodes as XCHG EAX, EAX but is NOP.
1165 // 66 90 decodes as XCHG AX, AX and is NOP too.
1166 // 48 90 decodes as XCHG RAX, RAX and is NOP too.
1167 // 43 90 decodes as XCHG R8D, EAX and is *not* NOP.
1168 // F3 90 decodes as REP XCHG EAX, EAX but is PAUSE.
1169 // It's all too special to handle in the decoding tables, at least for n ow.
1170 if inst.Op == XCHG && inst.Opcode>>24 == 0x90 {
1171 if inst.Args[0] == RAX || inst.Args[0] == EAX || inst.Args[0] == AX {
1172 inst.Op = NOP
1173 if dataSizeIndex >= 0 {
1174 inst.Prefix[dataSizeIndex] &^= PrefixImplicit
1175 }
1176 inst.Args[0] = nil
1177 inst.Args[1] = nil
1178 }
1179 if repIndex >= 0 && inst.Prefix[repIndex] == 0xF3 {
1180 inst.Prefix[repIndex] |= PrefixImplicit
1181 inst.Op = PAUSE
1182 inst.Args[0] = nil
1183 inst.Args[1] = nil
1184 } else if gnuCompat {
1185 for i := nprefix - 1; i >= 0; i-- {
1186 if inst.Prefix[i]&0xFF == 0xF3 {
1187 inst.Prefix[i] |= PrefixImplicit
1188 inst.Op = PAUSE
1189 inst.Args[0] = nil
1190 inst.Args[1] = nil
1191 break
1192 }
1193 }
1194 }
1195 }
1196
1085 // defaultSeg returns the default segment for an implicit 1197 // defaultSeg returns the default segment for an implicit
1086 // memory reference: the final override if present, or else DS. 1198 // memory reference: the final override if present, or else DS.
1087 defaultSeg := func() Reg { 1199 defaultSeg := func() Reg {
1088 if segIndex >= 0 { 1200 if segIndex >= 0 {
1089 inst.Prefix[segIndex] |= PrefixImplicit 1201 inst.Prefix[segIndex] |= PrefixImplicit
1090 return prefixToSegment(inst.Prefix[segIndex]) 1202 return prefixToSegment(inst.Prefix[segIndex])
1091 } 1203 }
1092 return DS 1204 return DS
1093 } 1205 }
1094 1206
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1189 // since segment prefixes don't make sense on conditional jumps. 1301 // since segment prefixes don't make sense on conditional jumps.
1190 // Rewrite final instance to prediction prefix. 1302 // Rewrite final instance to prediction prefix.
1191 // The set of instructions to which the prefixes apply (other then the 1303 // The set of instructions to which the prefixes apply (other then the
1192 // Jcc conditional jumps) is not 100% clear from the manuals, but 1304 // Jcc conditional jumps) is not 100% clear from the manuals, but
1193 // the disassemblers seem to agree about the LOOP and JCXZ instructions, 1305 // the disassemblers seem to agree about the LOOP and JCXZ instructions,
1194 // so we'll follow along. 1306 // so we'll follow along.
1195 // TODO(rsc): Perhaps this instruction class should be derived from the CSV. 1307 // TODO(rsc): Perhaps this instruction class should be derived from the CSV.
1196 if isCondJmp[inst.Op] || isLoop[inst.Op] || inst.Op == JCXZ || inst.Op = = JECXZ || inst.Op == JRCXZ { 1308 if isCondJmp[inst.Op] || isLoop[inst.Op] || inst.Op == JCXZ || inst.Op = = JECXZ || inst.Op == JRCXZ {
1197 PredictLoop: 1309 PredictLoop:
1198 for i := nprefix - 1; i >= 0; i-- { 1310 for i := nprefix - 1; i >= 0; i-- {
1199 » » » switch inst.Prefix[i] & 0xFF { 1311 » » » p := inst.Prefix[i]
1312 » » » switch p & 0xFF {
1200 case PrefixCS: 1313 case PrefixCS:
1201 inst.Prefix[i] = PrefixPN 1314 inst.Prefix[i] = PrefixPN
1202 break PredictLoop 1315 break PredictLoop
1203 case PrefixDS: 1316 case PrefixDS:
1204 inst.Prefix[i] = PrefixPT 1317 inst.Prefix[i] = PrefixPT
1205 break PredictLoop 1318 break PredictLoop
1206 } 1319 }
1207 } 1320 }
1208 } 1321 }
1209 1322
1210 // The BND prefix is part of the Intel Memory Protection Extensions (MPX ). 1323 // The BND prefix is part of the Intel Memory Protection Extensions (MPX ).
1211 // A REPN applied to certain control transfers is a BND prefix to bound 1324 // A REPN applied to certain control transfers is a BND prefix to bound
1212 // the range of possible destinations. There's surprisingly little docum entation 1325 // the range of possible destinations. There's surprisingly little docum entation
1213 // about this, so we just do what libopcodes and xed agree on. 1326 // about this, so we just do what libopcodes and xed agree on.
1214 // In particular, it's unclear why a REPN applied to LOOP or JCXZ instru ctions 1327 // In particular, it's unclear why a REPN applied to LOOP or JCXZ instru ctions
1215 // does not turn into a BND. 1328 // does not turn into a BND.
1216 // TODO(rsc): Perhaps this instruction class should be derived from the CSV. 1329 // TODO(rsc): Perhaps this instruction class should be derived from the CSV.
1217 if isCondJmp[inst.Op] || inst.Op == JMP || inst.Op == CALL || inst.Op == RET { 1330 if isCondJmp[inst.Op] || inst.Op == JMP || inst.Op == CALL || inst.Op == RET {
1218 for i := nprefix - 1; i >= 0; i-- { 1331 for i := nprefix - 1; i >= 0; i-- {
1219 p := inst.Prefix[i] 1332 p := inst.Prefix[i]
1220 if p&^PrefixIgnored == PrefixREPN { 1333 if p&^PrefixIgnored == PrefixREPN {
1221 » » » » inst.Prefix[i] = p&PrefixIgnored | PrefixBND 1334 » » » » inst.Prefix[i] = PrefixBND
1222 break 1335 break
1223 } 1336 }
1224 } 1337 }
1225 } 1338 }
1226 1339
1227 // The LOCK prefix only applies to certain instructions, and then only 1340 // The LOCK prefix only applies to certain instructions, and then only
1228 // to instances of the instruction with a memory destination. 1341 // to instances of the instruction with a memory destination.
1229 // Other uses of LOCK are invalid and cause a processor exception, 1342 // Other uses of LOCK are invalid and cause a processor exception,
1230 // in contrast to the "just ignore it" spirit applied to all other prefi xes. 1343 // in contrast to the "just ignore it" spirit applied to all other prefi xes.
1231 // Mark invalid lock prefixes. 1344 // Mark invalid lock prefixes.
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1296 CMPSB, CMPSW, CMPSD, CMPSQ, 1409 CMPSB, CMPSW, CMPSD, CMPSQ,
1297 SCASB, SCASW, SCASD, SCASQ, 1410 SCASB, SCASW, SCASD, SCASQ,
1298 STOSB, STOSW, STOSD, STOSQ: 1411 STOSB, STOSW, STOSD, STOSQ:
1299 // ok 1412 // ok
1300 default: 1413 default:
1301 inst.Prefix[repIndex] |= PrefixIgnored 1414 inst.Prefix[repIndex] |= PrefixIgnored
1302 } 1415 }
1303 } 1416 }
1304 } 1417 }
1305 1418
1419 // If REX was present, mark implicit if all the 1 bits were consumed.
1420 if rexIndex >= 0 {
1421 if rexUsed != 0 {
1422 rexUsed |= PrefixREX
1423 }
1424 if rex&^rexUsed == 0 {
1425 inst.Prefix[rexIndex] |= PrefixImplicit
1426 }
1427 }
1428
1306 inst.DataSize = dataMode 1429 inst.DataSize = dataMode
1307 inst.AddrSize = addrMode 1430 inst.AddrSize = addrMode
1308 inst.Mode = mode 1431 inst.Mode = mode
1309 return inst, pos, nil 1432 return inst, pos, nil
1310 } 1433 }
1311 1434
1312 var errInternal = errors.New("internal error") 1435 var errInternal = errors.New("internal error")
1313 1436
1314 // addr16 records the eight 16-bit addressing modes. 1437 // addr16 records the eight 16-bit addressing modes.
1315 var addr16 = [8]Mem{ 1438 var addr16 = [8]Mem{
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
1484 } 1607 }
1485 1608
1486 // isLoop records the loop operators. 1609 // isLoop records the loop operators.
1487 var isLoop = [maxOp + 1]bool{ 1610 var isLoop = [maxOp + 1]bool{
1488 LOOP: true, 1611 LOOP: true,
1489 LOOPE: true, 1612 LOOPE: true,
1490 LOOPNE: true, 1613 LOOPNE: true,
1491 JECXZ: true, 1614 JECXZ: true,
1492 JRCXZ: true, 1615 JRCXZ: true,
1493 } 1616 }
OLDNEW
« no previous file with comments | « x86asm/Makefile ('k') | x86asm/ext_test.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b