misc/instructiontest.s (2/2)
1 2
	movea.l	14(sp),a0		;pc
	moveq.l	#$ffffffc0,d0
	and.w	(a0),d0			;oc
	cmp.w	#$40c0,d0
	beq	10f			;move-from-sr
	movem.l	(sp)+,d0-d1/a0
	move.l	old_privilege_instruction,-(sp)
	rts

;move-from-sr
10:	ori.w	#$0200,(a0)		;modify move-from-sr to move-from-ccr
	jbsr	cache_flush
	movem.l	(sp)+,d0-d1/a0
	rte

	.data
	.align	4
old_privilege_instruction:
	.dc.l	0


;--------------------------------------------------------------------------------
;timerc
	.text
	.even
new_timerc_handler:
	addq.l	#1,timerc_counter
	move.l	old_timerc_handler,-(sp)
	rts

	.data
	.align	4
old_timerc_handler:
	.dc.l	0
timerc_counter:
	.dc.l	0


;--------------------------------------------------------------------------------
;mnemonic
;<d0.l:test_number
;<a0.l:mnemonic
;>d0.l:0=skip,1=test
;?a0-a1
	.text
	.even
mnemonic_check:
	movem.l	a0-a2,-(sp)
	lea.l	test_flag,a2
	adda.l	d0,a2
	tst.b	(a2)
	bne	2f			;already tested
	lea.l	mnemonic_buffer,a1
	cmpi.l	#'all'<<8,(a1)
	beq	3f			;all
1:	tst.b	(a1)
	beq	3f
	cmpm.b	(a0)+,(a1)+
	beq	1b
2:	moveq.l	#0,d0			;skip
	bra	4f
3:	st.b	(a2)

	move.b	test_level,d0
	cmp.b	last_level,d0
	beq	@f
	move.b	d0,last_level
	jbsr	print_header
@@:

	move.l	timerc_counter,mnemonic_started

	moveq.l	#1,d0			;test
4:	movem.l	(sp)+,a0-a2
	rts

	.bss
	.align	4
mnemonic_buffer:
	.ds.b	256+4
	.align	4
mnemonic_started:
	.ds.l	1
mnemonic_ended:
	.ds.l	1


;--------------------------------------------------------------------------------
;test
	.text
	.even
test_start:
	clr.l	test_failed
	clr.l	test_tested
	rts

;<d1.l:expected crc32
;<CRC32_REG.l:actual crc32
;?d0
	.text
	.even
test_check:
	move.l	timerc_counter,mnemonic_ended
	movem.l	d0-d1,-(sp)
	addq.l	#1,test_tested
	move.l	d1,d0			;expected crc32
	jbsr	print_hex8
	print	'   '
	move.l	CRC32_REG,d0		;actual crc32
	jbsr	print_hex8
	cmp.l	CRC32_REG,d1
	bne	1f
	print	'   OK      '
	bra	2f
1:	print	'   ERROR   '
	addq.l	#1,test_failed
2:	move.l	mnemonic_ended,d0
	sub.l	mnemonic_started,d0
	moveq.l	#2,d1
	jbsr	print_fix
	print	's',13,10
	movem.l	(sp)+,d0-d1
	rts

test_end:
	movem.l	d0-d4,-(sp)
	move.l	test_failed,d2
;<d2.lfailed
	move.l	test_tested,d3
;<d3.l:tested
	move.l	d3,d4
	sub.l	d2,d4
;<d4.l:passed
	print	'tested:'
	move.l	d3,d0			;tested
	jbsr	print_dec
	tst.l	d3
	beq	38f			;no tests were performed
	print	', passed:'
	move.l	d4,d0			;passed
	jbsr	print_dec
	print	'('
	mulu.w	#10000,d0
	divu.w	d3,d0			;10000*passed/tested
	and.l	#$0000ffff,d0
	move.l	#10000,d4
	sub.w	d0,d4			;100-100*passed/tested
	moveq.l	#2,d1
	jbsr	print_fix
	print	'%), failed:'
	move.l	d2,d0			;failed
	jbsr	print_dec
	print	'('
	move.l	d4,d0			;100-100*passed/tested
	jbsr	print_fix
	print	'%)'
38:
	jbsr	print_crlf
	move.l	test_ended,d0
	sub.l	test_started,d0
	moveq.l	#2,d1
	jbsr	print_fix
	print	's',13,10
	movem.l	(sp)+,d0-d4
	rts

	.bss
	.align	4
