6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Fri Nov 22, 2024 6:58 pm

All times are UTC




Post new topic Reply to topic  [ 89 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6  Next
Author Message
PostPosted: Fri May 08, 2020 4:56 am 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 704
Location: North Tejas
BillG wrote:
* enhance the existing 6800 assembler to add features such as conditional assembly directives


I dove headlong into the assembler. Implementing conditional assembly does not initially appear to be very easy.

So to learn the code, I made a few changes to fix some things which have always bothered me about this assembler:

* The assembler does not allow placing a colon after a label. It now allows but does not require it.

* The assembler distinguishes between upper and lower case in symbols. That is now a selectable option.

* The assembler reformats the source code when it generates a listing. It originally printed "ldaa" as "lda a"; it now preserves both forms of the mnemonic as written. I am still investigating making the reformatting a selectable option.


Top
 Profile  
Reply with quote  
PostPosted: Fri May 08, 2020 3:10 pm 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 704
Location: North Tejas
BillG wrote:
I am still investigating making the reformatting a selectable option.


A simple and elegant solution presented itself after I slept on it and came back to look at the problem from outside of the box: format each line of code, or not, in this case, as if the whole thing was a comment.

This is ideal for those of you on the spaces side of the Great Spaces versus TABs Debate. FLEX already provides automagic space compression on disk as sequences of two or more spaces (up to 255) are replaced with two bytes: a tag and a count. You may now make your code listings look exactly like you want.

Despite having this feature, many early FLEX programmers got into the unusual habit of separating fields in their assembly language programs with a single space and relying on the assembler to make listings legible.

Those on the TAB side were left out because the tag byte was, you guessed it, the hard TAB character. FLEX text files cannot contain hard TABs the way the tools were configured. Editors responded to the TAB key by inserting an appropriate number of spaces.


Top
 Profile  
Reply with quote  
PostPosted: Fri May 08, 2020 7:16 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8505
Location: Midwestern USA
Any chance of seeing some screen shots of directory listings, etc?

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Fri May 08, 2020 8:38 pm 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 704
Location: North Tejas
BigDumbDinosaur wrote:
Any chance of seeing some screen shots of directory listings, etc?


Attachment:
FLEX1.png
FLEX1.png [ 25.17 KiB | Viewed 1415 times ]


Attachment:
FLEX2.png
FLEX2.png [ 19.21 KiB | Viewed 1415 times ]


Attachment:
FLEX3.png
FLEX3.png [ 22.47 KiB | Viewed 1415 times ]


Top
 Profile  
Reply with quote  
PostPosted: Sat May 16, 2020 9:13 pm 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 704
Location: North Tejas
I have been known to say that programming a 6502 in assembly language is tedious compared with other processors. However, I just encountered an example in which the 6502 absolutely blows away the 6800.

One of my current projects is to convert the original 6800 FLEX assembler into a cross assembler running on the 6502.

Its symbol table is an array of eight byte entries: two bytes for the value and six for the symbol name. The symbol name is hashed to obtain an index into the array. In case of a collision, the name is rehashed up to a maximum of forty times to try other locations.

At the end of the assembly process, the table is packed and sorted, then the entries are printed in alphabetical order.

A subroutine swaps two entries addressed by the variables I and J, a task which the 6502 does with ease. It has just enough registers to avoid unnecessary memory accesses. I have observed in the past that the 6800 can be severely hampered by having only a single index register and that the 6502 addressing modes are particularly well suited for marching in lockstep through two parallel arrays.

The 6502 version of the subroutine consumes less than half the cycles while also being much smaller.

The 6502 code:

Code:
.1832                     04047 XCHNG
.                         04048 ; LDX I
.1832 A0 07           [2] 04049          ldy    #8-1      ; SET COUNT and index
.                         04050
.1834                     04051 XCHNG1                    ;PSHB ; SAVE COUNT
.1834 B1 22         [5/6] 04052          lda    (I),Y     ; GET CHAR FROM I
.1836 AA              [2] 04053          tax              ; Stash I[Y]
.                         04054 ; STX I
.                         04055 ; LDX J
.1837 B1 24         [5/6] 04056          lda    (J),Y     ; GET CHAR FROM J
.1839 91 22           [6] 04057          sta    (I),Y     ; Replace in I
.                         04058 ; INX
.                         04059 ; STX J ; SET NEW J
.                         04060 ; LDX I
.183B 8A              [2] 04061          txa              ; Recover I[Y]
.183C 91 24           [6] 04062          sta    (J),Y     ; Replace in J
.                         04063 ; INX
.                         04064
.                         04065 ; PULB ; RESTORE COUNT
.                         04066
.183E 88              [2] 04067          dey              ; DECREMENT IT
.183F 10 F3 (1834)  [2/3] 04068          bpl    XCHNG1    ; LOOP IF NOT -1TH BYTE
.                         04069
.                         04070 ; BSR XSUB8 ; FIX I POINTER
.                         04071 ; STX I
.                         04072 ; LDX J
.                         04073 ; BSR XSUB8 ; FIX J POINTER
.                         04074 ; STX J
.                         04075
.1841 60              [6] 04076          rts


The original 6800 code:

Code:
.151F 09              [4] 02889 XSUB8    DEX              DECREMENT X BY 8
.1520 09              [4] 02890          DEX
.1521 09              [4] 02891          DEX
.1522 09              [4] 02892          DEX
.1523 09              [4] 02893          DEX
.1524 09              [4] 02894          DEX
.1525 09              [4] 02895          DEX
.1526 09              [4] 02896          DEX
.1527 39              [5] 02897          RTS
.                         02898 *
.1528 DE 20           [4] 02899 XCHNG    LDX    I
.152A C6 08           [2] 02900          LDAB   #$08      SET COUNT
.152C 37              [4] 02901 XCHNG1   PSHB             SAVE COUNT
.152D E6 00           [5] 02902          LDAB   0,X       GET CHAR FROM I
.152F DF 20           [5] 02903          STX    I
.1531 DE 22           [4] 02904          LDX    J
.1533 A6 00           [5] 02905          LDAA   0,X       GET CHAR FROM J
.1535 E7 00           [6] 02906          STAB   0,X       REPLACE WITH I CHAR
.1537 08              [4] 02907          INX
.1538 DF 22           [5] 02908          STX    J         SET NEW J
.153A DE 20           [4] 02909          LDX    I
.153C A7 00           [6] 02910          STAA   0,X       REPLACE WITH J CHAR
.153E 08              [4] 02911          INX
.153F 33              [4] 02912          PULB             RESTORE COUNT
.1540 5A              [2] 02913          DECB             DECREMENT IT
.1541 26 E9 (152C)    [4] 02914          BNE    XCHNG1    LOOP IF NOT 8TH BYTE
.1543 8D DA (151F)    [8] 02915          BSR    XSUB8     FIX I POINTER
.1545 DF 20           [5] 02916          STX    I
.1547 DE 22           [4] 02917          LDX    J
.1549 8D D4 (151F)    [8] 02918          BSR    XSUB8     FIX J POINTER
.154B DF 22           [5] 02919          STX    J
.154D 39              [5] 02920          RTS


On further examination, the 6800 version can be made substantially faster than the 6502 version by completely unrolling the loop but the code is almost twice as big. (The XSUB8 subroutine is also used elsewhere, so it cannot be eliminated in the process.) A small speed gain by a similar transformation of the 6502 version does not justify the massive increase in code size required.


Top
 Profile  
Reply with quote  
PostPosted: Sun May 17, 2020 5:47 am 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1949
Location: Sacramento, CA, USA
Yeah, (zp),y is a real jewel. Whoever invented it certainly deserves our appreciation.

_________________
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)


