#include "cpu/exec.h"

make_EHelper(mov) {
  operand_write(id_dest, &id_src->val);
  print_asm_template2(mov);
}

make_EHelper(push) {
  static_assert(sizeof(paddr_t) * 8 == 32);
  if(decoding.is_operand_size_16) {
    // 16b push
    rtl_push<2>(&id_dest->val);
  }
  else {
    // 32b push
    rtl_push<4>(&id_dest->val);
  }

  print_asm_template1(push);
}

make_EHelper(pop) {
  static_assert(sizeof(paddr_t) * 8 == 32);
  if(decoding.is_operand_size_16) {
    // 16b
    rtl_pop<2>(&id_dest->val);
  }
  else {
    // 32b
    rtl_pop<4>(&id_dest->val);
  }
  operand_write(id_dest, &id_dest->val);

  print_asm_template1(pop);
}

make_EHelper(pusha) {
  TODO();

  print_asm("pusha");
}

make_EHelper(popa) {
  TODO();

  print_asm("popa");
}

make_EHelper(leave) {
  rtl_mv(&cpu.esp, &cpu.ebp);
  if(decoding.is_operand_size_16) {
    rtlreg_t tmpReg;
    rtl_pop<2>(&tmpReg);
    reg_w(R_BP) = (uint16_t)tmpReg;
  }
  else {
    rtl_pop<4>(&cpu.ebp);
  }

  print_asm("leave");
}

make_EHelper(cltd) {
  if (decoding.is_operand_size_16) {
    TODO();
  }
  else {
    TODO();
  }

  print_asm(decoding.is_operand_size_16 ? "cwtl" : "cltd");
}

make_EHelper(cwtl) {
  if (decoding.is_operand_size_16) {
    TODO();
  }
  else {
    TODO();
  }

  print_asm(decoding.is_operand_size_16 ? "cbtw" : "cwtl");
}

make_EHelper(movsx) {
  id_dest->width = decoding.is_operand_size_16 ? 2 : 4;
  rtl_sext(&t0, &id_src->val, id_src->width);
  operand_write(id_dest, &t0);
  print_asm_template2(movsx);
}

make_EHelper(movzx) {
  id_dest->width = decoding.is_operand_size_16 ? 2 : 4;
  operand_write(id_dest, &id_src->val);
  print_asm_template2(movzx);
}

make_EHelper(lea) {
  operand_write(id_dest, &id_src->addr);
  print_asm_template2(lea);
}
