Jump to content
ralphb

xdt99: New TI 99 cross-development tools available

Recommended Posts

Had an idea to help newbies like me.

 

And this may already be possible...

 

One thing that I get stuck with is figuring out how many bytes each instruction uses. ie

					;rotate keys
		ci r3,90		;z key - rotate
		jne $+4
		b @rotl
		
		ci r3,67		;c key - rotate
		jne $+4
		b @rotr


		li r9,0
		bl @collsp

For the small keyscan routine above, to figure out that I needed to jump $+4, I actually loaded up the LBLA & entering each instruction (as the LBLA compiles each line as entered) it told me how many bytes each instruction took.

 

If it was possibly for the xdt tools to take an .asm file, & from a starting AORG actually output how many bytes each instruction took in 2 columns

 

ie

 

7D00 lwpi >70b8

7D04 li r0,>0384

7D08 etc etc
That might be useful for useless people such as myself!
cheers
Daryn

Share this post


Link to post
Share on other sites

 

Had an idea to help newbies like me.

 

And this may already be possible...

 

One thing that I get stuck with is figuring out how many bytes each instruction uses. ie

...

 

Use labels. They're a bit more cryptic with the LBLA than with the E/A module—2 characters as opposed to the 6 allowed with E/A. You then rarely need to know how many bytes instructions take. Your code above would be

 

;rotate keys
ci r3,90 ;z key - rotate
jne kc
b @rotl
kc ci r3,67 ;c key - rotate
jne ex
b @rotr
ex li r9,0
bl @collsp

 

...lee

Edited by Lee Stewart
  • Like 1

Share this post


Link to post
Share on other sites

I'm working on some F18A GPU code and will soon be using the XORG directive. Is there any chance you could add support for the new F18A GPU instructions?

CALL	>0C80	0000 1100 10Ts SSSS	
RET	>0C00	0000 1100 0000 0000	
PUSH	>0D00	0000 1101 00Ts SSSS	
POP	>0F00	0000 1111 00Td DDDD	
SLC	>0E00	0000 1110 SHFT SSSS	

Thanks,

Rasmus

  • Like 1

Share this post


Link to post
Share on other sites

 

Use labels. They're a bit more cryptic with the LBLA than with the E/A module—2 characters as opposed to the 6 allowed with E/A. You then rarely need to know how many bytes instructions take. Your code above would be

 

;rotate keys
ci r3,90 ;z key - rotate
jne kc
b @rotl
kc ci r3,67 ;c key - rotate
jne ex
b @rotr
ex li r9,0
bl @collsp

 

...lee

 

Funny, I use labels everywhere...but did not think of doing this! haha

 

cheers Lee!

 

Daryn

Share this post


Link to post
Share on other sites

 

Funny, I use labels everywhere...but did not think of doing this! haha

 

cheers Lee!

 

Daryn

 

Just remember that jump instructions do not use ‘@’ as do branch instructions. I still, occasionally, trip on that one.

 

...lee

Share this post


Link to post
Share on other sites

One thing that I get stuck with is figuring out how many bytes each instruction uses.

 

Sorry for the late reply, Daryn, but I've just returned from my vacation (nice to be offline for a while!).

 

There really isn't anything to add to Lee's reply, except for two minor points.

 

As you know, labels must be unique within each program so that references, e.g., in jump and branch instructions, can be resolved unambiguously. If you have many code sequences that correspond to IF or WHILE blocks you'll have to introduce a lot of unique labels.

.

;rotate keys
          ci r3,90        ;z key - rotate
          jne nextkey1
          b @rotl

nextkey1  ci r3,67        ;c key - rotate
          jne nextkey2
          b @rotr

nextkey2  li r9,0
          bl @collsp

.

These labels are not meant to be called from outside your current subroutine, and coming up with unique names can get difficult as your program grows. Just imagine that you want to test another key before the C key -- then you'd have to add a "nextkey3" label, but before the "nextkey2" one, which looks ugly.

 

Mostly for this reason xas99 supports so-called local labels that need not be unique. This sounds weird at first -- where should we jump to if the target is not unique?

