[comp.sys.handhelds] CHIP8 Macros for STAR 1.02.4 or later

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