1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449 |
- /****************************************************************************
- *
- * Realmode X86 Emulator Library
- *
- * Copyright (C) 1991-2004 SciTech Software, Inc.
- * Copyright (C) David Mosberger-Tang
- * Copyright (C) 1999 Egbert Eich
- *
- * ========================================================================
- *
- * Permission to use, copy, modify, distribute, and sell this software and
- * its documentation for any purpose is hereby granted without fee,
- * provided that the above copyright notice appear in all copies and that
- * both that copyright notice and this permission notice appear in
- * supporting documentation, and that the name of the authors not be used
- * in advertising or publicity pertaining to distribution of the software
- * without specific, written prior permission. The authors makes no
- * representations about the suitability of this software for any purpose.
- * It is provided "as is" without express or implied warranty.
- *
- * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
- * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
- * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- *
- * ========================================================================
- *
- * Language: ANSI C
- * Environment: Any
- * Developer: Kendall Bennett
- *
- * Description: This file contains the code to implement the primitive
- * machine operations used by the emulation code in ops.c
- *
- * Carry Chain Calculation
- *
- * This represents a somewhat expensive calculation which is
- * apparently required to emulate the setting of the OF343364 and AF flag.
- * The latter is not so important, but the former is. The overflow
- * flag is the XOR of the top two bits of the carry chain for an
- * addition (similar for subtraction). Since we do not want to
- * simulate the addition in a bitwise manner, we try to calculate the
- * carry chain given the two operands and the result.
- *
- * So, given the following table, which represents the addition of two
- * bits, we can derive a formula for the carry chain.
- *
- * a b cin r cout
- * 0 0 0 0 0
- * 0 0 1 1 0
- * 0 1 0 1 0
- * 0 1 1 0 1
- * 1 0 0 1 0
- * 1 0 1 0 1
- * 1 1 0 0 1
- * 1 1 1 1 1
- *
- * Construction of table for cout:
- *
- * ab
- * r \ 00 01 11 10
- * |------------------
- * 0 | 0 1 1 1
- * 1 | 0 0 1 0
- *
- * By inspection, one gets: cc = ab + r'(a + b)
- *
- * That represents alot of operations, but NO CHOICE....
- *
- * Borrow Chain Calculation.
- *
- * The following table represents the subtraction of two bits, from
- * which we can derive a formula for the borrow chain.
- *
- * a b bin r bout
- * 0 0 0 0 0
- * 0 0 1 1 1
- * 0 1 0 1 1
- * 0 1 1 0 1
- * 1 0 0 1 0
- * 1 0 1 0 0
- * 1 1 0 0 0
- * 1 1 1 1 1
- *
- * Construction of table for cout:
- *
- * ab
- * r \ 00 01 11 10
- * |------------------
- * 0 | 0 1 0 0
- * 1 | 1 1 1 0
- *
- * By inspection, one gets: bc = a'b + r(a' + b)
- *
- ****************************************************************************/
- #define PRIM_OPS_NO_REDEFINE_ASM
- #include "x86emu/x86emui.h"
- #if defined(CONFIG_BIOSEMU)
- /*------------------------- Global Variables ------------------------------*/
- static u32 x86emu_parity_tab[8] =
- {
- 0x96696996,
- 0x69969669,
- 0x69969669,
- 0x96696996,
- 0x69969669,
- 0x96696996,
- 0x96696996,
- 0x69969669,
- };
- #define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
- #define XOR2(x) (((x) ^ ((x)>>1)) & 0x1)
- /*----------------------------- Implementation ----------------------------*/
- int abs(int v)
- {
- return (v>0)?v:-v;
- }
- /*----------------------------- Implementation ----------------------------*/
- /*--------- Side effects helper functions -------*/
- /****************************************************************************
- REMARKS:
- implements side efects for byte operations that don't overflow
- ****************************************************************************/
- static void set_parity_flag(u32 res)
- {
- CONDITIONAL_SET_FLAG(PARITY(res & 0xFF), F_PF);
- }
- static void set_szp_flags_8(u8 res)
- {
- CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
- CONDITIONAL_SET_FLAG(res == 0, F_ZF);
- set_parity_flag(res);
- }
- static void set_szp_flags_16(u16 res)
- {
- CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
- CONDITIONAL_SET_FLAG(res == 0, F_ZF);
- set_parity_flag(res);
- }
- static void set_szp_flags_32(u32 res)
- {
- CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
- CONDITIONAL_SET_FLAG(res == 0, F_ZF);
- set_parity_flag(res);
- }
- static void no_carry_byte_side_eff(u8 res)
- {
- CLEAR_FLAG(F_OF);
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_AF);
- set_szp_flags_8(res);
- }
- static void no_carry_word_side_eff(u16 res)
- {
- CLEAR_FLAG(F_OF);
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_AF);
- set_szp_flags_16(res);
- }
- static void no_carry_long_side_eff(u32 res)
- {
- CLEAR_FLAG(F_OF);
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_AF);
- set_szp_flags_32(res);
- }
- static void calc_carry_chain(int bits, u32 d, u32 s, u32 res, int set_carry)
- {
- u32 cc;
- cc = (s & d) | ((~res) & (s | d));
- CONDITIONAL_SET_FLAG(XOR2(cc >> (bits - 2)), F_OF);
- CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
- if (set_carry) {
- CONDITIONAL_SET_FLAG(res & (1 << bits), F_CF);
- }
- }
- static void calc_borrow_chain(int bits, u32 d, u32 s, u32 res, int set_carry)
- {
- u32 bc;
- bc = (res & (~d | s)) | (~d & s);
- CONDITIONAL_SET_FLAG(XOR2(bc >> (bits - 2)), F_OF);
- CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
- if (set_carry) {
- CONDITIONAL_SET_FLAG(bc & (1 << (bits - 1)), F_CF);
- }
- }
- /****************************************************************************
- REMARKS:
- Implements the AAA instruction and side effects.
- ****************************************************************************/
- u16 aaa_word(u16 d)
- {
- u16 res;
- if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
- d += 0x6;
- d += 0x100;
- SET_FLAG(F_AF);
- SET_FLAG(F_CF);
- } else {
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_AF);
- }
- res = (u16)(d & 0xFF0F);
- set_szp_flags_16(res);
- return res;
- }
- /****************************************************************************
- REMARKS:
- Implements the AAA instruction and side effects.
- ****************************************************************************/
- u16 aas_word(u16 d)
- {
- u16 res;
- if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
- d -= 0x6;
- d -= 0x100;
- SET_FLAG(F_AF);
- SET_FLAG(F_CF);
- } else {
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_AF);
- }
- res = (u16)(d & 0xFF0F);
- set_szp_flags_16(res);
- return res;
- }
- /****************************************************************************
- REMARKS:
- Implements the AAD instruction and side effects.
- ****************************************************************************/
- u16 aad_word(u16 d)
- {
- u16 l;
- u8 hb, lb;
- hb = (u8)((d >> 8) & 0xff);
- lb = (u8)((d & 0xff));
- l = (u16)((lb + 10 * hb) & 0xFF);
- no_carry_byte_side_eff(l & 0xFF);
- return l;
- }
- /****************************************************************************
- REMARKS:
- Implements the AAM instruction and side effects.
- ****************************************************************************/
- u16 aam_word(u8 d)
- {
- u16 h, l;
- h = (u16)(d / 10);
- l = (u16)(d % 10);
- l |= (u16)(h << 8);
- no_carry_byte_side_eff(l & 0xFF);
- return l;
- }
- /****************************************************************************
- REMARKS:
- Implements the ADC instruction and side effects.
- ****************************************************************************/
- u8 adc_byte(u8 d, u8 s)
- {
- u32 res; /* all operands in native machine order */
- res = d + s;
- if (ACCESS_FLAG(F_CF)) res++;
- set_szp_flags_8(res);
- calc_carry_chain(8,s,d,res,1);
- return (u8)res;
- }
- /****************************************************************************
- REMARKS:
- Implements the ADC instruction and side effects.
- ****************************************************************************/
- u16 adc_word(u16 d, u16 s)
- {
- u32 res; /* all operands in native machine order */
- res = d + s;
- if (ACCESS_FLAG(F_CF))
- res++;
- set_szp_flags_16((u16)res);
- calc_carry_chain(16,s,d,res,1);
- return (u16)res;
- }
- /****************************************************************************
- REMARKS:
- Implements the ADC instruction and side effects.
- ****************************************************************************/
- u32 adc_long(u32 d, u32 s)
- {
- u32 lo; /* all operands in native machine order */
- u32 hi;
- u32 res;
- lo = (d & 0xFFFF) + (s & 0xFFFF);
- res = d + s;
- if (ACCESS_FLAG(F_CF)) {
- lo++;
- res++;
- }
- hi = (lo >> 16) + (d >> 16) + (s >> 16);
- set_szp_flags_32(res);
- calc_carry_chain(32,s,d,res,0);
- CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
- return res;
- }
- /****************************************************************************
- REMARKS:
- Implements the ADD instruction and side effects.
- ****************************************************************************/
- u8 add_byte(u8 d, u8 s)
- {
- u32 res; /* all operands in native machine order */
- res = d + s;
- set_szp_flags_8((u8)res);
- calc_carry_chain(8,s,d,res,1);
- return (u8)res;
- }
- /****************************************************************************
- REMARKS:
- Implements the ADD instruction and side effects.
- ****************************************************************************/
- u16 add_word(u16 d, u16 s)
- {
- u32 res; /* all operands in native machine order */
- res = d + s;
- set_szp_flags_16((u16)res);
- calc_carry_chain(16,s,d,res,1);
- return (u16)res;
- }
- /****************************************************************************
- REMARKS:
- Implements the ADD instruction and side effects.
- ****************************************************************************/
- u32 add_long(u32 d, u32 s)
- {
- u32 res;
- res = d + s;
- set_szp_flags_32(res);
- calc_carry_chain(32,s,d,res,0);
- CONDITIONAL_SET_FLAG(res < d || res < s, F_CF);
- return res;
- }
- /****************************************************************************
- REMARKS:
- Implements the AND instruction and side effects.
- ****************************************************************************/
- u8 and_byte(u8 d, u8 s)
- {
- u8 res; /* all operands in native machine order */
- res = d & s;
- no_carry_byte_side_eff(res);
- return res;
- }
- /****************************************************************************
- REMARKS:
- Implements the AND instruction and side effects.
- ****************************************************************************/
- u16 and_word(u16 d, u16 s)
- {
- u16 res; /* all operands in native machine order */
- res = d & s;
- no_carry_word_side_eff(res);
- return res;
- }
- /****************************************************************************
- REMARKS:
- Implements the AND instruction and side effects.
- ****************************************************************************/
- u32 and_long(u32 d, u32 s)
- {
- u32 res; /* all operands in native machine order */
- res = d & s;
- no_carry_long_side_eff(res);
- return res;
- }
- /****************************************************************************
- REMARKS:
- Implements the CMP instruction and side effects.
- ****************************************************************************/
- u8 cmp_byte(u8 d, u8 s)
- {
- u32 res; /* all operands in native machine order */
- res = d - s;
- set_szp_flags_8((u8)res);
- calc_borrow_chain(8, d, s, res, 1);
- return d;
- }
- /****************************************************************************
- REMARKS:
- Implements the CMP instruction and side effects.
- ****************************************************************************/
- u16 cmp_word(u16 d, u16 s)
- {
- u32 res; /* all operands in native machine order */
- res = d - s;
- set_szp_flags_16((u16)res);
- calc_borrow_chain(16, d, s, res, 1);
- return d;
- }
- /****************************************************************************
- REMARKS:
- Implements the CMP instruction and side effects.
- ****************************************************************************/
- u32 cmp_long(u32 d, u32 s)
- {
- u32 res; /* all operands in native machine order */
- res = d - s;
- set_szp_flags_32(res);
- calc_borrow_chain(32, d, s, res, 1);
- return d;
- }
- /****************************************************************************
- REMARKS:
- Implements the DAA instruction and side effects.
- ****************************************************************************/
- u8 daa_byte(u8 d)
- {
- u32 res = d;
- if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
- res += 6;
- SET_FLAG(F_AF);
- }
- if (res > 0x9F || ACCESS_FLAG(F_CF)) {
- res += 0x60;
- SET_FLAG(F_CF);
- }
- set_szp_flags_8((u8)res);
- return (u8)res;
- }
- /****************************************************************************
- REMARKS:
- Implements the DAS instruction and side effects.
- ****************************************************************************/
- u8 das_byte(u8 d)
- {
- if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
- d -= 6;
- SET_FLAG(F_AF);
- }
- if (d > 0x9F || ACCESS_FLAG(F_CF)) {
- d -= 0x60;
- SET_FLAG(F_CF);
- }
- set_szp_flags_8(d);
- return d;
- }
- /****************************************************************************
- REMARKS:
- Implements the DEC instruction and side effects.
- ****************************************************************************/
- u8 dec_byte(u8 d)
- {
- u32 res; /* all operands in native machine order */
- res = d - 1;
- set_szp_flags_8((u8)res);
- calc_borrow_chain(8, d, 1, res, 0);
- return (u8)res;
- }
- /****************************************************************************
- REMARKS:
- Implements the DEC instruction and side effects.
- ****************************************************************************/
- u16 dec_word(u16 d)
- {
- u32 res; /* all operands in native machine order */
- res = d - 1;
- set_szp_flags_16((u16)res);
- calc_borrow_chain(16, d, 1, res, 0);
- return (u16)res;
- }
- /****************************************************************************
- REMARKS:
- Implements the DEC instruction and side effects.
- ****************************************************************************/
- u32 dec_long(u32 d)
- {
- u32 res; /* all operands in native machine order */
- res = d - 1;
- set_szp_flags_32(res);
- calc_borrow_chain(32, d, 1, res, 0);
- return res;
- }
- /****************************************************************************
- REMARKS:
- Implements the INC instruction and side effects.
- ****************************************************************************/
- u8 inc_byte(u8 d)
- {
- u32 res; /* all operands in native machine order */
- res = d + 1;
- set_szp_flags_8((u8)res);
- calc_carry_chain(8, d, 1, res, 0);
- return (u8)res;
- }
- /****************************************************************************
- REMARKS:
- Implements the INC instruction and side effects.
- ****************************************************************************/
- u16 inc_word(u16 d)
- {
- u32 res; /* all operands in native machine order */
- res = d + 1;
- set_szp_flags_16((u16)res);
- calc_carry_chain(16, d, 1, res, 0);
- return (u16)res;
- }
- /****************************************************************************
- REMARKS:
- Implements the INC instruction and side effects.
- ****************************************************************************/
- u32 inc_long(u32 d)
- {
- u32 res; /* all operands in native machine order */
- res = d + 1;
- set_szp_flags_32(res);
- calc_carry_chain(32, d, 1, res, 0);
- return res;
- }
- /****************************************************************************
- REMARKS:
- Implements the OR instruction and side effects.
- ****************************************************************************/
- u8 or_byte(u8 d, u8 s)
- {
- u8 res; /* all operands in native machine order */
- res = d | s;
- no_carry_byte_side_eff(res);
- return res;
- }
- /****************************************************************************
- REMARKS:
- Implements the OR instruction and side effects.
- ****************************************************************************/
- u16 or_word(u16 d, u16 s)
- {
- u16 res; /* all operands in native machine order */
- res = d | s;
- no_carry_word_side_eff(res);
- return res;
- }
- /****************************************************************************
- REMARKS:
- Implements the OR instruction and side effects.
- ****************************************************************************/
- u32 or_long(u32 d, u32 s)
- {
- u32 res; /* all operands in native machine order */
- res = d | s;
- no_carry_long_side_eff(res);
- return res;
- }
- /****************************************************************************
- REMARKS:
- Implements the OR instruction and side effects.
- ****************************************************************************/
- u8 neg_byte(u8 s)
- {
- u8 res;
- CONDITIONAL_SET_FLAG(s != 0, F_CF);
- res = (u8)-s;
- set_szp_flags_8(res);
- calc_borrow_chain(8, 0, s, res, 0);
- return res;
- }
- /****************************************************************************
- REMARKS:
- Implements the OR instruction and side effects.
- ****************************************************************************/
- u16 neg_word(u16 s)
- {
- u16 res;
- CONDITIONAL_SET_FLAG(s != 0, F_CF);
- res = (u16)-s;
- set_szp_flags_16((u16)res);
- calc_borrow_chain(16, 0, s, res, 0);
- return res;
- }
- /****************************************************************************
- REMARKS:
- Implements the OR instruction and side effects.
- ****************************************************************************/
- u32 neg_long(u32 s)
- {
- u32 res;
- CONDITIONAL_SET_FLAG(s != 0, F_CF);
- res = (u32)-s;
- set_szp_flags_32(res);
- calc_borrow_chain(32, 0, s, res, 0);
- return res;
- }
- /****************************************************************************
- REMARKS:
- Implements the NOT instruction and side effects.
- ****************************************************************************/
- u8 not_byte(u8 s)
- {
- return ~s;
- }
- /****************************************************************************
- REMARKS:
- Implements the NOT instruction and side effects.
- ****************************************************************************/
- u16 not_word(u16 s)
- {
- return ~s;
- }
- /****************************************************************************
- REMARKS:
- Implements the NOT instruction and side effects.
- ****************************************************************************/
- u32 not_long(u32 s)
- {
- return ~s;
- }
- /****************************************************************************
- REMARKS:
- Implements the RCL instruction and side effects.
- ****************************************************************************/
- u8 rcl_byte(u8 d, u8 s)
- {
- unsigned int res, cnt, mask, cf;
- /* s is the rotate distance. It varies from 0 - 8. */
- /* have
- CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
- want to rotate through the carry by "s" bits. We could
- loop, but that's inefficient. So the width is 9,
- and we split into three parts:
- The new carry flag (was B_n)
- the stuff in B_n-1 .. B_0
- the stuff in B_7 .. B_n+1
- The new rotate is done mod 9, and given this,
- for a rotation of n bits (mod 9) the new carry flag is
- then located n bits from the MSB. The low part is
- then shifted up cnt bits, and the high part is or'd
- in. Using CAPS for new values, and lowercase for the
- original values, this can be expressed as:
- IF n > 0
- 1) CF <- b_(8-n)
- 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0
- 3) B_(n-1) <- cf
- 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1))
- */
- res = d;
- if ((cnt = s % 9) != 0) {
- /* extract the new CARRY FLAG. */
- /* CF <- b_(8-n) */
- cf = (d >> (8 - cnt)) & 0x1;
- /* get the low stuff which rotated
- into the range B_7 .. B_cnt */
- /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 */
- /* note that the right hand side done by the mask */
- res = (d << cnt) & 0xff;
- /* now the high stuff which rotated around
- into the positions B_cnt-2 .. B_0 */
- /* B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */
- /* shift it downward, 7-(n-2) = 9-n positions.
- and mask off the result before or'ing in.
- */
- mask = (1 << (cnt - 1)) - 1;
- res |= (d >> (9 - cnt)) & mask;
- /* if the carry flag was set, or it in. */
- if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
- /* B_(n-1) <- cf */
- res |= 1 << (cnt - 1);
- }
- /* set the new carry flag, based on the variable "cf" */
- CONDITIONAL_SET_FLAG(cf, F_CF);
- /* OVERFLOW is set *IFF* cnt==1, then it is the
- xor of CF and the most significant bit. Blecck. */
- /* parenthesized this expression since it appears to
- be causing OF to be misset */
- CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
- F_OF);
- }
- return (u8)res;
- }
- /****************************************************************************
- REMARKS:
- Implements the RCL instruction and side effects.
- ****************************************************************************/
- u16 rcl_word(u16 d, u8 s)
- {
- unsigned int res, cnt, mask, cf;
- res = d;
- if ((cnt = s % 17) != 0) {
- cf = (d >> (16 - cnt)) & 0x1;
- res = (d << cnt) & 0xffff;
- mask = (1 << (cnt - 1)) - 1;
- res |= (d >> (17 - cnt)) & mask;
- if (ACCESS_FLAG(F_CF)) {
- res |= 1 << (cnt - 1);
- }
- CONDITIONAL_SET_FLAG(cf, F_CF);
- CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
- F_OF);
- }
- return (u16)res;
- }
- /****************************************************************************
- REMARKS:
- Implements the RCL instruction and side effects.
- ****************************************************************************/
- u32 rcl_long(u32 d, u8 s)
- {
- u32 res, cnt, mask, cf;
- res = d;
- if ((cnt = s % 33) != 0) {
- cf = (d >> (32 - cnt)) & 0x1;
- res = (d << cnt) & 0xffffffff;
- mask = (1 << (cnt - 1)) - 1;
- res |= (d >> (33 - cnt)) & mask;
- if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
- res |= 1 << (cnt - 1);
- }
- CONDITIONAL_SET_FLAG(cf, F_CF);
- CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
- F_OF);
- }
- return res;
- }
- /****************************************************************************
- REMARKS:
- Implements the RCR instruction and side effects.
- ****************************************************************************/
- u8 rcr_byte(u8 d, u8 s)
- {
- u32 res, cnt;
- u32 mask, cf, ocf = 0;
- /* rotate right through carry */
- /*
- s is the rotate distance. It varies from 0 - 8.
- d is the byte object rotated.
- have
- CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
- The new rotate is done mod 9, and given this,
- for a rotation of n bits (mod 9) the new carry flag is
- then located n bits from the LSB. The low part is
- then shifted up cnt bits, and the high part is or'd
- in. Using CAPS for new values, and lowercase for the
- original values, this can be expressed as:
- IF n > 0
- 1) CF <- b_(n-1)
- 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
- 3) B_(8-n) <- cf
- 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0)
- */
- res = d;
- if ((cnt = s % 9) != 0) {
- /* extract the new CARRY FLAG. */
- /* CF <- b_(n-1) */
- if (cnt == 1) {
- cf = d & 0x1;
- /* note hackery here. Access_flag(..) evaluates to either
- 0 if flag not set
- non-zero if flag is set.
- doing access_flag(..) != 0 casts that into either
- 0..1 in any representation of the flags register
- (i.e. packed bit array or unpacked.)
- */
- ocf = ACCESS_FLAG(F_CF) != 0;
- } else
- cf = (d >> (cnt - 1)) & 0x1;
- /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */
- /* note that the right hand side done by the mask
- This is effectively done by shifting the
- object to the right. The result must be masked,
- in case the object came in and was treated
- as a negative number. Needed??? */
- mask = (1 << (8 - cnt)) - 1;
- res = (d >> cnt) & mask;
- /* now the high stuff which rotated around
- into the positions B_cnt-2 .. B_0 */
- /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */
- /* shift it downward, 7-(n-2) = 9-n positions.
- and mask off the result before or'ing in.
- */
- res |= (d << (9 - cnt));
- /* if the carry flag was set, or it in. */
- if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
- /* B_(8-n) <- cf */
- res |= 1 << (8 - cnt);
- }
- /* set the new carry flag, based on the variable "cf" */
- CONDITIONAL_SET_FLAG(cf, F_CF);
- /* OVERFLOW is set *IFF* cnt==1, then it is the
- xor of CF and the most significant bit. Blecck. */
- /* parenthesized... */
- if (cnt == 1) {
- CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
- F_OF);
- }
- }
- return (u8)res;
- }
- /****************************************************************************
- REMARKS:
- Implements the RCR instruction and side effects.
- ****************************************************************************/
- u16 rcr_word(u16 d, u8 s)
- {
- u32 res, cnt;
- u32 mask, cf, ocf = 0;
- /* rotate right through carry */
- res = d;
- if ((cnt = s % 17) != 0) {
- if (cnt == 1) {
- cf = d & 0x1;
- ocf = ACCESS_FLAG(F_CF) != 0;
- } else
- cf = (d >> (cnt - 1)) & 0x1;
- mask = (1 << (16 - cnt)) - 1;
- res = (d >> cnt) & mask;
- res |= (d << (17 - cnt));
- if (ACCESS_FLAG(F_CF)) {
- res |= 1 << (16 - cnt);
- }
- CONDITIONAL_SET_FLAG(cf, F_CF);
- if (cnt == 1) {
- CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
- F_OF);
- }
- }
- return (u16)res;
- }
- /****************************************************************************
- REMARKS:
- Implements the RCR instruction and side effects.
- ****************************************************************************/
- u32 rcr_long(u32 d, u8 s)
- {
- u32 res, cnt;
- u32 mask, cf, ocf = 0;
- /* rotate right through carry */
- res = d;
- if ((cnt = s % 33) != 0) {
- if (cnt == 1) {
- cf = d & 0x1;
- ocf = ACCESS_FLAG(F_CF) != 0;
- } else
- cf = (d >> (cnt - 1)) & 0x1;
- mask = (1 << (32 - cnt)) - 1;
- res = (d >> cnt) & mask;
- if (cnt != 1)
- res |= (d << (33 - cnt));
- if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
- res |= 1 << (32 - cnt);
- }
- CONDITIONAL_SET_FLAG(cf, F_CF);
- if (cnt == 1) {
- CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
- F_OF);
- }
- }
- return res;
- }
- /****************************************************************************
- REMARKS:
- Implements the ROL instruction and side effects.
- ****************************************************************************/
- u8 rol_byte(u8 d, u8 s)
- {
- unsigned int res, cnt, mask;
- /* rotate left */
- /*
- s is the rotate distance. It varies from 0 - 8.
- d is the byte object rotated.
- have
- CF B_7 ... B_0
- The new rotate is done mod 8.
- Much simpler than the "rcl" or "rcr" operations.
- IF n > 0
- 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0)
- 2) B_(n-1) .. B_(0) <- b_(7) .. b_(8-n)
- */
- res = d;
- if ((cnt = s % 8) != 0) {
- /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */
- res = (d << cnt);
- /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */
- mask = (1 << cnt) - 1;
- res |= (d >> (8 - cnt)) & mask;
- /* set the new carry flag, Note that it is the low order
- bit of the result!!! */
- CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
- /* OVERFLOW is set *IFF* s==1, then it is the
- xor of CF and the most significant bit. Blecck. */
- CONDITIONAL_SET_FLAG(s == 1 &&
- XOR2((res & 0x1) + ((res >> 6) & 0x2)),
- F_OF);
- } if (s != 0) {
- /* set the new carry flag, Note that it is the low order
- bit of the result!!! */
- CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
- }
- return (u8)res;
- }
- /****************************************************************************
- REMARKS:
- Implements the ROL instruction and side effects.
- ****************************************************************************/
- u16 rol_word(u16 d, u8 s)
- {
- unsigned int res, cnt, mask;
- res = d;
- if ((cnt = s % 16) != 0) {
- res = (d << cnt);
- mask = (1 << cnt) - 1;
- res |= (d >> (16 - cnt)) & mask;
- CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
- CONDITIONAL_SET_FLAG(s == 1 &&
- XOR2((res & 0x1) + ((res >> 14) & 0x2)),
- F_OF);
- } if (s != 0) {
- /* set the new carry flag, Note that it is the low order
- bit of the result!!! */
- CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
- }
- return (u16)res;
- }
- /****************************************************************************
- REMARKS:
- Implements the ROL instruction and side effects.
- ****************************************************************************/
- u32 rol_long(u32 d, u8 s)
- {
- u32 res, cnt, mask;
- res = d;
- if ((cnt = s % 32) != 0) {
- res = (d << cnt);
- mask = (1 << cnt) - 1;
- res |= (d >> (32 - cnt)) & mask;
- CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
- CONDITIONAL_SET_FLAG(s == 1 &&
- XOR2((res & 0x1) + ((res >> 30) & 0x2)),
- F_OF);
- } if (s != 0) {
- /* set the new carry flag, Note that it is the low order
- bit of the result!!! */
- CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
- }
- return res;
- }
- /****************************************************************************
- REMARKS:
- Implements the ROR instruction and side effects.
- ****************************************************************************/
- u8 ror_byte(u8 d, u8 s)
- {
- unsigned int res, cnt, mask;
- /* rotate right */
- /*
- s is the rotate distance. It varies from 0 - 8.
- d is the byte object rotated.
- have
- B_7 ... B_0
- The rotate is done mod 8.
- IF n > 0
- 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
- 2) B_(7) .. B_(8-n) <- b_(n-1) .. b_(0)
- */
- res = d;
- if ((cnt = s % 8) != 0) { /* not a typo, do nada if cnt==0 */
- /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) */
- res = (d << (8 - cnt));
- /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */
- mask = (1 << (8 - cnt)) - 1;
- res |= (d >> (cnt)) & mask;
- /* set the new carry flag, Note that it is the low order
- bit of the result!!! */
- CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
- /* OVERFLOW is set *IFF* s==1, then it is the
- xor of the two most significant bits. Blecck. */
- CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
- } else if (s != 0) {
- /* set the new carry flag, Note that it is the low order
- bit of the result!!! */
- CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
- }
- return (u8)res;
- }
- /****************************************************************************
- REMARKS:
- Implements the ROR instruction and side effects.
- ****************************************************************************/
- u16 ror_word(u16 d, u8 s)
- {
- unsigned int res, cnt, mask;
- res = d;
- if ((cnt = s % 16) != 0) {
- res = (d << (16 - cnt));
- mask = (1 << (16 - cnt)) - 1;
- res |= (d >> (cnt)) & mask;
- CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
- CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
- } else if (s != 0) {
- /* set the new carry flag, Note that it is the low order
- bit of the result!!! */
- CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
- }
- return (u16)res;
- }
- /****************************************************************************
- REMARKS:
- Implements the ROR instruction and side effects.
- ****************************************************************************/
- u32 ror_long(u32 d, u8 s)
- {
- u32 res, cnt, mask;
- res = d;
- if ((cnt = s % 32) != 0) {
- res = (d << (32 - cnt));
- mask = (1 << (32 - cnt)) - 1;
- res |= (d >> (cnt)) & mask;
- CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
- CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
- } else if (s != 0) {
- /* set the new carry flag, Note that it is the low order
- bit of the result!!! */
- CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
- }
- return res;
- }
- /****************************************************************************
- REMARKS:
- Implements the SHL instruction and side effects.
- ****************************************************************************/
- u8 shl_byte(u8 d, u8 s)
- {
- unsigned int cnt, res, cf;
- if (s < 8) {
- cnt = s % 8;
- /* last bit shifted out goes into carry flag */
- if (cnt > 0) {
- res = d << cnt;
- cf = d & (1 << (8 - cnt));
- CONDITIONAL_SET_FLAG(cf, F_CF);
- set_szp_flags_8((u8)res);
- } else {
- res = (u8) d;
- }
- if (cnt == 1) {
- /* Needs simplification. */
- CONDITIONAL_SET_FLAG(
- (((res & 0x80) == 0x80) ^
- (ACCESS_FLAG(F_CF) != 0)),
- /* was (M.x86.R_FLG&F_CF)==F_CF)), */
- F_OF);
- } else {
- CLEAR_FLAG(F_OF);
- }
- } else {
- res = 0;
- CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80, F_CF);
- CLEAR_FLAG(F_OF);
- CLEAR_FLAG(F_SF);
- SET_FLAG(F_PF);
- SET_FLAG(F_ZF);
- }
- return (u8)res;
- }
- /****************************************************************************
- REMARKS:
- Implements the SHL instruction and side effects.
- ****************************************************************************/
- u16 shl_word(u16 d, u8 s)
- {
- unsigned int cnt, res, cf;
- if (s < 16) {
- cnt = s % 16;
- if (cnt > 0) {
- res = d << cnt;
- cf = d & (1 << (16 - cnt));
- CONDITIONAL_SET_FLAG(cf, F_CF);
- set_szp_flags_16((u16)res);
- } else {
- res = (u16) d;
- }
- if (cnt == 1) {
- CONDITIONAL_SET_FLAG(
- (((res & 0x8000) == 0x8000) ^
- (ACCESS_FLAG(F_CF) != 0)),
- F_OF);
- } else {
- CLEAR_FLAG(F_OF);
- }
- } else {
- res = 0;
- CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
- CLEAR_FLAG(F_OF);
- CLEAR_FLAG(F_SF);
- SET_FLAG(F_PF);
- SET_FLAG(F_ZF);
- }
- return (u16)res;
- }
- /****************************************************************************
- REMARKS:
- Implements the SHL instruction and side effects.
- ****************************************************************************/
- u32 shl_long(u32 d, u8 s)
- {
- unsigned int cnt, res, cf;
- if (s < 32) {
- cnt = s % 32;
- if (cnt > 0) {
- res = d << cnt;
- cf = d & (1 << (32 - cnt));
- CONDITIONAL_SET_FLAG(cf, F_CF);
- set_szp_flags_32((u32)res);
- } else {
- res = d;
- }
- if (cnt == 1) {
- CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
- (ACCESS_FLAG(F_CF) != 0)), F_OF);
- } else {
- CLEAR_FLAG(F_OF);
- }
- } else {
- res = 0;
- CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
- CLEAR_FLAG(F_OF);
- CLEAR_FLAG(F_SF);
- SET_FLAG(F_PF);
- SET_FLAG(F_ZF);
- }
- return res;
- }
- /****************************************************************************
- REMARKS:
- Implements the SHR instruction and side effects.
- ****************************************************************************/
- u8 shr_byte(u8 d, u8 s)
- {
- unsigned int cnt, res, cf;
- if (s < 8) {
- cnt = s % 8;
- if (cnt > 0) {
- cf = d & (1 << (cnt - 1));
- res = d >> cnt;
- CONDITIONAL_SET_FLAG(cf, F_CF);
- set_szp_flags_8((u8)res);
- } else {
- res = (u8) d;
- }
- if (cnt == 1) {
- CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
- } else {
- CLEAR_FLAG(F_OF);
- }
- } else {
- res = 0;
- CONDITIONAL_SET_FLAG((d >> (s-1)) & 0x1, F_CF);
- CLEAR_FLAG(F_OF);
- CLEAR_FLAG(F_SF);
- SET_FLAG(F_PF);
- SET_FLAG(F_ZF);
- }
- return (u8)res;
- }
- /****************************************************************************
- REMARKS:
- Implements the SHR instruction and side effects.
- ****************************************************************************/
- u16 shr_word(u16 d, u8 s)
- {
- unsigned int cnt, res, cf;
- if (s < 16) {
- cnt = s % 16;
- if (cnt > 0) {
- cf = d & (1 << (cnt - 1));
- res = d >> cnt;
- CONDITIONAL_SET_FLAG(cf, F_CF);
- set_szp_flags_16((u16)res);
- } else {
- res = d;
- }
- if (cnt == 1) {
- CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
- } else {
- CLEAR_FLAG(F_OF);
- }
- } else {
- res = 0;
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_OF);
- SET_FLAG(F_ZF);
- CLEAR_FLAG(F_SF);
- CLEAR_FLAG(F_PF);
- }
- return (u16)res;
- }
- /****************************************************************************
- REMARKS:
- Implements the SHR instruction and side effects.
- ****************************************************************************/
- u32 shr_long(u32 d, u8 s)
- {
- unsigned int cnt, res, cf;
- if (s < 32) {
- cnt = s % 32;
- if (cnt > 0) {
- cf = d & (1 << (cnt - 1));
- res = d >> cnt;
- CONDITIONAL_SET_FLAG(cf, F_CF);
- set_szp_flags_32((u32)res);
- } else {
- res = d;
- }
- if (cnt == 1) {
- CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
- } else {
- CLEAR_FLAG(F_OF);
- }
- } else {
- res = 0;
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_OF);
- SET_FLAG(F_ZF);
- CLEAR_FLAG(F_SF);
- CLEAR_FLAG(F_PF);
- }
- return res;
- }
- /****************************************************************************
- REMARKS:
- Implements the SAR instruction and side effects.
- ****************************************************************************/
- u8 sar_byte(u8 d, u8 s)
- {
- unsigned int cnt, res, cf, mask, sf;
- res = d;
- sf = d & 0x80;
- cnt = s % 8;
- if (cnt > 0 && cnt < 8) {
- mask = (1 << (8 - cnt)) - 1;
- cf = d & (1 << (cnt - 1));
- res = (d >> cnt) & mask;
- CONDITIONAL_SET_FLAG(cf, F_CF);
- if (sf) {
- res |= ~mask;
- }
- set_szp_flags_8((u8)res);
- } else if (cnt >= 8) {
- if (sf) {
- res = 0xff;
- SET_FLAG(F_CF);
- CLEAR_FLAG(F_ZF);
- SET_FLAG(F_SF);
- SET_FLAG(F_PF);
- } else {
- res = 0;
- CLEAR_FLAG(F_CF);
- SET_FLAG(F_ZF);
- CLEAR_FLAG(F_SF);
- CLEAR_FLAG(F_PF);
- }
- }
- return (u8)res;
- }
- /****************************************************************************
- REMARKS:
- Implements the SAR instruction and side effects.
- ****************************************************************************/
- u16 sar_word(u16 d, u8 s)
- {
- unsigned int cnt, res, cf, mask, sf;
- sf = d & 0x8000;
- cnt = s % 16;
- res = d;
- if (cnt > 0 && cnt < 16) {
- mask = (1 << (16 - cnt)) - 1;
- cf = d & (1 << (cnt - 1));
- res = (d >> cnt) & mask;
- CONDITIONAL_SET_FLAG(cf, F_CF);
- if (sf) {
- res |= ~mask;
- }
- set_szp_flags_16((u16)res);
- } else if (cnt >= 16) {
- if (sf) {
- res = 0xffff;
- SET_FLAG(F_CF);
- CLEAR_FLAG(F_ZF);
- SET_FLAG(F_SF);
- SET_FLAG(F_PF);
- } else {
- res = 0;
- CLEAR_FLAG(F_CF);
- SET_FLAG(F_ZF);
- CLEAR_FLAG(F_SF);
- CLEAR_FLAG(F_PF);
- }
- }
- return (u16)res;
- }
- /****************************************************************************
- REMARKS:
- Implements the SAR instruction and side effects.
- ****************************************************************************/
- u32 sar_long(u32 d, u8 s)
- {
- u32 cnt, res, cf, mask, sf;
- sf = d & 0x80000000;
- cnt = s % 32;
- res = d;
- if (cnt > 0 && cnt < 32) {
- mask = (1 << (32 - cnt)) - 1;
- cf = d & (1 << (cnt - 1));
- res = (d >> cnt) & mask;
- CONDITIONAL_SET_FLAG(cf, F_CF);
- if (sf) {
- res |= ~mask;
- }
- set_szp_flags_32(res);
- } else if (cnt >= 32) {
- if (sf) {
- res = 0xffffffff;
- SET_FLAG(F_CF);
- CLEAR_FLAG(F_ZF);
- SET_FLAG(F_SF);
- SET_FLAG(F_PF);
- } else {
- res = 0;
- CLEAR_FLAG(F_CF);
- SET_FLAG(F_ZF);
- CLEAR_FLAG(F_SF);
- CLEAR_FLAG(F_PF);
- }
- }
- return res;
- }
- /****************************************************************************
- REMARKS:
- Implements the SHLD instruction and side effects.
- ****************************************************************************/
- u16 shld_word (u16 d, u16 fill, u8 s)
- {
- unsigned int cnt, res, cf;
- if (s < 16) {
- cnt = s % 16;
- if (cnt > 0) {
- res = (d << cnt) | (fill >> (16-cnt));
- cf = d & (1 << (16 - cnt));
- CONDITIONAL_SET_FLAG(cf, F_CF);
- set_szp_flags_16((u16)res);
- } else {
- res = d;
- }
- if (cnt == 1) {
- CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
- (ACCESS_FLAG(F_CF) != 0)), F_OF);
- } else {
- CLEAR_FLAG(F_OF);
- }
- } else {
- res = 0;
- CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
- CLEAR_FLAG(F_OF);
- CLEAR_FLAG(F_SF);
- SET_FLAG(F_PF);
- SET_FLAG(F_ZF);
- }
- return (u16)res;
- }
- /****************************************************************************
- REMARKS:
- Implements the SHLD instruction and side effects.
- ****************************************************************************/
- u32 shld_long (u32 d, u32 fill, u8 s)
- {
- unsigned int cnt, res, cf;
- if (s < 32) {
- cnt = s % 32;
- if (cnt > 0) {
- res = (d << cnt) | (fill >> (32-cnt));
- cf = d & (1 << (32 - cnt));
- CONDITIONAL_SET_FLAG(cf, F_CF);
- set_szp_flags_32((u32)res);
- } else {
- res = d;
- }
- if (cnt == 1) {
- CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
- (ACCESS_FLAG(F_CF) != 0)), F_OF);
- } else {
- CLEAR_FLAG(F_OF);
- }
- } else {
- res = 0;
- CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
- CLEAR_FLAG(F_OF);
- CLEAR_FLAG(F_SF);
- SET_FLAG(F_PF);
- SET_FLAG(F_ZF);
- }
- return res;
- }
- /****************************************************************************
- REMARKS:
- Implements the SHRD instruction and side effects.
- ****************************************************************************/
- u16 shrd_word (u16 d, u16 fill, u8 s)
- {
- unsigned int cnt, res, cf;
- if (s < 16) {
- cnt = s % 16;
- if (cnt > 0) {
- cf = d & (1 << (cnt - 1));
- res = (d >> cnt) | (fill << (16 - cnt));
- CONDITIONAL_SET_FLAG(cf, F_CF);
- set_szp_flags_16((u16)res);
- } else {
- res = d;
- }
- if (cnt == 1) {
- CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
- } else {
- CLEAR_FLAG(F_OF);
- }
- } else {
- res = 0;
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_OF);
- SET_FLAG(F_ZF);
- CLEAR_FLAG(F_SF);
- CLEAR_FLAG(F_PF);
- }
- return (u16)res;
- }
- /****************************************************************************
- REMARKS:
- Implements the SHRD instruction and side effects.
- ****************************************************************************/
- u32 shrd_long (u32 d, u32 fill, u8 s)
- {
- unsigned int cnt, res, cf;
- if (s < 32) {
- cnt = s % 32;
- if (cnt > 0) {
- cf = d & (1 << (cnt - 1));
- res = (d >> cnt) | (fill << (32 - cnt));
- CONDITIONAL_SET_FLAG(cf, F_CF);
- set_szp_flags_32((u32)res);
- } else {
- res = d;
- }
- if (cnt == 1) {
- CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
- } else {
- CLEAR_FLAG(F_OF);
- }
- } else {
- res = 0;
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_OF);
- SET_FLAG(F_ZF);
- CLEAR_FLAG(F_SF);
- CLEAR_FLAG(F_PF);
- }
- return res;
- }
- /****************************************************************************
- REMARKS:
- Implements the SBB instruction and side effects.
- ****************************************************************************/
- u8 sbb_byte(u8 d, u8 s)
- {
- u32 res; /* all operands in native machine order */
- u32 bc;
- if (ACCESS_FLAG(F_CF))
- res = d - s - 1;
- else
- res = d - s;
- set_szp_flags_8((u8)res);
- /* calculate the borrow chain. See note at top */
- bc = (res & (~d | s)) | (~d & s);
- CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
- CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
- CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
- return (u8)res;
- }
- /****************************************************************************
- REMARKS:
- Implements the SBB instruction and side effects.
- ****************************************************************************/
- u16 sbb_word(u16 d, u16 s)
- {
- u32 res; /* all operands in native machine order */
- u32 bc;
- if (ACCESS_FLAG(F_CF))
- res = d - s - 1;
- else
- res = d - s;
- set_szp_flags_16((u16)res);
- /* calculate the borrow chain. See note at top */
- bc = (res & (~d | s)) | (~d & s);
- CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
- CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
- CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
- return (u16)res;
- }
- /****************************************************************************
- REMARKS:
- Implements the SBB instruction and side effects.
- ****************************************************************************/
- u32 sbb_long(u32 d, u32 s)
- {
- u32 res; /* all operands in native machine order */
- u32 bc;
- if (ACCESS_FLAG(F_CF))
- res = d - s - 1;
- else
- res = d - s;
- set_szp_flags_32(res);
- /* calculate the borrow chain. See note at top */
- bc = (res & (~d | s)) | (~d & s);
- CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
- CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
- CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
- return res;
- }
- /****************************************************************************
- REMARKS:
- Implements the SUB instruction and side effects.
- ****************************************************************************/
- u8 sub_byte(u8 d, u8 s)
- {
- u32 res; /* all operands in native machine order */
- u32 bc;
- res = d - s;
- set_szp_flags_8((u8)res);
- /* calculate the borrow chain. See note at top */
- bc = (res & (~d | s)) | (~d & s);
- CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
- CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
- CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
- return (u8)res;
- }
- /****************************************************************************
- REMARKS:
- Implements the SUB instruction and side effects.
- ****************************************************************************/
- u16 sub_word(u16 d, u16 s)
- {
- u32 res; /* all operands in native machine order */
- u32 bc;
- res = d - s;
- set_szp_flags_16((u16)res);
- /* calculate the borrow chain. See note at top */
- bc = (res & (~d | s)) | (~d & s);
- CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
- CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
- CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
- return (u16)res;
- }
- /****************************************************************************
- REMARKS:
- Implements the SUB instruction and side effects.
- ****************************************************************************/
- u32 sub_long(u32 d, u32 s)
- {
- u32 res; /* all operands in native machine order */
- u32 bc;
- res = d - s;
- set_szp_flags_32(res);
- /* calculate the borrow chain. See note at top */
- bc = (res & (~d | s)) | (~d & s);
- CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
- CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
- CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
- return res;
- }
- /****************************************************************************
- REMARKS:
- Implements the TEST instruction and side effects.
- ****************************************************************************/
- void test_byte(u8 d, u8 s)
- {
- u32 res; /* all operands in native machine order */
- res = d & s;
- CLEAR_FLAG(F_OF);
- set_szp_flags_8((u8)res);
- /* AF == dont care */
- CLEAR_FLAG(F_CF);
- }
- /****************************************************************************
- REMARKS:
- Implements the TEST instruction and side effects.
- ****************************************************************************/
- void test_word(u16 d, u16 s)
- {
- u32 res; /* all operands in native machine order */
- res = d & s;
- CLEAR_FLAG(F_OF);
- set_szp_flags_16((u16)res);
- /* AF == dont care */
- CLEAR_FLAG(F_CF);
- }
- /****************************************************************************
- REMARKS:
- Implements the TEST instruction and side effects.
- ****************************************************************************/
- void test_long(u32 d, u32 s)
- {
- u32 res; /* all operands in native machine order */
- res = d & s;
- CLEAR_FLAG(F_OF);
- set_szp_flags_32(res);
- /* AF == dont care */
- CLEAR_FLAG(F_CF);
- }
- /****************************************************************************
- REMARKS:
- Implements the XOR instruction and side effects.
- ****************************************************************************/
- u8 xor_byte(u8 d, u8 s)
- {
- u8 res; /* all operands in native machine order */
- res = d ^ s;
- no_carry_byte_side_eff(res);
- return res;
- }
- /****************************************************************************
- REMARKS:
- Implements the XOR instruction and side effects.
- ****************************************************************************/
- u16 xor_word(u16 d, u16 s)
- {
- u16 res; /* all operands in native machine order */
- res = d ^ s;
- no_carry_word_side_eff(res);
- return res;
- }
- /****************************************************************************
- REMARKS:
- Implements the XOR instruction and side effects.
- ****************************************************************************/
- u32 xor_long(u32 d, u32 s)
- {
- u32 res; /* all operands in native machine order */
- res = d ^ s;
- no_carry_long_side_eff(res);
- return res;
- }
- /****************************************************************************
- REMARKS:
- Implements the IMUL instruction and side effects.
- ****************************************************************************/
- void imul_byte(u8 s)
- {
- s16 res = (s16)((s8)M.x86.R_AL * (s8)s);
- M.x86.R_AX = res;
- if (((M.x86.R_AL & 0x80) == 0 && M.x86.R_AH == 0x00) ||
- ((M.x86.R_AL & 0x80) != 0 && M.x86.R_AH == 0xFF)) {
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_OF);
- } else {
- SET_FLAG(F_CF);
- SET_FLAG(F_OF);
- }
- }
- /****************************************************************************
- REMARKS:
- Implements the IMUL instruction and side effects.
- ****************************************************************************/
- void imul_word(u16 s)
- {
- s32 res = (s16)M.x86.R_AX * (s16)s;
- M.x86.R_AX = (u16)res;
- M.x86.R_DX = (u16)(res >> 16);
- if (((M.x86.R_AX & 0x8000) == 0 && M.x86.R_DX == 0x0000) ||
- ((M.x86.R_AX & 0x8000) != 0 && M.x86.R_DX == 0xFFFF)) {
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_OF);
- } else {
- SET_FLAG(F_CF);
- SET_FLAG(F_OF);
- }
- }
- /****************************************************************************
- REMARKS:
- Implements the IMUL instruction and side effects.
- ****************************************************************************/
- void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s)
- {
- #ifdef __HAS_LONG_LONG__
- s64 res = (s32)d * (s32)s;
- *res_lo = (u32)res;
- *res_hi = (u32)(res >> 32);
- #else
- u32 d_lo,d_hi,d_sign;
- u32 s_lo,s_hi,s_sign;
- u32 rlo_lo,rlo_hi,rhi_lo;
- if ((d_sign = d & 0x80000000) != 0)
- d = -d;
- d_lo = d & 0xFFFF;
- d_hi = d >> 16;
- if ((s_sign = s & 0x80000000) != 0)
- s = -s;
- s_lo = s & 0xFFFF;
- s_hi = s >> 16;
- rlo_lo = d_lo * s_lo;
- rlo_hi = (d_hi * s_lo + d_lo * s_hi) + (rlo_lo >> 16);
- rhi_lo = d_hi * s_hi + (rlo_hi >> 16);
- *res_lo = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
- *res_hi = rhi_lo;
- if (d_sign != s_sign) {
- d = ~*res_lo;
- s = (((d & 0xFFFF) + 1) >> 16) + (d >> 16);
- *res_lo = ~*res_lo+1;
- *res_hi = ~*res_hi+(s >> 16);
- }
- #endif
- }
- /****************************************************************************
- REMARKS:
- Implements the IMUL instruction and side effects.
- ****************************************************************************/
- void imul_long(u32 s)
- {
- imul_long_direct(&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s);
- if (((M.x86.R_EAX & 0x80000000) == 0 && M.x86.R_EDX == 0x00000000) ||
- ((M.x86.R_EAX & 0x80000000) != 0 && M.x86.R_EDX == 0xFFFFFFFF)) {
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_OF);
- } else {
- SET_FLAG(F_CF);
- SET_FLAG(F_OF);
- }
- }
- /****************************************************************************
- REMARKS:
- Implements the MUL instruction and side effects.
- ****************************************************************************/
- void mul_byte(u8 s)
- {
- u16 res = (u16)(M.x86.R_AL * s);
- M.x86.R_AX = res;
- if (M.x86.R_AH == 0) {
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_OF);
- } else {
- SET_FLAG(F_CF);
- SET_FLAG(F_OF);
- }
- }
- /****************************************************************************
- REMARKS:
- Implements the MUL instruction and side effects.
- ****************************************************************************/
- void mul_word(u16 s)
- {
- u32 res = M.x86.R_AX * s;
- M.x86.R_AX = (u16)res;
- M.x86.R_DX = (u16)(res >> 16);
- if (M.x86.R_DX == 0) {
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_OF);
- } else {
- SET_FLAG(F_CF);
- SET_FLAG(F_OF);
- }
- }
- /****************************************************************************
- REMARKS:
- Implements the MUL instruction and side effects.
- ****************************************************************************/
- void mul_long(u32 s)
- {
- #ifdef __HAS_LONG_LONG__
- u64 res = (u32)M.x86.R_EAX * (u32)s;
- M.x86.R_EAX = (u32)res;
- M.x86.R_EDX = (u32)(res >> 32);
- #else
- u32 a,a_lo,a_hi;
- u32 s_lo,s_hi;
- u32 rlo_lo,rlo_hi,rhi_lo;
- a = M.x86.R_EAX;
- a_lo = a & 0xFFFF;
- a_hi = a >> 16;
- s_lo = s & 0xFFFF;
- s_hi = s >> 16;
- rlo_lo = a_lo * s_lo;
- rlo_hi = (a_hi * s_lo + a_lo * s_hi) + (rlo_lo >> 16);
- rhi_lo = a_hi * s_hi + (rlo_hi >> 16);
- M.x86.R_EAX = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
- M.x86.R_EDX = rhi_lo;
- #endif
- if (M.x86.R_EDX == 0) {
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_OF);
- } else {
- SET_FLAG(F_CF);
- SET_FLAG(F_OF);
- }
- }
- /****************************************************************************
- REMARKS:
- Implements the IDIV instruction and side effects.
- ****************************************************************************/
- void idiv_byte(u8 s)
- {
- s32 dvd, div, mod;
- dvd = (s16)M.x86.R_AX;
- if (s == 0) {
- x86emu_intr_raise(0);
- return;
- }
- div = dvd / (s8)s;
- mod = dvd % (s8)s;
- if (abs(div) > 0x7f) {
- x86emu_intr_raise(0);
- return;
- }
- M.x86.R_AL = (s8) div;
- M.x86.R_AH = (s8) mod;
- }
- /****************************************************************************
- REMARKS:
- Implements the IDIV instruction and side effects.
- ****************************************************************************/
- void idiv_word(u16 s)
- {
- s32 dvd, div, mod;
- dvd = (((s32)M.x86.R_DX) << 16) | M.x86.R_AX;
- if (s == 0) {
- x86emu_intr_raise(0);
- return;
- }
- div = dvd / (s16)s;
- mod = dvd % (s16)s;
- if (abs(div) > 0x7fff) {
- x86emu_intr_raise(0);
- return;
- }
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_SF);
- CONDITIONAL_SET_FLAG(div == 0, F_ZF);
- set_parity_flag(mod);
- M.x86.R_AX = (u16)div;
- M.x86.R_DX = (u16)mod;
- }
- /****************************************************************************
- REMARKS:
- Implements the IDIV instruction and side effects.
- ****************************************************************************/
- void idiv_long(u32 s)
- {
- #ifdef __HAS_LONG_LONG__
- s64 dvd, div, mod;
- dvd = (((s64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
- if (s == 0) {
- x86emu_intr_raise(0);
- return;
- }
- div = dvd / (s32)s;
- mod = dvd % (s32)s;
- if (abs(div) > 0x7fffffff) {
- x86emu_intr_raise(0);
- return;
- }
- #else
- s32 div = 0, mod;
- s32 h_dvd = M.x86.R_EDX;
- u32 l_dvd = M.x86.R_EAX;
- u32 abs_s = s & 0x7FFFFFFF;
- u32 abs_h_dvd = h_dvd & 0x7FFFFFFF;
- u32 h_s = abs_s >> 1;
- u32 l_s = abs_s << 31;
- int counter = 31;
- int carry;
- if (s == 0) {
- x86emu_intr_raise(0);
- return;
- }
- do {
- div <<= 1;
- carry = (l_dvd >= l_s) ? 0 : 1;
- if (abs_h_dvd < (h_s + carry)) {
- h_s >>= 1;
- l_s = abs_s << (--counter);
- continue;
- } else {
- abs_h_dvd -= (h_s + carry);
- l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
- : (l_dvd - l_s);
- h_s >>= 1;
- l_s = abs_s << (--counter);
- div |= 1;
- continue;
- }
- } while (counter > -1);
- /* overflow */
- if (abs_h_dvd || (l_dvd > abs_s)) {
- x86emu_intr_raise(0);
- return;
- }
- /* sign */
- div |= ((h_dvd & 0x10000000) ^ (s & 0x10000000));
- mod = l_dvd;
- #endif
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_AF);
- CLEAR_FLAG(F_SF);
- SET_FLAG(F_ZF);
- set_parity_flag(mod);
- M.x86.R_EAX = (u32)div;
- M.x86.R_EDX = (u32)mod;
- }
- /****************************************************************************
- REMARKS:
- Implements the DIV instruction and side effects.
- ****************************************************************************/
- void div_byte(u8 s)
- {
- u32 dvd, div, mod;
- dvd = M.x86.R_AX;
- if (s == 0) {
- x86emu_intr_raise(0);
- return;
- }
- div = dvd / (u8)s;
- mod = dvd % (u8)s;
- if (abs(div) > 0xff) {
- x86emu_intr_raise(0);
- return;
- }
- M.x86.R_AL = (u8)div;
- M.x86.R_AH = (u8)mod;
- }
- /****************************************************************************
- REMARKS:
- Implements the DIV instruction and side effects.
- ****************************************************************************/
- void div_word(u16 s)
- {
- u32 dvd, div, mod;
- dvd = (((u32)M.x86.R_DX) << 16) | M.x86.R_AX;
- if (s == 0) {
- x86emu_intr_raise(0);
- return;
- }
- div = dvd / (u16)s;
- mod = dvd % (u16)s;
- if (abs(div) > 0xffff) {
- x86emu_intr_raise(0);
- return;
- }
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_SF);
- CONDITIONAL_SET_FLAG(div == 0, F_ZF);
- set_parity_flag(mod);
- M.x86.R_AX = (u16)div;
- M.x86.R_DX = (u16)mod;
- }
- /****************************************************************************
- REMARKS:
- Implements the DIV instruction and side effects.
- ****************************************************************************/
- void div_long(u32 s)
- {
- #ifdef __HAS_LONG_LONG__
- u64 dvd, div, mod;
- dvd = (((u64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
- if (s == 0) {
- x86emu_intr_raise(0);
- return;
- }
- div = dvd / (u32)s;
- mod = dvd % (u32)s;
- if (abs(div) > 0xffffffff) {
- x86emu_intr_raise(0);
- return;
- }
- #else
- s32 div = 0, mod;
- s32 h_dvd = M.x86.R_EDX;
- u32 l_dvd = M.x86.R_EAX;
- u32 h_s = s;
- u32 l_s = 0;
- int counter = 32;
- int carry;
- if (s == 0) {
- x86emu_intr_raise(0);
- return;
- }
- do {
- div <<= 1;
- carry = (l_dvd >= l_s) ? 0 : 1;
- if (h_dvd < (h_s + carry)) {
- h_s >>= 1;
- l_s = s << (--counter);
- continue;
- } else {
- h_dvd -= (h_s + carry);
- l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
- : (l_dvd - l_s);
- h_s >>= 1;
- l_s = s << (--counter);
- div |= 1;
- continue;
- }
- } while (counter > -1);
- /* overflow */
- if (h_dvd || (l_dvd > s)) {
- x86emu_intr_raise(0);
- return;
- }
- mod = l_dvd;
- #endif
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_AF);
- CLEAR_FLAG(F_SF);
- SET_FLAG(F_ZF);
- set_parity_flag(mod);
- M.x86.R_EAX = (u32)div;
- M.x86.R_EDX = (u32)mod;
- }
- /****************************************************************************
- REMARKS:
- Implements the IN string instruction and side effects.
- ****************************************************************************/
- static void single_in(int size)
- {
- if(size == 1)
- store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inb)(M.x86.R_DX));
- else if (size == 2)
- store_data_word_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inw)(M.x86.R_DX));
- else
- store_data_long_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inl)(M.x86.R_DX));
- }
- void ins(int size)
- {
- int inc = size;
- if (ACCESS_FLAG(F_DF)) {
- inc = -size;
- }
- if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
- /* dont care whether REPE or REPNE */
- /* in until CX is ZERO. */
- u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
- M.x86.R_ECX : M.x86.R_CX);
- while (count--) {
- single_in(size);
- M.x86.R_DI += inc;
- }
- M.x86.R_CX = 0;
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_ECX = 0;
- }
- M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
- } else {
- single_in(size);
- M.x86.R_DI += inc;
- }
- }
- /****************************************************************************
- REMARKS:
- Implements the OUT string instruction and side effects.
- ****************************************************************************/
- static void single_out(int size)
- {
- if(size == 1)
- (*sys_outb)(M.x86.R_DX,fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
- else if (size == 2)
- (*sys_outw)(M.x86.R_DX,fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
- else
- (*sys_outl)(M.x86.R_DX,fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
- }
- void outs(int size)
- {
- int inc = size;
- if (ACCESS_FLAG(F_DF)) {
- inc = -size;
- }
- if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
- /* dont care whether REPE or REPNE */
- /* out until CX is ZERO. */
- u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
- M.x86.R_ECX : M.x86.R_CX);
- while (count--) {
- single_out(size);
- M.x86.R_SI += inc;
- }
- M.x86.R_CX = 0;
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_ECX = 0;
- }
- M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
- } else {
- single_out(size);
- M.x86.R_SI += inc;
- }
- }
- /****************************************************************************
- PARAMETERS:
- addr - Address to fetch word from
- REMARKS:
- Fetches a word from emulator memory using an absolute address.
- ****************************************************************************/
- u16 mem_access_word(int addr)
- {
- DB( if (CHECK_MEM_ACCESS())
- x86emu_check_mem_access(addr);)
- return (*sys_rdw)(addr);
- }
- /****************************************************************************
- REMARKS:
- Pushes a word onto the stack.
- NOTE: Do not inline this, as (*sys_wrX) is already inline!
- ****************************************************************************/
- void push_word(u16 w)
- {
- DB( if (CHECK_SP_ACCESS())
- x86emu_check_sp_access();)
- M.x86.R_SP -= 2;
- (*sys_wrw)(((u32)M.x86.R_SS << 4) + M.x86.R_SP, w);
- }
- /****************************************************************************
- REMARKS:
- Pushes a long onto the stack.
- NOTE: Do not inline this, as (*sys_wrX) is already inline!
- ****************************************************************************/
- void push_long(u32 w)
- {
- DB( if (CHECK_SP_ACCESS())
- x86emu_check_sp_access();)
- M.x86.R_SP -= 4;
- (*sys_wrl)(((u32)M.x86.R_SS << 4) + M.x86.R_SP, w);
- }
- /****************************************************************************
- REMARKS:
- Pops a word from the stack.
- NOTE: Do not inline this, as (*sys_rdX) is already inline!
- ****************************************************************************/
- u16 pop_word(void)
- {
- u16 res;
- DB( if (CHECK_SP_ACCESS())
- x86emu_check_sp_access();)
- res = (*sys_rdw)(((u32)M.x86.R_SS << 4) + M.x86.R_SP);
- M.x86.R_SP += 2;
- return res;
- }
- /****************************************************************************
- REMARKS:
- Pops a long from the stack.
- NOTE: Do not inline this, as (*sys_rdX) is already inline!
- ****************************************************************************/
- u32 pop_long(void)
- {
- u32 res;
- DB( if (CHECK_SP_ACCESS())
- x86emu_check_sp_access();)
- res = (*sys_rdl)(((u32)M.x86.R_SS << 4) + M.x86.R_SP);
- M.x86.R_SP += 4;
- return res;
- }
- #endif
|