test_failed:
	.ds.l	1
test_tested:
	.ds.l	1
test_started:
	.ds.l	1
test_ended:
	.ds.l	1


;--------------------------------------------------------------------------------
;ccr data
	.data

	.align	4
ccr_mono_data:
	.dc.w	0,31
;sentry
	.dc.w	0

	.align	4
ccr_light_data:
	.dc.w	%00000,%11111,%00001,%11110,%00010,%11101,%00100,%11011,%01000,%10111,%10000,%01111
;sentry
	.dc.w	0

	.align	4
ccr_full_data:
	.dc.w	0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
;sentry
	.dc.w	0


;--------------------------------------------------------------------------------
;bit field data
	.data
	.align	4
bf_offset_data:
	.dc.l	0,1,7,8,9,15,16,17,23,24,25,31	;zero must appear first
	.dc.l	32,33,39,40,41,47,48,49,55,56,57,63
	.dc.l	-32,-31,-25,-24,-23,-17,-16,-15,-9,-8,-7,-1
;sentry
	.dc.l	0
bf_width_data:
	.dc.l	1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32
;sentry
	.dc.l	0


;--------------------------------------------------------------------------------
;byte data

put_byte	.macro	x
	.dc.l	x
	.dc.l	.notb.(x)
	.dc.l	$ffffff00+(x)
	.dc.l	$ffffff00+.notb.(x)
	.endm

	.data

	.align	4
byte_mono_data:
;no one
	put_byte	0
;sentry
	.dc.l	0

	.align	4
byte_light_data:
;no one
	put_byte	0
;one one
  .irp i,0,1,7
	put_byte	1<<i
  .endm
;two ones
  .irp i,0,1,7
    .irp j,0,1,7
      .if i>j
	put_byte	(1<<i)+(1<<j)
      .endif
    .endm
  .endm
;three or more consecutive ones
  .irp i,0,1,7
    .irp j,0,1,7
      .if i>j+1
	put_byte	(2<<i)-(1<<j)
      .endif
    .endm
  .endm
;sentry
	.dc.l	0

	.align	4
byte_medium_data:
;no one
	put_byte	0
;one one
  .irp i,0,1,2,4,6,7
	put_byte	1<<i
  .endm
;two ones
  .irp i,0,1,2,4,6,7
    .irp j,0,1,2,4,6,7
      .if i>j
	put_byte	(1<<i)+(1<<j)
      .endif
    .endm
  .endm
;three or more consecutive ones
  .irp i,0,1,2,4,6,7
    .irp j,0,1,2,4,6,7
      .if i>j+1
	put_byte	(2<<i)-(1<<j)
      .endif
    .endm
  .endm
;sentry
	.dc.l	0

	.align	4
byte_heavy_data:
;no one
	put_byte	0
;one one
  .irp i,0,1,2,3,4,5,6,7
	put_byte	1<<i
  .endm
;two ones
  .irp i,0,1,2,3,4,5,6,7
    .irp j,0,1,2,3,4,5,6,7
      .if i>j
	put_byte	(1<<i)+(1<<j)
      .endif
    .endm
  .endm
;three or more consecutive ones
  .irp i,0,1,2,3,4,5,6,7
    .irp j,0,1,2,3,4,5,6,7
      .if i>j+1
	put_byte	(2<<i)-(1<<j)
      .endif
    .endm
  .endm
;sentry
	.dc.l	0

	.align	4
byte_full_data:
  .irp i,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
    .irp j,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
	put_byte	(i<<4)+j
    .endm
  .endm
;sentry
	.dc.l	0


;--------------------------------------------------------------------------------
;word data

put_word	.macro	x
	.dc.l	x
	.dc.l	.notw.(x)
	.dc.l	$ffff0000+(x)
	.dc.l	$ffff0000+.notw.(x)
	.endm

	.data

	.align	4
word_mono_data:
;no one
	put_word	0
;sentry
	.dc.l	0

	.align	4
word_light_data:
;no one
	put_word	0
;one one
  .irp i,0,1,7,8,9,15
	put_word	1<<i
  .endm
;two ones
  .irp i,0,1,7,8,9,15
    .irp j,0,1,7,8,9,15
      .if i>j
	put_word	(1<<i)+(1<<j)
      .endif
    .endm
  .endm