Top
 Profile  
Reply with quote  
PostPosted: Sun May 17, 2020 12:43 pm 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 704
Location: North Tejas
I keep forgetting that (zp,X) has the same effect as (zp),Y when both X and Y are zero.

It would be nice if (abs),Y was also available...


Top
 Profile  
Reply with quote  
PostPosted: Sun May 17, 2020 3:10 pm 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
BillG wrote:
I keep forgetting that (zp,X) has the same effect as (zp),Y when both X and Y are zero.
Yes, the same effect. But FWIW (zp),Y avoids a dead cycle when y=0. By comparison, (zp,X) always entails a dead cycle, making it one cycle slower in this case.

Quote:
It would be nice if (abs),Y was also available...
Yeah. Instead you need to simulate this addressing mode. One solution begins by copying the two bytes to zero-page (assuming you have two zero-page bytes available). Another begins by copying the two bytes into the operand field of an abs,y instruction that follows the copy -- IOW, self-modifying code. In the linked article Garth explains how, among other things, SMC can make up for instructions or addressing modes the processor doesn't have.

-- Jeff

_________________
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html


Top
 Profile  
Reply with quote  
PostPosted: Sun May 17, 2020 3:42 pm 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 704
Location: North Tejas
Dr Jefyll wrote:
BillG wrote:
I keep forgetting that (zp,X) has the same effect as (zp),Y when both X and Y are zero.
Yes, the same effect. But FWIW (zp),Y avoids a dead cycle when y=0. By comparison, (zp,X) always entails a dead cycle, making it one cycle slower in this case.


