mirror of http://shamusworld.gotdns.org/git/rmac
Added Jaguar Object Processor assembler.
Rationale for this and how it works can be found in docs/note-on-the-op-assembler.txt. Version now at 1.13.0.
This commit is contained in:
parent
ae528e6fdb
commit
261f8d9198
|
@ -2,6 +2,8 @@
|
|||
68kgen.o
|
||||
68ktab.h
|
||||
68kmn
|
||||
6502kw.h
|
||||
opkw.h
|
||||
*.o
|
||||
*~
|
||||
kwtab.h
|
||||
|
|
71
direct.c
71
direct.c
|
@ -79,6 +79,7 @@ int d_cstruct(void);
|
|||
int d_prgflags(void);
|
||||
int d_opt(void);
|
||||
int d_dsp(void);
|
||||
int d_objproc(void);
|
||||
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_opt, // 58 .opt
|
||||
d_opt, // 66 .opt
|
||||
d_objproc, // 67 .objproc
|
||||
};
|
||||
|
||||
|
||||
|
@ -216,8 +218,8 @@ int d_org(void)
|
|||
{
|
||||
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)
|
||||
{
|
||||
|
@ -225,7 +227,7 @@ int d_org(void)
|
|||
return ERROR;
|
||||
}
|
||||
|
||||
if (rgpu | rdsp)
|
||||
if (rgpu | rdsp | robjproc)
|
||||
{
|
||||
orgaddr = address;
|
||||
orgactive = 1;
|
||||
|
@ -1066,9 +1068,6 @@ int d_dc(WORD siz)
|
|||
uint16_t tdb = eattr & TDB;
|
||||
uint16_t defined = eattr & DEFINED;
|
||||
|
||||
if ((challoc - ch_size) < 4)
|
||||
chcheck(4);
|
||||
|
||||
switch (siz)
|
||||
{
|
||||
case SIZB:
|
||||
|
@ -1136,6 +1135,7 @@ int d_dc(WORD siz)
|
|||
|
||||
D_long(eval);
|
||||
}
|
||||
|
||||
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...)
|
||||
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
|
||||
|
@ -1158,8 +1168,9 @@ int d_dc(WORD siz)
|
|||
}
|
||||
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;
|
||||
|
@ -1180,8 +1191,9 @@ int d_dc(WORD siz)
|
|||
}
|
||||
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;
|
||||
|
@ -1204,8 +1216,9 @@ int d_dc(WORD siz)
|
|||
}
|
||||
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;
|
||||
|
@ -1483,7 +1496,7 @@ int d_nlist(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;
|
||||
|
@ -1601,6 +1614,7 @@ int d_gpu(void)
|
|||
|
||||
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;
|
||||
}
|
||||
|
@ -1626,6 +1640,7 @@ int d_dsp(void)
|
|||
|
||||
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;
|
||||
}
|
||||
|
@ -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...]
|
||||
//
|
||||
|
|
|
@ -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
|
||||
|
15
eagen0.c
15
eagen0.c
|
@ -214,8 +214,9 @@ int eaNgen(WORD siz)
|
|||
// 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
|
||||
|
@ -238,8 +239,9 @@ int eaNgen(WORD siz)
|
|||
// 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;
|
||||
|
@ -258,8 +260,9 @@ int eaNgen(WORD siz)
|
|||
// 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;
|
||||
|
|
23
fltpoint.c
23
fltpoint.c
|
@ -14,6 +14,7 @@
|
|||
#include "fltpoint.h"
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
//
|
||||
|
||||
#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[]);
|
||||
|
||||
uint64_t DoubleToFixedPoint(double d, int intBits, int fracBits);
|
||||
|
||||
#endif // __FLTPOINT_H__
|
||||
|
||||
|
|
67
makefile
67
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
|
||||
|
||||
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
|
||||
#
|
||||
|
||||
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
|
||||
|
@ -61,6 +61,9 @@ kwtab.h : kwtab kwgen
|
|||
risckw.h : kwtab kwgen
|
||||
./kwgen mr <risctab >risckw.h
|
||||
|
||||
opkw.h : op.tab kwgen
|
||||
./kwgen mo <op.tab >opkw.h
|
||||
|
||||
#
|
||||
# Build tools
|
||||
#
|
||||
|
@ -120,6 +123,9 @@ mark.o : mark.c mark.h
|
|||
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
|
||||
|
||||
|
@ -151,41 +157,44 @@ clean:
|
|||
#
|
||||
# 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
|
||||
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
|
||||
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
|
||||
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 \
|
||||
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
|
||||
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 \
|
||||
|
|
38
mark.c
38
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
|
||||
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)
|
||||
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)
|
||||
|
@ -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)
|
||||
if (!(w & MLONG))
|
||||
if (!(w & (MLONG | MQUAD)))
|
||||
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
|
||||
|
@ -415,19 +419,31 @@ printf(" validsegment(3): rflag = $%08X\n", rflag);
|
|||
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));
|
||||
|
||||
// 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
|
||||
printf(" validsegment(4): diff = $%08X --> ", diff);
|
||||
printf(" validsegment(4): diff = $%08X ", 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)
|
||||
|
@ -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.
|
||||
if (rflag & 0x02)
|
||||
if (rflag & 0x02) // WORD relocation
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
|
7
mark.h
7
mark.h
|
@ -26,14 +26,15 @@ MCHUNK {
|
|||
|
||||
#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
|
||||
#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
|
||||
|
|
8
mntab
8
mntab
|
@ -110,9 +110,10 @@ prgflags 57
|
|||
nofpu 65
|
||||
.opt 66
|
||||
opt 66
|
||||
.objproc 67
|
||||
|
||||
.if 500
|
||||
if 500
|
||||
.if 500
|
||||
if 500
|
||||
.else 501
|
||||
else 501
|
||||
.endc 502
|
||||
|
@ -120,7 +121,7 @@ endc 502
|
|||
.endif 502
|
||||
endif 502
|
||||
.iif 503
|
||||
iif 503
|
||||
iif 503
|
||||
.macro 504
|
||||
macro 504
|
||||
.endm 505
|
||||
|
@ -131,3 +132,4 @@ rept 506
|
|||
endr 507
|
||||
.exitm 510
|
||||
exitm 510
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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__
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
# Jaguar Object Processor mnemonics
|
||||
#
|
||||
bitmap 3100
|
||||
scbitmap 3101
|
||||
gpuobj 3102
|
||||
branch 3103
|
||||
stop 3104
|
||||
nop 3105
|
||||
jump 3106
|
||||
|
37
procln.c
37
procln.c
|
@ -15,6 +15,7 @@
|
|||
#include "listing.h"
|
||||
#include "mach.h"
|
||||
#include "macro.h"
|
||||
#include "op.h"
|
||||
#include "riscasm.h"
|
||||
#include "sect.h"
|
||||
#include "symbol.h"
|
||||
|
@ -34,6 +35,10 @@
|
|||
#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
|
||||
|
@ -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)
|
||||
{
|
||||
|
|
11
riscasm.c
11
riscasm.c
|
@ -13,6 +13,7 @@
|
|||
#include "expr.h"
|
||||
#include "mark.h"
|
||||
#include "procln.h"
|
||||
#include "rmac.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
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#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;
|
||||
|
|
12
rmac.c
12
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 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
|
||||
|
@ -55,6 +56,16 @@ int activecpu = CPU_68000; // Active 68k CPU (68000 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.
|
||||
//
|
||||
|
@ -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
|
||||
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
|
||||
|
|
2
rmac.h
2
rmac.h
|
@ -284,6 +284,7 @@ enum
|
|||
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;
|
||||
|
@ -306,6 +307,7 @@ extern int activecpu;
|
|||
extern int activefpu;
|
||||
|
||||
// Exported functions
|
||||
void strtoupper(char * s);
|
||||
char * fext(char *, char *, int);
|
||||
int nthpath(char *, int, char *);
|
||||
int ParseOptimization(char * optstring);
|
||||
|
|
45
sect.c
45
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)
|
||||
printf(" name: %s, value: $lX\n", symbol->sname, symbol->svalue);
|
||||
printf(" name: %s, value: $%lX\n", symbol->sname, symbol->svalue);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -679,9 +679,8 @@ int ResolveFixups(int sno)
|
|||
|
||||
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;
|
||||
|
||||
|
@ -702,6 +701,44 @@ int ResolveFixups(int sno)
|
|||
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:
|
||||
|
|
12
sect.h
12
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_QUAD 0x000A // Fixup quad-word (8 bytes)
|
||||
|
||||
#define FU_SEXT 0x0010 // Ok to sign extend
|
||||
#define FU_PCREL 0x0020 // Subtract PC first
|
||||
|
@ -98,9 +99,14 @@
|
|||
#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
|
||||
|
|
Loading…
Reference in New Issue