string.macro.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. "use strict";
  2. /*
  3. * string operations
  4. *
  5. * cmp si di
  6. * movs 0 1 1 A4
  7. * cmps 1 1 1 A6
  8. * stos 0 0 1 AA
  9. * lods 0 1 0 AC
  10. * scas 1 0 1 AE
  11. * ins 0 0 1
  12. * outs 0 1 0
  13. */
  14. #define string_instruction(s, use_cmp, use_di, use_si, fn, aligned_fn)\
  15. var src, dest, data_src, data_dest;\
  16. var size = flags & flag_direction ? -(s >> 3) : s >> 3;\
  17. var ds, es;\
  18. if(use_cmp && !use_si) data_src = reg ## s[reg_eax];\
  19. if(use_di) es = get_seg(reg_es), dest = es + regv[reg_vdi];\
  20. if(use_si) ds = get_seg_prefix(reg_ds), src = ds + regv[reg_vsi];\
  21. if(repeat_string_prefix) {\
  22. if(regv[reg_vcx] === 0) return;\
  23. var aligned = s > 8 && (!use_di || (dest & (s >> 3) - 1) === 0) && (!use_si || (src & (s >> 3) - 1) === 0);\
  24. do {\
  25. if(aligned) {\
  26. aligned_fn;\
  27. } else {\
  28. fn;\
  29. }\
  30. if(use_di) dest += size, regv[reg_vdi] += size;\
  31. if(use_si) src += size, regv[reg_vsi] += size;\
  32. } while(--regv[reg_vcx] && (!use_cmp || (data_src === data_dest) === repeat_string_type));\
  33. } else {\
  34. fn;\
  35. if(use_di) regv[reg_vdi] += size;\
  36. if(use_si) regv[reg_vsi] += size;\
  37. }\
  38. if(use_cmp) cmp ## s(data_src, data_dest);\
  39. function movsb()
  40. {
  41. string_instruction(8, false, true, true,
  42. {
  43. safe_write8(dest, safe_read8(src));
  44. }, {});
  45. }
  46. function movsw()
  47. {
  48. string_instruction(16, false, true, true,
  49. {
  50. safe_write16(dest, safe_read16(src));
  51. }, {
  52. var phys_src = translate_address_read(src);
  53. var phys_dest = translate_address_write(dest);
  54. memory.write_aligned16(phys_dest, memory.read_aligned16(phys_src));
  55. });
  56. }
  57. function movsd()
  58. {
  59. string_instruction(32, false, true, true,
  60. {
  61. safe_write32(dest, safe_read32s(src));
  62. }, {
  63. var phys_src = translate_address_read(src);
  64. var phys_dest = translate_address_write(dest);
  65. memory.write_aligned32(phys_dest, memory.read_aligned32(phys_src));
  66. });
  67. }
  68. function cmpsb()
  69. {
  70. string_instruction(8, true, true, true,
  71. {
  72. data_dest = safe_read8(dest);
  73. data_src = safe_read8(src);
  74. }, {});
  75. }
  76. function cmpsw()
  77. {
  78. string_instruction(16, true, true, true,
  79. {
  80. data_dest = safe_read16(dest);
  81. data_src = safe_read16(src);
  82. }, {
  83. data_dest = memory.read_aligned16(translate_address_read(dest));
  84. data_src = memory.read_aligned16(translate_address_read(src));
  85. });
  86. }
  87. function cmpsd()
  88. {
  89. string_instruction(32, true, true, true,
  90. {
  91. data_dest = safe_read32(dest);
  92. data_src = safe_read32(src);
  93. }, {
  94. data_dest = memory.read_aligned32(translate_address_read(dest)) >>> 0;
  95. data_src = memory.read_aligned32(translate_address_read(src)) >>> 0;
  96. });
  97. }
  98. function stosb()
  99. {
  100. var data = reg8[reg_al];
  101. string_instruction(8, false, true, false,
  102. {
  103. safe_write8(dest, data);
  104. }, {});
  105. }
  106. function stosw()
  107. {
  108. var data = reg16[reg_ax];
  109. string_instruction(16, false, true, false,
  110. {
  111. safe_write16(dest, data);
  112. }, {
  113. memory.write_aligned16(translate_address_write(dest), data);
  114. });
  115. }
  116. function stosd()
  117. {
  118. //dbg_log("stosd " + ((reg32[reg_edi] & 3) ? "mis" : "") + "aligned", LOG_CPU);
  119. var data = reg32[reg_eax];
  120. string_instruction(32, false, true, false,
  121. {
  122. safe_write32(dest, data);
  123. }, {
  124. memory.write_aligned32(translate_address_write(dest), data);
  125. });
  126. }
  127. function lodsb()
  128. {
  129. string_instruction(8, false, false, true,
  130. {
  131. reg8[reg_al] = safe_read8(src);
  132. }, {});
  133. }
  134. function lodsw()
  135. {
  136. string_instruction(16, false, false, true,
  137. {
  138. reg16[reg_ax] = safe_read16(src);
  139. }, {
  140. reg16[reg_ax] = safe_read16(src);
  141. });
  142. }
  143. function lodsd()
  144. {
  145. string_instruction(32, false, false, true,
  146. {
  147. reg32[reg_eax] = safe_read32s(src);
  148. }, {
  149. reg32[reg_eax] = safe_read32s(src);
  150. });
  151. }
  152. function scasb()
  153. {
  154. string_instruction(8, true, true, false,
  155. {
  156. data_dest = safe_read8(dest);
  157. }, {});
  158. }
  159. function scasw()
  160. {
  161. string_instruction(16, true, true, false,
  162. {
  163. data_dest = safe_read16(dest);
  164. }, {
  165. data_dest = memory.read_aligned16(translate_address_read(dest));
  166. });
  167. }
  168. function scasd()
  169. {
  170. string_instruction(32, true, true, false,
  171. {
  172. data_dest = safe_read32(dest);
  173. }, {
  174. data_dest = memory.read_aligned32(translate_address_read(dest)) >>> 0;
  175. });
  176. }
  177. function insb()
  178. {
  179. var port = reg16[reg_dx];
  180. string_instruction(8, false, true, false,
  181. {
  182. safe_write8(dest, in8(port));
  183. }, {
  184. });
  185. }
  186. function insw()
  187. {
  188. var port = reg16[reg_dx];
  189. string_instruction(8, false, true, false,
  190. {
  191. safe_write16(dest, in16(port));
  192. }, {
  193. var phys_dest = translate_address_write(dest);
  194. memory.write_aligned16(phys_dest, in16(port));
  195. });
  196. }
  197. function insd()
  198. {
  199. var port = reg16[reg_dx];
  200. string_instruction(32, false, true, false,
  201. {
  202. safe_write32(dest, in32(port));
  203. }, {
  204. var phys_dest = translate_address_write(dest);
  205. memory.write_aligned32(phys_dest, in32(port));
  206. });
  207. }
  208. function outsb()
  209. {
  210. var port = reg16[reg_dx];
  211. string_instruction(8, false, false, true,
  212. {
  213. out8(port, safe_read8(src));
  214. }, {
  215. out8(port, safe_read8(src));
  216. });
  217. }
  218. function outsw()
  219. {
  220. var port = reg16[reg_dx];
  221. string_instruction(16, false, false, true,
  222. {
  223. out16(port, safe_read16(src));
  224. }, {
  225. out16(port, safe_read16(src));
  226. });
  227. }
  228. function outsd()
  229. {
  230. var port = reg16[reg_dx];
  231. string_instruction(32, false, false, true,
  232. {
  233. out32(port, safe_read32s(src));
  234. }, {
  235. out32(port, safe_read32s(src));
  236. });
  237. }