;three or more consecutive ones
  .irp i,0,1,7,8,9,15
    .irp j,0,1,7,8,9,15
      .if i>j+1
	put_word	(2<<i)-(1<<j)
      .endif
    .endm
  .endm
;sentry
	.dc.l	0

	.align	4
word_medium_data:
;no one
	put_word	0
;one one
  .irp i,0,1,2,4,6,7,8,9,10,12,14,15
	put_word	1<<i
  .endm
;two ones
  .irp i,0,1,2,4,6,7,8,9,10,12,14,15
    .irp j,0,1,2,4,6,7,8,9,10,12,14,15
      .if i>j
	put_word	(1<<i)+(1<<j)
      .endif
    .endm
  .endm
;three or more consecutive ones
  .irp i,0,1,2,4,6,7,8,9,10,12,14,15
    .irp j,0,1,2,4,6,7,8,9,10,12,14,15
      .if i>j+1
	put_word	(2<<i)-(1<<j)
      .endif
    .endm
  .endm
;sentry
	.dc.l	0

	.align	4
word_heavy_data:
;no one
	put_word	0
;one one
  .irp i,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
	put_word	1<<i
  .endm
;two ones
  .irp i,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
    .irp j,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
      .if i>j
	put_word	(1<<i)+(1<<j)
      .endif
    .endm
  .endm
;three or more consecutive ones
  .irp i,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
    .irp j,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
      .if i>j+1
	put_word	(2<<i)-(1<<j)
      .endif
    .endm
  .endm
;sentry
	.dc.l	0


;--------------------------------------------------------------------------------
;long data

put_long	.macro	x
	.dc.l	x
	.dc.l	.not.(x)
	.endm

	.data

	.align	4
long_mono_data:
;no one
	put_long	0
;sentry
	.dc.l	0

	.align	4
long_light_data:
;no one
	put_long	0
;one one
  .irp i,0,1,7,8,9,15,16,17,23,24,25,31
	put_long	1<<i
  .endm
;two ones
  .irp i,0,1,7,8,9,15,16,17,23,24,25,31
    .irp j,0,1,7,8,9,15,16,17,23,24,25,31
      .if i>j
	put_long	(1<<i)+(1<<j)
      .endif
    .endm
  .endm
;three or more consecutive ones
  .irp i,0,1,7,8,9,15,16,17,23,24,25,31
    .irp j,0,1,7,8,9,15,16,17,23,24,25,31
      .if i>j+1
	put_long	(2<<i)-(1<<j)
      .endif
    .endm
  .endm
;sentry
	.dc.l	0

	.align	4
long_medium_data:
;no one
	put_long	0
;one one
  .irp i,0,1,2,4,6,7,8,9,10,12,14,15,16,17,18,20,22,23,24,25,26,28,30,31
	put_long	1<<i
  .endm
;two ones
  .irp i,0,1,2,4,6,7,8,9,10,12,14,15,16,17,18,20,22,23,24,25,26,28,30,31
    .irp j,0,1,2,4,6,7,8,9,10,12,14,15,16,17,18,20,22,23,24,25,26,28,30,31
      .if i>j
	put_long	(1<<i)+(1<<j)
      .endif
    .endm
  .endm
;three or more consecutive ones
  .irp i,0,1,2,4,6,7,8,9,10,12,14,15,16,17,18,20,22,23,24,25,26,28,30,31
    .irp j,0,1,2,4,6,7,8,9,10,12,14,15,16,17,18,20,22,23,24,25,26,28,30,31
      .if i>j+1
	put_long	(2<<i)-(1<<j)
      .endif
    .endm
  .endm
;sentry
	.dc.l	0

	.align	4
long_heavy_data:
;no one
	put_long	0
;one one
  .irp i,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
	put_long	1<<i
  .endm
;two ones
  .irp i,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
    .irp j,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
      .if i>j
	put_long	(1<<i)+(1<<j)
      .endif
    .endm
  .endm
;three or more consecutive ones
  .irp i,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
    .irp j,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
      .if i>j+1
	put_long	(2<<i)-(1<<j)
      .endif
    .endm
  .endm
;sentry
	.dc.l	0


;--------------------------------------------------------------------------------
;quad data

put_quad	.macro	xh,xl
	.dc.l	xh,xl
	.dc.l	.not.(xh),.not.(xl)
	.endm

	.data

	.align	4
quad_mono_data:
;no one
	put_quad	0,0
;sentry
	.dc.l	0,0

	.align	4
