modrm.rs 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. use codegen;
  2. use cpu::global_pointers;
  3. use cpu_context::CpuContext;
  4. use jit::JitContext;
  5. use prefix::{PREFIX_MASK_SEGMENT, SEG_PREFIX_ZERO};
  6. use profiler;
  7. use regs::{BP, BX, DI, SI};
  8. use regs::{CS, DS, SS};
  9. use regs::{EAX, EBP, EBX, ECX, EDI, EDX, ESI, ESP};
  10. pub struct ModrmByte {
  11. segment: u32,
  12. first_reg: Option<u32>,
  13. second_reg: Option<u32>,
  14. shift: u8,
  15. immediate: i32,
  16. is_16: bool,
  17. }
  18. pub fn decode(ctx: &mut CpuContext, modrm_byte: u8) -> ModrmByte {
  19. if ctx.asize_32() { decode32(ctx, modrm_byte) } else { decode16(ctx, modrm_byte) }
  20. }
  21. fn decode16(ctx: &mut CpuContext, modrm_byte: u8) -> ModrmByte {
  22. fn mk16(
  23. segment: u32,
  24. first_reg: Option<u32>,
  25. second_reg: Option<u32>,
  26. immediate: i32,
  27. ) -> ModrmByte {
  28. ModrmByte {
  29. segment,
  30. first_reg,
  31. second_reg,
  32. shift: 0,
  33. immediate,
  34. is_16: true,
  35. }
  36. }
  37. match modrm_byte & !0o070 {
  38. 0o000 => mk16(DS, Some(BX), Some(SI), 0),
  39. 0o001 => mk16(DS, Some(BX), Some(DI), 0),
  40. 0o002 => mk16(SS, Some(BP), Some(SI), 0),
  41. 0o003 => mk16(SS, Some(BP), Some(DI), 0),
  42. 0o004 => mk16(DS, Some(SI), None, 0),
  43. 0o005 => mk16(DS, Some(DI), None, 0),
  44. 0o006 => mk16(DS, None, None, ctx.read_imm16() as i32),
  45. 0o007 => mk16(DS, Some(BX), None, 0),
  46. 0o100 => mk16(DS, Some(BX), Some(SI), ctx.read_imm8s() as i32),
  47. 0o101 => mk16(DS, Some(BX), Some(DI), ctx.read_imm8s() as i32),
  48. 0o102 => mk16(SS, Some(BP), Some(SI), ctx.read_imm8s() as i32),
  49. 0o103 => mk16(SS, Some(BP), Some(DI), ctx.read_imm8s() as i32),
  50. 0o104 => mk16(DS, Some(SI), None, ctx.read_imm8s() as i32),
  51. 0o105 => mk16(DS, Some(DI), None, ctx.read_imm8s() as i32),
  52. 0o106 => mk16(SS, Some(BP), None, ctx.read_imm8s() as i32),
  53. 0o107 => mk16(DS, Some(BX), None, ctx.read_imm8s() as i32),
  54. 0o200 => mk16(DS, Some(BX), Some(SI), ctx.read_imm16() as i32),
  55. 0o201 => mk16(DS, Some(BX), Some(DI), ctx.read_imm16() as i32),
  56. 0o202 => mk16(SS, Some(BP), Some(SI), ctx.read_imm16() as i32),
  57. 0o203 => mk16(SS, Some(BP), Some(DI), ctx.read_imm16() as i32),
  58. 0o204 => mk16(DS, Some(SI), None, ctx.read_imm16() as i32),
  59. 0o205 => mk16(DS, Some(DI), None, ctx.read_imm16() as i32),
  60. 0o206 => mk16(SS, Some(BP), None, ctx.read_imm16() as i32),
  61. 0o207 => mk16(DS, Some(BX), None, ctx.read_imm16() as i32),
  62. _ => panic!("modrm byte >= 0xC0"),
  63. }
  64. }
  65. fn decode32(ctx: &mut CpuContext, modrm_byte: u8) -> ModrmByte {
  66. fn mk32(segment: u32, first_reg: Option<u32>, immediate: i32) -> ModrmByte {
  67. ModrmByte {
  68. segment,
  69. first_reg,
  70. second_reg: None,
  71. shift: 0,
  72. immediate,
  73. is_16: false,
  74. }
  75. }
  76. match modrm_byte & !0o070 {
  77. 0o000 => mk32(DS, Some(EAX), 0),
  78. 0o001 => mk32(DS, Some(ECX), 0),
  79. 0o002 => mk32(DS, Some(EDX), 0),
  80. 0o003 => mk32(DS, Some(EBX), 0),
  81. 0o004 => decode_sib(ctx, Imm32::None),
  82. 0o005 => mk32(DS, None, ctx.read_imm32() as i32),
  83. 0o006 => mk32(DS, Some(ESI), 0),
  84. 0o007 => mk32(DS, Some(EDI), 0),
  85. 0o100 => mk32(DS, Some(EAX), ctx.read_imm8s() as i32),
  86. 0o101 => mk32(DS, Some(ECX), ctx.read_imm8s() as i32),
  87. 0o102 => mk32(DS, Some(EDX), ctx.read_imm8s() as i32),
  88. 0o103 => mk32(DS, Some(EBX), ctx.read_imm8s() as i32),
  89. 0o104 => decode_sib(ctx, Imm32::Imm8),
  90. 0o105 => mk32(SS, Some(EBP), ctx.read_imm8s() as i32),
  91. 0o106 => mk32(DS, Some(ESI), ctx.read_imm8s() as i32),
  92. 0o107 => mk32(DS, Some(EDI), ctx.read_imm8s() as i32),
  93. 0o200 => mk32(DS, Some(EAX), ctx.read_imm32() as i32),
  94. 0o201 => mk32(DS, Some(ECX), ctx.read_imm32() as i32),
  95. 0o202 => mk32(DS, Some(EDX), ctx.read_imm32() as i32),
  96. 0o203 => mk32(DS, Some(EBX), ctx.read_imm32() as i32),
  97. 0o204 => decode_sib(ctx, Imm32::Imm32),
  98. 0o205 => mk32(SS, Some(EBP), ctx.read_imm32() as i32),
  99. 0o206 => mk32(DS, Some(ESI), ctx.read_imm32() as i32),
  100. 0o207 => mk32(DS, Some(EDI), ctx.read_imm32() as i32),
  101. _ => panic!("modrm byte >= 0xC0"),
  102. }
  103. }
  104. fn decode_sib(ctx: &mut CpuContext, immediate: Imm32) -> ModrmByte {
  105. let sib_byte = ctx.read_imm8();
  106. let r = sib_byte & 7;
  107. let m = sib_byte >> 3 & 7;
  108. let shift = sib_byte >> 6 & 3;
  109. let second_reg = if m == 4 { None } else { Some(m as u32) };
  110. let segment;
  111. let reg;
  112. if r == 4 {
  113. segment = SS;
  114. reg = ESP;
  115. }
  116. else if r == 5 {
  117. if immediate == Imm32::None {
  118. return ModrmByte {
  119. segment: DS,
  120. first_reg: None,
  121. second_reg,
  122. shift,
  123. immediate: ctx.read_imm32() as i32,
  124. is_16: false,
  125. };
  126. }
  127. else {
  128. segment = SS;
  129. reg = EBP;
  130. }
  131. }
  132. else {
  133. segment = DS;
  134. reg = r as u32;
  135. }
  136. let immediate = match immediate {
  137. Imm32::None => 0,
  138. Imm32::Imm8 => ctx.read_imm8s() as i32,
  139. Imm32::Imm32 => ctx.read_imm32() as i32,
  140. };
  141. ModrmByte {
  142. segment,
  143. first_reg: Some(reg),
  144. second_reg,
  145. shift,
  146. immediate,
  147. is_16: false,
  148. }
  149. }
  150. pub fn gen(ctx: &mut JitContext, modrm_byte: ModrmByte) {
  151. codegen::gen_profiler_stat_increment(
  152. ctx.builder,
  153. match modrm_byte {
  154. ModrmByte {
  155. first_reg: None,
  156. second_reg: None,
  157. ..
  158. } => profiler::stat::MODRM_SIMPLE_CONST_OFFSET,
  159. ModrmByte {
  160. first_reg: Some(_),
  161. second_reg: None,
  162. ..
  163. }
  164. | ModrmByte {
  165. first_reg: None,
  166. second_reg: Some(_),
  167. shift: 0,
  168. ..
  169. } => {
  170. if modrm_byte.immediate == 0 {
  171. profiler::stat::MODRM_SIMPLE_REG
  172. }
  173. else {
  174. profiler::stat::MODRM_SIMPLE_REG_WITH_OFFSET
  175. }
  176. },
  177. _ => profiler::stat::MODRM_COMPLEX,
  178. },
  179. );
  180. let mut have_something_on_stack = false;
  181. if let Some(reg) = modrm_byte.first_reg {
  182. codegen::gen_get_reg32(ctx, reg);
  183. have_something_on_stack = true;
  184. }
  185. if let Some(reg) = modrm_byte.second_reg {
  186. codegen::gen_get_reg32(ctx, reg);
  187. if modrm_byte.shift != 0 {
  188. ctx.builder.const_i32(modrm_byte.shift.into());
  189. ctx.builder.shl_i32();
  190. }
  191. if have_something_on_stack {
  192. ctx.builder.add_i32();
  193. }
  194. have_something_on_stack = true;
  195. }
  196. if modrm_byte.immediate != 0 || !have_something_on_stack {
  197. ctx.builder.const_i32(modrm_byte.immediate);
  198. if have_something_on_stack {
  199. ctx.builder.add_i32();
  200. }
  201. }
  202. if modrm_byte.is_16 {
  203. ctx.builder.const_i32(0xFFFF);
  204. ctx.builder.and_i32();
  205. }
  206. jit_add_seg_offset(ctx, modrm_byte.segment);
  207. }
  208. pub fn skip(ctx: &mut CpuContext, modrm_byte: u8) { let _ = decode(ctx, modrm_byte); }
  209. #[derive(PartialEq)]
  210. enum Imm32 {
  211. None,
  212. Imm8,
  213. Imm32,
  214. }
  215. fn can_optimize_get_seg(ctx: &mut JitContext, segment: u32) -> bool {
  216. (segment == DS || segment == SS) && ctx.cpu.has_flat_segmentation()
  217. }
  218. pub fn jit_add_seg_offset(ctx: &mut JitContext, default_segment: u32) {
  219. let prefix = ctx.cpu.prefixes & PREFIX_MASK_SEGMENT;
  220. let seg = if prefix != 0 { prefix - 1 } else { default_segment };
  221. if can_optimize_get_seg(ctx, seg) || prefix == SEG_PREFIX_ZERO {
  222. codegen::gen_profiler_stat_increment(ctx.builder, profiler::stat::SEG_OFFSET_OPTIMISED);
  223. return;
  224. }
  225. codegen::gen_profiler_stat_increment(ctx.builder, profiler::stat::SEG_OFFSET_NOT_OPTIMISED);
  226. if cfg!(debug_assertions) && seg != CS && seg != SS {
  227. ctx.builder.const_i32(seg as i32);
  228. ctx.builder.call_fn1("log_segment_null");
  229. }
  230. ctx.builder
  231. .load_fixed_u8(global_pointers::get_segment_is_null_offset(seg));
  232. ctx.builder.if_void();
  233. codegen::gen_trigger_gp(ctx, 0);
  234. ctx.builder.block_end();
  235. ctx.builder
  236. .load_fixed_i32(global_pointers::get_seg_offset(seg));
  237. ctx.builder.add_i32();
  238. }