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_pre.lua 57KB

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