prim_ops.c 62 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447
  1. /****************************************************************************
  2. *
  3. * Realmode X86 Emulator Library
  4. *
  5. * Copyright (C) 1991-2004 SciTech Software, Inc.
  6. * Copyright (C) David Mosberger-Tang
  7. * Copyright (C) 1999 Egbert Eich
  8. *
  9. * ========================================================================
  10. *
  11. * Permission to use, copy, modify, distribute, and sell this software and
  12. * its documentation for any purpose is hereby granted without fee,
  13. * provided that the above copyright notice appear in all copies and that
  14. * both that copyright notice and this permission notice appear in
  15. * supporting documentation, and that the name of the authors not be used
  16. * in advertising or publicity pertaining to distribution of the software
  17. * without specific, written prior permission. The authors makes no
  18. * representations about the suitability of this software for any purpose.
  19. * It is provided "as is" without express or implied warranty.
  20. *
  21. * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  22. * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  23. * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  24. * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
  25. * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  26. * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  27. * PERFORMANCE OF THIS SOFTWARE.
  28. *
  29. * ========================================================================
  30. *
  31. * Language: ANSI C
  32. * Environment: Any
  33. * Developer: Kendall Bennett
  34. *
  35. * Description: This file contains the code to implement the primitive
  36. * machine operations used by the emulation code in ops.c
  37. *
  38. * Carry Chain Calculation
  39. *
  40. * This represents a somewhat expensive calculation which is
  41. * apparently required to emulate the setting of the OF343364 and AF flag.
  42. * The latter is not so important, but the former is. The overflow
  43. * flag is the XOR of the top two bits of the carry chain for an
  44. * addition (similar for subtraction). Since we do not want to
  45. * simulate the addition in a bitwise manner, we try to calculate the
  46. * carry chain given the two operands and the result.
  47. *
  48. * So, given the following table, which represents the addition of two
  49. * bits, we can derive a formula for the carry chain.
  50. *
  51. * a b cin r cout
  52. * 0 0 0 0 0
  53. * 0 0 1 1 0
  54. * 0 1 0 1 0
  55. * 0 1 1 0 1
  56. * 1 0 0 1 0
  57. * 1 0 1 0 1
  58. * 1 1 0 0 1
  59. * 1 1 1 1 1
  60. *
  61. * Construction of table for cout:
  62. *
  63. * ab
  64. * r \ 00 01 11 10
  65. * |------------------
  66. * 0 | 0 1 1 1
  67. * 1 | 0 0 1 0
  68. *
  69. * By inspection, one gets: cc = ab + r'(a + b)
  70. *
  71. * That represents alot of operations, but NO CHOICE....
  72. *
  73. * Borrow Chain Calculation.
  74. *
  75. * The following table represents the subtraction of two bits, from
  76. * which we can derive a formula for the borrow chain.
  77. *
  78. * a b bin r bout
  79. * 0 0 0 0 0
  80. * 0 0 1 1 1
  81. * 0 1 0 1 1
  82. * 0 1 1 0 1
  83. * 1 0 0 1 0
  84. * 1 0 1 0 0
  85. * 1 1 0 0 0
  86. * 1 1 1 1 1
  87. *
  88. * Construction of table for cout:
  89. *
  90. * ab
  91. * r \ 00 01 11 10
  92. * |------------------
  93. * 0 | 0 1 0 0
  94. * 1 | 1 1 1 0
  95. *
  96. * By inspection, one gets: bc = a'b + r(a' + b)
  97. *
  98. ****************************************************************************/
  99. #include <common.h>
  100. #define PRIM_OPS_NO_REDEFINE_ASM
  101. #include "x86emu/x86emui.h"
  102. /*------------------------- Global Variables ------------------------------*/
  103. static u32 x86emu_parity_tab[8] =
  104. {
  105. 0x96696996,
  106. 0x69969669,
  107. 0x69969669,
  108. 0x96696996,
  109. 0x69969669,
  110. 0x96696996,
  111. 0x96696996,
  112. 0x69969669,
  113. };
  114. #define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
  115. #define XOR2(x) (((x) ^ ((x)>>1)) & 0x1)
  116. /*----------------------------- Implementation ----------------------------*/
  117. int abs(int v)
  118. {
  119. return (v>0)?v:-v;
  120. }
  121. /*----------------------------- Implementation ----------------------------*/
  122. /*--------- Side effects helper functions -------*/
  123. /****************************************************************************
  124. REMARKS:
  125. implements side efects for byte operations that don't overflow
  126. ****************************************************************************/
  127. static void set_parity_flag(u32 res)
  128. {
  129. CONDITIONAL_SET_FLAG(PARITY(res & 0xFF), F_PF);
  130. }
  131. static void set_szp_flags_8(u8 res)
  132. {
  133. CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
  134. CONDITIONAL_SET_FLAG(res == 0, F_ZF);
  135. set_parity_flag(res);
  136. }
  137. static void set_szp_flags_16(u16 res)
  138. {
  139. CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
  140. CONDITIONAL_SET_FLAG(res == 0, F_ZF);
  141. set_parity_flag(res);
  142. }
  143. static void set_szp_flags_32(u32 res)
  144. {
  145. CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
  146. CONDITIONAL_SET_FLAG(res == 0, F_ZF);
  147. set_parity_flag(res);
  148. }
  149. static void no_carry_byte_side_eff(u8 res)
  150. {
  151. CLEAR_FLAG(F_OF);
  152. CLEAR_FLAG(F_CF);
  153. CLEAR_FLAG(F_AF);
  154. set_szp_flags_8(res);
  155. }
  156. static void no_carry_word_side_eff(u16 res)
  157. {
  158. CLEAR_FLAG(F_OF);
  159. CLEAR_FLAG(F_CF);
  160. CLEAR_FLAG(F_AF);
  161. set_szp_flags_16(res);
  162. }
  163. static void no_carry_long_side_eff(u32 res)
  164. {
  165. CLEAR_FLAG(F_OF);
  166. CLEAR_FLAG(F_CF);
  167. CLEAR_FLAG(F_AF);
  168. set_szp_flags_32(res);
  169. }
  170. static void calc_carry_chain(int bits, u32 d, u32 s, u32 res, int set_carry)
  171. {
  172. u32 cc;
  173. cc = (s & d) | ((~res) & (s | d));
  174. CONDITIONAL_SET_FLAG(XOR2(cc >> (bits - 2)), F_OF);
  175. CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
  176. if (set_carry) {
  177. CONDITIONAL_SET_FLAG(res & (1 << bits), F_CF);
  178. }
  179. }
  180. static void calc_borrow_chain(int bits, u32 d, u32 s, u32 res, int set_carry)
  181. {
  182. u32 bc;
  183. bc = (res & (~d | s)) | (~d & s);
  184. CONDITIONAL_SET_FLAG(XOR2(bc >> (bits - 2)), F_OF);
  185. CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
  186. if (set_carry) {
  187. CONDITIONAL_SET_FLAG(bc & (1 << (bits - 1)), F_CF);
  188. }
  189. }
  190. /****************************************************************************
  191. REMARKS:
  192. Implements the AAA instruction and side effects.
  193. ****************************************************************************/
  194. u16 aaa_word(u16 d)
  195. {
  196. u16 res;
  197. if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
  198. d += 0x6;
  199. d += 0x100;
  200. SET_FLAG(F_AF);
  201. SET_FLAG(F_CF);
  202. } else {
  203. CLEAR_FLAG(F_CF);
  204. CLEAR_FLAG(F_AF);
  205. }
  206. res = (u16)(d & 0xFF0F);
  207. set_szp_flags_16(res);
  208. return res;
  209. }
  210. /****************************************************************************
  211. REMARKS:
  212. Implements the AAA instruction and side effects.
  213. ****************************************************************************/
  214. u16 aas_word(u16 d)
  215. {
  216. u16 res;
  217. if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
  218. d -= 0x6;
  219. d -= 0x100;
  220. SET_FLAG(F_AF);
  221. SET_FLAG(F_CF);
  222. } else {
  223. CLEAR_FLAG(F_CF);
  224. CLEAR_FLAG(F_AF);
  225. }
  226. res = (u16)(d & 0xFF0F);
  227. set_szp_flags_16(res);
  228. return res;
  229. }
  230. /****************************************************************************
  231. REMARKS:
  232. Implements the AAD instruction and side effects.
  233. ****************************************************************************/
  234. u16 aad_word(u16 d)
  235. {
  236. u16 l;
  237. u8 hb, lb;
  238. hb = (u8)((d >> 8) & 0xff);
  239. lb = (u8)((d & 0xff));
  240. l = (u16)((lb + 10 * hb) & 0xFF);
  241. no_carry_byte_side_eff(l & 0xFF);
  242. return l;
  243. }
  244. /****************************************************************************
  245. REMARKS:
  246. Implements the AAM instruction and side effects.
  247. ****************************************************************************/
  248. u16 aam_word(u8 d)
  249. {
  250. u16 h, l;
  251. h = (u16)(d / 10);
  252. l = (u16)(d % 10);
  253. l |= (u16)(h << 8);
  254. no_carry_byte_side_eff(l & 0xFF);
  255. return l;
  256. }
  257. /****************************************************************************
  258. REMARKS:
  259. Implements the ADC instruction and side effects.
  260. ****************************************************************************/
  261. u8 adc_byte(u8 d, u8 s)
  262. {
  263. u32 res; /* all operands in native machine order */
  264. res = d + s;
  265. if (ACCESS_FLAG(F_CF)) res++;
  266. set_szp_flags_8(res);
  267. calc_carry_chain(8,s,d,res,1);
  268. return (u8)res;
  269. }
  270. /****************************************************************************
  271. REMARKS:
  272. Implements the ADC instruction and side effects.
  273. ****************************************************************************/
  274. u16 adc_word(u16 d, u16 s)
  275. {
  276. u32 res; /* all operands in native machine order */
  277. res = d + s;
  278. if (ACCESS_FLAG(F_CF))
  279. res++;
  280. set_szp_flags_16((u16)res);
  281. calc_carry_chain(16,s,d,res,1);
  282. return (u16)res;
  283. }
  284. /****************************************************************************
  285. REMARKS:
  286. Implements the ADC instruction and side effects.
  287. ****************************************************************************/
  288. u32 adc_long(u32 d, u32 s)
  289. {
  290. u32 lo; /* all operands in native machine order */
  291. u32 hi;
  292. u32 res;
  293. lo = (d & 0xFFFF) + (s & 0xFFFF);
  294. res = d + s;
  295. if (ACCESS_FLAG(F_CF)) {
  296. lo++;
  297. res++;
  298. }
  299. hi = (lo >> 16) + (d >> 16) + (s >> 16);
  300. set_szp_flags_32(res);
  301. calc_carry_chain(32,s,d,res,0);
  302. CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
  303. return res;
  304. }
  305. /****************************************************************************
  306. REMARKS:
  307. Implements the ADD instruction and side effects.
  308. ****************************************************************************/
  309. u8 add_byte(u8 d, u8 s)
  310. {
  311. u32 res; /* all operands in native machine order */
  312. res = d + s;
  313. set_szp_flags_8((u8)res);
  314. calc_carry_chain(8,s,d,res,1);
  315. return (u8)res;
  316. }
  317. /****************************************************************************
  318. REMARKS:
  319. Implements the ADD instruction and side effects.
  320. ****************************************************************************/
  321. u16 add_word(u16 d, u16 s)
  322. {
  323. u32 res; /* all operands in native machine order */
  324. res = d + s;
  325. set_szp_flags_16((u16)res);
  326. calc_carry_chain(16,s,d,res,1);
  327. return (u16)res;
  328. }
  329. /****************************************************************************
  330. REMARKS:
  331. Implements the ADD instruction and side effects.
  332. ****************************************************************************/
  333. u32 add_long(u32 d, u32 s)
  334. {
  335. u32 res;
  336. res = d + s;
  337. set_szp_flags_32(res);
  338. calc_carry_chain(32,s,d,res,0);
  339. CONDITIONAL_SET_FLAG(res < d || res < s, F_CF);
  340. return res;
  341. }
  342. /****************************************************************************
  343. REMARKS:
  344. Implements the AND instruction and side effects.
  345. ****************************************************************************/
  346. u8 and_byte(u8 d, u8 s)
  347. {
  348. u8 res; /* all operands in native machine order */
  349. res = d & s;
  350. no_carry_byte_side_eff(res);
  351. return res;
  352. }
  353. /****************************************************************************
  354. REMARKS:
  355. Implements the AND instruction and side effects.
  356. ****************************************************************************/
  357. u16 and_word(u16 d, u16 s)
  358. {
  359. u16 res; /* all operands in native machine order */
  360. res = d & s;
  361. no_carry_word_side_eff(res);
  362. return res;
  363. }
  364. /****************************************************************************
  365. REMARKS:
  366. Implements the AND instruction and side effects.
  367. ****************************************************************************/
  368. u32 and_long(u32 d, u32 s)
  369. {
  370. u32 res; /* all operands in native machine order */
  371. res = d & s;
  372. no_carry_long_side_eff(res);
  373. return res;
  374. }
  375. /****************************************************************************
  376. REMARKS:
  377. Implements the CMP instruction and side effects.
  378. ****************************************************************************/
  379. u8 cmp_byte(u8 d, u8 s)
  380. {
  381. u32 res; /* all operands in native machine order */
  382. res = d - s;
  383. set_szp_flags_8((u8)res);
  384. calc_borrow_chain(8, d, s, res, 1);
  385. return d;
  386. }
  387. /****************************************************************************
  388. REMARKS:
  389. Implements the CMP instruction and side effects.
  390. ****************************************************************************/
  391. u16 cmp_word(u16 d, u16 s)
  392. {
  393. u32 res; /* all operands in native machine order */
  394. res = d - s;
  395. set_szp_flags_16((u16)res);
  396. calc_borrow_chain(16, d, s, res, 1);
  397. return d;
  398. }
  399. /****************************************************************************
  400. REMARKS:
  401. Implements the CMP instruction and side effects.
  402. ****************************************************************************/
  403. u32 cmp_long(u32 d, u32 s)
  404. {
  405. u32 res; /* all operands in native machine order */
  406. res = d - s;
  407. set_szp_flags_32(res);
  408. calc_borrow_chain(32, d, s, res, 1);
  409. return d;
  410. }
  411. /****************************************************************************
  412. REMARKS:
  413. Implements the DAA instruction and side effects.
  414. ****************************************************************************/
  415. u8 daa_byte(u8 d)
  416. {
  417. u32 res = d;
  418. if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
  419. res += 6;
  420. SET_FLAG(F_AF);
  421. }
  422. if (res > 0x9F || ACCESS_FLAG(F_CF)) {
  423. res += 0x60;
  424. SET_FLAG(F_CF);
  425. }
  426. set_szp_flags_8((u8)res);
  427. return (u8)res;
  428. }
  429. /****************************************************************************
  430. REMARKS:
  431. Implements the DAS instruction and side effects.
  432. ****************************************************************************/
  433. u8 das_byte(u8 d)
  434. {
  435. if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
  436. d -= 6;
  437. SET_FLAG(F_AF);
  438. }
  439. if (d > 0x9F || ACCESS_FLAG(F_CF)) {
  440. d -= 0x60;
  441. SET_FLAG(F_CF);
  442. }
  443. set_szp_flags_8(d);
  444. return d;
  445. }
  446. /****************************************************************************
  447. REMARKS:
  448. Implements the DEC instruction and side effects.
  449. ****************************************************************************/
  450. u8 dec_byte(u8 d)
  451. {
  452. u32 res; /* all operands in native machine order */
  453. res = d - 1;
  454. set_szp_flags_8((u8)res);
  455. calc_borrow_chain(8, d, 1, res, 0);
  456. return (u8)res;
  457. }
  458. /****************************************************************************
  459. REMARKS:
  460. Implements the DEC instruction and side effects.
  461. ****************************************************************************/
  462. u16 dec_word(u16 d)
  463. {
  464. u32 res; /* all operands in native machine order */
  465. res = d - 1;
  466. set_szp_flags_16((u16)res);
  467. calc_borrow_chain(16, d, 1, res, 0);
  468. return (u16)res;
  469. }
  470. /****************************************************************************
  471. REMARKS:
  472. Implements the DEC instruction and side effects.
  473. ****************************************************************************/
  474. u32 dec_long(u32 d)
  475. {
  476. u32 res; /* all operands in native machine order */
  477. res = d - 1;
  478. set_szp_flags_32(res);
  479. calc_borrow_chain(32, d, 1, res, 0);
  480. return res;
  481. }
  482. /****************************************************************************
  483. REMARKS:
  484. Implements the INC instruction and side effects.
  485. ****************************************************************************/
  486. u8 inc_byte(u8 d)
  487. {
  488. u32 res; /* all operands in native machine order */
  489. res = d + 1;
  490. set_szp_flags_8((u8)res);
  491. calc_carry_chain(8, d, 1, res, 0);
  492. return (u8)res;
  493. }
  494. /****************************************************************************
  495. REMARKS:
  496. Implements the INC instruction and side effects.
  497. ****************************************************************************/
  498. u16 inc_word(u16 d)
  499. {
  500. u32 res; /* all operands in native machine order */
  501. res = d + 1;
  502. set_szp_flags_16((u16)res);
  503. calc_carry_chain(16, d, 1, res, 0);
  504. return (u16)res;
  505. }
  506. /****************************************************************************
  507. REMARKS:
  508. Implements the INC instruction and side effects.
  509. ****************************************************************************/
  510. u32 inc_long(u32 d)
  511. {
  512. u32 res; /* all operands in native machine order */
  513. res = d + 1;
  514. set_szp_flags_32(res);
  515. calc_carry_chain(32, d, 1, res, 0);
  516. return res;
  517. }
  518. /****************************************************************************
  519. REMARKS:
  520. Implements the OR instruction and side effects.
  521. ****************************************************************************/
  522. u8 or_byte(u8 d, u8 s)
  523. {
  524. u8 res; /* all operands in native machine order */
  525. res = d | s;
  526. no_carry_byte_side_eff(res);
  527. return res;
  528. }
  529. /****************************************************************************
  530. REMARKS:
  531. Implements the OR instruction and side effects.
  532. ****************************************************************************/
  533. u16 or_word(u16 d, u16 s)
  534. {
  535. u16 res; /* all operands in native machine order */
  536. res = d | s;
  537. no_carry_word_side_eff(res);
  538. return res;
  539. }
  540. /****************************************************************************
  541. REMARKS:
  542. Implements the OR instruction and side effects.
  543. ****************************************************************************/
  544. u32 or_long(u32 d, u32 s)
  545. {
  546. u32 res; /* all operands in native machine order */
  547. res = d | s;
  548. no_carry_long_side_eff(res);
  549. return res;
  550. }
  551. /****************************************************************************
  552. REMARKS:
  553. Implements the OR instruction and side effects.
  554. ****************************************************************************/
  555. u8 neg_byte(u8 s)
  556. {
  557. u8 res;
  558. CONDITIONAL_SET_FLAG(s != 0, F_CF);
  559. res = (u8)-s;
  560. set_szp_flags_8(res);
  561. calc_borrow_chain(8, 0, s, res, 0);
  562. return res;
  563. }
  564. /****************************************************************************
  565. REMARKS:
  566. Implements the OR instruction and side effects.
  567. ****************************************************************************/
  568. u16 neg_word(u16 s)
  569. {
  570. u16 res;
  571. CONDITIONAL_SET_FLAG(s != 0, F_CF);
  572. res = (u16)-s;
  573. set_szp_flags_16((u16)res);
  574. calc_borrow_chain(16, 0, s, res, 0);
  575. return res;
  576. }
  577. /****************************************************************************
  578. REMARKS:
  579. Implements the OR instruction and side effects.
  580. ****************************************************************************/
  581. u32 neg_long(u32 s)
  582. {
  583. u32 res;
  584. CONDITIONAL_SET_FLAG(s != 0, F_CF);
  585. res = (u32)-s;
  586. set_szp_flags_32(res);
  587. calc_borrow_chain(32, 0, s, res, 0);
  588. return res;
  589. }
  590. /****************************************************************************
  591. REMARKS:
  592. Implements the NOT instruction and side effects.
  593. ****************************************************************************/
  594. u8 not_byte(u8 s)
  595. {
  596. return ~s;
  597. }
  598. /****************************************************************************
  599. REMARKS:
  600. Implements the NOT instruction and side effects.
  601. ****************************************************************************/
  602. u16 not_word(u16 s)
  603. {
  604. return ~s;
  605. }
  606. /****************************************************************************
  607. REMARKS:
  608. Implements the NOT instruction and side effects.
  609. ****************************************************************************/
  610. u32 not_long(u32 s)
  611. {
  612. return ~s;
  613. }
  614. /****************************************************************************
  615. REMARKS:
  616. Implements the RCL instruction and side effects.
  617. ****************************************************************************/
  618. u8 rcl_byte(u8 d, u8 s)
  619. {
  620. unsigned int res, cnt, mask, cf;
  621. /* s is the rotate distance. It varies from 0 - 8. */
  622. /* have
  623. CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
  624. want to rotate through the carry by "s" bits. We could
  625. loop, but that's inefficient. So the width is 9,
  626. and we split into three parts:
  627. The new carry flag (was B_n)
  628. the stuff in B_n-1 .. B_0
  629. the stuff in B_7 .. B_n+1
  630. The new rotate is done mod 9, and given this,
  631. for a rotation of n bits (mod 9) the new carry flag is
  632. then located n bits from the MSB. The low part is
  633. then shifted up cnt bits, and the high part is or'd
  634. in. Using CAPS for new values, and lowercase for the
  635. original values, this can be expressed as:
  636. IF n > 0
  637. 1) CF <- b_(8-n)
  638. 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0
  639. 3) B_(n-1) <- cf
  640. 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1))
  641. */
  642. res = d;
  643. if ((cnt = s % 9) != 0) {
  644. /* extract the new CARRY FLAG. */
  645. /* CF <- b_(8-n) */
  646. cf = (d >> (8 - cnt)) & 0x1;
  647. /* get the low stuff which rotated
  648. into the range B_7 .. B_cnt */
  649. /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 */
  650. /* note that the right hand side done by the mask */
  651. res = (d << cnt) & 0xff;
  652. /* now the high stuff which rotated around
  653. into the positions B_cnt-2 .. B_0 */
  654. /* B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */
  655. /* shift it downward, 7-(n-2) = 9-n positions.
  656. and mask off the result before or'ing in.
  657. */
  658. mask = (1 << (cnt - 1)) - 1;
  659. res |= (d >> (9 - cnt)) & mask;
  660. /* if the carry flag was set, or it in. */
  661. if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
  662. /* B_(n-1) <- cf */
  663. res |= 1 << (cnt - 1);
  664. }
  665. /* set the new carry flag, based on the variable "cf" */
  666. CONDITIONAL_SET_FLAG(cf, F_CF);
  667. /* OVERFLOW is set *IFF* cnt==1, then it is the
  668. xor of CF and the most significant bit. Blecck. */
  669. /* parenthesized this expression since it appears to
  670. be causing OF to be misset */
  671. CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
  672. F_OF);
  673. }
  674. return (u8)res;
  675. }
  676. /****************************************************************************
  677. REMARKS:
  678. Implements the RCL instruction and side effects.
  679. ****************************************************************************/
  680. u16 rcl_word(u16 d, u8 s)
  681. {
  682. unsigned int res, cnt, mask, cf;
  683. res = d;
  684. if ((cnt = s % 17) != 0) {
  685. cf = (d >> (16 - cnt)) & 0x1;
  686. res = (d << cnt) & 0xffff;
  687. mask = (1 << (cnt - 1)) - 1;
  688. res |= (d >> (17 - cnt)) & mask;
  689. if (ACCESS_FLAG(F_CF)) {
  690. res |= 1 << (cnt - 1);
  691. }
  692. CONDITIONAL_SET_FLAG(cf, F_CF);
  693. CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
  694. F_OF);
  695. }
  696. return (u16)res;
  697. }
  698. /****************************************************************************
  699. REMARKS:
  700. Implements the RCL instruction and side effects.
  701. ****************************************************************************/
  702. u32 rcl_long(u32 d, u8 s)
  703. {
  704. u32 res, cnt, mask, cf;
  705. res = d;
  706. if ((cnt = s % 33) != 0) {
  707. cf = (d >> (32 - cnt)) & 0x1;
  708. res = (d << cnt) & 0xffffffff;
  709. mask = (1 << (cnt - 1)) - 1;
  710. res |= (d >> (33 - cnt)) & mask;
  711. if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
  712. res |= 1 << (cnt - 1);
  713. }
  714. CONDITIONAL_SET_FLAG(cf, F_CF);
  715. CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
  716. F_OF);
  717. }
  718. return res;
  719. }
  720. /****************************************************************************
  721. REMARKS:
  722. Implements the RCR instruction and side effects.
  723. ****************************************************************************/
  724. u8 rcr_byte(u8 d, u8 s)
  725. {
  726. u32 res, cnt;
  727. u32 mask, cf, ocf = 0;
  728. /* rotate right through carry */
  729. /*
  730. s is the rotate distance. It varies from 0 - 8.
  731. d is the byte object rotated.
  732. have
  733. CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
  734. The new rotate is done mod 9, and given this,
  735. for a rotation of n bits (mod 9) the new carry flag is
  736. then located n bits from the LSB. The low part is
  737. then shifted up cnt bits, and the high part is or'd
  738. in. Using CAPS for new values, and lowercase for the
  739. original values, this can be expressed as:
  740. IF n > 0
  741. 1) CF <- b_(n-1)
  742. 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
  743. 3) B_(8-n) <- cf
  744. 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0)
  745. */
  746. res = d;
  747. if ((cnt = s % 9) != 0) {
  748. /* extract the new CARRY FLAG. */
  749. /* CF <- b_(n-1) */
  750. if (cnt == 1) {
  751. cf = d & 0x1;
  752. /* note hackery here. Access_flag(..) evaluates to either
  753. 0 if flag not set
  754. non-zero if flag is set.
  755. doing access_flag(..) != 0 casts that into either
  756. 0..1 in any representation of the flags register
  757. (i.e. packed bit array or unpacked.)
  758. */
  759. ocf = ACCESS_FLAG(F_CF) != 0;
  760. } else
  761. cf = (d >> (cnt - 1)) & 0x1;
  762. /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */
  763. /* note that the right hand side done by the mask
  764. This is effectively done by shifting the
  765. object to the right. The result must be masked,
  766. in case the object came in and was treated
  767. as a negative number. Needed??? */
  768. mask = (1 << (8 - cnt)) - 1;
  769. res = (d >> cnt) & mask;
  770. /* now the high stuff which rotated around
  771. into the positions B_cnt-2 .. B_0 */
  772. /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */
  773. /* shift it downward, 7-(n-2) = 9-n positions.
  774. and mask off the result before or'ing in.
  775. */
  776. res |= (d << (9 - cnt));
  777. /* if the carry flag was set, or it in. */
  778. if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
  779. /* B_(8-n) <- cf */
  780. res |= 1 << (8 - cnt);
  781. }
  782. /* set the new carry flag, based on the variable "cf" */
  783. CONDITIONAL_SET_FLAG(cf, F_CF);
  784. /* OVERFLOW is set *IFF* cnt==1, then it is the
  785. xor of CF and the most significant bit. Blecck. */
  786. /* parenthesized... */
  787. if (cnt == 1) {
  788. CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
  789. F_OF);
  790. }
  791. }
  792. return (u8)res;
  793. }
  794. /****************************************************************************
  795. REMARKS:
  796. Implements the RCR instruction and side effects.
  797. ****************************************************************************/
  798. u16 rcr_word(u16 d, u8 s)
  799. {
  800. u32 res, cnt;
  801. u32 mask, cf, ocf = 0;
  802. /* rotate right through carry */
  803. res = d;
  804. if ((cnt = s % 17) != 0) {
  805. if (cnt == 1) {
  806. cf = d & 0x1;
  807. ocf = ACCESS_FLAG(F_CF) != 0;
  808. } else
  809. cf = (d >> (cnt - 1)) & 0x1;
  810. mask = (1 << (16 - cnt)) - 1;
  811. res = (d >> cnt) & mask;
  812. res |= (d << (17 - cnt));
  813. if (ACCESS_FLAG(F_CF)) {
  814. res |= 1 << (16 - cnt);
  815. }
  816. CONDITIONAL_SET_FLAG(cf, F_CF);
  817. if (cnt == 1) {
  818. CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
  819. F_OF);
  820. }
  821. }
  822. return (u16)res;
  823. }
  824. /****************************************************************************
  825. REMARKS:
  826. Implements the RCR instruction and side effects.
  827. ****************************************************************************/
  828. u32 rcr_long(u32 d, u8 s)
  829. {
  830. u32 res, cnt;
  831. u32 mask, cf, ocf = 0;
  832. /* rotate right through carry */
  833. res = d;
  834. if ((cnt = s % 33) != 0) {
  835. if (cnt == 1) {
  836. cf = d & 0x1;
  837. ocf = ACCESS_FLAG(F_CF) != 0;
  838. } else
  839. cf = (d >> (cnt - 1)) & 0x1;
  840. mask = (1 << (32 - cnt)) - 1;
  841. res = (d >> cnt) & mask;
  842. if (cnt != 1)
  843. res |= (d << (33 - cnt));
  844. if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
  845. res |= 1 << (32 - cnt);
  846. }
  847. CONDITIONAL_SET_FLAG(cf, F_CF);
  848. if (cnt == 1) {
  849. CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
  850. F_OF);
  851. }
  852. }
  853. return res;
  854. }
  855. /****************************************************************************
  856. REMARKS:
  857. Implements the ROL instruction and side effects.
  858. ****************************************************************************/
  859. u8 rol_byte(u8 d, u8 s)
  860. {
  861. unsigned int res, cnt, mask;
  862. /* rotate left */
  863. /*
  864. s is the rotate distance. It varies from 0 - 8.
  865. d is the byte object rotated.
  866. have
  867. CF B_7 ... B_0
  868. The new rotate is done mod 8.
  869. Much simpler than the "rcl" or "rcr" operations.
  870. IF n > 0
  871. 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0)
  872. 2) B_(n-1) .. B_(0) <- b_(7) .. b_(8-n)
  873. */
  874. res = d;
  875. if ((cnt = s % 8) != 0) {
  876. /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */
  877. res = (d << cnt);
  878. /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */
  879. mask = (1 << cnt) - 1;
  880. res |= (d >> (8 - cnt)) & mask;
  881. /* set the new carry flag, Note that it is the low order
  882. bit of the result!!! */
  883. CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
  884. /* OVERFLOW is set *IFF* s==1, then it is the
  885. xor of CF and the most significant bit. Blecck. */
  886. CONDITIONAL_SET_FLAG(s == 1 &&
  887. XOR2((res & 0x1) + ((res >> 6) & 0x2)),
  888. F_OF);
  889. } if (s != 0) {
  890. /* set the new carry flag, Note that it is the low order
  891. bit of the result!!! */
  892. CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
  893. }
  894. return (u8)res;
  895. }
  896. /****************************************************************************
  897. REMARKS:
  898. Implements the ROL instruction and side effects.
  899. ****************************************************************************/
  900. u16 rol_word(u16 d, u8 s)
  901. {
  902. unsigned int res, cnt, mask;
  903. res = d;
  904. if ((cnt = s % 16) != 0) {
  905. res = (d << cnt);
  906. mask = (1 << cnt) - 1;
  907. res |= (d >> (16 - cnt)) & mask;
  908. CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
  909. CONDITIONAL_SET_FLAG(s == 1 &&
  910. XOR2((res & 0x1) + ((res >> 14) & 0x2)),
  911. F_OF);
  912. } if (s != 0) {
  913. /* set the new carry flag, Note that it is the low order
  914. bit of the result!!! */
  915. CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
  916. }
  917. return (u16)res;
  918. }
  919. /****************************************************************************
  920. REMARKS:
  921. Implements the ROL instruction and side effects.
  922. ****************************************************************************/
  923. u32 rol_long(u32 d, u8 s)
  924. {
  925. u32 res, cnt, mask;
  926. res = d;
  927. if ((cnt = s % 32) != 0) {
  928. res = (d << cnt);
  929. mask = (1 << cnt) - 1;
  930. res |= (d >> (32 - cnt)) & mask;
  931. CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
  932. CONDITIONAL_SET_FLAG(s == 1 &&
  933. XOR2((res & 0x1) + ((res >> 30) & 0x2)),
  934. F_OF);
  935. } if (s != 0) {
  936. /* set the new carry flag, Note that it is the low order
  937. bit of the result!!! */
  938. CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
  939. }
  940. return res;
  941. }
  942. /****************************************************************************
  943. REMARKS:
  944. Implements the ROR instruction and side effects.
  945. ****************************************************************************/
  946. u8 ror_byte(u8 d, u8 s)
  947. {
  948. unsigned int res, cnt, mask;
  949. /* rotate right */
  950. /*
  951. s is the rotate distance. It varies from 0 - 8.
  952. d is the byte object rotated.
  953. have
  954. B_7 ... B_0
  955. The rotate is done mod 8.
  956. IF n > 0
  957. 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
  958. 2) B_(7) .. B_(8-n) <- b_(n-1) .. b_(0)
  959. */
  960. res = d;
  961. if ((cnt = s % 8) != 0) { /* not a typo, do nada if cnt==0 */
  962. /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) */
  963. res = (d << (8 - cnt));
  964. /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */
  965. mask = (1 << (8 - cnt)) - 1;
  966. res |= (d >> (cnt)) & mask;
  967. /* set the new carry flag, Note that it is the low order
  968. bit of the result!!! */
  969. CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
  970. /* OVERFLOW is set *IFF* s==1, then it is the
  971. xor of the two most significant bits. Blecck. */
  972. CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
  973. } else if (s != 0) {
  974. /* set the new carry flag, Note that it is the low order
  975. bit of the result!!! */
  976. CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
  977. }
  978. return (u8)res;
  979. }
  980. /****************************************************************************
  981. REMARKS:
  982. Implements the ROR instruction and side effects.
  983. ****************************************************************************/
  984. u16 ror_word(u16 d, u8 s)
  985. {
  986. unsigned int res, cnt, mask;
  987. res = d;
  988. if ((cnt = s % 16) != 0) {
  989. res = (d << (16 - cnt));
  990. mask = (1 << (16 - cnt)) - 1;
  991. res |= (d >> (cnt)) & mask;
  992. CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
  993. CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
  994. } else if (s != 0) {
  995. /* set the new carry flag, Note that it is the low order
  996. bit of the result!!! */
  997. CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
  998. }
  999. return (u16)res;
  1000. }
  1001. /****************************************************************************
  1002. REMARKS:
  1003. Implements the ROR instruction and side effects.
  1004. ****************************************************************************/
  1005. u32 ror_long(u32 d, u8 s)
  1006. {
  1007. u32 res, cnt, mask;
  1008. res = d;
  1009. if ((cnt = s % 32) != 0) {
  1010. res = (d << (32 - cnt));
  1011. mask = (1 << (32 - cnt)) - 1;
  1012. res |= (d >> (cnt)) & mask;
  1013. CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
  1014. CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
  1015. } else if (s != 0) {
  1016. /* set the new carry flag, Note that it is the low order
  1017. bit of the result!!! */
  1018. CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
  1019. }
  1020. return res;
  1021. }
  1022. /****************************************************************************
  1023. REMARKS:
  1024. Implements the SHL instruction and side effects.
  1025. ****************************************************************************/
  1026. u8 shl_byte(u8 d, u8 s)
  1027. {
  1028. unsigned int cnt, res, cf;
  1029. if (s < 8) {
  1030. cnt = s % 8;
  1031. /* last bit shifted out goes into carry flag */
  1032. if (cnt > 0) {
  1033. res = d << cnt;
  1034. cf = d & (1 << (8 - cnt));
  1035. CONDITIONAL_SET_FLAG(cf, F_CF);
  1036. set_szp_flags_8((u8)res);
  1037. } else {
  1038. res = (u8) d;
  1039. }
  1040. if (cnt == 1) {
  1041. /* Needs simplification. */
  1042. CONDITIONAL_SET_FLAG(
  1043. (((res & 0x80) == 0x80) ^
  1044. (ACCESS_FLAG(F_CF) != 0)),
  1045. /* was (M.x86.R_FLG&F_CF)==F_CF)), */
  1046. F_OF);
  1047. } else {
  1048. CLEAR_FLAG(F_OF);
  1049. }
  1050. } else {
  1051. res = 0;
  1052. CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80, F_CF);
  1053. CLEAR_FLAG(F_OF);
  1054. CLEAR_FLAG(F_SF);
  1055. SET_FLAG(F_PF);
  1056. SET_FLAG(F_ZF);
  1057. }
  1058. return (u8)res;
  1059. }
  1060. /****************************************************************************
  1061. REMARKS:
  1062. Implements the SHL instruction and side effects.
  1063. ****************************************************************************/
  1064. u16 shl_word(u16 d, u8 s)
  1065. {
  1066. unsigned int cnt, res, cf;
  1067. if (s < 16) {
  1068. cnt = s % 16;
  1069. if (cnt > 0) {
  1070. res = d << cnt;
  1071. cf = d & (1 << (16 - cnt));
  1072. CONDITIONAL_SET_FLAG(cf, F_CF);
  1073. set_szp_flags_16((u16)res);
  1074. } else {
  1075. res = (u16) d;
  1076. }
  1077. if (cnt == 1) {
  1078. CONDITIONAL_SET_FLAG(
  1079. (((res & 0x8000) == 0x8000) ^
  1080. (ACCESS_FLAG(F_CF) != 0)),
  1081. F_OF);
  1082. } else {
  1083. CLEAR_FLAG(F_OF);
  1084. }
  1085. } else {
  1086. res = 0;
  1087. CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
  1088. CLEAR_FLAG(F_OF);
  1089. CLEAR_FLAG(F_SF);
  1090. SET_FLAG(F_PF);
  1091. SET_FLAG(F_ZF);
  1092. }
  1093. return (u16)res;
  1094. }
  1095. /****************************************************************************
  1096. REMARKS:
  1097. Implements the SHL instruction and side effects.
  1098. ****************************************************************************/
  1099. u32 shl_long(u32 d, u8 s)
  1100. {
  1101. unsigned int cnt, res, cf;
  1102. if (s < 32) {
  1103. cnt = s % 32;
  1104. if (cnt > 0) {
  1105. res = d << cnt;
  1106. cf = d & (1 << (32 - cnt));
  1107. CONDITIONAL_SET_FLAG(cf, F_CF);
  1108. set_szp_flags_32((u32)res);
  1109. } else {
  1110. res = d;
  1111. }
  1112. if (cnt == 1) {
  1113. CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
  1114. (ACCESS_FLAG(F_CF) != 0)), F_OF);
  1115. } else {
  1116. CLEAR_FLAG(F_OF);
  1117. }
  1118. } else {
  1119. res = 0;
  1120. CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
  1121. CLEAR_FLAG(F_OF);
  1122. CLEAR_FLAG(F_SF);
  1123. SET_FLAG(F_PF);
  1124. SET_FLAG(F_ZF);
  1125. }
  1126. return res;
  1127. }
  1128. /****************************************************************************
  1129. REMARKS:
  1130. Implements the SHR instruction and side effects.
  1131. ****************************************************************************/
  1132. u8 shr_byte(u8 d, u8 s)
  1133. {
  1134. unsigned int cnt, res, cf;
  1135. if (s < 8) {
  1136. cnt = s % 8;
  1137. if (cnt > 0) {
  1138. cf = d & (1 << (cnt - 1));
  1139. res = d >> cnt;
  1140. CONDITIONAL_SET_FLAG(cf, F_CF);
  1141. set_szp_flags_8((u8)res);
  1142. } else {
  1143. res = (u8) d;
  1144. }
  1145. if (cnt == 1) {
  1146. CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
  1147. } else {
  1148. CLEAR_FLAG(F_OF);
  1149. }
  1150. } else {
  1151. res = 0;
  1152. CONDITIONAL_SET_FLAG((d >> (s-1)) & 0x1, F_CF);
  1153. CLEAR_FLAG(F_OF);
  1154. CLEAR_FLAG(F_SF);
  1155. SET_FLAG(F_PF);
  1156. SET_FLAG(F_ZF);
  1157. }
  1158. return (u8)res;
  1159. }
  1160. /****************************************************************************
  1161. REMARKS:
  1162. Implements the SHR instruction and side effects.
  1163. ****************************************************************************/
  1164. u16 shr_word(u16 d, u8 s)
  1165. {
  1166. unsigned int cnt, res, cf;
  1167. if (s < 16) {
  1168. cnt = s % 16;
  1169. if (cnt > 0) {
  1170. cf = d & (1 << (cnt - 1));
  1171. res = d >> cnt;
  1172. CONDITIONAL_SET_FLAG(cf, F_CF);
  1173. set_szp_flags_16((u16)res);
  1174. } else {
  1175. res = d;
  1176. }
  1177. if (cnt == 1) {
  1178. CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
  1179. } else {
  1180. CLEAR_FLAG(F_OF);
  1181. }
  1182. } else {
  1183. res = 0;
  1184. CLEAR_FLAG(F_CF);
  1185. CLEAR_FLAG(F_OF);
  1186. SET_FLAG(F_ZF);
  1187. CLEAR_FLAG(F_SF);
  1188. CLEAR_FLAG(F_PF);
  1189. }
  1190. return (u16)res;
  1191. }
  1192. /****************************************************************************
  1193. REMARKS:
  1194. Implements the SHR instruction and side effects.
  1195. ****************************************************************************/
  1196. u32 shr_long(u32 d, u8 s)
  1197. {
  1198. unsigned int cnt, res, cf;
  1199. if (s < 32) {
  1200. cnt = s % 32;
  1201. if (cnt > 0) {
  1202. cf = d & (1 << (cnt - 1));
  1203. res = d >> cnt;
  1204. CONDITIONAL_SET_FLAG(cf, F_CF);
  1205. set_szp_flags_32((u32)res);
  1206. } else {
  1207. res = d;
  1208. }
  1209. if (cnt == 1) {
  1210. CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
  1211. } else {
  1212. CLEAR_FLAG(F_OF);
  1213. }
  1214. } else {
  1215. res = 0;
  1216. CLEAR_FLAG(F_CF);
  1217. CLEAR_FLAG(F_OF);
  1218. SET_FLAG(F_ZF);
  1219. CLEAR_FLAG(F_SF);
  1220. CLEAR_FLAG(F_PF);
  1221. }
  1222. return res;
  1223. }
  1224. /****************************************************************************
  1225. REMARKS:
  1226. Implements the SAR instruction and side effects.
  1227. ****************************************************************************/
  1228. u8 sar_byte(u8 d, u8 s)
  1229. {
  1230. unsigned int cnt, res, cf, mask, sf;
  1231. res = d;
  1232. sf = d & 0x80;
  1233. cnt = s % 8;
  1234. if (cnt > 0 && cnt < 8) {
  1235. mask = (1 << (8 - cnt)) - 1;
  1236. cf = d & (1 << (cnt - 1));
  1237. res = (d >> cnt) & mask;
  1238. CONDITIONAL_SET_FLAG(cf, F_CF);
  1239. if (sf) {
  1240. res |= ~mask;
  1241. }
  1242. set_szp_flags_8((u8)res);
  1243. } else if (cnt >= 8) {
  1244. if (sf) {
  1245. res = 0xff;
  1246. SET_FLAG(F_CF);
  1247. CLEAR_FLAG(F_ZF);
  1248. SET_FLAG(F_SF);
  1249. SET_FLAG(F_PF);
  1250. } else {
  1251. res = 0;
  1252. CLEAR_FLAG(F_CF);
  1253. SET_FLAG(F_ZF);
  1254. CLEAR_FLAG(F_SF);
  1255. CLEAR_FLAG(F_PF);
  1256. }
  1257. }
  1258. return (u8)res;
  1259. }
  1260. /****************************************************************************
  1261. REMARKS:
  1262. Implements the SAR instruction and side effects.
  1263. ****************************************************************************/
  1264. u16 sar_word(u16 d, u8 s)
  1265. {
  1266. unsigned int cnt, res, cf, mask, sf;
  1267. sf = d & 0x8000;
  1268. cnt = s % 16;
  1269. res = d;
  1270. if (cnt > 0 && cnt < 16) {
  1271. mask = (1 << (16 - cnt)) - 1;
  1272. cf = d & (1 << (cnt - 1));
  1273. res = (d >> cnt) & mask;
  1274. CONDITIONAL_SET_FLAG(cf, F_CF);
  1275. if (sf) {
  1276. res |= ~mask;
  1277. }
  1278. set_szp_flags_16((u16)res);
  1279. } else if (cnt >= 16) {
  1280. if (sf) {
  1281. res = 0xffff;
  1282. SET_FLAG(F_CF);
  1283. CLEAR_FLAG(F_ZF);
  1284. SET_FLAG(F_SF);
  1285. SET_FLAG(F_PF);
  1286. } else {
  1287. res = 0;
  1288. CLEAR_FLAG(F_CF);
  1289. SET_FLAG(F_ZF);
  1290. CLEAR_FLAG(F_SF);
  1291. CLEAR_FLAG(F_PF);
  1292. }
  1293. }
  1294. return (u16)res;
  1295. }
  1296. /****************************************************************************
  1297. REMARKS:
  1298. Implements the SAR instruction and side effects.
  1299. ****************************************************************************/
  1300. u32 sar_long(u32 d, u8 s)
  1301. {
  1302. u32 cnt, res, cf, mask, sf;
  1303. sf = d & 0x80000000;
  1304. cnt = s % 32;
  1305. res = d;
  1306. if (cnt > 0 && cnt < 32) {
  1307. mask = (1 << (32 - cnt)) - 1;
  1308. cf = d & (1 << (cnt - 1));
  1309. res = (d >> cnt) & mask;
  1310. CONDITIONAL_SET_FLAG(cf, F_CF);
  1311. if (sf) {
  1312. res |= ~mask;
  1313. }
  1314. set_szp_flags_32(res);
  1315. } else if (cnt >= 32) {
  1316. if (sf) {
  1317. res = 0xffffffff;
  1318. SET_FLAG(F_CF);
  1319. CLEAR_FLAG(F_ZF);
  1320. SET_FLAG(F_SF);
  1321. SET_FLAG(F_PF);
  1322. } else {
  1323. res = 0;
  1324. CLEAR_FLAG(F_CF);
  1325. SET_FLAG(F_ZF);
  1326. CLEAR_FLAG(F_SF);
  1327. CLEAR_FLAG(F_PF);
  1328. }
  1329. }
  1330. return res;
  1331. }
  1332. /****************************************************************************
  1333. REMARKS:
  1334. Implements the SHLD instruction and side effects.
  1335. ****************************************************************************/
  1336. u16 shld_word (u16 d, u16 fill, u8 s)
  1337. {
  1338. unsigned int cnt, res, cf;
  1339. if (s < 16) {
  1340. cnt = s % 16;
  1341. if (cnt > 0) {
  1342. res = (d << cnt) | (fill >> (16-cnt));
  1343. cf = d & (1 << (16 - cnt));
  1344. CONDITIONAL_SET_FLAG(cf, F_CF);
  1345. set_szp_flags_16((u16)res);
  1346. } else {
  1347. res = d;
  1348. }
  1349. if (cnt == 1) {
  1350. CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
  1351. (ACCESS_FLAG(F_CF) != 0)), F_OF);
  1352. } else {
  1353. CLEAR_FLAG(F_OF);
  1354. }
  1355. } else {
  1356. res = 0;
  1357. CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
  1358. CLEAR_FLAG(F_OF);
  1359. CLEAR_FLAG(F_SF);
  1360. SET_FLAG(F_PF);
  1361. SET_FLAG(F_ZF);
  1362. }
  1363. return (u16)res;
  1364. }
  1365. /****************************************************************************
  1366. REMARKS:
  1367. Implements the SHLD instruction and side effects.
  1368. ****************************************************************************/
  1369. u32 shld_long (u32 d, u32 fill, u8 s)
  1370. {
  1371. unsigned int cnt, res, cf;
  1372. if (s < 32) {
  1373. cnt = s % 32;
  1374. if (cnt > 0) {
  1375. res = (d << cnt) | (fill >> (32-cnt));
  1376. cf = d & (1 << (32 - cnt));
  1377. CONDITIONAL_SET_FLAG(cf, F_CF);
  1378. set_szp_flags_32((u32)res);
  1379. } else {
  1380. res = d;
  1381. }
  1382. if (cnt == 1) {
  1383. CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
  1384. (ACCESS_FLAG(F_CF) != 0)), F_OF);
  1385. } else {
  1386. CLEAR_FLAG(F_OF);
  1387. }
  1388. } else {
  1389. res = 0;
  1390. CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
  1391. CLEAR_FLAG(F_OF);
  1392. CLEAR_FLAG(F_SF);
  1393. SET_FLAG(F_PF);
  1394. SET_FLAG(F_ZF);
  1395. }
  1396. return res;
  1397. }
  1398. /****************************************************************************
  1399. REMARKS:
  1400. Implements the SHRD instruction and side effects.
  1401. ****************************************************************************/
  1402. u16 shrd_word (u16 d, u16 fill, u8 s)
  1403. {
  1404. unsigned int cnt, res, cf;
  1405. if (s < 16) {
  1406. cnt = s % 16;
  1407. if (cnt > 0) {
  1408. cf = d & (1 << (cnt - 1));
  1409. res = (d >> cnt) | (fill << (16 - cnt));
  1410. CONDITIONAL_SET_FLAG(cf, F_CF);
  1411. set_szp_flags_16((u16)res);
  1412. } else {
  1413. res = d;
  1414. }
  1415. if (cnt == 1) {
  1416. CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
  1417. } else {
  1418. CLEAR_FLAG(F_OF);
  1419. }
  1420. } else {
  1421. res = 0;
  1422. CLEAR_FLAG(F_CF);
  1423. CLEAR_FLAG(F_OF);
  1424. SET_FLAG(F_ZF);
  1425. CLEAR_FLAG(F_SF);
  1426. CLEAR_FLAG(F_PF);
  1427. }
  1428. return (u16)res;
  1429. }
  1430. /****************************************************************************
  1431. REMARKS:
  1432. Implements the SHRD instruction and side effects.
  1433. ****************************************************************************/
  1434. u32 shrd_long (u32 d, u32 fill, u8 s)
  1435. {
  1436. unsigned int cnt, res, cf;
  1437. if (s < 32) {
  1438. cnt = s % 32;
  1439. if (cnt > 0) {
  1440. cf = d & (1 << (cnt - 1));
  1441. res = (d >> cnt) | (fill << (32 - cnt));
  1442. CONDITIONAL_SET_FLAG(cf, F_CF);
  1443. set_szp_flags_32((u32)res);
  1444. } else {
  1445. res = d;
  1446. }
  1447. if (cnt == 1) {
  1448. CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
  1449. } else {
  1450. CLEAR_FLAG(F_OF);
  1451. }
  1452. } else {
  1453. res = 0;
  1454. CLEAR_FLAG(F_CF);
  1455. CLEAR_FLAG(F_OF);
  1456. SET_FLAG(F_ZF);
  1457. CLEAR_FLAG(F_SF);
  1458. CLEAR_FLAG(F_PF);
  1459. }
  1460. return res;
  1461. }
  1462. /****************************************************************************
  1463. REMARKS:
  1464. Implements the SBB instruction and side effects.
  1465. ****************************************************************************/
  1466. u8 sbb_byte(u8 d, u8 s)
  1467. {
  1468. u32 res; /* all operands in native machine order */
  1469. u32 bc;
  1470. if (ACCESS_FLAG(F_CF))
  1471. res = d - s - 1;
  1472. else
  1473. res = d - s;
  1474. set_szp_flags_8((u8)res);
  1475. /* calculate the borrow chain. See note at top */
  1476. bc = (res & (~d | s)) | (~d & s);
  1477. CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
  1478. CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
  1479. CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
  1480. return (u8)res;
  1481. }
  1482. /****************************************************************************
  1483. REMARKS:
  1484. Implements the SBB instruction and side effects.
  1485. ****************************************************************************/
  1486. u16 sbb_word(u16 d, u16 s)
  1487. {
  1488. u32 res; /* all operands in native machine order */
  1489. u32 bc;
  1490. if (ACCESS_FLAG(F_CF))
  1491. res = d - s - 1;
  1492. else
  1493. res = d - s;
  1494. set_szp_flags_16((u16)res);
  1495. /* calculate the borrow chain. See note at top */
  1496. bc = (res & (~d | s)) | (~d & s);
  1497. CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
  1498. CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
  1499. CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
  1500. return (u16)res;
  1501. }
  1502. /****************************************************************************
  1503. REMARKS:
  1504. Implements the SBB instruction and side effects.
  1505. ****************************************************************************/
  1506. u32 sbb_long(u32 d, u32 s)
  1507. {
  1508. u32 res; /* all operands in native machine order */
  1509. u32 bc;
  1510. if (ACCESS_FLAG(F_CF))
  1511. res = d - s - 1;
  1512. else
  1513. res = d - s;
  1514. set_szp_flags_32(res);
  1515. /* calculate the borrow chain. See note at top */
  1516. bc = (res & (~d | s)) | (~d & s);
  1517. CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
  1518. CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
  1519. CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
  1520. return res;
  1521. }
  1522. /****************************************************************************
  1523. REMARKS:
  1524. Implements the SUB instruction and side effects.
  1525. ****************************************************************************/
  1526. u8 sub_byte(u8 d, u8 s)
  1527. {
  1528. u32 res; /* all operands in native machine order */
  1529. u32 bc;
  1530. res = d - s;
  1531. set_szp_flags_8((u8)res);
  1532. /* calculate the borrow chain. See note at top */
  1533. bc = (res & (~d | s)) | (~d & s);
  1534. CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
  1535. CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
  1536. CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
  1537. return (u8)res;
  1538. }
  1539. /****************************************************************************
  1540. REMARKS:
  1541. Implements the SUB instruction and side effects.
  1542. ****************************************************************************/
  1543. u16 sub_word(u16 d, u16 s)
  1544. {
  1545. u32 res; /* all operands in native machine order */
  1546. u32 bc;
  1547. res = d - s;
  1548. set_szp_flags_16((u16)res);
  1549. /* calculate the borrow chain. See note at top */
  1550. bc = (res & (~d | s)) | (~d & s);
  1551. CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
  1552. CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
  1553. CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
  1554. return (u16)res;
  1555. }
  1556. /****************************************************************************
  1557. REMARKS:
  1558. Implements the SUB instruction and side effects.
  1559. ****************************************************************************/
  1560. u32 sub_long(u32 d, u32 s)
  1561. {
  1562. u32 res; /* all operands in native machine order */
  1563. u32 bc;
  1564. res = d - s;
  1565. set_szp_flags_32(res);
  1566. /* calculate the borrow chain. See note at top */
  1567. bc = (res & (~d | s)) | (~d & s);
  1568. CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
  1569. CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
  1570. CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
  1571. return res;
  1572. }
  1573. /****************************************************************************
  1574. REMARKS:
  1575. Implements the TEST instruction and side effects.
  1576. ****************************************************************************/
  1577. void test_byte(u8 d, u8 s)
  1578. {
  1579. u32 res; /* all operands in native machine order */
  1580. res = d & s;
  1581. CLEAR_FLAG(F_OF);
  1582. set_szp_flags_8((u8)res);
  1583. /* AF == dont care */
  1584. CLEAR_FLAG(F_CF);
  1585. }
  1586. /****************************************************************************
  1587. REMARKS:
  1588. Implements the TEST instruction and side effects.
  1589. ****************************************************************************/
  1590. void test_word(u16 d, u16 s)
  1591. {
  1592. u32 res; /* all operands in native machine order */
  1593. res = d & s;
  1594. CLEAR_FLAG(F_OF);
  1595. set_szp_flags_16((u16)res);
  1596. /* AF == dont care */
  1597. CLEAR_FLAG(F_CF);
  1598. }
  1599. /****************************************************************************
  1600. REMARKS:
  1601. Implements the TEST instruction and side effects.
  1602. ****************************************************************************/
  1603. void test_long(u32 d, u32 s)
  1604. {
  1605. u32 res; /* all operands in native machine order */
  1606. res = d & s;
  1607. CLEAR_FLAG(F_OF);
  1608. set_szp_flags_32(res);
  1609. /* AF == dont care */
  1610. CLEAR_FLAG(F_CF);
  1611. }
  1612. /****************************************************************************
  1613. REMARKS:
  1614. Implements the XOR instruction and side effects.
  1615. ****************************************************************************/
  1616. u8 xor_byte(u8 d, u8 s)
  1617. {
  1618. u8 res; /* all operands in native machine order */
  1619. res = d ^ s;
  1620. no_carry_byte_side_eff(res);
  1621. return res;
  1622. }
  1623. /****************************************************************************
  1624. REMARKS:
  1625. Implements the XOR instruction and side effects.
  1626. ****************************************************************************/
  1627. u16 xor_word(u16 d, u16 s)
  1628. {
  1629. u16 res; /* all operands in native machine order */
  1630. res = d ^ s;
  1631. no_carry_word_side_eff(res);
  1632. return res;
  1633. }
  1634. /****************************************************************************
  1635. REMARKS:
  1636. Implements the XOR instruction and side effects.
  1637. ****************************************************************************/
  1638. u32 xor_long(u32 d, u32 s)
  1639. {
  1640. u32 res; /* all operands in native machine order */
  1641. res = d ^ s;
  1642. no_carry_long_side_eff(res);
  1643. return res;
  1644. }
  1645. /****************************************************************************
  1646. REMARKS:
  1647. Implements the IMUL instruction and side effects.
  1648. ****************************************************************************/
  1649. void imul_byte(u8 s)
  1650. {
  1651. s16 res = (s16)((s8)M.x86.R_AL * (s8)s);
  1652. M.x86.R_AX = res;
  1653. if (((M.x86.R_AL & 0x80) == 0 && M.x86.R_AH == 0x00) ||
  1654. ((M.x86.R_AL & 0x80) != 0 && M.x86.R_AH == 0xFF)) {
  1655. CLEAR_FLAG(F_CF);
  1656. CLEAR_FLAG(F_OF);
  1657. } else {
  1658. SET_FLAG(F_CF);
  1659. SET_FLAG(F_OF);
  1660. }
  1661. }
  1662. /****************************************************************************
  1663. REMARKS:
  1664. Implements the IMUL instruction and side effects.
  1665. ****************************************************************************/
  1666. void imul_word(u16 s)
  1667. {
  1668. s32 res = (s16)M.x86.R_AX * (s16)s;
  1669. M.x86.R_AX = (u16)res;
  1670. M.x86.R_DX = (u16)(res >> 16);
  1671. if (((M.x86.R_AX & 0x8000) == 0 && M.x86.R_DX == 0x0000) ||
  1672. ((M.x86.R_AX & 0x8000) != 0 && M.x86.R_DX == 0xFFFF)) {
  1673. CLEAR_FLAG(F_CF);
  1674. CLEAR_FLAG(F_OF);
  1675. } else {
  1676. SET_FLAG(F_CF);
  1677. SET_FLAG(F_OF);
  1678. }
  1679. }
  1680. /****************************************************************************
  1681. REMARKS:
  1682. Implements the IMUL instruction and side effects.
  1683. ****************************************************************************/
  1684. void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s)
  1685. {
  1686. #ifdef __HAS_LONG_LONG__
  1687. s64 res = (s32)d * (s32)s;
  1688. *res_lo = (u32)res;
  1689. *res_hi = (u32)(res >> 32);
  1690. #else
  1691. u32 d_lo,d_hi,d_sign;
  1692. u32 s_lo,s_hi,s_sign;
  1693. u32 rlo_lo,rlo_hi,rhi_lo;
  1694. if ((d_sign = d & 0x80000000) != 0)
  1695. d = -d;
  1696. d_lo = d & 0xFFFF;
  1697. d_hi = d >> 16;
  1698. if ((s_sign = s & 0x80000000) != 0)
  1699. s = -s;
  1700. s_lo = s & 0xFFFF;
  1701. s_hi = s >> 16;
  1702. rlo_lo = d_lo * s_lo;
  1703. rlo_hi = (d_hi * s_lo + d_lo * s_hi) + (rlo_lo >> 16);
  1704. rhi_lo = d_hi * s_hi + (rlo_hi >> 16);
  1705. *res_lo = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
  1706. *res_hi = rhi_lo;
  1707. if (d_sign != s_sign) {
  1708. d = ~*res_lo;
  1709. s = (((d & 0xFFFF) + 1) >> 16) + (d >> 16);
  1710. *res_lo = ~*res_lo+1;
  1711. *res_hi = ~*res_hi+(s >> 16);
  1712. }
  1713. #endif
  1714. }
  1715. /****************************************************************************
  1716. REMARKS:
  1717. Implements the IMUL instruction and side effects.
  1718. ****************************************************************************/
  1719. void imul_long(u32 s)
  1720. {
  1721. imul_long_direct(&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s);
  1722. if (((M.x86.R_EAX & 0x80000000) == 0 && M.x86.R_EDX == 0x00000000) ||
  1723. ((M.x86.R_EAX & 0x80000000) != 0 && M.x86.R_EDX == 0xFFFFFFFF)) {
  1724. CLEAR_FLAG(F_CF);
  1725. CLEAR_FLAG(F_OF);
  1726. } else {
  1727. SET_FLAG(F_CF);
  1728. SET_FLAG(F_OF);
  1729. }
  1730. }
  1731. /****************************************************************************
  1732. REMARKS:
  1733. Implements the MUL instruction and side effects.
  1734. ****************************************************************************/
  1735. void mul_byte(u8 s)
  1736. {
  1737. u16 res = (u16)(M.x86.R_AL * s);
  1738. M.x86.R_AX = res;
  1739. if (M.x86.R_AH == 0) {
  1740. CLEAR_FLAG(F_CF);
  1741. CLEAR_FLAG(F_OF);
  1742. } else {
  1743. SET_FLAG(F_CF);
  1744. SET_FLAG(F_OF);
  1745. }
  1746. }
  1747. /****************************************************************************
  1748. REMARKS:
  1749. Implements the MUL instruction and side effects.
  1750. ****************************************************************************/
  1751. void mul_word(u16 s)
  1752. {
  1753. u32 res = M.x86.R_AX * s;
  1754. M.x86.R_AX = (u16)res;
  1755. M.x86.R_DX = (u16)(res >> 16);
  1756. if (M.x86.R_DX == 0) {
  1757. CLEAR_FLAG(F_CF);
  1758. CLEAR_FLAG(F_OF);
  1759. } else {
  1760. SET_FLAG(F_CF);
  1761. SET_FLAG(F_OF);
  1762. }
  1763. }
  1764. /****************************************************************************
  1765. REMARKS:
  1766. Implements the MUL instruction and side effects.
  1767. ****************************************************************************/
  1768. void mul_long(u32 s)
  1769. {
  1770. #ifdef __HAS_LONG_LONG__
  1771. u64 res = (u32)M.x86.R_EAX * (u32)s;
  1772. M.x86.R_EAX = (u32)res;
  1773. M.x86.R_EDX = (u32)(res >> 32);
  1774. #else
  1775. u32 a,a_lo,a_hi;
  1776. u32 s_lo,s_hi;
  1777. u32 rlo_lo,rlo_hi,rhi_lo;
  1778. a = M.x86.R_EAX;
  1779. a_lo = a & 0xFFFF;
  1780. a_hi = a >> 16;
  1781. s_lo = s & 0xFFFF;
  1782. s_hi = s >> 16;
  1783. rlo_lo = a_lo * s_lo;
  1784. rlo_hi = (a_hi * s_lo + a_lo * s_hi) + (rlo_lo >> 16);
  1785. rhi_lo = a_hi * s_hi + (rlo_hi >> 16);
  1786. M.x86.R_EAX = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
  1787. M.x86.R_EDX = rhi_lo;
  1788. #endif
  1789. if (M.x86.R_EDX == 0) {
  1790. CLEAR_FLAG(F_CF);
  1791. CLEAR_FLAG(F_OF);
  1792. } else {
  1793. SET_FLAG(F_CF);
  1794. SET_FLAG(F_OF);
  1795. }
  1796. }
  1797. /****************************************************************************
  1798. REMARKS:
  1799. Implements the IDIV instruction and side effects.
  1800. ****************************************************************************/
  1801. void idiv_byte(u8 s)
  1802. {
  1803. s32 dvd, div, mod;
  1804. dvd = (s16)M.x86.R_AX;
  1805. if (s == 0) {
  1806. x86emu_intr_raise(0);
  1807. return;
  1808. }
  1809. div = dvd / (s8)s;
  1810. mod = dvd % (s8)s;
  1811. if (abs(div) > 0x7f) {
  1812. x86emu_intr_raise(0);
  1813. return;
  1814. }
  1815. M.x86.R_AL = (s8) div;
  1816. M.x86.R_AH = (s8) mod;
  1817. }
  1818. /****************************************************************************
  1819. REMARKS:
  1820. Implements the IDIV instruction and side effects.
  1821. ****************************************************************************/
  1822. void idiv_word(u16 s)
  1823. {
  1824. s32 dvd, div, mod;
  1825. dvd = (((s32)M.x86.R_DX) << 16) | M.x86.R_AX;
  1826. if (s == 0) {
  1827. x86emu_intr_raise(0);
  1828. return;
  1829. }
  1830. div = dvd / (s16)s;
  1831. mod = dvd % (s16)s;
  1832. if (abs(div) > 0x7fff) {
  1833. x86emu_intr_raise(0);
  1834. return;
  1835. }
  1836. CLEAR_FLAG(F_CF);
  1837. CLEAR_FLAG(F_SF);
  1838. CONDITIONAL_SET_FLAG(div == 0, F_ZF);
  1839. set_parity_flag(mod);
  1840. M.x86.R_AX = (u16)div;
  1841. M.x86.R_DX = (u16)mod;
  1842. }
  1843. /****************************************************************************
  1844. REMARKS:
  1845. Implements the IDIV instruction and side effects.
  1846. ****************************************************************************/
  1847. void idiv_long(u32 s)
  1848. {
  1849. #ifdef __HAS_LONG_LONG__
  1850. s64 dvd, div, mod;
  1851. dvd = (((s64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
  1852. if (s == 0) {
  1853. x86emu_intr_raise(0);
  1854. return;
  1855. }
  1856. div = dvd / (s32)s;
  1857. mod = dvd % (s32)s;
  1858. if (abs(div) > 0x7fffffff) {
  1859. x86emu_intr_raise(0);
  1860. return;
  1861. }
  1862. #else
  1863. s32 div = 0, mod;
  1864. s32 h_dvd = M.x86.R_EDX;
  1865. u32 l_dvd = M.x86.R_EAX;
  1866. u32 abs_s = s & 0x7FFFFFFF;
  1867. u32 abs_h_dvd = h_dvd & 0x7FFFFFFF;
  1868. u32 h_s = abs_s >> 1;
  1869. u32 l_s = abs_s << 31;
  1870. int counter = 31;
  1871. int carry;
  1872. if (s == 0) {
  1873. x86emu_intr_raise(0);
  1874. return;
  1875. }
  1876. do {
  1877. div <<= 1;
  1878. carry = (l_dvd >= l_s) ? 0 : 1;
  1879. if (abs_h_dvd < (h_s + carry)) {
  1880. h_s >>= 1;
  1881. l_s = abs_s << (--counter);
  1882. continue;
  1883. } else {
  1884. abs_h_dvd -= (h_s + carry);
  1885. l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
  1886. : (l_dvd - l_s);
  1887. h_s >>= 1;
  1888. l_s = abs_s << (--counter);
  1889. div |= 1;
  1890. continue;
  1891. }
  1892. } while (counter > -1);
  1893. /* overflow */
  1894. if (abs_h_dvd || (l_dvd > abs_s)) {
  1895. x86emu_intr_raise(0);
  1896. return;
  1897. }
  1898. /* sign */
  1899. div |= ((h_dvd & 0x10000000) ^ (s & 0x10000000));
  1900. mod = l_dvd;
  1901. #endif
  1902. CLEAR_FLAG(F_CF);
  1903. CLEAR_FLAG(F_AF);
  1904. CLEAR_FLAG(F_SF);
  1905. SET_FLAG(F_ZF);
  1906. set_parity_flag(mod);
  1907. M.x86.R_EAX = (u32)div;
  1908. M.x86.R_EDX = (u32)mod;
  1909. }
  1910. /****************************************************************************
  1911. REMARKS:
  1912. Implements the DIV instruction and side effects.
  1913. ****************************************************************************/
  1914. void div_byte(u8 s)
  1915. {
  1916. u32 dvd, div, mod;
  1917. dvd = M.x86.R_AX;
  1918. if (s == 0) {
  1919. x86emu_intr_raise(0);
  1920. return;
  1921. }
  1922. div = dvd / (u8)s;
  1923. mod = dvd % (u8)s;
  1924. if (abs(div) > 0xff) {
  1925. x86emu_intr_raise(0);
  1926. return;
  1927. }
  1928. M.x86.R_AL = (u8)div;
  1929. M.x86.R_AH = (u8)mod;
  1930. }
  1931. /****************************************************************************
  1932. REMARKS:
  1933. Implements the DIV instruction and side effects.
  1934. ****************************************************************************/
  1935. void div_word(u16 s)
  1936. {
  1937. u32 dvd, div, mod;
  1938. dvd = (((u32)M.x86.R_DX) << 16) | M.x86.R_AX;
  1939. if (s == 0) {
  1940. x86emu_intr_raise(0);
  1941. return;
  1942. }
  1943. div = dvd / (u16)s;
  1944. mod = dvd % (u16)s;
  1945. if (abs(div) > 0xffff) {
  1946. x86emu_intr_raise(0);
  1947. return;
  1948. }
  1949. CLEAR_FLAG(F_CF);
  1950. CLEAR_FLAG(F_SF);
  1951. CONDITIONAL_SET_FLAG(div == 0, F_ZF);
  1952. set_parity_flag(mod);
  1953. M.x86.R_AX = (u16)div;
  1954. M.x86.R_DX = (u16)mod;
  1955. }
  1956. /****************************************************************************
  1957. REMARKS:
  1958. Implements the DIV instruction and side effects.
  1959. ****************************************************************************/
  1960. void div_long(u32 s)
  1961. {
  1962. #ifdef __HAS_LONG_LONG__
  1963. u64 dvd, div, mod;
  1964. dvd = (((u64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
  1965. if (s == 0) {
  1966. x86emu_intr_raise(0);
  1967. return;
  1968. }
  1969. div = dvd / (u32)s;
  1970. mod = dvd % (u32)s;
  1971. if (abs(div) > 0xffffffff) {
  1972. x86emu_intr_raise(0);
  1973. return;
  1974. }
  1975. #else
  1976. s32 div = 0, mod;
  1977. s32 h_dvd = M.x86.R_EDX;
  1978. u32 l_dvd = M.x86.R_EAX;
  1979. u32 h_s = s;
  1980. u32 l_s = 0;
  1981. int counter = 32;
  1982. int carry;
  1983. if (s == 0) {
  1984. x86emu_intr_raise(0);
  1985. return;
  1986. }
  1987. do {
  1988. div <<= 1;
  1989. carry = (l_dvd >= l_s) ? 0 : 1;
  1990. if (h_dvd < (h_s + carry)) {
  1991. h_s >>= 1;
  1992. l_s = s << (--counter);
  1993. continue;
  1994. } else {
  1995. h_dvd -= (h_s + carry);
  1996. l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
  1997. : (l_dvd - l_s);
  1998. h_s >>= 1;
  1999. l_s = s << (--counter);
  2000. div |= 1;
  2001. continue;
  2002. }
  2003. } while (counter > -1);
  2004. /* overflow */
  2005. if (h_dvd || (l_dvd > s)) {
  2006. x86emu_intr_raise(0);
  2007. return;
  2008. }
  2009. mod = l_dvd;
  2010. #endif
  2011. CLEAR_FLAG(F_CF);
  2012. CLEAR_FLAG(F_AF);
  2013. CLEAR_FLAG(F_SF);
  2014. SET_FLAG(F_ZF);
  2015. set_parity_flag(mod);
  2016. M.x86.R_EAX = (u32)div;
  2017. M.x86.R_EDX = (u32)mod;
  2018. }
  2019. /****************************************************************************
  2020. REMARKS:
  2021. Implements the IN string instruction and side effects.
  2022. ****************************************************************************/
  2023. static void single_in(int size)
  2024. {
  2025. if(size == 1)
  2026. store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inb)(M.x86.R_DX));
  2027. else if (size == 2)
  2028. store_data_word_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inw)(M.x86.R_DX));
  2029. else
  2030. store_data_long_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inl)(M.x86.R_DX));
  2031. }
  2032. void ins(int size)
  2033. {
  2034. int inc = size;
  2035. if (ACCESS_FLAG(F_DF)) {
  2036. inc = -size;
  2037. }
  2038. if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
  2039. /* dont care whether REPE or REPNE */
  2040. /* in until CX is ZERO. */
  2041. u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
  2042. M.x86.R_ECX : M.x86.R_CX);
  2043. while (count--) {
  2044. single_in(size);
  2045. M.x86.R_DI += inc;
  2046. }
  2047. M.x86.R_CX = 0;
  2048. if (M.x86.mode & SYSMODE_PREFIX_DATA) {
  2049. M.x86.R_ECX = 0;
  2050. }
  2051. M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
  2052. } else {
  2053. single_in(size);
  2054. M.x86.R_DI += inc;
  2055. }
  2056. }
  2057. /****************************************************************************
  2058. REMARKS:
  2059. Implements the OUT string instruction and side effects.
  2060. ****************************************************************************/
  2061. static void single_out(int size)
  2062. {
  2063. if(size == 1)
  2064. (*sys_outb)(M.x86.R_DX,fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
  2065. else if (size == 2)
  2066. (*sys_outw)(M.x86.R_DX,fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
  2067. else
  2068. (*sys_outl)(M.x86.R_DX,fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
  2069. }
  2070. void outs(int size)
  2071. {
  2072. int inc = size;
  2073. if (ACCESS_FLAG(F_DF)) {
  2074. inc = -size;
  2075. }
  2076. if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
  2077. /* dont care whether REPE or REPNE */
  2078. /* out until CX is ZERO. */
  2079. u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
  2080. M.x86.R_ECX : M.x86.R_CX);
  2081. while (count--) {
  2082. single_out(size);
  2083. M.x86.R_SI += inc;
  2084. }
  2085. M.x86.R_CX = 0;
  2086. if (M.x86.mode & SYSMODE_PREFIX_DATA) {
  2087. M.x86.R_ECX = 0;
  2088. }
  2089. M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
  2090. } else {
  2091. single_out(size);
  2092. M.x86.R_SI += inc;
  2093. }
  2094. }
  2095. /****************************************************************************
  2096. PARAMETERS:
  2097. addr - Address to fetch word from
  2098. REMARKS:
  2099. Fetches a word from emulator memory using an absolute address.
  2100. ****************************************************************************/
  2101. u16 mem_access_word(int addr)
  2102. {
  2103. DB( if (CHECK_MEM_ACCESS())
  2104. x86emu_check_mem_access(addr);)
  2105. return (*sys_rdw)(addr);
  2106. }
  2107. /****************************************************************************
  2108. REMARKS:
  2109. Pushes a word onto the stack.
  2110. NOTE: Do not inline this, as (*sys_wrX) is already inline!
  2111. ****************************************************************************/
  2112. void push_word(u16 w)
  2113. {
  2114. DB( if (CHECK_SP_ACCESS())
  2115. x86emu_check_sp_access();)
  2116. M.x86.R_SP -= 2;
  2117. (*sys_wrw)(((u32)M.x86.R_SS << 4) + M.x86.R_SP, w);
  2118. }
  2119. /****************************************************************************
  2120. REMARKS:
  2121. Pushes a long onto the stack.
  2122. NOTE: Do not inline this, as (*sys_wrX) is already inline!
  2123. ****************************************************************************/
  2124. void push_long(u32 w)
  2125. {
  2126. DB( if (CHECK_SP_ACCESS())
  2127. x86emu_check_sp_access();)
  2128. M.x86.R_SP -= 4;
  2129. (*sys_wrl)(((u32)M.x86.R_SS << 4) + M.x86.R_SP, w);
  2130. }
  2131. /****************************************************************************
  2132. REMARKS:
  2133. Pops a word from the stack.
  2134. NOTE: Do not inline this, as (*sys_rdX) is already inline!
  2135. ****************************************************************************/
  2136. u16 pop_word(void)
  2137. {
  2138. u16 res;
  2139. DB( if (CHECK_SP_ACCESS())
  2140. x86emu_check_sp_access();)
  2141. res = (*sys_rdw)(((u32)M.x86.R_SS << 4) + M.x86.R_SP);
  2142. M.x86.R_SP += 2;
  2143. return res;
  2144. }
  2145. /****************************************************************************
  2146. REMARKS:
  2147. Pops a long from the stack.
  2148. NOTE: Do not inline this, as (*sys_rdX) is already inline!
  2149. ****************************************************************************/
  2150. u32 pop_long(void)
  2151. {
  2152. u32 res;
  2153. DB( if (CHECK_SP_ACCESS())
  2154. x86emu_check_sp_access();)
  2155. res = (*sys_rdl)(((u32)M.x86.R_SS << 4) + M.x86.R_SP);
  2156. M.x86.R_SP += 4;
  2157. return res;
  2158. }