Lua 5.3 didn't need an x86 emulator. But now, it has one regardless.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

emu_core.lua 60KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240
  1. local ram_640k = {}
  2. local io_ports = {}
  3. local ram_rom = {}
  4. local run_one = nil
  5. local opc = 0
  6. RAM = {}
  7. if memory_preallocate then
  8. local max_mem = 0xA0000
  9. if reduced_memory_mode > 0 then max_mem = max_mem >> reduced_memory_mode end
  10. for i=1,max_mem do
  11. ram_640k[i]=0
  12. end
  13. end
  14. if reduced_memory_mode > 0 then
  15. local rmm_mask = (1 << reduced_memory_mode) - 1
  16. local rmm = reduced_memory_mode
  17. setmetatable(RAM, {
  18. __index = function(t, key)
  19. if (key < 0xA0000) then
  20. local k = (key >> rmm) + 1
  21. return ((ram_640k[k] or 0) >> ((key & rmm_mask) << 3)) & 0xFF
  22. elseif (key < 0xC0000) then
  23. return video_vram_read(key)
  24. elseif (key >= 0xF0000 and key < 0x100000) then
  25. local k = ((key - 0xF0000) >> rmm) + 1
  26. return ((ram_rom[k] or 0) >> ((key & rmm_mask) << 3)) & 0xFF
  27. else
  28. return 0xFF
  29. end
  30. end,
  31. __newindex = function(t, key, value)
  32. if (key < 0xA0000) then
  33. local shift = ((key & rmm_mask) << 3)
  34. local k = (key >> rmm) + 1
  35. local mask = 255 << shift
  36. local nmask = mask ~ (-1)
  37. ram_640k[k] = ((ram_640k[k] or 0) & nmask) | ((value & 0xFF) << shift)
  38. elseif (key < 0xC0000) then
  39. video_vram_write(key, value)
  40. elseif (key >= 0xF0000 and key < 0x100000) then
  41. local shift = ((key & rmm_mask) << 3)
  42. local k = ((key - 0xF0000) >> rmm) + 1
  43. local mask = 255 << shift
  44. local nmask = mask ~ (-1)
  45. ram_rom[k] = ((ram_rom[k] or 0) & nmask) | ((value & 0xFF) << shift)
  46. end
  47. end
  48. })
  49. rawset(RAM, "r16", function(ram, key)
  50. if (key < 0x9FFFE) and ((key & rmm_mask) < rmm_mask) then
  51. local k = (key >> rmm) + 1
  52. return ((ram_640k[k] or 0) >> ((key & rmm_mask) << 3)) & 0xFFFF
  53. else
  54. return ram[key] | (ram[key + 1] << 8)
  55. end
  56. end)
  57. rawset(RAM, "w16", function(ram, key, value)
  58. if (key < 0x9FFFE) and ((key & rmm_mask) < rmm_mask) then
  59. local k = (key >> rmm) + 1
  60. local shift = ((key & rmm_mask) << 3)
  61. local mask = 0xFFFF << shift
  62. local nmask = mask ~ (-1)
  63. ram_640k[k] = ((ram_640k[k] or 0) & nmask) | ((value & 0xFFFF) << shift)
  64. else
  65. ram[key] = (value & 0xFF)
  66. ram[key + 1] = (value >> 8)
  67. end
  68. end)
  69. else
  70. setmetatable(RAM, {
  71. __index = function(t, key)
  72. if (key < 0xA0000) then
  73. return ram_640k[key + 1] or 0
  74. elseif (key < 0xC0000) then
  75. return video_vram_read(key)
  76. elseif (key >= 0xF0000 and key < 0x100000) then
  77. return ram_rom[key - 0xEFFFF] or 0x00
  78. else
  79. return 0xFF
  80. end
  81. end,
  82. __newindex = function(t, key, value)
  83. if (key < 0xA0000) then
  84. ram_640k[key + 1] = value
  85. elseif (key < 0xC0000) then
  86. video_vram_write(key, value)
  87. elseif (key >= 0xF0000 and key < 0x100000) then
  88. ram_rom[key - 0xEFFFF] = value
  89. end
  90. end
  91. })
  92. rawset(RAM, "r16", function(ram, key)
  93. if key < 0x9FFFF then
  94. return (ram_640k[key + 1] or 0) | ((ram_640k[key + 2] or 0) << 8)
  95. else
  96. return ram[key] | (ram[key + 1] << 8)
  97. end
  98. end)
  99. rawset(RAM, "w16", function(ram, key, value)
  100. if key < 0x9FFFF then
  101. ram_640k[key + 1] = (value & 0xFF)
  102. ram_640k[key + 2] = (value >> 8)
  103. else
  104. ram[key] = (value & 0xFF)
  105. ram[key + 1] = (value >> 8)
  106. end
  107. end)
  108. end
  109. rawset(RAM, "w32", function(ram, key, value)
  110. ram[key] = (value & 0xFF)
  111. ram[key + 1] = (value >> 8) & 0xFF
  112. ram[key + 2] = (value >> 16) & 0xFF
  113. ram[key + 3] = (value >> 24)
  114. end)
  115. rawset(RAM, "r32", function(ram, key)
  116. return ram[key] | (ram[key + 1] << 8) | (ram[key + 2] << 16) | (ram[key + 3] << 32)
  117. end)
  118. SEG_ES = 0
  119. SEG_CS = 1
  120. SEG_SS = 2
  121. SEG_DS = 3
  122. -- ax,cx,dx,bx,sp,bp,si,di
  123. local CPU_REGS = {0,0,0,0,0,0,0,0}
  124. -- es,cs,ss,ds,fs,gs
  125. local CPU_SEGMENTS = {0,0,0,0,0,0}
  126. local CPU_IP = 0
  127. local CPU_FLAGS = 0
  128. local CPU_SEGMOD = nil
  129. local CPU_HALTED = false
  130. local CPU_INTQUEUE = {}
  131. local CPU_HASINT = false
  132. CPU = {
  133. regs = CPU_REGS,
  134. segments = CPU_SEGMENTS,
  135. flags = CPU_FLAGS
  136. }
  137. local CPU = CPU
  138. local RAM = RAM
  139. local SEG_ES = SEG_ES
  140. local SEG_SS = SEG_SS
  141. local SEG_CS = SEG_CS
  142. local SEG_DS = SEG_DS
  143. -- initialize ivt (early, so it can be overridden)
  144. for i=0,255 do
  145. RAM:w16(i*4, 0x1100 + i)
  146. RAM:w16(i*4 + 2, 0xF000)
  147. end
  148. function seg(s, v)
  149. return (CPU_SEGMENTS[s+1]<<4) + v
  150. end
  151. function segmd(s, v)
  152. return (CPU_SEGMENTS[(CPU_SEGMOD or (s+1))]<<4) + v
  153. end
  154. local function cpu_advance_ip()
  155. local ip = ((CPU_SEGMENTS[(SEG_CS)+1]<<4)+(CPU_IP))
  156. CPU_IP = (CPU_IP + 1) & 0xFFFF
  157. return RAM[ip]
  158. end
  159. local function cpu_advance_ip16()
  160. local ip = ((CPU_SEGMENTS[(SEG_CS)+1]<<4)+(CPU_IP))
  161. CPU_IP = (CPU_IP + 2) & 0xFFFF
  162. return RAM:r16(ip)
  163. end
  164. local function to_s8(i)
  165. if i >= 0x80 then return i - 0x100 else return i end
  166. end
  167. local function to_s16(i)
  168. if i >= 0x8000 then return i - 0x10000 else return i end
  169. end
  170. local function to_s32(i)
  171. if i >= 0x80000000 then return i - 0x100000000 else return i end
  172. end
  173. function cpu_flag(t)
  174. return (CPU_FLAGS & (1 << t)) ~= 0
  175. end
  176. function cpu_clear_flag(t)
  177. CPU_FLAGS = CPU_FLAGS & (~(1 << t))
  178. end
  179. function cpu_set_flag(t)
  180. CPU_FLAGS = CPU_FLAGS | (1 << t)
  181. end
  182. function cpu_write_flag(t, v)
  183. if v then
  184. CPU_FLAGS = CPU_FLAGS | (1 << t)
  185. else
  186. CPU_FLAGS = CPU_FLAGS & (~(1 << t))
  187. end
  188. end
  189. local cpu_write_flag = cpu_write_flag
  190. function cpu_complement_flag(t)
  191. CPU_FLAGS = CPU_FLAGS ~ (1 << t)
  192. end
  193. local function cpu_incdec_dir(t, amount)
  194. if ((CPU_FLAGS & (1<<(10))) ~= 0) then
  195. CPU_REGS[t] = (CPU_REGS[t] - amount) & 0xFFFF
  196. else
  197. CPU_REGS[t] = (CPU_REGS[t] + amount) & 0xFFFF
  198. end
  199. end
  200. local function cpu_print(t)
  201. emu_debug(1, string.format("[%04X %04X] ", CPU_SEGMENTS[2], (CPU_IP-1) & 0xFFFF) .. t)
  202. end
  203. function cpu_set_ip(vcs, vip)
  204. CPU_SEGMENTS[2] = vcs
  205. CPU_IP = vip
  206. end
  207. -- src format:
  208. -- 0-7 = ax,cx,dx,bx,sp,bp,si,di
  209. -- 8-15 = bx+si+disp, bx+di+disp, bp+si+disp, bp+di+disp, si+disp, di+disp, bp+disp, bx+disp
  210. -- 16-23 = al,cl,dl,bl,ah,ch,dh,bh
  211. -- 24-25 = address8(disp), address16(disp)
  212. -- 26-31 = es,cs,ss,ds,fs,gs
  213. -- 32-39 = 8-15(8-bit)
  214. -- 40 = imm8, 41 = imm16
  215. local _cpu_rm_seg_t = {
  216. SEG_DS, SEG_DS,
  217. SEG_SS, SEG_SS,
  218. SEG_DS, SEG_DS,
  219. SEG_SS, SEG_DS
  220. }
  221. local function _cpu_rm_seg(v)
  222. return _cpu_rm_seg_t[v]
  223. end
  224. local _cpu_rm_addr_t = {
  225. function(data) return (CPU_REGS[4] + CPU_REGS[7] + data.disp) & 0xFFFF end,
  226. function(data) return (CPU_REGS[4] + CPU_REGS[8] + data.disp) & 0xFFFF end,
  227. function(data) return (CPU_REGS[6] + CPU_REGS[7] + data.disp) & 0xFFFF end,
  228. function(data) return (CPU_REGS[6] + CPU_REGS[8] + data.disp) & 0xFFFF end,
  229. function(data) return (CPU_REGS[7] + data.disp) & 0xFFFF end,
  230. function(data) return (CPU_REGS[8] + data.disp) & 0xFFFF end,
  231. function(data) return (CPU_REGS[6] + data.disp) & 0xFFFF end,
  232. function(data) return (CPU_REGS[4] + data.disp) & 0xFFFF end
  233. }
  234. local function _cpu_rm_addr(data, v)
  235. return _cpu_rm_addr_t[v](data)
  236. end
  237. local function cpu_seg_rm(data, v)
  238. if v >= 8 and v < 16 then
  239. return _cpu_rm_seg_t[(v - 7)]
  240. elseif v >= 32 and v < 40 then
  241. return _cpu_rm_seg_t[(v - 31)]
  242. else return SEG_DS end
  243. end
  244. local function cpu_addr_rm(data, v)
  245. if v >= 8 and v < 16 then
  246. return _cpu_rm_addr_t[(v - 7)]((data))
  247. elseif v >= 24 and v <= 25 then
  248. return data.disp
  249. elseif v >= 32 and v < 40 then
  250. return _cpu_rm_addr_t[(v - 31)]((data))
  251. else
  252. platform_error("cpu_addr_rm todo: " .. v)
  253. end
  254. end
  255. local readrm_table = {}
  256. readrm_table[0] = function(data, v) return CPU_REGS[1] end
  257. readrm_table[1] = function(data, v) return CPU_REGS[2] end
  258. readrm_table[2] = function(data, v) return CPU_REGS[3] end
  259. readrm_table[3] = function(data, v) return CPU_REGS[4] end
  260. readrm_table[4] = function(data, v) return CPU_REGS[5] end
  261. readrm_table[5] = function(data, v) return CPU_REGS[6] end
  262. readrm_table[6] = function(data, v) return CPU_REGS[7] end
  263. readrm_table[7] = function(data, v) return CPU_REGS[8] end
  264. for i=8,15 do readrm_table[i] = function(data, v)
  265. return RAM:r16(((CPU_SEGMENTS[(CPU_SEGMOD or (_cpu_rm_seg_t[(v - 7)]+1))]<<4) + (_cpu_rm_addr_t[(v - 7)]((data)))))
  266. end end
  267. readrm_table[16] = function(data, v) return CPU_REGS[1] & 0xFF end
  268. readrm_table[17] = function(data, v) return CPU_REGS[2] & 0xFF end
  269. readrm_table[18] = function(data, v) return CPU_REGS[3] & 0xFF end
  270. readrm_table[19] = function(data, v) return CPU_REGS[4] & 0xFF end
  271. readrm_table[20] = function(data, v) return CPU_REGS[1] >> 8 end
  272. readrm_table[21] = function(data, v) return CPU_REGS[2] >> 8 end
  273. readrm_table[22] = function(data, v) return CPU_REGS[3] >> 8 end
  274. readrm_table[23] = function(data, v) return CPU_REGS[4] >> 8 end
  275. readrm_table[24] = function(data, v) return RAM[((CPU_SEGMENTS[(CPU_SEGMOD or (4))]<<4) + (data.disp))] end
  276. readrm_table[25] = function(data, v) return RAM:r16(((CPU_SEGMENTS[(CPU_SEGMOD or (4))]<<4) + (data.disp))) end
  277. for i=26,31 do readrm_table[i] = function(data, v)
  278. return CPU_SEGMENTS[v - 25]
  279. end end
  280. for i=32,39 do readrm_table[i] = function(data, v)
  281. return RAM[((CPU_SEGMENTS[(CPU_SEGMOD or (_cpu_rm_seg_t[(v - 31)]+1))]<<4) + (_cpu_rm_addr_t[(v - 31)]((data))))]
  282. end end
  283. readrm_table[40] = function(data, v) return data.imm & 0xFF end
  284. readrm_table[41] = function(data, v) return data.imm end
  285. local function cpu_read_rm(data, v)
  286. return readrm_table[v](data, v)
  287. end
  288. local writerm_table = {}
  289. writerm_table[0] = function(data, v, val) CPU_REGS[1] = val end
  290. writerm_table[1] = function(data, v, val) CPU_REGS[2] = val end
  291. writerm_table[2] = function(data, v, val) CPU_REGS[3] = val end
  292. writerm_table[3] = function(data, v, val) CPU_REGS[4] = val end
  293. writerm_table[4] = function(data, v, val) CPU_REGS[5] = val end
  294. writerm_table[5] = function(data, v, val) CPU_REGS[6] = val end
  295. writerm_table[6] = function(data, v, val) CPU_REGS[7] = val end
  296. writerm_table[7] = function(data, v, val) CPU_REGS[8] = val end
  297. for i=8,15 do writerm_table[i] = function(data, v, val)
  298. RAM:w16(((CPU_SEGMENTS[(CPU_SEGMOD or (_cpu_rm_seg_t[(v - 7)]+1))]<<4) + (_cpu_rm_addr_t[(v - 7)]((data)))), val)
  299. end end
  300. writerm_table[16] = function(data, v, val) CPU_REGS[1] = (CPU_REGS[1] & 0xFF00) | (val & 0xFF) end
  301. writerm_table[17] = function(data, v, val) CPU_REGS[2] = (CPU_REGS[2] & 0xFF00) | (val & 0xFF) end
  302. writerm_table[18] = function(data, v, val) CPU_REGS[3] = (CPU_REGS[3] & 0xFF00) | (val & 0xFF) end
  303. writerm_table[19] = function(data, v, val) CPU_REGS[4] = (CPU_REGS[4] & 0xFF00) | (val & 0xFF) end
  304. writerm_table[20] = function(data, v, val) CPU_REGS[1] = (CPU_REGS[1] & 0xFF) | ((val & 0xFF) << 8) end
  305. writerm_table[21] = function(data, v, val) CPU_REGS[2] = (CPU_REGS[2] & 0xFF) | ((val & 0xFF) << 8) end
  306. writerm_table[22] = function(data, v, val) CPU_REGS[3] = (CPU_REGS[3] & 0xFF) | ((val & 0xFF) << 8) end
  307. writerm_table[23] = function(data, v, val) CPU_REGS[4] = (CPU_REGS[4] & 0xFF) | ((val & 0xFF) << 8) end
  308. writerm_table[24] = function(data, v, val)
  309. RAM[((CPU_SEGMENTS[(CPU_SEGMOD or (4))]<<4) + (data.disp))] = val & 0xFF
  310. end
  311. writerm_table[25] = function(data, v, val)
  312. RAM:w16(((CPU_SEGMENTS[(CPU_SEGMOD or (4))]<<4) + (data.disp)), val)
  313. end
  314. for i=26,31 do writerm_table[i] = function(data, v, val)
  315. CPU_SEGMENTS[v - 25] = val
  316. end end
  317. for i=32,39 do writerm_table[i] = function(data, v, val)
  318. RAM[((CPU_SEGMENTS[(CPU_SEGMOD or (_cpu_rm_seg_t[(v - 31)]+1))]<<4) + (_cpu_rm_addr_t[(v - 31)]((data))))] = val & 0xFF
  319. end end
  320. local function cpu_write_rm(data, v, val)
  321. writerm_table[v](data, v, val)
  322. end
  323. local mrm_table = {}
  324. for i=0,2047 do
  325. local is_seg = (i & 1024) ~= 0
  326. local mod = (i >> 6) & 0x03
  327. local reg = (i >> 3) & 0x07
  328. local rm = i & 0x07
  329. local d = (i >> 9) & 0x01
  330. local w = (i >> 8) & 0x01
  331. if is_seg then w = 1 end
  332. local op1 = reg
  333. local op2 = rm
  334. if is_seg then
  335. op1 = (op1 % 6) + 26
  336. elseif w == 0 then
  337. op1 = op1 + 16
  338. end
  339. if mod == 0 and rm == 6 then
  340. op2 = 24 + w
  341. elseif mod ~= 3 then -- do not treat rm as reg field
  342. if w == 0 then
  343. op2 = op2 + 32
  344. else
  345. op2 = op2 + 8
  346. end
  347. else -- rm is reg field
  348. if w == 0 then
  349. op2 = op2 + 16
  350. end
  351. end
  352. local src, dst
  353. if d == 0 then
  354. src = op1
  355. dst = op2
  356. else
  357. src = op2
  358. dst = op1
  359. end
  360. local cdisp = 0
  361. if mod == 2 then cdisp = 2
  362. elseif mod == 1 then cdisp = 1
  363. elseif mod == 0 and rm == 6 then cdisp = 3 end
  364. mrm_table[i] = {src=src,dst=dst,cdisp=cdisp,disp=0}
  365. end
  366. local function cpu_mod_rm(opcode, is_seg)
  367. local modrm = cpu_advance_ip() | ((opcode & 3) << 8) | (is_seg or 0)
  368. local data = mrm_table[modrm]
  369. if data.cdisp == 0 then
  370. return data
  371. elseif data.cdisp == 2 then
  372. data.disp = to_s16(cpu_advance_ip16())
  373. elseif data.cdisp == 1 then
  374. data.disp = to_s8(cpu_advance_ip())
  375. elseif data.cdisp == 3 then
  376. data.disp = cpu_advance_ip16()
  377. end
  378. return data
  379. end
  380. local function cpu_mrm_copy(data)
  381. return {src=data.src,dst=data.dst,disp=data.disp}
  382. end
  383. local mrm6_4 = {src=40,dst=16,imm=0}
  384. local mrm6_5 = {src=41,dst=0,imm=0}
  385. local mrm6_table = {
  386. [0]=cpu_mod_rm,
  387. [1]=cpu_mod_rm,
  388. [2]=cpu_mod_rm,
  389. [3]=cpu_mod_rm,
  390. [4]=function(v)
  391. mrm6_4.imm=cpu_advance_ip()
  392. return mrm6_4
  393. end,
  394. [5]=function(v)
  395. mrm6_5.imm=cpu_advance_ip16()
  396. return mrm6_5
  397. end,
  398. [6]=cpu_mod_rm,
  399. [7]=cpu_mod_rm
  400. }
  401. local function cpu_mod_rm6(opcode)
  402. local v = opcode & 0x07
  403. return mrm6_table[v](v)
  404. end
  405. local parity_table = {}
  406. for i = 0,255 do
  407. local p = 0
  408. local v = i
  409. while v ~= 0 do
  410. p = p + (v & 1)
  411. v = v >> 1
  412. end
  413. if (p & 1) == 0 then
  414. parity_table[i] = 4
  415. else
  416. parity_table[i] = 0
  417. end
  418. end
  419. local function cpu_write_parity(v)
  420. CPU_FLAGS = CPU_FLAGS & 0xFFFB | parity_table[v & 0xFF]
  421. end
  422. local function cpu_push16(v)
  423. CPU_REGS[5] = (CPU_REGS[5] - 2) & 0xFFFF
  424. RAM:w16(((CPU_SEGMENTS[(SEG_SS)+1]<<4)+(CPU_REGS[5])), v & 0xFFFF)
  425. --emu_debug(0, string.format("stack: >%04X @%04X\n", v, CPU_REGS[5]))
  426. end
  427. local function cpu_pop16()
  428. local sp = CPU_REGS[5]
  429. CPU_REGS[5] = (sp + 2) & 0xFFFF
  430. --emu_debug(0, string.format("stack: <%04X @%04X\n", RAM:r16(((CPU_SEGMENTS[(SEG_SS)+1]<<4)+(sp))), sp))
  431. return RAM:r16(((CPU_SEGMENTS[(SEG_SS)+1]<<4)+(sp)))
  432. end
  433. local function cpu_mov(mrm)
  434. local v1 = cpu_read_rm(mrm, mrm.src)
  435. cpu_write_rm(mrm, mrm.dst, v1)
  436. end
  437. local function _cpu_uf_zsp(vr, opc)
  438. if (opc & 0x01) == 1 then
  439. cpu_write_flag(6, (vr & 0xFFFF) == 0)
  440. cpu_write_flag(7, (vr & 0x8000) ~= 0)
  441. CPU_FLAGS = CPU_FLAGS & 0xFFFB | parity_table[vr & 0xFF]
  442. else
  443. cpu_write_flag(6, (vr & 0xFF) == 0)
  444. cpu_write_flag(7, (vr & 0x80) ~= 0)
  445. CPU_FLAGS = CPU_FLAGS & 0xFFFB | parity_table[vr & 0xFF]
  446. end
  447. end
  448. local function _cpu_uf_inc(vr, opc)
  449. _cpu_uf_zsp(vr, opc)
  450. cpu_write_flag(4, (vr & 0xF) == 0x0) -- 15 + 1 = 16
  451. if (opc & 0x01) == 1 then
  452. cpu_write_flag(11, vr == 0x8000)
  453. else
  454. cpu_write_flag(11, vr == 0x80)
  455. end
  456. end
  457. local function _cpu_uf_dec(vr, opc)
  458. _cpu_uf_zsp(vr, opc)
  459. cpu_write_flag(4, (vr & 0xF) == 0xF) -- 0 - 1 = 15
  460. if (opc & 0x01) == 1 then
  461. cpu_write_flag(11, vr == 0x7FFF)
  462. else
  463. cpu_write_flag(11, vr == 0x7F)
  464. end
  465. end
  466. local function _cpu_uf_co_add(v1, v2, vc, vr, opc)
  467. cpu_write_flag(4, ((v1 & 0xF) + (v2 & 0xF) + vc) >= 0x10)
  468. if (opc & 0x01) == 1 then
  469. cpu_write_flag(0, (vr & 0xFFFF) ~= vr)
  470. cpu_write_flag(11, ((v1 & 0x8000) == (v2 & 0x8000)) and ((vr & 0x8000) ~= (v1 & 0x8000)))
  471. else
  472. cpu_write_flag(0, (vr & 0xFF) ~= vr)
  473. cpu_write_flag(11, ((v1 & 0x80) == (v2 & 0x80)) and ((vr & 0x80) ~= (v1 & 0x80)))
  474. end
  475. end
  476. local function _cpu_uf_co_sub(v1, v2, vb, vr, opc)
  477. -- v2 - v1
  478. cpu_write_flag(4, ((v2 & 0xF) - (v1 & 0xF) - vb) < 0)
  479. if (opc & 0x01) == 1 then
  480. cpu_write_flag(0, (vr & 0xFFFF) ~= vr)
  481. cpu_write_flag(11, ((v1 & 0x8000) ~= (v2 & 0x8000)) and ((vr & 0x8000) == (v1 & 0x8000)))
  482. else
  483. cpu_write_flag(0, (vr & 0xFF) ~= vr)
  484. cpu_write_flag(11, ((v1 & 0x80) ~= (v2 & 0x80)) and ((vr & 0x80) == (v1 & 0x80)))
  485. end
  486. end
  487. local function _cpu_uf_bit(vr, opc)
  488. CPU_FLAGS = CPU_FLAGS & (~0x0801) -- clear carry (0) and overflow (11)
  489. _cpu_uf_zsp(vr, opc)
  490. end
  491. local cpu_shift_mask = 0x1F
  492. if cpu_arch == "8086" then
  493. cpu_shift_mask = 0xFF
  494. end
  495. local function cpu_shl(mrm, opcode)
  496. local v1 = cpu_read_rm(mrm, mrm.src) & cpu_shift_mask
  497. if v1 >= 1 then
  498. -- todo: is the ifcheck correct?
  499. local v2 = cpu_read_rm(mrm, mrm.dst)
  500. local w = (opcode & 0x01)
  501. local mask = 0xFFFF
  502. if w == 0 then mask = 0xFF end
  503. local msb = ((mask >> 1) + 1)
  504. local vr = v2 << v1
  505. cpu_write_flag(0, (vr & (mask + 1)) ~= 0)
  506. cpu_write_rm(mrm, mrm.dst, vr & mask)
  507. _cpu_uf_zsp(vr & mask, opcode)
  508. if v1 == 1 then
  509. local msb_result = (vr & msb) ~= 0
  510. cpu_write_flag(11, ((CPU_FLAGS & (1<<(0))) ~= 0) ~= msb_result)
  511. end
  512. end
  513. end
  514. local function cpu_shr(mrm, opcode, arith)
  515. local w = (opcode & 0x01)
  516. local mask = 0x8000
  517. if w == 0 then mask = 0x80 end
  518. local v1 = cpu_read_rm(mrm, mrm.src) & cpu_shift_mask
  519. local v2 = cpu_read_rm(mrm, mrm.dst)
  520. local vr
  521. if (arith) then
  522. vr = v2
  523. local shift1 = v1
  524. while shift1 > 0 do
  525. vr = (vr & mask) | ((vr >> 1) & (mask - 1))
  526. shift1 = shift1 - 1
  527. end
  528. else
  529. vr = v2 >> v1
  530. end
  531. cpu_write_rm(mrm, mrm.dst, vr)
  532. _cpu_uf_zsp(vr, opcode)
  533. -- TODO: handle 0xFF
  534. if (1 << ((v1 & 0x1F) - 1)) > mask then
  535. cpu_write_flag(0, arith and ((v2 & mask) ~= 0))
  536. else
  537. cpu_write_flag(0, (v2 & (1 << (v1 - 1))) ~= 0)
  538. end
  539. if v1 == 1 then
  540. cpu_write_flag(11, (not arith) and ((v2 & mask) ~= 0))
  541. end
  542. end
  543. local ROTATE_MODE_ROR = 0
  544. local ROTATE_MODE_ROL = 1
  545. local ROTATE_MODE_RCR = 2
  546. local ROTATE_MODE_RCL = 3
  547. local function cpu_rotate(mrm, opcode, mode)
  548. local w = (opcode & 0x01)
  549. local shift = 15
  550. if w == 0 then shift = 7 end
  551. local v1 = (cpu_read_rm(mrm, mrm.src) & cpu_shift_mask)
  552. local v2 = cpu_read_rm(mrm, mrm.dst)
  553. local vr = v2
  554. local cf = 0
  555. local of = 0
  556. if ((CPU_FLAGS & (1<<(0))) ~= 0) then cf = 1 end
  557. local shifts = v1
  558. if shifts > 0 then
  559. if mode == ROTATE_MODE_ROR then
  560. shifts = shifts & shift
  561. local shiftmask = (1 << shifts) - 1
  562. cf = (vr >> ((shifts - 1) & shift)) & 0x01
  563. vr = (vr >> shifts) | ((vr & shiftmask) << ((shift - shifts + 1) & shift))
  564. of = ((vr >> shift) ~ (vr >> (shift - 1))) & 0x01
  565. elseif mode == ROTATE_MODE_ROL then
  566. shifts = shifts & shift
  567. cf = (vr >> ((shift - shifts + 1) & shift)) & 0x01
  568. vr = ((vr << shifts) & ((1 << (shift + 1)) - 1)) | (vr >> ((shift - shifts + 1) & shift))
  569. of = ((vr >> shift) ~ cf) & 0x01
  570. elseif mode == ROTATE_MODE_RCR then
  571. shifts = shifts % (shift + 2)
  572. while shifts > 0 do
  573. local newcf = (vr & 0x01)
  574. vr = (vr >> 1) | (cf << shift)
  575. shifts = shifts - 1
  576. cf = newcf
  577. end
  578. of = ((vr >> shift) ~ (vr >> (shift - 1))) & 0x01
  579. elseif mode == ROTATE_MODE_RCL then
  580. shifts = shifts % (shift + 2)
  581. while shifts > 0 do
  582. local newcf = (vr >> shift) & 0x01
  583. vr = ((vr << 1) & ((1 << (shift + 1)) - 1)) | cf
  584. shifts = shifts - 1
  585. cf = newcf
  586. end
  587. of = ((vr >> shift) ~ cf) & 0x01
  588. end
  589. cpu_write_rm(mrm, mrm.dst, vr & 0xFFFF)
  590. cpu_write_flag(0, cf == 1)
  591. if v1 == 1 then
  592. cpu_write_flag(11, of == 1)
  593. end
  594. end
  595. end
  596. local function cpu_mul(mrm, opcode)
  597. local w = (opcode & 0x01)
  598. local v1 = cpu_read_rm(mrm, mrm.src)
  599. local v2 = cpu_read_rm(mrm, mrm.dst)
  600. local vr = v1 * v2
  601. local vrf
  602. if w == 1 then
  603. vr = vr & 0xFFFFFFFF
  604. CPU_REGS[3] = (vr >> 16)
  605. CPU_REGS[1] = vr & 0xFFFF
  606. vrf = vr >> 16
  607. else
  608. vr = vr & 0xFFFF
  609. CPU_REGS[1] = vr
  610. vrf = vr >> 8
  611. end
  612. cpu_write_flag(0, vrf ~= 0)
  613. cpu_write_flag(11, vrf ~= 0)
  614. end
  615. local function cpu_imul(mrm, opcode)
  616. local w = (opcode & 0x01)
  617. local v1 = cpu_read_rm(mrm, mrm.src)
  618. local v2 = cpu_read_rm(mrm, mrm.dst)
  619. local vr = 0
  620. if w == 1 then
  621. vr = (to_s16(v1) * to_s16(v2))
  622. CPU_REGS[3] = (vr >> 16) & 0xFFFF
  623. CPU_REGS[1] = vr & 0xFFFF
  624. cpu_write_flag(0, (vr < -0x8000) or (vr >= 0x8000))
  625. cpu_write_flag(11, (vr < -0x8000) or (vr >= 0x8000))
  626. else
  627. vr = (to_s8(v1) * to_s8(v2))
  628. CPU_REGS[1] = vr & 0xFFFF
  629. cpu_write_flag(0, (vr < -0x80) or (vr >= 0x80))
  630. cpu_write_flag(11, (vr < -0x80) or (vr >= 0x80))
  631. end
  632. end
  633. local function cpu_div(mrm, opcode)
  634. local w = (opcode & 0x01)
  635. local v2 = cpu_read_rm(mrm, mrm.dst)
  636. if w == 1 then
  637. local v = (CPU_REGS[3] << 16) | (CPU_REGS[1])
  638. if v2 == 0 then
  639. emu_debug(1, "throw exception (/ by 0: " .. v .. " / " .. v2 .. ")")
  640. cpu_emit_interrupt(0, false)
  641. return
  642. end
  643. local vd = math.floor(v / v2)
  644. local vr = v % v2
  645. if vd > 0xFFFF then
  646. emu_debug(1, "throw exception (overflow: " .. v .. " / " .. v2 .. " = " .. vd .. ")")
  647. cpu_emit_interrupt(0, false)
  648. return
  649. end
  650. CPU_REGS[3] = vr & 0xFFFF
  651. CPU_REGS[1] = vd & 0xFFFF
  652. else
  653. local v = (CPU_REGS[1])
  654. if v2 == 0 then
  655. emu_debug(1, "throw exception (/ by 0: " .. v .. " / " .. v2 .. ")")
  656. cpu_emit_interrupt(0, false)
  657. return
  658. end
  659. local vd = math.floor(v / v2)
  660. local vr = v % v2
  661. if vd > 0xFF then
  662. emu_debug(1, "throw exception (overflow: " .. v .. " / " .. v2 .. " = " .. vd .. ")")
  663. cpu_emit_interrupt(0, false)
  664. return
  665. end
  666. CPU_REGS[1] = ((vr & 0xFF) << 8) | (vd & 0xFF)
  667. end
  668. end
  669. local function cpu_idiv(mrm, opcode)
  670. local w = (opcode & 0x01)
  671. local v2 = cpu_read_rm(mrm, mrm.dst)
  672. if w == 1 then
  673. local v = (CPU_REGS[3] << 16) | (CPU_REGS[1])
  674. v = to_s32(v)
  675. v2 = to_s16(v2)
  676. if v2 == 0 then
  677. emu_debug(1, "throw exception (/ by 0: " .. v .. " / " .. v2 .. ")")
  678. cpu_emit_interrupt(0, false)
  679. return
  680. end
  681. local vd = v / v2
  682. if vd >= 0 then vd = math.floor(vd) else vd = math.ceil(vd) end
  683. local vr = math.fmod(v, v2)
  684. if (vd >= 0x8000) or (vd < -0x8000) then
  685. emu_debug(1, "throw exception (overflow: " .. v .. " / " .. v2 .. " = " .. vd .. ")")
  686. cpu_emit_interrupt(0, false)
  687. return
  688. end
  689. CPU_REGS[3] = vr & 0xFFFF
  690. CPU_REGS[1] = vd & 0xFFFF
  691. else
  692. local v = (CPU_REGS[1])
  693. v = to_s16(v)
  694. v2 = to_s8(v2)
  695. if v2 == 0 then
  696. emu_debug(1, "throw exception (/ by 0: " .. v .. " / " .. v2 .. ")")
  697. cpu_emit_interrupt(0, false)
  698. return
  699. end
  700. local vd = math.floor(v / v2)
  701. if vd >= 0 then vd = math.floor(vd) else vd = math.ceil(vd) end
  702. local vr = math.fmod(v, v2)
  703. if (vd >= 0x80) or (vd < -0x80) then
  704. emu_debug(1, "throw exception (overflow: " .. v .. " / " .. v2 .. " = " .. vd .. ")")
  705. cpu_emit_interrupt(0, false)
  706. return
  707. end
  708. CPU_REGS[1] = ((vr & 0xFF) << 8) | (vd & 0xFF)
  709. end
  710. end
  711. local function cpu_add(mrm, opcode, carry)
  712. local w = (opcode & 0x01)
  713. local v1 = cpu_read_rm(mrm, mrm.src)
  714. local v2 = cpu_read_rm(mrm, mrm.dst)
  715. local vc = 0
  716. if carry and ((CPU_FLAGS & (1<<(0))) ~= 0) then
  717. vc = 1
  718. end
  719. local vr = v1 + v2 + vc
  720. if w == 1 then
  721. cpu_write_rm(mrm, mrm.dst, vr & 0xFFFF)
  722. else
  723. cpu_write_rm(mrm, mrm.dst, vr & 0xFF)
  724. end
  725. _cpu_uf_zsp(vr, opcode)
  726. _cpu_uf_co_add(v1, v2, vc, vr, opcode)
  727. end
  728. local function cpu_cmp(v2, v1, opcode)
  729. local vr = v2 - v1
  730. _cpu_uf_co_sub(v1, v2, 0, vr, opcode)
  731. _cpu_uf_zsp(vr, opcode)
  732. end
  733. local function cpu_cmp_mrm(mrm, opcode)
  734. cpu_cmp(cpu_read_rm(mrm, mrm.dst), cpu_read_rm(mrm, mrm.src), opcode)
  735. end
  736. local function cpu_sub(mrm, opcode, borrow)
  737. local w = (opcode & 0x01)
  738. local v1 = cpu_read_rm(mrm, mrm.src)
  739. local v2 = cpu_read_rm(mrm, mrm.dst)
  740. local vb = 0
  741. if borrow and ((CPU_FLAGS & (1<<(0))) ~= 0) then
  742. vb = 1
  743. end
  744. local vr = v2 - v1 - vb
  745. _cpu_uf_co_sub(v1, v2, vb, vr, opcode)
  746. if w == 1 then
  747. vr = vr & 0xFFFF
  748. else
  749. vr = vr & 0xFF
  750. end
  751. cpu_write_rm(mrm, mrm.dst, vr)
  752. _cpu_uf_zsp(vr, opcode)
  753. end
  754. local function cpu_xor(mrm, opc)
  755. local v1 = cpu_read_rm(mrm, mrm.src)
  756. local v2 = cpu_read_rm(mrm, mrm.dst)
  757. local vr = v1 ~ v2
  758. cpu_write_rm(mrm, mrm.dst, vr)
  759. _cpu_uf_bit(vr, opc)
  760. end
  761. local function cpu_and(mrm, opc)
  762. local v1 = cpu_read_rm(mrm, mrm.src)
  763. local v2 = cpu_read_rm(mrm, mrm.dst)
  764. local vr = v1 & v2
  765. cpu_write_rm(mrm, mrm.dst, vr)
  766. _cpu_uf_bit(vr, opc)
  767. end
  768. local function cpu_test(mrm, opc)
  769. local v1 = cpu_read_rm(mrm, mrm.src)
  770. local v2 = cpu_read_rm(mrm, mrm.dst)
  771. local vr = v1 & v2
  772. _cpu_uf_bit(vr, opc)
  773. end
  774. local function cpu_or(mrm, opc)
  775. local v1 = cpu_read_rm(mrm, mrm.src)
  776. local v2 = cpu_read_rm(mrm, mrm.dst)
  777. local vr = v1 | v2
  778. cpu_write_rm(mrm, mrm.dst, vr)
  779. _cpu_uf_bit(vr, opc)
  780. end
  781. local function cpu_print_state(opcode, adv)
  782. cpu_print(string.format("AX:%04X CX:%04X DX:%04X BX:%04X SP:%04X BP:%04X SI:%04X DI:%04X | %04X %04X %04X %04X | %04X",
  783. CPU_REGS[1], CPU_REGS[2], CPU_REGS[3], CPU_REGS[4], CPU_REGS[5], CPU_REGS[6], CPU_REGS[7], CPU_REGS[8],
  784. CPU_SEGMENTS[1], CPU_SEGMENTS[2], CPU_SEGMENTS[3], CPU_SEGMENTS[4], CPU_FLAGS))
  785. -- cpu_print(string.format("%02X (flags %04X, seg ES %04X CS %04X SS %04X DS %04X)", opcode, CPU_FLAGS, CPU_SEGMENTS[1], CPU_SEGMENTS[2], CPU_SEGMENTS[3], CPU_SEGMENTS[4]))
  786. -- cpu_print(string.format("AX %04X CX %04X DX %04X BX %04X SP %04X BP %04X SI %04X DI %04X", CPU_REGS[1], CPU_REGS[2], CPU_REGS[3], CPU_REGS[4], CPU_REGS[5], CPU_REGS[6], CPU_REGS[7], CPU_REGS[8]))
  787. if adv then
  788. local s = "c?p?a?zstidoppn?"
  789. local s2 = ""
  790. local fl = CPU_FLAGS
  791. for i=0,15 do
  792. local s3 = s:sub(i + 1, i + 1)
  793. if (fl & 1) == 1 then s3 = s3:upper() end
  794. s2 = s2 .. s3
  795. fl = fl >> 1
  796. end
  797. cpu_print("FLAGS ADV:" .. s2)
  798. end
  799. end
  800. local function cpu_rep(cond)
  801. local old_ip = CPU_IP
  802. local opcode = cpu_advance_ip()
  803. -- check for string instructions
  804. -- local opc_c = opcode & 0xFE
  805. -- if opc_c ~= 0x6C and opc_c ~= 0x6E and opc_c ~= 0xA4 and opc_c ~= 0xA6 and opc_c ~= 0xAA and opc_c ~= 0xAC
  806. -- and opc_c ~= 0xAE then
  807. -- CPU_IP = old_ip
  808. -- return true
  809. -- end
  810. -- if length zero, skip
  811. -- TODO: this relies on the opcode after REP always being 1 long...
  812. if (CPU_REGS[2] == 0) then
  813. return true
  814. end
  815. CPU_IP = old_ip
  816. local pr_state = true
  817. local skipConds = opcode ~= 0xA6 and opcode ~= 0xA7 and opcode ~= 0xAE and opcode ~= 0xAF
  818. while CPU_REGS[2] ~= 0 do
  819. local r = run_one(true, pr_state)
  820. if not r then return false
  821. elseif r == "block" then platform_error("this should never see 'block'") end
  822. CPU_REGS[2] = (CPU_REGS[2] - 1) & 0xFFFF
  823. if CPU_REGS[2] == 0 then break end
  824. local condResult = skipConds
  825. if not condResult then condResult = cond() end
  826. if condResult then
  827. CPU_IP = old_ip
  828. pr_state = false
  829. else
  830. break
  831. end
  832. end
  833. return true
  834. end
  835. local function cpu_in(cond)
  836. local p = io_ports[cond+1]
  837. if p == nil then
  838. return 0xFF
  839. elseif type(p) == "function" then return p(cond)
  840. else return p end
  841. end
  842. local function cpu_out(cond, val)
  843. local p = io_ports[cond+1]
  844. if type(p) == "function" then p(cond,val)
  845. elseif p ~= nil then io_ports[cond+1] = val
  846. else
  847. end
  848. end
  849. function cpu_port_get(cond)
  850. return io_ports[cond+1]
  851. end
  852. function cpu_port_set(cond, val, val2)
  853. if type(val) == "function" and type(val2) == "function" then
  854. io_ports[cond+1] = function(cond,v)
  855. if v then val2(cond,v) else val(cond) end
  856. end
  857. else
  858. io_ports[cond+1] = val
  859. end
  860. end
  861. local interrupt_handlers = {
  862. }
  863. function cpu_register_interrupt_handler(v, hnd)
  864. interrupt_handlers[v + 1] = hnd
  865. end
  866. local function cpu_int_fake(cond)
  867. local ax = CPU_REGS[1]
  868. local ah = (ax >> 8)
  869. local al = (ax & 0xFF)
  870. local h = interrupt_handlers[cond + 1]
  871. if h then
  872. local r = h(ax,ah,al)
  873. if r then
  874. return r
  875. end
  876. end
  877. -- emu_debug(1, string.format("unknown interrupt: %02X AX=%04X", cond, ax))
  878. end
  879. local function cpu_int(cond)
  880. local addr = RAM:r16(cond * 4)
  881. local seg = RAM:r16(cond * 4 + 2)
  882. cpu_push16(CPU_FLAGS)
  883. cpu_push16(CPU_SEGMENTS[2])
  884. cpu_push16(CPU_IP)
  885. CPU_SEGMENTS[2]=seg
  886. CPU_IP=addr
  887. CPU_HALTED=false
  888. CPU_FLAGS = CPU_FLAGS & (~(1 << (9)))
  889. end
  890. local rel_jmp_conds = {
  891. function() return ((CPU_FLAGS & (1<<(11))) ~= 0) end,
  892. function() return not ((CPU_FLAGS & (1<<(11))) ~= 0) end,
  893. function() return ((CPU_FLAGS & (1<<(0))) ~= 0) end,
  894. function() return not ((CPU_FLAGS & (1<<(0))) ~= 0) end,
  895. function() return ((CPU_FLAGS & (1<<(6))) ~= 0) end,
  896. function() return not ((CPU_FLAGS & (1<<(6))) ~= 0) end,
  897. function() return ((CPU_FLAGS & (1<<(0))) ~= 0) or ((CPU_FLAGS & (1<<(6))) ~= 0) end,
  898. function() return not (((CPU_FLAGS & (1<<(0))) ~= 0) or ((CPU_FLAGS & (1<<(6))) ~= 0)) end,
  899. function() return ((CPU_FLAGS & (1<<(7))) ~= 0) end,
  900. function() return not ((CPU_FLAGS & (1<<(7))) ~= 0) end,
  901. function() return ((CPU_FLAGS & (1<<(2))) ~= 0) end,
  902. function() return not ((CPU_FLAGS & (1<<(2))) ~= 0) end,
  903. function() return ((CPU_FLAGS & (1<<(11))) ~= 0) ~= ((CPU_FLAGS & (1<<(7))) ~= 0) end,
  904. function() return ((CPU_FLAGS & (1<<(11))) ~= 0) == ((CPU_FLAGS & (1<<(7))) ~= 0) end,
  905. function() return (((CPU_FLAGS & (1<<(11))) ~= 0) ~= ((CPU_FLAGS & (1<<(7))) ~= 0)) or ((CPU_FLAGS & (1<<(6))) ~= 0) end,
  906. function() return not ((((CPU_FLAGS & (1<<(11))) ~= 0) ~= ((CPU_FLAGS & (1<<(7))) ~= 0)) or ((CPU_FLAGS & (1<<(6))) ~= 0)) end
  907. }
  908. local function dump_memory()
  909. local f = io.open("mem", "wb")
  910. for i=0,0x9FFFF do
  911. f:write(string.char(RAM[i]))
  912. end
  913. f:close()
  914. end
  915. local opcode_map = {}
  916. opcode_map[0x90] = function(opcode) end
  917. -- ADD
  918. opcode_map[0x00] = function(opcode) cpu_add(mrm6_table[((opcode) & 0x7)]((opcode)), opcode) end
  919. for i=0x01,0x05 do opcode_map[i] = opcode_map[0x00] end
  920. -- PUSH/POP ES
  921. opcode_map[0x06] = function(opcode) cpu_push16(CPU_SEGMENTS[1]) end
  922. opcode_map[0x07] = function(opcode) CPU_SEGMENTS[1] = cpu_pop16() end
  923. -- OR
  924. opcode_map[0x08] = function(opcode) cpu_or(mrm6_table[((opcode) & 0x7)]((opcode)), opcode) end
  925. for i=0x09,0x0D do opcode_map[i] = opcode_map[0x08] end
  926. -- PUSH CS
  927. opcode_map[0x0E] = function(opcode) cpu_push16(CPU_SEGMENTS[2]) end
  928. -- POP CS (8086)
  929. if cpu_arch == "8086" then
  930. opcode_map[0x0F] = function(opcode) CPU_SEGMENTS[2] = cpu_pop16() end
  931. end
  932. -- ADC
  933. opcode_map[0x10] = function(opcode) cpu_add(mrm6_table[((opcode) & 0x7)]((opcode)), opcode, true) end
  934. for i=0x11,0x15 do opcode_map[i] = opcode_map[0x10] end
  935. -- PUSH/POP SS
  936. opcode_map[0x16] = function(opcode) cpu_push16(CPU_SEGMENTS[3]) end
  937. opcode_map[0x17] = function(opcode) CPU_SEGMENTS[3] = cpu_pop16() end
  938. -- SBB
  939. opcode_map[0x18] = function(opcode) cpu_sub(mrm6_table[((opcode) & 0x7)]((opcode)), opcode, true) end
  940. for i=0x19,0x1D do opcode_map[i] = opcode_map[0x18] end
  941. -- PUSH/POP DS
  942. opcode_map[0x1E] = function(opcode) cpu_push16(CPU_SEGMENTS[4]) end
  943. opcode_map[0x1F] = function(opcode) CPU_SEGMENTS[4] = cpu_pop16() end
  944. -- AND
  945. opcode_map[0x20] = function(opcode) cpu_and(mrm6_table[((opcode) & 0x7)]((opcode)), opcode) end
  946. for i=0x21,0x25 do opcode_map[i] = opcode_map[0x20] end
  947. -- ES:
  948. opcode_map[0x26] = function(opcode)
  949. CPU_SEGMOD = 1
  950. local r = run_one(true, true)
  951. CPU_SEGMOD = nil
  952. return r
  953. end
  954. -- DAA
  955. opcode_map[0x27] = function(opcode)
  956. local al = CPU_REGS[1] & 0xFF
  957. local old_al = al
  958. local old_cf = ((CPU_FLAGS & (1<<(0))) ~= 0)
  959. if ((old_al & 0x0F) > 0x9) or ((CPU_FLAGS & (1<<(4))) ~= 0) then
  960. al = al + 0x6
  961. cpu_write_flag(0, old_cf or (al > 0xFF))
  962. CPU_FLAGS = CPU_FLAGS | (1 << (4))
  963. else
  964. CPU_FLAGS = CPU_FLAGS & (~(1 << (4)))
  965. end
  966. if (old_al > 0x99) or old_cf then
  967. al = al + 0x60
  968. CPU_FLAGS = CPU_FLAGS | (1 << (0))
  969. end
  970. CPU_REGS[1] = (CPU_REGS[1] & 0xFF00) | (al & 0xFF)
  971. _cpu_uf_zsp(al, 0)
  972. end
  973. -- SUB
  974. opcode_map[0x28] = function(opcode) cpu_sub(mrm6_table[((opcode) & 0x7)]((opcode)), opcode) end
  975. for i=0x29,0x2D do opcode_map[i] = opcode_map[0x28] end
  976. -- CS:
  977. opcode_map[0x2E] = function(opcode)
  978. CPU_SEGMOD = 2
  979. local r = run_one(true, true)
  980. CPU_SEGMOD = nil
  981. return r
  982. end
  983. -- DAS
  984. opcode_map[0x2F] = function(opcode)
  985. local al = CPU_REGS[1] & 0xFF
  986. local old_al = al
  987. local old_cf = ((CPU_FLAGS & (1<<(0))) ~= 0)
  988. if ((al & 0x0F) > 0x9) or ((CPU_FLAGS & (1<<(4))) ~= 0) then
  989. al = al - 0x6
  990. cpu_write_flag(0, old_cf or (al < 0))
  991. CPU_FLAGS = CPU_FLAGS | (1 << (4))
  992. else
  993. CPU_FLAGS = CPU_FLAGS & (~(1 << (4)))
  994. end
  995. if ((al) > 0x99) or old_cf then
  996. al = al - 0x60
  997. CPU_FLAGS = CPU_FLAGS | (1 << (0))
  998. else
  999. CPU_FLAGS = CPU_FLAGS & (~(1 << (0)))
  1000. end
  1001. CPU_REGS[1] = (CPU_REGS[1] & 0xFF00) | (al & 0xFF)
  1002. _cpu_uf_zsp(al, 0)
  1003. end
  1004. -- XOR
  1005. opcode_map[0x30] = function(opcode) cpu_xor(mrm6_table[((opcode) & 0x7)]((opcode)), opcode) end
  1006. for i=0x31,0x35 do opcode_map[i] = opcode_map[0x30] end
  1007. -- SS:
  1008. opcode_map[0x36] = function(opcode)
  1009. CPU_SEGMOD = 3
  1010. local r = run_one(true, true)
  1011. CPU_SEGMOD = nil
  1012. return r
  1013. end
  1014. -- AAA
  1015. opcode_map[0x37] = function(opcode)
  1016. local al = CPU_REGS[1] & 0xFF
  1017. if ((al & 0x0F) >= 0x9) or ((CPU_FLAGS & (1<<(4))) ~= 0) then
  1018. CPU_REGS[1] = (CPU_REGS[1] + 0x106) & 0xFFFF
  1019. CPU_FLAGS = CPU_FLAGS | (1 << (0))
  1020. CPU_FLAGS = CPU_FLAGS | (1 << (4))
  1021. else
  1022. CPU_FLAGS = CPU_FLAGS & (~(1 << (0)))
  1023. CPU_FLAGS = CPU_FLAGS & (~(1 << (4)))
  1024. end
  1025. CPU_REGS[1] = (CPU_REGS[1] & 0xFF0F)
  1026. end
  1027. -- CMP
  1028. opcode_map[0x38] = function(opcode) cpu_cmp_mrm(mrm6_table[((opcode) & 0x7)]((opcode)), opcode) end
  1029. for i=0x39,0x3D do opcode_map[i] = opcode_map[0x38] end
  1030. -- DS:
  1031. opcode_map[0x3E] = function(opcode)
  1032. CPU_SEGMOD = 4
  1033. local r = run_one(true, true)
  1034. CPU_SEGMOD = nil
  1035. return r
  1036. end
  1037. -- AAS
  1038. opcode_map[0x3F] = function(opcode)
  1039. local al = CPU_REGS[1] & 0xFF
  1040. if ((al & 0x0F) >= 0x9) or ((CPU_FLAGS & (1<<(4))) ~= 0) then
  1041. CPU_REGS[1] = (CPU_REGS[1] - 0x006) & 0xFFFF
  1042. local ah = (CPU_REGS[1] & 0xFF00) >> 8
  1043. ah = (ah - 1) & 0xFF
  1044. CPU_REGS[1] = (CPU_REGS[1] & 0xFF) | (ah << 8)
  1045. CPU_FLAGS = CPU_FLAGS | (1 << (0))
  1046. CPU_FLAGS = CPU_FLAGS | (1 << (4))
  1047. else
  1048. CPU_FLAGS = CPU_FLAGS & (~(1 << (0)))
  1049. CPU_FLAGS = CPU_FLAGS & (~(1 << (4)))
  1050. end
  1051. CPU_REGS[1] = (CPU_REGS[1] & 0xFF0F)
  1052. end
  1053. -- INC
  1054. opcode_map[(0x40)] = function(opcode) local v = CPU_REGS[(1)]; v = (v + 1) & 0xFFFF; CPU_REGS[(1)] = v; _cpu_uf_inc(v, 1) end
  1055. opcode_map[(0x41)] = function(opcode) local v = CPU_REGS[(2)]; v = (v + 1) & 0xFFFF; CPU_REGS[(2)] = v; _cpu_uf_inc(v, 1) end
  1056. opcode_map[(0x42)] = function(opcode) local v = CPU_REGS[(3)]; v = (v + 1) & 0xFFFF; CPU_REGS[(3)] = v; _cpu_uf_inc(v, 1) end
  1057. opcode_map[(0x43)] = function(opcode) local v = CPU_REGS[(4)]; v = (v + 1) & 0xFFFF; CPU_REGS[(4)] = v; _cpu_uf_inc(v, 1) end
  1058. opcode_map[(0x44)] = function(opcode) local v = CPU_REGS[(5)]; v = (v + 1) & 0xFFFF; CPU_REGS[(5)] = v; _cpu_uf_inc(v, 1) end
  1059. opcode_map[(0x45)] = function(opcode) local v = CPU_REGS[(6)]; v = (v + 1) & 0xFFFF; CPU_REGS[(6)] = v; _cpu_uf_inc(v, 1) end
  1060. opcode_map[(0x46)] = function(opcode) local v = CPU_REGS[(7)]; v = (v + 1) & 0xFFFF; CPU_REGS[(7)] = v; _cpu_uf_inc(v, 1) end
  1061. opcode_map[(0x47)] = function(opcode) local v = CPU_REGS[(8)]; v = (v + 1) & 0xFFFF; CPU_REGS[(8)] = v; _cpu_uf_inc(v, 1) end
  1062. -- DEC
  1063. opcode_map[(0x48)] = function(opcode) local v = CPU_REGS[(1)]; v = (v - 1) & 0xFFFF; CPU_REGS[(1)] = v; _cpu_uf_dec(v, 1) end
  1064. opcode_map[(0x49)] = function(opcode) local v = CPU_REGS[(2)]; v = (v - 1) & 0xFFFF; CPU_REGS[(2)] = v; _cpu_uf_dec(v, 1) end
  1065. opcode_map[(0x4A)] = function(opcode) local v = CPU_REGS[(3)]; v = (v - 1) & 0xFFFF; CPU_REGS[(3)] = v; _cpu_uf_dec(v, 1) end
  1066. opcode_map[(0x4B)] = function(opcode) local v = CPU_REGS[(4)]; v = (v - 1) & 0xFFFF; CPU_REGS[(4)] = v; _cpu_uf_dec(v, 1) end
  1067. opcode_map[(0x4C)] = function(opcode) local v = CPU_REGS[(5)]; v = (v - 1) & 0xFFFF; CPU_REGS[(5)] = v; _cpu_uf_dec(v, 1) end
  1068. opcode_map[(0x4D)] = function(opcode) local v = CPU_REGS[(6)]; v = (v - 1) & 0xFFFF; CPU_REGS[(6)] = v; _cpu_uf_dec(v, 1) end
  1069. opcode_map[(0x4E)] = function(opcode) local v = CPU_REGS[(7)]; v = (v - 1) & 0xFFFF; CPU_REGS[(7)] = v; _cpu_uf_dec(v, 1) end
  1070. opcode_map[(0x4F)] = function(opcode) local v = CPU_REGS[(8)]; v = (v - 1) & 0xFFFF; CPU_REGS[(8)] = v; _cpu_uf_dec(v, 1) end
  1071. -- PUSH/POP
  1072. opcode_map[0x50] = function(opcode) cpu_push16(CPU_REGS[1]) end
  1073. opcode_map[0x51] = function(opcode) cpu_push16(CPU_REGS[2]) end
  1074. opcode_map[0x52] = function(opcode) cpu_push16(CPU_REGS[3]) end
  1075. opcode_map[0x53] = function(opcode) cpu_push16(CPU_REGS[4]) end
  1076. opcode_map[0x54] = function(opcode) cpu_push16(CPU_REGS[5]) end
  1077. opcode_map[0x55] = function(opcode) cpu_push16(CPU_REGS[6]) end
  1078. opcode_map[0x56] = function(opcode) cpu_push16(CPU_REGS[7]) end
  1079. opcode_map[0x57] = function(opcode) cpu_push16(CPU_REGS[8]) end
  1080. opcode_map[0x58] = function(opcode) CPU_REGS[1] = cpu_pop16() end
  1081. opcode_map[0x59] = function(opcode) CPU_REGS[2] = cpu_pop16() end
  1082. opcode_map[0x5A] = function(opcode) CPU_REGS[3] = cpu_pop16() end
  1083. opcode_map[0x5B] = function(opcode) CPU_REGS[4] = cpu_pop16() end
  1084. opcode_map[0x5C] = function(opcode) CPU_REGS[5] = cpu_pop16() end
  1085. opcode_map[0x5D] = function(opcode) CPU_REGS[6] = cpu_pop16() end
  1086. opcode_map[0x5E] = function(opcode) CPU_REGS[7] = cpu_pop16() end
  1087. opcode_map[0x5F] = function(opcode) CPU_REGS[8] = cpu_pop16() end
  1088. if cpu_arch == "8086" or cpu_arch == "80186" then
  1089. -- PUSH SP (8086/80186 bug reproduction)
  1090. opcode_map[0x54] = function(opcode) cpu_push16(CPU_REGS[5] - 2) end
  1091. end
  1092. -- JMP
  1093. for i=0x70,0x7F do
  1094. local cond = rel_jmp_conds[i - 0x6F]
  1095. opcode_map[i] = function(opcode)
  1096. local offset = cpu_advance_ip()
  1097. if cond() then
  1098. CPU_IP = (CPU_IP + to_s8(offset)) & 0xFFFF
  1099. end
  1100. end
  1101. end
  1102. if cpu_arch == "8086" then
  1103. for i=0,15 do
  1104. opcode_map[0x60 + i] = opcode_map[0x70 + i]
  1105. end
  1106. else
  1107. -- 80186+ opcodes
  1108. -- TODO: IMUL(69/6B), BOUND
  1109. -- PUSHA
  1110. opcode_map[0x60] = function(opcode)
  1111. local tmp = CPU_REGS[5]
  1112. cpu_push16(CPU_REGS[1])
  1113. cpu_push16(CPU_REGS[2])
  1114. cpu_push16(CPU_REGS[3])
  1115. cpu_push16(CPU_REGS[4])
  1116. cpu_push16(tmp)
  1117. cpu_push16(CPU_REGS[6])
  1118. cpu_push16(CPU_REGS[7])
  1119. cpu_push16(CPU_REGS[8])
  1120. end
  1121. -- POPA
  1122. opcode_map[0x61] = function(opcode)
  1123. CPU_REGS[8] = cpu_pop16()
  1124. CPU_REGS[7] = cpu_pop16()
  1125. CPU_REGS[6] = cpu_pop16()
  1126. cpu_pop16()
  1127. CPU_REGS[4] = cpu_pop16()
  1128. CPU_REGS[3] = cpu_pop16()
  1129. CPU_REGS[2] = cpu_pop16()
  1130. CPU_REGS[1] = cpu_pop16()
  1131. end
  1132. -- PUSH imm16/imm8
  1133. opcode_map[0x68] = function(opcode)
  1134. cpu_push16(cpu_advance_ip16())
  1135. end
  1136. opcode_map[0x6A] = function(opcode)
  1137. cpu_push16(cpu_advance_ip())
  1138. end
  1139. -- ENTER (TESTME)
  1140. opcode_map[0xC8] = function(opcode)
  1141. local nb = cpu_advance_ip16()
  1142. local level = cpu_advance_ip() & 0x1F
  1143. cpu_push16(CPU_REGS[6])
  1144. local frame_ptr = CPU_REGS[5]
  1145. if level > 0 then
  1146. for i=1,level-1 do
  1147. CPU_REGS[6] = CPU_REGS[6] - 2
  1148. cpu_push16(CPU_REGS[6])
  1149. end
  1150. cpu_push16(frame_ptr)
  1151. end
  1152. CPU_REGS[6] = frame_ptr
  1153. CPU_REGS[5] = CPU_REGS[5] - nb
  1154. end
  1155. -- LEAVE
  1156. opcode_map[0xC9] = function(opcode)
  1157. CPU_REGS[5] = CPU_REGS[6]
  1158. CPU_REGS[6] = cpu_pop16()
  1159. end
  1160. opcode_map[0xA4] = function(opcode)
  1161. local addrSrc = ((CPU_SEGMENTS[(CPU_SEGMOD or (4))]<<4) + (CPU_REGS[7]))
  1162. local addrDst = ((CPU_SEGMENTS[(SEG_ES)+1]<<4)+(CPU_REGS[8]))
  1163. RAM[addrDst] = RAM[addrSrc]
  1164. cpu_incdec_dir(7, 1)
  1165. cpu_incdec_dir(8, 1)
  1166. end
  1167. opcode_map[0xA5] = function(opcode)
  1168. local addrSrc = ((CPU_SEGMENTS[(CPU_SEGMOD or (4))]<<4) + (CPU_REGS[7]))
  1169. local addrDst = ((CPU_SEGMENTS[(SEG_ES)+1]<<4)+(CPU_REGS[8]))
  1170. RAM:w16(addrDst, RAM:r16(addrSrc))
  1171. cpu_incdec_dir(7, 2)
  1172. cpu_incdec_dir(8, 2)
  1173. end
  1174. -- INS Ib
  1175. opcode_map[0x6C] = function(opcode)
  1176. local addrDst = ((CPU_SEGMENTS[(SEG_ES)+1]<<4)+(CPU_REGS[8]))
  1177. RAM[addrDst] = cpu_in(CPU_REGS[3]) & 0xFF
  1178. cpu_incdec_dir(8, 1)
  1179. end
  1180. -- INS Iw
  1181. opcode_map[0x6D] = function(opcode)
  1182. local addrDst = ((CPU_SEGMENTS[(SEG_ES)+1]<<4)+(CPU_REGS[8]))
  1183. RAM:w16(addrDst, cpu_in(CPU_REGS[3]) & 0xFFFF)
  1184. cpu_incdec_dir(8, 2)
  1185. end
  1186. -- OUTS Ib
  1187. opcode_map[0x6E] = function(opcode)
  1188. local addrSrc = ((CPU_SEGMENTS[(CPU_SEGMOD or (4))]<<4) + (CPU_REGS[7]))
  1189. cpu_out(CPU_REGS[3], RAM[addrSrc])
  1190. cpu_incdec_dir(7, 1)
  1191. end
  1192. -- OUTS Iw
  1193. opcode_map[0x6F] = function(opcode)
  1194. local addrSrc = ((CPU_SEGMENTS[(CPU_SEGMOD or (4))]<<4) + (CPU_REGS[7]))
  1195. cpu_out(CPU_REGS[3], RAM:r16(addrSrc))
  1196. cpu_incdec_dir(7, 2)
  1197. end
  1198. end -- (80186+ opcodes)
  1199. local grp1_table = {
  1200. [0]=cpu_add,
  1201. [1]=cpu_or,
  1202. [2]=function(a,b) cpu_add(a,b,true) end,
  1203. [3]=function(a,b) cpu_sub(a,b,true) end,
  1204. [4]=cpu_and,
  1205. [5]=function(a,b) cpu_sub(a,b,false) end,
  1206. [6]=cpu_xor,
  1207. [7]=function(a,b) cpu_cmp_mrm(a,b) end
  1208. }
  1209. -- GRP1
  1210. opcode_map[0x80] = function(opcode)
  1211. local mrm = cpu_mrm_copy(cpu_mod_rm(0))
  1212. local v = mrm.src & 0x07
  1213. mrm.src = 40
  1214. mrm.imm = cpu_advance_ip()
  1215. grp1_table[v](mrm, opcode)
  1216. end
  1217. opcode_map[0x81] = function(opcode)
  1218. local mrm = cpu_mrm_copy(cpu_mod_rm(1))
  1219. local v = mrm.src & 0x07
  1220. mrm.src = 41
  1221. mrm.imm = cpu_advance_ip16()
  1222. grp1_table[v](mrm, opcode)
  1223. end
  1224. opcode_map[0x82] = function(opcode)
  1225. local mrm = cpu_mrm_copy(cpu_mod_rm(0))
  1226. local v = mrm.src & 0x07
  1227. mrm.src = 40
  1228. mrm.imm = cpu_advance_ip()
  1229. grp1_table[v](mrm, opcode)
  1230. end
  1231. opcode_map[0x83] = function(opcode)
  1232. local mrm = cpu_mrm_copy(cpu_mod_rm(1))
  1233. local v = mrm.src & 0x07
  1234. mrm.src = 41
  1235. mrm.imm = to_s8(cpu_advance_ip()) & 0xFFFF
  1236. grp1_table[v](mrm, opcode)
  1237. end
  1238. -- TEST
  1239. opcode_map[0x84] = function(opcode) cpu_test(cpu_mod_rm(0), opcode) end
  1240. opcode_map[0x85] = function(opcode) cpu_test(cpu_mod_rm(1), opcode) end
  1241. -- XCHG
  1242. opcode_map[0x86] = function(opcode)
  1243. local mrm = cpu_mod_rm(opcode & 0x01)
  1244. local t = cpu_read_rm(mrm, mrm.src)
  1245. cpu_write_rm(mrm, mrm.src, cpu_read_rm(mrm, mrm.dst))
  1246. cpu_write_rm(mrm, mrm.dst, t)
  1247. end
  1248. opcode_map[0x87] = opcode_map[0x86]
  1249. -- MOV mod/rm
  1250. opcode_map[0x88] = function(opcode) cpu_mov(cpu_mod_rm(0)) end
  1251. opcode_map[0x89] = function(opcode) cpu_mov(cpu_mod_rm(1)) end
  1252. opcode_map[0x8A] = function(opcode) cpu_mov(cpu_mod_rm(2)) end
  1253. opcode_map[0x8B] = function(opcode) cpu_mov(cpu_mod_rm(3)) end
  1254. -- MOV segment
  1255. opcode_map[0x8C] = function(opcode)
  1256. local mrm = cpu_mod_rm(opcode, 1024)
  1257. if mrm.dst == 26+SEG_CS then
  1258. platform_error("Tried writing to CS segment!")
  1259. end
  1260. cpu_mov(mrm)
  1261. -- Loading the SS register with a MOV inhibits all interrupts until after the next instruction,
  1262. -- so let's just call an extra instruction marked non-interruptible here
  1263. if mrm.dst == 26+SEG_SS then
  1264. return run_one(true, true)
  1265. end
  1266. end
  1267. opcode_map[0x8E] = opcode_map[0x8C]
  1268. -- LEA
  1269. opcode_map[0x8D] = function(opcode)
  1270. local mrm = cpu_mod_rm(3)
  1271. cpu_write_rm(mrm, mrm.dst, cpu_addr_rm(mrm, mrm.src))
  1272. end
  1273. -- POP m16
  1274. opcode_map[0x8F] = function(opcode)
  1275. local mrm = cpu_mod_rm(1)
  1276. cpu_write_rm(mrm, mrm.dst, cpu_pop16())
  1277. end
  1278. -- XCHG (XCHG AX, AX == NOP)
  1279. opcode_map[(0x91)] = function(opcode) local v = CPU_REGS[(2)]; CPU_REGS[(2)] = CPU_REGS[1]; CPU_REGS[1] = v; end
  1280. opcode_map[(0x92)] = function(opcode) local v = CPU_REGS[(3)]; CPU_REGS[(3)] = CPU_REGS[1]; CPU_REGS[1] = v; end
  1281. opcode_map[(0x93)] = function(opcode) local v = CPU_REGS[(4)]; CPU_REGS[(4)] = CPU_REGS[1]; CPU_REGS[1] = v; end
  1282. opcode_map[(0x94)] = function(opcode) local v = CPU_REGS[(5)]; CPU_REGS[(5)] = CPU_REGS[1]; CPU_REGS[1] = v; end
  1283. opcode_map[(0x95)] = function(opcode) local v = CPU_REGS[(6)]; CPU_REGS[(6)] = CPU_REGS[1]; CPU_REGS[1] = v; end
  1284. opcode_map[(0x96)] = function(opcode) local v = CPU_REGS[(7)]; CPU_REGS[(7)] = CPU_REGS[1]; CPU_REGS[1] = v; end
  1285. opcode_map[(0x97)] = function(opcode) local v = CPU_REGS[(8)]; CPU_REGS[(8)] = CPU_REGS[1]; CPU_REGS[1] = v; end
  1286. -- CBW
  1287. opcode_map[0x98] = function(opcode)
  1288. local v = CPU_REGS[1] & 0xFF
  1289. if v >= 0x80 then v = v | 0xFF00 end
  1290. CPU_REGS[1] = v
  1291. end
  1292. -- CWD
  1293. opcode_map[0x99] = function(opcode)
  1294. if CPU_REGS[1] >= 0x8000 then
  1295. CPU_REGS[3] = 0xFFFF
  1296. else
  1297. CPU_REGS[3] = 0x0000
  1298. end
  1299. end
  1300. -- CALL far
  1301. opcode_map[0x9A] = function(opcode)
  1302. local newIp = cpu_advance_ip16()
  1303. local newCs = cpu_advance_ip16()
  1304. cpu_push16(CPU_SEGMENTS[2])
  1305. cpu_push16(CPU_IP)
  1306. CPU_IP = newIp
  1307. CPU_SEGMENTS[2] = newCs
  1308. end
  1309. -- PUSHF/POPF
  1310. opcode_map[0x9C] = function(opcode) cpu_push16(CPU_FLAGS) end
  1311. -- ARCHNOTE: The 286 clears bits 12-15 in real mode.
  1312. opcode_map[0x9D] = function(opcode) CPU_FLAGS = cpu_pop16() | 0xF002 end
  1313. -- SAHF/LAHF
  1314. opcode_map[0x9E] = function(opcode)
  1315. CPU_FLAGS = (CPU_FLAGS & 0xFF00) | ((CPU_REGS[1] & 0xFF00) >> 8)
  1316. end
  1317. opcode_map[0x9F] = function(opcode)
  1318. CPU_REGS[1] = (CPU_REGS[1] & 0xFF) | ((CPU_FLAGS & 0xFF) << 8)
  1319. end
  1320. -- MOV offs->AL
  1321. opcode_map[0xA0] = function(opcode)
  1322. local addr = cpu_advance_ip16()
  1323. CPU_REGS[1] = (CPU_REGS[1] & 0xFF00) | RAM[((CPU_SEGMENTS[(CPU_SEGMOD or (4))]<<4) + (addr))]
  1324. end
  1325. -- MOV offs->AX
  1326. opcode_map[0xA1] = function(opcode)
  1327. local addr = cpu_advance_ip16()
  1328. CPU_REGS[1] = RAM:r16(((CPU_SEGMENTS[(CPU_SEGMOD or (4))]<<4) + (addr)))
  1329. end
  1330. -- MOV AL->offs
  1331. opcode_map[0xA2] = function(opcode)
  1332. local addr = cpu_advance_ip16()
  1333. RAM[((CPU_SEGMENTS[(CPU_SEGMOD or (4))]<<4) + (addr))] = CPU_REGS[1] & 0xFF
  1334. end
  1335. -- MOV AX->offs
  1336. opcode_map[0xA3] = function(opcode)
  1337. local addr = cpu_advance_ip16()
  1338. RAM:w16(((CPU_SEGMENTS[(CPU_SEGMOD or (4))]<<4) + (addr)), CPU_REGS[1])
  1339. end
  1340. -- MOVSB/MOVSW
  1341. opcode_map[0xA4] = function(opcode)
  1342. local addrSrc = ((CPU_SEGMENTS[(CPU_SEGMOD or (4))]<<4) + (CPU_REGS[7]))
  1343. local addrDst = ((CPU_SEGMENTS[(SEG_ES)+1]<<4)+(CPU_REGS[8]))
  1344. RAM[addrDst] = RAM[addrSrc]
  1345. cpu_incdec_dir(7, 1)
  1346. cpu_incdec_dir(8, 1)
  1347. end
  1348. opcode_map[0xA5] = function(opcode)
  1349. local addrSrc = ((CPU_SEGMENTS[(CPU_SEGMOD or (4))]<<4) + (CPU_REGS[7]))
  1350. local addrDst = ((CPU_SEGMENTS[(SEG_ES)+1]<<4)+(CPU_REGS[8]))
  1351. RAM:w16(addrDst, RAM:r16(addrSrc))
  1352. cpu_incdec_dir(7, 2)
  1353. cpu_incdec_dir(8, 2)
  1354. end
  1355. -- CMPSB/CMPSW
  1356. opcode_map[0xA6] = function(opcode)
  1357. local addrSrc = ((CPU_SEGMENTS[(CPU_SEGMOD or (4))]<<4) + (CPU_REGS[7]))
  1358. local addrDst = ((CPU_SEGMENTS[(SEG_ES)+1]<<4)+(CPU_REGS[8]))
  1359. cpu_cmp(RAM[addrSrc], RAM[addrDst], opcode)
  1360. cpu_incdec_dir(7, 1)
  1361. cpu_incdec_dir(8, 1)
  1362. end
  1363. opcode_map[0xA7] = function(opcode)
  1364. local addrSrc = ((CPU_SEGMENTS[(CPU_SEGMOD or (4))]<<4) + (CPU_REGS[7]))
  1365. local addrDst = ((CPU_SEGMENTS[(SEG_ES)+1]<<4)+(CPU_REGS[8]))
  1366. cpu_cmp(RAM:r16(addrSrc), RAM:r16(addrDst), opcode)
  1367. cpu_incdec_dir(7, 2)
  1368. cpu_incdec_dir(8, 2)
  1369. end
  1370. -- TEST AL, imm8
  1371. opcode_map[0xA8] = function(opcode)
  1372. _cpu_uf_bit((CPU_REGS[1] & cpu_advance_ip()) & 0xFF, 0)
  1373. end
  1374. -- TEST AX, imm16
  1375. opcode_map[0xA9] = function(opcode)
  1376. _cpu_uf_bit((CPU_REGS[1] & cpu_advance_ip16()), 1)
  1377. end
  1378. -- STOSB/STOSW
  1379. opcode_map[0xAA] = function(opcode)
  1380. local addrDst = ((CPU_SEGMENTS[(SEG_ES)+1]<<4)+(CPU_REGS[8]))
  1381. RAM[addrDst] = CPU_REGS[1] & 0xFF
  1382. cpu_incdec_dir(8, 1)
  1383. end
  1384. opcode_map[0xAB] = function(opcode)
  1385. local addrDst = ((CPU_SEGMENTS[(SEG_ES)+1]<<4)+(CPU_REGS[8]))
  1386. RAM:w16(addrDst, CPU_REGS[1])
  1387. cpu_incdec_dir(8, 2)
  1388. end
  1389. -- LODSB/LODSW
  1390. opcode_map[0xAC] = function(opcode)
  1391. local addrSrc = ((CPU_SEGMENTS[(CPU_SEGMOD or (4))]<<4) + (CPU_REGS[7]))
  1392. CPU_REGS[1] = (CPU_REGS[1] & 0xFF00) | RAM[addrSrc]
  1393. cpu_incdec_dir(7, 1)
  1394. end
  1395. opcode_map[0xAD] = function(opcode)
  1396. local addrSrc = ((CPU_SEGMENTS[(CPU_SEGMOD or (4))]<<4) + (CPU_REGS[7]))
  1397. CPU_REGS[1] = RAM:r16(addrSrc)
  1398. cpu_incdec_dir(7, 2)
  1399. end
  1400. -- SCASB/SCASW
  1401. opcode_map[0xAE] = function(opcode)
  1402. local addrDst = ((CPU_SEGMENTS[(SEG_ES)+1]<<4)+(CPU_REGS[8]))
  1403. cpu_cmp(CPU_REGS[1] & 0xFF, RAM[addrDst], opcode)
  1404. cpu_incdec_dir(8, 1)
  1405. end
  1406. opcode_map[0xAF] = function(opcode)
  1407. local addrDst = ((CPU_SEGMENTS[(SEG_ES)+1]<<4)+(CPU_REGS[8]))
  1408. cpu_cmp(CPU_REGS[1], RAM:r16(addrDst), opcode)
  1409. cpu_incdec_dir(8, 2)
  1410. end
  1411. -- MOV imm8
  1412. opcode_map[0xB0] = function(opcode) CPU_REGS[1] = (CPU_REGS[1] & 0xFF00) | (cpu_advance_ip()) end
  1413. opcode_map[0xB1] = function(opcode) CPU_REGS[2] = (CPU_REGS[2] & 0xFF00) | (cpu_advance_ip()) end
  1414. opcode_map[0xB2] = function(opcode) CPU_REGS[3] = (CPU_REGS[3] & 0xFF00) | (cpu_advance_ip()) end
  1415. opcode_map[0xB3] = function(opcode) CPU_REGS[4] = (CPU_REGS[4] & 0xFF00) | (cpu_advance_ip()) end
  1416. opcode_map[0xB4] = function(opcode) CPU_REGS[1] = (CPU_REGS[1] & 0xFF) | (cpu_advance_ip() << 8) end
  1417. opcode_map[0xB5] = function(opcode) CPU_REGS[2] = (CPU_REGS[2] & 0xFF) | (cpu_advance_ip() << 8) end
  1418. opcode_map[0xB6] = function(opcode) CPU_REGS[3] = (CPU_REGS[3] & 0xFF) | (cpu_advance_ip() << 8) end
  1419. opcode_map[0xB7] = function(opcode) CPU_REGS[4] = (CPU_REGS[4] & 0xFF) | (cpu_advance_ip() << 8) end
  1420. -- MOV imm16
  1421. opcode_map[0xB8] = function(opcode) CPU_REGS[1] = cpu_advance_ip16() end
  1422. opcode_map[0xB9] = function(opcode) CPU_REGS[2] = cpu_advance_ip16() end
  1423. opcode_map[0xBA] = function(opcode) CPU_REGS[3] = cpu_advance_ip16() end
  1424. opcode_map[0xBB] = function(opcode) CPU_REGS[4] = cpu_advance_ip16() end
  1425. opcode_map[0xBC] = function(opcode) CPU_REGS[5] = cpu_advance_ip16() end
  1426. opcode_map[0xBD] = function(opcode) CPU_REGS[6] = cpu_advance_ip16() end
  1427. opcode_map[0xBE] = function(opcode) CPU_REGS[7] = cpu_advance_ip16() end
  1428. opcode_map[0xBF] = function(opcode) CPU_REGS[8] = cpu_advance_ip16() end
  1429. -- RET near + pop
  1430. opcode_map[0xC2] = function(opcode)
  1431. local btp = cpu_advance_ip16()
  1432. CPU_IP = cpu_pop16()
  1433. CPU_REGS[5] = CPU_REGS[5] + btp
  1434. end
  1435. -- RET near
  1436. opcode_map[0xC3] = function(opcode)
  1437. CPU_IP = cpu_pop16()
  1438. end
  1439. -- LES/LDS
  1440. opcode_map[0xC4] = function(opcode)
  1441. local mrm = cpu_mod_rm(3)
  1442. local addr = cpu_addr_rm(mrm, mrm.src)
  1443. local defseg = cpu_seg_rm(mrm, mrm.src)
  1444. cpu_write_rm(mrm, mrm.dst, RAM:r16(((CPU_SEGMENTS[(CPU_SEGMOD or (defseg+1))]<<4) + (addr))))
  1445. if opcode == 0xC5 then
  1446. CPU_SEGMENTS[4] = RAM:r16(((CPU_SEGMENTS[(CPU_SEGMOD or (defseg+1))]<<4) + (addr + 2)))
  1447. else
  1448. CPU_SEGMENTS[1] = RAM:r16(((CPU_SEGMENTS[(CPU_SEGMOD or (defseg+1))]<<4) + (addr + 2)))
  1449. end
  1450. end
  1451. opcode_map[0xC5] = opcode_map[0xC4]
  1452. -- MOV imm(rm)
  1453. opcode_map[0xC6] = function(opcode)
  1454. local mrm = cpu_mod_rm(0)
  1455. cpu_write_rm(mrm, mrm.dst, cpu_advance_ip())
  1456. end
  1457. opcode_map[0xC7] = function(opcode)
  1458. local mrm = cpu_mod_rm(1)
  1459. cpu_write_rm(mrm, mrm.dst, cpu_advance_ip16())
  1460. end
  1461. -- RET far + pop
  1462. opcode_map[0xCA] = function(opcode)
  1463. local btp = cpu_advance_ip16()
  1464. CPU_IP = cpu_pop16()
  1465. CPU_SEGMENTS[2] = cpu_pop16()
  1466. CPU_REGS[5] = CPU_REGS[5] + btp
  1467. end
  1468. -- RET far
  1469. opcode_map[0xCB] = function(opcode)
  1470. CPU_IP = cpu_pop16()
  1471. CPU_SEGMENTS[2] = cpu_pop16()
  1472. end
  1473. -- INT 3
  1474. opcode_map[0xCC] = function(opcode)
  1475. -- cpu_int(3)
  1476. dump_memory()
  1477. platform_error("breakpoint")
  1478. end
  1479. -- INT imm
  1480. opcode_map[0xCD] = function(opcode) cpu_int(cpu_advance_ip()) end
  1481. -- INTO
  1482. opcode_map[0xCE] = function(opcode)
  1483. if ((CPU_FLAGS & (1<<(11))) ~= 0) then
  1484. cpu_int(4)
  1485. end
  1486. end
  1487. -- IRET far
  1488. opcode_map[0xCF] = function(opcode)
  1489. CPU_IP = cpu_pop16()
  1490. CPU_SEGMENTS[2] = cpu_pop16()
  1491. CPU_FLAGS = cpu_pop16()
  1492. end
  1493. local grp2_table = {
  1494. function(a,b) cpu_rotate(a,b,ROTATE_MODE_ROL) end,
  1495. function(a,b) cpu_rotate(a,b,ROTATE_MODE_ROR) end,
  1496. function(a,b) cpu_rotate(a,b,ROTATE_MODE_RCL) end,
  1497. function(a,b) cpu_rotate(a,b,ROTATE_MODE_RCR) end,
  1498. cpu_shl,
  1499. cpu_shr,
  1500. cpu_shl, -- SAL
  1501. function(a,b) cpu_shr(a,b,true) end
  1502. }
  1503. -- GRP2
  1504. opcode_map[0xD0] = function(opcode)
  1505. local mrm = cpu_mrm_copy(cpu_mod_rm(opcode & 0x01))
  1506. local v = (mrm.src & 0x07) + 1
  1507. mrm.src = 40
  1508. mrm.imm = 1
  1509. grp2_table[v](mrm,opcode)
  1510. end
  1511. opcode_map[0xD2] = function(opcode)
  1512. local mrm = cpu_mrm_copy(cpu_mod_rm(opcode & 0x01))
  1513. local v = (mrm.src & 0x07) + 1
  1514. mrm.src = 17
  1515. grp2_table[v](mrm,opcode)
  1516. end
  1517. if cpu_arch ~= "8086" then
  1518. opcode_map[0xC0] = function(opcode)
  1519. local mrm = cpu_mrm_copy(cpu_mod_rm(opcode & 0x01))
  1520. local v = (mrm.src & 0x07) + 1
  1521. mrm.src = 40
  1522. mrm.imm = cpu_advance_ip()
  1523. grp2_table[v](mrm,opcode)
  1524. end
  1525. opcode_map[0xC1] = opcode_map[0xD0]
  1526. end
  1527. opcode_map[0xD1] = opcode_map[0xD0]
  1528. opcode_map[0xD3] = opcode_map[0xD2]
  1529. -- AAM
  1530. opcode_map[0xD4] = function(opcode)
  1531. local base = cpu_advance_ip()
  1532. local old_al = CPU_REGS[1] & 0xFF
  1533. local ah = math.floor(old_al / base)
  1534. local al = old_al % base
  1535. CPU_REGS[1] = ((ah & 0xFF) << 8) | (al & 0xFF)
  1536. _cpu_uf_zsp(al, 0)
  1537. end
  1538. -- AAD
  1539. opcode_map[0xD5] = function(opcode)
  1540. local base = cpu_advance_ip()
  1541. local old_al = CPU_REGS[1] & 0xFF
  1542. local old_ah = (CPU_REGS[1] >> 8) & 0xFF
  1543. CPU_REGS[1] = (old_al + (old_ah * base)) & 0xFF
  1544. _cpu_uf_zsp(CPU_REGS[1], 0)
  1545. end
  1546. -- SALC (undocumented)
  1547. opcode_map[0xD6] = function(opcode)
  1548. if ((CPU_FLAGS & (1<<(0))) ~= 0) then
  1549. CPU_REGS[1] = CPU_REGS[1] | 0xFF
  1550. else
  1551. CPU_REGS[1] = CPU_REGS[1] & 0xFF00
  1552. end
  1553. end
  1554. -- XLAT
  1555. opcode_map[0xD7] = function(opcode)
  1556. local addr = (CPU_REGS[4] + (CPU_REGS[1] & 0xFF)) & 0xFFFF
  1557. CPU_REGS[1] = (CPU_REGS[1] & 0xFF00) | RAM[((CPU_SEGMENTS[(CPU_SEGMOD or (4))]<<4) + (addr))]
  1558. end
  1559. -- LOOPNZ r8
  1560. opcode_map[0xE0] = function(opcode)
  1561. local offset = to_s8(cpu_advance_ip())
  1562. CPU_REGS[2] = CPU_REGS[2] - 1
  1563. if CPU_REGS[2] ~= 0 and not ((CPU_FLAGS & (1<<(6))) ~= 0) then
  1564. CPU_IP = (CPU_IP + offset) & 0xFFFF
  1565. end
  1566. end
  1567. -- LOOPZ r8
  1568. opcode_map[0xE1] = function(opcode)
  1569. local offset = to_s8(cpu_advance_ip())
  1570. CPU_REGS[2] = CPU_REGS[2] - 1
  1571. if CPU_REGS[2] ~= 0 and ((CPU_FLAGS & (1<<(6))) ~= 0) then
  1572. CPU_IP = (CPU_IP + offset) & 0xFFFF
  1573. end
  1574. end
  1575. -- LOOP r8
  1576. opcode_map[0xE2] = function(opcode)
  1577. local offset = to_s8(cpu_advance_ip())
  1578. CPU_REGS[2] = CPU_REGS[2] - 1
  1579. if CPU_REGS[2] ~= 0 then
  1580. CPU_IP = (CPU_IP + offset) & 0xFFFF
  1581. end
  1582. end
  1583. -- JCXZ r8
  1584. opcode_map[0xE3] = function(opcode)
  1585. local offset = to_s8(cpu_advance_ip())
  1586. if CPU_REGS[2] == 0 then
  1587. CPU_IP = (CPU_IP + offset) & 0xFFFF
  1588. end
  1589. end
  1590. -- IN AL, Ib
  1591. opcode_map[0xE4] = function(opcode)
  1592. CPU_REGS[1] = (CPU_REGS[1] & 0xFF00) | (cpu_in(cpu_advance_ip()) & 0xFF)
  1593. end
  1594. -- IN AX, Ib
  1595. opcode_map[0xE5] = function(opcode)
  1596. CPU_REGS[1] = (cpu_in(cpu_advance_ip()) & 0xFFFF)
  1597. end
  1598. -- OUT AL, Ib
  1599. opcode_map[0xE6] = function(opcode)
  1600. cpu_out(cpu_advance_ip(), CPU_REGS[1] & 0xFF)
  1601. end
  1602. -- OUT AX, Ib
  1603. opcode_map[0xE7] = function(opcode)
  1604. cpu_out(cpu_advance_ip(), CPU_REGS[1])
  1605. end
  1606. -- CALL rel16
  1607. opcode_map[0xE8] = function(opcode)
  1608. local offset = to_s16(cpu_advance_ip16())
  1609. cpu_push16(CPU_IP)
  1610. CPU_IP = (CPU_IP + offset) & 0xFFFF
  1611. end
  1612. -- JMP rel16
  1613. opcode_map[0xE9] = function(opcode)
  1614. local offset = to_s16(cpu_advance_ip16())
  1615. CPU_IP = (CPU_IP + offset) & 0xFFFF
  1616. end
  1617. -- JMP ptr
  1618. opcode_map[0xEA] = function(opcode)
  1619. local newIp = cpu_advance_ip16()
  1620. local newCs = cpu_advance_ip16()
  1621. CPU_IP = newIp
  1622. CPU_SEGMENTS[2] = newCs
  1623. end
  1624. -- JMP r8
  1625. opcode_map[0xEB] = function(opcode)
  1626. local offset = to_s8(cpu_advance_ip())
  1627. CPU_IP = (CPU_IP + offset) & 0xFFFF
  1628. end
  1629. -- IN AL, DX
  1630. opcode_map[0xEC] = function(opcode)
  1631. CPU_REGS[1] = (CPU_REGS[1] & 0xFF00) | (cpu_in(CPU_REGS[3]) & 0xFF)
  1632. end
  1633. -- IN AX, DX
  1634. opcode_map[0xED] = function(opcode)
  1635. CPU_REGS[1] = (cpu_in(CPU_REGS[3]) & 0xFFFF)
  1636. end
  1637. -- OUT AL, DX
  1638. opcode_map[0xEE] = function(opcode)
  1639. cpu_out(CPU_REGS[3], CPU_REGS[1] & 0xFF)
  1640. end
  1641. -- OUT AX, DX
  1642. opcode_map[0xEF] = function(opcode)
  1643. cpu_out(CPU_REGS[3], CPU_REGS[1])
  1644. end
  1645. -- LOCK
  1646. opcode_map[0xF0] = function(opcode)
  1647. -- We're not hardware, we can ignore this
  1648. end
  1649. -- REPNZ
  1650. opcode_map[0xF2] = function(opcode)
  1651. if not cpu_rep(function() return not ((CPU_FLAGS & (1<<(6))) ~= 0) end) then return false end
  1652. end
  1653. -- REPZ
  1654. opcode_map[0xF3] = function(opcode)
  1655. if not cpu_rep(function() return ((CPU_FLAGS & (1<<(6))) ~= 0) end) then return false end
  1656. end
  1657. -- HLT
  1658. opcode_map[0xF4] = function(opcode)
  1659. CPU_HALTED = true
  1660. return "block"
  1661. end
  1662. -- CMC
  1663. opcode_map[0xF5] = function(opcode) CPU_FLAGS = CPU_FLAGS ~ (1 << (0)) end
  1664. -- GRP3
  1665. local grp3_table = {}
  1666. grp3_table[0] = function(mrm, opcode)
  1667. mrm = cpu_mrm_copy(mrm)
  1668. if opcode == 0xF7 then
  1669. mrm.src = 41
  1670. mrm.imm = cpu_advance_ip16()
  1671. else
  1672. mrm.src = 40
  1673. mrm.imm = cpu_advance_ip()
  1674. end
  1675. cpu_test(mrm, opcode)
  1676. end
  1677. grp3_table[1] = function()
  1678. platform_error("invalid opcode: GRP3/1")
  1679. end
  1680. -- GRP3/NOT
  1681. grp3_table[2] = function(mrm, opcode)
  1682. if opcode == 0xF7 then
  1683. cpu_write_rm(mrm, mrm.dst, cpu_read_rm(mrm, mrm.dst) ~ 0xFFFF)
  1684. else
  1685. cpu_write_rm(mrm, mrm.dst, cpu_read_rm(mrm, mrm.dst) ~ 0xFF)
  1686. end
  1687. end
  1688. -- GRP3/NEG
  1689. grp3_table[3] = function(mrm, opcode)
  1690. local src = cpu_read_rm(mrm, mrm.dst)
  1691. local result = 0
  1692. if opcode == 0xF7 then
  1693. result = ((src ~ 0xFFFF) + 1) & 0xFFFF
  1694. cpu_write_flag(11, src == 0x8000)
  1695. else
  1696. result = ((src ~ 0xFF) + 1) & 0xFF
  1697. cpu_write_flag(11, src == 0x80)
  1698. end
  1699. cpu_write_rm(mrm, mrm.dst, result)
  1700. cpu_write_flag(0, src ~= 0)
  1701. cpu_write_flag(4, ((src ~ result) & 0x10) ~= 0)
  1702. _cpu_uf_zsp(result, opcode)
  1703. end
  1704. grp3_table[4] = cpu_mul
  1705. grp3_table[5] = cpu_imul
  1706. grp3_table[6] = cpu_div
  1707. grp3_table[7] = cpu_idiv
  1708. opcode_map[0xF6] = function(opcode)
  1709. local mrm = cpu_mod_rm(opcode & 0x01)
  1710. local v = mrm.src & 0x07
  1711. if v >= 4 then
  1712. mrm = cpu_mrm_copy(mrm)
  1713. if opcode == 0xF7 then mrm.src = 0 else mrm.src = 16 end
  1714. end
  1715. grp3_table[v](mrm, opcode)
  1716. end
  1717. opcode_map[0xF7] = opcode_map[0xF6]
  1718. -- flag setters
  1719. opcode_map[0xF8] = function(opcode) CPU_FLAGS = CPU_FLAGS & (~(1 << (0))) end
  1720. opcode_map[0xF9] = function(opcode) CPU_FLAGS = CPU_FLAGS | (1 << (0)) end
  1721. opcode_map[0xFA] = function(opcode) CPU_FLAGS = CPU_FLAGS & (~(1 << (9))) end
  1722. opcode_map[0xFB] = function(opcode) CPU_FLAGS = CPU_FLAGS | (1 << (9)) end
  1723. opcode_map[0xFC] = function(opcode) CPU_FLAGS = CPU_FLAGS & (~(1 << (10))) end
  1724. opcode_map[0xFD] = function(opcode) CPU_FLAGS = CPU_FLAGS | (1 << (10)) end
  1725. -- GRP4
  1726. opcode_map[0xFE] = function(opcode)
  1727. local mrm = cpu_mod_rm(0)
  1728. local v = mrm.src & 0x07
  1729. -- emu_debug(0, "GRP4/"..v)
  1730. if v == 0 then -- INC
  1731. local v = (cpu_read_rm(mrm,mrm.dst) + 1) & 0xFF
  1732. cpu_write_rm(mrm,mrm.dst,v)
  1733. _cpu_uf_inc(v, 0)
  1734. elseif v == 1 then -- DEC
  1735. local v = (cpu_read_rm(mrm,mrm.dst) - 1) & 0xFF
  1736. cpu_write_rm(mrm,mrm.dst,v)
  1737. _cpu_uf_dec(v, 0)
  1738. else platform_error("GRP4 todo: " .. v) end
  1739. end
  1740. -- GRP5
  1741. opcode_map[0xFF] = function(opcode)
  1742. local mrm = cpu_mod_rm(1)
  1743. local v = mrm.src & 0x07
  1744. -- emu_debug(0,"GRP5/"..v)
  1745. if v == 0 then -- INC
  1746. local v = (cpu_read_rm(mrm,mrm.dst) + 1) & 0xFFFF
  1747. cpu_write_rm(mrm,mrm.dst,v)
  1748. _cpu_uf_inc(v, 1)
  1749. elseif v == 1 then -- DEC
  1750. local v = (cpu_read_rm(mrm,mrm.dst) - 1) & 0xFFFF
  1751. cpu_write_rm(mrm,mrm.dst,v)
  1752. _cpu_uf_dec(v, 1)
  1753. elseif v == 2 then -- CALL near abs
  1754. local newIp = cpu_read_rm(mrm,mrm.dst)
  1755. cpu_push16(CPU_IP)
  1756. CPU_IP = newIp
  1757. elseif v == 3 then -- CALL far abs
  1758. local addr = ((CPU_SEGMENTS[(CPU_SEGMOD or (cpu_seg_rm(mrm,mrm.dst)+1))]<<4) + (cpu_addr_rm(mrm,mrm.dst)))
  1759. local newIp = RAM:r16(addr)
  1760. local newCs = RAM:r16(addr+2)
  1761. cpu_push16(CPU_SEGMENTS[2])
  1762. cpu_push16(CPU_IP)
  1763. CPU_IP = newIp
  1764. CPU_SEGMENTS[2] = newCs
  1765. elseif v == 4 then -- JMP near abs
  1766. CPU_IP = cpu_read_rm(mrm,mrm.dst)
  1767. elseif v == 5 then -- JMP far
  1768. local addr = ((CPU_SEGMENTS[(CPU_SEGMOD or (cpu_seg_rm(mrm,mrm.dst)+1))]<<4) + (cpu_addr_rm(mrm,mrm.dst)))
  1769. local newIp = RAM:r16(addr)
  1770. local newCs = RAM:r16(addr+2)
  1771. CPU_IP = newIp
  1772. CPU_SEGMENTS[2] = newCs
  1773. elseif v == 6 then cpu_push16(cpu_read_rm(mrm,mrm.dst))
  1774. else platform_error("GRP5 todo: " .. v) end
  1775. end
  1776. -- 8087 FPU stubs
  1777. opcode_map[0x9B] = function(opcode) end
  1778. for i=0xD8,0xDF do
  1779. opcode_map[i] = function(opcode) cpu_mod_rm(1) end
  1780. end
  1781. if cpu_arch == "8086" then
  1782. -- 8086 0xCX opcode aliases
  1783. opcode_map[0xC0] = opcode_map[0xC2]
  1784. opcode_map[0xC1] = opcode_map[0xC3]
  1785. opcode_map[0xC8] = opcode_map[0xCA]
  1786. opcode_map[0xC9] = opcode_map[0xCB]
  1787. end
  1788. run_one = function(no_interrupting, pr_state)
  1789. if CPU_HASINT and not no_interrupting then
  1790. -- local intr = table.remove(CPU_INTQUEUE, 1)
  1791. local intr = CPU_INTQUEUE[1]
  1792. if intr ~= nil then
  1793. if intr >= 256 or ((CPU_FLAGS & (1<<(9))) ~= 0) then
  1794. table.remove(CPU_INTQUEUE, 1)
  1795. cpu_int(intr & 0xFF)
  1796. if #CPU_INTQUEUE == 0 then CPU_HASINT = false end
  1797. end
  1798. end
  1799. end
  1800. if ((CPU_IP & 0xFF00) == 0x1100) and (CPU_SEGMENTS[2] == 0xF000) then
  1801. CPU_FLAGS = CPU_FLAGS | (1 << (9)) -- enable interrupts during (after!) fake handlers
  1802. local intr = cpu_int_fake(CPU_IP & 0xFF)
  1803. if intr ~= "block" then
  1804. CPU_IP = cpu_pop16()
  1805. CPU_SEGMENTS[2] = cpu_pop16()
  1806. local old_flags = cpu_pop16()
  1807. local old_flag_mask = 0x0200
  1808. CPU_FLAGS = (CPU_FLAGS & (~old_flag_mask)) | (old_flags & old_flag_mask)
  1809. return true
  1810. else
  1811. return "block"
  1812. end
  1813. end
  1814. local opcode = cpu_advance_ip()
  1815. local om = opcode_map[opcode]
  1816. if om ~= nil then
  1817. local result = om(opcode)
  1818. if result ~= nil then
  1819. return result
  1820. else
  1821. return true
  1822. end
  1823. else
  1824. emu_debug(2, "unknown opcode: " .. string.format("%02X", opcode))
  1825. cpu_print_state(opcode)
  1826. cpu_emit_interrupt(6, false)
  1827. return true
  1828. end
  1829. end
  1830. function cpu_emit_interrupt(v, nmi)
  1831. nmi = (v == 2)
  1832. if nmi then
  1833. table.insert(CPU_INTQUEUE, v + 256)
  1834. else
  1835. table.insert(CPU_INTQUEUE, v)
  1836. end
  1837. CPU_HASINT = true
  1838. end
  1839. -- invalid opcode interrupt
  1840. cpu_register_interrupt_handler(0x06, function(ax,ah,al)
  1841. -- dummy - override by user
  1842. return true
  1843. end)
  1844. -- keyboard interrupt
  1845. cpu_register_interrupt_handler(0x09, function(ax,ah,al)
  1846. -- dummy - override by user
  1847. return true
  1848. end)
  1849. dofile("pic.lua")
  1850. dofile("pit.lua")
  1851. dofile("timer.lua")
  1852. dofile("video.lua")
  1853. dofile("disks.lua")
  1854. dofile("keyboard.lua")
  1855. dofile("sysconf.lua")
  1856. dofile("comms.lua")
  1857. local last_opc = 0
  1858. local opc_avg = {}
  1859. local opc_avg_i = 0
  1860. local clock = os.clock()
  1861. local function upd_count(last_clock)
  1862. opc_avg_i = (opc_avg_i + 1) % 20
  1863. opc_avg[opc_avg_i + 1] = ((opc - last_opc) / (clock - last_clock))
  1864. local oa = 0
  1865. local oac = 0
  1866. for i=1,20 do
  1867. if opc_avg[i] then
  1868. oa = oa + opc_avg[i]
  1869. oac = oac + 1
  1870. end
  1871. end
  1872. emu_debug(2, (oa / oac) .. " IPS")
  1873. opc = last_opc
  1874. end
  1875. local oc_tick_i = 0
  1876. local function upd_tick(cv)
  1877. local last_clock = clock
  1878. clock = cv
  1879. -- handle video
  1880. video_update()
  1881. keyboard_update()
  1882. pit_tick(clock)
  1883. -- handle OC waits
  1884. cv = os.clock()
  1885. if (cv - clock) < 0.05 then
  1886. oc_tick_i = oc_tick_i + 1
  1887. -- if (oc_tick_i % 3) == 0 then
  1888. platform_sleep(0)
  1889. -- end
  1890. end
  1891. --cv = os.clock()
  1892. -- handle pc speaker
  1893. if (kbd_get_spkr_latch() & 0x03) == 0x03 then
  1894. local pch = pit_channel(3)
  1895. if (pch.mode == 2 or pch.mode == 3 or pch.mode == 6 or pch.mode == 7) and (pch.reload_set_lo and pch.reload_set_hi) then
  1896. local freq = (pit_osc_freq * 1000000) / pch.reload
  1897. platform_beep(freq, 0.05)
  1898. end
  1899. end
  1900. clock = cv
  1901. end
  1902. local function cpu_execute()
  1903. if CPU_HALTED and not CPU_HASINT then return "block" end
  1904. execute = true
  1905. while execute == true do
  1906. execute = run_one(false, true)
  1907. if execute == "block" then
  1908. upd_tick(os.clock())
  1909. execute = true
  1910. elseif ((opc & 0x1FF) == 0) and (os.clock() - clock) >= 0.05 then
  1911. upd_tick(os.clock())
  1912. end
  1913. opc = opc + 1
  1914. end
  1915. platform_error("execution stopped\n")
  1916. end
  1917. function emu_execute()
  1918. CPU_FLAGS = 0x0202
  1919. sysconf_init()
  1920. -- set IVT locations to NOP or IRET
  1921. for i=0,255 do
  1922. if interrupt_handlers[i+1] then
  1923. RAM[0xF1100+i] = 0x90
  1924. else
  1925. RAM[0xF1100+i] = 0xCF
  1926. end
  1927. end
  1928. cpu_execute()
  1929. end