quad_light_data:
;no one
	put_quad	0,0
;one one
  .irp i,0,1,7,8,9,15,16,17,23,24,25,31,32,33,39,40,41,47,48,49,55,56,57,63
    .if i<32
	put_quad	0,1<<i
    .else
	put_quad	1<<(i-32),0
    .endif
  .endm
;two ones
  .irp i,0,1,7,8,9,15,16,17,23,24,25,31,32,33,39,40,41,47,48,49,55,56,57,63
    .irp j,0,1,7,8,9,15,16,17,23,24,25,31,32,33,39,40,41,47,48,49,55,56,57,63
      .if i>j
        .if i<32
	put_quad	0,(1<<i)+(1<<j)
        .elif j<32
	put_quad	1<<(i-32),1<<j
        .else
	put_quad	(1<<(i-32))+(1<<(j-32)),0
        .endif
      .endif
    .endm
  .endm
;sentry
	.dc.l	0,0


;--------------------------------------------------------------------------------
;sext data

put_sext	.macro	xh,xm,xl
	.dc.l	xh,xm,xl
	.dc.l	.not.(xh),.not.(xm),.not.(xl)
	.endm

	.data

	.align	4
sext_mono_data:
;no one
	put_sext	0,0,0
;sentry
	.dc.l	0,0,0

	.align	4
sext_light_data:
;no one
	put_sext	0,0,0
;one one
  .irp i,0,1,7,8,9,15,16,17,23,24,25,31,32,33,39,40,41,47,48,49,55,56,57,63,64,65,71,72,73,79,80,81,87,88,89,95
    .if i<32
	put_sext	0,0,1<<i
    .elif i<64
	put_sext	0,1<<(i-32),0
    .else
	put_sext	1<<(i-64),0,0
    .endif
  .endm
;sentry
	.dc.l	0,0,0


;--------------------------------------------------------------------------------
;oct data

put_oct	.macro	x0,x1,x2,x3
	.dc.l	x0,x1,x2,x3
	.dc.l	.not.(x0),.not.(x1),.not.(x2),.not.(x3)
	.endm

	.data

	.align	4
oct_mono_data:
;no one
	put_oct	0,0,0,0
;sentry
	.dc.l	0,0,0,0

	.align	4
oct_light_data:
;no one
	put_oct	0,0,0,0
;one one
  .irp i,0,1,7,8,9,15,16,17,23,24,25,31,32,33,39,40,41,47,48,49,55,56,57,63,64,65,71,72,73,79,80,81,87,88,89,95,96,97,103,104,105,111,112,113,119,120,121,127
    .if i<32
	put_oct	0,0,0,1<<i
    .elif i<64
	put_oct	0,0,1<<(i-32),0
    .elif i<96
	put_oct	0,1<<(i-64),0,0
    .else
	put_oct	1<<(i-96),0,0,0
    .endif
  .endm
;sentry
	.dc.l	0,0,0,0

	.align	4
oct_medium_data:
;no one
	put_oct	0,0,0,0
;one one
  .irp i,0,1,2,4,6,7,8,9,10,12,14,15,16,17,18,20,22,23,24,25,26,28,30,31,32,33,34,36,38,39,40,41,42,44,46,47,48,49,50,52,54,55,56,57,58,60,62,63,64,65,66,68,70,71,72,73,74,76,78,79,80,81,82,84,86,87,88,89,90,92,94,95,96,97,98,100,102,103,104,105,106,108,110,111,112,113,114,116,118,119,120,121,122,124,126,127
    .if i<32
	put_oct	0,0,0,1<<i
    .elif i<64
	put_oct	0,0,1<<(i-32),0
    .elif i<96
	put_oct	0,1<<(i-64),0,0
    .else
	put_oct	1<<(i-96),0,0,0
    .endif
  .endm
;sentry
	.dc.l	0,0,0,0


;--------------------------------------------------------------------------------
;mpu
	.text
	.even
mpu_check:
	move.l	mpu_number,d0
	bmi	@f
	rts

@@:	movem.l	d1/a0-a1,-(sp)
;
	clr.l	-(sp)
	DOS	_SUPER
	move.l	d0,(sp)
;
	move.w	sr,-(sp)		;sr
	ori.w	#$0700,sr
	move.l	$002c.w,-(sp)		;line 1111 emulator
	move.l	$0010.w,-(sp)		;illegal instruction
	lea.l	100f(pc),a1
	move.l	a1,$0010.w
	move.l	a1,$002c.w
	movea.l	sp,a1
