DATA:	NEG1:	-1
	ONE:	1
	ZERO:	0
	RDWRT:	0
	TA:	0
	TB:	0
	TC1:	0
	TC2:	0
	TZ:	0
	STACK:	0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
		0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
	SP:	STACK

; Unconditional branch macro
#define	GOTO(a)	NEG1 ZERO a

; Conditional branch macros
#define	BLT(a,b,c)		\
	TA	TA	.+1	\
	TB	TB	.+1	\
	TA	a	.+1	\
	TB	b	.+1	\
	TB	TA	c

#define	BGT(a,b,c)		\
	TA	TA	.+1	\
	TB	TB	.+1	\
	TA	a	.+1	\
	TB	b	.+1	\
	TA	TB	c

#define	BLE(a,b,c)		\
	TA	TA	.+1	\
	TB	TB	.+1	\
	TA	a	.+1	\
	TB	b	.+1	\
	TB	TA	c	\
	TB	ONE	c

#define	BGE(a,b,c)		\
	TA	TA	.+1	\
	TB	TB	.+1	\
	TA	a	.+1	\
	TB	b	.+1	\
	TA	TB	c	\
	TA	ONE	c

#define	BEQ(a,b,c)		\
	TA	TA	.+1	\
	TB	TB	.+1	\
	TA	a	.+1	\
	TB	b	.+1	\
	TA	TB	.+10	\
	TB	TB	.+1	\
	TB	TA	.+4	\
	NEG1	ZERO	c

#define	BNE(a,b,c)		\
	TA	TA	.+1	\
	TB	TB	.+1	\
	TA	a	.+1	\
	TB	b	.+1	\
	TA	TB	c	\
	TB	TB	.+1	\
	TB	TA	c

; Halt macro
#define	HALT	NEG1 ZERO STOP

; Read in values
#define	READINT(a)		\
	RDWRT	RDWRT	.+1	\
	RDWRT	READ	.+1	\
	a	a	.+1	\
	a	RDWRT	.+1

; Write out values
#define	WRITEINT(a)		\
	RDWRT	RDWRT	.+1	\
	RDWRT	a	.+1	\
	WRITE	RDWRT	.+1


; Address assignment: b = &a
; Tricky part: some data is stored in the middle, skipped
; over by the NEG1 ZERO .2 (notice the +2)
#define	AMOV(a,b)		\
	b	b	.+1	\
	TB	TB	.+1	\
	NEG1	ZERO	.+2	\
	a			\
	TB	.-2	.+1	\
	b	TB	.+1

; Indirect move: b = *a
; Tricky part: self-modifying code is used.  The address a
; is copied into the Y field of an instruction.
#define	IMOV(a,b)		\
	b	b	.+1	\
	TA	TA	.+1	\
	TB	TB	.+1	\
	TA	a	.+1	\
	.+7	.+6	.+1	\
	.+4	TA	.+1	\
	TB	0	.+1	\
	b	TB	.+1

; Indirect move: *b = a
; Tricky part: self-modifying code is used.  The address b
; is copied into the X and Y fields of an instruction, to clear
; the location pointed to by b.  The address b is then copied
; into the X field of a second instruction, to actually perform
; the move.  36 words.
#define	MOVI(a,b)		\
	TA	TA	.+1	\
	TB	TB	.+1	\
	TA	a	.+1	\
	TB	b	.+1	\
	.+13	.+12	.+1	\
	.+10	TB	.+1	\
	.+6	.+5	.+1	\
	.+3	TB	.+1	\
	0	0	.+1	\
	.+6	.+5	.+1	\
	.+3	TB	.+1	\
	0	TA	.+1

; Push a value on the stack: *SP++ = a
; 39 words
#define	PUSH(a)			\
	MOVI(a,SP)		\
	SP	NEG1	.+1

; Pop a value from the stack: a = *--SP
#define	POP(a)			\
	SP	ONE	.+1	\
	IMOV(SP,a)

; Call a subroutine - b is the label to return to
#define	CALL(a,b)		\
	AMOV(b,TC1)		\
	TC2	TC2	.+1	\
	TC2	TC1	.+1	\
	PUSH(TC2)		\
	NEG1	ZERO	a

; Return from a subroutine
; Tricky part: self-modifying code is used to get the return address
#define	RET			\
	POP(TC1)		\
	.+8	.+7	.+1	\
	.+5	TC1	.+1	\
	NEG1	ZERO	0

; Copy value: b = a
#define	MOV(a,b)		\
	TA	TA	.+1	\
	b	b	.+1	\
	TA	a	.+1	\
	b	TA	.+1

; Add values: c = a + b
#define	ADD(a,b,c)		\
	TA	TA	.+1	\
	TA	a	.+1	\
	TA	b	.+1	\
	c	c	.+1	\
	c	TA	.+1

; Divide values: c = a / b
#define	DIV(a,b,c)		\
	TA	TA	.+1	\
	TB	TB	.+1	\
	TA	a	.+1	\
	TB	b	.+1	\
	TZ	TZ	.+1	\
	c	c	.+1	\
	TA	TB	.+4	\
	TZ	TA	.+7	\
	c	NEG1	.+1	\
	GOTO(.-11)

; Multiply numbers: c = a * b
#define	MUL(a,b,c)		\
	c	c	.+1	\
	TB	TB	.+1	\
	TB	b	.+1	\
	TB	ONE	.+1	\
	TB	NEG1	.+4	\
	GOTO(.+10)		\
	c	a	.+1	\
	GOTO(.-11)		\
	TB	TB	.+1	\
	TA	TA	.+1	\
	TB	c	.+1	\
	TA	TB	.+1	\
	c	c	.+1	\
	c	TA	.+1

; Macro to subtract two numbers: c = a - b
#define	SUB(a,b,c)		\
	c	c	.+1	\
	c	b	.+1	\
	TA	TA	.+1	\
	TA	a	.+1	\
	TA	c	.+1	\
	c	c	.+1	\
	c	TA	.+1