Very true. But that one dead cycle is much less than ping ponging the Y register between 0 and some other value.


Dr Jefyll wrote:
BillG wrote:
It would be nice if (abs),Y was also available...
Yeah. Instead you need to simulate this addressing mode. One solution begins by copying the two bytes to zero-page (assuming you have two zero-page bytes available). Another begins by copying the two bytes into the operand field of an abs,y instruction that follows the copy -- IOW, self-modifying code. In the linked article Garth explains how, among other things, SMC can make up for instructions or addressing modes the processor doesn't have.

-- Jeff


When working on the assembler, and soon the editor and BASIC interpreter, I have the luxury of using as much of the zero page as needed. Most of the variables have been in the zero page so that simulation is not necessary.

The FLEX operating system, on the other hand, endeavors to continue the tradition on 680x processors in which application programs and not the operating system gets to use the zero page. Within the operating system code, the copying of addresses to the zero page is excessive. Self modifying code is out of the question as some have expressed a desire to place the FLEX operating system code in ROM.


Top
 Profile  
Reply with quote  
PostPosted: Mon May 18, 2020 2:11 am 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 704
Location: North Tejas
BillG wrote:
On further examination, the 6800 version can be made substantially faster than the 6502 version by completely unrolling the loop but the code is almost twice as big. (The XSUB8 subroutine is also used elsewhere, so it cannot be eliminated in the process.) A small speed gain by a similar transformation of the 6502 version does not justify the massive increase in code size required.


I have to partially retract that statement. Somehow, I managed to forget that the 6800 only has one index register; the X register must to be ping ponged between I and J. Still, completely unrolling that loop makes the 6800 code about as fast as the 6502 version, but with much bigger code size. The result would look something like this:

Code:
 0100 DE 00         [4] 00006            ldx    I
                        00007 *
 0102 E6 00         [5] 00008            ldab   0,X
 0104 DE 02         [4] 00009            ldx    J
 0106 A6 00         [5] 00010            ldaa   0,X
 0108 E7 00         [6] 00011            stab   0,X
 010A DE 00         [4] 00012            ldx    I
 010C A7 00         [6] 00013            staa   0,X
                        00014 *
 010E E6 01         [5] 00015            ldab   1,X
 0110 DE 02         [4] 00016            ldx    J
 0112 A6 01         [5] 00017            ldaa   1,X
 0114 E7 01         [6] 00018            stab   1,X
 0116 DE 00         [4] 00019            ldx    I
 0118 A7 01         [6] 00020            staa   1,X