;MC68000
;!VBR
	moveq.l	#0,d1
	lea.l	99f(pc),a0
	.cpu	68010
	movec.l	vbr,d0
	.cpu	68000
;MC68010
;VBR && !scale factor
	moveq.l	#1,d1
	moveq.l	#1,d0
	.cpu	68020
	and.b	(*-3,pc,d0.w*2),d0
	.cpu	68010
	beq	99f
;MC68020
;CALLM
	moveq.l	#2,d1
	lea.l	29f(pc),a0
	.cpu	68020
	callm	#0,21f(pc)
	.cpu	68000
	bra	99f

;module descriptor
21:	.dc.l	0<<13|0<<24|0<<16	;option=0,type=0,accesslevel=0
	.dc.l	22f			;module entry pointer
	.dc.l	0			;module data area pointer
	.dc.l	0
;module entry
22:	.dc.w	15<<12			;Rn=sp
	.cpu	68020
	rtm	sp
	.cpu	68000

29:
;MC68030
;!CALLM && CAAR
	moveq.l	#3,d1
	lea.l	39f(pc),a0
	.cpu	68030
	movec.l	caar,d0
	.cpu	68000
	bra	99f

39:
;MC68040
;MMUSR
	moveq.l	#4,d1
	lea.l	49f(pc),a0
	.cpu	68040
	movec.l	mmusr,d0
	.cpu	68000
	bra	99f

49:
;MC68060
;PCR
	moveq.l	#6,d1
	lea.l	69f(pc),a0
	.cpu	68060
	movec.l	pcr,d0
	.cpu	68000
	bra	99f

69:
;unknown
	moveq.l	#0,d1
;
99:	move.l	(sp)+,$0010.w		;illegal instruction
	move.l	(sp)+,$002c.w		;line 1111 emulator
	move.w	(sp)+,sr		;sr
;
	DOS	_SUPER
	addq.l	#4,sp
;
	move.l	d1,d0
	movem.l	(sp)+,d1/a0-a1
	move.l	d0,mpu_number
	rts

100:	movea.l	a1,sp
	jmp	(a0)

;cache flush
;	supervisor mode only
cache_flush:
	move.l	d0,-(sp)
	jbsr	mpu_check
	subq.b	#2,d0
	bcs	9f
	subq.b	#4-2,d0
	bcc	4f
;MC68020/MC68030
	.cpu	68030
	movec.l	cacr,d0
	or.w	#$0808,d0
	movec.l	d0,cacr
	and.w	#$f7f7,d0
	movec.l	d0,cacr
	.cpu	68000
	bra	9f

;MC68040/MC68060
4:	.cpu	68040
	cpusha	bc
	.cpu	68000
9:	move.l	(sp)+,d0
	rts

	.data
	.align	4
mpu_number:
	.dc.l	-1

;--------------------------------------------------------------------------------
;crc32
  .if 0
	.text
	.even
crc32_test:
	move.l	d0,-(sp)
;crc32('A')=$d3d99e8b
	jbsr	crc32_reset
	moveq.l	#'A',d0
	jbsr	crc32_byte
	jbsr	crc32_print
	jbsr	print_crlf
;crc32('ABCD')=$db1720a5
	jbsr	crc32_reset
	move.l	#'ABCD',d0
	jbsr	crc32_long
	jbsr	crc32_print
	jbsr	print_crlf
	move.l	(sp)+,d0
	rts

crc32_print:
	move.l	d0,-(sp)
	move.l	CRC32_REG,d0
	jbsr	print_hex8
	move.l	(sp)+,d0
	rts
  .endif

	.text
	.even
crc32_reset:
	moveq.l	#0,CRC32_REG
	rts

;<d0.b:data
;<CRC32_REG.l:crc32
;>CRC32_REG.l:crc32
;?d0
	.text
	.even
crc32_byte:
	move.l	d0,-(sp)
	not.l	CRC32_REG
	eor.b	d0,CRC32_REG
	moveq.l	#0,d0
	move.b	CRC32_REG,d0
	lsr.l	#8,CRC32_REG
	lsl.w	#2,d0
	move.l	crc32_table(pc,d0.w),d0
	eor.l	d0,CRC32_REG
	not.l	CRC32_REG
	move.l	(sp)+,d0
	rts

