Jump to content

Photo

xdt99: New TI 99 cross-development tools available


269 replies to this topic

#251 ralphb OFFLINE  

ralphb

    Dragonstomper

  • Topic Starter
  • 657 posts
  • Location:Germany

Posted Thu Mar 7, 2019 12:27 PM

I've just updated xas99.py on GitHub.  Embarrassingly, there aren't really any brand new features, but most work was done to consolidate two diverged branches of xas99 on two different machines. 

 

Anyway, I already mentioned # for cross-bank access.  The # goes after the label in the different bank, so you'd write

.

B @FARAWAY#(R1)
B @NOTHERE# + OFFSET

.

Yes, I could think of worse address expressions and I'm not sure # will work in those cases.  :)   But I had no time for "relocatable" all over again.  ;)

 

Second, instead of AORG >6000, 1, write

.

AORG >6000
BANK 1

.

and 

.

BANK ALL

.

for a shared code segment.  In the old notation, which still works, you'd have to keep up with addresses if you wanted to change to a bank after a shared segment.

 

Third, the -t option now has an argument which consist of a, b or c to generate "DATA" expressions for assembly, BASIC, or C, and 2 or 4 for BYTE or DATA, resp.

.

$ xas99.py -t a4 someprg.a99
->
  DATA >1234, >5678, >ABCD, >1234
  DATA >4567

$ xas99.py -t c2 someprg.99
->
  0x12, 0x34, 0x56, 0x78,
  0xab, 0xcd, 0x12, 0x34,
  ...

.

:arrow:  I use this for example to include my SDD99 assembly DSR into the C kernel.  But I'm sure there are already tons of tools to do this.

 

Fourth, I reverted a new parser I had built that would not be so strict about whitespace.  The downside was that it couldn't assemble old-style files with "flying comments" any more.  A few months back it still seemed like a good idea, but now I thought it's a solution to a problem no one really has.  :P

 

EDIT: Oops, I forgot Five, xas99 will now check if B statements could be replaced by a JMP, and will issue a warning if so.

 

I think I will spend more time on xdt99, in fact, I already have some improvements for xda99 and xdg99, and a large todo list.  :)


Edited by ralphb, Thu Mar 7, 2019 12:47 PM.


#252 Asmusr OFFLINE  

Asmusr

    River Patroller

  • 3,144 posts
  • Location:Denmark

Posted Thu Mar 7, 2019 2:12 PM

Excellent. I'm already up and running with the new features. I now have 36 bytes more scratchpad available because I could move my trampoline code to the shared ROM segment.

 

If you make more improvements, please also consider my old suggestion to automatically optimize @field(rx) to *rx if field equ 0.



#253 Tursi OFFLINE  

Tursi

    Quadrunner

  • 5,664 posts
  • HarmlessLion
  • Location:BUR

Posted Thu Mar 7, 2019 11:26 PM

If you make more improvements, please also consider my old suggestion to automatically optimize @field(rx) to *rx if field equ 0.


If you do that, please make it an option that must be explicitly turned on.

@field(rx) adds a two byte absolute value into the output assembly code - I've used it in the past for padding and for self-modifying code. An assembler that automatically changes the assembly code you write violates the Principle of Least Surprise. ;)

#254 Asmusr OFFLINE  

Asmusr

    River Patroller

  • 3,144 posts
  • Location:Denmark

Posted Fri Mar 8, 2019 12:20 AM

Having an optimize flag sounds good to me. It could also replace those b instructions with jmp automatically instead of producing a warning.



#255 ralphb OFFLINE  

ralphb

    Dragonstomper

  • Topic Starter
  • 657 posts
  • Location:Germany

Posted Sun Mar 10, 2019 3:24 AM

I had to do another update, because my displacement computation in the B/JMP warning was wrong by a factor of 2.  :ponder:   For a while, I was frightened that my JMP displacement computation was also wrong, but it wasn't.  This is as far as JMP can jump:

.

      jmp l1
      bss 254
l1    nop
      bss 252
      jmp l1

.

It just looks weird, since the backwards displacement can be -128, but the forward displacement can only be 127.  But the displacement is applied to LC + 2, so it actually becomes -127 to 128.  And the displacement is for words, not bytes, hence the address delta is -254 to 256.

 

Besides, I also added warnings for @0(Rn) and missing R's when assembling with -R.  There's also a new '-w' option to disable warnings.

 

