140 lines
2.9 KiB
ArmAsm
140 lines
2.9 KiB
ArmAsm
.define .cii
|
|
|
|
! 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
|
|
|
|
|
|
|
|
.define .cuu
|
|
|
|
! 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
|