;<d0.w:data
;<CRC32_REG.l:crc32
;>CRC32_REG.l:crc32
	.text
	.even
crc32_word:
	movem.l	d0-d1,-(sp)
	not.l	CRC32_REG
	moveq.l	#-2,d1
1:	moveq.l	#0,d0
	move.b	4(sp,d1.w),d0
	eor.b	CRC32_REG,d0
	lsr.l	#8,CRC32_REG
	lsl.w	#2,d0
	move.l	crc32_table(pc,d0.w),d0
	eor.l	d0,CRC32_REG
	addq.w	#1,d1
	bne	1b
	not.l	CRC32_REG
	movem.l	(sp)+,d0-d1
	rts

;<d0.l:data
;<CRC32_REG.l:crc32
;>CRC32_REG.l:crc32
	.text
	.even
crc32_long:
	movem.l	d0-d1,-(sp)
	not.l	CRC32_REG
	moveq.l	#-4,d1
1:	moveq.l	#0,d0
	move.b	4(sp,d1.w),d0
	eor.b	CRC32_REG,d0
	lsr.l	#8,CRC32_REG
	lsl.w	#2,d0
	move.l	crc32_table(pc,d0.w),d0
	eor.l	d0,CRC32_REG
	addq.w	#1,d1
	bne	1b
	not.l	CRC32_REG
	movem.l	(sp)+,d0-d1
	rts

	.text
	.align	4
crc32_table:
	.dc.l	$00000000,$77073096,$ee0e612c,$990951ba,$076dc419,$706af48f,$e963a535,$9e6495a3
	.dc.l	$0edb8832,$79dcb8a4,$e0d5e91e,$97d2d988,$09b64c2b,$7eb17cbd,$e7b82d07,$90bf1d91
	.dc.l	$1db71064,$6ab020f2,$f3b97148,$84be41de,$1adad47d,$6ddde4eb,$f4d4b551,$83d385c7
	.dc.l	$136c9856,$646ba8c0,$fd62f97a,$8a65c9ec,$14015c4f,$63066cd9,$fa0f3d63,$8d080df5
	.dc.l	$3b6e20c8,$4c69105e,$d56041e4,$a2677172,$3c03e4d1,$4b04d447,$d20d85fd,$a50ab56b
	.dc.l	$35b5a8fa,$42b2986c,$dbbbc9d6,$acbcf940,$32d86ce3,$45df5c75,$dcd60dcf,$abd13d59
	.dc.l	$26d930ac,$51de003a,$c8d75180,$bfd06116,$21b4f4b5,$56b3c423,$cfba9599,$b8bda50f
	.dc.l	$2802b89e,$5f058808,$c60cd9b2,$b10be924,$2f6f7c87,$58684c11,$c1611dab,$b6662d3d
	.dc.l	$76dc4190,$01db7106,$98d220bc,$efd5102a,$71b18589,$06b6b51f,$9fbfe4a5,$e8b8d433
	.dc.l	$7807c9a2,$0f00f934,$9609a88e,$e10e9818,$7f6a0dbb,$086d3d2d,$91646c97,$e6635c01
	.dc.l	$6b6b51f4,$1c6c6162,$856530d8,$f262004e,$6c0695ed,$1b01a57b,$8208f4c1,$f50fc457
	.dc.l	$65b0d9c6,$12b7e950,$8bbeb8ea,$fcb9887c,$62dd1ddf,$15da2d49,$8cd37cf3,$fbd44c65
	.dc.l	$4db26158,$3ab551ce,$a3bc0074,$d4bb30e2,$4adfa541,$3dd895d7,$a4d1c46d,$d3d6f4fb
	.dc.l	$4369e96a,$346ed9fc,$ad678846,$da60b8d0,$44042d73,$33031de5,$aa0a4c5f,$dd0d7cc9
	.dc.l	$5005713c,$270241aa,$be0b1010,$c90c2086,$5768b525,$206f85b3,$b966d409,$ce61e49f
	.dc.l	$5edef90e,$29d9c998,$b0d09822,$c7d7a8b4,$59b33d17,$2eb40d81,$b7bd5c3b,$c0ba6cad
	.dc.l	$edb88320,$9abfb3b6,$03b6e20c,$74b1d29a,$ead54739,$9dd277af,$04db2615,$73dc1683
	.dc.l	$e3630b12,$94643b84,$0d6d6a3e,$7a6a5aa8,$e40ecf0b,$9309ff9d,$0a00ae27,$7d079eb1
	.dc.l	$f00f9344,$8708a3d2,$1e01f268,$6906c2fe,$f762575d,$806567cb,$196c3671,$6e6b06e7
	.dc.l	$fed41b76,$89d32be0,$10da7a5a,$67dd4acc,$f9b9df6f,$8ebeeff9,$17b7be43,$60b08ed5
	.dc.l	$d6d6a3e8,$a1d1937e,$38d8c2c4,$4fdff252,$d1bb67f1,$a6bc5767,$3fb506dd,$48b2364b
	.dc.l	$d80d2bda,$af0a1b4c,$36034af6,$41047a60,$df60efc3,$a867df55,$316e8eef,$4669be79
	.dc.l	$cb61b38c,$bc66831a,$256fd2a0,$5268e236,$cc0c7795,$bb0b4703,$220216b9,$5505262f
	.dc.l	$c5ba3bbe,$b2bd0b28,$2bb45a92,$5cb36a04,$c2d7ffa7,$b5d0cf31,$2cd99e8b,$5bdeae1d
	.dc.l	$9b64c2b0,$ec63f226,$756aa39c,$026d930a,$9c0906a9,$eb0e363f,$72076785,$05005713
	.dc.l	$95bf4a82,$e2b87a14,$7bb12bae,$0cb61b38,$92d28e9b,$e5d5be0d,$7cdcefb7,$0bdbdf21
	.dc.l	$86d3d2d4,$f1d4e242,$68ddb3f8,$1fda836e,$81be16cd,$f6b9265b,$6fb077e1,$18b74777
	.dc.l	$88085ae6,$ff0f6a70,$66063bca,$11010b5c,$8f659eff,$f862ae69,$616bffd3,$166ccf45
	.dc.l	$a00ae278,$d70dd2ee,$4e048354,$3903b3c2,$a7672661,$d06016f7,$4969474d,$3e6e77db
	.dc.l	$aed16a4a,$d9d65adc,$40df0b66,$37d83bf0,$a9bcae53,$debb9ec5,$47b2cf7f,$30b5ffe9
	.dc.l	$bdbdf21c,$cabac28a,$53b39330,$24b4a3a6,$bad03605,$cdd70693,$54de5729,$23d967bf
	.dc.l	$b3667a2e,$c4614ab8,$5d681b02,$2a6f2b94,$b40bbe37,$c30c8ea1,$5a05df1b,$2d02ef8d


