144 lines
		
	
	
	
		
			3 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			144 lines
		
	
	
	
		
			3 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
.define .cii
 | 
						|
.define .cuu
 | 
						|
.sect .text
 | 
						|
.sect .rom
 | 
						|
.sect .data
 | 
						|
.sect .bss
 | 
						|
.sect .text
 | 
						|
 | 
						|
! cii: convert integer to integer
 | 
						|
! parameters:
 | 
						|
!    stack:   destination size
 | 
						|
!	      source size
 | 
						|
!	      source
 | 
						|
!    stack:   result (out)
 | 
						|
! This code is also used by cuu.
 | 
						|
! The contents of the a-register determines
 | 
						|
! if we're doing a cii (a=0) or a cuu (a=1),
 | 
						|
! so be very careful with this register!
 | 
						|
 | 
						|
 | 
						|
 | 
						|
.cii:
 | 
						|
	pop ix		! return address
 | 
						|
	pop hl		! destination size
 | 
						|
	pop de		! source size
 | 
						|
	ld b,h		! bc := destination size
 | 
						|
	ld c,l
 | 
						|
	xor a		! watch it, this is dirty!
 | 
						|
			! Besides clearing the carry
 | 
						|
			! this instruction sets a-reg.
 | 
						|
			! to 0, to indicate this is
 | 
						|
			! a cii and not a cuu.
 | 
						|
	sbc hl,de	! hl := destination size
 | 
						|
			!  - source size
 | 
						|
	jr z,1f		! equal, return
 | 
						|
	jp p,2f		! larger, expand
 | 
						|
	! smaller, shrink
 | 
						|
	! The most significant part of the source
 | 
						|
	! is removed. As the least sign. part is
 | 
						|
	! on top of the stack, we have to move an
 | 
						|
	! entire data block.
 | 
						|
9:
 | 
						|
	add hl,sp	! note that hl < 0
 | 
						|
			! (also come here via cuu)
 | 
						|
	add hl,de
 | 
						|
	dec hl		! now hl points to most
 | 
						|
			! significant byte of what
 | 
						|
			! will be left over of source
 | 
						|
	ex de,hl
 | 
						|
	add hl,sp
 | 
						|
	ex de,hl
 | 
						|
	dec de		! now de points to highest
 | 
						|
			! byte of source
 | 
						|
	lddr		! move 'destination size'
 | 
						|
			! bytes upwards (i.e. away
 | 
						|
			! from top of stack)
 | 
						|
	inc de
 | 
						|
	ex de,hl
 | 
						|
	ld sp,hl	! adjust stackpointer
 | 
						|
1:
 | 
						|
	jp (ix)		! return
 | 
						|
 | 
						|
2:
 | 
						|
	! larger, expand
 | 
						|
	! A number of bytes (containing the signbits
 | 
						|
	! of the source) is inserted before the most
 | 
						|
	! significant byte of the source.
 | 
						|
	! As this byte is somewhere in the middle of
 | 
						|
	! the stack, the entire source must first be
 | 
						|
	! moved downwards (in the direction of the
 | 
						|
	! top)
 | 
						|
8:
 | 
						|
	ld b,d		! bc := source size
 | 
						|
			! (also come here via cuu)
 | 
						|
	ld c,e
 | 
						|
	ex de,hl	! de := difference (> 0)
 | 
						|
	ld hl,0
 | 
						|
	add hl,sp	! hl := sp
 | 
						|
	push hl
 | 
						|
	or a
 | 
						|
	sbc hl,de
 | 
						|
	ex de,hl	! de := sp - difference
 | 
						|
	pop hl		! hl := sp
 | 
						|
	ex de,hl	! adjust sp
 | 
						|
	ld sp,hl
 | 
						|
	ex de,hl
 | 
						|
	ldir		! move source upwards,
 | 
						|
			! creating a 'hole'
 | 
						|
			! inside the stack
 | 
						|
	! now we will fill the hole with bytes
 | 
						|
	! containing either 0 or -1, depending
 | 
						|
	! on the signbit of the source.
 | 
						|
	or a
 | 
						|
	sbc hl,de
 | 
						|
	ex de,hl	! de := difference
 | 
						|
	dec hl		! now hl points to
 | 
						|
			! most significant byte
 | 
						|
			! of the source
 | 
						|
	or a		! see if we're doing
 | 
						|
			! a 'cii' or a 'cuu'
 | 
						|
	jr nz,3f	! cuu, expand with zeroes
 | 
						|
	bit 7,(hl)	! test signbit
 | 
						|
	jr z,3f
 | 
						|
	dec b		! b := -1 (was 0 after ldir)
 | 
						|
3:
 | 
						|
	inc hl
 | 
						|
	ld (hl),b	! either 0 or -1
 | 
						|
	dec de
 | 
						|
	ld a,d
 | 
						|
	or e
 | 
						|
	jr nz,3b
 | 
						|
	jp (ix)		! return
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
! cuu: convert unsigned to unsigned
 | 
						|
! parameters:
 | 
						|
!    stack:  destination size
 | 
						|
!	     source size
 | 
						|
!	     source
 | 
						|
!    stack:  result (out)
 | 
						|
! The only difference between a cuu and a cii is:
 | 
						|
! if the destination is larger than the source,
 | 
						|
! the former extends with zeroes and the latter
 | 
						|
! extends with sign bits
 | 
						|
! cuu uses the code of cii. In this case it puts
 | 
						|
! a '1' in the accumulator to indicate this is
 | 
						|
! a cuu.
 | 
						|
 | 
						|
 | 
						|
 | 
						|
.cuu:
 | 
						|
	pop ix
 | 
						|
	pop hl
 | 
						|
	pop de
 | 
						|
	ld b,h
 | 
						|
	ld c,l
 | 
						|
	xor a		! clear carry
 | 
						|
	sbc hl,de
 | 
						|
	jr z,1b		! equal, return
 | 
						|
	jp m,9b		! smaller, shrink
 | 
						|
	inc a		! a := 1
 | 
						|
	jr 8b		! larger, expand
 |