| @@ -209,15 +209,116 @@ class Assembler{ | |||
| // Variable label!! | |||
| } else if (tokens[0][tokens[0].length - 1] === ':'){ | |||
| // Jump label!! | |||
| } else if (tokens[0].length === 3){ | |||
| } else if (tokens[0].length === 3){ | |||
| let StoreSingleOp = (code)=>{ | |||
| if (tokens.length === 1){ | |||
| op.push(code); | |||
| this.__PC += 1; | |||
| return true; | |||
| } | |||
| return false; | |||
| }; | |||
| let StoreBranchOp = (code) => { | |||
| if (tokens.length === 2){ | |||
| if (token[1][0] === '$' && (tokens[1].length === 3 || tokens[1].length === 5)){ | |||
| let v = parseInt(token[1].substr(1), 16); | |||
| if (isNaN(v)) | |||
| return false; | |||
| if (v < this.__PC - 127 || v > this.__PC + 128) | |||
| throw new Error("Branch exceeds maximum number of bytes on program address " + toHexString(this.__PC)); | |||
| v = v - this.__PC; | |||
| op.push(code); | |||
| op.push((v >= 0) ? v : v + 255); | |||
| this.__PC += 2; | |||
| } | |||
| } | |||
| return false; | |||
| }; | |||
| let StoreOp = (codes, mint, maxt) => { | |||
| if (tokens.length >= mint && tokens.length <= maxt){ | |||
| let mv = addrModeVal(tokens[1], (tokens.length === 3) ? tokens[2].toUpperCase(), null); | |||
| let modea = true; | |||
| switch(mv[0]){ | |||
| case "i": | |||
| modea = codes[0] !== null; | |||
| if (modea){ | |||
| op.push(codes[0]); | |||
| op.push(mv[1]); | |||
| this.__PC += 2; | |||
| } break; | |||
| case "z": | |||
| modea = codes[1] !== null; | |||
| if (modea){ | |||
| op.push(codes[1]); | |||
| op.push(mv[1]); | |||
| this.__PC += 2; | |||
| } break; | |||
| case "zX": | |||
| modea = codes[2] !== null; | |||
| if (modea){ | |||
| op.push(codes[2]); | |||
| op.push(mv[1]); | |||
| this.__PC += 2; | |||
| } break; | |||
| case "a": | |||
| modea = codes[3] !== null; | |||
| if (modea){ | |||
| op.push(codes[3]); | |||
| op.push(mv[1] & 0x000000FF); | |||
| op.push((mv[1] & 0x0000FF00) >> 8); | |||
| this.__PC += 3; | |||
| } break; | |||
| case "aX": | |||
| modea = codes[4] !== null; | |||
| if (modea){ | |||
| op.push(codes[4]); | |||
| op.push(mv[1] & 0x000000FF); | |||
| op.push((mv[1] & 0x0000FF00) >> 8); | |||
| this.__PC += 3; | |||
| } break; | |||
| case "aY": | |||
| modea = codes[5] !== null; | |||
| if (modea){ | |||
| op.push(codes[5]); | |||
| op.push(mv[1] & 0x000000FF); | |||
| op.push((mv[1] & 0x0000FF00) >> 8); | |||
| this.__PC += 3; | |||
| } break; | |||
| case "nX": | |||
| modea = codes[6] !== null; | |||
| if (modea){ | |||
| op.push(codes[6]); | |||
| op.push(mv[1]); | |||
| this.__PC += 2; | |||
| } break; | |||
| case "nY": | |||
| modea = codes[7] !== null; | |||
| if (modea){ | |||
| op.push(codes[7]); | |||
| op.push(mv[1]); | |||
| this.__PC += 2; | |||
| } break; | |||
| } | |||
| if (modea === false) | |||
| throw new Error("Op-code does not support implied mode on program address " + toHexString(this.__PC)); | |||
| return true; | |||
| } | |||
| return false; | |||
| }; | |||
| let procFailed = false; | |||
| let mv = null; | |||
| // Possible op code. | |||
| switch(tokens[0].toLowerCase()){ | |||
| // --- ADC | |||
| case 'adc': | |||
| procFailed = StoreOp([0x69, 0x65, 0x75, 0x6D, 0x7D, 0x79, 0x61, 0x71], 2, 3); | |||
| /* | |||
| if (tokens.length >= 2 && tokens.length <= 3){ | |||
| mv = addrModeVal(tokens[1]); | |||
| mv = addrModeVal(tokens[1], (tokens.length === 3) ? tokens[2].toUpperCase(), null); | |||
| this.__PC += 2; | |||
| switch(mv[0]){ | |||
| case "i": | |||
| @@ -244,207 +345,183 @@ class Assembler{ | |||
| break; | |||
| } | |||
| } else { procFailed = true; } | |||
| */ | |||
| break; | |||
| // --- AND | |||
| case 'and': | |||
| procFailed = StoreOp([0x29, 0x25, 0x35, 0x2D, 0x3D, 0x39, 0x21, 0x31], 2, 3); | |||
| break; | |||
| // --- ASL | |||
| case 'asl': | |||
| if (tokens.length === 2){ | |||
| if (tokens[1].toUpperCase() === 'A'){ | |||
| op.push(0x0A); | |||
| this.__PC += 1; | |||
| break; | |||
| } | |||
| } | |||
| procFailed = StoreOp([null, 0x06, 0x16, 0x0E, 0x1E, null, null, null], 2, 3); | |||
| break; | |||
| // --- BCC | |||
| case 'bcc': | |||
| break; | |||
| procFailed = StoreBranchOp(0x90); break; | |||
| // --- BCS | |||
| case 'bcs': | |||
| break; | |||
| procFailed = StoreBranchOp(0xB0); break; | |||
| // --- BEQ | |||
| case 'beq': | |||
| break; | |||
| procFailed = StoreBranchOp(0xF0); break; | |||
| // --- BIT | |||
| case 'bit': | |||
| break; | |||
| procFailed = StoreOp([null, 0x24, null, 0x2C, null, null, null, null], 2, 2); break; | |||
| // --- BMI | |||
| case 'bmi': | |||
| break; | |||
| procFailed = StoreBranchOp(0x30); break; | |||
| // --- BNE | |||
| case 'bne': | |||
| break; | |||
| procFailed = StoreBranchOp(0xD0); break; | |||
| // --- BPL | |||
| case 'bpl': | |||
| break; | |||
| procFailed = StoreBranchOp(0x10); break; | |||
| // --- BRK | |||
| case 'brk': | |||
| if (tokens.length === 1){ | |||
| op.push(0x00); | |||
| this.__PC += 1; | |||
| } else { procFailed = true; } | |||
| break; | |||
| procFailed = StoreSingleOp(0x00); break; | |||
| // --- BVC | |||
| case 'bvc': | |||
| break; | |||
| procFailed = StoreBranchOp(0x50); break; | |||
| // --- BVS | |||
| case 'bvs': | |||
| break; | |||
| procFailed = StoreBranchOp(0x70); break; | |||
| // --- CLC | |||
| case 'clc': | |||
| if (tokens.length === 1){ | |||
| op.push(0x18); | |||
| this.__PC += 1; | |||
| } else { procFailed = true; } | |||
| break; | |||
| procFailed = StoreSingleOp(0x18); break; | |||
| // --- CLD | |||
| case 'cld': | |||
| if (tokens.length === 1){ | |||
| op.push(0xD8); | |||
| this.__PC += 1; | |||
| } else { procFailed = true; } | |||
| break; | |||
| procFailed = StoreSingleOp(0xD8); break; | |||
| // --- CLI | |||
| case 'cli': | |||
| if (tokens.length === 1){ | |||
| op.push(0x58); | |||
| this.__PC += 1; | |||
| } else { procFailed = true; } | |||
| break; | |||
| procFailed = StoreSingleOp(0x58); break; | |||
| // --- CLV | |||
| case 'clv': | |||
| if (tokens.length === 1){ | |||
| op.push(0xB8); | |||
| this.__PC += 1; | |||
| } else { procFailed = true; } | |||
| break; | |||
| procFailed = StoreSingleOp(0xB8); break; | |||
| // --- CMP | |||
| case 'cmp': | |||
| break; | |||
| procFailed = StoreOp([0xC9, 0xC5, 0xD5, 0xCD, 0xDD, 0xD9, 0xC1, 0xD1], 2, 3); break; | |||
| // --- CPX | |||
| case 'cpx': | |||
| break; | |||
| procFailed = StoreOp([0xE0, 0xE4, null, 0xEC, null, null, null, null], 2, 2); break; | |||
| // --- CPY | |||
| case 'cpy': | |||
| break; | |||
| procFailed = StoreOp([0xC0, 0xC4, null, 0xCC, null, null, null, null], 2, 2); break; | |||
| // --- DEC | |||
| case 'dec': | |||
| break; | |||
| procFailed = StoreOp([null, 0xC6, 0xD6, 0xCE, 0xDE, null, null, null], 2, 3); break; | |||
| // --- DEX | |||
| case 'dex': | |||
| if (tokens.length === 1){ | |||
| op.push(0xCA); | |||
| this.__PC += 1; | |||
| } else { procFailed = true; } | |||
| break; | |||
| procFailed = StoreSingleOp(0xCA); break; | |||
| // --- DEY | |||
| case 'dey': | |||
| if (tokens.length === 1){ | |||
| op.push(0x88); | |||
| this.__PC += 1; | |||
| } else { procFailed = true; } | |||
| break; | |||
| procFailed = StoreSingleOp(0x88); break; | |||
| // --- EOR | |||
| case 'eor': | |||
| break; | |||
| procFailed = StoreOp([0x49, 0x45, 0x55, 0x4D, 0x5D, 0x59, 0x41, 0x51], 2, 3); break; | |||
| // --- INC | |||
| case 'inc': | |||
| break; | |||
| procFailed = StoreOp([null, 0xE6, 0xF6, 0xEE, 0xFE, null, null, null], 2, 3); break; | |||
| // --- INX | |||
| case 'inx': | |||
| if (tokens.length === 1){ | |||
| op.push(0xE8); | |||
| this.__PC += 1; | |||
| } else { procFailed = true; } | |||
| break; | |||
| procFailed = StoreSingleOp(0xE8); break; | |||
| // --- INY | |||
| case 'iny': | |||
| if (tokens.length === 1){ | |||
| op.push(0xC8); | |||
| this.__PC += 1 | |||
| } else { procFailed = true; } | |||
| break; | |||
| procFailed = StoreSingleOp(0xC8); break; | |||
| // --- JMP | |||
| case 'jmp': | |||
| break; | |||
| // --- JSR | |||
| case 'jsr': | |||
| break; | |||
| // --- LDA | |||
| case 'lda': | |||
| break; | |||
| // --- LDX | |||
| case 'ldx': | |||
| break; | |||
| // --- LDY | |||
| case 'ldy': | |||
| break; | |||
| // --- LSR | |||
| case 'lsr': | |||
| break; | |||
| // --- NOP | |||
| case 'nop': | |||
| if (tokens.length === 1){ | |||
| op.push(0xEA); | |||
| this.__PC += 1; | |||
| } else { procFailed = true; } | |||
| break; | |||
| procFailed = StoreSingleOp(0xEA); break; | |||
| // --- ORA | |||
| case 'ora': | |||
| break; | |||
| // --- PHA | |||
| case 'pha': | |||
| break; | |||
| // --- PHP | |||
| case 'php': | |||
| break; | |||
| // --- PLA | |||
| case 'pla': | |||
| break; | |||
| // --- PLP | |||
| case 'plp': | |||
| break; | |||
| // --- ROL | |||
| case 'rol': | |||
| break; | |||
| // --- ROR | |||
| case 'ror': | |||
| break; | |||
| // --- RTI | |||
| case 'rti': | |||
| break; | |||
| // --- RTS | |||
| case 'rts': | |||
| break; | |||
| // --- SBC | |||
| case 'sbc': | |||
| break; | |||
| // --- SEC | |||
| case 'sec': | |||
| if (tokens.length === 1){ | |||
| op.push(0x38); | |||
| this.__PC += 1; | |||
| } else { procFailed = true; } | |||
| break; | |||
| procFailed = StoreSingleOp(0x38); break; | |||
| // --- SED | |||
| case 'sed': | |||
| if (tokens.length === 1){ | |||
| op.push(0xF8); | |||
| this.__PC += 1; | |||
| } else { procFailed = true; } | |||
| break; | |||
| procFailed = StoreSingleOp(0xF8); break; | |||
| // --- SEI | |||
| case 'sei': | |||
| op.push(0x78); | |||
| this.__PC += 1; | |||
| procFailed = StoreSingleOp(0x78); break; | |||
| break; | |||
| // --- STA | |||
| case 'sta': | |||
| break; | |||
| // --- STX | |||
| case 'stx': | |||
| break; | |||
| // --- STY | |||
| case 'sty': | |||
| break; | |||
| // --- TAX | |||
| case 'tax': | |||
| if (tokens.length === 1){ | |||
| op.push(0xAA); | |||
| this.__PC += 1; | |||
| } else { procFailed = true; } | |||
| break; | |||
| procFailed = StoreSingleOp(0xAA); break; | |||
| // --- TAY | |||
| case 'tay': | |||
| if (tokens.length === 1){ | |||
| op.push(0xA8); | |||
| this.__PC += 1; | |||
| } else { procFailed = true; } | |||
| break; | |||
| procFailed = StoreSingleOp(0xA8); break; | |||
| // --- TSX | |||
| case 'tsx': | |||
| break; | |||
| // --- TXA | |||
| case 'txa': | |||
| if (tokens.length === 1){ | |||
| op.push(0x8A); | |||
| this.__PC += 1; | |||
| } else { procFailed = true; } | |||
| break; | |||
| procFailed = StoreSingleOp(0x8A); break; | |||
| // --- TXS | |||
| case 'txs': | |||
| break; | |||
| // --- TYA | |||
| case 'tya': | |||
| if (tokens.length === 1){ | |||
| op.push(0x98); | |||
| this.__PC += 1; | |||
| } else { procFailed = true; } | |||
| break; | |||
| procFailed = StoreSingleOp(0x98); break; | |||
| // --- --- | |||
| default: | |||
| throw new Error("Unknown op-code '" + tokens[0].toUpperCase() + "' at program address " + toHexString(this.__PC)); | |||