I still have to do the optimization -O at some point.  In general I'd prefer that people fix their code themselves, but in the case of Rasmus' @0(Rn) I understand that it cannot be fixed manually.  (Although, have you tried using macros for that?  :idea:   A bit ugly though.)

 

EDIT: Layout


Edited by ralphb, Sun Mar 10, 2019 3:25 AM.


#256 mizapf OFFLINE  

mizapf

    River Patroller

  • 3,665 posts
  • Location:Germany

Posted Sun Mar 10, 2019 7:30 AM

I learned that in the MIPS architecture, the branch offset is calculated from the instruction following the branch instruction, that is pretty much the same as with the TMS architecture. The reason seems to be that the program counter has already advanced after getting the instruction.

 

Accordingly, the NOP pseudo-instruction is >1000 (JMP $+2).



#257 FarmerPotato OFFLINE  

FarmerPotato

    Moonsweeper

  • 354 posts
  • Location:Austin, TX

Posted Sun Mar 17, 2019 1:26 PM

Feature request: issue a warning for this syntax:

ci   r1,r2

I know it's legal, but the 'r' indicates the real intention.

 

my bug was introduced when I rewrote a CI, putting the constant in R2.

 

; random number bits, modulo 20
    andi r1,>3f       
    li   r2,>14
mod0:
    ci   r1,r2
    jl   mod1
    s    r2,r1        ; 64 modulo 20 makes the first 4 more likely
    jmp  mod0
mod1:

Edited by FarmerPotato, Sun Mar 17, 2019 1:27 PM.


#258 ralphb OFFLINE  

ralphb

    Dragonstomper

  • Topic Starter
  • 657 posts
  • Location:Germany

Posted Sun Mar 17, 2019 2:09 PM

 

Feature request: issue a warning for this syntax:

ci   r1,r2

 

Yes, I like that, we should also cover this combination.

 

The reason you can do all this dates back to the original E/A, where R0 ... R15 were just pre-defined EQU's with values 0 ... 15.  xas99 kept that handy short-cut, but of course we can issue warnings during parsing of a register when we find no 'R'.

 

This way around might be slightly more complicated/ugly to implement, but I'll get going.



#259 ralphb OFFLINE  

ralphb

    Dragonstomper

  • Topic Starter
  • 657 posts
  • Location:Germany

Posted Wed Apr 3, 2019 10:59 AM

There's a new xas99 version on GitHub.

 

I added two(?) new warnings, so we have these warnings now:

.

 val  equ 0 
      mov  r0, >000a     ; Treating as register, did you intent an @address?
      ci   r1, r2        ; Register used as immediate operand
      b    @lab          ; Possible B/JMP optimization
      data 0
 lab  mov  @val(r1), r2  ; Using indexed address @0, could use *Rn instead
 cons data 1             ; Unreferenced symbol (summary at end of assembly)

.

Then there are new things called modifiers that attach to symbols, literals, or registers.

 

Prepending an integer literal with w# or b# will automatically create a constants at the end of the code.

.

 cb   @>8375, b#42                  cb   @>8375, @b_42
 xor  w#>1fff, r0     vs            xor  @h_1fff, r0
                             b_42   byte 42
                             h_1fff data >1fff

.

The advantage is that you won't get stale constants that are actually no longer used (although there's a warning now), you won't accidentally create constants for both 48 and >30, and you have to write less.  Note, however, that your program will be just as large as without modifiers; it's just syntactic convenience.

 

The l# modifier (that's an "ell") yields the address of the LSB of the modified register.  It does honor the current workspace pointer.

.

 movb l#r0, @vdpwa
 movb r0, @vdpwa

.

No more tedious computation of the correct address, SWPB'ing, or helper symbols like r1lsb that lose their validity when the workspace changes.

 

And as last modifier, x# is now the new valid cross-bank check tag (sorry Rasmus!).  :)



#260 PeteE OFFLINE  

PeteE

    Chopper Commander

  • 228 posts
  • Location:Beaverton, OR

Posted Wed Apr 3, 2019 11:16 AM

Ralph, this is wonderful!  I have only one suggestion: Don't warn about "Register used as immediate operand" for shift instructions that use R0 as the shift amount.  I prefer writing R0 as a reminder that R0 will be used.



#261 ralphb OFFLINE  

ralphb

    Dragonstomper

  • Topic Starter
  • 657 posts
  • Location:Germany