;--------------------------------------------------------------------------------
;print decimal number
;<d0.l:number
	.text
	.even
print_dec:
	movem.l	d0-d2/a0-a1,-(sp)
	lea.l	-12(sp),sp
	movea.l	sp,a0
	tst.l	d0
	bne	1f
	move.b	#'0',(a0)+
	bra	5f
1:
	lea.l	base_ten(pc),a1
2:
	move.l	(a1)+,d1
	cmp.l	d1,d0
	blo	2b
3:
	moveq.l	#'0'-1,d2
4:
	addq.b	#1,d2
	sub.l	d1,d0
	bcc	4b
	add.l	d1,d0
	move.b	d2,(a0)+
	move.l	(a1)+,d1
	bne	3b
5:
	suba.l	sp,a0
	move.l	a0,-(sp)
	pea.l	4(sp)
	move.w	#1,-(sp)
	DOS	_WRITE
	lea.l	10+12(sp),sp
	movem.l	(sp)+,d0-d2/a0-a1
	rts


;--------------------------------------------------------------------------------
;print fixed point decimal number
;<d0.l:fixed point decimal number * 10^d1
;<d1.b:number of digits after decimal point (>=1)
	.text
	.even
print_fix:
	movem.l	d0-d4/a0-a1,-(sp)
	moveq.l	#0,d3
	move.b	d1,d3
;<d3.l:number of digits after decimal point (>=1)
	move.l	d3,d4
	addq.w	#3,d4
	and.w	#-4,d4		;round up to multiples of four
	add.w	#12,d4		;12 bytes for integer part and decimal point
;<d4.l:buffer size
	suba.l	d4,sp
;<sp.l:buffer
	movea.l	sp,a0
	tst.l	d0
	bne	20f
;zero
	move.b	#'0',(a0)+
	move.b	#'.',(a0)+
	move.w	d3,d2		;number of digits after decimal point (>=1)
	bra	12f

11:
	move.b	#'0',(a0)+
