]> Shamusworld >> Repos - rmac/commitdiff
Added Jaguar Object Processor assembler.
authorShamus Hammons <jlhamm@acm.org>
Mon, 26 Feb 2018 03:39:59 +0000 (21:39 -0600)
committerShamus Hammons <jlhamm@acm.org>
Mon, 26 Feb 2018 03:39:59 +0000 (21:39 -0600)
Rationale for this and how it works can be found in
docs/note-on-the-op-assembler.txt. Version now at 1.13.0.

21 files changed:
.gitignore
direct.c
docs/note-on-the-op-assembler.txt [new file with mode: 0644]
eagen0.c
fltpoint.c
fltpoint.h
makefile
mark.c
mark.h
mntab
op.c [new file with mode: 0644]
op.h [new file with mode: 0644]
op.tab [new file with mode: 0644]
procln.c
riscasm.c
riscasm.h
rmac.c
rmac.h
sect.c
sect.h
version.h

index be2b8f877f1e35820971881fed4c26e096f2b953..8266a9c64842530bc7c4aa63d2c575c5686e041f 100644 (file)
@@ -2,6 +2,8 @@
 68kgen.o
 68ktab.h
 68kmn
 68kgen.o
 68ktab.h
 68kmn
+6502kw.h
+opkw.h
 *.o
 *~
 kwtab.h
 *.o
 *~
 kwtab.h
index 9e397198465be703203a32f2a16bf6d76e865fe6..2511473fb5c89953decbe40a3579943dfb84f8c0 100644 (file)
--- a/direct.c
+++ b/direct.c
@@ -79,6 +79,7 @@ int d_cstruct(void);
 int d_prgflags(void);
 int d_opt(void);
 int d_dsp(void);
 int d_prgflags(void);
 int d_opt(void);
 int d_dsp(void);
+int d_objproc(void);
 void SetLargestAlignment(int);
 
 // Directive handler table
 void SetLargestAlignment(int);
 
 // Directive handler table
@@ -149,7 +150,8 @@ int (*dirtab[])() = {
        d_68882,                        // 63 .68882
        d_56001,                        // 64 .56001
        d_nofpu,                        // 65 nofpu
        d_68882,                        // 63 .68882
        d_56001,                        // 64 .56001
        d_nofpu,                        // 65 nofpu
-       d_opt,                          // 58 .opt
+       d_opt,                          // 66 .opt
+       d_objproc,                      // 67 .objproc
 };
 
 
 };
 
 
@@ -216,8 +218,8 @@ int d_org(void)
 {
        uint64_t address;
 
 {
        uint64_t address;
 
-       if (!rgpu && !rdsp && !m6502)
-               return error(".org permitted only in gpu/dsp and 6502 sections");
+       if (!rgpu && !rdsp && !robjproc && !m6502)
+               return error(".org permitted only in GPU/DSP/OP and 6502 sections");
 
        if (abs_expr(&address) == ERROR)
        {
 
        if (abs_expr(&address) == ERROR)
        {
@@ -225,7 +227,7 @@ int d_org(void)
                return ERROR;
        }
 
                return ERROR;
        }
 
-       if (rgpu | rdsp)
+       if (rgpu | rdsp | robjproc)
        {
                orgaddr = address;
                orgactive = 1;
        {
                orgaddr = address;
                orgactive = 1;
@@ -1066,9 +1068,6 @@ int d_dc(WORD siz)
                uint16_t tdb = eattr & TDB;
                uint16_t defined = eattr & DEFINED;
 
                uint16_t tdb = eattr & TDB;
                uint16_t defined = eattr & DEFINED;
 
-               if ((challoc - ch_size) < 4)
-                       chcheck(4);
-
                switch (siz)
                {
                case SIZB:
                switch (siz)
                {
                case SIZB:
@@ -1136,6 +1135,7 @@ int d_dc(WORD siz)
 
                                D_long(eval);
                        }
 
                                D_long(eval);
                        }
+
                        break;
                case SIZQ:
                        // 64-bit size
                        break;
                case SIZQ:
                        // 64-bit size
@@ -1144,7 +1144,17 @@ int d_dc(WORD siz)
 
                        // Shamus: We only handle DC.Q type stuff, will have to add fixups
                        //         and stuff later (maybe... might not be needed...)
 
                        // Shamus: We only handle DC.Q type stuff, will have to add fixups
                        //         and stuff later (maybe... might not be needed...)
-                       D_quad(eval);
+                       // DEFINITELY NEED FIXUPS HERE!
+                       if (!defined)
+                       {
+                               AddFixup(FU_QUAD, sloc, exprbuf);
+                               D_quad(0LL);
+                       }
+                       else
+                       {
+                               D_quad(eval);
+                       }
+
                        break;
                case SIZS:
                        // 32-bit float size
                        break;
                case SIZS:
                        // 32-bit float size
@@ -1158,8 +1168,9 @@ int d_dc(WORD siz)
                        }
                        else
                        {
                        }
                        else
                        {
-                               if (tdb)
-                                       MarkRelocatable(cursect, sloc, tdb, MSINGLE, NULL);
+//Would this *ever* happen?
+//                             if (tdb)
+//                                     MarkRelocatable(cursect, sloc, tdb, MSINGLE, NULL);
 
                                PTR ptr;
                                ptr.u64 = &eval;
 
                                PTR ptr;
                                ptr.u64 = &eval;
@@ -1180,8 +1191,9 @@ int d_dc(WORD siz)
                        }
                        else
                        {
                        }
                        else
                        {
-                               if (tdb)
-                                       MarkRelocatable(cursect, sloc, tdb, MDOUBLE, NULL);
+//Would this *ever* happen?
+//                             if (tdb)
+//                                     MarkRelocatable(cursect, sloc, tdb, MDOUBLE, NULL);
 
                                PTR ptr;
                                ptr.u64 = &eval;
 
                                PTR ptr;
                                ptr.u64 = &eval;
@@ -1204,8 +1216,9 @@ int d_dc(WORD siz)
                        }
                        else
                        {
                        }
                        else
                        {
-                               if (tdb)
-                                       MarkRelocatable(cursect, sloc, tdb, MEXTEND, NULL);
+//Would this *ever* happen?
+//                             if (tdb)
+//                                     MarkRelocatable(cursect, sloc, tdb, MEXTEND, NULL);
 
                                PTR ptr;
                                ptr.u64 = &eval;
 
                                PTR ptr;
                                ptr.u64 = &eval;
@@ -1483,7 +1496,7 @@ int d_nlist(void)
 //
 int d_68000(void)
 {
 //
 int d_68000(void)
 {
-       rgpu = rdsp = 0;
+       rgpu = rdsp = robjproc = 0;
        // Switching from gpu/dsp sections should reset any ORG'd Address
        orgactive = 0;
        orgwarning = 0;
        // Switching from gpu/dsp sections should reset any ORG'd Address
        orgactive = 0;
        orgwarning = 0;
@@ -1601,6 +1614,7 @@ int d_gpu(void)
 
        rgpu = 1;                       // Set GPU assembly
        rdsp = 0;                       // Unset DSP assembly
 
        rgpu = 1;                       // Set GPU assembly
        rdsp = 0;                       // Unset DSP assembly
+       robjproc = 0;           // Unset OP assembly
        regbank = BANK_N;       // Set no default register bank
        return 0;
 }
        regbank = BANK_N;       // Set no default register bank
        return 0;
 }
@@ -1626,6 +1640,7 @@ int d_dsp(void)
 
        rdsp = 1;                       // Set DSP assembly
        rgpu = 0;                       // Unset GPU assembly
 
        rdsp = 1;                       // Set DSP assembly
        rgpu = 0;                       // Unset GPU assembly
+       robjproc = 0;           // Unset OP assembly
        regbank = BANK_N;       // Set no default register bank
        return 0;
 }
        regbank = BANK_N;       // Set no default register bank
        return 0;
 }
@@ -1876,6 +1891,32 @@ int d_cstruct(void)
 }
 
 
 }
 
 
+//
+// Define start of OP object list (allows the use of ORG)
+//
+int d_objproc(void)
+{
+       if ((cursect != TEXT) && (cursect != DATA))
+       {
+               error(".objproc can only be used in the TEXT or DATA segments");
+               return ERROR;
+       }
+
+       // If previous section was DSP or 68000 then we need to reset ORG'd
+       // Addresses
+       if (!robjproc)
+       {
+               orgactive = 0;
+               orgwarning = 0;
+       }
+
+       robjproc = 1;           // Set OP assembly
+       rgpu = 0;                       // Unset GPU assembly
+       rdsp = 0;                       // Unset DSP assembly
+       return OK;
+}
+
+
 //
 // Undefine a macro - .undefmac macname [, macname...]
 //
 //
 // Undefine a macro - .undefmac macname [, macname...]
 //
