Mercurial > hg > Applications > Tokio
diff Examples/6502/isp.mc6502 @ 0:cfb7c6b24319
Initial revision
author | kono |
---|---|
date | Thu, 30 Aug 2007 14:57:44 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Examples/6502/isp.mc6502 Thu Aug 30 14:57:44 2007 +0900 @@ -0,0 +1,596 @@ +! ISPS Description of the MOS Technology MCS 6502 Microprocessor + +! G.W.Leive +! 10 July 1978 ISPS Version +! COPYRIGHT (C) 1978 + +MC6502 := + BEGIN + +**MP.STATE** + MACRO romlow:= |"F800 |, + MACRO romhi := |"FFFF |, + MACRO ramlow:= |"0000 |, + MACRO ramhi := |"1000 |, + MACRO maxb := |"FFFF |, ! High end of byte memory + + Mb[0:maxb]<7:0>, ! Primary memory range + ram[ramlow:ramhi]<7:0> := mb[ramlow:ramhi]<7:0>, ! RAM + rom[romlow:romhi]<7:0> := mb[romlow:romhi]<7:0> ! ROM + +**PC.STATE** + + Pc<15:0>, ! Program counter + + Y<7:0>, ! Index register + X<7:0>, ! Index register + S<7:0>, ! Stack pointer + Dl<7:0>, ! Input data latch + A<7:0>, ! Accumulator + Ir<7:0>, ! Instruction register + P<7:0>, ! Processor status + n<> := P<7>, ! Negative result + v<> := P<6>, ! Overflow + b<> := P<4>, ! Break command + d<> := P<3>, ! Decimal mode + i<> := P<2>, ! Interrupt disable + z<> := P<1>, ! Zero + c<> := P<0>, ! Carry + + Irq<>, ! Interrupt request + Nmi<>, ! Non-maskable interrupt + IFSync<>, ! High when instruction fetch + Rw<>, ! Read/Write control pin + So<>, ! Set overflow pin + Reset<>, ! Power up bit + Ready<> ! 1 means run, 0 means stop + +**ADDRESS.CALCULATION** + + immed()<15:0> := ! Immediate + BEGIN + immed = ab = Pc NEXT + Pc = Pc + 1 + END, + + zp()<15:0> := ! Zero page + BEGIN + zp = ab = read(Pc) NEXT + Pc = Pc + 1 + END, + + abs()<15:0> := ! Absolute + BEGIN + abs = ab(Pc + 1, Pc) NEXT + Pc = Pc + 2 + END, + + indx()<15:0> := ! Indexed indirect - (IND, X) + BEGIN + indx = ab((read(Pc) + X + 1)<7:0>, (read(Pc) + X)<7:0>) NEXT + Pc = Pc + 1 + END, + + indy()<15:0> := ! Indirect indexed - (IND), Y + BEGIN + indy = ab = ab(read(Pc) + 1, read(Pc)) + Y NEXT + Pc = Pc + 1 + END, + + zpx()<15:0> := ! Zero page indexed by X + BEGIN + zpx = ab = (read(Pc) + X)<7:0> NEXT + Pc = Pc + 1 + END, + + zpy()<15:0> := ! Zero page indexed by Y + BEGIN + zpy = ab = (read(Pc) + Y)<7:0> NEXT + Pc = Pc + 1 + END, + + + absy()<15:0> := ! Absolute modified by Y + BEGIN + absy = ab = ab(Pc + 1, Pc) + Y NEXT + Pc = Pc + 2 + END, + + absx()<15:0> := ! Ablolute modified by X + BEGIN + absx = ab = ab(Pc + 1, Pc) + X NEXT + Pc = Pc + 2 + END + +**SERVICE.FACILITIES** + + push(dbb.<7:0>) := ! Push a byte on the stack + BEGIN + write(1@S, dbb.) NEXT + S = S - 1 + END, + + pull<7:0> := ! Pull a byte off the stack + BEGIN + S = S + 1 NEXT + pull = read(1@S) + END, + + opex := ! Operation exception + BEGIN + Ready = 0 NEXT + RESTART run + END, + + setnz(ta.<7:0>) := ! Set neg and zero condition code + BEGIN + z = ta. EQL 0; n = ta.<7> + END, + + branch(cond<>) := + BEGIN + DECODE cond => + BEGIN + 0 := Pc = Pc + 1, + 1 := Pc = (Pc + 1) + read(PC) ! Relative addressing + END + END, + + decimal.adjust(tac.<8:0>) := ! Used by sbc and adc + BEGIN + IF A<7> EQV read<7> => v = tac.<7> XOR A<7>; c = tac.<8> NEXT + IF d => + BEGIN + tac.<8> = 0 NEXT + IF tac.<3:0> GTR{US} "9 => tac. = tac.<7:0> + "6 NEXT + IF NOT c => c = tac.<8> NEXT + IF tac.<7:4> GTR{US} "9 => tac. = tac.<7:0> + "60 NEXT + IF NOT c => c = tac.<8> + END NEXT + A = tac.<7:0> NEXT + setnz(A) + END, + + ab(adh.<15:0>, adl.<15:0>)<15:0> := ! Address buffer + BEGIN + ab<15:8> = read(adh.) NEXT + ab<7:0> = read(adl.) + END, + + ! Read and write memory access routines + + read(ab.<15:0>)<7:0> := ! Read from valid memory + BEGIN + Rw = 1 NEXT + IF NOT Ready => RESTART run NEXT + read = "FF NEXT ! Fake a nonexistant memory access + IF (ab. GEQ{US} ramlow) AND (ab. LEQ{US} ramhi) => read = ram[ab.]; + IF (ab. GEQ{US} romlow) AND (ab. LEQ{US} romhi) => read = rom[ab.] + END, + + write(ab.<15:0>, dbb.<7:0>) := ! Write to valid memory + BEGIN + IF (ab. GEQ{US} ramlow) AND (ab. LEQ{US} ramhi) => ram[ab.] = dbb.; + Rw = 0 + END, + + ! Interrupt routines + + intstk := ! Interrupt stack operations + BEGIN + push(Pc<15:8>) NEXT + push(Pc<7:0>) NEXT + push(P) NEXT + i = 1 + END, + + int := ! Interrupt processing + BEGIN + IF NOT Reset => + BEGIN + Reset = Irq = Nmi = Ready = 1 NEXT + Pc = ab("FFFD, "FFFC) NEXT + i = 1 NEXT + LEAVE int + END NEXT + + IF NOT Nmi => + BEGIN + Nmi = 1 NEXT + intstk() NEXT + Pc = ab("FFFB, "FFFA) NEXT + LEAVE int + END NEXT + + IF b OR (NOT Irq AND NOT i) => + BEGIN + intstk() NEXT + b = 0 NEXT + Pc = ab("FFFF, "FFFE) + END + END + +**INSTRUCTION.INTERPRETATION** + + run := + BEGIN + IF NOT Reset => int() NEXT ! Initial startup + IF NOT ready => stop() NEXT + IFSync = 1 NEXT ! Instruction fetch + Ir = read(Pc) NEXT + Pc = Pc + 1 NEXT + IFSync = 0 NEXT ! Execute + DECODE IR<1:0> => + BEGIN + '01 := group1(), + '10 := group2(), + '00 := group3(), + '11 := opex() + END NEXT + int() NEXT + IF So => v = 1 NEXT + RESTART RUN + END, + + ! Group 1 instruction decode + + group1 := + BEGIN + DECODE Ir<7:5> => + BEGIN + #0 := ora(), + #1 := and.(), + #2 := eor(), + #3 := adc(), + #4 := sta(), + #5 := lda(), + #6 := cmp(), + #7 := sbc() + END + END, + + ! Group 2 instruction decode + + group2 := + BEGIN + DECODE Ir<7:5> => + BEGIN + #0 := asl(), + #1 := rol(), + #2 := lsr(), + #3 := ror(), + #4 := stx(), ! Includes txa, txs + #5 := ldx(), ! Includes tax, tsx + #6 := dec(), ! Includes dex + #7 := inc() ! Includes no.op + END + END, + + ! Group 3 instruction decode + + group3 := + BEGIN + DECODE Ir => + BEGIN + "00 := brk(), ! Break + "08 := php(), ! Push status on stack + "28 := plp(), ! Pull status from stack + "48 := pha(), ! Push accumulator + "68 := pla(), ! Pull accumulator + "10 := bpl(), ! Branch on plus + "30 := bmi(), ! Branch on minus + "50 := bvc(), ! Branch if overflow clear + "70 := bvs(), ! Branch if overflow set + "90 := bcc(), ! Branch on carry clear + "D0 := bne(), ! Branch on not equal + "F0 := beq(), ! Branch if equal + "B0 := bcs(), ! Branch if carry set + "18 := clc(), ! Clear carry + "38 := sec(), ! Set carry + "58 := cli(), ! Clear interrupt enable + "78 := sei(), ! Set interrupt enable + "B8 := clv(), ! Clear overflow + "D8 := cld(), ! Clear decimal mode + "F8 := sed(), ! Set decimal mode + "20 := jsr(), ! Jump to subroutine + "24 := bit(read(zp())), ! Bit test - zero page + "2C := bit(read(abs())), ! Bit test - absolute + "40 := rti(), ! Return from interrupt + "4C := jmp(), ! Jump - absolute + "6C := jmp(), ! Jump - indirect + "60 := rts(), ! Return from subroutine + "84 := sty(zp()), ! Store Y - zero page + "8C := sty(abs()), ! Store Y - absolute + "94 := sty(zpx()), ! Store Y - zero page, X + "88 := dey(), ! Decrement Y + "C8 := iny(), ! Increment Y + "E8 := inx(), ! Increment X + "98 := tya(), ! Transfer Y to A + "A8 := tay(), ! Transfer A to Y + "A0 := ldy(immed()), ! Load Y - immediate + "A4 := ldy(zp()), ! Load Y - zero page + "AC := ldy(abs()), ! Load Y - absolute + "B4 := ldy(zpx()), ! Load Y - zero page, X + "BC := ldy(absx()), ! Load Y - absolute, X + "C0 := cpy(immed()), ! Compare immediate to Y + "C4 := cpy(zp()), ! Compare zero page to Y + "CC := cpy(abs()), ! Compare absolute to Y + "E0 := cpx(immed()), ! Compare immediate to X + "E4 := cpx(zp()), ! Compare zero page to X + "EC := cpx(abs()), ! Compare absolute to X + OTHERWISE := opex() + END + END + +**INSTRUCTION.EXECUTION** + + ! Group 1 instruction execution + + addrs1()<15:0> := ! Group 1 address generation + BEGIN + DECODE Ir<4:2> => + BEGIN + #0 := addrs1 = indx(), + #1 := addrs1 = zp(), + #2 := addrs1 = immed(), + #3 := addrs1 = abs(), + #4 := addrs1 = indy(), + #5 := addrs1 = zpx(), + #6 := addrs1 = absy(), + #7 := addrs1 = absx() + END + END, + + ora := ! Or + BEGIN + A = A OR read(addrs1()) NEXT + setnz(A) + END, + + and. := ! And + BEGIN + A = A AND read(addrs1()) NEXT + setnz(A) + END, + + eor := ! Exclusive or + BEGIN + A = A XOR read(addrs1()) NEXT + setnz(A) + END, + + adc := (decimal.adjust(A +{US} c + read(addrs1()))), ! Add with carry + + sta := (IF Ir NEQ{US} "89 => write(addrs1(),A)), ! Store immediate + + lda := ! Load accumulator + BEGIN + A = read(addrs1()) NEXT + setnz(A) + END, + + cmp := ! Compare + BEGIN + setnz(A - read(addrs1())) NEXT + c = A GEQ read + END, + + sbc := (decimal.adjust(A +{US} c + NOT read(addrs1()))), ! Sub/carry + + ! Group 2 addressing mode selection + + ! Group 2 gets and puts + + get2()<8:0> := ! Get the correct operand and return it in "get2" + BEGIN + DECODE Ir<4:2> => + BEGIN + #1 := get2<7:0> = read(zp()), + #2 := get2<7:0> = A, + #3 := get2<7:0> = read(abs()), + #5 := get2<7:0> = read(zpx()), + #7 := get2<7:0> = read(absx()), + OTHERWISE := opex() + END NEXT + get2<8> = c + END, + + put2(ta.<7:0>) := ! Put the operand in the proper location + BEGIN + DECODE Ir<4:2> => + BEGIN + [#1,#3,#5,#7] := write(ab, ta.), + #2 := A = ta., + OTHERWISE := opex() + END NEXT + setnz(ta.) + END, + + ! Group 2 instruction execution + + asl := ! Arithmetic shift left + BEGIN + get2 = get2() SL0 1 NEXT + c = get2<8>; put2(get2) + END, + + + rol := ! rotate left + BEGIN + get2 = get2() SLR 1 NEXT + c = get2<8>; put2(get2) + END, + + lsr := ! Logical shift right + BEGIN + c = get2<2> NEXT + get2 = get2<7:0> SR0 1 NEXT + put2(get2) + END, + + ror := ! Rotate right + BEGIN + get2 = get2() SRR 1 NEXT + c = get2<8>; put2(get2) + END, + + stx := ! Store index register + BEGIN + DECODE Ir<4:2> => + BEGIN + #1 := write(zp(), X), + #2 := A = X, ! Txa + #3 := write(abs(), X), + #5 := write(zpy(), X), + #6 := S = X, ! Txs + OTHERWISE := opex() + END + END, + + ldx := ! Load index register + BEGIN + DECODE Ir<4:2> => + BEGIN + #0 := X = read(immed()), + #1 := X = read(zp()), + #2 := X = A, ! Tax + #3 := X = read(abs()), + #4 := opex(), + #5 := X = read(zpy()), + #6 := X = S, ! Tsx + #7 := X = read(absy()) + END NEXT + setnz(X) + END, + + dec := ! Decrement + BEGIN + DECODE Ir EQL "CA => + BEGIN + 0 := put2(get2() - 1), + 1 := BEGIN ! Dex + X = X - 1 NEXT + setnz(X) + END + END + END, + + inc := ! Increment + BEGIN + IF Ir NEQ "EA => put2(get2() + 1) ! Op "EA => no.op + END, + + ! Group 3 instruction execution + + brk := (b = 1; Pc = Pc+1), ! Break + + php := (push(P)), ! Push processor status on stack + plp := (P = pull()), ! Pull processor status from stack + pha := (push(A)), ! Push accumulator on stack + pla := ! Pull accumulator from stack + BEGIN + A = pull() NEXT + setnz(A) + END, + + bpl := (branch(NOT n)), ! Branch on plus + bmi := (branch(n)), ! Branch on minus + bvc := (branch(NOT v)), ! Branch on overflow clear + bvs := (branch(v)), ! Branch if overflow set + bcc := (Branch(NOT c)), ! Branch on carry clear + bne := (branch(NOT z)), ! Branch if not equal + beq := (branch(z)), ! Branch on equal + bcs := (branch(c)), ! Branch on carry set + + clc := (c = 0), ! Clear carry flag + sec := (c = 1), ! Set carry + cli := (i = 0), ! Clear interrupt disable bit + sei := (i = 1), ! Set interrupt disable status + clv := (v = 0), ! Clear overflow + cld := (d = 0), ! Clear decimal mode + sed := (d = 1), ! Set decimal mode + + jsr := ! Jump to subroutine + BEGIN + push((Pc + 1)<15:8>) NEXT + push((Pc + 1)<7:0>) NEXT + Pc = abs() + END, + + bit(ta.<7:0>) := ! Bit test + BEGIN + n = ta.<7>; v = ta.<6>; z = (ta. AND A) EQL 0 + END, + + rti := ! Return from interrupt + BEGIN + P = pull() NEXT + Pc<7:0> = pull() NEXT + Pc<15:8> = pull(); b = 0 + END, + + jmp := ! Jump + BEGIN + Pc = abs() NEXT + IF Ir EQL "6C => Pc = abs() ! Indirect + END, + + ! Group 3 instruction execution (page 2) + + rts := ! return from subroutine + BEGIN + Pc<7:0> = pull() NEXT + Pc<15:8> = pull() NEXT + Pc = Pc + 1 + END, + + sty(ab.<15:0>) := (write(ab., Y)), ! Store index Y in memory + + dey := ! Decrement index Y by one + BEGIN + Y = Y - 1 NEXT + setnz(Y) + END, + + tya := ! Transfer index Y to accumulator + BEGIN + A = Y NEXT + setnz(A) + END, + + ldy(ab.<15:0>) := (Y = read(ab.)), ! Load index Y with memory + + tay := ! Transfer accumulator to index Y + BEGIN + Y = A NEXT + setnz(Y) + END, + + cpy(ab.<15:0>) := ! Compare memory and index Y + BEGIN + setnz(Y - read(ab.)) NEXT + c = Y GEQ read + END, + + iny := ! Increment index Y by one + BEGIN + Y = Y + 1 NEXT + setnz(Y) + END, + + cpx(ab.<15:0>) := ! Compare memory and index X + BEGIN + setnz(X - read(ab.)) NEXT + c = X GEQ read + END, + + inx := ! Increment index X by one + BEGIN + X = X + 1 NEXT + setnz(X) + END + + + END ! End of MC6502 + +