
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>MOV命令ジェネレーター（修正済・スマホ対応）</title>
  <style>
    body {
      font-family: sans-serif;
      padding: 10px;
      background: #f9f9f9;
      max-width: 480px;
      margin: auto;
    }
    input, select, button, textarea {
      width: 100%;
      font-size: 16px;
      box-sizing: border-box;
      margin: 6px 0;
    }
    textarea {
      height: 180px;
      font-family: monospace;
    }
    label {
      display: block;
      margin-top: 10px;
    }
  </style>
</head>
<body>

<h2>MOV命令ジェネレーター</h2>

<label>数値（10進）:
  <input type="text" id="valueDec" placeholder="例: 1234">
</label>
<label>数値（16進・4桁まで）:
  <input type="text" id="valueHex" placeholder="例: 4D2 または 0x4D2">
</label>

<label>ビット幅:
  <select id="bitSelector">
    <option value="32">32bit</option>
    <option value="64">64bit</option>
  </select>
</label>

<label>レジスタ:
  <select id="regSelector"></select>
</label>

<button onclick="copyAsm()">オペコードをコピー</button>
<button onclick="copyMachine()">機械語をコピー</button>

<h3>出力:</h3>
<textarea id="output" readonly></textarea>

<script>
  const regSelector = document.getElementById('regSelector');
  for (let i = 0; i < 32; i++) {
    regSelector.innerHTML += `<option value="${i}">${i}</option>`;
  }

  const valueDec = document.getElementById('valueDec');
  const valueHex = document.getElementById('valueHex');
  const bitSelector = document.getElementById('bitSelector');
  const output = document.getElementById('output');
  let lastAsm = "", lastMachine = "";

  valueDec.addEventListener('input', generateMOV);
  valueHex.addEventListener('input', generateMOV);
  bitSelector.addEventListener('change', generateMOV);
  regSelector.addEventListener('change', generateMOV);

  function toHex(value, width = 4) {
    return value.toString(16).padStart(width, '0').toUpperCase();
  }

  function toOpcodeHex(opcode) {
    return toHex(opcode >>> 0, 8).match(/../g).reverse().join(' ');
  }

  function generateMOV() {
    try {
      let value;
      const hexInput = valueHex.value.trim();
      const decInput = valueDec.value.trim();

      if (hexInput) {
        let hexStr = hexInput.replace(/^0x/, '');
        if (!/^[0-9a-fA-F]{1,4}$/.test(hexStr)) {
          throw new Error("16進数は最大4桁（0xFFFF）までです");
        }
        value = parseInt(hexStr, 16);
      } else if (decInput) {
        value = parseInt(decInput);
        if (isNaN(value)) throw new Error("10進数が無効です");
      } else {
        throw new Error("数値が入力されていません");
      }

      const regIndex = parseInt(regSelector.value);
      const bit = parseInt(bitSelector.value);
      const regPrefix = bit === 32 ? 'w' : 'x';
      const reg = regPrefix + regIndex;

      if ((bit === 32 && (value < 0 || value > 0xFFFFFFFF)) ||
          (bit === 64 && (value < 0 || value > 0xFFFFFFFFFFFFFFFF))) {
        throw new Error("値が範囲外です");
      }

      let asm = [], machine = [];

      if (bit === 32) {
        if (value <= 0xFFFF) {
          asm.push(`mov ${reg}, #${toHex(value)}`);
          machine.push(toOpcodeHex(0x52800000 | (value << 5) | regIndex));
        } else {
          const lo = value & 0xFFFF;
          const hi = (value >> 16) & 0xFFFF;
          asm.push(`mov ${reg}, #${toHex(lo)}`);
          asm.push(`movk ${reg}, #${toHex(hi)}, lsl #16`);
          machine.push(toOpcodeHex(0x52800000 | (lo << 5) | regIndex));
          machine.push(toOpcodeHex(0x72800000 | (hi << 5) | (1 << 21) | regIndex));
        }
      } else {
        const parts = [0, 0, 0, 0];
        for (let i = 0; i < 4; i++) {
          parts[i] = (value >> (16 * i)) & 0xFFFF;
        }

        // 修正: parts[0]が0でも必ずmovを出力する
        asm.push(`mov ${reg}, #${toHex(parts[0])}`);
        machine.push(toOpcodeHex(0xD2800000 | (parts[0] << 5) | regIndex));

        for (let i = 1; i < 4; i++) {
          if (parts[i] !== 0) {
            asm.push(`movk ${reg}, #${toHex(parts[i])}, lsl #${i * 16}`);
            machine.push(toOpcodeHex(0xF2800000 | (parts[i] << 5) | (i << 21) | regIndex));
          }
        }
      }

      lastAsm = asm.join('\n');
      lastMachine = machine.join('\n');
      output.value = `生成されたオペコード:\n${lastAsm}\n\n生成された機械語:\n${lastMachine}`;
    } catch (e) {
      output.value = "エラー: " + e.message;
    }
  }

  function copyAsm() {
    navigator.clipboard.writeText(lastAsm);
  }

  function copyMachine() {
    navigator.clipboard.writeText(lastMachine);
  }
</script>

</body>
</html>