etc.


There are two other service subroutines for the symbol table sorter.

CMPLBL compares two symbols, pointed to by the variables I and J. Note that the 6800 version uses a couple of temporary variables instead of modifying I and J, then fixing them after the loop is finished; this same approach would have made the exchange subroutine better. Completely unrolling the loop is again the fastest implementation.

The original 6800 code:

Code:
.154E DE 20           [4] 02922 CMPLBL   LDX    I
.1550 DF 76           [5] 02923          STX    XTEMP     GET I INTO XTEMP
.1552 DE 22           [4] 02924          LDX    J
.1554 DF 80           [5] 02925          STX    XTEMP5    GET J INTO XTEMP5
.1556 C6 06           [2] 02926          LDAB   #$06      SET COMPARE COUNT
.1558 DE 76           [4] 02927 CMPLB1   LDX    XTEMP
.155A A6 00           [5] 02928          LDAA   0,X       GET CHAR FROM I
.155C 08              [4] 02929          INX
.155D DF 76           [5] 02930          STX    XTEMP
.155F DE 80           [4] 02931          LDX    XTEMP5
.1561 A1 00           [5] 02932          CMPA   0,X       COMPARE WITH J CHAR
.1563 26 06 (156B)    [4] 02933          BNE    CMPLB2    EXIT IF NOT EQUAL
.1565 08              [4] 02934          INX
.1566 DF 80           [5] 02935          STX    XTEMP5
.1568 5A              [2] 02936          DECB             ELSE DECREMENT COUNT
.1569 26 ED (1558)    [4] 02937          BNE    CMPLB1    LOOP UNTIL DONE
.156B 39              [5] 02938 CMPLB2   RTS


The 6502 code:

Code:
.1981                     04172 CMPLBL
.                         04173 ; LDX I
.                         04174 ; STX XTEMP ; GET I INTO XTEMP
.                         04175 ; LDX J
.                         04176 ; STX XTEMP5 ; GET J INTO XTEMP5
.1981 A0 00           [2] 04177          ldy    #0        ; SET index
.1983                     04178 CMPLB1                    ;LDX XTEMP
.1983 B1 22         [5/6] 04179          lda    (I),Y     ; GET CHAR FROM I
.                         04180 ; INX
.                         04181 ; STX XTEMP
.                         04182 ; LDX XTEMP5
.1985 D1 24         [5/6] 04183          cmp    (J),Y     ; COMPARE WITH J CHAR
.1987 D0 05 (198E)  [2/3] 04184          bne    CMPLB2    ; EXIT IF NOT EQUAL
.                         04185 ; INX
.                         04186 ; STX XTEMP5
.                         04187
.1989 C8              [2] 04188          iny              ; ELSE inCREMENT index
.198A C0 06           [2] 04189          cpy    #6
.198C D0 F5 (1983)  [2/3] 04190          bne    CMPLB1    ; LOOP UNTIL DONE
.                         04191
.198E 60              [6] 04192 CMPLB2   rts


PUSH pushes an address onto a software stack. This code is an even test which illustrates shortcomings in both processors. The 6800 does not provide easy access to the index register; this is corrected in the 6809. The 6502 does not provide an easy way to perform 16-bit arithmetic.

The original 6800 code:

Code:
.14B5 DF 80           [5] 02823 PUSH     STX    XTEMP5    PUT THE VALUE IN
.14B7 DE 28           [4] 02824          LDX    SRSP      THE X REGISTER ONTO THE
.14B9 96 80           [3] 02825          LDAA   XTEMP5    SORT REQUEST STACK AND
.14BB A7 00           [6] 02826          STAA   0,X       UPDATE THE SORT REQUEST
.14BD 08              [4] 02827          INX              STACK POINTER
.14BE 96 81           [3] 02828          LDAA   XTEMP5+1
.14C0 A7 00           [6] 02829          STAA   0,X
.14C2 08              [4] 02830          INX
.14C3 DF 28           [5] 02831          STX    SRSP
.14C5 39              [5] 02832          RTS