Posted Wed Apr 3, 2019 11:21 AM

Heh, that's clever!  :thumbsup:   It's some pretty special exception to the rule, though, but I think I can get this case covered.



#262 Tursi OFFLINE  

Tursi

    Quadrunner

  • 5,664 posts
  • HarmlessLion
  • Location:BUR

Posted Thu Apr 4, 2019 12:44 PM

Prepending an integer literal with w# or b# will automatically create a constants at the end of the code.


Oh, that's interesting. :)

#263 Lee Stewart OFFLINE  

Lee Stewart

    River Patroller

  • 3,989 posts
  • Location:Silver Run, Maryland

Posted Thu Apr 4, 2019 1:14 PM

I may need to finally bite the bullet and convert my 4-bank fbForth 2.0 code for assembly by xas99 instead of the asm994a I have been using.  I am pretty proud of the method I use to calculate target addresses for blocks of code that get moved, but I should not need to use it in xas99.  XORG should make it much easier to read and I do like your last enhancement with modifiers.  Of course, as has been said many times before, xas99 has the added benefit of current support.

 

...lee



#264 ralphb OFFLINE  

ralphb

    Dragonstomper

  • Topic Starter
  • 657 posts
  • Location:Germany

Posted Mon Apr 15, 2019 5:23 AM

I have a feature request.  It would be really great if labels could be preceded with an arbitrary amount of white space instead of having to be smack against the left.  I would really like to be able to indent my assembly code for better readability.

 

I realize this breaks E/A compatibility, so maybe having to set a flag to use the option would be required.  I also realize that a prefix token might be required for the label to make it possible to detect an indented label vs code.  I'm okay with that.  Maybe a line where the first non-white-space character is a semicolon means a label follows... or something like that.

 

Matt, I have not forgotten about this request.  But to be honest, I'm not 100 percent excited about it.  :)

 

Would it work for you, as some sort of compromise, to keep the labels flush to the left, but indent the instructions to the right?  Similar effect, but more conventional parsing.



#265 matthew180 OFFLINE  

matthew180

    River Patroller

  • 2,629 posts
  • Location:Castaic, California

Posted Mon Apr 15, 2019 10:25 PM

That's okay, I did not even think you noticed the request. ;-)

 

I went ahead and made the modification myself back in April 2017, here is the diff:

$ git diff xas99.py
diff --git a/xas99.py b/xas99.py
index 2219331..cc597cf 100755
--- a/xas99.py
+++ b/xas99.py
@@ -1405,6 +1405,15 @@ class Parser:
             label = label[:6]
             operands = re.split(",", optext) if optext else []
         else:
+            # If a line starts with a colon and is not the only character on a line,
+            # remove the white-space and the colon, then proceed as normal.  Otherwise
+            # leave the line as-is.
+            strip = line.lstrip()
+            off = len(line) - len(strip)
+
+            if (len(strip) > 1 and line[off] == ':') or line[off] == '{' or line[off] == '}' :
+                line = strip[1:]
+
             # comment field separated by two blanks
             parts = self.escape(line).split(";")
             fields = re.split("\s+", parts[0], maxsplit=2)

That would be against V1.6.0 according to the comment at the top of the file.  I have not really done any assembly programming since then, so I can't tell you how well I liked the change.  Apparently I used a line starting with a colon to be able to indent instructions as I wanted, as well as support for curly-braces.

 

Over the years I have given a lot of thought to assembly, and to me a lot of the problem with writing clear code is the same problem line-number BASIC has, i.e. there is no indentation or visual structure.  I started experimenting with various ways of writing assembly to help readability.

 

There is a lot that can be done for assembly with some basic preprocessing, and a lot of ideas have already been expressed here.  Structures could be implemented, number conversions, simple block-constructs that allow jumps to be auto created, i.e. to make it easy to write IF-THEN-ELSE, loops, etc. without having to come up with unique labels all over the place, local labels in functions, etc.

 

I don't much like languages that force syntax on the programmer (Python comes to mind (no offense intended)), and I'm not a fan of the fixed format of TI's assembler.  I realize back in the day it was necessary to make writing the assembler easier, but these days, if a feature makes using the software nicer for someone, and it is not a big deal to implement, why would you not just add it?

 

In my case it is no big deal, I just made a quick hack, and I'm not even sure I would have continued using the format (it was to quick of a hack, and I would really like to have real indentation allowed and the auto-block constructs (which is what I was trying to hack in with the curly-braces)).

 