diff --git a/docs/note-on-the-op-assembler.txt b/docs/note-on-the-op-assembler.txt
new file mode 100644 (file)
index 0000000..8a3d14b
--- /dev/null
@@ -0,0 +1,129 @@
+A Few Notes on the New Object Processor Assembler
+-------------------------------------------------
+
+Q: What is it?
+
+A: An assembler to generate object lists for the Atari Jaguar's Object
+   processor.
+
+
+Q: Why is it here?
+
+A: To really utilize the OP properly, it needs an assembler. Otherwise, what
+   happens is you end up writing an assembler in your code to assemble the OP
+   list, and that's a real drag--something that *should* be handled by a proper
+   assembler.
+
+
+Q: How do I use it?
+
+A: The OP assembler works similarly to the RISC assembler; to enter the OP
+   assembler, you put the .objproc directive in your code (N.B.: like the RISC
+   assembler, it only works in a TEXT or DATA section). From there, you build
+   the OP list how you want it and go from there. A few caveats: you will want
+   to put a .org directive at the top of your list, and labels that you want to
+   be able to address in 68xxx code (for moving from a data section to an
+   address where it will be executed by the OP, for example) should be created
+   in .68xxx mode.
+
+
+Q: What are the opcodes?
+
+A: They are bitmap, scbitmap, gpuobj, branch, stop, nop, and jump. nop and jump
+   are psuedo-ops, they are there as a convenience to the coder.
+
+
+Q: What are the proper forms for these opcodes?
+
+A: They are as follows:
+
+   bitmap <data addr>, <xloc>, <yloc>, <dwidth>, <iwidth>, <iheight>, <bpp>,
+          <pallete idx>, <flags>, <firstpix>, <pitch>
+   scbitmap <data addr>, <xloc>, <yloc>, <dwidth>, <iwidth>, <iheight>,
+            <xscale>, <yscale>, <remainder>, <bpp>, <pallete idx>,
+            <flags>, <firstpix>, <pitch>
+   gpuobj <line #>, <userdata> (bits 14-63 of this object)
+   branch VC <condition (<, =, >)> <line #>, <link addr>
+   branch OPFLAG, <link addr>
+   branch SECHALF, <link addr>
+   stop
+   nop
+   jump <link addr>
+
+   Note that the <flags> field in bitmap and scbitmap objects consist of the
+   following: REFLECT, RMW, TRANS, RELEASE. They can be in any order (and
+   should be separated by whitespace *only*), and you can only put a maximum of
+   four of them in. Further note that with bitmap and scbitmap objects, all the
+   parameters after <data addr> are optional--if they are omitted, they will
+   use defaults (mostly 0, but 1 is the default for pitch). Also, in the
+   scbitmap object, the <xscale>, <yscale>, and <remainder> fields can be
+   floating point constants/expressions. <data addr> can refer to any address
+   defined (even external!) and the linker (rln v1.6.0 or greater) will
+   properly fix up the address.
+
+
+Q: What do they do?
+
+A: Pretty much what you expect. It's beyond the scope of this little note to
+   explain the Jaguar's Object Processor and how it operates, so you'll have to
+   seek explanations for how they work elsewhere.
+
+
+Q: Why do I want to put a .org directive at the top of my list?
+
+A: You want to put a .org directive at the top of your list because otherwise
+   the assembler will not know where in memory the object list is supposed
+   go--then when you move it to its destination, the object link addresses will
+   all be wrong and it won't work.
+
+
+Q: Why would I copy my object list to another memory location?
+
+A: Simple: because the OP destroys the list as it uses it to render the screen.
+   If you don't keep a fresh copy stashed away somewhere to refresh it before
+   the next frame is rendered, what you see on the screen will not be what you
+   expect, as the OP has scribbled all over it!
+
+
+Q: Does the assembler do anything behind my back?
+
+A: Yes, it will emit NOPs to ensure that bitmaps and scbitmaps are on proper
+   memory boundaries, and fixup link addresses as necessary. This is needed
+   because of a quirk in how the OP works (it ORs constants on the address
+   lines to get the phrases it needs and if they are not zeroes, it will fail
+   in bizarre ways).
+
+
+Q: Why can't I define the link addresses for all the objects?
+
+A: You really, *really* don't want to do this. Trust me on this one.
+
+
+Q: How about an example of an object list?
+
+A: Here you go:
+
+               objList = $10000
+               bRam = $20000
+;
+               .68000
+objects:                       ; This is the label you will use to address this in 68K code
+               .objproc        ; Engage the OP assembler
+               .org    objList ; Tell the OP assembler where the list will execute
+;
+               branch          VC < 69, .stahp         ; Branch to the STOP object if VC < 69
+               branch          VC > 241, .stahp        ; Branch to the STOP object if VC > 241
+               bitmap          bRAM, 22, 70, 24, 24, 22, 4
+               bitmap          bRAM, 20+96+96, 70, 24, 24, 22, 4, 0, REFLECT
+               scbitmap        tms, 20, 70, 1, 1, 8, 3.0, 3.0, 2.9999, 0, 0, TRANS
+               scbitmap        tmsShadow, 23, 73, 1, 1, 8, 3.0, 3.0, 2.9999, 0, 3, TRANS
+               bitmap          sbRelBM, 30, 108, 3, 3, 8, 0, 1, TRANS
+               bitmap          txt1BM, 46, 132, 3, 3, 8, 0, 2, TRANS
+               bitmap          txt2BM, 46, 148, 3, 3, 8, 0, 2, TRANS
+               bitmap          txt3BM, 22, 164, 3, 3, 8, 0, 2, TRANS
+               jump            .haha
+.stahp:
+               stop
+.haha:
+               jump            .stahp
+
index 1bc5fd675255bd3ee1c203573928596c7d29ecda..5b3c4ab5b35df2e34043b50364407d6bc5fe01c2 100644 (file)
--- a/eagen0.c
+++ b/eagen0.c
@@ -214,8 +214,9 @@ int eaNgen(WORD siz)
                        // 68881/68882/68040 only
                        if (w)
                        {
                        // 68881/68882/68040 only
                        if (w)
                        {
-                               if (tdb)
-                                       MarkRelocatable(cursect, sloc, tdb, MSINGLE, NULL);
+//Would a floating point value *ever* need to be fixed up as if it were an address? :-P
+//                             if (tdb)
+//                                     MarkRelocatable(cursect, sloc, tdb, MSINGLE, NULL);
 
                                // The value passed back from expr() is an internal C double;
                                // so we have to access it as such then convert it to an
 
                                // The value passed back from expr() is an internal C double;
                                // so we have to access it as such then convert it to an
@@ -238,8 +239,9 @@ int eaNgen(WORD siz)
                        // 68881/68882/68040 only
                        if (w)
                        {
                        // 68881/68882/68040 only
                        if (w)
                        {
-                               if (tdb)
-                                       MarkRelocatable(cursect, sloc, tdb, MDOUBLE, NULL);
+//Would a floating point value *ever* need to be fixed up as if it were an address? :-P
+//                             if (tdb)
+//                                     MarkRelocatable(cursect, sloc, tdb, MDOUBLE, NULL);
 
                                PTR p;
                                p.u64 = &aNexval;
 
                                PTR p;
                                p.u64 = &aNexval;
@@ -258,8 +260,9 @@ int eaNgen(WORD siz)
                        // 68881/68882/68040 only
                        if (w)
                        {
                        // 68881/68882/68040 only
                        if (w)
                        {
-                               if (tdb)
-                                       MarkRelocatable(cursect, sloc, tdb, MEXTEND, NULL);
+//Would a floating point value *ever* need to be fixed up as if it were an address? :-P
+//                             if (tdb)
+//                                     MarkRelocatable(cursect, sloc, tdb, MEXTEND, NULL);
 
                                PTR p;
                                p.u64 = &aNexval;
 
                                PTR p;
                                p.u64 = &aNexval;
index fa1eb41ad9c78af887a63b444f099a4ecf184d95..911e0085ae2729b6c513cf16f975061a86287adb 100644 (file)
@@ -14,6 +14,7 @@
 #include "fltpoint.h"
 #include <float.h>
 #include <math.h>
 #include "fltpoint.h"
 #include <float.h>
 #include <math.h>
+#include <stdio.h>
 
 //
 // Check for IEEE-754 conformance (C99 compilers should be OK here)
 
 //
 // Check for IEEE-754 conformance (C99 compilers should be OK here)
@@ -169,3 +170,25 @@ void DoubleToExtended(double d, uint8_t out[])
        out[11] = intMant & 0xFF;
 }
 
        out[11] = intMant & 0xFF;
 }
 
+
+//
+// Convert a host native floating point number to a fixed point number.
+//
+uint64_t DoubleToFixedPoint(double d, int intBits, int fracBits)
+{
+       uint8_t signBit = (signbit(d) ? 1 : 0);
+
+       // Ensure what we're working on is positive...
+       if (d < 0)
+               d *= -1;
+
+       double scaleFactor = (double)(1 << fracBits);
+       uint64_t result = (uint64_t)(d * scaleFactor);
+
+       // Invert the result, if necessary
+       if (signBit == 1)
+               result = (result = 0xFFFFFFFFFFFFFFFFLL) + 1;
+
+       return result;
+}
+
index c3d4038709012046e195904c8988191b8c962ef9..558ad7b5d24e378c01b607d486b5de3b62889d62 100644 (file)
@@ -1,13 +1,20 @@
 //
 //
-// Cross-platform floating point handling
+// Cross-platform floating point handling (fixed point handling too!)
 //
 // by James Hammons
 // (C) 2018 Underground Software
 //
 
 //
 // by James Hammons
 // (C) 2018 Underground Software
 //
 
+#ifndef __FLTPOINT_H__
+#define __FLTPOINT_H__
+
 #include <stdint.h>
 
 uint32_t FloatToIEEE754(float f);
 uint64_t DoubleToIEEE754(double d);
 void DoubleToExtended(double d, uint8_t out[]);
 
 #include <stdint.h>
 
 uint32_t FloatToIEEE754(float f);
 uint64_t DoubleToIEEE754(double d);
 void DoubleToExtended(double d, uint8_t out[]);
 
+uint64_t DoubleToFixedPoint(double d, int intBits, int fracBits);
+
+#endif // __FLTPOINT_H__
+
index 997e2bc19d3e5873873ac998394075c8ef215d47..f966ea1e3daf8e28f3995b42e2af53e2759b0395 100644 (file)
--- a/makefile
+++ b/makefile
@@ -27,15 +27,15 @@ HOSTCC = gcc
 #CFLAGS = -std=$(STD) -D_DEFAULT_SOURCE -g -D__GCCUNIX__ -I. -O2 -MMD
 CFLAGS = -std=$(STD) -D_DEFAULT_SOURCE -g -D__GCCUNIX__ -I. -O2
 
 #CFLAGS = -std=$(STD) -D_DEFAULT_SOURCE -g -D__GCCUNIX__ -I. -O2 -MMD
 CFLAGS = -std=$(STD) -D_DEFAULT_SOURCE -g -D__GCCUNIX__ -I. -O2
 
-SRCS = 6502.c amode.c debug.c direct.c eagen.c error.c expr.c fltpoint.c listing.c mach.c macro.c mark.c object.c procln.c riscasm.c rmac.c sect.c symbol.c token.c
+SRCS = 6502.c amode.c debug.c direct.c eagen.c error.c expr.c fltpoint.c listing.c mach.c macro.c mark.c object.c op.c procln.c riscasm.c rmac.c sect.c symbol.c token.c
 
 
-OBJS = 6502.o amode.o debug.o direct.o eagen.o error.o expr.o fltpoint.o listing.o mach.o macro.o mark.o object.o procln.o riscasm.o rmac.o sect.o symbol.o token.o
+OBJS = 6502.o amode.o debug.o direct.o eagen.o error.o expr.o fltpoint.o listing.o mach.o macro.o mark.o object.o op.o procln.o riscasm.o rmac.o sect.o symbol.o token.o
 
 #
 # Build everything
 #
 
 
 #
 # Build everything
 #
 
-all : mntab.h 68ktab.h kwtab.h risckw.h 6502kw.h rmac
+all : mntab.h 68ktab.h kwtab.h risckw.h 6502kw.h opkw.h rmac
        @echo
        @echo "Don't forget to bump the version number before commiting!"
        @echo
        @echo
        @echo "Don't forget to bump the version number before commiting!"
        @echo
@@ -61,6 +61,9 @@ kwtab.h : kwtab kwgen
 risckw.h : kwtab kwgen
        ./kwgen mr <risctab >risckw.h
 
 risckw.h : kwtab kwgen
        ./kwgen mr <risctab >risckw.h
 
+opkw.h : op.tab kwgen
+       ./kwgen mo <op.tab >opkw.h
+
 #
 # Build tools
 #
 #
 # Build tools
 #
@@ -120,6 +123,9 @@ mark.o : mark.c mark.h
 object.o : object.c object.h
        $(CC) $(CFLAGS) -c object.c
 
 object.o : object.c object.h
        $(CC) $(CFLAGS) -c object.c
 
+op.o : op.c op.h
+       $(CC) $(CFLAGS) -c op.c
+
 procln.o : procln.c procln.h
        $(CC) $(CFLAGS) -c procln.c
 
 procln.o : procln.c procln.h
        $(CC) $(CFLAGS) -c procln.c
 
@@ -151,41 +157,44 @@ clean:
 #
 # Dependencies
 #
 #
 # Dependencies
 #
-6502.o: 6502.c direct.h rmac.h symbol.h expr.h error.h mach.h procln.h \
token.h riscasm.h sect.h
+6502.o: 6502.c direct.h rmac.h symbol.h token.h expr.h error.h mach.h \
procln.h riscasm.h sect.h
 68kgen.o: 68kgen.c
 amode.o: amode.c amode.h rmac.h symbol.h error.h expr.h mach.h procln.h \
  token.h sect.h kwtab.h mntab.h parmode.h
 68kgen.o: 68kgen.c
 amode.o: amode.c amode.h rmac.h symbol.h error.h expr.h mach.h procln.h \
  token.h sect.h kwtab.h mntab.h parmode.h
-debug.o: debug.c debug.h rmac.h symbol.h amode.h direct.h mark.h sect.h \
- token.h
-direct.o: direct.c direct.h rmac.h symbol.h 6502.h amode.h error.h expr.h \
- listing.h mach.h macro.h mark.h procln.h token.h riscasm.h sect.h \
- kwtab.h fltpoint.h
-eagen.o: eagen.c eagen.h rmac.h symbol.h amode.h sect.h mark.h error.h \
- mach.h riscasm.h eagen0.c fltpoint.h
-error.o: error.c error.h rmac.h symbol.h token.h listing.h
-expr.o: expr.c expr.h rmac.h symbol.h direct.h error.h listing.h mach.h \
- procln.h token.h riscasm.h sect.h kwtab.h
+debug.o: debug.c debug.h rmac.h symbol.h amode.h direct.h token.h expr.h \
+ mark.h sect.h
+direct.o: direct.c direct.h rmac.h symbol.h token.h 6502.h amode.h \
+ error.h expr.h fltpoint.h listing.h mach.h macro.h mark.h procln.h \
+ riscasm.h sect.h kwtab.h
+eagen.o: eagen.c eagen.h rmac.h symbol.h amode.h error.h fltpoint.h \
+ mach.h mark.h riscasm.h sect.h token.h eagen0.c
+error.o: error.c error.h rmac.h symbol.h listing.h token.h
+expr.o: expr.c expr.h rmac.h symbol.h direct.h token.h error.h listing.h \
+ mach.h procln.h riscasm.h sect.h kwtab.h
+fltpoint.o: fltpoint.c fltpoint.h
 kwgen.o: kwgen.c
 listing.o: listing.c listing.h rmac.h symbol.h error.h procln.h token.h \
  sect.h version.h
 kwgen.o: kwgen.c
 listing.o: listing.c listing.h rmac.h symbol.h error.h procln.h token.h \
  sect.h version.h
-mach.o: mach.c mach.h rmac.h symbol.h amode.h direct.h eagen.h error.h \
procln.h token.h riscasm.h sect.h kwtab.h 68ktab.h
-macro.o: macro.c macro.h rmac.h symbol.h debug.h direct.h error.h expr.h \
listing.h procln.h token.h
+mach.o: mach.c mach.h rmac.h symbol.h amode.h direct.h token.h eagen.h \
error.h expr.h procln.h riscasm.h sect.h kwtab.h 68ktab.h
+macro.o: macro.c macro.h rmac.h symbol.h debug.h direct.h token.h error.h \
expr.h listing.h procln.h
 mark.o: mark.c mark.h rmac.h symbol.h error.h object.h riscasm.h sect.h
 mark.o: mark.c mark.h rmac.h symbol.h error.h object.h riscasm.h sect.h
-object.o: object.c object.h rmac.h symbol.h 6502.h error.h mark.h \
- riscasm.h sect.h
+object.o: object.c object.h rmac.h symbol.h 6502.h direct.h token.h \
+ error.h mark.h riscasm.h sect.h
+op.o: op.c op.h rmac.h symbol.h direct.h token.h error.h expr.h \
+ fltpoint.h mark.h procln.h riscasm.h sect.h
 procln.o: procln.c procln.h rmac.h symbol.h token.h 6502.h amode.h \
 procln.o: procln.c procln.h rmac.h symbol.h token.h 6502.h amode.h \
- direct.h error.h expr.h listing.h mach.h macro.h riscasm.h sect.h \
- kwtab.h mntab.h risckw.h 6502kw.h
-riscasm.o: riscasm.c riscasm.h rmac.h symbol.h amode.h direct.h error.h \
- expr.h mark.h procln.h token.h sect.h risckw.h kwtab.h
-rmac.o: rmac.c rmac.h symbol.h 6502.h debug.h direct.h error.h expr.h \
listing.h mark.h macro.h object.h procln.h token.h riscasm.h sect.h \
+ direct.h error.h expr.h listing.h mach.h macro.h op.h riscasm.h sect.h \
+ kwtab.h mntab.h risckw.h 6502kw.h opkw.h
+riscasm.o: riscasm.c riscasm.h rmac.h symbol.h amode.h direct.h token.h \
+ error.h expr.h mark.h procln.h sect.h risckw.h kwtab.h
+rmac.o: rmac.c rmac.h symbol.h 6502.h debug.h direct.h token.h error.h \
expr.h listing.h mark.h macro.h object.h procln.h riscasm.h sect.h \
  version.h
  version.h
-sect.o: sect.c sect.h rmac.h symbol.h 6502.h direct.h error.h expr.h \
listing.h mach.h mark.h riscasm.h token.h
+sect.o: sect.c sect.h rmac.h symbol.h 6502.h direct.h token.h error.h \
expr.h listing.h mach.h mark.h riscasm.h
 symbol.o: symbol.c symbol.h error.h rmac.h listing.h object.h procln.h \
  token.h
 token.o: token.c token.h rmac.h symbol.h direct.h error.h macro.h \
 symbol.o: symbol.c symbol.h error.h rmac.h listing.h object.h procln.h \
  token.h
 token.o: token.c token.h rmac.h symbol.h direct.h error.h macro.h \
diff --git a/mark.c b/mark.c
index 53eaf871854bb87bcd7e32f6a36e519ebcf8250f..ca7152e81bdf643f76a035715a661b4de1095e74 100644 (file)
--- a/mark.c
+++ b/mark.c
@@ -71,9 +71,9 @@ void StopMark(void)
 uint32_t MarkRelocatable(uint16_t section, uint32_t loc, uint16_t to, uint16_t flags, SYM * symbol)
 {
 #ifdef DEBUG_IMAGE_MARKING
 uint32_t MarkRelocatable(uint16_t section, uint32_t loc, uint16_t to, uint16_t flags, SYM * symbol)
 {
 #ifdef DEBUG_IMAGE_MARKING
-printf("MarkRelocatable: section=%i, loc=$%X, to=$%X, flags=$%x, symbol=$%X\n", section, loc, to, flags, symbol);
+printf("MarkRelocatable: section=%i, loc=$%X, to=$%X, flags=$%x, symbol=%p\n", section, loc, to, flags, symbol);
 if (symbol)
 if (symbol)
-       printf("      symbol->stype=$%02X, sattr=$%04X, sattre=$%08X, svalue=%i, sname=%s\n", symbol->stype, symbol->sattr, symbol->sattre, symbol->svalue, symbol->sname);
+       printf("      symbol->stype=$%02X, sattr=$%04X, sattre=$%08X, svalue=%li, sname=%s\n", symbol->stype, symbol->sattr, symbol->sattre, symbol->svalue, symbol->sname);
 #endif
 
        if ((mcalloc - mcused) < MIN_MARK_MEM)
 #endif
 
        if ((mcalloc - mcused) < MIN_MARK_MEM)
@@ -380,9 +380,13 @@ printf(" validsegment: raddr = $%08X\n", loc);
                        // This tells the linker to do a WORD relocation (otherwise it
                        // defaults to doing a LONG, throwing things off for WORD sized
                        // fixups)
                        // This tells the linker to do a WORD relocation (otherwise it
                        // defaults to doing a LONG, throwing things off for WORD sized
                        // fixups)
-                       if (!(w & MLONG))
+                       if (!(w & (MLONG | MQUAD)))
                                rflag |= 0x00000002;
 
                                rflag |= 0x00000002;
 
+                       // Tell the linker that the fixup is an OL QUAD data address
+                       if (w & MQUAD)
+                               rflag |= 0x00000004;
+
                        if (symbol != NULL)
                        {
                                // Deposit external reference
                        if (symbol != NULL)
                        {
                                // Deposit external reference
@@ -415,19 +419,31 @@ printf("  validsegment(3): rflag = $%08X\n", rflag);
                                if (w & (DATA | BSS))
                                {
                                        uint8_t * dp = objImage + BSDHDRSIZE + loc;
                                if (w & (DATA | BSS))
                                {
                                        uint8_t * dp = objImage + BSDHDRSIZE + loc;
+                                       uint32_t olBitsSave = 0;
 
                                        // Bump the start of the section if it's DATA (& not TEXT)
                                        if (from == DATA)
                                                dp += tsize;
 
                                        uint32_t diff = (rflag & 0x02 ? GETBE16(dp, 0) : GETBE32(dp, 0));
 
                                        // Bump the start of the section if it's DATA (& not TEXT)
                                        if (from == DATA)
                                                dp += tsize;
 
                                        uint32_t diff = (rflag & 0x02 ? GETBE16(dp, 0) : GETBE32(dp, 0));
+
+                                       // Special handling for OP (data addr) relocation...
+                                       if (rflag & 0x04)
+                                       {
+                                               olBitsSave = diff & 0x7FF;
+                                               diff = (diff & 0xFFFFF800) >> 8;
+                                       }
+
                                        DEBUG printf("diff=%uX ==> ", diff);
 #ifdef DEBUG_IMAGE_MARKING
                                        DEBUG printf("diff=%uX ==> ", diff);
 #ifdef DEBUG_IMAGE_MARKING
-printf("  validsegment(4): diff = $%08X --> ", diff);
+printf("  validsegment(4): diff = $%08X ", diff);
 #endif
                                        if (rflag & 0x01)
                                                diff = WORDSWAP32(diff);
 
 #endif
                                        if (rflag & 0x01)
                                                diff = WORDSWAP32(diff);
 
+#ifdef DEBUG_IMAGE_MARKING
+printf("(sect[TEXT].sloc=$%X) --> ", sect[TEXT].sloc);
+#endif
                                        diff += sect[TEXT].sloc;
 
                                        if (w == BSS)
                                        diff += sect[TEXT].sloc;
 
                                        if (w == BSS)
@@ -442,11 +458,21 @@ printf("  validsegment(4): diff = $%08X --> ", diff);
                                        //       thus leaving a naked semicolon afterwards to
                                        //       screw up the if/else structure. This is the price
                                        //       you pay when using macros pretending to be code.
                                        //       thus leaving a naked semicolon afterwards to
                                        //       screw up the if/else structure. This is the price
                                        //       you pay when using macros pretending to be code.
-                                       if (rflag & 0x02)
+                                       if (rflag & 0x02)               // WORD relocation
                                        {
                                                SETBE16(dp, 0, diff);
                                        }
                                        {
                                                SETBE16(dp, 0, diff);
                                        }
-                                       else
+                                       else if (rflag & 0x04)  // OP data address relocation
+                                       {
+                                               // We do it this way because we might have an offset
+                                               // that is not a multiple of 8 and thus we need this in
+                                               // place to prevent a bad address at link time. :-P As
+                                               // a consequence of this, the highest address we can
+                                               // have here is $1FFFF8.
+                                               diff = ((diff & 0x001FFFFF) << 11) | olBitsSave;
+                                               SETBE32(dp, 0, diff);
+                                       }
+                                       else                                    // LONG relocation
                                        {
                                                SETBE32(dp, 0, diff);
                                        }
                                        {
                                                SETBE32(dp, 0, diff);
                                        }
diff --git a/mark.h b/mark.h
index 5e97d8a290229ed346c121abf66442dd17be33dc..2415a80720783f779902314ea939b2eb46e08762 100644 (file)
--- a/mark.h
+++ b/mark.h
@@ -26,14 +26,15 @@ MCHUNK {
 
 #define MWORD        0x0000            // Marked word
 #define MLONG        0x0100            // Marked long
 
 #define MWORD        0x0000            // Marked word
 #define MLONG        0x0100            // Marked long
+#define MQUAD        0x0400            // Marked quad
 //This will have to be defined eventually. Might have to overhaul the mark
 //system as 8-bits doesn't seem to be enough, at least for a bitfield (which it
 //might not have to be, in which case it would be big enough...)
 //#define MQUAD        0x              // Marked quad word (TODO: merge with MDOUBLE?)
 #define MMOVEI       0x0200            // Mark RISC MOVEI instruction
 //This will have to be defined eventually. Might have to overhaul the mark
 //system as 8-bits doesn't seem to be enough, at least for a bitfield (which it
 //might not have to be, in which case it would be big enough...)
 //#define MQUAD        0x              // Marked quad word (TODO: merge with MDOUBLE?)
 #define MMOVEI       0x0200            // Mark RISC MOVEI instruction
-#define MDOUBLE      0x0400            // Marked double float
-#define MEXTEND      0x0800            // Marked extended float
-#define MSINGLE      0x0880            // Marked single float (TODO: merge with MLONG?)
+//#define MDOUBLE      0x0400          // Marked double float
+//#define MEXTEND      0x0800          // Marked extended float
+//#define MSINGLE      0x0880          // Marked single float (TODO: merge with MLONG?)
 #define MGLOBAL      0x0800            // Mark contains global
 #define MPCREL       0x1000            // Mark is PC-relative
 #define MCHEND       0x2000            // Indicates end of mark chunk
 #define MGLOBAL      0x0800            // Mark contains global
 #define MPCREL       0x1000            // Mark is PC-relative
 #define MCHEND       0x2000            // Indicates end of mark chunk
diff --git a/mntab b/mntab
index b65271a153eceb43bf8b21cfe9d2de4166cc676c..3355dfe2df2ba9fd33bd805e937357121cb34220 100644 (file)
--- a/mntab
+++ b/mntab
@@ -110,9 +110,10 @@ prgflags   57
 nofpu   65
 .opt    66
 opt     66
 nofpu   65
 .opt    66
 opt     66
+.objproc       67
 
 
-.if    500
-if     500
+.if            500
+if             500
 .else  501
 else   501
 .endc  502
 .else  501
 else   501
 .endc  502
@@ -120,7 +121,7 @@ endc        502
 .endif 502
 endif  502
 .iif   503
 .endif 502
 endif  502
 .iif   503
-iif    503
+iif            503
 .macro 504
 macro  504
 .endm  505
 .macro 504
 macro  504
 .endm  505
@@ -131,3 +132,4 @@ rept        506
 endr   507
 .exitm 510
 exitm  510
 endr   507
 .exitm 510
 exitm  510
+
diff --git a/op.c b/op.c
new file mode 100644 (file)
index 0000000..f0ec970
--- /dev/null
+++ b/op.c
@@ -0,0 +1,487 @@
+//
+// Jaguar Object Processor assembler
+//
+// by James Hammons
+// (C) 2018 Underground Software
+//
+
+#include "op.h"
+#include "direct.h"
+#include "error.h"
+#include "expr.h"
+#include "fltpoint.h"
+#include "mark.h"
+#include "procln.h"
+#include "riscasm.h"
+#include "rmac.h"
+#include "sect.h"
+#include "token.h"
+
+// Macros to help define things (though largely unnecessary for this assembler)
+#define BITMAP    3100
+#define SCBITMAP  3101
+#define GPUOBJ    3102
+#define BRANCH    3103
+#define STOP      3104
+#define NOP       3105
+#define JUMP      3106
+
+// Function prototypes
+int HandleBitmap(void);
+int HandleScaledBitmap(void);
+int HandleGPUObject(void);
+int HandleBranch(void);
+int HandleStop(void);
+int HandleNOP(void);
+int HandleJump(void);
+
+// OP assembler vars.
+static uint8_t lastObjType;
+static uint32_t lastSloc;
+static char scratchbuf[4096];
+static TOKEN fixupExpr[4] = { CONST, 0, 0, ENDEXPR };
+//static PTR fixupPtr = { .tk = (fixupExpr + 1) };             // C99 \o/
+static PTR fixupPtr = { (uint8_t *)(fixupExpr + 1) };  // meh, it works
+
+
+//
+// The main Object Processor assembler. Basically just calls the sub functions
+// to generate the appropriate code.
+//
+int GenerateOPCode(int state)
+{
+       if (!robjproc)
+               return error("opcode only valid in OP mode");
+
+       switch (state)
+       {
+       case BITMAP:
+               return HandleBitmap();
+       case SCBITMAP:
+               return HandleScaledBitmap();
+       case GPUOBJ:
+               return HandleGPUObject();
+       case BRANCH:
+               return HandleBranch();
+       case STOP:
+               return HandleStop();
+       case NOP:
+               return HandleNOP();
+       case JUMP:
+               return HandleJump();
+       }
+
+       return error("unknown OP opcode");
+}
+
+
+static inline void GetSymbolUCFromTokenStream(char * s)
+{
+       strcpy(s, string[tok[1]]);
+       strtoupper(s);
+       tok += 2;
+}
+
+
+static inline uint64_t CheckFlags(char * s)
+{
+       GetSymbolUCFromTokenStream(s);
+
+       if (strcmp(scratchbuf, "REFLECT") == 0)
+               return 0x01;
+       else if (strcmp(scratchbuf, "RMW") == 0)
+               return 0x02;
+       else if (strcmp(scratchbuf, "TRANS") == 0)
+               return 0x04;
+       else if (strcmp(scratchbuf, "RELEASE") == 0)
+               return 0x08;
+       return 0;
+}
+
+
+//
+// Define a bitmap object
+// Form: bitmap <data>, <xloc>, <yloc>, <dwidth>, <iwidth>, <iheight>, <bpp>,
+//              <pallete idx>, <flags>, <firstpix>, <pitch>
+//
+int HandleBitmap(void)
+{
+       uint64_t xpos = 0;
+       uint64_t ypos = 0;
+       uint64_t iheight = 0;
+       uint64_t dwidth = 0;
+       uint64_t iwidth = 0;
+       uint64_t bpp = 0;
+       uint64_t index = 0;
+       uint64_t flags = 0;
+       uint64_t firstpix = 0;
+       uint64_t pitch = 1;
+
+       uint64_t eval;
+       uint16_t eattr;
+       SYM * esym = 0;
+
+       if ((orgaddr & 0x0F) != 0)
+       {
+               warn("bitmap not on double phrase boundary");
+
+               // Fixup org address (by emitting a NOP)...
+               HandleNOP();
+
+               // We don't need to do a fixup here, because we're guaranteed that the
+               // last object, if it was a scaled bitmap *or* regular bitmap, will
+               // already be on the correct boundary, so we won't have to fix it up.
+       }
+
+       if (expr(exprbuf, &eval, &eattr, &esym) != OK)
+               return ERROR;
+
+       if (!(eattr & DEFINED))
+               AddFixup(FU_QUAD | FU_OBJDATA, sloc, exprbuf);
+       else if (eattr & TDB)
+               MarkRelocatable(cursect, sloc, (eattr & TDB), MQUAD, NULL);
+
+       uint64_t dataAddr = eval & 0xFFFFF8;
+       uint64_t linkAddr = (orgaddr + 16) & 0x3FFFF8;
+
+       uint64_t * vars[10] = { &xpos, &ypos, &dwidth, &iwidth, &iheight, &bpp, &index, 0, &firstpix, &pitch };
+
+       for(int i=0; i<10; i++)
+       {
+               // If there are less than 10 arguments after the data address, use
+               // defaults for the rest of them
+               // N.B.: Should there be a default minimum # of args? Like the first 5?
+               if (tok[0] == EOL)
+                       break;
+
+               CHECK_COMMA;
+
+               if (i != 7)
+               {
+                       if (expr(exprbuf, &eval, &eattr, &esym) != OK)
+                               return ERROR;
+
+                       if (!(eattr & DEFINED))
+                               return error("bad expression");
+
+                       *vars[i] = eval;
+               }
+               else
+               {
+                       // Handle FLAGs. Can have at most four.
+                       for(int j=0; j<4; j++)
+                       {
+                               if (tok[0] != SYMBOL)
+                                       return error("missing REFLECT, RMW, TRANS, and/or RELEASE");
+
+                               flags |= CheckFlags(scratchbuf);
+
+                               // Break out if no more symbols...
+                               if (tok[0] != SYMBOL)
+                                       break;
+                       }
+               }
+       }
+
+       at_eol();
+
+       uint64_t p1 = 0x00 | ((ypos * 2) << 3) | (iheight << 14) | (linkAddr << 21) | (dataAddr << 40);
+       uint64_t p2 = xpos | (bpp << 12) | (pitch << 15) | (dwidth << 18) | (iwidth << 28) | (index << 38) | (flags << 45) | (firstpix << 49);
+
+       lastSloc = sloc;
+       lastObjType = 0;
+       D_quad(p1);
+       D_quad(p2);
+
+       return OK;
+}
+
+
+//
+// Define a scaled bitmap object
+// Form: scbitmap <data>, <xloc>, <yloc>, <dwidth>, <iwidth>, <iheight>,
+//                <xscale>, <yscale>, <remainder>, <bpp>, <pallete idx>,
+//                <flags>, <firstpix>, <pitch>
+//
+int HandleScaledBitmap(void)
+{
+       uint64_t xpos = 0;
+       uint64_t ypos = 0;
+       uint64_t iheight = 0;
+       uint64_t dwidth = 0;
+       uint64_t iwidth = 0;
+       uint64_t bpp = 0;
+       uint64_t index = 0;
+       uint64_t flags = 0;
+       uint64_t firstpix = 0;
+       uint64_t pitch = 1;
+       uint64_t xscale = 0;
+       uint64_t yscale = 0;
+       uint64_t remainder = 0;
+
+       uint64_t eval;
+       uint16_t eattr;
+       SYM * esym = 0;
+
+       if ((orgaddr & 0x1F) != 0)
+       {
+               warn("scaled bitmap not on quad phrase boundary");
+
+               // We only have to do a fixup here if the previous object was a bitmap,
+               // as it can live on a 16-byte boundary while scaled bitmaps can't. If
+               // the previous object was a scaled bitmap, it is guaranteed to have
+               // been aligned, therefore no fixup is necessary.
+               if (lastObjType == 0)
+               {
+                       *fixupPtr.u64 = (orgaddr + 0x18) & 0xFFFFFFE0;
+                       AddFixup(FU_QUAD | FU_OBJLINK, lastSloc, fixupExpr);
+               }
+
+               switch (orgaddr & 0x1F)
+               {
+               case 0x08: HandleNOP(); // Emit 3 NOPs
+               case 0x10: HandleNOP(); // Emit 2 NOPs
+               case 0x18: HandleNOP(); // Emit 1 NOP
+               }
+       }
+
+       if (expr(exprbuf, &eval, &eattr, &esym) != OK)
+               return ERROR;
+
+       if (!(eattr & DEFINED))
+               AddFixup(FU_QUAD | FU_OBJDATA, sloc, exprbuf);
+       else if (eattr & TDB)
+               MarkRelocatable(cursect, sloc, (eattr & TDB), MQUAD, NULL);
+
+       uint64_t dataAddr = eval & 0xFFFFF8;
+       uint64_t linkAddr = (orgaddr + 32) & 0x3FFFF8;
+
+       uint64_t * vars[13] = { &xpos, &ypos, &dwidth, &iwidth, &iheight, &xscale, &yscale, &remainder, &bpp, &index, 0, &firstpix, &pitch };
+
+       for(int i=0; i<13; i++)
+       {
+               // If there are less than 13 arguments after the data address, use
+               // defaults for the rest of them
+               // N.B.: Should there be a default minimum # of args? Like the first 5?
+               if (tok[0] == EOL)
+                       break;
+
+               CHECK_COMMA;
+
+               if (i != 10)
+               {
+                       if (expr(exprbuf, &eval, &eattr, &esym) != OK)
+                               return ERROR;
+
+                       if (!(eattr & DEFINED))
+                               return error("bad expression");
+
+                       // Handle 3.5 fixed point nums (if any)...
+                       if ((i >= 5) && (i <= 7))
+                       {
+                               if (eattr & FLOAT)                      // Handle floats
+                               {
+//                                     PTR p = { .u64 = &eval };               // C99 \o/
+                                       PTR p = { (uint8_t *)&eval };   // Meh, it works
+                                       eval = DoubleToFixedPoint(*p.dp, 3, 5);
+                               }
+                               else
+                                       eval <<= 5;                             // Otherwise, it's just an int...
+                       }
+
+                       *vars[i] = eval;
+               }
+               else
+               {
+                       // Handle FLAGs. Can have at most four.
+                       for(int j=0; j<4; j++)
+                       {
+                               if (tok[0] != SYMBOL)
+                                       return error("missing REFLECT, RMW, TRANS, and/or RELEASE");
+
+                               flags |= CheckFlags(scratchbuf);
+
+                               // Break out if no more symbols...
+                               if (tok[0] != SYMBOL)
+                                       break;
+                       }
+               }
+       }
+
+       at_eol();
+
+       uint64_t p1 = 0x01 | ((ypos * 2) << 3) | (iheight << 14) | (linkAddr << 21) | (dataAddr << 40);
+       uint64_t p2 = xpos | (bpp << 12) | (pitch << 15) | (dwidth << 18) | (iwidth << 28) | (index << 38) | (flags << 45) | (firstpix << 49);
+       uint64_t p3 = (xscale & 0xFF) | (yscale & 0xFF) << 8 | (remainder & 0xFF) << 16;
+
+       lastSloc = sloc;
+       lastObjType = 1;
+       D_quad(p1);
+       D_quad(p2);
+       D_quad(p3);
+       D_quad(0LL);
+
+       return OK;
+}
+
+
+//
+// Insert GPU object
+// Form: gpuobj <line #>, <userdata> (bits 14-63 of this object)
+//
+int HandleGPUObject(void)
+{
+       uint64_t eval;
+       uint16_t eattr;
+       SYM * esym = 0;
+
+       if (expr(exprbuf, &eval, &eattr, &esym) != OK)
+               return ERROR;
+
+       if (!(eattr & DEFINED))
+               return error("bad expression in y position");
+
+       uint64_t ypos = eval;
+
+       CHECK_COMMA;
+
+       if (expr(exprbuf, &eval, &eattr, &esym) != OK)
+               return ERROR;
+
+       if (!(eattr & DEFINED))
+               return error("bad expression in data");
+
+       at_eol();
+
+       uint64_t p1 = 0x02 | ((ypos * 2) << 3) | (eval << 14);
+
+       lastObjType = 2;
+       D_quad(p1);
+
+       return OK;
+}
+
+
+//
+// Insert a branch object
+// Form: branch VC <condition (<, =, >)> <line #>, <link addr>
+//       branch OPFLAG, <link addr>
+//       branch SECHALF, <link addr>
+//
+int HandleBranch(void)
+{
+       char missingKeyword[] = "missing VC, OPFLAG, or SECHALF in branch";
+       uint32_t cc = 0;
+       uint32_t ypos = 0;
+       uint64_t eval;
+       uint16_t eattr;
+       SYM * esym = 0;
+
+       if (tok[0] != SYMBOL)
+               return error(missingKeyword);
+
+       GetSymbolUCFromTokenStream(scratchbuf);
+
+       if (strcmp(scratchbuf, "VC") == 0)
+       {
+               switch (*tok++)
+               {
+               case '=': cc = 0; break;
+               case '<': cc = 1; break;
+               case '>': cc = 2; break;
+               default:
+                       return error("missing '<', '>', or '='");
+               }
+
+               if (expr(exprbuf, &eval, &eattr, &esym) != OK)
+                       return ERROR;
+
+               if (!(eattr & DEFINED))
+                       return error("bad expression");
+
+               ypos = (uint32_t)eval;
+       }
+       else if (strcmp(scratchbuf, "OPFLAG") == 0)
+               cc = 3;
+       else if (strcmp(scratchbuf, "SECHALF") == 0)
+               cc = 4;
+       else
+               return error(missingKeyword);
+
+       CHECK_COMMA;
+
+       if (expr(exprbuf, &eval, &eattr, &esym) != OK)
+               return ERROR;
+
+       if (!(eattr & DEFINED))
+               AddFixup(FU_QUAD | FU_OBJLINK, sloc, exprbuf);
+
+       at_eol();
+
+       uint64_t p1 = 0x03 | (cc << 14) | ((ypos * 2) << 3) | ((eval & 0x3FFFF8) << 21);
+
+       lastObjType = 3;
+       D_quad(p1);
+
+       return OK;
+}
+
+
+//
+// Insert a stop object
+// Form: stop
+//
+int HandleStop(void)
+{
+       lastObjType = 4;
+       D_quad(4LL);
+
+       return OK;
+}
+
+
+//
+// Insert a phrase sized "NOP" in the object list (psuedo-op)
+// Form: nop
+//
+int HandleNOP(void)
+{
+       uint64_t eval = (orgaddr + 8) & 0x3FFFF8;
+       // This is "branch if VC > 2047". Branch addr is next phrase, so either way
+       // it will pass by this phrase.
+       uint64_t p1 = 0x03 | (2 << 14) | (0x7FF << 3) | (eval << 21);
+
+       lastObjType = 3;
+       D_quad(p1);
+
+       return OK;
+}
+
+
+//
+// Insert an unconditional jump in the object list (psuedo-op)
+// Form: jump <link addr>
+//
+int HandleJump(void)
+{
+       uint64_t eval;
+       uint16_t eattr;
+       SYM * esym = 0;
+
+       if (expr(exprbuf, &eval, &eattr, &esym) != OK)
+               return ERROR;
+
+       if (!(eattr & DEFINED))
+               AddFixup(FU_QUAD | FU_OBJLINK, sloc, exprbuf);
+
+       at_eol();
+
+       // This is "branch if VC < 2047", which pretty much guarantees the branch.
+       uint64_t p1 = 0x03 | (1 << 14) | (0x7FF << 3) | ((eval & 0x3FFFF8) << 21);
+
+       lastObjType = 3;
+       D_quad(p1);
+
+       return OK;
+}
+
diff --git a/op.h b/op.h
new file mode 100644 (file)
index 0000000..f7c31b8
--- /dev/null
+++ b/op.h
@@ -0,0 +1,15 @@
+//
+// Object Processor assembler
+//
+// by James Hammons
+// (C) 2018 Underground Software
+//
+
+#ifndef __OP_H__
+#define __OP_H__
+
+// Exported functions
+int GenerateOPCode(int);
+
+#endif // __OP_H__
+
diff --git a/op.tab b/op.tab
new file mode 100644 (file)
index 0000000..cdbc8eb
--- /dev/null
+++ b/op.tab
@@ -0,0 +1,11 @@
+#
+#  Jaguar Object Processor mnemonics
+#
+bitmap    3100
+scbitmap  3101
+gpuobj    3102
+branch    3103
+stop      3104
+nop       3105
+jump      3106
+
index addff0462d8247e6cdc02632f88939e75f531b3e..eb7428121e8b2b4d1cd44576afd0f8449c711d11 100644 (file)
--- a/procln.c
+++ b/procln.c
@@ -15,6 +15,7 @@
 #include "listing.h"
 #include "mach.h"
 #include "macro.h"
 #include "listing.h"
 #include "mach.h"
 #include "macro.h"
+#include "op.h"
 #include "riscasm.h"
 #include "sect.h"
 #include "symbol.h"
 #include "riscasm.h"
 #include "sect.h"
 #include "symbol.h"
 #define DECL_MP                                        // Include 6502 keyword state machine tables
 #include "6502kw.h"
 
 #define DECL_MP                                        // Include 6502 keyword state machine tables
 #include "6502kw.h"
 
+#define DEF_MO                                 // Include OP keyword definitions
+#define DECL_MO                                        // Include OP keyword state machine tables
+#include "opkw.h"
+
 IFENT * ifent;                                 // Current ifent
 static IFENT ifent0;                   // Root ifent
 IFENT * f_ifent;                               // Freelist of ifents
 IFENT * ifent;                                 // Current ifent
 static IFENT ifent0;                   // Root ifent
 IFENT * f_ifent;                               // Freelist of ifents
@@ -659,6 +664,38 @@ When checking to see if it's already been equated, issue a warning.
                }
        }
 
                }
        }
 
+       // If we are in OP mode and still in need of a mnemonic then search for one
+       if (robjproc && ((state < 0) || (state >= 1000)))
+       {
+               for(state=0, p=opname; state>=0;)
+               {
+                       j = mobase[state] + (int)tolowertab[*p];
+
+                       // Reject, character doesn't match
+                       if (mocheck[j] != state)
+                       {
+                               state = -1;                                     // No match
+                               break;
+                       }
+
+                       // Must accept or reject at EOS
+                       if (!*++p)
+                       {
+                               state = moaccept[j];            // (-1 on no terminal match)
+                               break;
+                       }
+
+                       state = motab[j];
+               }
+
+               // Call OP code generator if we found a mnemonic
+               if (state >= 3100)
+               {
+                       GenerateOPCode(state);
+                       goto loop;
+               }
+       }
+
        // Invoke macro or complain about bad mnemonic
        if (state < 0)
        {
        // Invoke macro or complain about bad mnemonic
        if (state < 0)
        {
index d595ebc96257f275a907febb33e63b9cebcf81d5..0b09bf18ba3c641fa15189cf70cdd32d2c6d439b 100644 (file)
--- a/riscasm.c
+++ b/riscasm.c
@@ -13,6 +13,7 @@
 #include "expr.h"
 #include "mark.h"
 #include "procln.h"
 #include "expr.h"
 #include "mark.h"
 #include "procln.h"
+#include "rmac.h"
 #include "sect.h"
 #include "token.h"
 
 #include "sect.h"
 #include "token.h"
 
@@ -134,16 +135,6 @@ static const char * malformErr[] = {
 };
 
 
 };
 
 
-//
-// Convert a string to uppercase
-//
-static void strtoupper(char * s)
-{
-       while (*s)
-               *s++ &= 0xDF;
-}
-
-
 //
 // Function to return "malformed expression" error
 // This is done mainly to remove a bunch of GOTO statements in the parser
 //
 // Function to return "malformed expression" error
 // This is done mainly to remove a bunch of GOTO statements in the parser
index 560726cce8591e62566e92ddde1dc2938f1333f6..91376dcdfc8640c22af21672c4431a8118213a48 100644 (file)
--- a/riscasm.h
+++ b/riscasm.h
@@ -32,7 +32,7 @@
 #define GPUONLY     0x4000             // Opcode is for the GPU Only
 #define DSPONLY     0x8000             // Opcode is for the DSP Only
 
 #define GPUONLY     0x4000             // Opcode is for the GPU Only
 #define DSPONLY     0x8000             // Opcode is for the DSP Only
 
-#define CHECK_COMMA  if(*tok++ != ',') { error(comma_error); return(ERROR); }
+#define CHECK_COMMA  if (*tok++ != ',') { return error(comma_error); }
 
 // Globals, externals etc
 extern unsigned orgactive;
 
 // Globals, externals etc
 extern unsigned orgactive;
diff --git a/rmac.c b/rmac.c
index 21e1fb8c0d0be275166e52a39c44a18c3c879d7f..199cff759e18ba3aea3c64aa25eb39fce21051a5 100644 (file)
--- a/rmac.c
+++ b/rmac.c
@@ -40,6 +40,7 @@ int debug;                                            // [1..9] Enable debugging levels
 int err_flag;                                  // '-e' specified
 int err_fd;                                            // File to write error messages to
 int rgpu, rdsp;                                        // Assembling Jaguar GPU or DSP code
 int err_flag;                                  // '-e' specified
 int err_fd;                                            // File to write error messages to
 int rgpu, rdsp;                                        // Assembling Jaguar GPU or DSP code
+int robjproc;                                  // Assembling Jaguar Object Processor code
 int dsp56001;                                  // Assembling DSP 56001 code
 int list_fd;                                   // File to write listing to
 int regbank;                                   // RISC register bank
 int dsp56001;                                  // Assembling DSP 56001 code
 int list_fd;                                   // File to write listing to
 int regbank;                                   // RISC register bank
@@ -55,6 +56,16 @@ int activecpu = CPU_68000;           // Active 68k CPU (68000 by default)
 int activefpu = FPU_NONE;              // Active FPU (none by default)
 
 
 int activefpu = FPU_NONE;              // Active FPU (none by default)
 
 
+//
+// Convert a string to uppercase
+//
+void strtoupper(char * s)
+{
+       while (*s)
+               *s++ &= 0xDF;
+}
+
+
 //
 // Manipulate file extension.
 //
 //
 // Manipulate file extension.
 //
@@ -271,6 +282,7 @@ int Process(int argc, char ** argv)
        err_flag = 0;                                   // Initialise error flag
        rgpu = 0;                                               // Initialise GPU assembly flag
        rdsp = 0;                                               // Initialise DSP assembly flag
        err_flag = 0;                                   // Initialise error flag
        rgpu = 0;                                               // Initialise GPU assembly flag
        rdsp = 0;                                               // Initialise DSP assembly flag
+       robjproc = 0;                                   // Initialise OP assembly flag
        lsym_flag = 1;                                  // Include local symbols in object file
        regbank = BANK_N;                               // No RISC register bank specified
        orgactive = 0;                                  // Not in RISC org section
        lsym_flag = 1;                                  // Include local symbols in object file
        regbank = BANK_N;                               // No RISC register bank specified
        orgactive = 0;                                  // Not in RISC org section
diff --git a/rmac.h b/rmac.h
index 07d6ed162508b4dcf3f93b644ba5ebeab5d16e99..f282460176f9cdd1ed547ffd38d310245a7567f9 100644 (file)
--- a/rmac.h
+++ b/rmac.h
@@ -284,6 +284,7 @@ enum
 extern int verb_flag;
 extern int debug;
 extern int rgpu, rdsp;
 extern int verb_flag;
 extern int debug;
 extern int rgpu, rdsp;
+extern int robjproc;
 extern int dsp56001;
 extern int err_flag;
 extern int err_fd;
 extern int dsp56001;
 extern int err_flag;
 extern int err_fd;
@@ -306,6 +307,7 @@ extern int activecpu;
 extern int activefpu;
 
 // Exported functions
 extern int activefpu;
 
 // Exported functions
+void strtoupper(char * s);
 char * fext(char *, char *, int);
 int nthpath(char *, int, char *);
 int ParseOptimization(char * optstring);
 char * fext(char *, char *, int);
 int nthpath(char *, int, char *);
 int ParseOptimization(char * optstring);
diff --git a/sect.c b/sect.c
index 2269403e2b68e3426e843a9cb0569d5aa3b58637..5d7fb4ad22b31b87efa3784c897533f63a17519d 100644 (file)
--- a/sect.c
+++ b/sect.c
@@ -290,7 +290,7 @@ int AddFixup(uint32_t attr, uint32_t loc, TOKEN * fexpr)
 
        DEBUG { printf("AddFixup: sno=%u, l#=%u, attr=$%X, loc=$%X, expr=%p, sym=%p, org=$%X\n", cursect, fixup->lineno, fixup->attr, fixup->loc, (void *)fixup->expr, (void *)fixup->symbol, fixup->orgaddr);
                if (symbol != NULL)
 
        DEBUG { printf("AddFixup: sno=%u, l#=%u, attr=$%X, loc=$%X, expr=%p, sym=%p, org=$%X\n", cursect, fixup->lineno, fixup->attr, fixup->loc, (void *)fixup->expr, (void *)fixup->symbol, fixup->orgaddr);
                if (symbol != NULL)
-                       printf("          name: %s, value: $lX\n", symbol->sname, symbol->svalue);
+                       printf("          name: %s, value: $%lX\n", symbol->sname, symbol->svalue);
        }
 
        return 0;
        }
 
        return 0;
@@ -679,9 +679,8 @@ int ResolveFixups(int sno)
 
                        break;
 
 
                        break;
 
-               // Fixup LONG forward references;
-               // the long could be unaligned in the section buffer, so be careful
-               // (again).
+               // Fixup LONG forward references; the long could be unaligned in the
+               // section buffer, so be careful (again).
                case FU_LONG:
                        flags = MLONG;
 
                case FU_LONG:
                        flags = MLONG;
 
@@ -702,6 +701,44 @@ int ResolveFixups(int sno)
                        SETBE32(locp, 0, eval);
                        break;
 
                        SETBE32(locp, 0, eval);
                        break;
 
+               // Fixup QUAD forward references
+               // Need to add flags for OP uses... [DONE]
+               case FU_QUAD:
+                       // If the symbol is undefined, make sure to pass the symbol in
+                       // to the MarkRelocatable() function.
+/*                     if (!(eattr & DEFINED))
+                               MarkRelocatable(sno, loc, 0, MQUAD, esym);
+                       else if (tdb)
+                               MarkRelocatable(sno, loc, tdb, MQUAD, NULL);//*/
+
+                       if (w & FU_OBJLINK)
+                       {
+                               uint64_t quad = GETBE64(locp, 0);
+                               uint64_t addr = eval;
+
+                               if (fup->orgaddr)
+                                       addr = fup->orgaddr;
+
+//printf("sect.c: FU_OBJLINK quad=%016lX, addr=%016lX ", quad, addr);
+
+                               eval = (quad & 0xFFFFFC0000FFFFFFLL) | ((addr & 0x3FFFF8) << 21);
+//printf("(%016lX)\n", eval);
+                       }
+                       else if (w & FU_OBJDATA)
+                       {
+                               uint64_t quad = GETBE64(locp, 0);
+                               uint64_t addr = eval;
+
+                               if (fup->orgaddr)
+                                       addr = fup->orgaddr;
+
+                               eval = (quad & 0x000007FFFFFFFFFFLL) | ((addr & 0xFFFFF8) << 40);
+                       }
+
+                       SETBE64(locp, 0, eval);
+//printf("(%016lX)\n", eval);
+                       break;
+
                // Fixup a 3-bit "QUICK" reference in bits 9..1
                // (range of 1..8) in a word. [Really bits 1..3 in a byte.]
                case FU_QUICK:
                // Fixup a 3-bit "QUICK" reference in bits 9..1
                // (range of 1..8) in a word. [Really bits 1..3 in a byte.]
                case FU_QUICK:
diff --git a/sect.h b/sect.h
index dc5e16751e6f06c7c537ee277be6b192ffc3f118..11ddfd4caf4e2b3cba51036b313d062bd5767f8c 100644 (file)
--- a/sect.h
+++ b/sect.h
@@ -76,6 +76,7 @@
 #define FU_6BRA      0x0007            // Fixup 6502-format branch offset
 #define FU_BYTEH     0x0008            // Fixup 6502 high byte of immediate word
 #define FU_BYTEL     0x0009            // Fixup 6502 low byte of immediate word
 #define FU_6BRA      0x0007            // Fixup 6502-format branch offset
 #define FU_BYTEH     0x0008            // Fixup 6502 high byte of immediate word
 #define FU_BYTEL     0x0009            // Fixup 6502 low byte of immediate word
+#define FU_QUAD      0x000A            // Fixup quad-word (8 bytes)
 
 #define FU_SEXT      0x0010            // Ok to sign extend
 #define FU_PCREL     0x0020            // Subtract PC first
 
 #define FU_SEXT      0x0010            // Ok to sign extend
 #define FU_PCREL     0x0020            // Subtract PC first
 #define FU_DONE      0x8000            // Fixup has been done
 
 // FPU fixups
 #define FU_DONE      0x8000            // Fixup has been done
 
 // FPU fixups
-#define FU_FLOATSING 0x000A            // Fixup 32-bit float
-#define FU_FLOATDOUB 0x000B            // Fixup 64-bit float
-#define FU_FLOATEXT  0x000C            // Fixup 96-bit float
+#define FU_FLOATSING 0x000B            // Fixup 32-bit float
+#define FU_FLOATDOUB 0x000C            // Fixup 64-bit float
+#define FU_FLOATEXT  0x000D            // Fixup 96-bit float
+
+// OP fixups
+#define FU_OBJLINK   0x10000   // Fixup OL link addr (bits 24-42, drop last 3)
+#define FU_OBJDATA   0x20000   // Fixup OL data addr (bits 43-63, drop last 3)
+
 
 // Chunks are used to hold generated code and fixup records
 #define CHUNK  struct _chunk
 
 // Chunks are used to hold generated code and fixup records
 #define CHUNK  struct _chunk
index b56b49a5ff03504515436c21958f753015b2812d..66de9ac75f5c3344fac09688ccc5c6a681cd730f 100644 (file)
--- a/version.h
+++ b/version.h
@@ -14,8 +14,8 @@
 // Release Information
 
 #define MAJOR   1              // Major version number
 // Release Information
 
 #define MAJOR   1              // Major version number
-#define MINOR   12             // Minor version number
-#define PATCH   5              // Patch release number
+#define MINOR   13             // Minor version number
+#define PATCH   0              // Patch release number
 
 #endif // __VERSION_H__
 
 
 #endif // __VERSION_H__