bson@rice-chex.ai.mit.edu (Jan Brittenson) (12/12/90)
Here are CHIP-48 macro definitions for STAR 1.02.4. Don't try to run it on any version older than 1.02.4, as there is a bug in STAR related to macro argument parsing. To be more specific, any comment on the line will be included in the last argument, causing problems under certain specific conditions. This file is included with the STAR distribution. To find out which version you have, type "star -h". If STAR says `1.02', then it's 1.02.0. The package is a conversion of Roger Ivie's Macro-80 definitions, and are fully compatible. (Therefrom the rather preculiar and Zilogish LD instruction.) The comments are mostly Roger's. Enjoy, --Jan Brittenson bson@ai.mit.edu O / \/ /\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ O \ ;;++ ;; ;; CHIP-8 Macro Definitions for STAR, the Saturn Macro Assembler ;; ;; Copyright (C) 1990 Roger Ivie ;; Copyright (C) 1990 Jan Brittenson ;; ;;-- save list list = 0 if (pass == 1) && !chip8loaded ;;++ ;; ;; This macro package is based on the M80 (Digital Research' ;; Macro Assembler for the Intel 8080 and Zilog Z80 families of ;; micro processors) written by: ;; ;; Roger Ivie ;; slsw2@cc.usu.edu (internet) ;; 35 South 300 West ;; Logan, Utah 84321 ;; ;; ;; If you have questions regarding the STAR port, or about the ;; STAR Macro assembler, write to: ;; ;; Jan Brittenson <bson@ai.mit.edu> ;; ;; This package will not run on any STAR version prior to 1.02.4. ;; ;;-- ; Define symbols for the registers. Note that the scheme assumes that ; data will never be bigger than 12 bits. v0=x'0f000 v1=x'0f001 v2=x'0f002 v3=x'0f003 v4=x'0f004 v5=x'0f005 v6=x'0f006 v7=x'0f007 v8=x'0f008 v9=x'0f009 va=x'0f00a vb=x'0f00b vc=x'0f00c vd=x'0f00d ve=x'0f00e vf=x'0f00f hide v0 hide v1 hide v2 hide v3 hide v4 hide v5 hide v6 hide v7 hide v8 hide v9 hide va hide vb hide vc hide vd hide ve hide vf __instrhi=0 __instrlo=0 hide __instrhi hide __instrlo ;------- ; ; Other-endian DW macro __dw value=0 value = $value byte value >> 8 & 0xff, value & 0xff endmacro hide __dw ;------- ; ; Clear screen: ; ; CLS macro cls __dw 0x00e0 endmacro hide cls ;------- ; ; Return from subroutine: ; ; RET ; RETURN macro ret __dw 0x00ee endmacro macro return __dw 0x00ee endmacro hide ret hide return ;------- ; ; Jump to location: ; ; JUMP <addr> ; JUMP <addr>+V0 macro jump dest dest=$dest if dest >= v0 __dw dest & 0x0fff + 0x0b000 else ;; Otherwise, it's JUMP <addr> __dw dest + 0x01000 endif endmacro hide jump ;------- ; ; Call a subroutine: ; ; CALL <addr> ; macro call dest __dw $dest + 0x02000 endmacro hide call ;------- ; ; Skip if equal: ; ; SKE Vx,<constant> ; SKE Vx,Vy macro ske x, y x = $x y = $y if x >= v0 ;; Verify first operand is a register if y >= v0 ;; It's SKE Vx,Vy __dw ((x & 0xf) << 8) + ((y & 0xf) << 4) + 0x5000 else __dw ((x & 0xf) << 8) + y + 0x3000 endif else error The first operand of SKE must be a register, not `$x' data.4 0 endif endmacro hide ske ;------- ; ; Skip if not equal: ; ; SKNE Vx,<constant> ; SKNE Vx,Vy macro skne x, y x = $x y = $y if x >= v0 ;; Verify first operand is a register if y >= v0 ;; It's SKNE Vx,Vy __dw ((x & 0xf) << 8) + ((y & 0xf) << 4) + 0x9000 else ;; It's SKNE Vx,<constant> __dw ((x & 0xf) << 8) + y + 0x4000 endif else error The first operand of SKNE must be a register, not `$x' data.4 0 endif endmacro hide skne ;------- ; ; Register transfer: ; ; LD Vx,<constant> ; LD Vx,Vy ; LD I,<constant> ; LD Vx,DELAY ; LD DELAY,Vx ; LD SOUND,Vx ; LD BCD,Vx ; LD @I,Vx ; LD Vx,@I macro ld dest, src if uc^dest == `I' ;; It's LD I,? if ($src) < v0 ;; Source has to be a constant __dw ($src) + 0xa000 else error I can only be loaded from a constant, not `$src' data.4 0 endif else ;; *1* if uc^dest == `DELAY' ;; It's LD DELAY,? if ($src) >= v0 ;; Source has to be a register __dw ($src) & 0xf << 8 + 0xf015 else error DELAY can only be loaded from a register, not `$src' data.4 0 endif else ;; *2* if uc^src == `DELAY' ;; It's LD ?,DELAY if ($dest) >= v0 ;; Destination has to be a register __dw ($dest) & 0xf << 8 + 0xf007 else error Only a register can be loaded from DELAY, not `$src' data.4 0 endif else ;; *3* if uc^dest == `SOUND' ;; It's LD SOUND,? if ($src) >= v0 ;; Source has to be a register __dw ($src) & 0xf << 8 + 0xf018 else error SOUND can only be loaded from a register, not `$src' data.4 0 endif else ;; *4* if uc^dest == `BCD' ;; It's LD BCD,? if ($src) >= v0 ;; Source has to be a register __dw ($src) & 0xf << 8 + 0xf033 else error BCD can only be loaded from a register, not `$src' data.4 0 endif else ;; *5* if uc^dest == `@I' ;; It's LD @I,? if src >= v0 ;; Source has to be a register __dw ($src) & 0xf << 8 + 0xf055 else error @I can only be loaded from a register, not `$src' data.4 0 endif else ;; *6* if uc^src == `@I' ;; It's LD ?,@I if ($dest) >= v0 ;; Destination as to be a register __dw ($dest) & 0xf << 8 + 0xf065 else error Only a register can be loaded from @I, not `$dest' data.4 0 endif else ;; *7* ;; If we get here, it should be either LD Vx,Vy or LD Vx,<constant> dest = $dest src = $src if dest >= v0 ;; Make certain destination is a register if src < v0 ;; It's LD Vx,<constant> __dw dest & 0xf << 8 + src + 0x6000 else ;; It has to be LD Vx,Vy __dw dest & 0xf << 8 + (src & 0xf << 4) + 0x8000 endif else error Invalid LD instruction data.4 0 endif endif endif endif endif endif endif endif endmacro hide ld ;------- ; ; Add two operands: ; ; ADD Vx,<constant> ; ADD Vx,Vy ; ADD I,Vx macro add dest, src src = $src if uc^dest == `I' ;; It's ADD I,Vx if src >= v0 ;; Verify that the source is a register __dw src & 0xf << 8 + 0xf01e else error Only a register can be added to I, not `$src' data.4 0 endif else ;; *1* ;; It has to be either ADD Vx,Vy or ADD Vx,<constant> dest = $dest if dest >= v0 ;; Verify that the destination is a register if src >= v0 ;; It's ADD Vx,Vy __dw dest & 0xf << 8 + (src & 0xf << 4) + 0x8004 else ;; It's ADD Vx,<constant> __dw dest & 0xf << 8 + src + 0x7000 endif else error Things can be ADDed only to I or to a register, not `$dest' data.4 0 endif endif endmacro hide add ;------- ; ; Inclusive or: ; ; OR Vx,Vy macro or dest,src dest = $dest src = $src if (dest >= v0) && (src >= v0) __dw ((dest & 0xf) << 8) + ((src & 0xf) << 4) + 0x8001 else error Both operands must be registers data.4 0 endif endmacro hide or ;------- ; ; Bitwise and: ; ; AND Vx,Vy macro and dest,src dest = $dest src = $src if (dest >= v0) && (src >= v0) __dw ((dest & 0xf) << 8) + ((src & 0xf) << 4) + 0x8002 else error Both operands must be registers data.4 0 endif endmacro hide and ;------- ; ; Bitwise exclusive or: ; ; XOR Vx,Vy macro xor dest,src dest = $dest src = $src if (dest >= v0) && (src >= v0) __dw ((dest & 0xf) << 8) + ((src & 0xf) << 4) + 0x8003 else error Both operands must be registers data.4 0 endif endmacro hide xor ;------- ; ; Subtract: ; ; SUB Vx,Vy macro sub dest,src dest = $dest src = $src if (dest >= v0) && (src >= v0) __dw ((dest & 0xf) << 8) + ((src & 0xf) << 4) + 0x8005 else error Both operands must be registers data.4 0 endif endmacro hide sub ;------- ; ; Shift right: ; ; SHR Vx,Vy macro shr dest,src dest = $dest src = $src if (dest >= v0) && (src >= v0) __dw ((dest & 0xf) << 8) + ((src & 0xf) << 4) + 0x8006 else error Both operands must be registers data.4 0 endif endmacro hide shr ;------- ; ; Reverse subtract: ; ; RSUB Vx,Vy macro rsub dest,src dest = $dest src = $src if (dest >= v0) && (src >= v0) __dw ((dest & 0xf) << 8) + ((src & 0xf) << 4) + 0x8007 else error Both operands must be registers data.4 0 endif endmacro hide rsub ;------- ; ; Shift left: ; ; SHL Vx,Vy macro shl dest,src dest = $dest src = $src if (dest >= v0) && (src >= v0) __dw ((dest & 0xf) << 8) + ((src & 0xf) << 4) + 0x800E else error Both operands must be registers data.4 0 endif endmacro hide shl ;------- ; ; And constant and random number: ; ; RANDOM Vx ; Uses 0FFH for constant ; RANDOM Vx,<constant> macro random dest,mask=``nil'' dest = $dest mask = $mask if dest >= v0 if mask == `nil' __dw ((dest & 0xf) << 8) + 0xc0ff else __dw ((dest & 0xf) << 8) + mask + 0xc000 endif else error First operand must be a register, not `$dest' data.4 0 endif endmacro hide random ;------- ; ; Show sprite: ; ; SHOW Vx,Vy,N macro show x,y,n x = $x y = $y n = $n if (x >= v0) && (y >= v0) __DW ((x & 0xf) << 8) + ((y & 0xf) << 4) + (n & 0xf) + 0xd000 else error Coordinates must be registers data.4 0 endif endmacro hide show ;------- ; ; Skip if key pressed: ; ; SKIFKEY Vx macro skifkey dest dest = $dest if dest >= v0 __dw ((dest & 0xf) << 8) + 0xe09e else error Destination must be a register data.4 0 endif endmacro hide skifkey ;------- ; ; Skip if key not pressed: ; ; SKIFNOTKEY Vx macro skifnotkey dest dest = $dest if dest >= v0 __dw ((dest & 0xf) << 8) + 0xe0a1 else error Destination must be a register, not `$dest' data.4 0 endif endmacro hide skifnotkey ;------- ; ; Get a keystroke: ; ; GETKEY Vx macro getkey dest dest = $dest if dest >= v0 __dw ((dest & 0xf) << 8) + 0xf00a else error Destination must be a register, not `$dest' data.4 0 endif endmacro hide getkey ;------- ; ; Point to character font element: ; ; CHAR Vx macro char src src = $src if src >= v0 __dw ((src & 0xf) << 8) + 0xF029 else error Source must be a register data.4 0 endif endmacro hide char chip8loaded = 1 hide chip8loaded static 0, x'1ff floating x'200, x'ffff endif . = x'200 hide list restore list