12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948 |
- /* mops.c - handle pseudo-ops */
- #include "syshead.h"
- #include "const.h"
- #include "type.h"
- #include "globvar.h"
- #include "opcode.h"
- #include "scan.h"
- #undef EXTERN
- #define EXTERN
- #include "address.h"
- #define is8bitadr(offset) ((offset_t) offset < 0x100)
- #define is8bitsignedoffset(offset) ((offset_t) (offset) + 0x80 < 0x100)
- #define pass2 (pass==last_pass)
- FORWARD void mshort2 P((void));
- FORWARD reg_pt regchk P((void));
- FORWARD void reldata P((void));
- FORWARD void segadj P((void));
- #ifdef I80386
- #define iswordadr(offset) ((offset_t) (offset) < 0x10000L)
- #define iswordoffset(offset) ((offset_t) (offset) + 0x8000L < 0x10000L)
- #define iswordorswordoffset(offset) ((offset_t) (offset) + 0xFFFFL < 0x1FFFEL)
- #define BYTE_SEGWORD 0x00
- #define isspecreg(r) ((r) >= CR0REG && (r) <= TR7REG)
- #define BASE_MASK 0x07
- #define BASE_SHIFT 0
- #define INDEX_MASK 0x38
- #define INDEX_SHIFT 3
- #define MOD_MASK 0xC0
- # define REG_MOD 0xC0
- # define MEM0_MOD 0x00
- # define MEM1_MOD 0x40
- # define MEM2_MOD 0x80
- #define REG_MASK 0x38
- #define REG_SHIFT 3
- #define RM_MASK 0x07
- #define RM_SHIFT 0
- # define D16_RM 0x06
- # define D32_RM 0x05
- # define SIB_NOBASE 0x05
- # define SIB_RM 0x04
- #define SREG_MASK 0x38
- #define SREG_SHIFT 3
- #define SS_MASK 0xC0
- #define SS_SHIFT 6
- #define SEGMOV 0x04
- #define SIGNBIT 0x02
- #define TOREGBIT 0x02
- #define WORDBIT 0x01
- PRIVATE opcode_t baseind16[] =
- {
- 0x00, /* BP + BP, illegal */
- 0x00, /* BX + BP, illegal */
- 0x03, /* DI + BP */
- 0x02, /* SI + BP */
- 0x00, /* BP + BX, illegal */
- 0x00, /* BX + BX, illegal */
- 0x01, /* DI + BX */
- 0x00, /* SI + BX */
- 0x03, /* BP + DI */
- 0x01, /* BX + DI */
- 0x00, /* DI + DI, illegal */
- 0x00, /* SI + DI, illegal */
- 0x02, /* BP + SI */
- 0x00, /* BX + SI */
- 0x00, /* DI + SI, illegal */
- 0x00, /* SI + SI, illegal */
- };
- PRIVATE opcode_t regbits[] =
- {
- 0x05 << REG_SHIFT, /* BP */
- 0x03 << REG_SHIFT, /* BX */
- 0x07 << REG_SHIFT, /* DI */
- 0x06 << REG_SHIFT, /* SI */
- 0x00 << REG_SHIFT, /* EAX */
- 0x05 << REG_SHIFT, /* EBP */
- 0x03 << REG_SHIFT, /* EBX */
- 0x01 << REG_SHIFT, /* ECX */
- 0x07 << REG_SHIFT, /* EDI */
- 0x02 << REG_SHIFT, /* EDX */
- 0x06 << REG_SHIFT, /* ESI */
- 0x04 << REG_SHIFT, /* ESP */
- 0x00 << REG_SHIFT, /* AX */
- 0x01 << REG_SHIFT, /* CX */
- 0x02 << REG_SHIFT, /* DX */
- 0x04 << REG_SHIFT, /* SP */
- 0x04 << REG_SHIFT, /* AH */
- 0x00 << REG_SHIFT, /* AL */
- 0x07 << REG_SHIFT, /* BH */
- 0x03 << REG_SHIFT, /* BL */
- 0x05 << REG_SHIFT, /* CH */
- 0x01 << REG_SHIFT, /* CL */
- 0x06 << REG_SHIFT, /* DH */
- 0x02 << REG_SHIFT, /* DL */
- 0x01 << REG_SHIFT, /* CS */
- 0x03 << REG_SHIFT, /* DS */
- 0x00 << REG_SHIFT, /* ES */
- 0x04 << REG_SHIFT, /* FS */
- 0x05 << REG_SHIFT, /* GS */
- 0x02 << REG_SHIFT, /* SS */
- 0x00 << REG_SHIFT, /* CR0 */
- 0x02 << REG_SHIFT, /* CR2 */
- 0x03 << REG_SHIFT, /* CR3 */
- 0x00 << REG_SHIFT, /* DR0 */
- 0x01 << REG_SHIFT, /* DR1 */
- 0x02 << REG_SHIFT, /* DR2 */
- 0x03 << REG_SHIFT, /* DR3 */
- 0x06 << REG_SHIFT, /* DR6 */
- 0x07 << REG_SHIFT, /* DR7 */
- 0x03 << REG_SHIFT, /* TR3 */
- 0x04 << REG_SHIFT, /* TR4 */
- 0x05 << REG_SHIFT, /* TR5 */
- 0x06 << REG_SHIFT, /* TR6 */
- 0x07 << REG_SHIFT, /* TR7 */
- 0x00 << REG_SHIFT, /* ST(0) */
- 0x01 << REG_SHIFT, /* ST(1) */
- 0x02 << REG_SHIFT, /* ST(2) */
- 0x03 << REG_SHIFT, /* ST(3) */
- 0x04 << REG_SHIFT, /* ST(4) */
- 0x05 << REG_SHIFT, /* ST(5) */
- 0x06 << REG_SHIFT, /* ST(6) */
- 0x07 << REG_SHIFT, /* ST(7) */
- };
- PRIVATE opsize_t regsize[] =
- {
- 2, /* BP */
- 2, /* BX */
- 2, /* DI */
- 2, /* SI */
- 4, /* EAX */
- 4, /* EBP */
- 4, /* EBX */
- 4, /* ECX */
- 4, /* EDI */
- 4, /* EDX */
- 4, /* ESI */
- 4, /* ESP */
- 2, /* AX */
- 2, /* CX */
- 2, /* DX */
- 2, /* SP */
- 1, /* AH */
- 1, /* AL */
- 1, /* BH */
- 1, /* BL */
- 1, /* CH */
- 1, /* CL */
- 1, /* DH */
- 1, /* DL */
- 2, /* CS */
- 2, /* DS */
- 2, /* ES */
- 2, /* FS */
- 2, /* GS */
- 2, /* SS */
- 4, /* CR0 */
- 4, /* CR2 */
- 4, /* CR3 */
- 4, /* DR0 */
- 4, /* DR1 */
- 4, /* DR2 */
- 4, /* DR3 */
- 4, /* DR6 */
- 4, /* DR7 */
- 4, /* TR3 */
- 4, /* TR4 */
- 4, /* TR5 */
- 4, /* TR6 */
- 4, /* TR7 */
- 10, /* ST(0) */
- 10, /* ST(1) */
- 10, /* ST(2) */
- 10, /* ST(3) */
- 10, /* ST(4) */
- 10, /* ST(5) */
- 10, /* ST(6) */
- 10, /* ST(7) */
- 0, /* NOREG */
- };
- PRIVATE opcode_t regsegword[] =
- {
- WORDBIT, /* BP */
- WORDBIT, /* BX */
- WORDBIT, /* DI */
- WORDBIT, /* SI */
- WORDBIT, /* EAX */
- WORDBIT, /* EBP */
- WORDBIT, /* EBX */
- WORDBIT, /* ECX */
- WORDBIT, /* EDI */
- WORDBIT, /* EDX */
- WORDBIT, /* ESI */
- WORDBIT, /* ESP */
- WORDBIT, /* AX */
- WORDBIT, /* CX */
- WORDBIT, /* DX */
- WORDBIT, /* SP */
- BYTE_SEGWORD, /* AH */
- BYTE_SEGWORD, /* AL */
- BYTE_SEGWORD, /* BH */
- BYTE_SEGWORD, /* BL */
- BYTE_SEGWORD, /* CH */
- BYTE_SEGWORD, /* CL */
- BYTE_SEGWORD, /* DH */
- BYTE_SEGWORD, /* DL */
- SEGMOV, /* CS */
- SEGMOV, /* DS */
- SEGMOV, /* ES */
- SEGMOV, /* FS */
- SEGMOV, /* GS */
- SEGMOV, /* SS */
- 0x20, /* CR0 */
- 0x20, /* CR2 */
- 0x20, /* CR3 */
- 0x21, /* DR0 */
- 0x21, /* DR1 */
- 0x21, /* DR2 */
- 0x21, /* DR3 */
- 0x21, /* DR6 */
- 0x21, /* DR7 */
- 0x24, /* TR3 */
- 0x24, /* TR4 */
- 0x24, /* TR5 */
- 0x24, /* TR6 */
- 0x24, /* TR7 */
- 0x00, /* ST(0) */
- 0x00, /* ST(1) */
- 0x00, /* ST(2) */
- 0x00, /* ST(3) */
- 0x00, /* ST(4) */
- 0x00, /* ST(5) */
- 0x00, /* ST(6) */
- 0x00, /* ST(7) */
- 0x00, /* NOREG */
- };
- PRIVATE opcode_t rm[] =
- {
- 0x05, /* BP */
- 0x03, /* BX */
- 0x07, /* DI */
- 0x06, /* SI */
- 0x00, /* EAX */
- 0x05, /* EBP */
- 0x03, /* EBX */
- 0x01, /* ECX */
- 0x07, /* EDI */
- 0x02, /* EDX */
- 0x06, /* ESI */
- 0x04, /* ESP */
- 0x00, /* AX */
- 0x01, /* CX */
- 0x02, /* DX */
- 0x04, /* SP */
- 0x04, /* AH */
- 0x00, /* AL */
- 0x07, /* BH */
- 0x03, /* BL */
- 0x05, /* CH */
- 0x01, /* CL */
- 0x06, /* DH */
- 0x02, /* DL */
- 0x01, /* CS */
- 0x03, /* DS */
- 0x00, /* ES */
- 0x04, /* FS */
- 0x05, /* GS */
- 0x02, /* SS */
- 0x00, /* CR0 */
- 0x00, /* CR2 */
- 0x00, /* CR3 */
- 0x00, /* DR0 */
- 0x00, /* DR1 */
- 0x00, /* DR2 */
- 0x00, /* DR3 */
- 0x00, /* DR6 */
- 0x00, /* DR7 */
- 0x00, /* TR3 */
- 0x00, /* TR4 */
- 0x00, /* TR5 */
- 0x00, /* TR6 */
- 0x00, /* TR7 */
- 0x00, /* ST(0) */
- 0x00, /* ST(1) */
- 0x00, /* ST(2) */
- 0x00, /* ST(3) */
- 0x00, /* ST(4) */
- 0x00, /* ST(5) */
- 0x00, /* ST(6) */
- 0x00, /* ST(7) */
- 0x04, /* null index reg for sib only */
- };
- PRIVATE opcode_t rmfunny[] =
- {
- 0x06, /* BP */
- 0x07, /* BX */
- 0x05, /* DI */
- 0x04, /* SI */
- };
- PRIVATE opcode_t segoverride[] =
- {
- 0x2E, /* CS */
- 0x3E, /* DS */
- 0x26, /* ES */
- 0x64, /* FS */
- 0x65, /* GS */
- 0x36, /* SS */
- };
- PRIVATE opcode_t ss[] = /* scale to ss bits */
- {
- 0x00, /* x0, illegal */
- 0x00 << SS_SHIFT, /* x1 */
- 0x01 << SS_SHIFT, /* x2 */
- 0x00, /* x3, illegal */
- 0x02 << SS_SHIFT, /* x4 */
- 0x00, /* x5, illegal */
- 0x00, /* x6, illegal */
- 0x00, /* x7, illegal */
- 0x03 << SS_SHIFT, /* x8 */
- };
- PRIVATE unsigned char calljmp_kludge;
- PRIVATE opcode_t direction;
- PRIVATE bool_t fpreg_allowed;
- PRIVATE opcode_t segword;
- /*
- Values of segword:
- BYTE_SEGWORD for byte ea's.
- SEGMOV for segment registers
- opcode for special registers
- WORDBIT for other word and dword ea's
- */
- PRIVATE struct ea_s source;
- PRIVATE struct ea_s source2;
- PRIVATE struct ea_s target;
- FORWARD void Eb P((struct ea_s *eap));
- FORWARD void Ew P((struct ea_s *eap));
- FORWARD void Ev P((struct ea_s *eap));
- FORWARD void Ex P((struct ea_s *eap));
- FORWARD void Gd P((struct ea_s *eap));
- FORWARD void Gw P((struct ea_s *eap));
- FORWARD void Gv P((struct ea_s *eap));
- FORWARD void Gx P((struct ea_s *eap));
- FORWARD void buildea P((struct ea_s *eap));
- FORWARD void buildfloat P((void));
- FORWARD void buildfreg P((void));
- FORWARD void buildimm P((struct ea_s *eap, bool_pt signflag));
- FORWARD void buildregular P((void));
- FORWARD void buildsegword P((struct ea_s *eap));
- FORWARD void buildunary P((opcode_pt opc));
- FORWARD opsize_pt displsize P((struct ea_s *eap));
- FORWARD reg_pt fpregchk P((void));
- FORWARD bool_pt getaccumreg P((struct ea_s *eap));
- FORWARD void getbinary P((void));
- FORWARD bool_pt getdxreg P((struct ea_s *eap));
- FORWARD void getea P((struct ea_s *eap));
- FORWARD void getimmed P((struct ea_s *eap, count_t immed_count));
- FORWARD void getindirect P((struct ea_s *eap));
- FORWARD void getshift P((struct ea_s *eap));
- FORWARD reg_pt indregchk P((reg_pt matchreg));
- FORWARD void kgerror P((char * err_str));
- FORWARD void lbranch P((int backamount));
- FORWARD void notbytesize P((struct ea_s *eap));
- FORWARD void notimmed P((struct ea_s *eap));
- FORWARD void notindirect P((struct ea_s *eap));
- FORWARD void notsegorspecreg P((struct ea_s *eap));
- FORWARD void yesimmed P((struct ea_s *eap));
- FORWARD void yes_samesize P((void));
- PRIVATE void Eb(eap)
- register struct ea_s *eap;
- {
- Ex(eap);
- if (eap->size != 0x1)
- {
- #ifndef NODEFAULTSIZE
- if (eap->size == 0x0)
- eap->size = 0x1;
- else
- #endif
- kgerror(ILL_SIZE);
- }
- }
- PRIVATE void Ew(eap)
- register struct ea_s *eap;
- {
- Ex(eap);
- if (eap->size != 0x2)
- {
- #ifndef NODEFAULTSIZE
- if (eap->size == 0x0)
- eap->size = 0x2;
- else
- #endif
- kgerror(ILL_SIZE);
- }
- }
- PRIVATE void Ev(eap)
- register struct ea_s *eap;
- {
- Ex(eap);
- notbytesize(eap);
- }
- PRIVATE void Ex(eap)
- register struct ea_s *eap;
- {
- getea(eap);
- notimmed(eap);
- notsegorspecreg(eap);
- }
- PRIVATE void Gd(eap)
- register struct ea_s *eap;
- {
- Gx(eap);
- if (eap->size != 0x4)
- kgerror(ILL_SIZE);
- }
- PRIVATE void Gw(eap)
- register struct ea_s *eap;
- {
- Gx(eap);
- if (eap->size != 0x2)
- kgerror(ILL_SIZE);
- }
- PRIVATE void Gv(eap)
- register struct ea_s *eap;
- {
- Gx(eap);
- notbytesize(eap);
- }
- PRIVATE void Gx(eap)
- register struct ea_s *eap;
- {
- Ex(eap);
- notindirect(eap);
- }
- PRIVATE void buildea(eap)
- register struct ea_s *eap;
- {
- opsize_t asize;
- ++mcount;
- lastexp = eap->displ;
- if (eap->indcount == 0x0)
- postb = REG_MOD | rm[eap->base];
- else
- {
- if (eap->base == NOREG)
- {
- if (eap->index == NOREG)
- {
- if ((asize = displsize(eap)) > 0x2)
- postb = D32_RM;
- else
- postb = D16_RM;
- }
- else
- {
- asize = 0x4;
- postb = SIB_NOBASE; /* for sib later */
- }
- }
- else
- {
- if (eap->base > MAX16BITINDREG)
- {
- asize = 0x4;
- postb = rm[eap->base];
- }
- else
- {
- asize = 0x2;
- if (!(lastexp.data & UNDBIT) &&
- !iswordorswordoffset(lastexp.offset))
- error(ABOUNDS);
- if (eap->index == NOREG)
- postb = rmfunny[eap->base];
- else if (eap->base <= MAX16BITINDREG)
- postb = baseind16[eap->base + 0x4 * eap->index];
- }
- }
- needcpu(asize==4?3:0);
- if (asize != defsize)
- aprefix = 0x67;
- if (eap->base == NOREG)
- mcount += asize;
- else if (lastexp.data & (FORBIT | RELBIT | UNDBIT) ||
- !is8bitsignedoffset(lastexp.offset))
- {
- postb |= MEM2_MOD;
- mcount += asize;
- }
- else if (lastexp.offset != 0x0 ||
- (eap->base == BPREG && eap->index == NOREG) ||
- eap->base == EBPREG)
- {
- postb |= MEM1_MOD;
- ++mcount;
- }
- if (asize > 0x2 && (eap->base == ESPREG || eap->index != NOREG))
- {
- sib = ss[eap->scale] |
- (rm[eap->index] << INDEX_SHIFT) |
- (postb & RM_MASK);
- postb = (postb & MOD_MASK) | SIB_RM;
- ++mcount;
- }
- }
- }
- PRIVATE void buildfloat()
- {
- if (mcount != 0x0)
- {
- buildea(&source);
- oprefix = 0x0;
- postb |= (opcode & 0x07) << REG_SHIFT;
- opcode = ESCAPE_OPCODE_BASE | ((opcode & 0x70) >> 0x4);
- }
- }
- PRIVATE void buildfreg()
- {
- mcount += 0x2;
- oprefix = 0x0;
- postb = REG_MOD | ((opcode & 0x07) << REG_SHIFT) | (target.base - ST0REG);
- opcode = ESCAPE_OPCODE_BASE | ((opcode & 0x70) >> 0x4);
- }
- PRIVATE void buildimm(eap, signflag)
- register struct ea_s *eap;
- bool_pt signflag;
- {
- immadr = eap->displ;
- immcount = eap->size;
- if (!(immadr.data & (FORBIT | RELBIT | UNDBIT)))
- {
- if (immcount == 0x1)
- {
- if ((offset_t) (immadr.offset + 0x80) >= 0x180)
- datatoobig();
- }
- else if (signflag && is8bitsignedoffset(immadr.offset))
- {
- opcode |= SIGNBIT;
- immcount = 0x1;
- }
- else if (immcount == 0x2)
- {
- if ((offset_t) (immadr.offset + 0x8000L) >= 0x18000L)
- datatoobig();
- }
- }
- }
- PRIVATE void buildregular()
- {
- if (mcount != 0x0)
- {
- buildea(&target);
- postb |= regbits[source.base];
- }
- }
- /* Check size and build segword. */
- PRIVATE void buildsegword(eap)
- register struct ea_s *eap;
- {
- if (eap->size == 0x0)
- #ifdef NODEFAULTSIZE
- kgerror(SIZE_UNK);
- #else
- eap->size = defsize;
- #endif
- if (eap->indcount != 0x0 || eap->base == NOREG)
- {
- segword = WORDBIT;
- if (eap->size == 0x1)
- segword = BYTE_SEGWORD;
- }
- else
- segword = regsegword[eap->base];
- }
- PRIVATE void buildunary(opc)
- opcode_pt opc;
- {
- if (mcount != 0x0)
- {
- buildea(&target);
- postb |= opcode;
- opcode = opc;
- }
- }
- PRIVATE opsize_pt displsize(eap)
- register struct ea_s *eap;
- {
- opsize_t asize;
- asize = defsize;
- if (!(eap->displ.data & UNDBIT))
- {
- if (asize > 0x2)
- {
- if (!(eap->displ.data & (FORBIT | RELBIT)) &&
- iswordadr(eap->displ.offset))
- asize = 0x2;
- }
- else if (!iswordorswordoffset(eap->displ.offset))
- /* should really use iswordadr() */
- /* but compiler generates signed offsets */
- {
- if (!(eap->displ.data & (FORBIT | RELBIT)))
- asize = 0x4;
- else if (pass2)
- error(ABOUNDS);
- }
- }
- return asize;
- }
- PRIVATE reg_pt fpregchk()
- {
- reg_pt fpreg;
- fpreg_allowed = TRUE;
- fpreg = regchk();
- fpreg_allowed = FALSE;
- if (fpreg != ST0REG)
- return NOREG;
- getsym();
- if (sym == LPAREN)
- {
- getsym();
- if (sym != INTCONST || (unsigned) number >= 0x8)
- error(ILL_FP_REG);
- else
- {
- fpreg += number;
- getsym();
- if (sym != RPAREN)
- error(RPEXP);
- else
- getsym();
- }
- }
- return fpreg;
- }
- PRIVATE bool_pt getaccumreg(eap)
- register struct ea_s *eap;
- {
- if ((eap->base = regchk()) != AXREG && eap->base != ALREG
- && eap->base != EAXREG)
- return FALSE;
- getsym();
- if ((eap->size = regsize[eap->base]) > 0x1 && eap->size != defsize)
- oprefix = 0x66;
- return TRUE;
- }
- /*
- Get binary ea's in target & source (flipped if direction is set).
- Put size in source if not already.
- Initialise direction, segword, bump mcount.
- */
- PRIVATE void getbinary()
- {
- ++mcount;
- getea(&target);
- if (target.indcount == 0x0 && target.base == NOREG)
- {
- error(ILL_IMM_MODE);
- target.base = AXREG;
- target.size = defsize;
- }
- getcomma();
- getea(&source);
- if (source.size == 0x0)
- source.size = target.size;
- else if (target.size != 0x0 && target.size != source.size)
- {
- kgerror(MISMATCHED_SIZE);
- return;
- }
- if (source.indcount == 0x0 && regsegword[target.base] < SEGMOV)
- direction = 0x0;
- else if (target.indcount == 0x0 && regsegword[source.base] < SEGMOV)
- {
- struct ea_s swap;
- direction = TOREGBIT;
- swap = source;
- source = target;
- target = swap;
- }
- else if (target.indcount != 0x0)
- {
- kgerror(ILL_IND_TO_IND);
- return;
- }
- else
- {
- kgerror(ILL_SEG_REG);
- return;
- }
- buildsegword(&source);
- }
- PRIVATE bool_pt getdxreg(eap)
- register struct ea_s *eap;
- {
- if ((eap->base = regchk()) != DXREG)
- return FALSE;
- getsym();
- return TRUE;
- }
- /* parse effective address */
- /*
- Syntax is restrictive in that displacements must be in the right spots
- and will not be added up.
- optional size-type prefix, which is
- BYTE
- BYTE PTR
- WORD
- WORD PTR
- DWORD
- DWORD PTR
- PTR
- reg
- segreg
- [scaled index]
- where scaled index =
- indreg
- indreg*scale
- indreg+indreg
- indreg+indreg*scale
- [scaled index+displ]
- [scaled index-displ]
- optional-immediate-prefix displ[scaled index]
- [displ]
- optional-imediate-prefix displ
- (scaled index) -- anachronism
- optional-imediate-prefix displ(scaled index) -- anachronism
- */
- PRIVATE void getea(eap)
- register struct ea_s *eap;
- {
- bool_t leading_displ;
- bool_t leading_immed;
- register struct sym_s *symptr;
- leading_immed = leading_displ = lastexp.data = eap->indcount
- = lastexp.offset = 0x0;
- eap->index = eap->base = NOREG;
- eap->scale = 0x1;
- eap->size = mnsize; /* 0x1 for byte ops, else 0x0 */
- if (sym == IDENT)
- {
- if ((symptr = gsymptr)->type & MNREGBIT)
- {
- if (symptr->data & SIZEBIT)
- {
- getsym();
- if (symptr->value_reg_or_op.op.opcode == 0x0)
- eap->indcount = 0x2 - calljmp_kludge;
- else
- {
- if (eap->size != 0x0)
- {
- if (eap->size != symptr->value_reg_or_op.op.opcode)
- error(MISMATCHED_SIZE);
- }
- else
- eap->size = symptr->value_reg_or_op.op.opcode;
- if (eap->size > 0x1 && eap->size != defsize)
- oprefix = 0x66;
- if (sym == IDENT &&
- (symptr = gsymptr)->type & MNREGBIT &&
- symptr->data & SIZEBIT &&
- symptr->value_reg_or_op.op.routine == PTROP)
- {
- getsym();
- eap->indcount = 0x2 - calljmp_kludge;
- }
- }
- }
- }
- if( last_pass == 1 )
- if (!(symptr->type & (LABIT | MACBIT | MNREGBIT | VARBIT)))
- symptr->data |= FORBIT; /* show seen in advance */
- }
- if ((eap->base = regchk()) != NOREG)
- {
- getsym();
- if (eap->indcount != 0x0)
- {
- error(ILL_IND_PTR);
- eap->indcount = 0x0;
- }
- if (eap->size != 0x0 && eap->size != regsize[eap->base])
- error(MISMATCHED_SIZE);
- if ((eap->size = regsize[eap->base]) > 0x1 && eap->size != defsize)
- oprefix = 0x66;
- eap->displ = lastexp;
- needcpu(eap->size==4?3:0);
- return;
- }
- if (sym != lindirect)
- {
- if (sym == IMMEDIATE || sym == STAR)
- {
- /* context-sensitive, STAR means signed immediate here */
- leading_immed = TRUE;
- getsym();
- }
- leading_displ = TRUE;
- expres();
- eap->displ = lastexp;
- }
- if (sym == lindirect)
- {
- getsym();
- eap->indcount = 0x2 - calljmp_kludge;
- if ((eap->base = indregchk((reg_pt) NOREG)) != NOREG)
- {
- if (eap->indcount == 0x0 && leading_displ)
- error(IND_REQ);
- getsym();
- if (sym == ADDOP)
- {
- getsym();
- if ((eap->index = indregchk(eap->base)) != NOREG)
- getsym();
- else
- {
- if (eap->indcount == 0x0)
- error(IND_REQ);
- if (leading_displ)
- error(REPEATED_DISPL);
- expres(); /* this eats ADDOP, SUBOP, MULOP */
- }
- }
- if (sym == STAR)
- {
- needcpu(3);
- /* context-sensitive, STAR means scaled here*/
- if (eap->index == NOREG && eap->base == ESPREG)
- {
- error(INDEX_REG_EXP);
- eap->base = EAXREG;
- }
- getsym();
- factor();
- chkabs();
- if (!(lastexp.data & UNDBIT) && lastexp.offset != 0x1)
- {
- if (eap->base <= MAX16BITINDREG ||
- (lastexp.offset != 0x2 && lastexp.offset != 0x4 &&
- lastexp.offset != 0x8))
- error(ILL_SCALE);
- else
- {
- eap->scale = lastexp.offset;
- if (eap->index == NOREG)
- {
- eap->index = eap->base;
- eap->base = NOREG;
- }
- }
- }
- lastexp.data = lastexp.offset = 0x0;
- }
- if ((sym == ADDOP || sym == SUBOP))
- {
- if (eap->indcount == 0x0)
- error(IND_REQ);
- if (leading_displ)
- error(REPEATED_DISPL);
- expres();
- }
- }
- else
- {
- if (leading_displ)
- error(REPEATED_DISPL);
- expres();
- }
- if (sym != rindirect)
- error(rindexp);
- else
- getsym();
- }
- /* RDB */
- else if (!leading_immed && defsize <= 0x2)
- eap->indcount = 0x1; /* compatibility kludge */
- if (!leading_displ)
- eap->displ = lastexp;
- needcpu(eap->size==4?3:0);
- }
- PRIVATE void getimmed(eap, immed_count)
- struct ea_s *eap;
- count_t immed_count;
- {
- getea(eap);
- yesimmed(eap);
- if (mcount != 0x0)
- {
- eap->size = immed_count;
- buildimm(eap, FALSE);
- }
- }
- PRIVATE void getindirect(eap)
- register struct ea_s *eap;
- {
- getea(eap);
- if (eap->indcount == 0x0)
- kgerror(IND_REQ);
- }
- PRIVATE void getshift(eap)
- register struct ea_s *eap;
- {
- getcomma();
- getea(eap);
- if (eap->base != CLREG)
- yesimmed(eap);
- }
- /*
- Check if current symbol is a compatible index register.
- Generate error if it is a reg but not a compatible index.
- Return register number (adjusted if necessary to a legal index) or NOREG.
- */
- PRIVATE reg_pt indregchk(matchreg)
- reg_pt matchreg;
- {
- reg_pt reg;
- if ((reg = regchk()) != NOREG)
- {
- switch (matchreg)
- {
- case BPREG:
- case BXREG:
- if (reg != DIREG && reg != SIREG)
- {
- reg = SIREG;
- error(INDEX_REG_EXP);
- }
- break;
- case DIREG:
- case SIREG:
- if (reg != BPREG && reg != BXREG)
- {
- reg = BXREG;
- error(INDEX_REG_EXP);
- }
- break;
- case NOREG:
- break;
- default:
- if (reg <= MAX16BITINDREG || reg == ESPREG)
- {
- reg = EAXREG;
- error(INDEX_REG_EXP);
- }
- break;
- }
- if (reg > MAXINDREG && calljmp_kludge == 0x0)
- {
- if (matchreg != NOREG)
- reg = EAXREG;
- else
- reg = BXREG;
- error(INDEX_REG_EXP);
- }
- }
- return reg;
- }
- PRIVATE void kgerror(err_str)
- char * err_str;
- {
- error(err_str);
- sprefix = oprefix = aprefix = mcount = 0x0;
- }
- PRIVATE void lbranch(backamount)
- int backamount;
- {
- mcount += defsize + 0x1;
- segadj();
- if (pass2)
- {
- reldata();
- if (!(lastexp.data & (RELBIT | UNDBIT)))
- {
- lastexp.offset = lastexp.offset - lc - lcjump;
- if ( last_pass<2 && backamount != 0x0 &&
- !(lastexp.data & IMPBIT) &&
- lastexp.offset + backamount < 0x80 + backamount)
- warning(SHORTB); /* -0x8? to 0x7F, warning */
- }
- }
- }
- /* BCC (long branches emulated by short branch over & long jump) */
- PUBLIC void mbcc()
- {
- getea(&target);
- if (target.indcount >= 0x2 || target.base != NOREG)
- kgerror(REL_REQ);
- else
- {
- #ifdef iscpu
- if (iscpu(3))
- #else
- if (defsize != 0x2)
- #endif
- {
- page = PAGE1_OPCODE;
- ++mcount;
- opcode += 0x10;
- lbranch(0x84);
- }
- else
- {
- aprefix = opcode ^ 0x1; /* kludged storage for short branch
- over */
- oprefix = defsize + 0x1;
- mcount += 0x2;
- opcode = JMP_OPCODE;
- lbranch(0x83);
- mcount -= 0x2;
- }
- }
- }
- /* bswap r32 */
- PUBLIC void mbswap()
- {
- needcpu(4);
- ++mcount;
- Gd(&target);
- opcode |= rm[target.base];
- }
- /* BR, CALL, J, JMP */
- PUBLIC void mcall()
- {
- opcode_pt far_diff;
- bool_t indirect;
- register struct sym_s *symptr;
- far_diff = 0x0;
- if (sym == IDENT && (symptr = gsymptr)->type & MNREGBIT &&
- symptr->data & SIZEBIT )
- {
- if(symptr->value_reg_or_op.op.routine == FAROP)
- {
- far_diff = 0x8;
- getsym();
- }
- if(symptr->value_reg_or_op.op.routine == WORDOP &&
- opcode == JMP_SHORT_OPCODE)
- {
- opcode = JMP_OPCODE;
- getsym();
- }
- }
- indirect = FALSE;
- if (asld_compatible && defsize <= 0x2)
- {
- calljmp_kludge = 0x2;
- if (sym == INDIRECT)
- {
- calljmp_kludge = 0x0;
- indirect = TRUE;
- getsym();
- }
- }
- getea(&target);
- if (indirect && target.indcount == 0x1)
- target.indcount = 0x2;
- calljmp_kludge = 0x0;
- if (sym == COLON)
- {
- int tsize = target.size?target.size:defsize;
- if (opcode == JMP_SHORT_OPCODE)
- opcode = JMP_OPCODE;
- ++mcount;
- yesimmed(&target);
- getsym();
- getea(&source);
- yesimmed(&source);
- if (mcount != 0x0)
- {
- if (opcode == JMP_OPCODE)
- opcode = 0xEA;
- else
- opcode = 0x9A;
- lastexp = source.displ;
- if (!(lastexp.data & (FORBIT | RELBIT | UNDBIT)) &&
- tsize == 0x2 &&
- (offset_t) (lastexp.offset + 0x8000L) >= 0x18000L)
- datatoobig();
- mcount += tsize;
- target.size = 0x2;
- buildimm(&target, FALSE);
- }
- }
- else if (target.indcount >= 0x2 || target.base != NOREG)
- {
- ++mcount;
- notsegorspecreg(&target);
- if (target.indcount == 0)
- notbytesize(&target);
- if (mcount != 0x0)
- {
- if (opcode == JMP_SHORT_OPCODE)
- opcode = JMP_OPCODE;
- buildea(&target);
- if (opcode == JMP_OPCODE)
- opcode = 0x20;
- else
- opcode = 0x10;
- postb |= opcode + far_diff;
- opcode = 0xFF;
- }
- }
- else if (opcode == JMP_SHORT_OPCODE)
- {
- if (jumps_long &&
- ((pass!=0 && !is8bitsignedoffset(lastexp.offset - lc - 2)) ||
- (last_pass==1)))
- {
- opcode = JMP_OPCODE;
- lbranch(0x83);
- }
- else
- {
- lastexp = target.displ;
- if (lastexp.data & IMPBIT)
- {
- error(NONIMPREQ);
- lastexp.data = FORBIT | UNDBIT;
- }
- mshort2();
- }
- }
- else
- lbranch(opcode == JMP_OPCODE ? 0x83 : 0x0);
- }
- /* CALLI, JMPI */
- PUBLIC void mcalli()
- {
- bool_t indirect;
- ++mcount;
- indirect = FALSE;
- if (sym == INDIRECT)
- {
- getsym();
- indirect = TRUE;
- }
- getea(&target);
- if (target.indcount >= 0x2 || target.base != NOREG)
- indirect = TRUE;
- if (indirect)
- {
- buildea(&target);
- if (opcode == 0xEA)
- opcode = 0x28;
- else
- opcode = 0x18;
- postb |= opcode;
- opcode = 0xFF;
- }
- else
- {
- int tsize = target.size?target.size:defsize;
- getcomma();
- getea(&source);
- yesimmed(&source);
- if (mcount != 0x0)
- {
- lastexp = target.displ;
- if (!(lastexp.data & (FORBIT | RELBIT | UNDBIT)) &&
- tsize == 0x2 &&
- (offset_t) (lastexp.offset + 0x8000L) >= 0x18000L)
- {
- tsize=4;
- if( tsize != defsize ) oprefix = 0x66;
- /* datatoobig(); */
- }
- needcpu(tsize==4?3:0);
- mcount += tsize;
- source.size = 0x2;
- buildimm(&source, FALSE);
- }
- }
- }
- /* DIV, IDIV, MUL */
- PUBLIC void mdivmul()
- {
- if (getaccumreg(&source))
- {
- ++mcount;
- getcomma();
- Ex(&target);
- yes_samesize();
- buildunary(0xF6 | regsegword[source.base]);
- }
- else
- mnegnot();
- }
- /* ENTER */
- PUBLIC void menter()
- {
- ++mcount;
- getimmed(&target, 0x2);
- getcomma();
- getimmed(&source, 0x1);
- if (mcount != 0x0)
- {
- mcount += 2;
- lastexp = target.displ; /* getimmed(&source) wiped it out */
- }
- needcpu(1);
- }
- /* arpl r/m16,r16 (Intel manual opcode chart wrongly says EwRw) */
- PUBLIC void mEwGw()
- {
- ++mcount;
- Ew(&target);
- getcomma();
- Gw(&source);
- oprefix = 0x0;
- buildregular();
- }
- /* [cmpxchg xadd] [r/m8,r8 r/m16,r16, r/m32,r32] */
- PUBLIC void mExGx()
- {
- ++mcount;
- Ex(&target);
- getcomma();
- Gx(&source);
- yes_samesize();
- opcode |= segword;
- buildregular();
- }
- PUBLIC void mf_inher()
- {
- mcount += 0x2;
- postb = REG_MOD | (opcode & ~REG_MOD);
- opcode = ESCAPE_OPCODE_BASE | (opcode >> 0x6);
- if (opcode == ESCAPE_OPCODE_BASE)
- opcode = ESCAPE_OPCODE_BASE | 0x6; /* fix up encoding of fcompp */
- }
- /* [fldenv fnsave fnstenv frstor] mem */
- PUBLIC void mf_m()
- {
- ++mcount;
- getindirect(&source);
- if (source.size != 0x0)
- kgerror(ILL_SIZE);
- buildfloat();
- }
- /* [fldcw fnstcw] mem2i */
- PUBLIC void mf_m2()
- {
- ++mcount;
- getindirect(&source);
- if (source.size != 0x0 && source.size != 0x2)
- kgerror(ILL_SIZE);
- buildfloat();
- }
- /* fnstsw [mem2i ax] */
- PUBLIC void mf_m2_ax()
- {
- if (getaccumreg(&target))
- {
- if (target.base != AXREG)
- kgerror(ILLREG);
- else
- {
- opcode = 0x74;
- target.base = ST0REG; /* fake, really ax */
- buildfreg();
- }
- }
- else
- mf_m2();
- }
- /* [fiadd ficom ficomp fidiv fidivr fimul fist fisub fisubr] [mem2i mem4i] */
- PUBLIC void mf_m2_m4()
- {
- ++mcount;
- getindirect(&source);
- if (source.size == 0x0)
- kgerror(SIZE_UNK);
- else if (source.size == 0x2)
- opcode |= 0x40;
- else if (source.size != 0x4)
- kgerror(ILL_SIZE);
- buildfloat();
- }
- /* [fild fistp] [mem2i mem4i mem8i] */
- PUBLIC void mf_m2_m4_m8()
- {
- ++mcount;
- getindirect(&source);
- if (source.size == 0x0)
- kgerror(SIZE_UNK);
- else if (source.size == 0x2)
- opcode |= 0x40;
- else if (source.size == 0x8)
- opcode |= 0x45; /* low bits 0 -> 5 and 3 -> 7 */
- else if (source.size != 0x4)
- kgerror(ILL_SIZE);
- buildfloat();
- }
- /* [fcom fcomp] [mem4r mem8r optional-st(i)] */
- PUBLIC void mf_m4_m8_optst()
- {
- if (sym == EOLSYM)
- {
- target.base = ST1REG;
- buildfreg();
- }
- else
- mf_m4_m8_st();
- }
- /* [fadd fdiv fdivr fmul fsub fsubr] [mem4r mem8r st,st(i) st(i),st] */
- PUBLIC void mf_m4_m8_stst()
- {
- target.base = fpregchk();
- if (target.base != NOREG)
- {
- getcomma();
- source.base = fpregchk();
- if (source.base == NOREG)
- {
- error(FP_REG_REQ);
- source.base = ST0REG;
- }
- if (target.base == ST0REG)
- target.base = source.base;
- else
- {
- if (source.base != ST0REG)
- error(ILL_FP_REG_PAIR);
- opcode |= 0x40;
- if ((opcode & 0x07) >= 0x4)
- opcode ^= 0x01; /* weird swap of fdiv/fdivr, fsub/fsubr */
- }
- buildfreg();
- }
- else
- {
- ++mcount;
- getindirect(&source);
- if (source.size == 0x0)
- kgerror(SIZE_UNK);
- else if (source.size == 0x8)
- opcode |= 0x40;
- else if (source.size != 0x4)
- kgerror(ILL_SIZE);
- buildfloat();
- }
- }
- /* fst [mem4r mem8r st(i)] */
- PUBLIC void mf_m4_m8_st()
- {
- target.base = fpregchk();
- if (target.base != NOREG)
- {
- if (opcode == FST_ENCODED)
- opcode |= 0x40;
- buildfreg();
- }
- else
- {
- ++mcount;
- getindirect(&source);
- if (source.size == 0x0)
- kgerror(SIZE_UNK);
- else if (source.size == 0x8)
- opcode |= 0x40;
- else if (source.size != 0x4)
- kgerror(ILL_SIZE);
- buildfloat();
- }
- }
- /* [fld fstp] [mem4r mem8r mem10r st(i)] */
- PUBLIC void mf_m4_m8_m10_st()
- {
- target.base = fpregchk();
- if (target.base != NOREG)
- {
- if (opcode == FSTP_ENCODED)
- opcode |= 0x40;
- buildfreg();
- }
- else
- {
- ++mcount;
- getindirect(&source);
- if (source.size == 0x0)
- kgerror(SIZE_UNK);
- else if (source.size == 0x8)
- opcode |= 0x40;
- else if (source.size == 0xA)
- opcode |= 0x25; /* low bits 0 -> 5 and 3 -> 7 */
- else if (source.size != 0x4)
- kgerror(ILL_SIZE);
- buildfloat();
- }
- }
- /* [fbld fbstp] mem10r */
- PUBLIC void mf_m10()
- {
- ++mcount;
- getindirect(&source);
- if (source.size != 0xA)
- kgerror(ILL_SIZE);
- buildfloat();
- }
- /* ffree st(i) */
- PUBLIC void mf_st()
- {
- target.base = fpregchk();
- if (target.base == NOREG)
- kgerror(FP_REG_REQ);
- buildfreg();
- }
- /* [fucom fucomp fxch] optional-st(i) */
- PUBLIC void mf_optst()
- {
- if (sym == EOLSYM)
- {
- target.base = ST1REG;
- buildfreg();
- }
- else
- mf_st();
- }
- /* [faddp fdivp fdivrp fmulp fsubp fsubrp] st(i),st */
- PUBLIC void mf_stst()
- {
- target.base = fpregchk();
- if (target.base == NOREG)
- {
- kgerror(FP_REG_REQ);
- return;
- }
- getcomma();
- source.base = fpregchk();
- if (source.base == NOREG)
- {
- kgerror(FP_REG_REQ);
- return;
- }
- if (source.base != ST0REG)
- {
- kgerror(ILL_FP_REG);
- return;
- }
- buildfreg();
- }
- PUBLIC void mf_w_inher()
- {
- sprefix = WAIT_OPCODE;
- mf_inher();
- }
- /* [fsave fstenv] mem */
- PUBLIC void mf_w_m()
- {
- sprefix = WAIT_OPCODE;
- mf_m();
- }
- /* fstcw mem2i */
- PUBLIC void mf_w_m2()
- {
- sprefix = WAIT_OPCODE;
- mf_m2();
- }
- /* fstsw [mem2i ax] */
- PUBLIC void mf_w_m2_ax()
- {
- sprefix = WAIT_OPCODE;
- mf_m2_ax();
- }
- /* ADC, ADD, AND, CMP, OR, SBB, SUB, XOR */
- PUBLIC void mgroup1()
- {
- getbinary();
- notsegorspecreg(&source);
- if (mcount != 0x0)
- {
- if (source.base == NOREG)
- {
- if (target.indcount == 0x0 && (target.base == ALREG ||
- target.base == AXREG ||
- (target.base == EAXREG &&
- (source.displ.data & (FORBIT | RELBIT | UNDBIT) ||
- !is8bitsignedoffset(source.displ.offset)))))
- {
- opcode |= 0x04 | segword;
- buildimm(&source, FALSE);
- }
- else
- {
- buildunary(0x80 | segword);
- buildimm(&source, TRUE);
- }
- }
- else
- {
- opcode |= direction | segword;
- buildregular();
- }
- }
- }
- /* RCL, RCR, ROL, ROR, SAL, SAR, SHL, SHR */
- PUBLIC void mgroup2()
- {
- ++mcount;
- Ex(&target);
- buildsegword(&target);
- getshift(&source);
- if (mcount != 0x0)
- {
- buildunary(0xD0 | segword);
- if (source.base == CLREG)
- opcode |= 0x2;
- else if (source.displ.offset != 0x1)
- {
- needcpu(1);
- opcode -= 0x10;
- source.size = 0x1;
- buildimm(&source, FALSE);
- }
- }
- }
- /* LLDT, LTR, SLDT, STR, VERR, VERW */
- PUBLIC void mgroup6()
- {
- needcpu(2);
- ++mcount;
- Ew(&target);
- oprefix = 0x0;
- buildunary(0x0);
- }
- /* INVLPG, LGDT, LIDT, LMSW, SGDT, SIDT, SMSW */
- PUBLIC void mgroup7()
- {
- needcpu(2); /* I think INVLPG is actually 386 */
- ++mcount;
- if (opcode == 0x20 || opcode == 0x30)
- {
- Ew(&target);
- oprefix = 0x0;
- }
- else
- {
- getindirect(&target);
- oprefix = 0x0;
- if (target.size != 0x0 && target.size != 0x6)
- error(MISMATCHED_SIZE); /* XXX - size 6 wrong for INVLPG? */
- }
- buildunary(0x1);
- }
- /* BT, BTR, BTS, BTC */
- PUBLIC void mgroup8()
- {
- needcpu(3);
- ++mcount;
- Ev(&target);
- getcomma();
- /* Gv or Ib */
- getea(&source);
- notindirect(&source);
- notsegorspecreg(&source);
- if (mcount != 0x0)
- {
- if (source.base == NOREG)
- {
- buildunary(0xBA);
- source.size = 0x1;
- buildimm(&source, TRUE);
- }
- else
- {
- yes_samesize();
- opcode += 0x83;
- buildregular();
- }
- }
- }
- /* BSF, BSR, LAR, LSL (Intel manual opcode chart wrongly says GvEw for L*) */
- PUBLIC void mGvEv()
- {
- needcpu(2);
- ++mcount;
- Gv(&source);
- getcomma();
- Ev(&target);
- yes_samesize();
- buildregular();
- }
- /* bound [r16,m16&16 r32,m32&32] */
- PUBLIC void mGvMa()
- {
- ++mcount;
- Gv(&source);
- getcomma();
- getindirect(&target);
- yes_samesize();
- buildregular();
- }
- /* LDS, LES, LFS, LGS, LSS */
- PUBLIC void mGvMp()
- {
- ++mcount;
- Gv(&source);
- getcomma();
- getindirect(&target);
- if (target.size != 0x0 && target.size != 0x2 + source.size)
- error(MISMATCHED_SIZE);
- buildregular();
- }
- /* IMUL */
- PUBLIC void mimul()
- {
- ++mcount;
- Ex(&target);
- if (sym != COMMA)
- {
- buildsegword(&target);
- buildunary(0xF6 | segword);
- return;
- }
- getcomma();
- notindirect(&target);
- source = target; /* direction is swapped */
- getea(&target);
- notsegorspecreg(&target);
- yes_samesize();
- if (sym != COMMA && (target.indcount != 0x0 || target.base != NOREG))
- {
- needcpu(3);
- page = PAGE1_OPCODE;
- ++mcount;
- opcode = 0xAF;
- buildregular();
- }
- else
- {
- if (sym == COMMA)
- {
- getsym();
- getea(&source2);
- yesimmed(&source2);
- }
- else
- {
- source2 = target;
- target = source;
- }
- source2.size = target.size;
- if (is8bitsignedoffset(source2.displ.offset))
- {
- source2.size = 0x1;
- opcode = 0x6B;
- }
- else
- {
- source2.size = target.size;
- opcode = 0x69;
- }
- buildregular();
- if (mcount != 0x0)
- buildimm(&source2, FALSE);
- }
- }
- /* IN */
- PUBLIC void min()
- {
- ++mcount;
- if (opcode & WORDBIT) /* inw; ind not supported */
- mnsize = 0x2;
- if (sym == EOLSYM && mnsize != 0x0)
- target.size = mnsize;
- else
- {
- if (getaccumreg(&target))
- {
- if (mnsize != 0x0 && regsize[target.base] != mnsize)
- error(MISMATCHED_SIZE);
- getcomma();
- }
- else
- target.size = regsize[target.base = mnsize < 0x2 ? ALREG : AXREG];
- opcode |= regsegword[target.base];
- if (!getdxreg(&source))
- {
- getimmed(&source, 0x1);
- opcode -= 0x8;
- }
- }
- if (target.size > 0x1 && target.size != defsize)
- oprefix = 0x66;
- }
- /* DEC, INC */
- PUBLIC void mincdec()
- {
- ++mcount;
- Ex(&target);
- buildsegword(&target);
- if (target.indcount == 0x0 && segword == WORDBIT)
- opcode |= 0x40 | rm[target.base];
- else
- buildunary(0xFE | segword);
- }
- /* CBW, CWD, CMPSW, INSW, IRET, LODSW, POPA, POPF, PUSHA, PUSHF */
- /* MOVSW, OUTSW, SCASW, STOSW */
- PUBLIC void minher16()
- {
- minher();
- if (defsize != 0x2)
- oprefix = 0x66;
- }
- /* CWDE, CDQ, CMPSD, INSD, IRETD, LODSD, POPAD, POPFD, PUSHAD, PUSHFD */
- /* MOVSD, OUTSD, SCASD, STOSD */
- PUBLIC void minher32()
- {
- minher();
- if (defsize != 0x4)
- oprefix = 0x66;
- needcpu(3);
- }
- /* AAD, AAM */
- PUBLIC void minhera()
- {
- ++mcount;
- if (sym == EOLSYM)
- {
- target.displ.offset = 0xA;
- target.size = 0x1;
- buildimm(&target, FALSE);
- }
- else
- getimmed(&target, 0x1);
- }
- /* INT */
- PUBLIC void mint()
- {
- ++mcount;
- getimmed(&target, 0x1);
- if (!(immadr.data & (FORBIT | RELBIT | UNDBIT)) &&
- (opcode_t) immadr.offset == 0x3)
- {
- immcount = 0x0;
- opcode = 0xCC;
- }
- }
- /* JCC */
- PUBLIC void mjcc()
- {
- /* First look for j* near */
- if (sym == IDENT &&
- gsymptr->type & MNREGBIT &&
- gsymptr->data & SIZEBIT &&
- gsymptr->value_reg_or_op.op.routine == WORDOP &&
- opcode < 0x80)
- {
- getsym();
- getea(&target);
- if (target.indcount >= 0x2 || target.base != NOREG)
- kgerror(REL_REQ);
- else
- {
- needcpu(3);
- page = PAGE1_OPCODE;
- ++mcount;
- opcode += 0x10;
- lbranch(0x84);
- }
- }
- else if (!jumps_long || opcode > 0x80) /* above 0x80 means loop, not long */
- mshort();
- else /* mbcc */
- {
- getea(&target);
- lastexp = target.displ;
- if ( (pass!=0 && !is8bitsignedoffset(lastexp.offset - lc - 2)) ||
- last_pass==1)
- {
- if (target.indcount >= 0x2 || target.base != NOREG)
- kgerror(REL_REQ);
- aprefix = opcode ^ 0x1; /* kludged storage for short branch
- over */
- oprefix = defsize + 0x1;
- mcount += 0x2;
- opcode = JMP_OPCODE;
- lbranch(0x83);
- mcount -= 0x2;
- }
- else
- {
- /* 8 bit */
- if (lastexp.data & IMPBIT)
- {
- error(NONIMPREQ);
- lastexp.data = FORBIT | UNDBIT;
- }
- mshort2();
- }
- }
- }
- /* JCXZ, JECXZ */
- PUBLIC void mjcxz()
- {
- if (opcode != defsize)
- {
- aprefix = 0x67;
- ++mcount; /* quick fix - mshort() needs to know */
- }
- opcode = 0xE3;
- mshort();
- if (aprefix != 0x0)
- --mcount; /* quick fix - main routine bumps it again */
- }
- /* LEA */
- PUBLIC void mlea()
- {
- Gv(&source); /* back to front */
- getcomma();
- ++mcount;
- getindirect(&target);
- yes_samesize();
- buildregular();
- }
- /* MOV */
- PUBLIC void mmov()
- {
- getbinary();
- if (segword >= SEGMOV)
- {
- oprefix = 0x0;
- notimmed(&target); /* target is actually the source */
- if (segword > SEGMOV) /* special reg */
- notindirect(&target);
- }
- if (mcount != 0x0)
- {
- if (target.base == NOREG && target.index == NOREG &&
- (source.base == ALREG || source.base == AXREG ||
- source.base == EAXREG))
- {
- opcode = 0xA0 | (direction ^ TOREGBIT) | segword;
- lastexp = target.displ;
- if ((source.size = displsize(&target)) != defsize)
- aprefix = 0x67;
- mcount += source.size;
- needcpu(source.size==4?3:0);
- }
- else if (source.base == NOREG)
- {
- if (target.indcount == 0x0)
- opcode = 0xB0 | (segword << 0x3) | rm[target.base];
- else
- {
- buildea(&target);
- opcode = 0xC6 | segword;
- }
- buildimm(&source, FALSE);
- }
- else
- {
- if (isspecreg(source.base))
- {
- needcpu(3);
- page = PAGE1_OPCODE;
- ++mcount;
- opcode = 0x0;
- }
- opcode |= direction | segword;
- buildregular();
- }
- }
- }
- /* MOVSX, MOVZX */
- PUBLIC void mmovx()
- {
- ++mcount;
- Gv(&source);
- getcomma();
- Ex(&target);
- if (target.size == 0x0)
- kgerror(SIZE_UNK);
- if (target.size > 0x2)
- kgerror(ILL_SIZE);
- oprefix = 0x0;
- if (source.size != defsize)
- oprefix = 0x66;
- buildsegword(&target);
- opcode |= segword;
- buildregular();
- }
- /* NEG, NOT */
- PUBLIC void mnegnot()
- {
- ++mcount;
- Ex(&target);
- buildsegword(&target);
- buildunary(0xF6 | segword);
- }
- /* OUT */
- PUBLIC void mout()
- {
- ++mcount;
- if (opcode & WORDBIT) /* outw; outd not supported */
- mnsize = 0x2;
- if (sym == EOLSYM && mnsize != 0x0)
- source.size = mnsize;
- else
- {
- if (!getdxreg(&target))
- {
- getimmed(&target, 0x1);
- opcode -= 0x8;
- }
- if (sym == COMMA)
- {
- getsym();
- if (!getaccumreg(&source))
- kgerror(AL_AX_EAX_EXP);
- else if (mnsize != 0x0 && regsize[source.base] != mnsize)
- error(MISMATCHED_SIZE);
- }
- else
- source.size = regsize[source.base = mnsize < 0x2 ? ALREG : AXREG];
- opcode |= regsegword[source.base];
- }
- if (source.size > 0x1 && source.size != defsize)
- oprefix = 0x66;
- }
- /* POP, PUSH */
- PUBLIC void mpushpop()
- {
- opcode_t oldopcode;
- ++mcount;
- getea(&target);
- buildsegword(&target);
- notbytesize(&target);
- if ((oldopcode = opcode) == POP_OPCODE)
- {
- notimmed(&target);
- if (target.base == CSREG)
- kgerror(ILL_SEG_REG);
- }
- if (mcount != 0x0)
- {
- if (target.indcount == 0x0)
- {
- if (segword == SEGMOV)
- {
- switch (target.base)
- {
- case CSREG:
- opcode = 0x0E;
- break;
- case DSREG:
- opcode = 0x1E;
- break;
- case ESREG:
- opcode = 0x06;
- break;
- case SSREG:
- opcode = 0x16;
- break;
- case FSREG:
- opcode = 0xA0;
- page = PAGE1_OPCODE;
- ++mcount;
- break;
- case GSREG:
- opcode = 0xA8;
- page = PAGE1_OPCODE;
- ++mcount;
- break;
- }
- if (oldopcode == POP_OPCODE)
- ++opcode;
- }
- else if (target.base != NOREG)
- {
- opcode = 0x50 | rm[target.base];
- if (oldopcode == POP_OPCODE)
- opcode |= 0x8;
- }
- else
- {
- needcpu(1); /* On 8086 PUSH does not allow immediate */
- opcode = 0x68;
- if (oldopcode == POP_OPCODE)
- ++opcode;
- buildimm(&target, TRUE);
- }
- }
- else
- {
- buildea(&target);
- if (oldopcode == PUSH_OPCODE)
- postb |= 0x6 << REG_SHIFT;
- }
- }
- }
- /* RET, RETF */
- PUBLIC void mret()
- {
- ++mcount;
- if (sym != EOLSYM)
- {
- --opcode;
- getimmed(&target, 0x2);
- }
- }
- /* SEG CS/DS/ES/FS/GS/SS */
- PUBLIC void mseg()
- {
- reg_pt reg;
- if (regsegword[reg = regchk()] != SEGMOV)
- error(SEG_REG_REQ);
- else
- {
- getsym();
- ++mcount;
- opcode = (segoverride - CSREG)[reg];
- }
- }
- /* SETCC */
- PUBLIC void msetcc()
- {
- ++mcount;
- Eb(&target);
- if (mcount != 0x0)
- buildea(&target);
- }
- /* SHLD, SHRD */
- PUBLIC void mshdouble()
- {
- needcpu(3);
- ++mcount;
- Ev(&target);
- getcomma();
- Gv(&source);
- yes_samesize();
- buildregular();
- getshift(&source2);
- lastexp = target.displ; /* getshift() wiped it out */
- if (mcount != 0x0)
- {
- if (source2.base == CLREG)
- opcode |= 0x1;
- else
- {
- source2.size = 0x1;
- buildimm(&source2, FALSE);
- }
- }
- }
- /*
- TEST
- Similar to the regular group1 operators.
- It does not allow the sign extended immediate byte forms
- and does not use the relevant direction bit.
- */
- PUBLIC void mtest()
- {
- getbinary();
- notsegorspecreg(&source);
- if (source.base == NOREG)
- {
- if (mcount != 0x0)
- {
- if (target.indcount == 0x0
- && (target.base == ALREG || target.base == AXREG
- || target.base == EAXREG))
- opcode = 0xA8 | segword;
- else
- {
- buildea(&target);
- opcode = 0xF6 | segword;
- }
- }
- buildimm(&source, FALSE);
- }
- else
- {
- opcode |= segword;
- buildregular();
- }
- }
- /*
- XCHG
- Similar to the regular group1 operators.
- It does not allow any of the immediate forms
- and does not use the irrelevant direction bit.
- */
- PUBLIC void mxchg()
- {
- getbinary();
- notimmed(&source);
- notsegorspecreg(&source);
- if (target.indcount == 0x0)
- {
- if (target.base == AXREG || target.base == EAXREG)
- {
- opcode = 0x90 + rm[source.base];
- return;
- }
- if (source.base == AXREG || source.base == EAXREG)
- {
- opcode = 0x90 + rm[target.base];
- return;
- }
- }
- opcode |= segword;
- buildregular();
- }
- PRIVATE void notbytesize(eap)
- register struct ea_s *eap;
- {
- if (eap->size == 0x1)
- kgerror(ILL_SIZE);
- }
- PRIVATE void notimmed(eap)
- register struct ea_s *eap;
- {
- if (eap->indcount == 0x0 && eap->base == NOREG)
- kgerror(ILL_IMM_MODE);
- }
- PRIVATE void notindirect(eap)
- register struct ea_s *eap;
- {
- if (eap->indcount != 0x0)
- kgerror(ILL_IND);
- }
- PRIVATE void notsegorspecreg(eap)
- register struct ea_s *eap;
- {
- if (regsegword[eap->base] >= SEGMOV)
- kgerror(ILLREG);
- }
- PRIVATE void yesimmed(eap)
- register struct ea_s *eap;
- {
- if (eap->indcount == 0x1)
- eap->indcount = 0x0;
- if (eap->indcount != 0x0 || eap->base != NOREG)
- kgerror(IMM_REQ);
- }
- PRIVATE void yes_samesize()
- {
- if (target.size == 0x0)
- target.size = source.size;
- else if (source.size != 0x0 && target.size != source.size)
- kgerror(MISMATCHED_SIZE);
- }
- #endif /* I80386 */
- #ifdef MC6809
- /* 6809 opcode constants */
- /* bits for indexed addressing */
- #define INDIRECTBIT 0x10
- #define INDEXBIT 0x80 /* except 5 bit offset */
- #define PCRELBIT 0x04 /* PC relative (in certain cases) */
- #define RRBITS 0x60 /* register select bits */
- PRIVATE opcode_t rrindex[] = /* register and index bits for indexed adr */
- {
- 0x60 | INDEXBIT, /* S */
- 0x40 | INDEXBIT, /* U */
- 0x00 | INDEXBIT, /* X */
- 0x20 | INDEXBIT, /* Y */
- PCRELBIT | INDEXBIT, /* PC */
- };
- PRIVATE opcode_t pushpull[] = /* push/pull codes */
- {
- 0x40, /* S */
- 0x40, /* U */
- 0x10, /* X */
- 0x20, /* Y */
- 0x80, /* PC */
- 0x02, /* A */
- 0x04, /* B */
- 0x01, /* CC */
- 0x08, /* DP */
- 0x06, /* D */
- };
- PRIVATE opcode_t tfrexg1[] = /* transfer/exchange codes for source reg */
- {
- 0x40, /* S */
- 0x30, /* U */
- 0x10, /* X */
- 0x20, /* Y */
- 0x50, /* PC */
- 0x80, /* A */
- 0x90, /* B */
- 0xA0, /* CC */
- 0xB0, /* DP */
- 0x00, /* D */
- };
- PRIVATE opcode_t tfrexg2[] = /* transfer/exchange codes for target reg */
- {
- 0x04, /* S */
- 0x03, /* U */
- 0x01, /* X */
- 0x02, /* Y */
- 0x05, /* PC */
- 0x08, /* A */
- 0x09, /* B */
- 0x0A, /* CC */
- 0x0B, /* DP */
- 0x00, /* D */
- };
- FORWARD void checkpostinc P((void));
- FORWARD void doaltind P((void));
- FORWARD void do1altind P((void));
- FORWARD void fixupind P((void));
- FORWARD void getindexnopost P((void));
- FORWARD void inderror P((char * err_str));
- FORWARD reg_pt indreg P((reg_pt maxindex));
- FORWARD void predec1 P((void));
- FORWARD void sustack P((reg_pt stackreg));
- PRIVATE void checkpostinc()
- {
- if (sym == ADDOP)
- {
- if (postb & INDIRECTBIT)
- inderror(ILLMOD); /* single-inc indirect illegal */
- else
- {
- lastexp.offset &= 0xFF00; /* for printing if postbyte is 0: ,X+ */
- getsym();
- }
- }
- else if (sym == POSTINCOP)
- {
- postb |= 0x1;
- getsym();
- }
- else
- postb |= 0x4;
- fixupind();
- }
- /* common code for all-mode ops, alterable-mode ops, indexed ops */
- PRIVATE void doaltind()
- {
- mcount += 0x2;
- if (sym == LBRACKET)
- {
- postb = INDIRECTBIT;
- getsym();
- do1altind();
- if (sym != RBRACKET)
- error(RBEXP);
- }
- else
- do1altind();
- }
- PRIVATE void do1altind()
- {
- bool_t byteflag; /* set if direct or short indexed adr forced */
- char *oldlineptr;
- char *oldsymname;
- reg_pt reg;
- bool_t wordflag; /* set if extended or long indexed adr forced*/
- if ((reg = regchk()) != NOREG)
- {
- switch (reg)
- {
- case AREG:
- postb |= 0x86;
- break;
- case BREG:
- postb |= 0x85;
- break;
- case DREG:
- postb |= 0x8B;
- break;
- default:
- if (indreg(MAXINDREG) != NOREG)
- checkpostinc();
- return;
- }
- getsym();
- if (sym != COMMA)
- inderror(COMEXP);
- else
- getindexnopost();
- return;
- }
- else if (sym == SUBOP) /* could be -R or - in expression */
- {
- oldlineptr = lineptr; /* save state */
- oldsymname = symname;
- getsym();
- reg = regchk();
- lineptr = oldlineptr;
- symname = oldsymname;
- if (reg != NOREG)
- {
- predec1(); /* it's -R */
- return;
- }
- sym = SUBOP;
- }
- else if (sym == COMMA)
- {
- postb |= INDEXBIT;
- getsym();
- if (sym == SUBOP)
- {
- predec1();
- return;
- }
- else if (sym != PREDECOP)
- {
- if (indreg(MAXINDREG) != NOREG)
- checkpostinc();
- return;
- }
- }
- if (sym == PREDECOP)
- {
- postb |= 0x83;
- getindexnopost();
- return;
- }
- /* should have expression */
- wordflag = byteflag = FALSE;
- if (sym == LESSTHAN)
- {
- /* context-sensitive, LESSTHAN means byte-sized here */
- byteflag = TRUE;
- getsym();
- }
- else if (sym == GREATERTHAN)
- {
- /* context-sensitive, GREATERTHAN means word-sized here */
- wordflag = TRUE;
- getsym();
- }
- expres();
- if (sym == COMMA)
- { /* offset from register */
- getsym();
- if ((reg = indreg(PCREG)) == NOREG)
- return;
- postb |= 0x8; /* default 8 bit offset */
- if (reg == PCREG)
- {
- reldata();
- if (!(lastexp.data & (RELBIT | UNDBIT)))
- {
- lastexp.offset = lastexp.offset - lc;
- if (page != 0x0)
- lastexp.offset -= 0x4; /* extra for instruction */
- else
- lastexp.offset -= 0x3; /* 3 byte instruction
- assuming 8 bit offset */
- }
- }
- if (byteflag)
- {
- if (!(lastexp.data & (RELBIT | UNDBIT)) &&
- !is8bitsignedoffset(lastexp.offset))
- error(ABOUNDS); /* forced short form is impossible */
- ++mcount;
- }
- else if (wordflag || lastexp.data & (FORBIT | RELBIT | UNDBIT) ||
- !is8bitsignedoffset(lastexp.offset))
- { /* 16 bit offset */
- if (postb & PCRELBIT && !(lastexp.data & RELBIT))
- --lastexp.offset; /* instruction 1 longer than already
- allowed */
- postb |= 0x1;
- mcount += 0x2;
- }
- else if (!(postb & PCRELBIT) &&
- (offset_t) (lastexp.offset + 0x10) < 0x20 &&
- !(postb & INDIRECTBIT && lastexp.offset != 0x0))
- { /* 5 bit offset */
- postb &= RRBITS | INDIRECTBIT;
- if (lastexp.offset == 0x0)
- postb |= 0x84; /* index with zero offset */
- else
- postb |= (lastexp.offset & 0x1F);
- }
- else /* 8 bit offset */
- ++mcount;
- fixupind();
- }
- else if (postb & INDIRECTBIT)
- { /* extended indirect */
- postb = 0x9F;
- mcount += 0x2;
- fixupind();
- }
- else if (postb & INDEXBIT)
- inderror(ILLMOD); /* e.g. LEAX $10 */
- else
- {
- if (byteflag || (!wordflag && !(lastexp.data & (FORBIT | RELBIT)) &&
- (lastexp.offset >> 0x8) == dirpag))
- { /* direct addressing */
- if (opcode >= 0x80)
- opcode |= 0x10;
- }
- else /* extended addressing */
- {
- if (opcode < 0x80)
- opcode |= 0x70;
- else
- opcode |= 0x30;
- ++mcount;
- if (pass2 && (opcode == JSR_OPCODE || opcode == JMP_OPCODE) &&
- !(lastexp.data & IMPBIT) &&
- lastexp.offset + (0x81 - 0x3) < 0x101)
- /* JSR or JMP could be done with BSR or BRA */
- warning(SHORTB);
- }
- }
- }
- PRIVATE void fixupind()
- {
- if ((opcode & 0x30) == 0x0) /* change all but LEA opcodes */
- {
- if (opcode < 0x80)
- opcode |= 0x60;
- else
- opcode |= 0x20;
- }
- }
- PRIVATE void getindexnopost()
- {
- getsym();
- if (indreg(MAXINDREG) != NOREG)
- fixupind();
- }
- PRIVATE void inderror(err_str)
- char * err_str;
- {
- error(err_str);
- if (postb & INDIRECTBIT)
- sym = RBRACKET; /* fake right bracket to kill further errors */
- fixupind();
- }
- /* check current symbol is an index register (possibly excepting PC) */
- /* if so, modify postbyte RR and INDEXBIT for it, get next sym, return TRUE */
- /* otherwise generate error, return FALSE */
- PRIVATE reg_pt indreg(maxindex)
- reg_pt maxindex;
- {
- reg_pt reg;
- if ((reg = regchk()) == NOREG)
- inderror(IREGEXP);
- else if (reg > maxindex)
- {
- inderror(ILLREG);
- reg = NOREG;
- }
- else
- {
- postb |= rrindex[reg];
- getsym();
- }
- return reg;
- }
- /* all-mode ops */
- PUBLIC void mall()
- {
- if (sym == IMMEDIATE)
- mimmed();
- else
- malter();
- }
- /* alterable mode ops */
- PUBLIC void malter()
- {
- postb = 0x0; /* not yet indexed or indirect */
- doaltind();
- }
- /* indexed mode ops */
- PUBLIC void mindex()
- {
- postb = INDEXBIT; /* indexed but not yet indirect */
- doaltind();
- }
- /* immediate ops */
- PUBLIC void mimmed()
- {
- opcode_t nybble;
- mcount += 0x2;
- if (sym != IMMEDIATE)
- error(ILLMOD);
- else
- {
- if (opcode >= 0x80 && ((nybble = opcode & 0xF) == 0x3 ||
- nybble == 0xC || nybble >= 0xE))
- ++mcount; /* magic for long immediate */
- symexpres();
- if (pass2 && mcount <= 0x2)
- {
- chkabs();
- checkdatabounds();
- }
- }
- }
- /* long branches */
- PUBLIC void mlong()
- {
- mcount += 0x3; /* may be 0x0 or 0x1 here */
- expres();
- segadj();
- if (pass2)
- {
- reldata();
- if (!(lastexp.data & (RELBIT | UNDBIT)))
- {
- lastexp.offset = lastexp.offset - lc - lcjump;
- if ( last_pass<2 && !(lastexp.data & IMPBIT) &&
- lastexp.offset + 0x81 < 0x101)
- warning(SHORTB); /* -0x81 to 0x7F, warning */
- }
- }
- }
- /* PSHS and PULS */
- PUBLIC void msstak()
- {
- sustack(SREG);
- }
- /* TFR and EXG */
- PUBLIC void mswap()
- {
- reg_pt reg;
- mcount = 0x2;
- if ((reg = regchk()) == NOREG)
- error(REGEXP);
- else
- {
- postb = tfrexg1[reg];
- getsym();
- if (sym != COMMA)
- error(COMEXP);
- else
- {
- getsym();
- if ((reg = regchk()) == NOREG)
- error(REGEXP);
- else if ((postb |= tfrexg2[reg])
- & 0x88 && (postb & 0x88) != 0x88)
- error(ILLREG); /* registers not of same size */
- }
- }
- }
- /* PSHU and PULU */
- PUBLIC void mustak()
- {
- sustack(UREG);
- }
- PRIVATE void predec1()
- {
- if (postb & INDIRECTBIT)
- inderror(ILLMOD); /* single-dec indirect illegal */
- else
- {
- postb |= 0x82;
- getindexnopost();
- }
- }
- /* common routine for PSHS/PULS/PSHU/PULU */
- PRIVATE void sustack(stackreg)
- reg_pt stackreg;
- {
- reg_pt reg;
- mcount = 0x2;
- while ((reg = regchk()) != NOREG)
- {
- if (reg == stackreg)
- {
- error(ILLREG); /* cannot stack self */
- break;
- }
- postb |= pushpull[reg];
- getsym();
- if (sym != COMMA)
- break;
- getsym();
- }
- }
- #endif /* MC6809 */
- /* routines common to all processors */
- PUBLIC void getcomma()
- {
- if (sym != COMMA)
- error(COMEXP);
- else
- getsym();
- }
- /* inherent ops */
- /* for I80386 */
- /* AAA, AAS, CLC, CLD, CLI, CLTS, CMC, CMPSB, DAA, DAS, HLT, INTO, INSB, */
- /* INVD, */
- /* LAHF, LEAVE, LOCK, LODSB, MOVSB, NOP, OUTSB, REP, REPE, REPNE, REPNZ, */
- /* REPZ, SAHF, SCASB, STC, STD, STI, STOSB, WAIT, WBINVD */
- PUBLIC void minher()
- {
- ++mcount;
- }
- /* short branches */
- PUBLIC void mshort()
- {
- nonimpexpres();
- mshort2();
- }
- PRIVATE void mshort2()
- {
- mcount += 0x2;
- if (pass2)
- {
- reldata();
- if (lastexp.data & RELBIT)
- showrelbad();
- else if (!(lastexp.data & UNDBIT))
- {
- lastexp.offset = lastexp.offset - lc - mcount;
- if (!is8bitsignedoffset(lastexp.offset))
- error(ABOUNDS);
- }
- }
- }
- /* check if current symbol is a register, return register number or NOREG */
- PRIVATE reg_pt regchk()
- {
- register struct sym_s *symptr;
- if (sym == IDENT)
- {
- if ((symptr = gsymptr)->type & MNREGBIT)
- {
- if (symptr->data & REGBIT)
- {
- int regno = symptr->value_reg_or_op.reg;
- #ifdef I80386
- if (regno == ST0REG && !fpreg_allowed)
- error(FP_REG_NOT_ALLOWED);
- /* Check cpu */
- needcpu((regno==FSREG||regno==GSREG)?3:0);
- needcpu((regno>=EAXREG && regno<=ESPREG)?3:0);
- needcpu((regno>=CR0REG && regno<=TR7REG)?3:0);
- #endif
- return regno;
- }
- }
- else
- if( last_pass == 1 )
- if (!(symptr->type & (LABIT | MACBIT | VARBIT)))
- symptr->data |= FORBIT; /* show seen in advance */
- }
- return NOREG;
- }
- /* convert lastexp.data for PC relative */
- PRIVATE void reldata()
- {
- if ((lastexp.data ^ lcdata) & (IMPBIT | RELBIT | SEGM))
- {
- if ((lastexp.data ^ lcdata) & RELBIT)
- showrelbad(); /* rel - abs is weird, abs - rel is bad */
- else
- {
- pcrflag = OBJ_R_MASK;
- lastexp.data = (lcdata & ~SEGM) | lastexp.data | RELBIT;
- /* segment is that of lastexp.data */
- }
- }
- else /* same file, segment and relocation */
- lastexp.data = (lastexp.data | lcdata) & ~(RELBIT | SEGM);
- }
- PRIVATE void segadj()
- {
- if ((lastexp.data & UNDBIT) && textseg >= 0 )
- {
- lastexp.sym->data &= ~SEGM;
- lastexp.sym->data |= (lcdata & SEGM);
- }
- }
|