.

        ci r3,90        ;z key - rotate
        jne !next
        b @rotl

!next   ci r3,67        ;c key - rotate
        jne !next
        b @rotr

!next   li r9,0
        bl @collsp

.

But the answer is actually quite simple: the assembler will pick the nearest label after the current position. In your example above, each "jne !next" will skip to the next "!next" label. You might even drop the name of the label and use

.

        ci r3,90        ;z key - rotate
        jne !
        b @rotl

!       ci r3,67        ;c key - rotate
        jne !
        b @rotr

!       li r9,0
        bl @collsp

.

for maximum brevity (and IMHO legibility). The "!..." will always search forward. If you want to jump backwards you simple prefix the local label reference with a unary minus, e.g.,

.

   li   r0, >a000
   li   r1, 128
!  clr  *r0+
   dect r1
   jne  -!         ; jump back
   rt

.

And you can use "!!..." (and "-!!...") to jump to the label after the next label (the label before the previous label), although I personally rarely use this.

 

Keep in mind, though, that local labels are unique to xas99; the original TI assembler won't know about them.

 

Finally, if you ever really need to find out the size (or timings) of instructions, you can have a look at the listing file, generated with the -L option:

.

XAS99 CROSS-ASSEMBLER   VERSION 1.5.1
...
0001               checkkeys
0002 0000 0283  22         ci r3,90        ;z key - rotate
     0002 005A 
0003 0004 1602  14         jne !
0004 0006 0460  28         b @rotl
     0008 001Cr
0005               
0006 000A 0283  22 !       ci r3,67        ;c key - rotate
     000C 0043 
0007 000E 1602  14         jne !
0008 0010 0460  28         b @rotr
     0012 001Er
0009               
0010 0014 0209  20 !       li r9,0
     0016 0000 
0011 0018 06A0  32         bl @collsp
     001A 0020r
...

.

The second column contains the (relative or absolute) address of the instruction.

  • Like 3

Share this post


Link to post
Share on other sites

 

Sorry for the late reply, Daryn, but I've just returned from my vacation (nice to be offline for a while!).

 

There really isn't anything to add to Lee's reply, except for two minor points.

 

As you know, labels must be unique within each program so that references, e.g., in jump and branch instructions, can be resolved unambiguously. If you have many code sequences that correspond to IF or WHILE blocks you'll have to introduce a lot of unique labels.

.

;rotate keys
          ci r3,90        ;z key - rotate
          jne nextkey1
          b @rotl

nextkey1  ci r3,67        ;c key - rotate
          jne nextkey2
          b @rotr

nextkey2  li r9,0
          bl @collsp

.

These labels are not meant to be called from outside your current subroutine, and coming up with unique names can get difficult as your program grows. Just imagine that you want to test another key before the C key -- then you'd have to add a "nextkey3" label, but before the "nextkey2" one, which looks ugly.

 

Mostly for this reason xas99 supports so-called local labels that need not be unique. This sounds weird at first -- where should we jump to if the target is not unique?

.

        ci r3,90        ;z key - rotate
        jne !next
        b @rotl

!next   ci r3,67        ;c key - rotate
        jne !next
        b @rotr

!next   li r9,0
        bl @collsp

.

But the answer is actually quite simple: the assembler will pick the nearest label after the current position. In your example above, each "jne !next" will skip to the next "!next" label. You might even drop the name of the label and use

.

        ci r3,90        ;z key - rotate
        jne !
        b @rotl

!       ci r3,67        ;c key - rotate
        jne !
        b @rotr

!       li r9,0
        bl @collsp

.

for maximum brevity (and IMHO legibility). The "!..." will always search forward. If you want to jump backwards you simple prefix the local label reference with a unary minus, e.g.,

.

   li   r0, >a000
   li   r1, 128
!  clr  *r0+
   dect r1
   jne  -!         ; jump back
   rt

.

And you can use "!!..." (and "-!!...") to jump to the label after the next label (the label before the previous label), although I personally rarely use this.

 

Keep in mind, though, that local labels are unique to xas99; the original TI assembler won't know about them.

 

