| 1 | <?php |
| 2 | namespace Std\Lib\Syntax; |
| 3 | |
| 4 | /** |
| 5 | * x86-64(NASMとGASのAT&T記法の両方) |
| 6 | */ |
| 7 | class AsmX8664 extends Assembly { |
| 8 | protected array $comment = [';', '#']; |
| 9 | protected string $immediatePrefix = ''; |
| 10 | protected bool $percentBinary = false; |
| 11 | protected bool $percentMacros = true; |
| 12 | protected array $prefixes = ['rep', 'repe', 'repne', 'repz', 'repnz', 'lock', 'xacquire', 'xrelease', 'bnd', 'notrack', 'data16', 'addr32', 'rex', 'rex.w']; |
| 13 | |
| 14 | protected array $tokens = [ |
| 15 | 'register' => [ |
| 16 | 'rax', 'rbx', 'rcx', 'rdx', 'rsi', 'rdi', 'rbp', 'rsp', |
| 17 | 'eax', 'ebx', 'ecx', 'edx', 'esi', 'edi', 'ebp', 'esp', |
| 18 | 'ax', 'bx', 'cx', 'dx', 'si', 'di', 'bp', 'sp', |
| 19 | 'al', 'bl', 'cl', 'dl', 'ah', 'bh', 'ch', 'dh', 'sil', 'dil', 'bpl', 'spl', |
| 20 | 'rip', 'eip', 'ip', 'rflags', 'eflags', 'flags', |
| 21 | 'cs', 'ds', 'es', 'fs', 'gs', 'ss', 'st', |
| 22 | ], |
| 23 | 'instruction' => [ |
| 24 | // データ転送 |
| 25 | 'mov', 'movzx', 'movsx', 'movsxd', 'movabs', 'lea', 'xchg', 'cmpxchg', 'cmpxchg8b', 'cmpxchg16b', 'xadd', 'bswap', 'push', 'pop', |
| 26 | 'pushf', 'popf', 'pushfq', 'popfq', 'pusha', 'popa', 'cbw', 'cwde', 'cdqe', 'cwd', 'cdq', 'cqo', 'movbe', 'movnti', |
| 27 | // AT&T記法のサイズ付き |
| 28 | 'movb', 'movw', 'movl', 'movq', 'leaq', 'leal', 'addq', 'addl', 'subq', 'subl', 'pushq', 'popq', 'cmpq', 'cmpl', 'xorl', 'xorq', |
| 29 | 'andq', 'andl', 'orq', 'orl', 'incq', 'incl', 'decq', 'decl', 'imulq', 'imull', 'testq', 'testl', 'shlq', 'shrq', 'sarq', 'callq', 'retq', |
| 30 | 'movzbl', 'movzwl', 'movsbl', 'movswl', 'movslq', 'cltq', 'cqto', 'cltd', |
| 31 | // 算術・論理 |
| 32 | 'add', 'adc', 'sub', 'sbb', 'mul', 'imul', 'div', 'idiv', 'inc', 'dec', 'neg', 'cmp', 'test', 'and', 'or', 'xor', 'not', |
| 33 | 'shl', 'shr', 'sal', 'sar', 'rol', 'ror', 'rcl', 'rcr', 'shld', 'shrd', 'bt', 'bts', 'btr', 'btc', 'bsf', 'bsr', |
| 34 | 'lzcnt', 'tzcnt', 'popcnt', 'andn', 'bextr', 'blsi', 'blsmsk', 'blsr', 'bzhi', 'mulx', 'pdep', 'pext', 'rorx', 'sarx', 'shlx', 'shrx', |
| 35 | 'adcx', 'adox', 'crc32', |
| 36 | // 分岐 |
| 37 | 'jmp', 'call', 'ret', 'retf', 'iret', 'iretq', 'loop', 'loope', 'loopne', 'jcxz', 'jecxz', 'jrcxz', 'enter', 'leave', |
| 38 | 'int', 'int3', 'into', 'syscall', 'sysret', 'sysenter', 'sysexit', |
| 39 | // 文字列 |
| 40 | 'movs', 'movsb', 'movsw', 'movsq', 'stos', 'stosb', 'stosw', 'stosd', 'stosq', 'lods', 'lodsb', 'lodsw', 'lodsd', 'lodsq', |
| 41 | 'scas', 'scasb', 'scasw', 'scasd', 'scasq', 'cmps', 'cmpsb', 'cmpsw', 'cmpsq', |
| 42 | // フラグ・その他 |
| 43 | 'clc', 'stc', 'cmc', 'cld', 'std', 'cli', 'sti', 'lahf', 'sahf', 'nop', 'hlt', 'pause', 'ud2', 'cpuid', 'rdtsc', 'rdtscp', 'rdrand', 'rdseed', |
| 44 | 'xgetbv', 'lfence', 'sfence', 'mfence', 'prefetcht0', 'prefetcht1', 'prefetcht2', 'prefetchnta', 'clflush', 'endbr64', 'in', 'out', |
| 45 | // x87 |
| 46 | 'fld', 'fst', 'fstp', 'fild', 'fist', 'fistp', 'fadd', 'faddp', 'fsub', 'fsubp', 'fmul', 'fmulp', 'fdiv', 'fdivp', 'fsqrt', 'fsin', 'fcos', |
| 47 | 'fxch', 'fcomi', 'fcomip', 'fldz', 'fld1', 'fninit', 'fwait', |
| 48 | // SSE・AVX |
| 49 | 'movaps', 'movups', 'movapd', 'movupd', 'movss', 'movsd', 'movd', 'movdqa', 'movdqu', 'movhlps', 'movlhps', 'movmskps', |
| 50 | 'addss', 'addsd', 'addps', 'addpd', 'subss', 'subsd', 'subps', 'subpd', 'mulss', 'mulsd', 'mulps', 'mulpd', 'divss', 'divsd', 'divps', 'divpd', |
| 51 | 'sqrtss', 'sqrtsd', 'sqrtps', 'sqrtpd', 'rsqrtss', 'rsqrtps', 'rcpss', 'rcpps', 'minss', 'minsd', 'minps', 'minpd', 'maxss', 'maxsd', 'maxps', 'maxpd', |
| 52 | 'andps', 'andpd', 'andnps', 'andnpd', 'orps', 'orpd', 'xorps', 'xorpd', 'cmpps', 'cmpss', 'comiss', 'comisd', 'ucomiss', 'ucomisd', |
| 53 | 'shufps', 'shufpd', 'unpcklps', 'unpckhps', 'unpcklpd', 'unpckhpd', 'blendps', 'blendvps', 'dpps', 'roundss', 'roundps', |
| 54 | 'cvtsi2ss', 'cvtsi2sd', 'cvtss2si', 'cvtsd2si', 'cvttss2si', 'cvttsd2si', 'cvtss2sd', 'cvtsd2ss', 'cvtdq2ps', 'cvtps2dq', 'cvttps2dq', |
| 55 | 'paddb', 'paddw', 'paddd', 'paddq', 'psubb', 'psubw', 'psubd', 'psubq', 'pmullw', 'pmulld', 'pmuludq', 'pand', 'pandn', 'por', 'pxor', |
| 56 | 'pcmpeqb', 'pcmpeqd', 'pcmpgtd', 'pshufb', 'pshufd', 'pslld', 'psrld', 'psrad', 'psllq', 'psrlq', 'punpcklbw', 'punpckldq', 'packuswb', |
| 57 | 'pmovmskb', 'ptest', 'pminsd', 'pmaxsd', 'pextrd', 'pinsrd', 'pabsd', 'phaddd', |
| 58 | 'vmovaps', 'vmovups', 'vmovapd', 'vmovupd', 'vmovss', 'vmovsd', 'vmovdqa', 'vmovdqu', 'vmovdqa64', 'vmovdqu8', 'vmovdqu32', |
| 59 | 'vaddps', 'vaddpd', 'vaddss', 'vaddsd', 'vsubps', 'vsubpd', 'vmulps', 'vmulpd', 'vdivps', 'vdivpd', 'vsqrtps', 'vminps', 'vmaxps', |
| 60 | 'vandps', 'vorps', 'vxorps', 'vpxor', 'vpand', 'vpor', 'vpaddd', 'vpsubd', 'vpmulld', 'vpshufb', 'vpermd', 'vpermps', 'vperm2f128', |
| 61 | 'vbroadcastss', 'vbroadcastsd', 'vpbroadcastd', 'vinsertf128', 'vextractf128', 'vshufps', 'vblendvps', 'vgatherdps', 'vcvtps2ph', 'vcvtph2ps', |
| 62 | 'vfmadd132ps', 'vfmadd213ps', 'vfmadd231ps', 'vfmadd132ss', 'vfmadd213ss', 'vfmadd231ss', 'vfmadd231pd', 'vfnmadd231ps', 'vfmsub231ps', |
| 63 | 'vzeroupper', 'vzeroall', 'vptest', 'vcmpps', 'vhaddps', 'vdpps', 'vroundps', 'kmovw', 'kmovq', 'vpternlogd', 'vpcompressd', 'vpexpandd', |
| 64 | ], |
| 65 | 'keyword' => [ |
| 66 | // サイズ指定等(NASM) |
| 67 | 'byte', 'word', 'dword', 'qword', 'tword', 'oword', 'yword', 'zword', 'ptr', 'rel', 'abs', 'near', 'far', 'short', 'strict', 'wrt', 'seg', |
| 68 | 'rep', 'repe', 'repne', 'repz', 'repnz', 'lock', 'xacquire', 'xrelease', 'bnd', 'notrack', |
| 69 | ], |
| 70 | 'directive' => [ |
| 71 | // NASM |
| 72 | 'section', 'segment', 'global', 'extern', 'common', 'static', 'bits', 'default', 'db', 'dw', 'dd', 'dq', 'dt', 'do', 'dy', 'dz', |
| 73 | 'resb', 'resw', 'resd', 'resq', 'rest', 'reso', 'resy', 'resz', 'equ', 'times', 'incbin', 'align', 'alignb', 'struc', 'endstruc', |
| 74 | 'istruc', 'iend', 'at', 'org', 'cpu', 'use16', 'use32', 'use64', 'absolute', 'sectalign', |
| 75 | ], |
| 76 | ]; |
| 77 | |
| 78 | public function prepare(string $code): void { |
| 79 | $tokens = $this->tokens; |
| 80 | // r8〜r15、各サイズ |
| 81 | foreach (self::numbered('r', 8, 15) as $r) array_push($tokens['register'], $r, "{$r}d", "{$r}w", "{$r}b", "{$r}l"); |
| 82 | // 制御・デバッグ・ベクター・マスク・MMX・x87 |
| 83 | foreach ([['cr', 0, 15], ['dr', 0, 15], ['xmm', 0, 31], ['ymm', 0, 31], ['zmm', 0, 31], ['k', 0, 7], ['mm', 0, 7], ['st', 0, 7]] as [$p, $a, $b]) { |
| 84 | foreach (self::numbered($p, $a, $b) as $r) $tokens['register'][] = $r; |
| 85 | } |
| 86 | // 条件付き命令(je, cmovne, setg等) |
| 87 | $cc = ['o', 'no', 'b', 'nb', 'c', 'nc', 'ae', 'nae', 'z', 'nz', 'e', 'ne', 'be', 'nbe', 'a', 'na', 's', 'ns', 'p', 'np', 'pe', 'po', |
| 88 | 'l', 'nl', 'ge', 'nge', 'le', 'nle', 'g', 'ng']; |
| 89 | foreach ($cc as $c) array_push($tokens['instruction'], "j{$c}", "cmov{$c}", "set{$c}"); |
| 90 | $this->words = $this->buildWords($tokens); |
| 91 | } |
| 92 | } |