The 6502 code:

Code:
.18AB                     03977 PUSH
.                         03978 ; STX XTEMP5 ; PUT THE VALUE IN
.                         03979 ; LDX SRSP ; THE X REGISTER ONTO THE
.                         03980 ; LDAA XTEMP5 ; SORT REQUEST STACK AND
.                         03981
.                         03982 ; Address in A:X
.18AB A0 01           [2] 03983          ldy    #1
.18AD 91 2A           [6] 03984          sta    (SRSP),Y  ; UPDATE THE SORT REQUEST
.18AF 88              [2] 03985          dey              ; STACK POINTER
.18B0 8A              [2] 03986          txa
.18B1 91 2A           [6] 03987          sta    (SRSP),Y
.                         03988
.18B3 18              [2] 03989          clc              ; Update "stack pointer"
.18B4 A5 2A           [3] 03990          lda    SRSP
.18B6 69 02           [2] 03991          adc    #2
.18B8 85 2A           [3] 03992          sta    SRSP
.18BA A5 2B           [3] 03993          lda    SRSP+1
.18BC 69 00           [2] 03994          adc    #0
.18BE 85 2B           [3] 03995          sta    SRSP+1
.                         03996
.18C0 60              [6] 03997          rts


At this time, the symbol table sorter has been completely coded. Wish me luck as I begin to test it...


Top
 Profile  
Reply with quote  
PostPosted: Tue May 19, 2020 1:57 pm 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 704
Location: North Tejas
I am now able to cross assemble most inherent 6800 instructions.

While 6800 binary files currently have no value on a 6502, this means that a large part of the fundamental infrastructure of the assembler is working.

Next up, evaluating expressions...

Attachment:
asmb.png
asmb.png [ 18.87 KiB | Viewed 1245 times ]


Top
 Profile  
Reply with quote  
PostPosted: Sun Jun 07, 2020 6:53 pm 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 704
Location: North Tejas
This project is now two months old.

The FLEX file system (File Management System or FMS) is still lacking the code for writing random access files until I can come up with a good way to test it. I may go ahead and write the code but leave it disconnected to get an idea how big it is likely to be.

The FLEX user interface portion is feature complete except for background printing. Again, I may write the code to find out how large it will be. The error message reporting mechanism is complete.

There was little progress on the Utility Command Set this month. The SAVE utility has been written, but not thoroughly tested.

The 6800 assembler now runs on the 6502 as a cross assembler. To help test it, I have started implementing the text editor. It can currently create a text file and make some simple edits to it. The editor is definitely more difficult code than the assembler has been.

The current system memory map is:

$0000..$00FF - Zero page, locations at $12 and above are free for application programs to use
$0100..$017F - FLEX line buffer
$0180..$01FF - Stack
$0200..$033F - FLEX entry points, variables and printer driver
$0340..$047F - System File Control Block
$0480..$0AFF - FLEX Utility Command Space
$0B00..MEMEND - User memory

Somewhere above that is about 6K of FLEX itself.

It is time to start trying to freeze the memory organization. I am considering making a somewhat radical change to move the public portions (entry points, variables, Utility Command Space) from $200 up to $2000. Why? Doing this will make it possible for a KIM-1 or clone with a expanded RAM and a serial port to run FLEX. The operating system itself can reside from $200 to $2000 on systems which allow that and at the top of user memory otherwise. Because the binary file format consists of a collection of separate chunks, pieces of the system can potentially be built to load into several disjoint places where memory is available.

Another decision is whether the system should reserve a part of the lower or upper end of the zero page.

The important part now is to determine where the public portions are located. This is where I need your input as to what your particular system requires and allows. It may not be possible to please everyone, but the main goal is to have one version of the utilities and application programs which work on all supported platforms.


Top
 Profile  
Reply with quote  
PostPosted: Wed Jun 17, 2020 7:28 pm 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 704
Location: North Tejas
The text editor code has been difficult; I can only stand to work on it a bit at a time.

