laag-nasm 2.13.03.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +57 -0
- data/LICENSE.txt +29 -0
- data/README.org +34 -0
- data/ext/laag/nasm/extconf.rb +16 -0
- data/laag-nasm.gemspec +20 -0
- data/lib/laag/nasm.rb +29 -0
- data/patches/Makefile.in.patch +13 -0
- data/vendor/repo.or.cz/nasm/.gitignore +102 -0
- data/vendor/repo.or.cz/nasm/AUTHORS +137 -0
- data/vendor/repo.or.cz/nasm/CHANGES +2 -0
- data/vendor/repo.or.cz/nasm/ChangeLog +2905 -0
- data/vendor/repo.or.cz/nasm/INSTALL +102 -0
- data/vendor/repo.or.cz/nasm/LICENSE +29 -0
- data/vendor/repo.or.cz/nasm/Makefile.in +855 -0
- data/vendor/repo.or.cz/nasm/Mkfiles/README +46 -0
- data/vendor/repo.or.cz/nasm/Mkfiles/msvc.mak +732 -0
- data/vendor/repo.or.cz/nasm/Mkfiles/openwcom.mak +706 -0
- data/vendor/repo.or.cz/nasm/README +23 -0
- data/vendor/repo.or.cz/nasm/SubmittingPatches +116 -0
- data/vendor/repo.or.cz/nasm/TODO +376 -0
- data/vendor/repo.or.cz/nasm/aclocal.m4 +139 -0
- data/vendor/repo.or.cz/nasm/asm/assemble.c +2957 -0
- data/vendor/repo.or.cz/nasm/asm/assemble.h +54 -0
- data/vendor/repo.or.cz/nasm/asm/directiv.c +566 -0
- data/vendor/repo.or.cz/nasm/asm/directiv.dat +92 -0
- data/vendor/repo.or.cz/nasm/asm/error.c +202 -0
- data/vendor/repo.or.cz/nasm/asm/eval.c +1014 -0
- data/vendor/repo.or.cz/nasm/asm/eval.h +49 -0
- data/vendor/repo.or.cz/nasm/asm/exprdump.c +79 -0
- data/vendor/repo.or.cz/nasm/asm/exprlib.c +200 -0
- data/vendor/repo.or.cz/nasm/asm/float.c +952 -0
- data/vendor/repo.or.cz/nasm/asm/float.h +54 -0
- data/vendor/repo.or.cz/nasm/asm/labels.c +540 -0
- data/vendor/repo.or.cz/nasm/asm/listing.c +346 -0
- data/vendor/repo.or.cz/nasm/asm/listing.h +113 -0
- data/vendor/repo.or.cz/nasm/asm/nasm.c +1855 -0
- data/vendor/repo.or.cz/nasm/asm/parser.c +1167 -0
- data/vendor/repo.or.cz/nasm/asm/parser.h +45 -0
- data/vendor/repo.or.cz/nasm/asm/phash.pl +109 -0
- data/vendor/repo.or.cz/nasm/asm/pptok.dat +96 -0
- data/vendor/repo.or.cz/nasm/asm/pptok.pl +271 -0
- data/vendor/repo.or.cz/nasm/asm/pragma.c +218 -0
- data/vendor/repo.or.cz/nasm/asm/preproc-nop.c +188 -0
- data/vendor/repo.or.cz/nasm/asm/preproc.c +5459 -0
- data/vendor/repo.or.cz/nasm/asm/preproc.h +55 -0
- data/vendor/repo.or.cz/nasm/asm/quote.c +479 -0
- data/vendor/repo.or.cz/nasm/asm/quote.h +44 -0
- data/vendor/repo.or.cz/nasm/asm/rdstrnum.c +68 -0
- data/vendor/repo.or.cz/nasm/asm/segalloc.c +51 -0
- data/vendor/repo.or.cz/nasm/asm/stdscan.c +345 -0
- data/vendor/repo.or.cz/nasm/asm/stdscan.h +49 -0
- data/vendor/repo.or.cz/nasm/asm/strfunc.c +359 -0
- data/vendor/repo.or.cz/nasm/asm/tokens.dat +135 -0
- data/vendor/repo.or.cz/nasm/asm/tokhash.pl +284 -0
- data/vendor/repo.or.cz/nasm/autogen.sh +9 -0
- data/vendor/repo.or.cz/nasm/common/common.c +122 -0
- data/vendor/repo.or.cz/nasm/config/msvc.h +192 -0
- data/vendor/repo.or.cz/nasm/config/unknown.h +51 -0
- data/vendor/repo.or.cz/nasm/config/watcom.h +74 -0
- data/vendor/repo.or.cz/nasm/configure.ac +253 -0
- data/vendor/repo.or.cz/nasm/contrib/MSVC6.txt +25 -0
- data/vendor/repo.or.cz/nasm/contrib/VSrules/nasm.README +16 -0
- data/vendor/repo.or.cz/nasm/contrib/VSrules/nasm.rules +79 -0
- data/vendor/repo.or.cz/nasm/disasm/disasm.c +1735 -0
- data/vendor/repo.or.cz/nasm/disasm/disasm.h +49 -0
- data/vendor/repo.or.cz/nasm/disasm/ndisasm.c +397 -0
- data/vendor/repo.or.cz/nasm/disasm/sync.c +132 -0
- data/vendor/repo.or.cz/nasm/disasm/sync.h +45 -0
- data/vendor/repo.or.cz/nasm/doc/Makefile.in +86 -0
- data/vendor/repo.or.cz/nasm/doc/README +20 -0
- data/vendor/repo.or.cz/nasm/doc/afmmetrics.ph +102 -0
- data/vendor/repo.or.cz/nasm/doc/changes.src +2588 -0
- data/vendor/repo.or.cz/nasm/doc/findfont.ph +180 -0
- data/vendor/repo.or.cz/nasm/doc/genps.pl +1294 -0
- data/vendor/repo.or.cz/nasm/doc/inslist.pl +108 -0
- data/vendor/repo.or.cz/nasm/doc/internal.doc +290 -0
- data/vendor/repo.or.cz/nasm/doc/local.css +1 -0
- data/vendor/repo.or.cz/nasm/doc/nasmdoc.css +150 -0
- data/vendor/repo.or.cz/nasm/doc/nasmdoc.src +8309 -0
- data/vendor/repo.or.cz/nasm/doc/nasmlogo.eps +212 -0
- data/vendor/repo.or.cz/nasm/doc/nasmlogw.png +0 -0
- data/vendor/repo.or.cz/nasm/doc/psfonts.ph +53 -0
- data/vendor/repo.or.cz/nasm/doc/pspdf.pl +98 -0
- data/vendor/repo.or.cz/nasm/doc/pswidth.ph +25 -0
- data/vendor/repo.or.cz/nasm/doc/rdsrc.pl +1111 -0
- data/vendor/repo.or.cz/nasm/doc/ttfmetrics.ph +63 -0
- data/vendor/repo.or.cz/nasm/headers/c +33 -0
- data/vendor/repo.or.cz/nasm/headers/doc +33 -0
- data/vendor/repo.or.cz/nasm/headers/mac +33 -0
- data/vendor/repo.or.cz/nasm/headers/perl +33 -0
- data/vendor/repo.or.cz/nasm/include/compiler.h +277 -0
- data/vendor/repo.or.cz/nasm/include/disp8.h +45 -0
- data/vendor/repo.or.cz/nasm/include/error.h +135 -0
- data/vendor/repo.or.cz/nasm/include/hashtbl.h +85 -0
- data/vendor/repo.or.cz/nasm/include/iflag.h +173 -0
- data/vendor/repo.or.cz/nasm/include/insns.h +76 -0
- data/vendor/repo.or.cz/nasm/include/labels.h +60 -0
- data/vendor/repo.or.cz/nasm/include/md5.h +21 -0
- data/vendor/repo.or.cz/nasm/include/nasm.h +1246 -0
- data/vendor/repo.or.cz/nasm/include/nasmint.h +219 -0
- data/vendor/repo.or.cz/nasm/include/nasmlib.h +524 -0
- data/vendor/repo.or.cz/nasm/include/opflags.h +271 -0
- data/vendor/repo.or.cz/nasm/include/perfhash.h +52 -0
- data/vendor/repo.or.cz/nasm/include/raa.h +46 -0
- data/vendor/repo.or.cz/nasm/include/rbtree.h +51 -0
- data/vendor/repo.or.cz/nasm/include/rdoff.h +169 -0
- data/vendor/repo.or.cz/nasm/include/saa.h +94 -0
- data/vendor/repo.or.cz/nasm/include/strlist.h +55 -0
- data/vendor/repo.or.cz/nasm/include/tables.h +70 -0
- data/vendor/repo.or.cz/nasm/include/ver.h +47 -0
- data/vendor/repo.or.cz/nasm/install-sh +250 -0
- data/vendor/repo.or.cz/nasm/macros/altreg.mac +107 -0
- data/vendor/repo.or.cz/nasm/macros/fp.mac +54 -0
- data/vendor/repo.or.cz/nasm/macros/ifunc.mac +48 -0
- data/vendor/repo.or.cz/nasm/macros/macros.pl +294 -0
- data/vendor/repo.or.cz/nasm/macros/smartalign.mac +189 -0
- data/vendor/repo.or.cz/nasm/macros/standard.mac +226 -0
- data/vendor/repo.or.cz/nasm/misc/Doxyfile +752 -0
- data/vendor/repo.or.cz/nasm/misc/Nindent +18 -0
- data/vendor/repo.or.cz/nasm/misc/README +2 -0
- data/vendor/repo.or.cz/nasm/misc/c16.mac +82 -0
- data/vendor/repo.or.cz/nasm/misc/c32.mac +52 -0
- data/vendor/repo.or.cz/nasm/misc/crcgen.c +44 -0
- data/vendor/repo.or.cz/nasm/misc/exebin.mac +57 -0
- data/vendor/repo.or.cz/nasm/misc/exebin2.mac +114 -0
- data/vendor/repo.or.cz/nasm/misc/fmtinsns.pl +40 -0
- data/vendor/repo.or.cz/nasm/misc/genfma.pl +63 -0
- data/vendor/repo.or.cz/nasm/misc/hints.txt +26 -0
- data/vendor/repo.or.cz/nasm/misc/magic +6 -0
- data/vendor/repo.or.cz/nasm/misc/myC32.mac +121 -0
- data/vendor/repo.or.cz/nasm/misc/nasm.sl +320 -0
- data/vendor/repo.or.cz/nasm/misc/nasmstab +296 -0
- data/vendor/repo.or.cz/nasm/misc/omfdump.c +517 -0
- data/vendor/repo.or.cz/nasm/misc/pmw.bat +9 -0
- data/vendor/repo.or.cz/nasm/misc/proc32.ash +441 -0
- data/vendor/repo.or.cz/nasm/misc/scitech.mac +1223 -0
- data/vendor/repo.or.cz/nasm/misc/xcrcgen.c +80 -0
- data/vendor/repo.or.cz/nasm/nasm.spec.in +83 -0
- data/vendor/repo.or.cz/nasm/nasm.spec.sed +3 -0
- data/vendor/repo.or.cz/nasm/nasm.txt +306 -0
- data/vendor/repo.or.cz/nasm/nasmlib/badenum.c +43 -0
- data/vendor/repo.or.cz/nasm/nasmlib/bsi.c +77 -0
- data/vendor/repo.or.cz/nasm/nasmlib/crc64.c +189 -0
- data/vendor/repo.or.cz/nasm/nasmlib/file.c +259 -0
- data/vendor/repo.or.cz/nasm/nasmlib/file.h +128 -0
- data/vendor/repo.or.cz/nasm/nasmlib/filename.c +69 -0
- data/vendor/repo.or.cz/nasm/nasmlib/hashtbl.c +232 -0
- data/vendor/repo.or.cz/nasm/nasmlib/ilog2.c +168 -0
- data/vendor/repo.or.cz/nasm/nasmlib/malloc.c +108 -0
- data/vendor/repo.or.cz/nasm/nasmlib/md5c.c +247 -0
- data/vendor/repo.or.cz/nasm/nasmlib/mmap.c +139 -0
- data/vendor/repo.or.cz/nasm/nasmlib/path.c +186 -0
- data/vendor/repo.or.cz/nasm/nasmlib/perfhash.c +55 -0
- data/vendor/repo.or.cz/nasm/nasmlib/perfhash.pl +362 -0
- data/vendor/repo.or.cz/nasm/nasmlib/raa.c +173 -0
- data/vendor/repo.or.cz/nasm/nasmlib/rbtree.c +119 -0
- data/vendor/repo.or.cz/nasm/nasmlib/readnum.c +172 -0
- data/vendor/repo.or.cz/nasm/nasmlib/realpath.c +135 -0
- data/vendor/repo.or.cz/nasm/nasmlib/saa.c +431 -0
- data/vendor/repo.or.cz/nasm/nasmlib/srcfile.c +128 -0
- data/vendor/repo.or.cz/nasm/nasmlib/string.c +242 -0
- data/vendor/repo.or.cz/nasm/nasmlib/strlist.c +100 -0
- data/vendor/repo.or.cz/nasm/nasmlib/ver.c +51 -0
- data/vendor/repo.or.cz/nasm/nasmlib/zerobuf.c +42 -0
- data/vendor/repo.or.cz/nasm/ndisasm.txt +94 -0
- data/vendor/repo.or.cz/nasm/nsis/NASMMultiUser.nsh +478 -0
- data/vendor/repo.or.cz/nasm/nsis/getpearch.pl +76 -0
- data/vendor/repo.or.cz/nasm/nsis/nasm-un.ico +0 -0
- data/vendor/repo.or.cz/nasm/nsis/nasm.ico +0 -0
- data/vendor/repo.or.cz/nasm/nsis/nasm.nsi +241 -0
- data/vendor/repo.or.cz/nasm/output/codeview.c +814 -0
- data/vendor/repo.or.cz/nasm/output/dwarf.h +566 -0
- data/vendor/repo.or.cz/nasm/output/elf.h +537 -0
- data/vendor/repo.or.cz/nasm/output/legacy.c +112 -0
- data/vendor/repo.or.cz/nasm/output/nulldbg.c +93 -0
- data/vendor/repo.or.cz/nasm/output/nullout.c +51 -0
- data/vendor/repo.or.cz/nasm/output/outaout.c +954 -0
- data/vendor/repo.or.cz/nasm/output/outaout.mac +37 -0
- data/vendor/repo.or.cz/nasm/output/outas86.c +650 -0
- data/vendor/repo.or.cz/nasm/output/outas86.mac +37 -0
- data/vendor/repo.or.cz/nasm/output/outbin.c +1713 -0
- data/vendor/repo.or.cz/nasm/output/outbin.mac +40 -0
- data/vendor/repo.or.cz/nasm/output/outcoff.c +1242 -0
- data/vendor/repo.or.cz/nasm/output/outcoff.mac +43 -0
- data/vendor/repo.or.cz/nasm/output/outdbg.c +425 -0
- data/vendor/repo.or.cz/nasm/output/outelf.c +3370 -0
- data/vendor/repo.or.cz/nasm/output/outelf.h +156 -0
- data/vendor/repo.or.cz/nasm/output/outelf.mac +41 -0
- data/vendor/repo.or.cz/nasm/output/outform.c +120 -0
- data/vendor/repo.or.cz/nasm/output/outform.h +379 -0
- data/vendor/repo.or.cz/nasm/output/outieee.c +1528 -0
- data/vendor/repo.or.cz/nasm/output/outlib.c +58 -0
- data/vendor/repo.or.cz/nasm/output/outlib.h +63 -0
- data/vendor/repo.or.cz/nasm/output/outmacho.c +2387 -0
- data/vendor/repo.or.cz/nasm/output/outmacho.mac +49 -0
- data/vendor/repo.or.cz/nasm/output/outobj.c +2725 -0
- data/vendor/repo.or.cz/nasm/output/outobj.mac +49 -0
- data/vendor/repo.or.cz/nasm/output/outrdf.mac +40 -0
- data/vendor/repo.or.cz/nasm/output/outrdf2.c +791 -0
- data/vendor/repo.or.cz/nasm/output/outrdf2.mac +43 -0
- data/vendor/repo.or.cz/nasm/output/pecoff.h +532 -0
- data/vendor/repo.or.cz/nasm/output/stabs.h +144 -0
- data/vendor/repo.or.cz/nasm/perllib/crc64.ph +158 -0
- data/vendor/repo.or.cz/nasm/perllib/gensv.pl +34 -0
- data/vendor/repo.or.cz/nasm/perllib/phash.ph +200 -0
- data/vendor/repo.or.cz/nasm/perllib/random_sv_vectors.ph +67 -0
- data/vendor/repo.or.cz/nasm/rdoff/README +185 -0
- data/vendor/repo.or.cz/nasm/rdoff/collectn.c +44 -0
- data/vendor/repo.or.cz/nasm/rdoff/collectn.h +22 -0
- data/vendor/repo.or.cz/nasm/rdoff/doc/Makefile +37 -0
- data/vendor/repo.or.cz/nasm/rdoff/doc/rdoff.texi +137 -0
- data/vendor/repo.or.cz/nasm/rdoff/doc/v1-v2.txt +62 -0
- data/vendor/repo.or.cz/nasm/rdoff/hash.c +122 -0
- data/vendor/repo.or.cz/nasm/rdoff/hash.h +17 -0
- data/vendor/repo.or.cz/nasm/rdoff/ldrdf.1 +41 -0
- data/vendor/repo.or.cz/nasm/rdoff/ldrdf.c +1395 -0
- data/vendor/repo.or.cz/nasm/rdoff/ldsegs.h +59 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdf2bin.1 +65 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdf2bin.c +431 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdf2com.1 +1 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdf2ihx.1 +1 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdf2ith.1 +1 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdf2srec.1 +1 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdfdump.1 +24 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdfdump.c +347 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdflib.1 +39 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdflib.c +434 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdfload.c +213 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdfload.h +29 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdfutils.h +165 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdlar.c +492 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdlar.h +34 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdlib.c +290 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdlib.h +62 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdoff.c +621 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdx.1 +21 -0
- data/vendor/repo.or.cz/nasm/rdoff/rdx.c +90 -0
- data/vendor/repo.or.cz/nasm/rdoff/segtab.c +172 -0
- data/vendor/repo.or.cz/nasm/rdoff/segtab.h +45 -0
- data/vendor/repo.or.cz/nasm/rdoff/symtab.c +159 -0
- data/vendor/repo.or.cz/nasm/rdoff/symtab.h +55 -0
- data/vendor/repo.or.cz/nasm/rdoff/test/Makefile +10 -0
- data/vendor/repo.or.cz/nasm/rdoff/test/makelib.sh +14 -0
- data/vendor/repo.or.cz/nasm/rdoff/test/rdfseg.asm +20 -0
- data/vendor/repo.or.cz/nasm/rdoff/test/rdfseg2.asm +12 -0
- data/vendor/repo.or.cz/nasm/rdoff/test/rdftest1.asm +54 -0
- data/vendor/repo.or.cz/nasm/rdoff/test/rdftest2.asm +33 -0
- data/vendor/repo.or.cz/nasm/rdoff/test/rdtlib.asm +48 -0
- data/vendor/repo.or.cz/nasm/rdoff/test/rdtmain.asm +47 -0
- data/vendor/repo.or.cz/nasm/rdoff/test/testlib.asm +18 -0
- data/vendor/repo.or.cz/nasm/stdlib/snprintf.c +29 -0
- data/vendor/repo.or.cz/nasm/stdlib/strlcpy.c +51 -0
- data/vendor/repo.or.cz/nasm/stdlib/strnlen.c +46 -0
- data/vendor/repo.or.cz/nasm/stdlib/vsnprintf.c +51 -0
- data/vendor/repo.or.cz/nasm/test/Makefile +106 -0
- data/vendor/repo.or.cz/nasm/test/_file_.asm +5 -0
- data/vendor/repo.or.cz/nasm/test/_version.asm +2 -0
- data/vendor/repo.or.cz/nasm/test/a32offs.asm +9 -0
- data/vendor/repo.or.cz/nasm/test/absolute.asm +40 -0
- data/vendor/repo.or.cz/nasm/test/addr64x.asm +18 -0
- data/vendor/repo.or.cz/nasm/test/align13.asm +19 -0
- data/vendor/repo.or.cz/nasm/test/align13s.asm +20 -0
- data/vendor/repo.or.cz/nasm/test/alonesym-obj.asm +166 -0
- data/vendor/repo.or.cz/nasm/test/andbyte.asm +15 -0
- data/vendor/repo.or.cz/nasm/test/aoutso.asm +99 -0
- data/vendor/repo.or.cz/nasm/test/aouttest.asm +86 -0
- data/vendor/repo.or.cz/nasm/test/aouttest.c +36 -0
- data/vendor/repo.or.cz/nasm/test/avx.asm +46 -0
- data/vendor/repo.or.cz/nasm/test/avx005.asm +529 -0
- data/vendor/repo.or.cz/nasm/test/avx2.asm +1608 -0
- data/vendor/repo.or.cz/nasm/test/avx512cd.asm +106 -0
- data/vendor/repo.or.cz/nasm/test/avx512er.asm +144 -0
- data/vendor/repo.or.cz/nasm/test/avx512f.asm +7000 -0
- data/vendor/repo.or.cz/nasm/test/avx512pf.asm +88 -0
- data/vendor/repo.or.cz/nasm/test/bcd.asm +23 -0
- data/vendor/repo.or.cz/nasm/test/binexe.asm +35 -0
- data/vendor/repo.or.cz/nasm/test/bintest.asm +59 -0
- data/vendor/repo.or.cz/nasm/test/bisect.sh +22 -0
- data/vendor/repo.or.cz/nasm/test/br1879590.asm +25 -0
- data/vendor/repo.or.cz/nasm/test/br2003451.asm +17 -0
- data/vendor/repo.or.cz/nasm/test/br2030823.asm +7 -0
- data/vendor/repo.or.cz/nasm/test/br2148476.asm +221 -0
- data/vendor/repo.or.cz/nasm/test/br2222615.asm +19 -0
- data/vendor/repo.or.cz/nasm/test/br2496848.asm +42 -0
- data/vendor/repo.or.cz/nasm/test/br3005117.asm +26 -0
- data/vendor/repo.or.cz/nasm/test/br3026808.asm +20 -0
- data/vendor/repo.or.cz/nasm/test/br3028880.asm +8 -0
- data/vendor/repo.or.cz/nasm/test/br3041451.asm +59 -0
- data/vendor/repo.or.cz/nasm/test/br3058845.asm +14 -0
- data/vendor/repo.or.cz/nasm/test/br3066383.asm +70 -0
- data/vendor/repo.or.cz/nasm/test/br3074517.asm +12 -0
- data/vendor/repo.or.cz/nasm/test/br3092924.asm +25 -0
- data/vendor/repo.or.cz/nasm/test/br3104312.asm +11 -0
- data/vendor/repo.or.cz/nasm/test/br3109604.asm +9 -0
- data/vendor/repo.or.cz/nasm/test/br3174983.asm +9 -0
- data/vendor/repo.or.cz/nasm/test/br3187743.asm +7 -0
- data/vendor/repo.or.cz/nasm/test/br3189064.asm +7 -0
- data/vendor/repo.or.cz/nasm/test/br3200749.asm +9 -0
- data/vendor/repo.or.cz/nasm/test/br3385573.asm +11 -0
- data/vendor/repo.or.cz/nasm/test/br3392252.asm +43 -0
- data/vendor/repo.or.cz/nasm/test/br3392259.asm +8 -0
- data/vendor/repo.or.cz/nasm/test/br3392363.asm +4 -0
- data/vendor/repo.or.cz/nasm/test/br3392392.asm +16 -0
- data/vendor/repo.or.cz/nasm/test/br3392396.asm +5 -0
- data/vendor/repo.or.cz/nasm/test/br3392411.asm +22 -0
- data/vendor/repo.or.cz/nasm/test/br3392418.asm +3 -0
- data/vendor/repo.or.cz/nasm/test/br3392439.asm +25 -0
- data/vendor/repo.or.cz/nasm/test/br3392442.asm +6 -0
- data/vendor/repo.or.cz/nasm/test/br560575.asm +17 -0
- data/vendor/repo.or.cz/nasm/test/br560873.asm +27 -0
- data/vendor/repo.or.cz/nasm/test/br890790.asm +7 -0
- data/vendor/repo.or.cz/nasm/test/br890790_i.asm +1 -0
- data/vendor/repo.or.cz/nasm/test/br978756.asm +7 -0
- data/vendor/repo.or.cz/nasm/test/changed.asm +383 -0
- data/vendor/repo.or.cz/nasm/test/cofftest.asm +85 -0
- data/vendor/repo.or.cz/nasm/test/cofftest.c +35 -0
- data/vendor/repo.or.cz/nasm/test/crc32.asm +37 -0
- data/vendor/repo.or.cz/nasm/test/cv8struc.asm +14 -0
- data/vendor/repo.or.cz/nasm/test/dtbcd.asm +72 -0
- data/vendor/repo.or.cz/nasm/test/elf64so.asm +118 -0
- data/vendor/repo.or.cz/nasm/test/elfso.asm +100 -0
- data/vendor/repo.or.cz/nasm/test/elftest.asm +87 -0
- data/vendor/repo.or.cz/nasm/test/elftest.c +38 -0
- data/vendor/repo.or.cz/nasm/test/elftest64.c +43 -0
- data/vendor/repo.or.cz/nasm/test/elif.asm +39 -0
- data/vendor/repo.or.cz/nasm/test/expimp.asm +90 -0
- data/vendor/repo.or.cz/nasm/test/far64.asm +10 -0
- data/vendor/repo.or.cz/nasm/test/float.asm +186 -0
- data/vendor/repo.or.cz/nasm/test/float8.asm +135 -0
- data/vendor/repo.or.cz/nasm/test/floatb.asm +35 -0
- data/vendor/repo.or.cz/nasm/test/floatexp.asm +382 -0
- data/vendor/repo.or.cz/nasm/test/floatize.asm +19 -0
- data/vendor/repo.or.cz/nasm/test/floattest.asm +28 -0
- data/vendor/repo.or.cz/nasm/test/floatx.asm +525 -0
- data/vendor/repo.or.cz/nasm/test/fpu.asm +127 -0
- data/vendor/repo.or.cz/nasm/test/fwdopt.asm +133 -0
- data/vendor/repo.or.cz/nasm/test/fwdoptpp.asm +150 -0
- data/vendor/repo.or.cz/nasm/test/gas2nasm.py +104 -0
- data/vendor/repo.or.cz/nasm/test/gather.asm +11 -0
- data/vendor/repo.or.cz/nasm/test/gotoff64.asm +25 -0
- data/vendor/repo.or.cz/nasm/test/hexfp.asm +25 -0
- data/vendor/repo.or.cz/nasm/test/hle.asm +19 -0
- data/vendor/repo.or.cz/nasm/test/ifelse.asm +46 -0
- data/vendor/repo.or.cz/nasm/test/ifenv.asm +31 -0
- data/vendor/repo.or.cz/nasm/test/ifmacro.asm +413 -0
- data/vendor/repo.or.cz/nasm/test/iftoken.asm +317 -0
- data/vendor/repo.or.cz/nasm/test/iftoken.pl +32 -0
- data/vendor/repo.or.cz/nasm/test/ilog2.asm +271 -0
- data/vendor/repo.or.cz/nasm/test/imacro.asm +8 -0
- data/vendor/repo.or.cz/nasm/test/imm.asm +23 -0
- data/vendor/repo.or.cz/nasm/test/imm64.asm +61 -0
- data/vendor/repo.or.cz/nasm/test/immwarn.asm +91 -0
- data/vendor/repo.or.cz/nasm/test/imul.asm +117 -0
- data/vendor/repo.or.cz/nasm/test/inc1.asm +6 -0
- data/vendor/repo.or.cz/nasm/test/inc2.asm +8 -0
- data/vendor/repo.or.cz/nasm/test/incbin.asm +7 -0
- data/vendor/repo.or.cz/nasm/test/incbin.data +2 -0
- data/vendor/repo.or.cz/nasm/test/inctest.asm +15 -0
- data/vendor/repo.or.cz/nasm/test/insnlbl.asm +12 -0
- data/vendor/repo.or.cz/nasm/test/invlpga.asm +11 -0
- data/vendor/repo.or.cz/nasm/test/jmp64.asm +19 -0
- data/vendor/repo.or.cz/nasm/test/lar_lsl.asm +124 -0
- data/vendor/repo.or.cz/nasm/test/larlsl.asm +23 -0
- data/vendor/repo.or.cz/nasm/test/lnxhello.asm +54 -0
- data/vendor/repo.or.cz/nasm/test/local.asm +19 -0
- data/vendor/repo.or.cz/nasm/test/loopoffs.asm +12 -0
- data/vendor/repo.or.cz/nasm/test/lwp.asm +213 -0
- data/vendor/repo.or.cz/nasm/test/macro-defaults.asm +64 -0
- data/vendor/repo.or.cz/nasm/test/macroerr.asm +12 -0
- data/vendor/repo.or.cz/nasm/test/macroerr.inc +3 -0
- data/vendor/repo.or.cz/nasm/test/mmxsize.asm +38 -0
- data/vendor/repo.or.cz/nasm/test/movd.asm +12 -0
- data/vendor/repo.or.cz/nasm/test/movd64.asm +15 -0
- data/vendor/repo.or.cz/nasm/test/movimm.asm +28 -0
- data/vendor/repo.or.cz/nasm/test/movnti.asm +10 -0
- data/vendor/repo.or.cz/nasm/test/mpx-64.asm +120 -0
- data/vendor/repo.or.cz/nasm/test/mpx.asm +89 -0
- data/vendor/repo.or.cz/nasm/test/multisection.asm +96 -0
- data/vendor/repo.or.cz/nasm/test/nasmformat.asm +17 -0
- data/vendor/repo.or.cz/nasm/test/new +9 -0
- data/vendor/repo.or.cz/nasm/test/newrdwr.asm +24 -0
- data/vendor/repo.or.cz/nasm/test/nop.asm +17 -0
- data/vendor/repo.or.cz/nasm/test/nullfile.asm +4 -0
- data/vendor/repo.or.cz/nasm/test/objexe.asm +30 -0
- data/vendor/repo.or.cz/nasm/test/objlink.c +33 -0
- data/vendor/repo.or.cz/nasm/test/objtest.asm +85 -0
- data/vendor/repo.or.cz/nasm/test/optimization.asm +104 -0
- data/vendor/repo.or.cz/nasm/test/org.asm +18 -0
- data/vendor/repo.or.cz/nasm/test/paste.asm +12 -0
- data/vendor/repo.or.cz/nasm/test/pcrel.asm +52 -0
- data/vendor/repo.or.cz/nasm/test/perf/label.pl +18 -0
- data/vendor/repo.or.cz/nasm/test/perf/macro.pl +18 -0
- data/vendor/repo.or.cz/nasm/test/perf/token.pl +23 -0
- data/vendor/repo.or.cz/nasm/test/performtest.pl +192 -0
- data/vendor/repo.or.cz/nasm/test/pextrw.asm +3 -0
- data/vendor/repo.or.cz/nasm/test/pinsr16.asm +53 -0
- data/vendor/repo.or.cz/nasm/test/pinsr32.asm +53 -0
- data/vendor/repo.or.cz/nasm/test/pinsr64.asm +68 -0
- data/vendor/repo.or.cz/nasm/test/popcnt.asm +32 -0
- data/vendor/repo.or.cz/nasm/test/ppindirect.asm +42 -0
- data/vendor/repo.or.cz/nasm/test/pragma.asm +12 -0
- data/vendor/repo.or.cz/nasm/test/prefix66.asm +28 -0
- data/vendor/repo.or.cz/nasm/test/ptr.asm +4 -0
- data/vendor/repo.or.cz/nasm/test/pushseg.asm +17 -0
- data/vendor/repo.or.cz/nasm/test/r13.asm +15 -0
- data/vendor/repo.or.cz/nasm/test/radix.asm +54 -0
- data/vendor/repo.or.cz/nasm/test/rdpid.asm +21 -0
- data/vendor/repo.or.cz/nasm/test/reldef.asm +57 -0
- data/vendor/repo.or.cz/nasm/test/relocs.asm +20 -0
- data/vendor/repo.or.cz/nasm/test/riprel.asm +5357 -0
- data/vendor/repo.or.cz/nasm/test/riprel.pl +29 -0
- data/vendor/repo.or.cz/nasm/test/riprel2.asm +11 -0
- data/vendor/repo.or.cz/nasm/test/sha-64.asm +30 -0
- data/vendor/repo.or.cz/nasm/test/sha.asm +31 -0
- data/vendor/repo.or.cz/nasm/test/smartalign16.asm +36 -0
- data/vendor/repo.or.cz/nasm/test/smartalign32.asm +36 -0
- data/vendor/repo.or.cz/nasm/test/smartalign64.asm +36 -0
- data/vendor/repo.or.cz/nasm/test/splitea.asm +11 -0
- data/vendor/repo.or.cz/nasm/test/sreg.asm +65 -0
- data/vendor/repo.or.cz/nasm/test/strlen.asm +5 -0
- data/vendor/repo.or.cz/nasm/test/struc.asm +33 -0
- data/vendor/repo.or.cz/nasm/test/test67.asm +38 -0
- data/vendor/repo.or.cz/nasm/test/testdos.asm +13 -0
- data/vendor/repo.or.cz/nasm/test/testnos3.asm +973 -0
- data/vendor/repo.or.cz/nasm/test/time.asm +11 -0
- data/vendor/repo.or.cz/nasm/test/times.asm +21 -0
- data/vendor/repo.or.cz/nasm/test/timesneg.asm +3 -0
- data/vendor/repo.or.cz/nasm/test/tmap.nas +1447 -0
- data/vendor/repo.or.cz/nasm/test/uscore.asm +15 -0
- data/vendor/repo.or.cz/nasm/test/utf.asm +82 -0
- data/vendor/repo.or.cz/nasm/test/vaesenc.asm +22 -0
- data/vendor/repo.or.cz/nasm/test/vex.asm +9 -0
- data/vendor/repo.or.cz/nasm/test/vgather.asm +76 -0
- data/vendor/repo.or.cz/nasm/test/vmread.asm +26 -0
- data/vendor/repo.or.cz/nasm/test/weirdpaste.asm +29 -0
- data/vendor/repo.or.cz/nasm/test/xchg.asm +96 -0
- data/vendor/repo.or.cz/nasm/test/xcrypt.asm +24 -0
- data/vendor/repo.or.cz/nasm/test/xmm0.asm +12 -0
- data/vendor/repo.or.cz/nasm/test/zerobyte.asm +22 -0
- data/vendor/repo.or.cz/nasm/tools/cleanfile +176 -0
- data/vendor/repo.or.cz/nasm/tools/cleanpatch +258 -0
- data/vendor/repo.or.cz/nasm/tools/mkdep.pl +261 -0
- data/vendor/repo.or.cz/nasm/tools/release +105 -0
- data/vendor/repo.or.cz/nasm/tools/syncfiles.pl +137 -0
- data/vendor/repo.or.cz/nasm/tools/tag-release +58 -0
- data/vendor/repo.or.cz/nasm/version +1 -0
- data/vendor/repo.or.cz/nasm/version.pl +189 -0
- data/vendor/repo.or.cz/nasm/x86/disp8.c +131 -0
- data/vendor/repo.or.cz/nasm/x86/insns-iflags.ph +280 -0
- data/vendor/repo.or.cz/nasm/x86/insns.dat +5371 -0
- data/vendor/repo.or.cz/nasm/x86/insns.pl +1043 -0
- data/vendor/repo.or.cz/nasm/x86/regs.dat +138 -0
- data/vendor/repo.or.cz/nasm/x86/regs.pl +204 -0
- metadata +520 -0
@@ -0,0 +1,139 @@
|
|
1
|
+
dnl --------------------------------------------------------------------------
|
2
|
+
dnl PA_ADD_CFLAGS()
|
3
|
+
dnl
|
4
|
+
dnl Attempt to add the given option to CFLAGS, if it doesn't break compilation
|
5
|
+
dnl --------------------------------------------------------------------------
|
6
|
+
AC_DEFUN(PA_ADD_CFLAGS,
|
7
|
+
[AC_MSG_CHECKING([if $CC accepts $1])
|
8
|
+
pa_add_cflags__old_cflags="$CFLAGS"
|
9
|
+
CFLAGS="$CFLAGS $1"
|
10
|
+
AC_TRY_LINK(AC_INCLUDES_DEFAULT,
|
11
|
+
[printf("Hello, World!\n");],
|
12
|
+
[AC_MSG_RESULT([yes])
|
13
|
+
CFLAGS="$pa_add_cflags__old_cflags ifelse([$2],[],[$1],[$2])"],
|
14
|
+
[AC_MSG_RESULT([no])
|
15
|
+
CFLAGS="$pa_add_cflags__old_cflags"])])
|
16
|
+
|
17
|
+
dnl --------------------------------------------------------------------------
|
18
|
+
dnl PA_ADD_CLDFLAGS()
|
19
|
+
dnl
|
20
|
+
dnl Attempt to add the given option to CFLAGS and LDFLAGS,
|
21
|
+
dnl if it doesn't break compilation
|
22
|
+
dnl --------------------------------------------------------------------------
|
23
|
+
AC_DEFUN(PA_ADD_CLDFLAGS,
|
24
|
+
[AC_MSG_CHECKING([if $CC accepts $1])
|
25
|
+
pa_add_cldflags__old_cflags="$CFLAGS"
|
26
|
+
CFLAGS="$CFLAGS $1"
|
27
|
+
pa_add_cldflags__old_ldflags="$LDFLAGS"
|
28
|
+
LDFLAGS="$LDFLAGS $1"
|
29
|
+
AC_TRY_LINK(AC_INCLUDES_DEFAULT,
|
30
|
+
[printf("Hello, World!\n");],
|
31
|
+
[AC_MSG_RESULT([yes])
|
32
|
+
CFLAGS="$pa_add_cldflags__old_cflags ifelse([$2],[],[$1],[$2])"
|
33
|
+
LDFLAGS="$pa_add_cldflags__old_ldflags ifelse([$2],[],[$1],[$2])"],
|
34
|
+
[AC_MSG_RESULT([no])
|
35
|
+
CFLAGS="$pa_add_cldflags__old_cflags"
|
36
|
+
LDFLAGS="$pa_add_cldflags__old_ldflags"])])
|
37
|
+
|
38
|
+
dnl --------------------------------------------------------------------------
|
39
|
+
dnl PA_HAVE_FUNC
|
40
|
+
dnl
|
41
|
+
dnl Look for a function with the specified arguments which could be
|
42
|
+
dnl a builtin/intrinsic function.
|
43
|
+
dnl --------------------------------------------------------------------------
|
44
|
+
AC_DEFUN(PA_HAVE_FUNC,
|
45
|
+
[AC_MSG_CHECKING([for $1])
|
46
|
+
AC_TRY_LINK([], [(void)$1$2;],
|
47
|
+
AC_MSG_RESULT([yes])
|
48
|
+
AC_DEFINE(m4_toupper([HAVE_$1]), [1],
|
49
|
+
[Define to 1 if you have the `$1' intrinsic function.]),
|
50
|
+
AC_MSG_RESULT([no]))])
|
51
|
+
|
52
|
+
dnl --------------------------------------------------------------------------
|
53
|
+
dnl PA_LIBEXT
|
54
|
+
dnl
|
55
|
+
dnl Guess the library extension based on the object extension
|
56
|
+
dnl --------------------------------------------------------------------------
|
57
|
+
AC_DEFUN(PA_LIBEXT,
|
58
|
+
[AC_MSG_CHECKING([for suffix of library files])
|
59
|
+
if test x"$LIBEXT" = x; then
|
60
|
+
case "$OBJEXT" in
|
61
|
+
obj )
|
62
|
+
LIBEXT=lib
|
63
|
+
;;
|
64
|
+
*)
|
65
|
+
LIBEXT=a
|
66
|
+
;;
|
67
|
+
esac
|
68
|
+
fi
|
69
|
+
AC_MSG_RESULT([$LIBEXT])
|
70
|
+
AC_SUBST([LIBEXT])])
|
71
|
+
|
72
|
+
dnl --------------------------------------------------------------------------
|
73
|
+
dnl PA_FUNC_ATTRIBUTE
|
74
|
+
dnl
|
75
|
+
dnl See if this compiler supports the equivalent of a specific gcc
|
76
|
+
dnl attribute on a function, using the __attribute__(()) syntax.
|
77
|
+
dnl All arguments except the attribute name are optional.
|
78
|
+
dnl PA_FUNC_ATTRIBUTE(attribute, attribute_opts, return_type,
|
79
|
+
dnl prototype_args, call_args)
|
80
|
+
dnl --------------------------------------------------------------------------
|
81
|
+
AC_DEFUN(PA_FUNC_ATTRIBUTE,
|
82
|
+
[AC_MSG_CHECKING([if $CC supports the $1 function attribute])
|
83
|
+
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
|
84
|
+
#include <stdarg.h>
|
85
|
+
extern ifelse([$3],[],[void *],[$3]) __attribute__(($1$2))
|
86
|
+
bar(ifelse([$4],[],[int],[$4]));
|
87
|
+
void *foo(void);
|
88
|
+
void *foo(void)
|
89
|
+
{
|
90
|
+
return bar(ifelse([$5],[],[1],[$5]));
|
91
|
+
}
|
92
|
+
])],
|
93
|
+
[AC_MSG_RESULT([yes])
|
94
|
+
AC_DEFINE(m4_toupper([HAVE_FUNC_ATTRIBUTE_$1]), 1,
|
95
|
+
[Define to 1 if your compiler supports __attribute__(($1)) on functions])],
|
96
|
+
[AC_MSG_RESULT([no])])
|
97
|
+
])
|
98
|
+
|
99
|
+
dnl --------------------------------------------------------------------------
|
100
|
+
dnl PA_FUNC_ATTRIBUTE_ERROR
|
101
|
+
dnl
|
102
|
+
dnl See if this compiler supports __attribute__((error("foo")))
|
103
|
+
dnl The generic version of this doesn't work as it makes the compiler
|
104
|
+
dnl throw an error by design.
|
105
|
+
dnl --------------------------------------------------------------------------
|
106
|
+
AC_DEFUN(PA_FUNC_ATTRIBUTE_ERROR,
|
107
|
+
[AC_MSG_CHECKING([if $CC supports the error function attribute])
|
108
|
+
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
|
109
|
+
#include <stdarg.h>
|
110
|
+
extern void __attribute__((error("message"))) barf(void);
|
111
|
+
void foo(void);
|
112
|
+
void foo(void)
|
113
|
+
{
|
114
|
+
if (0)
|
115
|
+
barf();
|
116
|
+
}
|
117
|
+
])],
|
118
|
+
[AC_MSG_RESULT([yes])
|
119
|
+
AC_DEFINE(m4_toupper([HAVE_FUNC_ATTRIBUTE_ERROR]), 1,
|
120
|
+
[Define to 1 if your compiler supports __attribute__((error)) on functions])],
|
121
|
+
[AC_MSG_RESULT([no])])
|
122
|
+
])
|
123
|
+
|
124
|
+
dnl --------------------------------------------------------------------------
|
125
|
+
dnl PA_ARG_ENABLED
|
126
|
+
dnl PA_ARG_DISABLED
|
127
|
+
dnl
|
128
|
+
dnl Simpler-to-use versions of AC_ARG_ENABLED, that include the
|
129
|
+
dnl test for $enableval and the AS_HELP_STRING definition
|
130
|
+
dnl --------------------------------------------------------------------------
|
131
|
+
AC_DEFUN(PA_ARG_ENABLED,
|
132
|
+
[AC_ARG_ENABLE([$1], [AS_HELP_STRING([--enable-$1],[$2])], [], [enableval=no])
|
133
|
+
AS_IF([test x"$enableval" != xno], [$3], [$4])
|
134
|
+
])
|
135
|
+
|
136
|
+
AC_DEFUN(PA_ARG_DISABLED,
|
137
|
+
[AC_ARG_ENABLE([$1],[AS_HELP_STRING([--disable-$1],[$2])], [], [enableval=yes])
|
138
|
+
AS_IF([test x"$enableval" = xno], [$3], [$4])
|
139
|
+
])
|
@@ -0,0 +1,2957 @@
|
|
1
|
+
/* ----------------------------------------------------------------------- *
|
2
|
+
*
|
3
|
+
* Copyright 1996-2018 The NASM Authors - All Rights Reserved
|
4
|
+
* See the file AUTHORS included with the NASM distribution for
|
5
|
+
* the specific copyright holders.
|
6
|
+
*
|
7
|
+
* Redistribution and use in source and binary forms, with or without
|
8
|
+
* modification, are permitted provided that the following
|
9
|
+
* conditions are met:
|
10
|
+
*
|
11
|
+
* * Redistributions of source code must retain the above copyright
|
12
|
+
* notice, this list of conditions and the following disclaimer.
|
13
|
+
* * Redistributions in binary form must reproduce the above
|
14
|
+
* copyright notice, this list of conditions and the following
|
15
|
+
* disclaimer in the documentation and/or other materials provided
|
16
|
+
* with the distribution.
|
17
|
+
*
|
18
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
19
|
+
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
20
|
+
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
21
|
+
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
22
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
23
|
+
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
24
|
+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
25
|
+
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
26
|
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
27
|
+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
28
|
+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
29
|
+
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
30
|
+
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
31
|
+
*
|
32
|
+
* ----------------------------------------------------------------------- */
|
33
|
+
|
34
|
+
/*
|
35
|
+
* assemble.c code generation for the Netwide Assembler
|
36
|
+
*
|
37
|
+
* Bytecode specification
|
38
|
+
* ----------------------
|
39
|
+
*
|
40
|
+
*
|
41
|
+
* Codes Mnemonic Explanation
|
42
|
+
*
|
43
|
+
* \0 terminates the code. (Unless it's a literal of course.)
|
44
|
+
* \1..\4 that many literal bytes follow in the code stream
|
45
|
+
* \5 add 4 to the primary operand number (b, low octdigit)
|
46
|
+
* \6 add 4 to the secondary operand number (a, middle octdigit)
|
47
|
+
* \7 add 4 to both the primary and the secondary operand number
|
48
|
+
* \10..\13 a literal byte follows in the code stream, to be added
|
49
|
+
* to the register value of operand 0..3
|
50
|
+
* \14..\17 the position of index register operand in MIB (BND insns)
|
51
|
+
* \20..\23 ib a byte immediate operand, from operand 0..3
|
52
|
+
* \24..\27 ib,u a zero-extended byte immediate operand, from operand 0..3
|
53
|
+
* \30..\33 iw a word immediate operand, from operand 0..3
|
54
|
+
* \34..\37 iwd select between \3[0-3] and \4[0-3] depending on 16/32 bit
|
55
|
+
* assembly mode or the operand-size override on the operand
|
56
|
+
* \40..\43 id a long immediate operand, from operand 0..3
|
57
|
+
* \44..\47 iwdq select between \3[0-3], \4[0-3] and \5[4-7]
|
58
|
+
* depending on the address size of the instruction.
|
59
|
+
* \50..\53 rel8 a byte relative operand, from operand 0..3
|
60
|
+
* \54..\57 iq a qword immediate operand, from operand 0..3
|
61
|
+
* \60..\63 rel16 a word relative operand, from operand 0..3
|
62
|
+
* \64..\67 rel select between \6[0-3] and \7[0-3] depending on 16/32 bit
|
63
|
+
* assembly mode or the operand-size override on the operand
|
64
|
+
* \70..\73 rel32 a long relative operand, from operand 0..3
|
65
|
+
* \74..\77 seg a word constant, from the _segment_ part of operand 0..3
|
66
|
+
* \1ab a ModRM, calculated on EA in operand a, with the spare
|
67
|
+
* field the register value of operand b.
|
68
|
+
* \172\ab the register number from operand a in bits 7..4, with
|
69
|
+
* the 4-bit immediate from operand b in bits 3..0.
|
70
|
+
* \173\xab the register number from operand a in bits 7..4, with
|
71
|
+
* the value b in bits 3..0.
|
72
|
+
* \174..\177 the register number from operand 0..3 in bits 7..4, and
|
73
|
+
* an arbitrary value in bits 3..0 (assembled as zero.)
|
74
|
+
* \2ab a ModRM, calculated on EA in operand a, with the spare
|
75
|
+
* field equal to digit b.
|
76
|
+
*
|
77
|
+
* \240..\243 this instruction uses EVEX rather than REX or VEX/XOP, with the
|
78
|
+
* V field taken from operand 0..3.
|
79
|
+
* \250 this instruction uses EVEX rather than REX or VEX/XOP, with the
|
80
|
+
* V field set to 1111b.
|
81
|
+
*
|
82
|
+
* EVEX prefixes are followed by the sequence:
|
83
|
+
* \cm\wlp\tup where cm is:
|
84
|
+
* cc 00m mmm
|
85
|
+
* c = 2 for EVEX and mmmm is the M field (EVEX.P0[3:0])
|
86
|
+
* and wlp is:
|
87
|
+
* 00 wwl lpp
|
88
|
+
* [l0] ll = 0 (.128, .lz)
|
89
|
+
* [l1] ll = 1 (.256)
|
90
|
+
* [l2] ll = 2 (.512)
|
91
|
+
* [lig] ll = 3 for EVEX.L'L don't care (always assembled as 0)
|
92
|
+
*
|
93
|
+
* [w0] ww = 0 for W = 0
|
94
|
+
* [w1] ww = 1 for W = 1
|
95
|
+
* [wig] ww = 2 for W don't care (always assembled as 0)
|
96
|
+
* [ww] ww = 3 for W used as REX.W
|
97
|
+
*
|
98
|
+
* [p0] pp = 0 for no prefix
|
99
|
+
* [60] pp = 1 for legacy prefix 60
|
100
|
+
* [f3] pp = 2
|
101
|
+
* [f2] pp = 3
|
102
|
+
*
|
103
|
+
* tup is tuple type for Disp8*N from %tuple_codes in insns.pl
|
104
|
+
* (compressed displacement encoding)
|
105
|
+
*
|
106
|
+
* \254..\257 id,s a signed 32-bit operand to be extended to 64 bits.
|
107
|
+
* \260..\263 this instruction uses VEX/XOP rather than REX, with the
|
108
|
+
* V field taken from operand 0..3.
|
109
|
+
* \270 this instruction uses VEX/XOP rather than REX, with the
|
110
|
+
* V field set to 1111b.
|
111
|
+
*
|
112
|
+
* VEX/XOP prefixes are followed by the sequence:
|
113
|
+
* \tmm\wlp where mm is the M field; and wlp is:
|
114
|
+
* 00 wwl lpp
|
115
|
+
* [l0] ll = 0 for L = 0 (.128, .lz)
|
116
|
+
* [l1] ll = 1 for L = 1 (.256)
|
117
|
+
* [lig] ll = 2 for L don't care (always assembled as 0)
|
118
|
+
*
|
119
|
+
* [w0] ww = 0 for W = 0
|
120
|
+
* [w1 ] ww = 1 for W = 1
|
121
|
+
* [wig] ww = 2 for W don't care (always assembled as 0)
|
122
|
+
* [ww] ww = 3 for W used as REX.W
|
123
|
+
*
|
124
|
+
* t = 0 for VEX (C4/C5), t = 1 for XOP (8F).
|
125
|
+
*
|
126
|
+
* \271 hlexr instruction takes XRELEASE (F3) with or without lock
|
127
|
+
* \272 hlenl instruction takes XACQUIRE/XRELEASE with or without lock
|
128
|
+
* \273 hle instruction takes XACQUIRE/XRELEASE with lock only
|
129
|
+
* \274..\277 ib,s a byte immediate operand, from operand 0..3, sign-extended
|
130
|
+
* to the operand size (if o16/o32/o64 present) or the bit size
|
131
|
+
* \310 a16 indicates fixed 16-bit address size, i.e. optional 0x67.
|
132
|
+
* \311 a32 indicates fixed 32-bit address size, i.e. optional 0x67.
|
133
|
+
* \312 adf (disassembler only) invalid with non-default address size.
|
134
|
+
* \313 a64 indicates fixed 64-bit address size, 0x67 invalid.
|
135
|
+
* \314 norexb (disassembler only) invalid with REX.B
|
136
|
+
* \315 norexx (disassembler only) invalid with REX.X
|
137
|
+
* \316 norexr (disassembler only) invalid with REX.R
|
138
|
+
* \317 norexw (disassembler only) invalid with REX.W
|
139
|
+
* \320 o16 indicates fixed 16-bit operand size, i.e. optional 0x66.
|
140
|
+
* \321 o32 indicates fixed 32-bit operand size, i.e. optional 0x66.
|
141
|
+
* \322 odf indicates that this instruction is only valid when the
|
142
|
+
* operand size is the default (instruction to disassembler,
|
143
|
+
* generates no code in the assembler)
|
144
|
+
* \323 o64nw indicates fixed 64-bit operand size, REX on extensions only.
|
145
|
+
* \324 o64 indicates 64-bit operand size requiring REX prefix.
|
146
|
+
* \325 nohi instruction which always uses spl/bpl/sil/dil
|
147
|
+
* \326 nof3 instruction not valid with 0xF3 REP prefix. Hint for
|
148
|
+
disassembler only; for SSE instructions.
|
149
|
+
* \330 a literal byte follows in the code stream, to be added
|
150
|
+
* to the condition code value of the instruction.
|
151
|
+
* \331 norep instruction not valid with REP prefix. Hint for
|
152
|
+
* disassembler only; for SSE instructions.
|
153
|
+
* \332 f2i REP prefix (0xF2 byte) used as opcode extension.
|
154
|
+
* \333 f3i REP prefix (0xF3 byte) used as opcode extension.
|
155
|
+
* \334 rex.l LOCK prefix used as REX.R (used in non-64-bit mode)
|
156
|
+
* \335 repe disassemble a rep (0xF3 byte) prefix as repe not rep.
|
157
|
+
* \336 mustrep force a REP(E) prefix (0xF3) even if not specified.
|
158
|
+
* \337 mustrepne force a REPNE prefix (0xF2) even if not specified.
|
159
|
+
* \336-\337 are still listed as prefixes in the disassembler.
|
160
|
+
* \340 resb reserve <operand 0> bytes of uninitialized storage.
|
161
|
+
* Operand 0 had better be a segmentless constant.
|
162
|
+
* \341 wait this instruction needs a WAIT "prefix"
|
163
|
+
* \360 np no SSE prefix (== \364\331)
|
164
|
+
* \361 66 SSE prefix (== \366\331)
|
165
|
+
* \364 !osp operand-size prefix (0x66) not permitted
|
166
|
+
* \365 !asp address-size prefix (0x67) not permitted
|
167
|
+
* \366 operand-size prefix (0x66) used as opcode extension
|
168
|
+
* \367 address-size prefix (0x67) used as opcode extension
|
169
|
+
* \370,\371 jcc8 match only if operand 0 meets byte jump criteria.
|
170
|
+
* jmp8 370 is used for Jcc, 371 is used for JMP.
|
171
|
+
* \373 jlen assemble 0x03 if bits==16, 0x05 if bits==32;
|
172
|
+
* used for conditional jump over longer jump
|
173
|
+
* \374 vsibx|vm32x|vm64x this instruction takes an XMM VSIB memory EA
|
174
|
+
* \375 vsiby|vm32y|vm64y this instruction takes an YMM VSIB memory EA
|
175
|
+
* \376 vsibz|vm32z|vm64z this instruction takes an ZMM VSIB memory EA
|
176
|
+
*/
|
177
|
+
|
178
|
+
#include "compiler.h"
|
179
|
+
|
180
|
+
#include <stdio.h>
|
181
|
+
#include <string.h>
|
182
|
+
#include <stdlib.h>
|
183
|
+
|
184
|
+
#include "nasm.h"
|
185
|
+
#include "nasmlib.h"
|
186
|
+
#include "error.h"
|
187
|
+
#include "assemble.h"
|
188
|
+
#include "insns.h"
|
189
|
+
#include "tables.h"
|
190
|
+
#include "disp8.h"
|
191
|
+
#include "listing.h"
|
192
|
+
|
193
|
+
enum match_result {
|
194
|
+
/*
|
195
|
+
* Matching errors. These should be sorted so that more specific
|
196
|
+
* errors come later in the sequence.
|
197
|
+
*/
|
198
|
+
MERR_INVALOP,
|
199
|
+
MERR_OPSIZEMISSING,
|
200
|
+
MERR_OPSIZEMISMATCH,
|
201
|
+
MERR_BRNOTHERE,
|
202
|
+
MERR_BRNUMMISMATCH,
|
203
|
+
MERR_MASKNOTHERE,
|
204
|
+
MERR_DECONOTHERE,
|
205
|
+
MERR_BADCPU,
|
206
|
+
MERR_BADMODE,
|
207
|
+
MERR_BADHLE,
|
208
|
+
MERR_ENCMISMATCH,
|
209
|
+
MERR_BADBND,
|
210
|
+
MERR_BADREPNE,
|
211
|
+
/*
|
212
|
+
* Matching success; the conditional ones first
|
213
|
+
*/
|
214
|
+
MOK_JUMP, /* Matching OK but needs jmp_match() */
|
215
|
+
MOK_GOOD /* Matching unconditionally OK */
|
216
|
+
};
|
217
|
+
|
218
|
+
typedef struct {
|
219
|
+
enum ea_type type; /* what kind of EA is this? */
|
220
|
+
int sib_present; /* is a SIB byte necessary? */
|
221
|
+
int bytes; /* # of bytes of offset needed */
|
222
|
+
int size; /* lazy - this is sib+bytes+1 */
|
223
|
+
uint8_t modrm, sib, rex, rip; /* the bytes themselves */
|
224
|
+
int8_t disp8; /* compressed displacement for EVEX */
|
225
|
+
} ea;
|
226
|
+
|
227
|
+
#define GEN_SIB(scale, index, base) \
|
228
|
+
(((scale) << 6) | ((index) << 3) | ((base)))
|
229
|
+
|
230
|
+
#define GEN_MODRM(mod, reg, rm) \
|
231
|
+
(((mod) << 6) | (((reg) & 7) << 3) | ((rm) & 7))
|
232
|
+
|
233
|
+
static int64_t calcsize(int32_t, int64_t, int, insn *,
|
234
|
+
const struct itemplate *);
|
235
|
+
static int emit_prefix(struct out_data *data, const int bits, insn *ins);
|
236
|
+
static void gencode(struct out_data *data, insn *ins);
|
237
|
+
static enum match_result find_match(const struct itemplate **tempp,
|
238
|
+
insn *instruction,
|
239
|
+
int32_t segment, int64_t offset, int bits);
|
240
|
+
static enum match_result matches(const struct itemplate *, insn *, int bits);
|
241
|
+
static opflags_t regflag(const operand *);
|
242
|
+
static int32_t regval(const operand *);
|
243
|
+
static int rexflags(int, opflags_t, int);
|
244
|
+
static int op_rexflags(const operand *, int);
|
245
|
+
static int op_evexflags(const operand *, int, uint8_t);
|
246
|
+
static void add_asp(insn *, int);
|
247
|
+
|
248
|
+
static enum ea_type process_ea(operand *, ea *, int, int,
|
249
|
+
opflags_t, insn *, const char **);
|
250
|
+
|
251
|
+
static inline bool absolute_op(const struct operand *o)
|
252
|
+
{
|
253
|
+
return o->segment == NO_SEG && o->wrt == NO_SEG &&
|
254
|
+
!(o->opflags & OPFLAG_RELATIVE);
|
255
|
+
}
|
256
|
+
|
257
|
+
static int has_prefix(insn * ins, enum prefix_pos pos, int prefix)
|
258
|
+
{
|
259
|
+
return ins->prefixes[pos] == prefix;
|
260
|
+
}
|
261
|
+
|
262
|
+
static void assert_no_prefix(insn * ins, enum prefix_pos pos)
|
263
|
+
{
|
264
|
+
if (ins->prefixes[pos])
|
265
|
+
nasm_error(ERR_NONFATAL, "invalid %s prefix",
|
266
|
+
prefix_name(ins->prefixes[pos]));
|
267
|
+
}
|
268
|
+
|
269
|
+
static const char *size_name(int size)
|
270
|
+
{
|
271
|
+
switch (size) {
|
272
|
+
case 1:
|
273
|
+
return "byte";
|
274
|
+
case 2:
|
275
|
+
return "word";
|
276
|
+
case 4:
|
277
|
+
return "dword";
|
278
|
+
case 8:
|
279
|
+
return "qword";
|
280
|
+
case 10:
|
281
|
+
return "tword";
|
282
|
+
case 16:
|
283
|
+
return "oword";
|
284
|
+
case 32:
|
285
|
+
return "yword";
|
286
|
+
case 64:
|
287
|
+
return "zword";
|
288
|
+
default:
|
289
|
+
return "???";
|
290
|
+
}
|
291
|
+
}
|
292
|
+
|
293
|
+
static void warn_overflow(int size)
|
294
|
+
{
|
295
|
+
nasm_error(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
|
296
|
+
"%s data exceeds bounds", size_name(size));
|
297
|
+
}
|
298
|
+
|
299
|
+
static void warn_overflow_const(int64_t data, int size)
|
300
|
+
{
|
301
|
+
if (overflow_general(data, size))
|
302
|
+
warn_overflow(size);
|
303
|
+
}
|
304
|
+
|
305
|
+
static void warn_overflow_out(int64_t data, int size, enum out_sign sign)
|
306
|
+
{
|
307
|
+
bool err;
|
308
|
+
|
309
|
+
switch (sign) {
|
310
|
+
case OUT_WRAP:
|
311
|
+
err = overflow_general(data, size);
|
312
|
+
break;
|
313
|
+
case OUT_SIGNED:
|
314
|
+
err = overflow_signed(data, size);
|
315
|
+
break;
|
316
|
+
case OUT_UNSIGNED:
|
317
|
+
err = overflow_unsigned(data, size);
|
318
|
+
break;
|
319
|
+
default:
|
320
|
+
panic();
|
321
|
+
break;
|
322
|
+
}
|
323
|
+
|
324
|
+
if (err)
|
325
|
+
warn_overflow(size);
|
326
|
+
}
|
327
|
+
|
328
|
+
/*
|
329
|
+
* This routine wrappers the real output format's output routine,
|
330
|
+
* in order to pass a copy of the data off to the listing file
|
331
|
+
* generator at the same time, flatten unnecessary relocations,
|
332
|
+
* and verify backend compatibility.
|
333
|
+
*/
|
334
|
+
static void out(struct out_data *data)
|
335
|
+
{
|
336
|
+
static int32_t lineno = 0; /* static!!! */
|
337
|
+
static const char *lnfname = NULL;
|
338
|
+
int asize;
|
339
|
+
const int amax = ofmt->maxbits >> 3; /* Maximum address size in bytes */
|
340
|
+
union {
|
341
|
+
uint8_t b[8];
|
342
|
+
uint64_t q;
|
343
|
+
} xdata;
|
344
|
+
uint64_t size = data->size;
|
345
|
+
int64_t addrval;
|
346
|
+
int32_t fixseg; /* Segment for which to produce fixed data */
|
347
|
+
|
348
|
+
if (!data->size)
|
349
|
+
return; /* Nothing to do */
|
350
|
+
|
351
|
+
/*
|
352
|
+
* Convert addresses to RAWDATA if possible
|
353
|
+
* XXX: not all backends want this for global symbols!!!!
|
354
|
+
*/
|
355
|
+
switch (data->type) {
|
356
|
+
case OUT_ADDRESS:
|
357
|
+
addrval = data->toffset;
|
358
|
+
fixseg = NO_SEG; /* Absolute address is fixed data */
|
359
|
+
goto address;
|
360
|
+
|
361
|
+
case OUT_RELADDR:
|
362
|
+
addrval = data->toffset - data->relbase;
|
363
|
+
fixseg = data->segment; /* Our own segment is fixed data */
|
364
|
+
goto address;
|
365
|
+
|
366
|
+
address:
|
367
|
+
asize = data->size;
|
368
|
+
nasm_assert(asize <= 8);
|
369
|
+
if (data->tsegment == fixseg && data->twrt == NO_SEG) {
|
370
|
+
uint8_t *q = xdata.b;
|
371
|
+
|
372
|
+
warn_overflow_out(addrval, asize, data->sign);
|
373
|
+
|
374
|
+
WRITEADDR(q, addrval, asize);
|
375
|
+
data->data = xdata.b;
|
376
|
+
data->type = OUT_RAWDATA;
|
377
|
+
asize = 0; /* No longer an address */
|
378
|
+
}
|
379
|
+
break;
|
380
|
+
|
381
|
+
default:
|
382
|
+
asize = 0; /* Not an address */
|
383
|
+
break;
|
384
|
+
}
|
385
|
+
|
386
|
+
lfmt->output(data);
|
387
|
+
|
388
|
+
/*
|
389
|
+
* this call to src_get determines when we call the
|
390
|
+
* debug-format-specific "linenum" function
|
391
|
+
* it updates lineno and lnfname to the current values
|
392
|
+
* returning 0 if "same as last time", -2 if lnfname
|
393
|
+
* changed, and the amount by which lineno changed,
|
394
|
+
* if it did. thus, these variables must be static
|
395
|
+
*/
|
396
|
+
|
397
|
+
if (src_get(&lineno, &lnfname))
|
398
|
+
dfmt->linenum(lnfname, lineno, data->segment);
|
399
|
+
|
400
|
+
if (asize && asize > amax) {
|
401
|
+
if (data->type != OUT_ADDRESS || data->sign == OUT_SIGNED) {
|
402
|
+
nasm_error(ERR_NONFATAL,
|
403
|
+
"%d-bit signed relocation unsupported by output format %s\n",
|
404
|
+
asize << 3, ofmt->shortname);
|
405
|
+
} else {
|
406
|
+
nasm_error(ERR_WARNING | ERR_WARN_ZEXTRELOC,
|
407
|
+
"%d-bit unsigned relocation zero-extended from %d bits\n",
|
408
|
+
asize << 3, ofmt->maxbits);
|
409
|
+
data->size = amax;
|
410
|
+
ofmt->output(data);
|
411
|
+
data->insoffs += amax;
|
412
|
+
data->offset += amax;
|
413
|
+
data->size = size = asize - amax;
|
414
|
+
}
|
415
|
+
data->data = zero_buffer;
|
416
|
+
data->type = OUT_RAWDATA;
|
417
|
+
}
|
418
|
+
|
419
|
+
ofmt->output(data);
|
420
|
+
data->offset += size;
|
421
|
+
data->insoffs += size;
|
422
|
+
}
|
423
|
+
|
424
|
+
static inline void out_rawdata(struct out_data *data, const void *rawdata,
|
425
|
+
size_t size)
|
426
|
+
{
|
427
|
+
data->type = OUT_RAWDATA;
|
428
|
+
data->data = rawdata;
|
429
|
+
data->size = size;
|
430
|
+
out(data);
|
431
|
+
}
|
432
|
+
|
433
|
+
static void out_rawbyte(struct out_data *data, uint8_t byte)
|
434
|
+
{
|
435
|
+
data->type = OUT_RAWDATA;
|
436
|
+
data->data = &byte;
|
437
|
+
data->size = 1;
|
438
|
+
out(data);
|
439
|
+
}
|
440
|
+
|
441
|
+
static inline void out_reserve(struct out_data *data, uint64_t size)
|
442
|
+
{
|
443
|
+
data->type = OUT_RESERVE;
|
444
|
+
data->size = size;
|
445
|
+
out(data);
|
446
|
+
}
|
447
|
+
|
448
|
+
static inline void out_imm(struct out_data *data, const struct operand *opx,
|
449
|
+
int size, enum out_sign sign)
|
450
|
+
{
|
451
|
+
data->type =
|
452
|
+
(opx->opflags & OPFLAG_RELATIVE) ? OUT_RELADDR : OUT_ADDRESS;
|
453
|
+
data->sign = sign;
|
454
|
+
data->size = size;
|
455
|
+
data->toffset = opx->offset;
|
456
|
+
data->tsegment = opx->segment;
|
457
|
+
data->twrt = opx->wrt;
|
458
|
+
/*
|
459
|
+
* XXX: improve this if at some point in the future we can
|
460
|
+
* distinguish the subtrahend in expressions like [foo - bar]
|
461
|
+
* where bar is a symbol in the current segment. However, at the
|
462
|
+
* current point, if OPFLAG_RELATIVE is set that subtraction has
|
463
|
+
* already occurred.
|
464
|
+
*/
|
465
|
+
data->relbase = 0;
|
466
|
+
out(data);
|
467
|
+
}
|
468
|
+
|
469
|
+
static void out_reladdr(struct out_data *data, const struct operand *opx,
|
470
|
+
int size)
|
471
|
+
{
|
472
|
+
if (opx->opflags & OPFLAG_RELATIVE)
|
473
|
+
nasm_error(ERR_NONFATAL, "invalid use of self-relative expression");
|
474
|
+
|
475
|
+
data->type = OUT_RELADDR;
|
476
|
+
data->sign = OUT_SIGNED;
|
477
|
+
data->size = size;
|
478
|
+
data->toffset = opx->offset;
|
479
|
+
data->tsegment = opx->segment;
|
480
|
+
data->twrt = opx->wrt;
|
481
|
+
data->relbase = data->offset + (data->inslen - data->insoffs);
|
482
|
+
out(data);
|
483
|
+
}
|
484
|
+
|
485
|
+
static inline void out_segment(struct out_data *data,
|
486
|
+
const struct operand *opx)
|
487
|
+
{
|
488
|
+
data->type = OUT_SEGMENT;
|
489
|
+
data->sign = OUT_UNSIGNED;
|
490
|
+
data->size = 2;
|
491
|
+
data->toffset = opx->offset; /* Is this really needed/wanted? */
|
492
|
+
data->tsegment = ofmt->segbase(opx->segment + 1);
|
493
|
+
data->twrt = opx->wrt;
|
494
|
+
out(data);
|
495
|
+
}
|
496
|
+
|
497
|
+
static bool jmp_match(int32_t segment, int64_t offset, int bits,
|
498
|
+
insn * ins, const struct itemplate *temp)
|
499
|
+
{
|
500
|
+
int64_t isize;
|
501
|
+
const uint8_t *code = temp->code;
|
502
|
+
uint8_t c = code[0];
|
503
|
+
bool is_byte;
|
504
|
+
|
505
|
+
if (((c & ~1) != 0370) || (ins->oprs[0].type & STRICT))
|
506
|
+
return false;
|
507
|
+
if (!optimizing)
|
508
|
+
return false;
|
509
|
+
if (optimizing < 0 && c == 0371)
|
510
|
+
return false;
|
511
|
+
|
512
|
+
isize = calcsize(segment, offset, bits, ins, temp);
|
513
|
+
|
514
|
+
if (ins->oprs[0].opflags & OPFLAG_UNKNOWN)
|
515
|
+
/* Be optimistic in pass 1 */
|
516
|
+
return true;
|
517
|
+
|
518
|
+
if (ins->oprs[0].segment != segment)
|
519
|
+
return false;
|
520
|
+
|
521
|
+
isize = ins->oprs[0].offset - offset - isize; /* isize is delta */
|
522
|
+
is_byte = (isize >= -128 && isize <= 127); /* is it byte size? */
|
523
|
+
|
524
|
+
if (is_byte && c == 0371 && ins->prefixes[PPS_REP] == P_BND) {
|
525
|
+
/* jmp short (opcode eb) cannot be used with bnd prefix. */
|
526
|
+
ins->prefixes[PPS_REP] = P_none;
|
527
|
+
nasm_error(ERR_WARNING | ERR_WARN_BND | ERR_PASS2 ,
|
528
|
+
"jmp short does not init bnd regs - bnd prefix dropped.");
|
529
|
+
}
|
530
|
+
|
531
|
+
return is_byte;
|
532
|
+
}
|
533
|
+
|
534
|
+
/* This is totally just a wild guess what is reasonable... */
|
535
|
+
#define INCBIN_MAX_BUF (ZERO_BUF_SIZE * 16)
|
536
|
+
|
537
|
+
int64_t assemble(int32_t segment, int64_t start, int bits, insn *instruction)
|
538
|
+
{
|
539
|
+
struct out_data data;
|
540
|
+
const struct itemplate *temp;
|
541
|
+
enum match_result m;
|
542
|
+
int64_t wsize; /* size for DB etc. */
|
543
|
+
|
544
|
+
nasm_zero(data);
|
545
|
+
data.offset = start;
|
546
|
+
data.segment = segment;
|
547
|
+
data.itemp = NULL;
|
548
|
+
data.sign = OUT_WRAP;
|
549
|
+
data.bits = bits;
|
550
|
+
|
551
|
+
wsize = idata_bytes(instruction->opcode);
|
552
|
+
if (wsize == -1)
|
553
|
+
return 0;
|
554
|
+
|
555
|
+
if (wsize) {
|
556
|
+
extop *e;
|
557
|
+
|
558
|
+
list_for_each(e, instruction->eops) {
|
559
|
+
if (e->type == EOT_DB_NUMBER) {
|
560
|
+
if (wsize > 8) {
|
561
|
+
nasm_error(ERR_NONFATAL,
|
562
|
+
"integer supplied to a DT, DO, DY or DZ"
|
563
|
+
" instruction");
|
564
|
+
} else {
|
565
|
+
data.insoffs = 0;
|
566
|
+
data.type = e->relative ? OUT_RELADDR : OUT_ADDRESS;
|
567
|
+
data.inslen = data.size = wsize;
|
568
|
+
data.toffset = e->offset;
|
569
|
+
data.tsegment = e->segment;
|
570
|
+
data.twrt = e->wrt;
|
571
|
+
data.relbase = 0;
|
572
|
+
out(&data);
|
573
|
+
}
|
574
|
+
} else if (e->type == EOT_DB_STRING ||
|
575
|
+
e->type == EOT_DB_STRING_FREE) {
|
576
|
+
int align = e->stringlen % wsize;
|
577
|
+
if (align)
|
578
|
+
align = wsize - align;
|
579
|
+
|
580
|
+
data.insoffs = 0;
|
581
|
+
data.inslen = e->stringlen + align;
|
582
|
+
|
583
|
+
out_rawdata(&data, e->stringval, e->stringlen);
|
584
|
+
out_rawdata(&data, zero_buffer, align);
|
585
|
+
}
|
586
|
+
}
|
587
|
+
} else if (instruction->opcode == I_INCBIN) {
|
588
|
+
const char *fname = instruction->eops->stringval;
|
589
|
+
FILE *fp;
|
590
|
+
size_t t = instruction->times; /* INCBIN handles TIMES by itself */
|
591
|
+
off_t base = 0;
|
592
|
+
off_t len;
|
593
|
+
const void *map = NULL;
|
594
|
+
char *buf = NULL;
|
595
|
+
size_t blk = 0; /* Buffered I/O block size */
|
596
|
+
size_t m = 0; /* Bytes last read */
|
597
|
+
|
598
|
+
if (!t)
|
599
|
+
goto done;
|
600
|
+
|
601
|
+
fp = nasm_open_read(fname, NF_BINARY|NF_FORMAP);
|
602
|
+
if (!fp) {
|
603
|
+
nasm_error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
|
604
|
+
fname);
|
605
|
+
goto done;
|
606
|
+
}
|
607
|
+
|
608
|
+
len = nasm_file_size(fp);
|
609
|
+
|
610
|
+
if (len == (off_t)-1) {
|
611
|
+
nasm_error(ERR_NONFATAL, "`incbin': unable to get length of file `%s'",
|
612
|
+
fname);
|
613
|
+
goto close_done;
|
614
|
+
}
|
615
|
+
|
616
|
+
if (instruction->eops->next) {
|
617
|
+
base = instruction->eops->next->offset;
|
618
|
+
if (base >= len) {
|
619
|
+
len = 0;
|
620
|
+
} else {
|
621
|
+
len -= base;
|
622
|
+
if (instruction->eops->next->next &&
|
623
|
+
len > (off_t)instruction->eops->next->next->offset)
|
624
|
+
len = (off_t)instruction->eops->next->next->offset;
|
625
|
+
}
|
626
|
+
}
|
627
|
+
|
628
|
+
lfmt->set_offset(data.offset);
|
629
|
+
lfmt->uplevel(LIST_INCBIN);
|
630
|
+
|
631
|
+
if (!len)
|
632
|
+
goto end_incbin;
|
633
|
+
|
634
|
+
/* Try to map file data */
|
635
|
+
map = nasm_map_file(fp, base, len);
|
636
|
+
if (!map) {
|
637
|
+
blk = len < (off_t)INCBIN_MAX_BUF ? (size_t)len : INCBIN_MAX_BUF;
|
638
|
+
buf = nasm_malloc(blk);
|
639
|
+
}
|
640
|
+
|
641
|
+
while (t--) {
|
642
|
+
/*
|
643
|
+
* Consider these irrelevant for INCBIN, since it is fully
|
644
|
+
* possible that these might be (way) bigger than an int
|
645
|
+
* can hold; there is, however, no reason to widen these
|
646
|
+
* types just for INCBIN. data.inslen == 0 signals to the
|
647
|
+
* backend that these fields are meaningless, if at all
|
648
|
+
* needed.
|
649
|
+
*/
|
650
|
+
data.insoffs = 0;
|
651
|
+
data.inslen = 0;
|
652
|
+
|
653
|
+
if (map) {
|
654
|
+
out_rawdata(&data, map, len);
|
655
|
+
} else if ((off_t)m == len) {
|
656
|
+
out_rawdata(&data, buf, len);
|
657
|
+
} else {
|
658
|
+
off_t l = len;
|
659
|
+
|
660
|
+
if (fseeko(fp, base, SEEK_SET) < 0 || ferror(fp)) {
|
661
|
+
nasm_error(ERR_NONFATAL,
|
662
|
+
"`incbin': unable to seek on file `%s'",
|
663
|
+
fname);
|
664
|
+
goto end_incbin;
|
665
|
+
}
|
666
|
+
while (l > 0) {
|
667
|
+
m = fread(buf, 1, l < (off_t)blk ? (size_t)l : blk, fp);
|
668
|
+
if (!m || feof(fp)) {
|
669
|
+
/*
|
670
|
+
* This shouldn't happen unless the file
|
671
|
+
* actually changes while we are reading
|
672
|
+
* it.
|
673
|
+
*/
|
674
|
+
nasm_error(ERR_NONFATAL,
|
675
|
+
"`incbin': unexpected EOF while"
|
676
|
+
" reading file `%s'", fname);
|
677
|
+
goto end_incbin;
|
678
|
+
}
|
679
|
+
out_rawdata(&data, buf, m);
|
680
|
+
l -= m;
|
681
|
+
}
|
682
|
+
}
|
683
|
+
}
|
684
|
+
end_incbin:
|
685
|
+
lfmt->downlevel(LIST_INCBIN);
|
686
|
+
if (instruction->times > 1) {
|
687
|
+
lfmt->set_offset(start);
|
688
|
+
lfmt->uplevel(LIST_TIMES);
|
689
|
+
lfmt->downlevel(LIST_TIMES);
|
690
|
+
}
|
691
|
+
if (ferror(fp)) {
|
692
|
+
nasm_error(ERR_NONFATAL,
|
693
|
+
"`incbin': error while"
|
694
|
+
" reading file `%s'", fname);
|
695
|
+
}
|
696
|
+
close_done:
|
697
|
+
if (buf)
|
698
|
+
nasm_free(buf);
|
699
|
+
if (map)
|
700
|
+
nasm_unmap_file(map, len);
|
701
|
+
fclose(fp);
|
702
|
+
done:
|
703
|
+
instruction->times = 1; /* Tell the upper layer not to iterate */
|
704
|
+
;
|
705
|
+
} else {
|
706
|
+
/* "Real" instruction */
|
707
|
+
|
708
|
+
/* Check to see if we need an address-size prefix */
|
709
|
+
add_asp(instruction, bits);
|
710
|
+
|
711
|
+
m = find_match(&temp, instruction, data.segment, data.offset, bits);
|
712
|
+
|
713
|
+
if (m == MOK_GOOD) {
|
714
|
+
/* Matches! */
|
715
|
+
int64_t insn_size = calcsize(data.segment, data.offset,
|
716
|
+
bits, instruction, temp);
|
717
|
+
nasm_assert(insn_size >= 0);
|
718
|
+
|
719
|
+
data.itemp = temp;
|
720
|
+
data.bits = bits;
|
721
|
+
data.insoffs = 0;
|
722
|
+
data.inslen = insn_size;
|
723
|
+
|
724
|
+
gencode(&data, instruction);
|
725
|
+
nasm_assert(data.insoffs == insn_size);
|
726
|
+
} else {
|
727
|
+
/* No match */
|
728
|
+
switch (m) {
|
729
|
+
case MERR_OPSIZEMISSING:
|
730
|
+
nasm_error(ERR_NONFATAL, "operation size not specified");
|
731
|
+
break;
|
732
|
+
case MERR_OPSIZEMISMATCH:
|
733
|
+
nasm_error(ERR_NONFATAL, "mismatch in operand sizes");
|
734
|
+
break;
|
735
|
+
case MERR_BRNOTHERE:
|
736
|
+
nasm_error(ERR_NONFATAL,
|
737
|
+
"broadcast not permitted on this operand");
|
738
|
+
break;
|
739
|
+
case MERR_BRNUMMISMATCH:
|
740
|
+
nasm_error(ERR_NONFATAL,
|
741
|
+
"mismatch in the number of broadcasting elements");
|
742
|
+
break;
|
743
|
+
case MERR_MASKNOTHERE:
|
744
|
+
nasm_error(ERR_NONFATAL,
|
745
|
+
"mask not permitted on this operand");
|
746
|
+
break;
|
747
|
+
case MERR_DECONOTHERE:
|
748
|
+
nasm_error(ERR_NONFATAL, "unsupported mode decorator for instruction");
|
749
|
+
break;
|
750
|
+
case MERR_BADCPU:
|
751
|
+
nasm_error(ERR_NONFATAL, "no instruction for this cpu level");
|
752
|
+
break;
|
753
|
+
case MERR_BADMODE:
|
754
|
+
nasm_error(ERR_NONFATAL, "instruction not supported in %d-bit mode",
|
755
|
+
bits);
|
756
|
+
break;
|
757
|
+
case MERR_ENCMISMATCH:
|
758
|
+
nasm_error(ERR_NONFATAL, "specific encoding scheme not available");
|
759
|
+
break;
|
760
|
+
case MERR_BADBND:
|
761
|
+
nasm_error(ERR_NONFATAL, "bnd prefix is not allowed");
|
762
|
+
break;
|
763
|
+
case MERR_BADREPNE:
|
764
|
+
nasm_error(ERR_NONFATAL, "%s prefix is not allowed",
|
765
|
+
(has_prefix(instruction, PPS_REP, P_REPNE) ?
|
766
|
+
"repne" : "repnz"));
|
767
|
+
break;
|
768
|
+
default:
|
769
|
+
nasm_error(ERR_NONFATAL,
|
770
|
+
"invalid combination of opcode and operands");
|
771
|
+
break;
|
772
|
+
}
|
773
|
+
|
774
|
+
instruction->times = 1; /* Avoid repeated error messages */
|
775
|
+
}
|
776
|
+
}
|
777
|
+
return data.offset - start;
|
778
|
+
}
|
779
|
+
|
780
|
+
int64_t insn_size(int32_t segment, int64_t offset, int bits, insn *instruction)
|
781
|
+
{
|
782
|
+
const struct itemplate *temp;
|
783
|
+
enum match_result m;
|
784
|
+
|
785
|
+
if (instruction->opcode == I_none)
|
786
|
+
return 0;
|
787
|
+
|
788
|
+
if (opcode_is_db(instruction->opcode)) {
|
789
|
+
extop *e;
|
790
|
+
int32_t isize, osize, wsize;
|
791
|
+
|
792
|
+
isize = 0;
|
793
|
+
wsize = idata_bytes(instruction->opcode);
|
794
|
+
nasm_assert(wsize > 0);
|
795
|
+
|
796
|
+
list_for_each(e, instruction->eops) {
|
797
|
+
int32_t align;
|
798
|
+
|
799
|
+
osize = 0;
|
800
|
+
if (e->type == EOT_DB_NUMBER) {
|
801
|
+
osize = 1;
|
802
|
+
warn_overflow_const(e->offset, wsize);
|
803
|
+
} else if (e->type == EOT_DB_STRING ||
|
804
|
+
e->type == EOT_DB_STRING_FREE)
|
805
|
+
osize = e->stringlen;
|
806
|
+
|
807
|
+
align = (-osize) % wsize;
|
808
|
+
if (align < 0)
|
809
|
+
align += wsize;
|
810
|
+
isize += osize + align;
|
811
|
+
}
|
812
|
+
return isize;
|
813
|
+
}
|
814
|
+
|
815
|
+
if (instruction->opcode == I_INCBIN) {
|
816
|
+
const char *fname = instruction->eops->stringval;
|
817
|
+
off_t len;
|
818
|
+
|
819
|
+
len = nasm_file_size_by_path(fname);
|
820
|
+
if (len == (off_t)-1) {
|
821
|
+
nasm_error(ERR_NONFATAL, "`incbin': unable to get length of file `%s'",
|
822
|
+
fname);
|
823
|
+
return 0;
|
824
|
+
}
|
825
|
+
|
826
|
+
if (instruction->eops->next) {
|
827
|
+
if (len <= (off_t)instruction->eops->next->offset) {
|
828
|
+
len = 0;
|
829
|
+
} else {
|
830
|
+
len -= instruction->eops->next->offset;
|
831
|
+
if (instruction->eops->next->next &&
|
832
|
+
len > (off_t)instruction->eops->next->next->offset) {
|
833
|
+
len = (off_t)instruction->eops->next->next->offset;
|
834
|
+
}
|
835
|
+
}
|
836
|
+
}
|
837
|
+
|
838
|
+
len *= instruction->times;
|
839
|
+
instruction->times = 1; /* Tell the upper layer to not iterate */
|
840
|
+
|
841
|
+
return len;
|
842
|
+
}
|
843
|
+
|
844
|
+
/* Check to see if we need an address-size prefix */
|
845
|
+
add_asp(instruction, bits);
|
846
|
+
|
847
|
+
m = find_match(&temp, instruction, segment, offset, bits);
|
848
|
+
if (m == MOK_GOOD) {
|
849
|
+
/* we've matched an instruction. */
|
850
|
+
return calcsize(segment, offset, bits, instruction, temp);
|
851
|
+
} else {
|
852
|
+
return -1; /* didn't match any instruction */
|
853
|
+
}
|
854
|
+
}
|
855
|
+
|
856
|
+
static void bad_hle_warn(const insn * ins, uint8_t hleok)
|
857
|
+
{
|
858
|
+
enum prefixes rep_pfx = ins->prefixes[PPS_REP];
|
859
|
+
enum whatwarn { w_none, w_lock, w_inval } ww;
|
860
|
+
static const enum whatwarn warn[2][4] =
|
861
|
+
{
|
862
|
+
{ w_inval, w_inval, w_none, w_lock }, /* XACQUIRE */
|
863
|
+
{ w_inval, w_none, w_none, w_lock }, /* XRELEASE */
|
864
|
+
};
|
865
|
+
unsigned int n;
|
866
|
+
|
867
|
+
n = (unsigned int)rep_pfx - P_XACQUIRE;
|
868
|
+
if (n > 1)
|
869
|
+
return; /* Not XACQUIRE/XRELEASE */
|
870
|
+
|
871
|
+
ww = warn[n][hleok];
|
872
|
+
if (!is_class(MEMORY, ins->oprs[0].type))
|
873
|
+
ww = w_inval; /* HLE requires operand 0 to be memory */
|
874
|
+
|
875
|
+
switch (ww) {
|
876
|
+
case w_none:
|
877
|
+
break;
|
878
|
+
|
879
|
+
case w_lock:
|
880
|
+
if (ins->prefixes[PPS_LOCK] != P_LOCK) {
|
881
|
+
nasm_error(ERR_WARNING | ERR_WARN_HLE | ERR_PASS2,
|
882
|
+
"%s with this instruction requires lock",
|
883
|
+
prefix_name(rep_pfx));
|
884
|
+
}
|
885
|
+
break;
|
886
|
+
|
887
|
+
case w_inval:
|
888
|
+
nasm_error(ERR_WARNING | ERR_WARN_HLE | ERR_PASS2,
|
889
|
+
"%s invalid with this instruction",
|
890
|
+
prefix_name(rep_pfx));
|
891
|
+
break;
|
892
|
+
}
|
893
|
+
}
|
894
|
+
|
895
|
+
/* Common construct */
|
896
|
+
#define case3(x) case (x): case (x)+1: case (x)+2
|
897
|
+
#define case4(x) case3(x): case (x)+3
|
898
|
+
|
899
|
+
static int64_t calcsize(int32_t segment, int64_t offset, int bits,
|
900
|
+
insn * ins, const struct itemplate *temp)
|
901
|
+
{
|
902
|
+
const uint8_t *codes = temp->code;
|
903
|
+
int64_t length = 0;
|
904
|
+
uint8_t c;
|
905
|
+
int rex_mask = ~0;
|
906
|
+
int op1, op2;
|
907
|
+
struct operand *opx;
|
908
|
+
uint8_t opex = 0;
|
909
|
+
enum ea_type eat;
|
910
|
+
uint8_t hleok = 0;
|
911
|
+
bool lockcheck = true;
|
912
|
+
enum reg_enum mib_index = R_none; /* For a separate index MIB reg form */
|
913
|
+
const char *errmsg;
|
914
|
+
|
915
|
+
ins->rex = 0; /* Ensure REX is reset */
|
916
|
+
eat = EA_SCALAR; /* Expect a scalar EA */
|
917
|
+
memset(ins->evex_p, 0, 3); /* Ensure EVEX is reset */
|
918
|
+
|
919
|
+
if (ins->prefixes[PPS_OSIZE] == P_O64)
|
920
|
+
ins->rex |= REX_W;
|
921
|
+
|
922
|
+
(void)segment; /* Don't warn that this parameter is unused */
|
923
|
+
(void)offset; /* Don't warn that this parameter is unused */
|
924
|
+
|
925
|
+
while (*codes) {
|
926
|
+
c = *codes++;
|
927
|
+
op1 = (c & 3) + ((opex & 1) << 2);
|
928
|
+
op2 = ((c >> 3) & 3) + ((opex & 2) << 1);
|
929
|
+
opx = &ins->oprs[op1];
|
930
|
+
opex = 0; /* For the next iteration */
|
931
|
+
|
932
|
+
switch (c) {
|
933
|
+
case4(01):
|
934
|
+
codes += c, length += c;
|
935
|
+
break;
|
936
|
+
|
937
|
+
case3(05):
|
938
|
+
opex = c;
|
939
|
+
break;
|
940
|
+
|
941
|
+
case4(010):
|
942
|
+
ins->rex |=
|
943
|
+
op_rexflags(opx, REX_B|REX_H|REX_P|REX_W);
|
944
|
+
codes++, length++;
|
945
|
+
break;
|
946
|
+
|
947
|
+
case4(014):
|
948
|
+
/* this is an index reg of MIB operand */
|
949
|
+
mib_index = opx->basereg;
|
950
|
+
break;
|
951
|
+
|
952
|
+
case4(020):
|
953
|
+
case4(024):
|
954
|
+
length++;
|
955
|
+
break;
|
956
|
+
|
957
|
+
case4(030):
|
958
|
+
length += 2;
|
959
|
+
break;
|
960
|
+
|
961
|
+
case4(034):
|
962
|
+
if (opx->type & (BITS16 | BITS32 | BITS64))
|
963
|
+
length += (opx->type & BITS16) ? 2 : 4;
|
964
|
+
else
|
965
|
+
length += (bits == 16) ? 2 : 4;
|
966
|
+
break;
|
967
|
+
|
968
|
+
case4(040):
|
969
|
+
length += 4;
|
970
|
+
break;
|
971
|
+
|
972
|
+
case4(044):
|
973
|
+
length += ins->addr_size >> 3;
|
974
|
+
break;
|
975
|
+
|
976
|
+
case4(050):
|
977
|
+
length++;
|
978
|
+
break;
|
979
|
+
|
980
|
+
case4(054):
|
981
|
+
length += 8; /* MOV reg64/imm */
|
982
|
+
break;
|
983
|
+
|
984
|
+
case4(060):
|
985
|
+
length += 2;
|
986
|
+
break;
|
987
|
+
|
988
|
+
case4(064):
|
989
|
+
if (opx->type & (BITS16 | BITS32 | BITS64))
|
990
|
+
length += (opx->type & BITS16) ? 2 : 4;
|
991
|
+
else
|
992
|
+
length += (bits == 16) ? 2 : 4;
|
993
|
+
break;
|
994
|
+
|
995
|
+
case4(070):
|
996
|
+
length += 4;
|
997
|
+
break;
|
998
|
+
|
999
|
+
case4(074):
|
1000
|
+
length += 2;
|
1001
|
+
break;
|
1002
|
+
|
1003
|
+
case 0172:
|
1004
|
+
case 0173:
|
1005
|
+
codes++;
|
1006
|
+
length++;
|
1007
|
+
break;
|
1008
|
+
|
1009
|
+
case4(0174):
|
1010
|
+
length++;
|
1011
|
+
break;
|
1012
|
+
|
1013
|
+
case4(0240):
|
1014
|
+
ins->rex |= REX_EV;
|
1015
|
+
ins->vexreg = regval(opx);
|
1016
|
+
ins->evex_p[2] |= op_evexflags(opx, EVEX_P2VP, 2); /* High-16 NDS */
|
1017
|
+
ins->vex_cm = *codes++;
|
1018
|
+
ins->vex_wlp = *codes++;
|
1019
|
+
ins->evex_tuple = (*codes++ - 0300);
|
1020
|
+
break;
|
1021
|
+
|
1022
|
+
case 0250:
|
1023
|
+
ins->rex |= REX_EV;
|
1024
|
+
ins->vexreg = 0;
|
1025
|
+
ins->vex_cm = *codes++;
|
1026
|
+
ins->vex_wlp = *codes++;
|
1027
|
+
ins->evex_tuple = (*codes++ - 0300);
|
1028
|
+
break;
|
1029
|
+
|
1030
|
+
case4(0254):
|
1031
|
+
length += 4;
|
1032
|
+
break;
|
1033
|
+
|
1034
|
+
case4(0260):
|
1035
|
+
ins->rex |= REX_V;
|
1036
|
+
ins->vexreg = regval(opx);
|
1037
|
+
ins->vex_cm = *codes++;
|
1038
|
+
ins->vex_wlp = *codes++;
|
1039
|
+
break;
|
1040
|
+
|
1041
|
+
case 0270:
|
1042
|
+
ins->rex |= REX_V;
|
1043
|
+
ins->vexreg = 0;
|
1044
|
+
ins->vex_cm = *codes++;
|
1045
|
+
ins->vex_wlp = *codes++;
|
1046
|
+
break;
|
1047
|
+
|
1048
|
+
case3(0271):
|
1049
|
+
hleok = c & 3;
|
1050
|
+
break;
|
1051
|
+
|
1052
|
+
case4(0274):
|
1053
|
+
length++;
|
1054
|
+
break;
|
1055
|
+
|
1056
|
+
case4(0300):
|
1057
|
+
break;
|
1058
|
+
|
1059
|
+
case 0310:
|
1060
|
+
if (bits == 64)
|
1061
|
+
return -1;
|
1062
|
+
length += (bits != 16) && !has_prefix(ins, PPS_ASIZE, P_A16);
|
1063
|
+
break;
|
1064
|
+
|
1065
|
+
case 0311:
|
1066
|
+
length += (bits != 32) && !has_prefix(ins, PPS_ASIZE, P_A32);
|
1067
|
+
break;
|
1068
|
+
|
1069
|
+
case 0312:
|
1070
|
+
break;
|
1071
|
+
|
1072
|
+
case 0313:
|
1073
|
+
if (bits != 64 || has_prefix(ins, PPS_ASIZE, P_A16) ||
|
1074
|
+
has_prefix(ins, PPS_ASIZE, P_A32))
|
1075
|
+
return -1;
|
1076
|
+
break;
|
1077
|
+
|
1078
|
+
case4(0314):
|
1079
|
+
break;
|
1080
|
+
|
1081
|
+
case 0320:
|
1082
|
+
{
|
1083
|
+
enum prefixes pfx = ins->prefixes[PPS_OSIZE];
|
1084
|
+
if (pfx == P_O16)
|
1085
|
+
break;
|
1086
|
+
if (pfx != P_none)
|
1087
|
+
nasm_error(ERR_WARNING | ERR_PASS2, "invalid operand size prefix");
|
1088
|
+
else
|
1089
|
+
ins->prefixes[PPS_OSIZE] = P_O16;
|
1090
|
+
break;
|
1091
|
+
}
|
1092
|
+
|
1093
|
+
case 0321:
|
1094
|
+
{
|
1095
|
+
enum prefixes pfx = ins->prefixes[PPS_OSIZE];
|
1096
|
+
if (pfx == P_O32)
|
1097
|
+
break;
|
1098
|
+
if (pfx != P_none)
|
1099
|
+
nasm_error(ERR_WARNING | ERR_PASS2, "invalid operand size prefix");
|
1100
|
+
else
|
1101
|
+
ins->prefixes[PPS_OSIZE] = P_O32;
|
1102
|
+
break;
|
1103
|
+
}
|
1104
|
+
|
1105
|
+
case 0322:
|
1106
|
+
break;
|
1107
|
+
|
1108
|
+
case 0323:
|
1109
|
+
rex_mask &= ~REX_W;
|
1110
|
+
break;
|
1111
|
+
|
1112
|
+
case 0324:
|
1113
|
+
ins->rex |= REX_W;
|
1114
|
+
break;
|
1115
|
+
|
1116
|
+
case 0325:
|
1117
|
+
ins->rex |= REX_NH;
|
1118
|
+
break;
|
1119
|
+
|
1120
|
+
case 0326:
|
1121
|
+
break;
|
1122
|
+
|
1123
|
+
case 0330:
|
1124
|
+
codes++, length++;
|
1125
|
+
break;
|
1126
|
+
|
1127
|
+
case 0331:
|
1128
|
+
break;
|
1129
|
+
|
1130
|
+
case 0332:
|
1131
|
+
case 0333:
|
1132
|
+
length++;
|
1133
|
+
break;
|
1134
|
+
|
1135
|
+
case 0334:
|
1136
|
+
ins->rex |= REX_L;
|
1137
|
+
break;
|
1138
|
+
|
1139
|
+
case 0335:
|
1140
|
+
break;
|
1141
|
+
|
1142
|
+
case 0336:
|
1143
|
+
if (!ins->prefixes[PPS_REP])
|
1144
|
+
ins->prefixes[PPS_REP] = P_REP;
|
1145
|
+
break;
|
1146
|
+
|
1147
|
+
case 0337:
|
1148
|
+
if (!ins->prefixes[PPS_REP])
|
1149
|
+
ins->prefixes[PPS_REP] = P_REPNE;
|
1150
|
+
break;
|
1151
|
+
|
1152
|
+
case 0340:
|
1153
|
+
if (!absolute_op(&ins->oprs[0]))
|
1154
|
+
nasm_error(ERR_NONFATAL, "attempt to reserve non-constant"
|
1155
|
+
" quantity of BSS space");
|
1156
|
+
else if (ins->oprs[0].opflags & OPFLAG_FORWARD)
|
1157
|
+
nasm_error(ERR_WARNING | ERR_PASS1,
|
1158
|
+
"forward reference in RESx can have unpredictable results");
|
1159
|
+
else
|
1160
|
+
length += ins->oprs[0].offset;
|
1161
|
+
break;
|
1162
|
+
|
1163
|
+
case 0341:
|
1164
|
+
if (!ins->prefixes[PPS_WAIT])
|
1165
|
+
ins->prefixes[PPS_WAIT] = P_WAIT;
|
1166
|
+
break;
|
1167
|
+
|
1168
|
+
case 0360:
|
1169
|
+
break;
|
1170
|
+
|
1171
|
+
case 0361:
|
1172
|
+
length++;
|
1173
|
+
break;
|
1174
|
+
|
1175
|
+
case 0364:
|
1176
|
+
case 0365:
|
1177
|
+
break;
|
1178
|
+
|
1179
|
+
case 0366:
|
1180
|
+
case 0367:
|
1181
|
+
length++;
|
1182
|
+
break;
|
1183
|
+
|
1184
|
+
case 0370:
|
1185
|
+
case 0371:
|
1186
|
+
break;
|
1187
|
+
|
1188
|
+
case 0373:
|
1189
|
+
length++;
|
1190
|
+
break;
|
1191
|
+
|
1192
|
+
case 0374:
|
1193
|
+
eat = EA_XMMVSIB;
|
1194
|
+
break;
|
1195
|
+
|
1196
|
+
case 0375:
|
1197
|
+
eat = EA_YMMVSIB;
|
1198
|
+
break;
|
1199
|
+
|
1200
|
+
case 0376:
|
1201
|
+
eat = EA_ZMMVSIB;
|
1202
|
+
break;
|
1203
|
+
|
1204
|
+
case4(0100):
|
1205
|
+
case4(0110):
|
1206
|
+
case4(0120):
|
1207
|
+
case4(0130):
|
1208
|
+
case4(0200):
|
1209
|
+
case4(0204):
|
1210
|
+
case4(0210):
|
1211
|
+
case4(0214):
|
1212
|
+
case4(0220):
|
1213
|
+
case4(0224):
|
1214
|
+
case4(0230):
|
1215
|
+
case4(0234):
|
1216
|
+
{
|
1217
|
+
ea ea_data;
|
1218
|
+
int rfield;
|
1219
|
+
opflags_t rflags;
|
1220
|
+
struct operand *opy = &ins->oprs[op2];
|
1221
|
+
struct operand *op_er_sae;
|
1222
|
+
|
1223
|
+
ea_data.rex = 0; /* Ensure ea.REX is initially 0 */
|
1224
|
+
|
1225
|
+
if (c <= 0177) {
|
1226
|
+
/* pick rfield from operand b (opx) */
|
1227
|
+
rflags = regflag(opx);
|
1228
|
+
rfield = nasm_regvals[opx->basereg];
|
1229
|
+
} else {
|
1230
|
+
rflags = 0;
|
1231
|
+
rfield = c & 7;
|
1232
|
+
}
|
1233
|
+
|
1234
|
+
/* EVEX.b1 : evex_brerop contains the operand position */
|
1235
|
+
op_er_sae = (ins->evex_brerop >= 0 ?
|
1236
|
+
&ins->oprs[ins->evex_brerop] : NULL);
|
1237
|
+
|
1238
|
+
if (op_er_sae && (op_er_sae->decoflags & (ER | SAE))) {
|
1239
|
+
/* set EVEX.b */
|
1240
|
+
ins->evex_p[2] |= EVEX_P2B;
|
1241
|
+
if (op_er_sae->decoflags & ER) {
|
1242
|
+
/* set EVEX.RC (rounding control) */
|
1243
|
+
ins->evex_p[2] |= ((ins->evex_rm - BRC_RN) << 5)
|
1244
|
+
& EVEX_P2RC;
|
1245
|
+
}
|
1246
|
+
} else {
|
1247
|
+
/* set EVEX.L'L (vector length) */
|
1248
|
+
ins->evex_p[2] |= ((ins->vex_wlp << (5 - 2)) & EVEX_P2LL);
|
1249
|
+
ins->evex_p[1] |= ((ins->vex_wlp << (7 - 4)) & EVEX_P1W);
|
1250
|
+
if (opy->decoflags & BRDCAST_MASK) {
|
1251
|
+
/* set EVEX.b */
|
1252
|
+
ins->evex_p[2] |= EVEX_P2B;
|
1253
|
+
}
|
1254
|
+
}
|
1255
|
+
|
1256
|
+
if (itemp_has(temp, IF_MIB)) {
|
1257
|
+
opy->eaflags |= EAF_MIB;
|
1258
|
+
/*
|
1259
|
+
* if a separate form of MIB (ICC style) is used,
|
1260
|
+
* the index reg info is merged into mem operand
|
1261
|
+
*/
|
1262
|
+
if (mib_index != R_none) {
|
1263
|
+
opy->indexreg = mib_index;
|
1264
|
+
opy->scale = 1;
|
1265
|
+
opy->hintbase = mib_index;
|
1266
|
+
opy->hinttype = EAH_NOTBASE;
|
1267
|
+
}
|
1268
|
+
}
|
1269
|
+
|
1270
|
+
if (process_ea(opy, &ea_data, bits,
|
1271
|
+
rfield, rflags, ins, &errmsg) != eat) {
|
1272
|
+
nasm_error(ERR_NONFATAL, "%s", errmsg);
|
1273
|
+
return -1;
|
1274
|
+
} else {
|
1275
|
+
ins->rex |= ea_data.rex;
|
1276
|
+
length += ea_data.size;
|
1277
|
+
}
|
1278
|
+
}
|
1279
|
+
break;
|
1280
|
+
|
1281
|
+
default:
|
1282
|
+
nasm_panic(0, "internal instruction table corrupt"
|
1283
|
+
": instruction code \\%o (0x%02X) given", c, c);
|
1284
|
+
break;
|
1285
|
+
}
|
1286
|
+
}
|
1287
|
+
|
1288
|
+
ins->rex &= rex_mask;
|
1289
|
+
|
1290
|
+
if (ins->rex & REX_NH) {
|
1291
|
+
if (ins->rex & REX_H) {
|
1292
|
+
nasm_error(ERR_NONFATAL, "instruction cannot use high registers");
|
1293
|
+
return -1;
|
1294
|
+
}
|
1295
|
+
ins->rex &= ~REX_P; /* Don't force REX prefix due to high reg */
|
1296
|
+
}
|
1297
|
+
|
1298
|
+
switch (ins->prefixes[PPS_VEX]) {
|
1299
|
+
case P_EVEX:
|
1300
|
+
if (!(ins->rex & REX_EV))
|
1301
|
+
return -1;
|
1302
|
+
break;
|
1303
|
+
case P_VEX3:
|
1304
|
+
case P_VEX2:
|
1305
|
+
if (!(ins->rex & REX_V))
|
1306
|
+
return -1;
|
1307
|
+
break;
|
1308
|
+
default:
|
1309
|
+
break;
|
1310
|
+
}
|
1311
|
+
|
1312
|
+
if (ins->rex & (REX_V | REX_EV)) {
|
1313
|
+
int bad32 = REX_R|REX_W|REX_X|REX_B;
|
1314
|
+
|
1315
|
+
if (ins->rex & REX_H) {
|
1316
|
+
nasm_error(ERR_NONFATAL, "cannot use high register in AVX instruction");
|
1317
|
+
return -1;
|
1318
|
+
}
|
1319
|
+
switch (ins->vex_wlp & 060) {
|
1320
|
+
case 000:
|
1321
|
+
case 040:
|
1322
|
+
ins->rex &= ~REX_W;
|
1323
|
+
break;
|
1324
|
+
case 020:
|
1325
|
+
ins->rex |= REX_W;
|
1326
|
+
bad32 &= ~REX_W;
|
1327
|
+
break;
|
1328
|
+
case 060:
|
1329
|
+
/* Follow REX_W */
|
1330
|
+
break;
|
1331
|
+
}
|
1332
|
+
|
1333
|
+
if (bits != 64 && ((ins->rex & bad32) || ins->vexreg > 7)) {
|
1334
|
+
nasm_error(ERR_NONFATAL, "invalid operands in non-64-bit mode");
|
1335
|
+
return -1;
|
1336
|
+
} else if (!(ins->rex & REX_EV) &&
|
1337
|
+
((ins->vexreg > 15) || (ins->evex_p[0] & 0xf0))) {
|
1338
|
+
nasm_error(ERR_NONFATAL, "invalid high-16 register in non-AVX-512");
|
1339
|
+
return -1;
|
1340
|
+
}
|
1341
|
+
if (ins->rex & REX_EV)
|
1342
|
+
length += 4;
|
1343
|
+
else if (ins->vex_cm != 1 || (ins->rex & (REX_W|REX_X|REX_B)) ||
|
1344
|
+
ins->prefixes[PPS_VEX] == P_VEX3)
|
1345
|
+
length += 3;
|
1346
|
+
else
|
1347
|
+
length += 2;
|
1348
|
+
} else if (ins->rex & REX_MASK) {
|
1349
|
+
if (ins->rex & REX_H) {
|
1350
|
+
nasm_error(ERR_NONFATAL, "cannot use high register in rex instruction");
|
1351
|
+
return -1;
|
1352
|
+
} else if (bits == 64) {
|
1353
|
+
length++;
|
1354
|
+
} else if ((ins->rex & REX_L) &&
|
1355
|
+
!(ins->rex & (REX_P|REX_W|REX_X|REX_B)) &&
|
1356
|
+
iflag_cpu_level_ok(&cpu, IF_X86_64)) {
|
1357
|
+
/* LOCK-as-REX.R */
|
1358
|
+
assert_no_prefix(ins, PPS_LOCK);
|
1359
|
+
lockcheck = false; /* Already errored, no need for warning */
|
1360
|
+
length++;
|
1361
|
+
} else {
|
1362
|
+
nasm_error(ERR_NONFATAL, "invalid operands in non-64-bit mode");
|
1363
|
+
return -1;
|
1364
|
+
}
|
1365
|
+
}
|
1366
|
+
|
1367
|
+
if (has_prefix(ins, PPS_LOCK, P_LOCK) && lockcheck &&
|
1368
|
+
(!itemp_has(temp,IF_LOCK) || !is_class(MEMORY, ins->oprs[0].type))) {
|
1369
|
+
nasm_error(ERR_WARNING | ERR_WARN_LOCK | ERR_PASS2 ,
|
1370
|
+
"instruction is not lockable");
|
1371
|
+
}
|
1372
|
+
|
1373
|
+
bad_hle_warn(ins, hleok);
|
1374
|
+
|
1375
|
+
/*
|
1376
|
+
* when BND prefix is set by DEFAULT directive,
|
1377
|
+
* BND prefix is added to every appropriate instruction line
|
1378
|
+
* unless it is overridden by NOBND prefix.
|
1379
|
+
*/
|
1380
|
+
if (globalbnd &&
|
1381
|
+
(itemp_has(temp, IF_BND) && !has_prefix(ins, PPS_REP, P_NOBND)))
|
1382
|
+
ins->prefixes[PPS_REP] = P_BND;
|
1383
|
+
|
1384
|
+
/*
|
1385
|
+
* Add length of legacy prefixes
|
1386
|
+
*/
|
1387
|
+
length += emit_prefix(NULL, bits, ins);
|
1388
|
+
|
1389
|
+
return length;
|
1390
|
+
}
|
1391
|
+
|
1392
|
+
static inline void emit_rex(struct out_data *data, insn *ins)
|
1393
|
+
{
|
1394
|
+
if (data->bits == 64) {
|
1395
|
+
if ((ins->rex & REX_MASK) &&
|
1396
|
+
!(ins->rex & (REX_V | REX_EV)) &&
|
1397
|
+
!ins->rex_done) {
|
1398
|
+
uint8_t rex = (ins->rex & REX_MASK) | REX_P;
|
1399
|
+
out_rawbyte(data, rex);
|
1400
|
+
ins->rex_done = true;
|
1401
|
+
}
|
1402
|
+
}
|
1403
|
+
}
|
1404
|
+
|
1405
|
+
static int emit_prefix(struct out_data *data, const int bits, insn *ins)
|
1406
|
+
{
|
1407
|
+
int bytes = 0;
|
1408
|
+
int j;
|
1409
|
+
|
1410
|
+
for (j = 0; j < MAXPREFIX; j++) {
|
1411
|
+
uint8_t c = 0;
|
1412
|
+
switch (ins->prefixes[j]) {
|
1413
|
+
case P_WAIT:
|
1414
|
+
c = 0x9B;
|
1415
|
+
break;
|
1416
|
+
case P_LOCK:
|
1417
|
+
c = 0xF0;
|
1418
|
+
break;
|
1419
|
+
case P_REPNE:
|
1420
|
+
case P_REPNZ:
|
1421
|
+
case P_XACQUIRE:
|
1422
|
+
case P_BND:
|
1423
|
+
c = 0xF2;
|
1424
|
+
break;
|
1425
|
+
case P_REPE:
|
1426
|
+
case P_REPZ:
|
1427
|
+
case P_REP:
|
1428
|
+
case P_XRELEASE:
|
1429
|
+
c = 0xF3;
|
1430
|
+
break;
|
1431
|
+
case R_CS:
|
1432
|
+
if (bits == 64) {
|
1433
|
+
nasm_error(ERR_WARNING | ERR_PASS2,
|
1434
|
+
"cs segment base generated, but will be ignored in 64-bit mode");
|
1435
|
+
}
|
1436
|
+
c = 0x2E;
|
1437
|
+
break;
|
1438
|
+
case R_DS:
|
1439
|
+
if (bits == 64) {
|
1440
|
+
nasm_error(ERR_WARNING | ERR_PASS2,
|
1441
|
+
"ds segment base generated, but will be ignored in 64-bit mode");
|
1442
|
+
}
|
1443
|
+
c = 0x3E;
|
1444
|
+
break;
|
1445
|
+
case R_ES:
|
1446
|
+
if (bits == 64) {
|
1447
|
+
nasm_error(ERR_WARNING | ERR_PASS2,
|
1448
|
+
"es segment base generated, but will be ignored in 64-bit mode");
|
1449
|
+
}
|
1450
|
+
c = 0x26;
|
1451
|
+
break;
|
1452
|
+
case R_FS:
|
1453
|
+
c = 0x64;
|
1454
|
+
break;
|
1455
|
+
case R_GS:
|
1456
|
+
c = 0x65;
|
1457
|
+
break;
|
1458
|
+
case R_SS:
|
1459
|
+
if (bits == 64) {
|
1460
|
+
nasm_error(ERR_WARNING | ERR_PASS2,
|
1461
|
+
"ss segment base generated, but will be ignored in 64-bit mode");
|
1462
|
+
}
|
1463
|
+
c = 0x36;
|
1464
|
+
break;
|
1465
|
+
case R_SEGR6:
|
1466
|
+
case R_SEGR7:
|
1467
|
+
nasm_error(ERR_NONFATAL,
|
1468
|
+
"segr6 and segr7 cannot be used as prefixes");
|
1469
|
+
break;
|
1470
|
+
case P_A16:
|
1471
|
+
if (bits == 64) {
|
1472
|
+
nasm_error(ERR_NONFATAL,
|
1473
|
+
"16-bit addressing is not supported "
|
1474
|
+
"in 64-bit mode");
|
1475
|
+
} else if (bits != 16)
|
1476
|
+
c = 0x67;
|
1477
|
+
break;
|
1478
|
+
case P_A32:
|
1479
|
+
if (bits != 32)
|
1480
|
+
c = 0x67;
|
1481
|
+
break;
|
1482
|
+
case P_A64:
|
1483
|
+
if (bits != 64) {
|
1484
|
+
nasm_error(ERR_NONFATAL,
|
1485
|
+
"64-bit addressing is only supported "
|
1486
|
+
"in 64-bit mode");
|
1487
|
+
}
|
1488
|
+
break;
|
1489
|
+
case P_ASP:
|
1490
|
+
c = 0x67;
|
1491
|
+
break;
|
1492
|
+
case P_O16:
|
1493
|
+
if (bits != 16)
|
1494
|
+
c = 0x66;
|
1495
|
+
break;
|
1496
|
+
case P_O32:
|
1497
|
+
if (bits == 16)
|
1498
|
+
c = 0x66;
|
1499
|
+
break;
|
1500
|
+
case P_O64:
|
1501
|
+
/* REX.W */
|
1502
|
+
break;
|
1503
|
+
case P_OSP:
|
1504
|
+
c = 0x66;
|
1505
|
+
break;
|
1506
|
+
case P_EVEX:
|
1507
|
+
case P_VEX3:
|
1508
|
+
case P_VEX2:
|
1509
|
+
case P_NOBND:
|
1510
|
+
case P_none:
|
1511
|
+
break;
|
1512
|
+
default:
|
1513
|
+
nasm_panic(0, "invalid instruction prefix");
|
1514
|
+
}
|
1515
|
+
if (c) {
|
1516
|
+
if (data)
|
1517
|
+
out_rawbyte(data, c);
|
1518
|
+
bytes++;
|
1519
|
+
}
|
1520
|
+
}
|
1521
|
+
return bytes;
|
1522
|
+
}
|
1523
|
+
|
1524
|
+
static void gencode(struct out_data *data, insn *ins)
|
1525
|
+
{
|
1526
|
+
uint8_t c;
|
1527
|
+
uint8_t bytes[4];
|
1528
|
+
int64_t size;
|
1529
|
+
int op1, op2;
|
1530
|
+
struct operand *opx;
|
1531
|
+
const uint8_t *codes = data->itemp->code;
|
1532
|
+
uint8_t opex = 0;
|
1533
|
+
enum ea_type eat = EA_SCALAR;
|
1534
|
+
int r;
|
1535
|
+
const int bits = data->bits;
|
1536
|
+
const char *errmsg;
|
1537
|
+
|
1538
|
+
ins->rex_done = false;
|
1539
|
+
|
1540
|
+
emit_prefix(data, bits, ins);
|
1541
|
+
|
1542
|
+
while (*codes) {
|
1543
|
+
c = *codes++;
|
1544
|
+
op1 = (c & 3) + ((opex & 1) << 2);
|
1545
|
+
op2 = ((c >> 3) & 3) + ((opex & 2) << 1);
|
1546
|
+
opx = &ins->oprs[op1];
|
1547
|
+
opex = 0; /* For the next iteration */
|
1548
|
+
|
1549
|
+
|
1550
|
+
switch (c) {
|
1551
|
+
case 01:
|
1552
|
+
case 02:
|
1553
|
+
case 03:
|
1554
|
+
case 04:
|
1555
|
+
emit_rex(data, ins);
|
1556
|
+
out_rawdata(data, codes, c);
|
1557
|
+
codes += c;
|
1558
|
+
break;
|
1559
|
+
|
1560
|
+
case 05:
|
1561
|
+
case 06:
|
1562
|
+
case 07:
|
1563
|
+
opex = c;
|
1564
|
+
break;
|
1565
|
+
|
1566
|
+
case4(010):
|
1567
|
+
emit_rex(data, ins);
|
1568
|
+
out_rawbyte(data, *codes++ + (regval(opx) & 7));
|
1569
|
+
break;
|
1570
|
+
|
1571
|
+
case4(014):
|
1572
|
+
break;
|
1573
|
+
|
1574
|
+
case4(020):
|
1575
|
+
out_imm(data, opx, 1, OUT_WRAP);
|
1576
|
+
break;
|
1577
|
+
|
1578
|
+
case4(024):
|
1579
|
+
out_imm(data, opx, 1, OUT_UNSIGNED);
|
1580
|
+
break;
|
1581
|
+
|
1582
|
+
case4(030):
|
1583
|
+
out_imm(data, opx, 2, OUT_WRAP);
|
1584
|
+
break;
|
1585
|
+
|
1586
|
+
case4(034):
|
1587
|
+
if (opx->type & (BITS16 | BITS32))
|
1588
|
+
size = (opx->type & BITS16) ? 2 : 4;
|
1589
|
+
else
|
1590
|
+
size = (bits == 16) ? 2 : 4;
|
1591
|
+
out_imm(data, opx, size, OUT_WRAP);
|
1592
|
+
break;
|
1593
|
+
|
1594
|
+
case4(040):
|
1595
|
+
out_imm(data, opx, 4, OUT_WRAP);
|
1596
|
+
break;
|
1597
|
+
|
1598
|
+
case4(044):
|
1599
|
+
size = ins->addr_size >> 3;
|
1600
|
+
out_imm(data, opx, size, OUT_WRAP);
|
1601
|
+
break;
|
1602
|
+
|
1603
|
+
case4(050):
|
1604
|
+
if (opx->segment == data->segment) {
|
1605
|
+
int64_t delta = opx->offset - data->offset
|
1606
|
+
- (data->inslen - data->insoffs);
|
1607
|
+
if (delta > 127 || delta < -128)
|
1608
|
+
nasm_error(ERR_NONFATAL, "short jump is out of range");
|
1609
|
+
}
|
1610
|
+
out_reladdr(data, opx, 1);
|
1611
|
+
break;
|
1612
|
+
|
1613
|
+
case4(054):
|
1614
|
+
out_imm(data, opx, 8, OUT_WRAP);
|
1615
|
+
break;
|
1616
|
+
|
1617
|
+
case4(060):
|
1618
|
+
out_reladdr(data, opx, 2);
|
1619
|
+
break;
|
1620
|
+
|
1621
|
+
case4(064):
|
1622
|
+
if (opx->type & (BITS16 | BITS32 | BITS64))
|
1623
|
+
size = (opx->type & BITS16) ? 2 : 4;
|
1624
|
+
else
|
1625
|
+
size = (bits == 16) ? 2 : 4;
|
1626
|
+
|
1627
|
+
out_reladdr(data, opx, size);
|
1628
|
+
break;
|
1629
|
+
|
1630
|
+
case4(070):
|
1631
|
+
out_reladdr(data, opx, 4);
|
1632
|
+
break;
|
1633
|
+
|
1634
|
+
case4(074):
|
1635
|
+
if (opx->segment == NO_SEG)
|
1636
|
+
nasm_error(ERR_NONFATAL, "value referenced by FAR is not"
|
1637
|
+
" relocatable");
|
1638
|
+
out_segment(data, opx);
|
1639
|
+
break;
|
1640
|
+
|
1641
|
+
case 0172:
|
1642
|
+
{
|
1643
|
+
int mask = ins->prefixes[PPS_VEX] == P_EVEX ? 7 : 15;
|
1644
|
+
const struct operand *opy;
|
1645
|
+
|
1646
|
+
c = *codes++;
|
1647
|
+
opx = &ins->oprs[c >> 3];
|
1648
|
+
opy = &ins->oprs[c & 7];
|
1649
|
+
if (!absolute_op(opy)) {
|
1650
|
+
nasm_error(ERR_NONFATAL,
|
1651
|
+
"non-absolute expression not permitted as argument %d",
|
1652
|
+
c & 7);
|
1653
|
+
} else if (opy->offset & ~mask) {
|
1654
|
+
nasm_error(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
|
1655
|
+
"is4 argument exceeds bounds");
|
1656
|
+
}
|
1657
|
+
c = opy->offset & mask;
|
1658
|
+
goto emit_is4;
|
1659
|
+
}
|
1660
|
+
|
1661
|
+
case 0173:
|
1662
|
+
c = *codes++;
|
1663
|
+
opx = &ins->oprs[c >> 4];
|
1664
|
+
c &= 15;
|
1665
|
+
goto emit_is4;
|
1666
|
+
|
1667
|
+
case4(0174):
|
1668
|
+
c = 0;
|
1669
|
+
emit_is4:
|
1670
|
+
r = nasm_regvals[opx->basereg];
|
1671
|
+
out_rawbyte(data, (r << 4) | ((r & 0x10) >> 1) | c);
|
1672
|
+
break;
|
1673
|
+
|
1674
|
+
case4(0254):
|
1675
|
+
if (absolute_op(opx) &&
|
1676
|
+
(int32_t)opx->offset != (int64_t)opx->offset) {
|
1677
|
+
nasm_error(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
|
1678
|
+
"signed dword immediate exceeds bounds");
|
1679
|
+
}
|
1680
|
+
out_imm(data, opx, 4, OUT_SIGNED);
|
1681
|
+
break;
|
1682
|
+
|
1683
|
+
case4(0240):
|
1684
|
+
case 0250:
|
1685
|
+
codes += 3;
|
1686
|
+
ins->evex_p[2] |= op_evexflags(&ins->oprs[0],
|
1687
|
+
EVEX_P2Z | EVEX_P2AAA, 2);
|
1688
|
+
ins->evex_p[2] ^= EVEX_P2VP; /* 1's complement */
|
1689
|
+
bytes[0] = 0x62;
|
1690
|
+
/* EVEX.X can be set by either REX or EVEX for different reasons */
|
1691
|
+
bytes[1] = ((((ins->rex & 7) << 5) |
|
1692
|
+
(ins->evex_p[0] & (EVEX_P0X | EVEX_P0RP))) ^ 0xf0) |
|
1693
|
+
(ins->vex_cm & EVEX_P0MM);
|
1694
|
+
bytes[2] = ((ins->rex & REX_W) << (7 - 3)) |
|
1695
|
+
((~ins->vexreg & 15) << 3) |
|
1696
|
+
(1 << 2) | (ins->vex_wlp & 3);
|
1697
|
+
bytes[3] = ins->evex_p[2];
|
1698
|
+
out_rawdata(data, bytes, 4);
|
1699
|
+
break;
|
1700
|
+
|
1701
|
+
case4(0260):
|
1702
|
+
case 0270:
|
1703
|
+
codes += 2;
|
1704
|
+
if (ins->vex_cm != 1 || (ins->rex & (REX_W|REX_X|REX_B)) ||
|
1705
|
+
ins->prefixes[PPS_VEX] == P_VEX3) {
|
1706
|
+
bytes[0] = (ins->vex_cm >> 6) ? 0x8f : 0xc4;
|
1707
|
+
bytes[1] = (ins->vex_cm & 31) | ((~ins->rex & 7) << 5);
|
1708
|
+
bytes[2] = ((ins->rex & REX_W) << (7-3)) |
|
1709
|
+
((~ins->vexreg & 15)<< 3) | (ins->vex_wlp & 07);
|
1710
|
+
out_rawdata(data, bytes, 3);
|
1711
|
+
} else {
|
1712
|
+
bytes[0] = 0xc5;
|
1713
|
+
bytes[1] = ((~ins->rex & REX_R) << (7-2)) |
|
1714
|
+
((~ins->vexreg & 15) << 3) | (ins->vex_wlp & 07);
|
1715
|
+
out_rawdata(data, bytes, 2);
|
1716
|
+
}
|
1717
|
+
break;
|
1718
|
+
|
1719
|
+
case 0271:
|
1720
|
+
case 0272:
|
1721
|
+
case 0273:
|
1722
|
+
break;
|
1723
|
+
|
1724
|
+
case4(0274):
|
1725
|
+
{
|
1726
|
+
uint64_t uv, um;
|
1727
|
+
int s;
|
1728
|
+
|
1729
|
+
if (absolute_op(opx)) {
|
1730
|
+
if (ins->rex & REX_W)
|
1731
|
+
s = 64;
|
1732
|
+
else if (ins->prefixes[PPS_OSIZE] == P_O16)
|
1733
|
+
s = 16;
|
1734
|
+
else if (ins->prefixes[PPS_OSIZE] == P_O32)
|
1735
|
+
s = 32;
|
1736
|
+
else
|
1737
|
+
s = bits;
|
1738
|
+
|
1739
|
+
um = (uint64_t)2 << (s-1);
|
1740
|
+
uv = opx->offset;
|
1741
|
+
|
1742
|
+
if (uv > 127 && uv < (uint64_t)-128 &&
|
1743
|
+
(uv < um-128 || uv > um-1)) {
|
1744
|
+
/* If this wasn't explicitly byte-sized, warn as though we
|
1745
|
+
* had fallen through to the imm16/32/64 case.
|
1746
|
+
*/
|
1747
|
+
nasm_error(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
|
1748
|
+
"%s value exceeds bounds",
|
1749
|
+
(opx->type & BITS8) ? "signed byte" :
|
1750
|
+
s == 16 ? "word" :
|
1751
|
+
s == 32 ? "dword" :
|
1752
|
+
"signed dword");
|
1753
|
+
}
|
1754
|
+
|
1755
|
+
/* Output as a raw byte to avoid byte overflow check */
|
1756
|
+
out_rawbyte(data, (uint8_t)uv);
|
1757
|
+
} else {
|
1758
|
+
out_imm(data, opx, 1, OUT_WRAP); /* XXX: OUT_SIGNED? */
|
1759
|
+
}
|
1760
|
+
break;
|
1761
|
+
}
|
1762
|
+
|
1763
|
+
case4(0300):
|
1764
|
+
break;
|
1765
|
+
|
1766
|
+
case 0310:
|
1767
|
+
if (bits == 32 && !has_prefix(ins, PPS_ASIZE, P_A16))
|
1768
|
+
out_rawbyte(data, 0x67);
|
1769
|
+
break;
|
1770
|
+
|
1771
|
+
case 0311:
|
1772
|
+
if (bits != 32 && !has_prefix(ins, PPS_ASIZE, P_A32))
|
1773
|
+
out_rawbyte(data, 0x67);
|
1774
|
+
break;
|
1775
|
+
|
1776
|
+
case 0312:
|
1777
|
+
break;
|
1778
|
+
|
1779
|
+
case 0313:
|
1780
|
+
ins->rex = 0;
|
1781
|
+
break;
|
1782
|
+
|
1783
|
+
case4(0314):
|
1784
|
+
break;
|
1785
|
+
|
1786
|
+
case 0320:
|
1787
|
+
case 0321:
|
1788
|
+
break;
|
1789
|
+
|
1790
|
+
case 0322:
|
1791
|
+
case 0323:
|
1792
|
+
break;
|
1793
|
+
|
1794
|
+
case 0324:
|
1795
|
+
ins->rex |= REX_W;
|
1796
|
+
break;
|
1797
|
+
|
1798
|
+
case 0325:
|
1799
|
+
break;
|
1800
|
+
|
1801
|
+
case 0326:
|
1802
|
+
break;
|
1803
|
+
|
1804
|
+
case 0330:
|
1805
|
+
out_rawbyte(data, *codes++ ^ get_cond_opcode(ins->condition));
|
1806
|
+
break;
|
1807
|
+
|
1808
|
+
case 0331:
|
1809
|
+
break;
|
1810
|
+
|
1811
|
+
case 0332:
|
1812
|
+
case 0333:
|
1813
|
+
out_rawbyte(data, c - 0332 + 0xF2);
|
1814
|
+
break;
|
1815
|
+
|
1816
|
+
case 0334:
|
1817
|
+
if (ins->rex & REX_R)
|
1818
|
+
out_rawbyte(data, 0xF0);
|
1819
|
+
ins->rex &= ~(REX_L|REX_R);
|
1820
|
+
break;
|
1821
|
+
|
1822
|
+
case 0335:
|
1823
|
+
break;
|
1824
|
+
|
1825
|
+
case 0336:
|
1826
|
+
case 0337:
|
1827
|
+
break;
|
1828
|
+
|
1829
|
+
case 0340:
|
1830
|
+
if (ins->oprs[0].segment != NO_SEG)
|
1831
|
+
nasm_panic(0, "non-constant BSS size in pass two");
|
1832
|
+
|
1833
|
+
out_reserve(data, ins->oprs[0].offset);
|
1834
|
+
break;
|
1835
|
+
|
1836
|
+
case 0341:
|
1837
|
+
break;
|
1838
|
+
|
1839
|
+
case 0360:
|
1840
|
+
break;
|
1841
|
+
|
1842
|
+
case 0361:
|
1843
|
+
out_rawbyte(data, 0x66);
|
1844
|
+
break;
|
1845
|
+
|
1846
|
+
case 0364:
|
1847
|
+
case 0365:
|
1848
|
+
break;
|
1849
|
+
|
1850
|
+
case 0366:
|
1851
|
+
case 0367:
|
1852
|
+
out_rawbyte(data, c - 0366 + 0x66);
|
1853
|
+
break;
|
1854
|
+
|
1855
|
+
case3(0370):
|
1856
|
+
break;
|
1857
|
+
|
1858
|
+
case 0373:
|
1859
|
+
out_rawbyte(data, bits == 16 ? 3 : 5);
|
1860
|
+
break;
|
1861
|
+
|
1862
|
+
case 0374:
|
1863
|
+
eat = EA_XMMVSIB;
|
1864
|
+
break;
|
1865
|
+
|
1866
|
+
case 0375:
|
1867
|
+
eat = EA_YMMVSIB;
|
1868
|
+
break;
|
1869
|
+
|
1870
|
+
case 0376:
|
1871
|
+
eat = EA_ZMMVSIB;
|
1872
|
+
break;
|
1873
|
+
|
1874
|
+
case4(0100):
|
1875
|
+
case4(0110):
|
1876
|
+
case4(0120):
|
1877
|
+
case4(0130):
|
1878
|
+
case4(0200):
|
1879
|
+
case4(0204):
|
1880
|
+
case4(0210):
|
1881
|
+
case4(0214):
|
1882
|
+
case4(0220):
|
1883
|
+
case4(0224):
|
1884
|
+
case4(0230):
|
1885
|
+
case4(0234):
|
1886
|
+
{
|
1887
|
+
ea ea_data;
|
1888
|
+
int rfield;
|
1889
|
+
opflags_t rflags;
|
1890
|
+
uint8_t *p;
|
1891
|
+
struct operand *opy = &ins->oprs[op2];
|
1892
|
+
|
1893
|
+
if (c <= 0177) {
|
1894
|
+
/* pick rfield from operand b (opx) */
|
1895
|
+
rflags = regflag(opx);
|
1896
|
+
rfield = nasm_regvals[opx->basereg];
|
1897
|
+
} else {
|
1898
|
+
/* rfield is constant */
|
1899
|
+
rflags = 0;
|
1900
|
+
rfield = c & 7;
|
1901
|
+
}
|
1902
|
+
|
1903
|
+
if (process_ea(opy, &ea_data, bits,
|
1904
|
+
rfield, rflags, ins, &errmsg) != eat)
|
1905
|
+
nasm_error(ERR_NONFATAL, "%s", errmsg);
|
1906
|
+
|
1907
|
+
p = bytes;
|
1908
|
+
*p++ = ea_data.modrm;
|
1909
|
+
if (ea_data.sib_present)
|
1910
|
+
*p++ = ea_data.sib;
|
1911
|
+
out_rawdata(data, bytes, p - bytes);
|
1912
|
+
|
1913
|
+
/*
|
1914
|
+
* Make sure the address gets the right offset in case
|
1915
|
+
* the line breaks in the .lst file (BR 1197827)
|
1916
|
+
*/
|
1917
|
+
|
1918
|
+
if (ea_data.bytes) {
|
1919
|
+
/* use compressed displacement, if available */
|
1920
|
+
if (ea_data.disp8) {
|
1921
|
+
out_rawbyte(data, ea_data.disp8);
|
1922
|
+
} else if (ea_data.rip) {
|
1923
|
+
out_reladdr(data, opy, ea_data.bytes);
|
1924
|
+
} else {
|
1925
|
+
int asize = ins->addr_size >> 3;
|
1926
|
+
|
1927
|
+
if (overflow_general(opy->offset, asize) ||
|
1928
|
+
signed_bits(opy->offset, ins->addr_size) !=
|
1929
|
+
signed_bits(opy->offset, ea_data.bytes << 3))
|
1930
|
+
warn_overflow(ea_data.bytes);
|
1931
|
+
|
1932
|
+
out_imm(data, opy, ea_data.bytes,
|
1933
|
+
(asize > ea_data.bytes)
|
1934
|
+
? OUT_SIGNED : OUT_WRAP);
|
1935
|
+
}
|
1936
|
+
}
|
1937
|
+
}
|
1938
|
+
break;
|
1939
|
+
|
1940
|
+
default:
|
1941
|
+
nasm_panic(0, "internal instruction table corrupt"
|
1942
|
+
": instruction code \\%o (0x%02X) given", c, c);
|
1943
|
+
break;
|
1944
|
+
}
|
1945
|
+
}
|
1946
|
+
}
|
1947
|
+
|
1948
|
+
static opflags_t regflag(const operand * o)
|
1949
|
+
{
|
1950
|
+
if (!is_register(o->basereg))
|
1951
|
+
nasm_panic(0, "invalid operand passed to regflag()");
|
1952
|
+
return nasm_reg_flags[o->basereg];
|
1953
|
+
}
|
1954
|
+
|
1955
|
+
static int32_t regval(const operand * o)
|
1956
|
+
{
|
1957
|
+
if (!is_register(o->basereg))
|
1958
|
+
nasm_panic(0, "invalid operand passed to regval()");
|
1959
|
+
return nasm_regvals[o->basereg];
|
1960
|
+
}
|
1961
|
+
|
1962
|
+
static int op_rexflags(const operand * o, int mask)
|
1963
|
+
{
|
1964
|
+
opflags_t flags;
|
1965
|
+
int val;
|
1966
|
+
|
1967
|
+
if (!is_register(o->basereg))
|
1968
|
+
nasm_panic(0, "invalid operand passed to op_rexflags()");
|
1969
|
+
|
1970
|
+
flags = nasm_reg_flags[o->basereg];
|
1971
|
+
val = nasm_regvals[o->basereg];
|
1972
|
+
|
1973
|
+
return rexflags(val, flags, mask);
|
1974
|
+
}
|
1975
|
+
|
1976
|
+
static int rexflags(int val, opflags_t flags, int mask)
|
1977
|
+
{
|
1978
|
+
int rex = 0;
|
1979
|
+
|
1980
|
+
if (val >= 0 && (val & 8))
|
1981
|
+
rex |= REX_B|REX_X|REX_R;
|
1982
|
+
if (flags & BITS64)
|
1983
|
+
rex |= REX_W;
|
1984
|
+
if (!(REG_HIGH & ~flags)) /* AH, CH, DH, BH */
|
1985
|
+
rex |= REX_H;
|
1986
|
+
else if (!(REG8 & ~flags) && val >= 4) /* SPL, BPL, SIL, DIL */
|
1987
|
+
rex |= REX_P;
|
1988
|
+
|
1989
|
+
return rex & mask;
|
1990
|
+
}
|
1991
|
+
|
1992
|
+
static int evexflags(int val, decoflags_t deco,
|
1993
|
+
int mask, uint8_t byte)
|
1994
|
+
{
|
1995
|
+
int evex = 0;
|
1996
|
+
|
1997
|
+
switch (byte) {
|
1998
|
+
case 0:
|
1999
|
+
if (val >= 0 && (val & 16))
|
2000
|
+
evex |= (EVEX_P0RP | EVEX_P0X);
|
2001
|
+
break;
|
2002
|
+
case 2:
|
2003
|
+
if (val >= 0 && (val & 16))
|
2004
|
+
evex |= EVEX_P2VP;
|
2005
|
+
if (deco & Z)
|
2006
|
+
evex |= EVEX_P2Z;
|
2007
|
+
if (deco & OPMASK_MASK)
|
2008
|
+
evex |= deco & EVEX_P2AAA;
|
2009
|
+
break;
|
2010
|
+
}
|
2011
|
+
return evex & mask;
|
2012
|
+
}
|
2013
|
+
|
2014
|
+
static int op_evexflags(const operand * o, int mask, uint8_t byte)
|
2015
|
+
{
|
2016
|
+
int val;
|
2017
|
+
|
2018
|
+
val = nasm_regvals[o->basereg];
|
2019
|
+
|
2020
|
+
return evexflags(val, o->decoflags, mask, byte);
|
2021
|
+
}
|
2022
|
+
|
2023
|
+
static enum match_result find_match(const struct itemplate **tempp,
|
2024
|
+
insn *instruction,
|
2025
|
+
int32_t segment, int64_t offset, int bits)
|
2026
|
+
{
|
2027
|
+
const struct itemplate *temp;
|
2028
|
+
enum match_result m, merr;
|
2029
|
+
opflags_t xsizeflags[MAX_OPERANDS];
|
2030
|
+
bool opsizemissing = false;
|
2031
|
+
int8_t broadcast = instruction->evex_brerop;
|
2032
|
+
int i;
|
2033
|
+
|
2034
|
+
/* broadcasting uses a different data element size */
|
2035
|
+
for (i = 0; i < instruction->operands; i++)
|
2036
|
+
if (i == broadcast)
|
2037
|
+
xsizeflags[i] = instruction->oprs[i].decoflags & BRSIZE_MASK;
|
2038
|
+
else
|
2039
|
+
xsizeflags[i] = instruction->oprs[i].type & SIZE_MASK;
|
2040
|
+
|
2041
|
+
merr = MERR_INVALOP;
|
2042
|
+
|
2043
|
+
for (temp = nasm_instructions[instruction->opcode];
|
2044
|
+
temp->opcode != I_none; temp++) {
|
2045
|
+
m = matches(temp, instruction, bits);
|
2046
|
+
if (m == MOK_JUMP) {
|
2047
|
+
if (jmp_match(segment, offset, bits, instruction, temp))
|
2048
|
+
m = MOK_GOOD;
|
2049
|
+
else
|
2050
|
+
m = MERR_INVALOP;
|
2051
|
+
} else if (m == MERR_OPSIZEMISSING && !itemp_has(temp, IF_SX)) {
|
2052
|
+
/*
|
2053
|
+
* Missing operand size and a candidate for fuzzy matching...
|
2054
|
+
*/
|
2055
|
+
for (i = 0; i < temp->operands; i++)
|
2056
|
+
if (i == broadcast)
|
2057
|
+
xsizeflags[i] |= temp->deco[i] & BRSIZE_MASK;
|
2058
|
+
else
|
2059
|
+
xsizeflags[i] |= temp->opd[i] & SIZE_MASK;
|
2060
|
+
opsizemissing = true;
|
2061
|
+
}
|
2062
|
+
if (m > merr)
|
2063
|
+
merr = m;
|
2064
|
+
if (merr == MOK_GOOD)
|
2065
|
+
goto done;
|
2066
|
+
}
|
2067
|
+
|
2068
|
+
/* No match, but see if we can get a fuzzy operand size match... */
|
2069
|
+
if (!opsizemissing)
|
2070
|
+
goto done;
|
2071
|
+
|
2072
|
+
for (i = 0; i < instruction->operands; i++) {
|
2073
|
+
/*
|
2074
|
+
* We ignore extrinsic operand sizes on registers, so we should
|
2075
|
+
* never try to fuzzy-match on them. This also resolves the case
|
2076
|
+
* when we have e.g. "xmmrm128" in two different positions.
|
2077
|
+
*/
|
2078
|
+
if (is_class(REGISTER, instruction->oprs[i].type))
|
2079
|
+
continue;
|
2080
|
+
|
2081
|
+
/* This tests if xsizeflags[i] has more than one bit set */
|
2082
|
+
if ((xsizeflags[i] & (xsizeflags[i]-1)))
|
2083
|
+
goto done; /* No luck */
|
2084
|
+
|
2085
|
+
if (i == broadcast) {
|
2086
|
+
instruction->oprs[i].decoflags |= xsizeflags[i];
|
2087
|
+
instruction->oprs[i].type |= (xsizeflags[i] == BR_BITS32 ?
|
2088
|
+
BITS32 : BITS64);
|
2089
|
+
} else {
|
2090
|
+
instruction->oprs[i].type |= xsizeflags[i]; /* Set the size */
|
2091
|
+
}
|
2092
|
+
}
|
2093
|
+
|
2094
|
+
/* Try matching again... */
|
2095
|
+
for (temp = nasm_instructions[instruction->opcode];
|
2096
|
+
temp->opcode != I_none; temp++) {
|
2097
|
+
m = matches(temp, instruction, bits);
|
2098
|
+
if (m == MOK_JUMP) {
|
2099
|
+
if (jmp_match(segment, offset, bits, instruction, temp))
|
2100
|
+
m = MOK_GOOD;
|
2101
|
+
else
|
2102
|
+
m = MERR_INVALOP;
|
2103
|
+
}
|
2104
|
+
if (m > merr)
|
2105
|
+
merr = m;
|
2106
|
+
if (merr == MOK_GOOD)
|
2107
|
+
goto done;
|
2108
|
+
}
|
2109
|
+
|
2110
|
+
done:
|
2111
|
+
*tempp = temp;
|
2112
|
+
return merr;
|
2113
|
+
}
|
2114
|
+
|
2115
|
+
static uint8_t get_broadcast_num(opflags_t opflags, opflags_t brsize)
|
2116
|
+
{
|
2117
|
+
unsigned int opsize = (opflags & SIZE_MASK) >> SIZE_SHIFT;
|
2118
|
+
uint8_t brcast_num;
|
2119
|
+
|
2120
|
+
if (brsize > BITS64)
|
2121
|
+
nasm_error(ERR_FATAL,
|
2122
|
+
"size of broadcasting element is greater than 64 bits");
|
2123
|
+
|
2124
|
+
/*
|
2125
|
+
* The shift term is to take care of the extra BITS80 inserted
|
2126
|
+
* between BITS64 and BITS128.
|
2127
|
+
*/
|
2128
|
+
brcast_num = ((opsize / (BITS64 >> SIZE_SHIFT)) * (BITS64 / brsize))
|
2129
|
+
>> (opsize > (BITS64 >> SIZE_SHIFT));
|
2130
|
+
|
2131
|
+
return brcast_num;
|
2132
|
+
}
|
2133
|
+
|
2134
|
+
static enum match_result matches(const struct itemplate *itemp,
|
2135
|
+
insn *instruction, int bits)
|
2136
|
+
{
|
2137
|
+
opflags_t size[MAX_OPERANDS], asize;
|
2138
|
+
bool opsizemissing = false;
|
2139
|
+
int i, oprs;
|
2140
|
+
|
2141
|
+
/*
|
2142
|
+
* Check the opcode
|
2143
|
+
*/
|
2144
|
+
if (itemp->opcode != instruction->opcode)
|
2145
|
+
return MERR_INVALOP;
|
2146
|
+
|
2147
|
+
/*
|
2148
|
+
* Count the operands
|
2149
|
+
*/
|
2150
|
+
if (itemp->operands != instruction->operands)
|
2151
|
+
return MERR_INVALOP;
|
2152
|
+
|
2153
|
+
/*
|
2154
|
+
* Is it legal?
|
2155
|
+
*/
|
2156
|
+
if (!(optimizing > 0) && itemp_has(itemp, IF_OPT))
|
2157
|
+
return MERR_INVALOP;
|
2158
|
+
|
2159
|
+
/*
|
2160
|
+
* {evex} available?
|
2161
|
+
*/
|
2162
|
+
switch (instruction->prefixes[PPS_VEX]) {
|
2163
|
+
case P_EVEX:
|
2164
|
+
if (!itemp_has(itemp, IF_EVEX))
|
2165
|
+
return MERR_ENCMISMATCH;
|
2166
|
+
break;
|
2167
|
+
case P_VEX3:
|
2168
|
+
case P_VEX2:
|
2169
|
+
if (!itemp_has(itemp, IF_VEX))
|
2170
|
+
return MERR_ENCMISMATCH;
|
2171
|
+
break;
|
2172
|
+
default:
|
2173
|
+
break;
|
2174
|
+
}
|
2175
|
+
|
2176
|
+
/*
|
2177
|
+
* Check that no spurious colons or TOs are present
|
2178
|
+
*/
|
2179
|
+
for (i = 0; i < itemp->operands; i++)
|
2180
|
+
if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
|
2181
|
+
return MERR_INVALOP;
|
2182
|
+
|
2183
|
+
/*
|
2184
|
+
* Process size flags
|
2185
|
+
*/
|
2186
|
+
switch (itemp_smask(itemp)) {
|
2187
|
+
case IF_GENBIT(IF_SB):
|
2188
|
+
asize = BITS8;
|
2189
|
+
break;
|
2190
|
+
case IF_GENBIT(IF_SW):
|
2191
|
+
asize = BITS16;
|
2192
|
+
break;
|
2193
|
+
case IF_GENBIT(IF_SD):
|
2194
|
+
asize = BITS32;
|
2195
|
+
break;
|
2196
|
+
case IF_GENBIT(IF_SQ):
|
2197
|
+
asize = BITS64;
|
2198
|
+
break;
|
2199
|
+
case IF_GENBIT(IF_SO):
|
2200
|
+
asize = BITS128;
|
2201
|
+
break;
|
2202
|
+
case IF_GENBIT(IF_SY):
|
2203
|
+
asize = BITS256;
|
2204
|
+
break;
|
2205
|
+
case IF_GENBIT(IF_SZ):
|
2206
|
+
asize = BITS512;
|
2207
|
+
break;
|
2208
|
+
case IF_GENBIT(IF_SIZE):
|
2209
|
+
switch (bits) {
|
2210
|
+
case 16:
|
2211
|
+
asize = BITS16;
|
2212
|
+
break;
|
2213
|
+
case 32:
|
2214
|
+
asize = BITS32;
|
2215
|
+
break;
|
2216
|
+
case 64:
|
2217
|
+
asize = BITS64;
|
2218
|
+
break;
|
2219
|
+
default:
|
2220
|
+
asize = 0;
|
2221
|
+
break;
|
2222
|
+
}
|
2223
|
+
break;
|
2224
|
+
default:
|
2225
|
+
asize = 0;
|
2226
|
+
break;
|
2227
|
+
}
|
2228
|
+
|
2229
|
+
if (itemp_armask(itemp)) {
|
2230
|
+
/* S- flags only apply to a specific operand */
|
2231
|
+
i = itemp_arg(itemp);
|
2232
|
+
memset(size, 0, sizeof size);
|
2233
|
+
size[i] = asize;
|
2234
|
+
} else {
|
2235
|
+
/* S- flags apply to all operands */
|
2236
|
+
for (i = 0; i < MAX_OPERANDS; i++)
|
2237
|
+
size[i] = asize;
|
2238
|
+
}
|
2239
|
+
|
2240
|
+
/*
|
2241
|
+
* Check that the operand flags all match up,
|
2242
|
+
* it's a bit tricky so lets be verbose:
|
2243
|
+
*
|
2244
|
+
* 1) Find out the size of operand. If instruction
|
2245
|
+
* doesn't have one specified -- we're trying to
|
2246
|
+
* guess it either from template (IF_S* flag) or
|
2247
|
+
* from code bits.
|
2248
|
+
*
|
2249
|
+
* 2) If template operand do not match the instruction OR
|
2250
|
+
* template has an operand size specified AND this size differ
|
2251
|
+
* from which instruction has (perhaps we got it from code bits)
|
2252
|
+
* we are:
|
2253
|
+
* a) Check that only size of instruction and operand is differ
|
2254
|
+
* other characteristics do match
|
2255
|
+
* b) Perhaps it's a register specified in instruction so
|
2256
|
+
* for such a case we just mark that operand as "size
|
2257
|
+
* missing" and this will turn on fuzzy operand size
|
2258
|
+
* logic facility (handled by a caller)
|
2259
|
+
*/
|
2260
|
+
for (i = 0; i < itemp->operands; i++) {
|
2261
|
+
opflags_t type = instruction->oprs[i].type;
|
2262
|
+
decoflags_t deco = instruction->oprs[i].decoflags;
|
2263
|
+
decoflags_t ideco = itemp->deco[i];
|
2264
|
+
bool is_broadcast = deco & BRDCAST_MASK;
|
2265
|
+
uint8_t brcast_num = 0;
|
2266
|
+
opflags_t template_opsize, insn_opsize;
|
2267
|
+
|
2268
|
+
if (!(type & SIZE_MASK))
|
2269
|
+
type |= size[i];
|
2270
|
+
|
2271
|
+
insn_opsize = type & SIZE_MASK;
|
2272
|
+
if (!is_broadcast) {
|
2273
|
+
template_opsize = itemp->opd[i] & SIZE_MASK;
|
2274
|
+
} else {
|
2275
|
+
decoflags_t deco_brsize = ideco & BRSIZE_MASK;
|
2276
|
+
|
2277
|
+
if (~ideco & BRDCAST_MASK)
|
2278
|
+
return MERR_BRNOTHERE;
|
2279
|
+
|
2280
|
+
/*
|
2281
|
+
* when broadcasting, the element size depends on
|
2282
|
+
* the instruction type. decorator flag should match.
|
2283
|
+
*/
|
2284
|
+
if (deco_brsize) {
|
2285
|
+
template_opsize = (deco_brsize == BR_BITS32 ? BITS32 : BITS64);
|
2286
|
+
/* calculate the proper number : {1to<brcast_num>} */
|
2287
|
+
brcast_num = get_broadcast_num(itemp->opd[i], template_opsize);
|
2288
|
+
} else {
|
2289
|
+
template_opsize = 0;
|
2290
|
+
}
|
2291
|
+
}
|
2292
|
+
|
2293
|
+
if (~ideco & deco & OPMASK_MASK)
|
2294
|
+
return MERR_MASKNOTHERE;
|
2295
|
+
|
2296
|
+
if (~ideco & deco & (Z_MASK|STATICRND_MASK|SAE_MASK))
|
2297
|
+
return MERR_DECONOTHERE;
|
2298
|
+
|
2299
|
+
if (itemp->opd[i] & ~type & ~SIZE_MASK) {
|
2300
|
+
return MERR_INVALOP;
|
2301
|
+
} else if (template_opsize) {
|
2302
|
+
if (template_opsize != insn_opsize) {
|
2303
|
+
if (insn_opsize) {
|
2304
|
+
return MERR_INVALOP;
|
2305
|
+
} else if (!is_class(REGISTER, type)) {
|
2306
|
+
/*
|
2307
|
+
* Note: we don't honor extrinsic operand sizes for registers,
|
2308
|
+
* so "missing operand size" for a register should be
|
2309
|
+
* considered a wildcard match rather than an error.
|
2310
|
+
*/
|
2311
|
+
opsizemissing = true;
|
2312
|
+
}
|
2313
|
+
} else if (is_broadcast &&
|
2314
|
+
(brcast_num !=
|
2315
|
+
(2U << ((deco & BRNUM_MASK) >> BRNUM_SHIFT)))) {
|
2316
|
+
/*
|
2317
|
+
* broadcasting opsize matches but the number of repeated memory
|
2318
|
+
* element does not match.
|
2319
|
+
* if 64b double precision float is broadcasted to ymm (256b),
|
2320
|
+
* broadcasting decorator must be {1to4}.
|
2321
|
+
*/
|
2322
|
+
return MERR_BRNUMMISMATCH;
|
2323
|
+
}
|
2324
|
+
}
|
2325
|
+
}
|
2326
|
+
|
2327
|
+
if (opsizemissing)
|
2328
|
+
return MERR_OPSIZEMISSING;
|
2329
|
+
|
2330
|
+
/*
|
2331
|
+
* Check operand sizes
|
2332
|
+
*/
|
2333
|
+
if (itemp_has(itemp, IF_SM) || itemp_has(itemp, IF_SM2)) {
|
2334
|
+
oprs = (itemp_has(itemp, IF_SM2) ? 2 : itemp->operands);
|
2335
|
+
for (i = 0; i < oprs; i++) {
|
2336
|
+
asize = itemp->opd[i] & SIZE_MASK;
|
2337
|
+
if (asize) {
|
2338
|
+
for (i = 0; i < oprs; i++)
|
2339
|
+
size[i] = asize;
|
2340
|
+
break;
|
2341
|
+
}
|
2342
|
+
}
|
2343
|
+
} else {
|
2344
|
+
oprs = itemp->operands;
|
2345
|
+
}
|
2346
|
+
|
2347
|
+
for (i = 0; i < itemp->operands; i++) {
|
2348
|
+
if (!(itemp->opd[i] & SIZE_MASK) &&
|
2349
|
+
(instruction->oprs[i].type & SIZE_MASK & ~size[i]))
|
2350
|
+
return MERR_OPSIZEMISMATCH;
|
2351
|
+
}
|
2352
|
+
|
2353
|
+
/*
|
2354
|
+
* Check template is okay at the set cpu level
|
2355
|
+
*/
|
2356
|
+
if (iflag_cmp_cpu_level(&insns_flags[itemp->iflag_idx], &cpu) > 0)
|
2357
|
+
return MERR_BADCPU;
|
2358
|
+
|
2359
|
+
/*
|
2360
|
+
* Verify the appropriate long mode flag.
|
2361
|
+
*/
|
2362
|
+
if (itemp_has(itemp, (bits == 64 ? IF_NOLONG : IF_LONG)))
|
2363
|
+
return MERR_BADMODE;
|
2364
|
+
|
2365
|
+
/*
|
2366
|
+
* If we have a HLE prefix, look for the NOHLE flag
|
2367
|
+
*/
|
2368
|
+
if (itemp_has(itemp, IF_NOHLE) &&
|
2369
|
+
(has_prefix(instruction, PPS_REP, P_XACQUIRE) ||
|
2370
|
+
has_prefix(instruction, PPS_REP, P_XRELEASE)))
|
2371
|
+
return MERR_BADHLE;
|
2372
|
+
|
2373
|
+
/*
|
2374
|
+
* Check if special handling needed for Jumps
|
2375
|
+
*/
|
2376
|
+
if ((itemp->code[0] & ~1) == 0370)
|
2377
|
+
return MOK_JUMP;
|
2378
|
+
|
2379
|
+
/*
|
2380
|
+
* Check if BND prefix is allowed.
|
2381
|
+
* Other 0xF2 (REPNE/REPNZ) prefix is prohibited.
|
2382
|
+
*/
|
2383
|
+
if (!itemp_has(itemp, IF_BND) &&
|
2384
|
+
(has_prefix(instruction, PPS_REP, P_BND) ||
|
2385
|
+
has_prefix(instruction, PPS_REP, P_NOBND)))
|
2386
|
+
return MERR_BADBND;
|
2387
|
+
else if (itemp_has(itemp, IF_BND) &&
|
2388
|
+
(has_prefix(instruction, PPS_REP, P_REPNE) ||
|
2389
|
+
has_prefix(instruction, PPS_REP, P_REPNZ)))
|
2390
|
+
return MERR_BADREPNE;
|
2391
|
+
|
2392
|
+
return MOK_GOOD;
|
2393
|
+
}
|
2394
|
+
|
2395
|
+
/*
|
2396
|
+
* Check if ModR/M.mod should/can be 01.
|
2397
|
+
* - EAF_BYTEOFFS is set
|
2398
|
+
* - offset can fit in a byte when EVEX is not used
|
2399
|
+
* - offset can be compressed when EVEX is used
|
2400
|
+
*/
|
2401
|
+
#define IS_MOD_01() (!(input->eaflags & EAF_WORDOFFS) && \
|
2402
|
+
(ins->rex & REX_EV ? seg == NO_SEG && !forw_ref && \
|
2403
|
+
is_disp8n(input, ins, &output->disp8) : \
|
2404
|
+
input->eaflags & EAF_BYTEOFFS || (o >= -128 && \
|
2405
|
+
o <= 127 && seg == NO_SEG && !forw_ref)))
|
2406
|
+
|
2407
|
+
static enum ea_type process_ea(operand *input, ea *output, int bits,
|
2408
|
+
int rfield, opflags_t rflags, insn *ins,
|
2409
|
+
const char **errmsg)
|
2410
|
+
{
|
2411
|
+
bool forw_ref = !!(input->opflags & OPFLAG_UNKNOWN);
|
2412
|
+
int addrbits = ins->addr_size;
|
2413
|
+
int eaflags = input->eaflags;
|
2414
|
+
|
2415
|
+
*errmsg = "invalid effective address"; /* Default error message */
|
2416
|
+
|
2417
|
+
output->type = EA_SCALAR;
|
2418
|
+
output->rip = false;
|
2419
|
+
output->disp8 = 0;
|
2420
|
+
|
2421
|
+
/* REX flags for the rfield operand */
|
2422
|
+
output->rex |= rexflags(rfield, rflags, REX_R | REX_P | REX_W | REX_H);
|
2423
|
+
/* EVEX.R' flag for the REG operand */
|
2424
|
+
ins->evex_p[0] |= evexflags(rfield, 0, EVEX_P0RP, 0);
|
2425
|
+
|
2426
|
+
if (is_class(REGISTER, input->type)) {
|
2427
|
+
/*
|
2428
|
+
* It's a direct register.
|
2429
|
+
*/
|
2430
|
+
if (!is_register(input->basereg))
|
2431
|
+
goto err;
|
2432
|
+
|
2433
|
+
if (!is_reg_class(REG_EA, input->basereg))
|
2434
|
+
goto err;
|
2435
|
+
|
2436
|
+
/* broadcasting is not available with a direct register operand. */
|
2437
|
+
if (input->decoflags & BRDCAST_MASK) {
|
2438
|
+
*errmsg = "broadcast not allowed with register operand";
|
2439
|
+
goto err;
|
2440
|
+
}
|
2441
|
+
|
2442
|
+
output->rex |= op_rexflags(input, REX_B | REX_P | REX_W | REX_H);
|
2443
|
+
ins->evex_p[0] |= op_evexflags(input, EVEX_P0X, 0);
|
2444
|
+
output->sib_present = false; /* no SIB necessary */
|
2445
|
+
output->bytes = 0; /* no offset necessary either */
|
2446
|
+
output->modrm = GEN_MODRM(3, rfield, nasm_regvals[input->basereg]);
|
2447
|
+
} else {
|
2448
|
+
/*
|
2449
|
+
* It's a memory reference.
|
2450
|
+
*/
|
2451
|
+
|
2452
|
+
/* Embedded rounding or SAE is not available with a mem ref operand. */
|
2453
|
+
if (input->decoflags & (ER | SAE)) {
|
2454
|
+
*errmsg = "embedded rounding is available only with "
|
2455
|
+
"register-register operations";
|
2456
|
+
goto err;
|
2457
|
+
}
|
2458
|
+
|
2459
|
+
if (input->basereg == -1 &&
|
2460
|
+
(input->indexreg == -1 || input->scale == 0)) {
|
2461
|
+
/*
|
2462
|
+
* It's a pure offset.
|
2463
|
+
*/
|
2464
|
+
if (bits == 64 && ((input->type & IP_REL) == IP_REL)) {
|
2465
|
+
if (input->segment == NO_SEG ||
|
2466
|
+
(input->opflags & OPFLAG_RELATIVE)) {
|
2467
|
+
nasm_error(ERR_WARNING | ERR_PASS2,
|
2468
|
+
"absolute address can not be RIP-relative");
|
2469
|
+
input->type &= ~IP_REL;
|
2470
|
+
input->type |= MEMORY;
|
2471
|
+
}
|
2472
|
+
}
|
2473
|
+
|
2474
|
+
if (bits == 64 &&
|
2475
|
+
!(IP_REL & ~input->type) && (eaflags & EAF_MIB)) {
|
2476
|
+
*errmsg = "RIP-relative addressing is prohibited for MIB";
|
2477
|
+
goto err;
|
2478
|
+
}
|
2479
|
+
|
2480
|
+
if (eaflags & EAF_BYTEOFFS ||
|
2481
|
+
(eaflags & EAF_WORDOFFS &&
|
2482
|
+
input->disp_size != (addrbits != 16 ? 32 : 16))) {
|
2483
|
+
nasm_error(ERR_WARNING | ERR_PASS1,
|
2484
|
+
"displacement size ignored on absolute address");
|
2485
|
+
}
|
2486
|
+
|
2487
|
+
if (bits == 64 && (~input->type & IP_REL)) {
|
2488
|
+
output->sib_present = true;
|
2489
|
+
output->sib = GEN_SIB(0, 4, 5);
|
2490
|
+
output->bytes = 4;
|
2491
|
+
output->modrm = GEN_MODRM(0, rfield, 4);
|
2492
|
+
output->rip = false;
|
2493
|
+
} else {
|
2494
|
+
output->sib_present = false;
|
2495
|
+
output->bytes = (addrbits != 16 ? 4 : 2);
|
2496
|
+
output->modrm = GEN_MODRM(0, rfield,
|
2497
|
+
(addrbits != 16 ? 5 : 6));
|
2498
|
+
output->rip = bits == 64;
|
2499
|
+
}
|
2500
|
+
} else {
|
2501
|
+
/*
|
2502
|
+
* It's an indirection.
|
2503
|
+
*/
|
2504
|
+
int i = input->indexreg, b = input->basereg, s = input->scale;
|
2505
|
+
int32_t seg = input->segment;
|
2506
|
+
int hb = input->hintbase, ht = input->hinttype;
|
2507
|
+
int t, it, bt; /* register numbers */
|
2508
|
+
opflags_t x, ix, bx; /* register flags */
|
2509
|
+
|
2510
|
+
if (s == 0)
|
2511
|
+
i = -1; /* make this easy, at least */
|
2512
|
+
|
2513
|
+
if (is_register(i)) {
|
2514
|
+
it = nasm_regvals[i];
|
2515
|
+
ix = nasm_reg_flags[i];
|
2516
|
+
} else {
|
2517
|
+
it = -1;
|
2518
|
+
ix = 0;
|
2519
|
+
}
|
2520
|
+
|
2521
|
+
if (is_register(b)) {
|
2522
|
+
bt = nasm_regvals[b];
|
2523
|
+
bx = nasm_reg_flags[b];
|
2524
|
+
} else {
|
2525
|
+
bt = -1;
|
2526
|
+
bx = 0;
|
2527
|
+
}
|
2528
|
+
|
2529
|
+
/* if either one are a vector register... */
|
2530
|
+
if ((ix|bx) & (XMMREG|YMMREG|ZMMREG) & ~REG_EA) {
|
2531
|
+
opflags_t sok = BITS32 | BITS64;
|
2532
|
+
int32_t o = input->offset;
|
2533
|
+
int mod, scale, index, base;
|
2534
|
+
|
2535
|
+
/*
|
2536
|
+
* For a vector SIB, one has to be a vector and the other,
|
2537
|
+
* if present, a GPR. The vector must be the index operand.
|
2538
|
+
*/
|
2539
|
+
if (it == -1 || (bx & (XMMREG|YMMREG|ZMMREG) & ~REG_EA)) {
|
2540
|
+
if (s == 0)
|
2541
|
+
s = 1;
|
2542
|
+
else if (s != 1)
|
2543
|
+
goto err;
|
2544
|
+
|
2545
|
+
t = bt, bt = it, it = t;
|
2546
|
+
x = bx, bx = ix, ix = x;
|
2547
|
+
}
|
2548
|
+
|
2549
|
+
if (bt != -1) {
|
2550
|
+
if (REG_GPR & ~bx)
|
2551
|
+
goto err;
|
2552
|
+
if (!(REG64 & ~bx) || !(REG32 & ~bx))
|
2553
|
+
sok &= bx;
|
2554
|
+
else
|
2555
|
+
goto err;
|
2556
|
+
}
|
2557
|
+
|
2558
|
+
/*
|
2559
|
+
* While we're here, ensure the user didn't specify
|
2560
|
+
* WORD or QWORD
|
2561
|
+
*/
|
2562
|
+
if (input->disp_size == 16 || input->disp_size == 64)
|
2563
|
+
goto err;
|
2564
|
+
|
2565
|
+
if (addrbits == 16 ||
|
2566
|
+
(addrbits == 32 && !(sok & BITS32)) ||
|
2567
|
+
(addrbits == 64 && !(sok & BITS64)))
|
2568
|
+
goto err;
|
2569
|
+
|
2570
|
+
output->type = ((ix & ZMMREG & ~REG_EA) ? EA_ZMMVSIB
|
2571
|
+
: ((ix & YMMREG & ~REG_EA)
|
2572
|
+
? EA_YMMVSIB : EA_XMMVSIB));
|
2573
|
+
|
2574
|
+
output->rex |= rexflags(it, ix, REX_X);
|
2575
|
+
output->rex |= rexflags(bt, bx, REX_B);
|
2576
|
+
ins->evex_p[2] |= evexflags(it, 0, EVEX_P2VP, 2);
|
2577
|
+
|
2578
|
+
index = it & 7; /* it is known to be != -1 */
|
2579
|
+
|
2580
|
+
switch (s) {
|
2581
|
+
case 1:
|
2582
|
+
scale = 0;
|
2583
|
+
break;
|
2584
|
+
case 2:
|
2585
|
+
scale = 1;
|
2586
|
+
break;
|
2587
|
+
case 4:
|
2588
|
+
scale = 2;
|
2589
|
+
break;
|
2590
|
+
case 8:
|
2591
|
+
scale = 3;
|
2592
|
+
break;
|
2593
|
+
default: /* then what the smeg is it? */
|
2594
|
+
goto err; /* panic */
|
2595
|
+
}
|
2596
|
+
|
2597
|
+
if (bt == -1) {
|
2598
|
+
base = 5;
|
2599
|
+
mod = 0;
|
2600
|
+
} else {
|
2601
|
+
base = (bt & 7);
|
2602
|
+
if (base != REG_NUM_EBP && o == 0 &&
|
2603
|
+
seg == NO_SEG && !forw_ref &&
|
2604
|
+
!(eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
|
2605
|
+
mod = 0;
|
2606
|
+
else if (IS_MOD_01())
|
2607
|
+
mod = 1;
|
2608
|
+
else
|
2609
|
+
mod = 2;
|
2610
|
+
}
|
2611
|
+
|
2612
|
+
output->sib_present = true;
|
2613
|
+
output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
|
2614
|
+
output->modrm = GEN_MODRM(mod, rfield, 4);
|
2615
|
+
output->sib = GEN_SIB(scale, index, base);
|
2616
|
+
} else if ((ix|bx) & (BITS32|BITS64)) {
|
2617
|
+
/*
|
2618
|
+
* it must be a 32/64-bit memory reference. Firstly we have
|
2619
|
+
* to check that all registers involved are type E/Rxx.
|
2620
|
+
*/
|
2621
|
+
opflags_t sok = BITS32 | BITS64;
|
2622
|
+
int32_t o = input->offset;
|
2623
|
+
|
2624
|
+
if (it != -1) {
|
2625
|
+
if (!(REG64 & ~ix) || !(REG32 & ~ix))
|
2626
|
+
sok &= ix;
|
2627
|
+
else
|
2628
|
+
goto err;
|
2629
|
+
}
|
2630
|
+
|
2631
|
+
if (bt != -1) {
|
2632
|
+
if (REG_GPR & ~bx)
|
2633
|
+
goto err; /* Invalid register */
|
2634
|
+
if (~sok & bx & SIZE_MASK)
|
2635
|
+
goto err; /* Invalid size */
|
2636
|
+
sok &= bx;
|
2637
|
+
}
|
2638
|
+
|
2639
|
+
/*
|
2640
|
+
* While we're here, ensure the user didn't specify
|
2641
|
+
* WORD or QWORD
|
2642
|
+
*/
|
2643
|
+
if (input->disp_size == 16 || input->disp_size == 64)
|
2644
|
+
goto err;
|
2645
|
+
|
2646
|
+
if (addrbits == 16 ||
|
2647
|
+
(addrbits == 32 && !(sok & BITS32)) ||
|
2648
|
+
(addrbits == 64 && !(sok & BITS64)))
|
2649
|
+
goto err;
|
2650
|
+
|
2651
|
+
/* now reorganize base/index */
|
2652
|
+
if (s == 1 && bt != it && bt != -1 && it != -1 &&
|
2653
|
+
((hb == b && ht == EAH_NOTBASE) ||
|
2654
|
+
(hb == i && ht == EAH_MAKEBASE))) {
|
2655
|
+
/* swap if hints say so */
|
2656
|
+
t = bt, bt = it, it = t;
|
2657
|
+
x = bx, bx = ix, ix = x;
|
2658
|
+
}
|
2659
|
+
|
2660
|
+
if (bt == -1 && s == 1 && !(hb == i && ht == EAH_NOTBASE)) {
|
2661
|
+
/* make single reg base, unless hint */
|
2662
|
+
bt = it, bx = ix, it = -1, ix = 0;
|
2663
|
+
}
|
2664
|
+
if (eaflags & EAF_MIB) {
|
2665
|
+
/* only for mib operands */
|
2666
|
+
if (it == -1 && (hb == b && ht == EAH_NOTBASE)) {
|
2667
|
+
/*
|
2668
|
+
* make a single reg index [reg*1].
|
2669
|
+
* gas uses this form for an explicit index register.
|
2670
|
+
*/
|
2671
|
+
it = bt, ix = bx, bt = -1, bx = 0, s = 1;
|
2672
|
+
}
|
2673
|
+
if ((ht == EAH_SUMMED) && bt == -1) {
|
2674
|
+
/* separate once summed index into [base, index] */
|
2675
|
+
bt = it, bx = ix, s--;
|
2676
|
+
}
|
2677
|
+
} else {
|
2678
|
+
if (((s == 2 && it != REG_NUM_ESP &&
|
2679
|
+
(!(eaflags & EAF_TIMESTWO) || (ht == EAH_SUMMED))) ||
|
2680
|
+
s == 3 || s == 5 || s == 9) && bt == -1) {
|
2681
|
+
/* convert 3*EAX to EAX+2*EAX */
|
2682
|
+
bt = it, bx = ix, s--;
|
2683
|
+
}
|
2684
|
+
if (it == -1 && (bt & 7) != REG_NUM_ESP &&
|
2685
|
+
(eaflags & EAF_TIMESTWO) &&
|
2686
|
+
(hb == b && ht == EAH_NOTBASE)) {
|
2687
|
+
/*
|
2688
|
+
* convert [NOSPLIT EAX*1]
|
2689
|
+
* to sib format with 0x0 displacement - [EAX*1+0].
|
2690
|
+
*/
|
2691
|
+
it = bt, ix = bx, bt = -1, bx = 0, s = 1;
|
2692
|
+
}
|
2693
|
+
}
|
2694
|
+
if (s == 1 && it == REG_NUM_ESP) {
|
2695
|
+
/* swap ESP into base if scale is 1 */
|
2696
|
+
t = it, it = bt, bt = t;
|
2697
|
+
x = ix, ix = bx, bx = x;
|
2698
|
+
}
|
2699
|
+
if (it == REG_NUM_ESP ||
|
2700
|
+
(s != 1 && s != 2 && s != 4 && s != 8 && it != -1))
|
2701
|
+
goto err; /* wrong, for various reasons */
|
2702
|
+
|
2703
|
+
output->rex |= rexflags(it, ix, REX_X);
|
2704
|
+
output->rex |= rexflags(bt, bx, REX_B);
|
2705
|
+
|
2706
|
+
if (it == -1 && (bt & 7) != REG_NUM_ESP) {
|
2707
|
+
/* no SIB needed */
|
2708
|
+
int mod, rm;
|
2709
|
+
|
2710
|
+
if (bt == -1) {
|
2711
|
+
rm = 5;
|
2712
|
+
mod = 0;
|
2713
|
+
} else {
|
2714
|
+
rm = (bt & 7);
|
2715
|
+
if (rm != REG_NUM_EBP && o == 0 &&
|
2716
|
+
seg == NO_SEG && !forw_ref &&
|
2717
|
+
!(eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
|
2718
|
+
mod = 0;
|
2719
|
+
else if (IS_MOD_01())
|
2720
|
+
mod = 1;
|
2721
|
+
else
|
2722
|
+
mod = 2;
|
2723
|
+
}
|
2724
|
+
|
2725
|
+
output->sib_present = false;
|
2726
|
+
output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
|
2727
|
+
output->modrm = GEN_MODRM(mod, rfield, rm);
|
2728
|
+
} else {
|
2729
|
+
/* we need a SIB */
|
2730
|
+
int mod, scale, index, base;
|
2731
|
+
|
2732
|
+
if (it == -1)
|
2733
|
+
index = 4, s = 1;
|
2734
|
+
else
|
2735
|
+
index = (it & 7);
|
2736
|
+
|
2737
|
+
switch (s) {
|
2738
|
+
case 1:
|
2739
|
+
scale = 0;
|
2740
|
+
break;
|
2741
|
+
case 2:
|
2742
|
+
scale = 1;
|
2743
|
+
break;
|
2744
|
+
case 4:
|
2745
|
+
scale = 2;
|
2746
|
+
break;
|
2747
|
+
case 8:
|
2748
|
+
scale = 3;
|
2749
|
+
break;
|
2750
|
+
default: /* then what the smeg is it? */
|
2751
|
+
goto err; /* panic */
|
2752
|
+
}
|
2753
|
+
|
2754
|
+
if (bt == -1) {
|
2755
|
+
base = 5;
|
2756
|
+
mod = 0;
|
2757
|
+
} else {
|
2758
|
+
base = (bt & 7);
|
2759
|
+
if (base != REG_NUM_EBP && o == 0 &&
|
2760
|
+
seg == NO_SEG && !forw_ref &&
|
2761
|
+
!(eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
|
2762
|
+
mod = 0;
|
2763
|
+
else if (IS_MOD_01())
|
2764
|
+
mod = 1;
|
2765
|
+
else
|
2766
|
+
mod = 2;
|
2767
|
+
}
|
2768
|
+
|
2769
|
+
output->sib_present = true;
|
2770
|
+
output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
|
2771
|
+
output->modrm = GEN_MODRM(mod, rfield, 4);
|
2772
|
+
output->sib = GEN_SIB(scale, index, base);
|
2773
|
+
}
|
2774
|
+
} else { /* it's 16-bit */
|
2775
|
+
int mod, rm;
|
2776
|
+
int16_t o = input->offset;
|
2777
|
+
|
2778
|
+
/* check for 64-bit long mode */
|
2779
|
+
if (addrbits == 64)
|
2780
|
+
goto err;
|
2781
|
+
|
2782
|
+
/* check all registers are BX, BP, SI or DI */
|
2783
|
+
if ((b != -1 && b != R_BP && b != R_BX && b != R_SI && b != R_DI) ||
|
2784
|
+
(i != -1 && i != R_BP && i != R_BX && i != R_SI && i != R_DI))
|
2785
|
+
goto err;
|
2786
|
+
|
2787
|
+
/* ensure the user didn't specify DWORD/QWORD */
|
2788
|
+
if (input->disp_size == 32 || input->disp_size == 64)
|
2789
|
+
goto err;
|
2790
|
+
|
2791
|
+
if (s != 1 && i != -1)
|
2792
|
+
goto err; /* no can do, in 16-bit EA */
|
2793
|
+
if (b == -1 && i != -1) {
|
2794
|
+
int tmp = b;
|
2795
|
+
b = i;
|
2796
|
+
i = tmp;
|
2797
|
+
} /* swap */
|
2798
|
+
if ((b == R_SI || b == R_DI) && i != -1) {
|
2799
|
+
int tmp = b;
|
2800
|
+
b = i;
|
2801
|
+
i = tmp;
|
2802
|
+
}
|
2803
|
+
/* have BX/BP as base, SI/DI index */
|
2804
|
+
if (b == i)
|
2805
|
+
goto err; /* shouldn't ever happen, in theory */
|
2806
|
+
if (i != -1 && b != -1 &&
|
2807
|
+
(i == R_BP || i == R_BX || b == R_SI || b == R_DI))
|
2808
|
+
goto err; /* invalid combinations */
|
2809
|
+
if (b == -1) /* pure offset: handled above */
|
2810
|
+
goto err; /* so if it gets to here, panic! */
|
2811
|
+
|
2812
|
+
rm = -1;
|
2813
|
+
if (i != -1)
|
2814
|
+
switch (i * 256 + b) {
|
2815
|
+
case R_SI * 256 + R_BX:
|
2816
|
+
rm = 0;
|
2817
|
+
break;
|
2818
|
+
case R_DI * 256 + R_BX:
|
2819
|
+
rm = 1;
|
2820
|
+
break;
|
2821
|
+
case R_SI * 256 + R_BP:
|
2822
|
+
rm = 2;
|
2823
|
+
break;
|
2824
|
+
case R_DI * 256 + R_BP:
|
2825
|
+
rm = 3;
|
2826
|
+
break;
|
2827
|
+
} else
|
2828
|
+
switch (b) {
|
2829
|
+
case R_SI:
|
2830
|
+
rm = 4;
|
2831
|
+
break;
|
2832
|
+
case R_DI:
|
2833
|
+
rm = 5;
|
2834
|
+
break;
|
2835
|
+
case R_BP:
|
2836
|
+
rm = 6;
|
2837
|
+
break;
|
2838
|
+
case R_BX:
|
2839
|
+
rm = 7;
|
2840
|
+
break;
|
2841
|
+
}
|
2842
|
+
if (rm == -1) /* can't happen, in theory */
|
2843
|
+
goto err; /* so panic if it does */
|
2844
|
+
|
2845
|
+
if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
|
2846
|
+
!(eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
|
2847
|
+
mod = 0;
|
2848
|
+
else if (IS_MOD_01())
|
2849
|
+
mod = 1;
|
2850
|
+
else
|
2851
|
+
mod = 2;
|
2852
|
+
|
2853
|
+
output->sib_present = false; /* no SIB - it's 16-bit */
|
2854
|
+
output->bytes = mod; /* bytes of offset needed */
|
2855
|
+
output->modrm = GEN_MODRM(mod, rfield, rm);
|
2856
|
+
}
|
2857
|
+
}
|
2858
|
+
}
|
2859
|
+
|
2860
|
+
output->size = 1 + output->sib_present + output->bytes;
|
2861
|
+
return output->type;
|
2862
|
+
|
2863
|
+
err:
|
2864
|
+
return output->type = EA_INVALID;
|
2865
|
+
}
|
2866
|
+
|
2867
|
+
static void add_asp(insn *ins, int addrbits)
|
2868
|
+
{
|
2869
|
+
int j, valid;
|
2870
|
+
int defdisp;
|
2871
|
+
|
2872
|
+
valid = (addrbits == 64) ? 64|32 : 32|16;
|
2873
|
+
|
2874
|
+
switch (ins->prefixes[PPS_ASIZE]) {
|
2875
|
+
case P_A16:
|
2876
|
+
valid &= 16;
|
2877
|
+
break;
|
2878
|
+
case P_A32:
|
2879
|
+
valid &= 32;
|
2880
|
+
break;
|
2881
|
+
case P_A64:
|
2882
|
+
valid &= 64;
|
2883
|
+
break;
|
2884
|
+
case P_ASP:
|
2885
|
+
valid &= (addrbits == 32) ? 16 : 32;
|
2886
|
+
break;
|
2887
|
+
default:
|
2888
|
+
break;
|
2889
|
+
}
|
2890
|
+
|
2891
|
+
for (j = 0; j < ins->operands; j++) {
|
2892
|
+
if (is_class(MEMORY, ins->oprs[j].type)) {
|
2893
|
+
opflags_t i, b;
|
2894
|
+
|
2895
|
+
/* Verify as Register */
|
2896
|
+
if (!is_register(ins->oprs[j].indexreg))
|
2897
|
+
i = 0;
|
2898
|
+
else
|
2899
|
+
i = nasm_reg_flags[ins->oprs[j].indexreg];
|
2900
|
+
|
2901
|
+
/* Verify as Register */
|
2902
|
+
if (!is_register(ins->oprs[j].basereg))
|
2903
|
+
b = 0;
|
2904
|
+
else
|
2905
|
+
b = nasm_reg_flags[ins->oprs[j].basereg];
|
2906
|
+
|
2907
|
+
if (ins->oprs[j].scale == 0)
|
2908
|
+
i = 0;
|
2909
|
+
|
2910
|
+
if (!i && !b) {
|
2911
|
+
int ds = ins->oprs[j].disp_size;
|
2912
|
+
if ((addrbits != 64 && ds > 8) ||
|
2913
|
+
(addrbits == 64 && ds == 16))
|
2914
|
+
valid &= ds;
|
2915
|
+
} else {
|
2916
|
+
if (!(REG16 & ~b))
|
2917
|
+
valid &= 16;
|
2918
|
+
if (!(REG32 & ~b))
|
2919
|
+
valid &= 32;
|
2920
|
+
if (!(REG64 & ~b))
|
2921
|
+
valid &= 64;
|
2922
|
+
|
2923
|
+
if (!(REG16 & ~i))
|
2924
|
+
valid &= 16;
|
2925
|
+
if (!(REG32 & ~i))
|
2926
|
+
valid &= 32;
|
2927
|
+
if (!(REG64 & ~i))
|
2928
|
+
valid &= 64;
|
2929
|
+
}
|
2930
|
+
}
|
2931
|
+
}
|
2932
|
+
|
2933
|
+
if (valid & addrbits) {
|
2934
|
+
ins->addr_size = addrbits;
|
2935
|
+
} else if (valid & ((addrbits == 32) ? 16 : 32)) {
|
2936
|
+
/* Add an address size prefix */
|
2937
|
+
ins->prefixes[PPS_ASIZE] = (addrbits == 32) ? P_A16 : P_A32;;
|
2938
|
+
ins->addr_size = (addrbits == 32) ? 16 : 32;
|
2939
|
+
} else {
|
2940
|
+
/* Impossible... */
|
2941
|
+
nasm_error(ERR_NONFATAL, "impossible combination of address sizes");
|
2942
|
+
ins->addr_size = addrbits; /* Error recovery */
|
2943
|
+
}
|
2944
|
+
|
2945
|
+
defdisp = ins->addr_size == 16 ? 16 : 32;
|
2946
|
+
|
2947
|
+
for (j = 0; j < ins->operands; j++) {
|
2948
|
+
if (!(MEM_OFFS & ~ins->oprs[j].type) &&
|
2949
|
+
(ins->oprs[j].disp_size ? ins->oprs[j].disp_size : defdisp) != ins->addr_size) {
|
2950
|
+
/*
|
2951
|
+
* mem_offs sizes must match the address size; if not,
|
2952
|
+
* strip the MEM_OFFS bit and match only EA instructions
|
2953
|
+
*/
|
2954
|
+
ins->oprs[j].type &= ~(MEM_OFFS & ~MEMORY);
|
2955
|
+
}
|
2956
|
+
}
|
2957
|
+
}
|