Finally, if you ever really need to find out the size (or timings) of instructions, you can have a look at the listing file, generated with the -L option:

.

XAS99 CROSS-ASSEMBLER   VERSION 1.5.1
...
0001               checkkeys
0002 0000 0283  22         ci r3,90        ;z key - rotate
     0002 005A 
0003 0004 1602  14         jne !
0004 0006 0460  28         b @rotl
     0008 001Cr
0005               
0006 000A 0283  22 !       ci r3,67        ;c key - rotate
     000C 0043 
0007 000E 1602  14         jne !
0008 0010 0460  28         b @rotr
     0012 001Er
0009               
0010 0014 0209  20 !       li r9,0
     0016 0000 
0011 0018 06A0  32         bl @collsp
     001A 0020r
...

.

The second column contains the (relative or absolute) address of the instruction.

 

 

Thanks so much for this info ralphb, will try the local labels out for sure! Fantastic set of tools!

Share this post


Link to post
Share on other sites

I'm working on some F18A GPU code and will soon be using the XORG directive. Is there any chance you could add support for the new F18A GPU instructions?

 

Sure! I've added all of the above, plus PIX as an alias for XOP. I guess the SPI instructions aren't needed for regular programming? Just grab the latest version directly from GitHub.

 

The IDEA plugin still needs to be updated, though. I noticed that a new IDEA platform version has been released, so I need to figure out any changes first. Are you staying put on IDEA 13, or do you plan to switch to their new subscription model?

  • Like 2

Share this post


Link to post
Share on other sites

 

Sure! I've added all of the above, plus PIX as an alias for XOP. I guess the SPI instructions aren't needed for regular programming? Just grab the latest version directly from GitHub.

 

The IDEA plugin still needs to be updated, though. I noticed that a new IDEA platform version has been released, so I need to figure out any changes first. Are you staying put on IDEA 13, or do you plan to switch to their new subscription model?

 

Thank you, that's great.

 

I will probably get a licence for IDEA 15 from my workplace.

 

I think I just found an issue. This program:

WIDTH   EQU >100
HEIGHT  EQU >C0
        LI  R2,WIDTH*HEIGHT/4

produces this output:

XAS99 CROSS-ASSEMBLER   VERSION 1.5.2
**** **** ****     > problem.a99
0001      0100     WIDTH   EQU >100
0002      00C0     HEIGHT  EQU >C0
0003 0000 0202  20         LI  R2,WIDTH*HEIGHT/4
     0002 F000 

but the result of the calculation should be >3000 instead of >F000.

problem.a99

Share this post


Link to post
Share on other sites

Here is another issue, this time with XORG. If I try to assemble the code below I get an error that the JMP instruction is far out of range: ***** Out of range: LOOP +/- -0x3803

       AORG >A000
       B    @LOOP
XCODE  XORG >3000
LOOP   JMP  LOOP
       END