12:
	dbra	d2,11b
	bra	80f		;print

;non-zero
20:
	lea.l	base_ten(pc),a1
;zero suppression
21:
	move.l	(a1)+,d1
	cmp.l	d1,d0
	blo	21b
;convert to decimal number
22:
	moveq.l	#'0'-1,d2
23:
	addq.b	#1,d2
	sub.l	d1,d0
	bcc	23b
	add.l	d1,d0
	move.b	d2,(a0)+
	move.l	(a1)+,d1
	bne	22b
;
	move.l	a0,d2
	sub.l	sp,d2
;<d2.l:number of digits
	cmp.w	d3,d2
	bls	40f
;number of digits > number of digits after decimal point
;insert '.'
	move.w	d3,d2		;number of digits after decimal point (>=1)
	movea.l	a0,a1
	addq.l	#1,a0
	bra	32f

31:
	move.b	-(a1),1(a1)
32:
	dbra	d2,31b
	move.b	#'.',(a1)
	bra	80f

40:
;number of digits after decimal point >= number of digits
;insert '0.00...'
	move.w	d3,d0		;number of digits after decimal point (>=1)
	sub.w	d2,d0		;number of zeros after decimal point (>=0)
	movea.l	a0,a1
	lea.l	2(a0,d0.w),a0
	bra	42f

41:
	move.b	-(a1),2(a1,d0.w)
42:
	dbra	d2,41b
	movea.l	sp,a1
	move.b	#'0',(a1)+
	move.b	#'.',(a1)+
	bra	44f

43:
	move.b	#'0',(a1)+
44:
	dbra	d0,43b

;print
80:
	suba.l	sp,a0
	move.l	a0,-(sp)	;length
	pea.l	4(sp)		;buffer
	move.w	#1,-(sp)	;stdout
	DOS	_WRITE
	lea.l	10(sp),sp
	adda.l	d4,sp
	movem.l	(sp)+,d0-d4/a0-a1
	rts

	.align	4
base_ten:
	.dc.l	1000000000
	.dc.l	100000000
	.dc.l	10000000
	.dc.l	1000000
	.dc.l	100000
	.dc.l	10000
	.dc.l	1000
	.dc.l	100
	.dc.l	10
	.dc.l	1
	.dc.l	0


;--------------------------------------------------------------------------------
;print hexadecimal number
;<d0.l:number
	.text
	.even
print_hex8:
	movem.l	d0-d2/a0,-(sp)
	lea.l	-10(sp),sp
	movea.l	sp,a0
	move.b	#'$',(a0)+
	moveq.l	#8-1,d2
2:
	rol.l	#4,d0
	moveq.l	#15,d1
	and.w	d0,d1
	move.b	10f(pc,d1.w),(a0)+
	dbra	d2,2b
	pea.l	1+8.w
	pea.l	4(sp)
	move.w	#1,-(sp)
	DOS	_WRITE
	lea.l	10+10(sp),sp
	movem.l	(sp)+,d0-d2/a0
	rts

10:
	.dc.b	'0123456789abcdef'


;--------------------------------------------------------------------------------
;print crlf
	.text
	.even
print_crlf:
	move.l	d0,-(sp)
	pea.l	2.w
	pea.l	10f(pc)
	move.w	#1,-(sp)
	DOS	_WRITE
	lea.l	10(sp),sp
	move.l	(sp)+,d0
	rts

10:
	.dc.b	13,10


;--------------------------------------------------------------------------------
;print character
;<4(sp).w:character
	.text
	.even
putchar_by_write:
	move.l	d0,-(sp)
	pea.l	1.w
	pea.l	12+1(sp)
	move.w	#1,-(sp)
	DOS	_WRITE
	lea.l	10(sp),sp
	move.l	(sp)+,d0
	rts


;--------------------------------------------------------------------------------
;print string
;<4(sp).l:string
	.text
	.even
print_by_write:
	movem.l	d0/a0-a1,-(sp)
	movea.l	16(sp),a1
	movea.l	a1,a0
@@:
	tst.b	(a1)+
	bne	@b
	subq.l	#1,a1
	suba.l	a0,a1
	movem.l	a0-a1,-(sp)
	move.w	#1,-(sp)
	DOS	_WRITE
	lea.l	10(sp),sp
	movem.l	(sp)+,d0/a0-a1
	rts


;--------------------------------------------------------------------------------
;end
	.end	main
1 2