I realize you probably need to support the original TI format so your tools are usable against legacy code, and I agree that is very important.  But, adding a ton of preprocessing can allow the tool to have really nice features.  To do both, and keep things manageable, maybe consider parsing each line multiple times, from the most strict to the least strict, until you get a match or error out.  For example, parse the line with TI's rules, and if it passes, then you are done, go to the next line.  If not, parse with the next set of new rules and see if that matches, and so on.

 

Anyway, just some thoughts.

 

Matthew



#266 ralphb OFFLINE  

ralphb

    Dragonstomper

  • Topic Starter
  • 657 posts
  • Location:Germany

Posted Tue Apr 23, 2019 12:48 PM

Another update for xas99 fixes bugs from my own list and some public ones on GitHub.  Also, auto-generated constants now allow for letters, like

   cb  r0, b#E   ; compares to 'E'

I'll add a few constants like 'enter', 'erase' etc. later.

 

For xga99, I now have functional feature parity with xas99.  In particular, xga99 now supports local labels and text generation.  Modifiers make no sense for xga99, since GPL supports immediate values in almost all operand positions, and there is no LSB of a register.  Cross-GROM access is also not a problem.

 

And finally, I did fixes and feature requests for xdm99.  No big changes, but you can now rename a disk with -n, and also specify a target directory with -o.



#267 ralphb OFFLINE  

ralphb

    Dragonstomper

  • Topic Starter
  • 657 posts
  • Location:Germany

Posted Wed May 8, 2019 12:39 PM

An update for xas99, xga99, xda99, and xdg99.

 

For xas99, there is now a size modifier s# that denotes the "size" of the symbol attached to, where size is the distance from the symbol to the syntactically subsequent symbol. Padding bytes are observed.

 

xga99 now has even more similarity to xas99, but for that I needed to rename the syntax option -s to -y.  Please don't hate me.

 

And xda99 and xdg99 have now options to format the disassembly, which by default is now lower-case.  There's also a -k option to skip bytes of the disassemblee.



#268 Asmusr OFFLINE  

Asmusr

    River Patroller

  • 3,144 posts
  • Location:Denmark

Posted Wed May 15, 2019 10:19 AM

An update for xas99, xga99, xda99, and xdg99.

 

For xas99, there is now a size modifier s# that denotes the "size" of the symbol attached to, where size is the distance from the symbol to the syntactically subsequent symbol. Padding bytes are observed.

 

xga99 now has even more similarity to xas99, but for that I needed to rename the syntax option -s to -y.  Please don't hate me.

 

And xda99 and xdg99 have now options to format the disassembly, which by default is now lower-case.  There's also a -k option to skip bytes of the disassemblee.

 

Could you provide an example of how to use the size modifier?



#269 PeteE OFFLINE  

PeteE

    Chopper Commander

  • 228 posts
  • Location:Beaverton, OR

Posted Wed May 15, 2019 11:15 AM

 

Could you provide an example of how to use the size modifier?

Please have a look at the amusingly-named file here.


Edited by PeteE, Wed May 15, 2019 11:16 AM.


#270 ralphb OFFLINE  

ralphb

    Dragonstomper

  • Topic Starter
  • 657 posts
  • Location:Germany

Posted Wed May 15, 2019 1:20 PM

Please have a look at the amusingly-named file here.

 

Indeed.  :)

 

The value of s#X is the difference of X and Y, where Y is the next label following X.  So this works for

.

greet:
   text 'HELLO!'
byebye:
   text 'GOOD BYE'
textend

.

where s#greet is @byebye - @greet and s#byebye is @textend - @byebye.  If textend were missing, s#byebye would not yield the correct result, or throw an error.  Also note that the number of statements/directives following the start label is irrelevant:

.

aa:
   data 1
   byte 1, 1
   text 'XX'
bb:
   text '....'

.

In this example, s#aa yields 6. There's one special case for an odd number of bytes:

.

greet:
   text 'HELLO'
weight:
   data 69

.

Here, the difference between weight and greet is 6 bytes, because weight is even-aligned.  xas99 keeps track of this, so in this case s#greet actually yields 5.  Again, this applies to all kind of statements, not just TEXT.  s# will not include the padding byte.

 

When using s#, you need to make sure that there's a label after the thing you want to size.  In general, this happens naturally, with the possible exception of the last element in a source file.






0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users