(This is just an example that wouldn't work with without a loop to copy the XCODE to >3000).

Share this post


Link to post
Share on other sites

 

Thank you, that's great.

 

I will probably get a licence for IDEA 15 from my workplace.

 

I think I just found an issue. This program:

WIDTH   EQU >100
HEIGHT  EQU >C0
        LI  R2,WIDTH*HEIGHT/4

produces this output:

XAS99 CROSS-ASSEMBLER   VERSION 1.5.2
**** **** ****     > problem.a99
0001      0100     WIDTH   EQU >100
0002      00C0     HEIGHT  EQU >C0
0003 0000 0202  20         LI  R2,WIDTH*HEIGHT/4
     0002 F000 

but the result of the calculation should be >3000 instead of >F000.

 

 

>F000 is, in fact, correct. That is what the E/A cartridge Assembler will give you. According to the E/A Manual, the “well-defined” expression in the EQU directive uses signed, integer division as opposed to the unsigned, integer division of the TMS9900's DIV instruction, which would result in the >3000 you expected. Asm994a gives >3000 for that same expression, which is in error per the E/A Manual. The E/A Manual does have a handful of errors; but, I doubt this is one of them.

 

...lee

Share this post


Link to post
Share on other sites

 

 

>F000 is, in fact, correct. That is what the E/A cartridge Assembler will give you. According to the E/A Manual, the “well-defined” expression in the EQU directive uses signed, integer division as opposed to the unsigned, integer division of the TMS9900's DIV instruction, which would result in the >3000 you expected. Asm994a gives >3000 for that same expression, which is in error per the E/A Manual. The E/A Manual does have a handful of errors; but, I doubt this is one of them.

 

...lee

 

 

OK, thanks, so it's another backwards compatibility issue. I think it would be more useful if any rounding was postponed until the end, or at least it should give a warning at the point where the result of the multiplication of two unsigned numbers is being treated as a signed number.

Share this post


Link to post
Share on other sites

How about a / for signed division, and a \ for unsigned division? Why you would want signed division in an assembler is beyond me, but I suppose we should stay with the TI standard. \ as unsigned seems more useful to me, however.

Share this post


Link to post
Share on other sites

Why you would want signed division in an assembler is beyond me

 

 

I could imagine you might want to find the difference of two memory location, and as soon as you assume negative values, you have to do signed arithmetics.

Share this post


Link to post
Share on other sites

Here is another issue, this time with XORG. If I try to assemble the code below I get an error that the JMP instruction is far out of range: ***** Out of range: LOOP +/- -0x3803

 

Doh! That was caused by a typo: In one case I accidentally wrote self.symbols.xorgLOffset instead of self.symbols.xorgOffset! Well, that's what you get when giving up statically typed languages in favor of Python ... :)

 

It's fixed on GitHub now. (And note to self: Test the basic stuff as well. :grin:)

Share this post


Link to post
Share on other sites

I could imagine you might want to find the difference of two memory location, and as soon as you assume negative values, you have to do signed arithmetics.

 

I concur. I guess what's missing here are shift operators. xas99 already supports &, |, and ^, but << and >> will require some fiddeling, as > is already used as hex indicator.

 

And yes, backwards compatibility can be a pain ... I particularly dislike that 1 + 2 * 3 yields 9, and I have to find a "modern" solution to that yet.

Share this post


Link to post
Share on other sites

 

I concur. I guess what's missing here are shift operators. xas99 already supports &, |, and ^, but << and >> will require some fiddeling, as > is already used as hex indicator.

 

And yes, backwards compatibility can be a pain ... I particularly dislike that 1 + 2 * 3 yields 9, and I have to find a "modern" solution to that yet.

 

Perhaps you could switch to 32-bit arithmetic when brackets are used, which means it does not have to be backwards compatible? Then (>100*>C0) would not be treated as a negative number and (>100*>C0)/4 would return the expected result of >3000.

 

Edit: This would also prevent that (>100/4)*>C0 yields a different result than (>100*>C0)/4.

Share this post


Link to post
Share on other sites

 

Perhaps you could switch to 32-bit arithmetic when brackets are used, which means it does not have to be backwards compatible? Then (>100*>C0) would not be treated as a negative number and (>100*>C0)/4 would return the expected result of >3000.

 

I would think it best to avoid using () to bracket calculations because of their use in addressing—perhaps [] or {} would be better.

 

...lee

Share this post


Link to post
Share on other sites

 

Doh! That was caused by a typo: In one case I accidentally wrote self.symbols.xorgLOffset instead of self.symbols.xorgOffset! Well, that's what you get when giving up statically typed languages in favor of Python ... :)

 

It's fixed on GitHub now. (And note to self: Test the basic stuff as well. :grin:)

 

Thanks. XORG, SLC, PIX all working fine.

Share this post


Link to post
Share on other sites

Is there any way to cancel XORG and return to use the previous AORG?

 

Sure, just use "AORG" without argument. IIRC this also works with the TI assembler when switching between RORG and AORG.

  • Like 2

Share this post


Link to post
Share on other sites

Sorry, me again. I have switched to IDEA 15. but I'm still getting errors:

null
java.lang.NullPointerException
	at net.endlos.xdt99.xas99.Xas99Reference.findBeginningOfLine(Xas99Reference.java:78)
	at net.endlos.xdt99.xas99.Xas99Reference.<init>(Xas99Reference.java:27)
	at net.endlos.xdt99.xas99.psi.impl.Xas99PsiImplUtil.getReference(Xas99PsiImplUtil.java:79)
	at net.endlos.xdt99.xas99.psi.impl.Xas99OpLabelImpl.getReference(Xas99OpLabelImpl.java:40)
	at com.intellij.psi.impl.SharedPsiElementImplUtil.getReferences(SharedPsiElementImplUtil.java:83)
	at com.intellij.psi.impl.PsiElementBase.getReferences(PsiElementBase.java:82)
	at org.intellij.plugins.intelliLang.references.InjectedReferencesContributor.getInjectedReferences(InjectedReferencesContributor.java:56)
	at org.intellij.plugins.intelliLang.references.InjectedReferencesInspection$1.visitElement(InjectedReferencesInspection.java:38)
	at com.intellij.psi.impl.PsiElementBase.accept(PsiElementBase.java:274)
	at net.endlos.xdt99.xas99.psi.impl.Xas99OpLabelImpl.accept(Xas99OpLabelImpl.java:23)
	at com.intellij.codeInspection.InspectionEngine.acceptElements(InspectionEngine.java:81)
	at com.intellij.codeInsight.daemon.impl.LocalInspectionsPass$4.process(LocalInspectionsPass.java:320)
	at com.intellij.codeInsight.daemon.impl.LocalInspectionsPass$4.process(LocalInspectionsPass.java:315)
	at com.intellij.concurrency.ApplierCompleter.a(ApplierCompleter.java:122)
	at com.intellij.concurrency.ApplierCompleter.access$000(ApplierCompleter.java:44)
	at com.intellij.concurrency.ApplierCompleter$1.run(ApplierCompleter.java:85)
	at com.intellij.openapi.application.impl.ApplicationImpl.tryRunReadAction(ApplicationImpl.java:1169)
	at com.intellij.concurrency.ApplierCompleter$2.run(ApplierCompleter.java:94)
	at com.intellij.openapi.progress.impl.CoreProgressManager.a(CoreProgressManager.java:446)
	at com.intellij.openapi.progress.impl.CoreProgressManager.a(CoreProgressManager.java:443)
	at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:392)
	at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:54)
	at com.intellij.concurrency.ApplierCompleter.a(ApplierCompleter.java:106)
	at com.intellij.concurrency.ApplierCompleter.compute(ApplierCompleter.java:82)
	at jsr166e.CountedCompleter.exec(CountedCompleter.java:684)
	at jsr166e.ForkJoinTask.doExec(ForkJoinTask.java:260)
	at jsr166e.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:858)
	at jsr166e.ForkJoinPool.scan(ForkJoinPool.java:1687)
	at jsr166e.ForkJoinPool.runWorker(ForkJoinPool.java:1642)
	at jsr166e.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:108)

Source code attached.

f18a-isometric-xas99.a99

Share this post


Link to post
Share on other sites

I've just released version 1.5.1, which contains an updated IDEA plugin that supports IDEA 15, adds a code formatter, and fixes some bugs, including the one above.

 

Code Reformat will do exactly that, based on your preferences in Settings > Editor > Code Style. This is handy when you copy and paste code from other sources, or if you want to cover up your sloppiness. For technical reasons you may have to reformat twice in a row to get comments align properly -- don't ask. And I suspect a bug in the IntelliJ platform that results in incorrect indenting if the very first line of the file does not start in column 1; let's see where that bug report goes.

  • Like 3

Share this post


Link to post
Share on other sites

Why does xga99 gpl compiler implement the SLL, SRC etc... (shift bit wise instructions) in reverse order to that specified in the gpl_programmers_guide.pdf ?

It took me some time to realise why it was throwing an exception.

 

According to PDF Shift Right Circular = SRC GD,GS

but XGA99 needs this instruction as SRC GS,GD

 

Thanks

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...