The 6800 version keeps values in the X register for long stretches of code, sometimes across several subroutines. I am about to give up trying to keep it in 6502 registers even part of the time, but to declare RegX, a 2-byte variable in the zero page, and copy values into and out of it as the 6800 loads and stores X. Addresses already have to be stored in the zero page to access memory. It will not be as efficient, but the code will be somewhat clearer; this program really needs that.

So far, the following functionality is complete:

loading a file
saving a file
text buffer management
Print command
Insert command
Delete command
Renumber command
Overlay command
Find command

The Copy command has been coded, but it does not work. When that is done, the Move command should be easy as it does a copy followed by a delete. I would guess we are somewhat past the halfway mark.

During breaks, I have been working on assemblers.

First, I added the SET directive to the 6800 ASMB. It is like EQU, but a label may be assigned a value more than once.

I have always liked the local labels in RELASMB, the 6809 relocatable assembler, and wished that ASMB implemented them.

Local labels work like this: a one or two digit number in the label field is considered to be a local label. It is referenced by stating the number followed by a "b" or "f" to designate whether to search for the nearest occurrence of the number before or following the current line. Note that it is not possible to find a local label on the current line. For example:

Code:
2                       ; This is the target for "2b"

2       beq     target  ; The label for this line cannot be specified

2                       ; This is the target for "2f"


Advantages of a local label include doing away with the need to come up with meaningful and unique names for short, trivial branches and a local label uses less memory than a regular symbol.

A web search for local label uncovered no prevalent standard, but a number with a "b" or "f" suffix is a very common form.

I will put a seemingly arbitrary limit on local labels: the number may not consist of only "0" and "1" digits. Why? ASMB 6800 accepts binary numbers in both the %xx and xxb forms. Something like "1b" is ambiguous.

I had been initially tempted to limit the reference of local labels to relative branch instructions to prevent people writing FORTRANish code, but RELASMB does not have that restriction. And it is convenient to be able to do something like the following:

Code:
        ldx     #2f     ; Print error message
        jsr     PSTRNG
        rts

2       fcc     "Operand expected."
        fcb     4


I am currently implementing local labels in my 6502 cross assembler. Should that go well, the capability will be migrated to the 6800 and 6809 assemblers. Then I will implement it in ASMB 6800; ASMB 6502 will inherit that functionality.


Top
 Profile  
Reply with quote  
PostPosted: Wed Jun 17, 2020 8:28 pm 
Offline
User avatar

Joined: Tue Mar 05, 2013 4:31 am
Posts: 1385
Great to see you making progress with this project. Unless I missed it, I think you're doing all of this on an emulated 6502 system, correct??

If yes, what would be an actual hardware configuration to implement with a 6502 system? I've been working on an IDE interface for my SBC and will eventually create a BIOS to access it. Perhaps FLEX could be implemented as the OS?

_________________
Regards, KM
https://github.com/floobydust


Top
 Profile  
Reply with quote  
PostPosted: Wed Jun 17, 2020 10:59 pm 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 704
Location: North Tejas
Yes, it has been developed so far only using emulation.

The current virtual hardware is essentially a SWTPC 6800 computer with a 6502 processor instead of the 6800, 56K of RAM (though it will not require that much), an ACIA for a serial port and a WD 1771 for a disk controller.

My intent is to support the Corsham SD card system for mass storage once I figure out how to emulate it. That will likely be the first supported configuration in actual hardware. https://www.corshamtech.com/product/sd-card-system/

Maybe you can be the first?

FLEX has broken out the console and disk drivers into separate files and only those need to be reimplemented to adapt the system to custom hardware.

This is the manual for adapting 6809 FLEX to a new system. The process for the 6502 is similar. http://www.flexusergroup.com/flexusergr ... 09fadg.pdf

Other FLEX manuals can be found at: http://www.flexusergroup.com/flexusergroup/fug4.htm


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 89 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 27 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: