add SI register

This commit is contained in:
Irmen de Jong 2017-12-25 21:43:06 +01:00
parent a0a561cfb6
commit c78cbc4a33
8 changed files with 83 additions and 11 deletions

View File

@ -135,7 +135,7 @@ class EvaluatingTransformer(ast.NodeTransformer):
globals = {"__builtins__": {}}
locals = None
try:
result = eval(code, globals, locals)
result = eval(code, globals, locals) # XXX unsafe...
except Exception as x:
raise self.src.to_error(str(x)) from x
else:

View File

@ -928,6 +928,12 @@ class CodeGenerator:
self.p("\t\tsec")
else:
self.p("\t\tclc")
elif l_register == "SI":
# interrupt disable bit
if rvalue.value:
self.p("\t\tsei")
else:
self.p("\t\tcli")
else:
raise CodeError("invalid register in immediate integer assignment", l_register, rvalue.value)

View File

@ -245,10 +245,10 @@ class ParseResult:
return True, ""
return False, "(unsigned) byte required"
return False, "incompatible indirect value for register assignment"
if self.register == "SC":
if self.register in ("SC", "SI"):
if isinstance(other, ParseResult.IntegerValue) and other.value in (0, 1):
return True, ""
return False, "can only assign an integer constant value of 0 or 1 to SC"
return False, "can only assign an integer constant value of 0 or 1 to SC and SI"
if self.constant:
return False, "cannot assign to a constant"
if isinstance(other, ParseResult.RegisterValue) and len(self.register) < len(other.register):

View File

@ -16,9 +16,9 @@ from typing import Optional, Set, Union, Tuple, Dict, Iterable, Sequence, Any, L
PrimitiveType = Union[int, float, str]
REGISTER_SYMBOLS = {"A", "X", "Y", "AX", "AY", "XY", "SC"}
REGISTER_SYMBOLS = {"A", "X", "Y", "AX", "AY", "XY", "SC", "SI"}
REGISTER_SYMBOLS_RETURNVALUES = REGISTER_SYMBOLS | {"SZ"}
REGISTER_BYTES = {"A", "X", "Y", "SC"}
REGISTER_BYTES = {"A", "X", "Y", "SC", "SI"}
REGISTER_WORDS = {"AX", "AY", "XY"}
# 5-byte cbm MFLPT format limitations:

View File

@ -10,7 +10,8 @@ output raw
memory SCRATCH_ZP1 = $02 ; scratch register #1 in ZP
memory SCRATCH_ZP2 = $03 ; scratch register #2 in ZP
memory COLOR = $286 ; cursor color
memory COLOR = $0286 ; cursor color
memory CINV = $0314 ; IRQ vector
; ---- VIC-II registers ----
@ -163,6 +164,8 @@ sub HOMECRSR () -> (A?, X?, Y?) = $E566 ; cursor to top left of screen
; ---- C64 kernal routines ----
sub IRQDFRT () -> (A?, X?, Y?) = $EA31 ; default IRQ routine
sub IRQDFEND () -> (A?, X?, Y?) = $EA81 ; default IRQ end/cleanup
sub CINT () -> (A?, X?, Y?) = $FF81 ; (alias: SCINIT) initialize screen editor and video chip
sub IOINIT () -> (A?, X?) = $FF84 ; initialize I/O devices
sub RAMTAS () -> (A?, X?, Y?) = $FF87 ; initialize RAM, tape buffer, screen
@ -189,7 +192,7 @@ sub CLOSE (logical: A) -> (A?, X?, Y?) = $FFC3 ; (via 796 ($31C))
sub CHKIN (logical: X) -> (A?, X?) = $FFC6 ; (via 798 ($31E)) define an input channel
sub CHKOUT (logical: X) -> (A?, X?) = $FFC9 ; (via 800 ($320)) define an output channel
sub CLRCHN () -> (A?, X?) = $FFCC ; (via 802 ($322)) restore default devices
sub CHRIN () -> (A, Y?) = $FFCF ; (via 804 ($324)) input a character
sub CHRIN () -> (A, Y?) = $FFCF ; (via 804 ($324)) input a character (for keyboard, read a whole line from the screen) A=byte read.
sub CHROUT (char: A) -> () = $FFD2 ; (via 806 ($326)) output a character
sub LOAD (verify: A, address: XY) -> (SC, A, X, Y) = $FFD5 ; (via 816 ($330)) load from device
sub SAVE (zp_startaddr: A, endaddr: XY) -> (SC, A) = $FFD8 ; (via 818 ($332)) save to a device
@ -205,9 +208,9 @@ sub IOBASE () -> (X, Y) = $FFF3 ; read base address
; ---- end of C64 kernal routines ----
memory .word NMI_VEC = $FFFA
memory .word RESET_VEC = $FFFC
memory .word IRQ_VEC = $FFFE
memory .word NMI_VEC = $FFFA ; nmi vector, set by the kernal if banked in
memory .word RESET_VEC = $FFFC ; reset vector, set by the kernal if banked in
memory .word IRQ_VEC = $FFFE ; interrupt vector, set by the kernal if banked in
}
@ -561,4 +564,26 @@ _pr_decimal
}
}
sub input_chars (buffer: AX) -> (A?, Y) {
; ---- Input a string (max. 80 chars) from the keyboard.
; It assumes the keyboard is selected as I/O channel!!
asm {
sta c64.SCRATCH_ZP1
stx c64.SCRATCH_ZP2
ldy #0 ; char counter = 0
- jsr c64.CHRIN
cmp #$0d ; return (ascii 13) pressed?
beq + ; yes, end.
sta (c64.SCRATCH_ZP1),y ; else store char in buffer
iny
bne -
+ lda #0
sta (c64.SCRATCH_ZP1),y ; finish string with 0 byte
rts
}
}
}

View File

@ -73,6 +73,7 @@ The following 6502 hardware registers are directly accessible in your code (and
- ``A``, ``X``, ``Y``
- ``AX``, ``AY``, ``XY`` (surrogate registers: 16-bit combined register pairs in LSB byte order lo/hi)
- ``SC`` (status register's Carry flag)
- ``SI`` (status register's Interrupt Disable flag)
### Zero Page ("ZP")
@ -240,7 +241,10 @@ if this makes sense.
Subroutines are parts of the code that can be repeatedly invoked using a subroutine call from elsewhere.
Their definition, using the sub statement, includes the specification of the required input- and output parameters.
For now, only register based parameters are supported (A, X, Y and paired registers, and the carry status bit SC as a special).
For now, only register based parameters are supported (A, X, Y and paired registers,
the carry status bit SC and the interrupt disable bit SI as specials).
For subroutine return values, the special SZ register is also available, it means the zero status bit.
The syntax is:
sub <identifier> ([proc_parameters]) -> ([proc_results]) {

View File

@ -223,6 +223,9 @@ start
SC = 0
SC = 1
SC = false
SI = 1
SI = 0
SI = false
uninitbyte1 = 99
uninitbyte1 = 1.234

34
testsource/input.ill Normal file
View File

@ -0,0 +1,34 @@
output prg,sys
import "c64lib"
~ main {
var .text name = "?"*80
start
SI = 1
[$0314.word] = #irq_handler
SI = 0
c64util.print_string("enter your name: ")
c64util.input_chars(name)
c64.CHROUT('\n')
; c64util.print_string("thank you, ") ; @todo fix param parsing /splitting
c64util.print_string("thank you ")
c64util.print_string(name)
c64.CHROUT('\n')
return
irq_handler
asm {
lda $cb
cmp #$40
beq +
inc c64.EXTCOL
+ jmp c64.IRQDFRT
}
}