I don't know how relevant this is these days since everyone seems to be using the TI-83 series (such as the 83+/84+) or TI-9x series now, but I wrote a short program to test the exact behavior of the IM 2 (interrupt mode 2) on the TI-86. Specifically what I wanted to know was what the TI-86 supplied for the lower 8 bits of the vector table address (where the I register supplies the upper 8 bits) when an interrupt occurs. I've seen claims that it could be *anything*. Most (if not all) Z80 TI-8x emulators I've used just supply a value of 0 for the lower 8 bits.
So what I did was I wrote a simple program that iteratively adjusted the vector table and gathered interrupt statistics for each adjustment. Basically, for each byte in the vector table, the program changes it so that, if that vector is used, the interrupt would be redirected to another interrupt handler that I supply. Here's a little illustration of the vector table after a few iterations:
Iteration 0: B A A A ... A A
Iteration 1: A B A A ... A A
Iteration 2: A A B A ... A A
Iteration 256: A A A A ... A B
Substitute A and B with real byte values. I used 0xe0 and 0xf0 for A and B, respectively, which results in 3 different interrupt handler addresses: 0xe0e0, 0xe0f0, and 0xf0e0.
After changing a byte, let interrupts run for a while (my program runs for 256 interrupts each time) and then print the number of times each of the three handlers ran.
After about an hour of debugging (and setting up my TI-86 build environment again after probably more than a year of not doing any TI-86 development), here is the code that performs this task:
Code: ; IM2 tester by Christopher Williams
; 2009-10-16
org 0xd748
AA equ 0xe0
BB equ 0xf0
vtable equ 0xdd
_putc equ 0x4a2b
start:
ld bc,256
ld hl,vtable*256
ld (hl),AA
ld de,vtable*256+1
ldir
di
im 2
ld a,vtable
ld i,a
ei
ld bc,-1
ld (bytenum),bc
ld d,vtable
ld e,0
loop:
ld bc,(bytenum)
inc bc
ld (bytenum),bc
push bc
push de
ld a,BB
ld (de),a
ld h,b
ld l,c
call print_hex3
halt
ld a,0
ld hl,0
ld (count_total),hl
ld (count_AAAA),hl
ld (count_AABB),hl
ld (count_BBAA),hl
loop2:
halt
dec a
jr nz,loop2
di
ld a,AA
ld (de),a
; print results
ld hl,(count_total)
call print_hex3
ld hl,(count_AAAA)
call print_hex3
ld hl,(count_AABB)
call print_hex3
ld hl,(count_BBAA)
call print_hex3
ld a,' '
call _putc
ei
pop de
pop bc
inc de
ld a,(bytenum+1)
or a
jr z,loop
di
im 1
ei
ret
print_nibble
and 0x0f ; make sure it's only a nibble
add a,'0'
cp '9'+1
jr c,.printit
add a,'a'-('9'+1)
.printit
jp _putc
print_hex
ld a,h
srl a
srl a
srl a
srl a
push hl
call print_nibble
pop hl
print_hex3
ld a,h
push hl
call print_nibble
pop hl
print_hex2
ld a,l
srl a
srl a
srl a
srl a
push hl
call print_nibble
pop hl
print_hex1
ld a,l
push hl
call print_nibble
pop hl
ld a,' '
jp _putc
common:
ld hl,(count_total)
inc hl
ld (count_total),hl
jp $66 ;jump to normal handler so it can do its things
count_total:
ds 2
count_AAAA:
ds 2
count_AABB
ds 2
count_BBAA
ds 2
bytenum
ds 2
org AA+256*AA
AAAA:
ex af,af'
exx
ld hl,(count_AAAA)
inc hl
ld (count_AAAA),hl
jp common
org BB+256*AA
BBAA:
ex af,af'
exx
ld hl,(count_BBAA)
inc hl
ld (count_BBAA),hl
jp common
org AA+256*BB
AABB:
ex af,af'
exx
ld hl,(count_AABB)
inc hl
ld (count_AABB),hl
jp common
It's not very pretty, and it's not very efficient, etc, etc, but it was a quick and dirty program to get the job done. :)
Here's the results of running this program on a couple emulators (VTI and TilEm):
Code: 000 000 000 100
001 000 100 000
002 100 000 000
003 100 000 000
004 100 000 000
005 100 000 000
... (values for 006 - 0ff are all the same)
100 100 000 000
All values are in hex (hex 100 = decimal 256). The first number is the byte number that is altered, the second is the count of "AA" interrupts, the third is the count of "AB" interrupts, and the fourth is the count of "BA" interrupts. These values indicate that the lower byte of the vector address was always 0 during the first 2 iterations. This was not surprising (I expected it, in fact).
Then I ran it on a real TI-86, and I got identical results. That was a little surprising to me. I partially expected the values to be unexpected. :)
So... what I take this to mean is that I don't actually have to initialize the full 257 byte vector table when I'm using mode 2 interrupts; I only have to set one 16-bit vector at the address I*256. The rest of the memory in the 255 bytes above that can be used for other purposes. This also means that I don't have to use interrupt handlers that start at an address in the form of "0xABAB" (eg, 0xd9d9 or 0xf0f0), since the vector is always taken from a word-aligned value in the vector table.
While this isn't exactly earth-shattering news, I thought I should share it anyway. It can probably be modified to run on the TI-83 series without too much difficulyt if someone wanted to test it on those calcs as well.
Last edited by Guest on 17 Oct 2009 08:48:31 pm; edited 1 time in total |