The deed has been accomplished.

As far as I can tell, there should be no more regressions, but that's
no guarantee of anything.  Assuming no more are found, this should go
out as version 2.0.0.  :-D
This commit is contained in:
Shamus Hammons 2019-08-07 18:24:52 -05:00
parent bdbf34766f
commit 29fa5dcf50
20 changed files with 2377 additions and 1734 deletions

33
6502.c
View File

@ -645,46 +645,39 @@ badmode:
if (sloc > 0x10000L)
fatal("6502 code pointer > 64K");
//Now why use this instead of at_eol()?
if (*tok != EOL)
error(extra_stuff);
ErrorIfNotAtEOL();
}
//
// Generate 6502 object output file.
// ggn: Converted to COM/EXE/XEX output format
//
// ggn: converted into a com/exe/xex output format
void m6502obj(int ofd)
{
uint16_t exeheader[3];
int headsize = 6;
uint16_t * headpoint = exeheader;
uint8_t header[4];
CHUNK * ch = sect[M6502].scode;
// If no 6502 code was generated, forget it
// If no 6502 code was generated, bail out
if ((ch == NULL) || (ch->challoc == 0))
return;
exeheader[0] = 0xFFFF; // Mandatory for first segment
register uint8_t * p = ch->chptr;
// Write out mandatory $FFFF header
header[0] = header[1] = 0xFF;
ssize_t unused = write(ofd, header, 2);
for(uint16_t * l=&orgmap[0][0]; l<currentorg; l+=2)
{
/*
Why are we assuming endianness here? This is retarded
*/
exeheader[1] = l[0];
exeheader[2] = l[1] - 1;
SETLE16(header, 0, l[0]);
SETLE16(header, 2, l[1] - 1);
// Write header
size_t unused = write(ofd, headpoint, headsize);
// Write header for segment
unused = write(ofd, header, 4);
// Write the segment data
unused = write(ofd, p + l[0], l[1] - l[0]);
// Skip the $FFFF after first segment, it's not mandatory
headpoint = &exeheader[1];
headsize = 4;
}
}

238
direct.c
View File

@ -9,6 +9,7 @@
#include "direct.h"
#include "6502.h"
#include "amode.h"
#include "dsp56k.h"
#include "error.h"
#include "expr.h"
#include "fltpoint.h"
@ -222,7 +223,9 @@ int d_org(void)
return error(".org permitted only in GPU/DSP/OP, 56001 and 6502 sections");
// M56K can leave the expression off the org for some reason :-/
if ((abs_expr(&address) == ERROR) && !dsp56001)
// (It's because the expression is non-standard, and so we have to look at
// it in isolation)
if (!dsp56001 && (abs_expr(&address) == ERROR))
{
error("cannot determine org'd address");
return ERROR;
@ -255,9 +258,94 @@ int d_org(void)
}
else if (dsp56001)
{
// Only mark segments we actually wrote something
if (chptr != dsp_currentorg->start && dsp_written_data_in_current_org)
{
dsp_currentorg->end = chptr;
dsp_currentorg++;
}
// Maybe we switched from a non-DSP section (TEXT, DATA, etc) and
// scode isn't initialised yet. Not that it's going to be a valid
// scenario, but if we try it anyhow it's going to lead to a crash. So
// let's fudge a value of 0 and get on with it.
orgaddr = (scode != NULL ? sloc : 0);
SaveSection();
if (tok[1] != ':')
return error(syntax_error);
int sectionToSwitch = 0;
switch (tok[0])
{
case KW_X:
dsp_currentorg->memtype = ORG_X;
sectionToSwitch = M56001X;
break;
case KW_Y:
dsp_currentorg->memtype = ORG_Y;
sectionToSwitch = M56001Y;
break;
case KW_P:
dsp_currentorg->memtype = ORG_P;
sectionToSwitch = M56001P;
break;
case KW_L:
dsp_currentorg->memtype = ORG_L;
sectionToSwitch = M56001L;
break;
default:
return error("unknown type in ORG");
}
if ((obj_format == LOD) || (obj_format == P56))
SwitchSection(sectionToSwitch);
tok += 2;
chcheck(3); // Ensure we got a valid address to write
dsp_currentorg->chunk = scode; // Mark down which chunk this org starts from (will be needed when outputting)
if (*tok == EOL)
{
// Well, the user didn't specify an address at all so we'll have to
// use the last used address of that section (or 0 if there wasn't one)
address = orgaddr;
dsp_currentorg->start = chptr;
dsp_currentorg->orgadr = orgaddr;
}
else
{
if (abs_expr(&address) == ERROR)
{
error("cannot determine org'd address");
return ERROR;
}
dsp_currentorg->start = chptr;
dsp_currentorg->orgadr = (uint32_t)address;
sect[cursect].orgaddr = (uint32_t)address;
}
if (address > DSP_MAX_RAM)
{
return error(range_error);
}
dsp_written_data_in_current_org = 0;
// Copied from 6502 above: kludge `lsloc' so the listing generator
// doesn't try to spew out megabytes.
lsloc = sloc = (int32_t)address;
// N.B.: It seems that by enabling this, even though it works elsewhere, will cause symbols to royally fuck up. Will have to do some digging to figure out why.
// orgactive = 1;
}
at_eol();
ErrorIfNotAtEOL();
return 0;
}
@ -830,7 +918,7 @@ int d_assert(void)
break;
}
at_eol();
ErrorIfNotAtEOL();
return 0;
}
@ -1011,7 +1099,7 @@ int d_ds(WORD siz)
dep_block(eval, siz, 0, (WORD)(DEFINED | ABS), NULL);
}
at_eol();
ErrorIfNotAtEOL();
return 0;
}
@ -1029,7 +1117,9 @@ int d_dc(WORD siz)
return error("illegal initialization of section");
// Do an auto_even if it's not BYTE sized (hmm, should we be doing this???)
if (cursect != M6502 && (siz != SIZB) && (sloc & 1))
if ((cursect != M6502) && (cursect != M56001P) && (cursect != M56001X)
&& (cursect != M56001Y) && (cursect != M56001L)
&& (siz != SIZB) && (sloc & 1))
auto_even();
// Check to see if we're trying to set LONGS on a non 32-bit aligned
@ -1086,6 +1176,138 @@ int d_dc(WORD siz)
uint16_t tdb = eattr & TDB;
uint16_t defined = eattr & DEFINED;
// N.B.: This is awful. This needs better handling, rather than just bodging something in that, while works, is basically an ugly wart on the assembler. !!! FIX !!!
if (dsp56001)
{
if (cursect != M56001L)
{
if (!defined)
{
AddFixup(FU_DSPIMM24 | FU_SEXT, sloc, exprbuf);
D_dsp(0);
}
else
{
if (eattr & FLOAT)
{
double fval = *(double *)&eval;
if (fval >= 1)
{
warn("value clamped to +1.");
eval = 0x7fffff;
}
else if (fval <= -1)
{
warn("value clamped to -1.");
eval = 0x800000;
}
else
{
// Convert fraction to 24 bits fixed point with sign and rounding
// Yeah, that cast to int32_t has to be there because casting
// a float to unsigned int is "undefined" according to the C
// standard. Which most compilers seem to do the sensible thing
// and just cast the f**king value properly, except gcc 4.x.x
// for arm (tested on raspbian).
// Thanks, C and gcc! Thanks for making me waste a few hours \o/
eval = 0;//!!! FIX !!! (uint32_t)(int32_t)round(fval*(1 << 23));
}
}
else
{
if ((uint32_t)eval + 0x1000000 >= 0x2000000)
return error(range_error);
}
// Deposit DSP word (24-bit)
D_dsp(eval);
}
}
else
{
// In L: we deposit stuff to both X: and Y: instead
// We will be a bit lazy and require that there is a 2nd value in the same source line.
// (Motorola's assembler can parse 12-digit hex values, which we can't do at the moment)
// This of course requires to parse 2 values in one pass.
// If there isn't another value in this line, assume X: value is 0.
int secondword = 0;
uint32_t evaly;
l_parse_loop:
if (!defined)
{
AddFixup(FU_DSPIMM24 | FU_SEXT, sloc, exprbuf);
D_dsp(0);
}
else
{
if (eattr & FLOAT)
{
float fval = *(float *)&eval;
if (fval >= 1)
{
warn("value clamped to +1.");
eval = 0x7fffff;
}
else if (fval <= -1)
{
warn("value clamped to -1.");
eval = 0x800000;
}
else
{
// Convert fraction to 24 bits fixed point with sign and rounding
// Yeah, that cast to int32_t has to be there because casting
// a float to unsigned int is "undefined" according to the C
// standard. Which most compilers seem to do the sensible thing
// and just cast the f**king value properly, except gcc 4.x.x
// for arm (tested on raspbian).
// Thanks, C and gcc! Thanks for making me waste a few hours \o/
eval = 0;//!!! FIX !!! (uint32_t)(int32_t)round(fval*(1 << 23));
}
}
else
{
if (eval + 0x1000000 >= 0x2000000)
return error(range_error);
}
// Parse 2nd value if we didn't do this yet
if (secondword == 0)
{
evaly = (uint32_t)eval;
secondword = 1;
if (*tok != ':')
{
// If we don't have a : then we're probably at EOL,
// which means the X: value will be 0
eval = 0;
ErrorIfNotAtEOL();
}
else
{
tok++; // Eat the comma;
if (expr(exprbuf, &eval, &eattr, NULL) != OK)
return 0;
defined = (WORD)(eattr & DEFINED);
goto l_parse_loop;
}
}
// Deposit DSP words (24-bit)
D_dsp(eval);
D_dsp(evaly);
sloc--; // We do write 2 DSP words but as far as L: space is concerned we actually advance our counter by one
}
}
goto comma;
}
switch (siz)
{
case SIZB:
@ -1252,7 +1474,7 @@ comma:
break;
}
at_eol();
ErrorIfNotAtEOL();
return 0;
}
@ -1480,7 +1702,7 @@ int d_comm(void)
return 0;
sym->svalue = eval; // Install common symbol's size
at_eol();
ErrorIfNotAtEOL();
return 0;
}
@ -1612,7 +1834,7 @@ int d_56001(void)
rgpu = rdsp = robjproc = 0;
SaveSection();
if (obj_format == LOD || obj_format == P56)
if ((obj_format == LOD) || (obj_format == P56))
SwitchSection(M56001P);
return 0;

View File

@ -6,7 +6,8 @@
// Source utilised with the kind permission of Landon Dyer
//
#pragma once
#ifndef __DSP56K_H__
#define __DSP56K_H__
#include "rmac.h"
#include "sect.h"
@ -36,7 +37,8 @@ extern DSP_ORG dsp_orgmap[1024]; // Mark all 56001 org changes
extern DSP_ORG * dsp_currentorg;
extern int dsp_written_data_in_current_org;
#define dprintf(...) p_buf += sprintf(p_buf, __VA_ARGS__)
#define D_printf(...) chptr += sprintf(chptr, __VA_ARGS__)
// Exported functions
#endif // __DSP56K_H__

File diff suppressed because it is too large Load Diff

11
error.c
View File

@ -11,18 +11,21 @@
#include "listing.h"
#include "token.h"
// Exported variables
int errcnt; // Error count
char * err_fname; // Name of error message file
// Internal variables
static long unused; // For supressing 'write' warnings
//
// Report error if not at EOL
//
// N.B.: Since this should *never* happen, we can feel free to add whatever
// diagnostics that will help in tracking down a problem to this function.
//
int at_eol(void)
int ErrorIfNotAtEOL(void)
{
if (*tok != EOL)
{
@ -40,9 +43,9 @@ int at_eol(void)
//
// Cannot create a file
//
void cantcreat(const char * fn)
void CantCreateFile(const char * fn)
{
printf("cannot create: '%s'\n", fn);
printf("Cannot create file: '%s'\n", fn);
exit(1);
}
@ -66,7 +69,7 @@ void err_setup(void)
err_fname = NULL;
if ((err_fd = open(fnbuf, _OPEN_FLAGS, _PERM_MODE)) < 0)
cantcreat(fnbuf);
CantCreateFile(fnbuf);
err_flag = 1;
}

View File

@ -22,9 +22,9 @@ int error(const char *, ...);
int warn(const char *, ...);
int fatal(const char *);
int interror(int);
void cantcreat(const char *);
void CantCreateFile(const char *);
void err_setup(void);
int at_eol(void);
int ErrorIfNotAtEOL(void);
#endif // __ERROR_H__

View File

@ -178,7 +178,7 @@ void list_setup(void)
list_fname = NULL;
if ((list_fd = open(fnbuf, _OPEN_FLAGS, _PERM_MODE)) < 0)
cantcreat(fnbuf);
CantCreateFile(fnbuf);
}

View File

@ -172,7 +172,7 @@ int DefineMacro(void)
{
argno = 0;
symlist(defmac2);
at_eol();
ErrorIfNotAtEOL();
}
// Suck in the macro definition; we're looking for an ENDM symbol on a line

180
object.c
View File

@ -9,11 +9,13 @@
#include "object.h"
#include "6502.h"
#include "direct.h"
#include "dsp56k.h"
#include "error.h"
#include "mark.h"
#include "riscasm.h"
#include "sect.h"
#include "symbol.h"
#include "version.h"
//#define DEBUG_ELF
@ -56,6 +58,10 @@ See left. 4 & 5 If these bits are set to 0 (PF_PRIVATE), the processes'
- 6-15 Currently unused
*/
// Internal function prototypes
static void WriteLOD(void);
static void WriteP56(void);
//
// Add entry to symbol table (in ALCYON mode)
@ -351,6 +357,7 @@ int WriteObject(int fd)
if (strtable == NULL)
{
free(buf);
error("cannot allocate string table memory (in BSD mode)");
return ERROR;
}
@ -359,6 +366,8 @@ int WriteObject(int fd)
// Build object file header
chptr = buf; // Base of header (for D_foo macros)
ch_size = 0;
challoc = 0x800000;
D_long(0x00000107); // Magic number
D_long(sect[TEXT].sloc); // TEXT size
D_long(sect[DATA].sloc); // DATA size
@ -440,6 +449,8 @@ int WriteObject(int fd)
// Build object file header just before the text+data image
chptr = buf; // -> base of header
ch_size = 0;
challoc = HDRSIZE + tds + symbolMaxSize;
D_word(0x601A); // 00 - magic number
D_long(sect[TEXT].sloc); // 02 - TEXT size
D_long(sect[DATA].sloc); // 06 - DATA size
@ -592,6 +603,8 @@ for(int j=0; j<i; j++)
// If you want to make any sense out of this you'd better take a look
// at Executable and Linkable Format on Wikipedia.
chptr = buf;
ch_size = 0;
challoc = 0x600000;
D_long(0x7F454C46); // 00 - "<7F>ELF" Magic Number
D_byte(0x01); // 04 - 32 vs 64 (1 = 32, 2 = 64)
D_byte(0x02); // 05 - Endianness (1 = LE, 2 = BE)
@ -774,7 +787,174 @@ for(int j=0; j<i; j++)
// Just write the object file
m6502obj(fd);
}
else if (obj_format == P56 || obj_format == LOD)
{
// Allocate 6MB object file image memory
uint8_t * buf = malloc(0x600000);
if (buf == NULL)
return error("cannot allocate object file memory (in P56/LOD mode)");
// objImage = buf; // Set global object image pointer
memset(buf, 0, 0x600000); // Clear allocated memory
// Iterate through DSP ram buffers
chptr = buf; // -> base of header
ch_size = 0;
challoc = 0x600000;
if (obj_format == LOD)
WriteLOD();
else
WriteP56();
// Write all the things |o/
ssize_t unused = write(fd, buf, chptr - buf);
if (buf)
free(buf);
}
return 0;
}
static void WriteLOD(void)
{
D_printf("_START %s 0000 0000 0000 RMAC %01i.%01i.%01i\n\n", firstfname, MAJOR, MINOR, PATCH);
for(DSP_ORG * l=&dsp_orgmap[0]; l<dsp_currentorg; l++)
{
if (l->end != l->start)
{
switch (l->memtype)
{
case ORG_P: D_printf("_DATA P %.4X\n", l->orgadr); break;
case ORG_X: D_printf("_DATA X %.4X\n", l->orgadr); break;
case ORG_Y: D_printf("_DATA Y %.4X\n", l->orgadr); break;
case ORG_L: D_printf("_DATA L %.4X\n", l->orgadr); break;
default:
error("Internal error: unknown DSP56001 org'd section");
return;
}
CHUNK * cp = l->chunk;
uint8_t * p_chunk = l->start;
uint8_t * p_chunk_end = p_chunk;
uint32_t j = 0;
while (p_chunk_end != l->end)
{
if (l->end < (cp->chptr + cp->ch_size) && l->end > cp->chptr)
{
// If the end of the section is inside the current chunk, just dump everything and stop
p_chunk_end = l->end;
}
else
{
// If the end of the section is not inside the current chunk, just dump everything from the current chunk and move on to the next
p_chunk_end = cp->chptr + cp->ch_size;
}
uint32_t count = (uint32_t)(p_chunk_end - p_chunk);
for(uint32_t i=0; i<count; i+=3)
{
if ((j & 7) != 7)
{
D_printf("%.6X ", (((p_chunk[0] << 8) | p_chunk[1]) << 8) | p_chunk[2]);
}
else
{
D_printf("%.6X\n", (((p_chunk[0] << 8) | p_chunk[1]) << 8) | p_chunk[2]);
}
p_chunk += 3;
j++;
}
cp = cp->chnext; // Advance chunk
if (cp != NULL)
p_chunk = cp->chptr; // Set dump pointer to start of this chunk
}
if ((j & 7) != 0)
D_printf("\n");
}
}
// Dump the symbol table into the buf
DumpLODSymbols();
D_printf("\n_END %.4X\n", dsp_orgmap[0].orgadr);
}
static void WriteP56(void)
{
for(DSP_ORG * l=&dsp_orgmap[0]; l<dsp_currentorg; l++)
{
if (l->end == l->start)
continue;
if ((l->memtype < ORG_P) || (l->memtype > ORG_L))
{
error("Internal error: unknown DSP56001 org'd section");
return;
}
CHUNK * cp = l->chunk;
uint8_t * p_chunk = l->start;
uint8_t * p_chunk_end = p_chunk;
// Memory type (P, X, Y or L)
D_dsp(l->memtype);
// Chunk start address (in DSP words)
D_dsp(l->orgadr);
// Chunk length (in DSP words)
// We'll fill this field after we write the chunk so we can calculate
// how long it is (so if the chunk is split into different CHUNKs we
// can deal with this during copy)
uint8_t * p_buf_len = chptr;
chptr += 3;
// The chunk itself
uint32_t chunk_size = 0;
while (p_chunk_end != l->end)
{
if (l->end < (cp->chptr + cp->ch_size) && l->end > cp->chptr)
{
// If the end of the section is inside the current chunk, just
// dump everything and stop
p_chunk_end = l->end;
}
else
{
// If the end of the section is not inside the current chunk,
// just dump everything from the current chunk and move on to
// the next
p_chunk_end = cp->chptr + cp->ch_size;
}
uint32_t current_chunk_size = p_chunk_end - p_chunk;
chunk_size += current_chunk_size;
memcpy(chptr, p_chunk, current_chunk_size);
chptr += current_chunk_size;
cp = cp->chnext; // Advance chunk
if (cp != NULL)
p_chunk = cp->chptr; // Set dump pointer to start of this chunk
}
// Now we can mark the chunk's length (DSP word size is 24-bits, so
// the byte count needs to be divided by 3)
SETBE24(p_buf_len, chunk_size / 3);
}
}

10
op.c
View File

@ -177,7 +177,7 @@ static int HandleBitmap(void)
}
}
at_eol();
ErrorIfNotAtEOL();
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);
@ -302,7 +302,7 @@ static int HandleScaledBitmap(void)
}
}
at_eol();
ErrorIfNotAtEOL();
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);
@ -345,7 +345,7 @@ static int HandleGPUObject(void)
if (!(eattr & DEFINED))
return error("bad expression in data");
at_eol();
ErrorIfNotAtEOL();
uint64_t p1 = 0x02 | ((ypos * 2) << 3) | (eval << 14);
@ -410,7 +410,7 @@ static int HandleBranch(void)
if (!(eattr & DEFINED))
AddFixup(FU_QUAD | FU_OBJLINK, sloc, exprbuf);
at_eol();
ErrorIfNotAtEOL();
uint64_t p1 = 0x03 | (cc << 14) | ((ypos * 2) << 3) | ((eval & 0x3FFFF8) << 21);
@ -468,7 +468,7 @@ static int HandleJump(void)
if (!(eattr & DEFINED))
AddFixup(FU_QUAD | FU_OBJLINK, sloc, exprbuf);
at_eol();
ErrorIfNotAtEOL();
// This is "branch if VC < 2047", which pretty much guarantees the branch.
uint64_t p1 = 0x03 | (1 << 14) | (0x7FF << 3) | ((eval & 0x3FFFF8) << 21);

View File

@ -587,7 +587,7 @@ When checking to see if it's already been equated, issue a warning.
if (list_flag) // Put value in listing
listvalue((uint32_t)eval);
at_eol(); // Must be at EOL now
ErrorIfNotAtEOL(); // Must be at EOL now
goto loop;
}
@ -782,11 +782,24 @@ When checking to see if it's already been equated, issue a warning.
parcode = 0;
}
#if 1
while ((dsp_am0 & md->mn0) == 0 || (dsp_am1 & md->mn1) == 0)
md = &dsp56k_machtab[md->mncont];
(*md->mnfunc)(md->mninst | (parcode << 8));
goto loop;
#else
for(;;)
{
if ((dsp_am0 & md->mn0) != 0 && (dsp_am1 & md->mn1) != 0)
{
(*md->mnfunc)(md->mninst|(parcode << 8));
goto loop;
}
md = &dsp56k_machtab[md->mncont];
}
#endif
}
}

View File

@ -258,7 +258,7 @@ int GenerateRISCCode(int state)
// UNPACK
case RI_ONE:
reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
at_eol();
ErrorIfNotAtEOL();
DepositRISCInstructionWord(parm, parm >> 6, reg2);
break;
@ -276,7 +276,7 @@ int GenerateRISCCode(int state)
altbankok = 1; // MOVETA
reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
at_eol();
ErrorIfNotAtEOL();
DepositRISCInstructionWord(parm, reg1, reg2);
break;
@ -338,7 +338,7 @@ int GenerateRISCCode(int state)
CHECK_COMMA;
reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
at_eol();
ErrorIfNotAtEOL();
DepositRISCInstructionWord(parm, reg1, reg2);
break;
@ -387,7 +387,7 @@ int GenerateRISCCode(int state)
CHECK_COMMA;
reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
at_eol();
ErrorIfNotAtEOL();
DepositRISCInstructionWord(parm, 0, reg2);
val = WORDSWAP32(eval);
@ -410,7 +410,7 @@ int GenerateRISCCode(int state)
CHECK_COMMA;
reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
at_eol();
ErrorIfNotAtEOL();
DepositRISCInstructionWord(parm, reg1, reg2);
break;
@ -533,7 +533,7 @@ int GenerateRISCCode(int state)
tok++;
CHECK_COMMA;
reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
at_eol();
ErrorIfNotAtEOL();
DepositRISCInstructionWord(parm, reg1, reg2);
break;
@ -652,7 +652,7 @@ int GenerateRISCCode(int state)
return MalformedOpcode(MALF_RPAREN);
tok++;
at_eol();
ErrorIfNotAtEOL();
DepositRISCInstructionWord(parm, reg2, reg1);
break;
@ -670,7 +670,7 @@ int GenerateRISCCode(int state)
tok++;
CHECK_COMMA;
reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
at_eol();
ErrorIfNotAtEOL();
DepositRISCInstructionWord(parm, reg1, reg2);
break;
@ -689,7 +689,7 @@ int GenerateRISCCode(int state)
return MalformedOpcode(MALF_RPAREN);
tok++;
at_eol();
ErrorIfNotAtEOL();
DepositRISCInstructionWord(parm, reg2, reg1);
break;
@ -802,7 +802,7 @@ int GenerateRISCCode(int state)
return MalformedOpcode(MALF_RPAREN);
tok++;
at_eol();
ErrorIfNotAtEOL();
}
DepositRISCInstructionWord(parm, reg2, reg1);

29
rmac.c
View File

@ -10,6 +10,7 @@
#include "6502.h"
#include "debug.h"
#include "direct.h"
#include "dsp56k.h"
#include "error.h"
#include "expr.h"
#include "listing.h"
@ -148,6 +149,8 @@ void DisplayHelp(void)
" a: ALCYON (use this for ST)\n"
" b: BSD (use this for Jaguar)\n"
" e: ELF\n"
" p: P56 (use this for DSP56001 only)\n"
" l: LOD (use this for DSP56001 only)\n"
" x: com/exe/xex (Atari 800)\n"
" -i[path] Directory to search for include files\n"
" -l[filename] Create an output listing file\n"
@ -161,6 +164,7 @@ void DisplayHelp(void)
" 6502\n"
" tom\n"
" jerry\n"
" 56001\n"
" -n Don't do things behind your back in RISC assembler\n"
" -o file Output file name\n"
" +o[value] Turn a specific optimisation on\n"
@ -358,6 +362,14 @@ int Process(int argc, char ** argv)
case 'E':
obj_format = ELF;
break;
case 'l': // -fl = LOD
case 'L':
obj_format = LOD;
break;
case 'p': // -fp = P56
case 'P':
obj_format = P56;
break;
case 'x': // -fx = COM/EXE/XEX
case 'X':
obj_format = XEX;
@ -588,6 +600,7 @@ int Process(int argc, char ** argv)
// - "foo.o" for linkable output;
// - "foo.prg" for GEMDOS executable (-p flag).
SaveSection();
int temp_section = cursect;
for(i=TEXT; i<=BSS; i<<=1)
{
@ -613,6 +626,20 @@ int Process(int argc, char ** argv)
currentorg += 2;
}
// This looks like an awful kludge... !!! FIX !!!
if (temp_section & (M56001P | M56001X | M56001Y))
{
SwitchSection(temp_section);
if (chptr != dsp_currentorg->start)
{
dsp_currentorg->end = chptr;
dsp_currentorg++;
}
}
SwitchSection(TEXT);
if (objfname == NULL)
{
if (firstfname == NULL)
@ -635,7 +662,7 @@ int Process(int argc, char ** argv)
if (errcnt == 0)
{
if ((fd = open(objfname, _OPEN_FLAGS, _PERM_MODE)) < 0)
cantcreat(objfname);
CantCreateFile(objfname);
if (verb_flag)
{

9
rmac.h
View File

@ -137,6 +137,12 @@
{ (a)[(r + 0)] = (uint8_t)((v) & 0xFF); \
(a)[(r + 1)] = (uint8_t)((v) >> 8); }
// In DSP56001 mode, this is useful:
#define SETBE24(a, v) \
{ (a)[0] = (uint8_t)(((v) >> 16) & 0xFF); \
(a)[1] = (uint8_t)(((v) >> 8) & 0xFF); \
(a)[2] = (uint8_t)((v) & 0xFF); }
// Byteswap crap
#define BYTESWAP16(x) ((((x) & 0x00FF) << 8) | (((x) & 0xFF00) >> 8))
#define BYTESWAP32(x) ((((x) & 0x000000FF) << 24) | (((x) & 0x0000FF00) << 8) | (((x) & 0x00FF0000) >> 8) | (((x) & 0xFF000000) >> 24))
@ -218,12 +224,13 @@ PTR
#define TEXT 0x0001 // Relative to text
#define DATA 0x0002 // Relative to data
#define BSS 0x0004 // Relative to BSS
//OK, this is bad, mmkay? These are treated as indices into an array which means that this was never meant to be defined this way--at least if it was, it was a compromise that has come home to bite us all in the ass. !!! FIX !!!
#define M6502 0x0008 // 6502/microprocessor (absolute)
#define M56001P 0x0010 // DSP 56001 Program RAM
#define M56001X 0x0020 // DSP 56001 X RAM
#define M56001Y 0x0040 // DSP 56001 Y RAM
#define M56001L 0x0080 // DSP 56001 L RAM
#define TDB (TEXT|DATA|BSS) // Mask for text+data+bss
#define TDB (TEXT|DATA|BSS) // Mask for TEXT+DATA+BSS
#define M56KPXYL (M56001P|M56001X|M56001Y|M56001L) // Mask for 56K stuff
// Sizes

69
sect.c
View File

@ -9,6 +9,7 @@
#include "sect.h"
#include "6502.h"
#include "direct.h"
#include "dsp56k.h"
#include "error.h"
#include "expr.h"
#include "listing.h"
@ -75,11 +76,14 @@ void InitSection(void)
MakeSection(i, 0);
// Construct default sections, make TEXT the current section
MakeSection(ABS, SUSED | SABS | SBSS); // ABS
MakeSection(TEXT, SUSED | TEXT ); // TEXT
MakeSection(DATA, SUSED | DATA ); // DATA
MakeSection(BSS, SUSED | BSS | SBSS); // BSS
MakeSection(M6502, SUSED | TEXT ); // 6502 code section
MakeSection(ABS, SUSED | SABS | SBSS); // ABS
MakeSection(TEXT, SUSED | TEXT ); // TEXT
MakeSection(DATA, SUSED | DATA ); // DATA
MakeSection(BSS, SUSED | BSS | SBSS); // BSS
MakeSection(M6502, SUSED | TEXT ); // 6502 code section
MakeSection(M56001P, SUSED | SABS ); // DSP 56001 Program RAM
MakeSection(M56001X, SUSED | SABS ); // DSP 56001 X RAM
MakeSection(M56001Y, SUSED | SABS ); // DSP 56001 Y RAM
// Switch to TEXT for starters
SwitchSection(TEXT);
@ -128,9 +132,13 @@ void SwitchSection(int sno)
// For 6502 mode, add the last org'd address
// Why?
/*
Because the way this is set up it treats the 6502 assembly space as a single 64K space (+ 16 bytes, for some reason) and just bobbles around inside that space and uses a stack of org "pointers" to show where the data ended up.
Because the way this is set up it treats the 6502 assembly space as a single 64K space (+ 16 bytes, for some unknown reason) and just bobbles around inside that space and uses a stack of org "pointers" to show where the data ended up.
This is a piss poor way to handle things, and for fucks sake, we can do better than this!
This is a shitty way to handle things, and we can do better than this! :-P
Really, there's no reason to have the 6502 (or DSP56001 for that matter) have their own private sections for this kind of thing, as there's literally *no* chance that it would be mingled with 68K+ code. It should be able to use the TEXT, DATA & BSS sections just like the 68K.
Or should it? After looking at the code, maybe it's better to keep the 56001 sections segregated from the rest. But we can still make the 6502 stuff better.
*/
if (m6502)
chptr = cp->chptr + orgaddr;
@ -267,7 +275,8 @@ int AddFixup(uint32_t attr, uint32_t loc, TOKEN * fexpr)
if (attr & FUMASKDSP)
{
attr |= FU_56001;
_orgaddr = orgaddr;
// Save the exact spot in this chunk where the fixup should go
_orgaddr = chptr - scode->chptr;
}
// Allocate space for the fixup + any expression
@ -349,6 +358,9 @@ int ResolveFixups(int sno)
// than this.
SetFilenameForErrorReporting();
if ((sno == M56001P) || (sno == M56001X) || (sno == M56001Y) || (sno == M56001L))
loc = fup->orgaddr;
// Search for chunk containing location to fix up; compute a
// pointer to the location (in the chunk). Often we will find the
// Fixup is in the "cached" chunk, so the linear-search is seldom
@ -566,16 +578,7 @@ int ResolveFixups(int sno)
case FU_WORD:
if ((dw & FUMASKRISC) == FU_JR)
{
#if 0
int reg;
if (fup->orgaddr)
reg = (signed)((eval - (fup->orgaddr + 2)) / 2);
else
reg = (signed)((eval - (loc + 2)) / 2);
#else
int reg = (signed)((eval - ((fup->orgaddr ? fup->orgaddr : loc) + 2)) / 2);
#endif
if ((reg < -16) || (reg > 15))
{
@ -727,8 +730,8 @@ int ResolveFixups(int sno)
uint64_t addr = eval;
//Hmm, not sure how this can be set, since it's only set if it's a DSP56001 fixup or a FU_JR... :-/
if (fup->orgaddr)
addr = fup->orgaddr;
// if (fup->orgaddr)
// addr = fup->orgaddr;
eval = (quad & 0xFFFFFC0000FFFFFFLL) | ((addr & 0x3FFFF8) << 21);
}
@ -743,8 +746,8 @@ int ResolveFixups(int sno)
uint64_t addr = eval;
//Hmm, not sure how this can be set, since it's only set if it's a DSP56001 fixup or a FU_JR... :-/
if (fup->orgaddr)
addr = fup->orgaddr;
// if (fup->orgaddr)
// addr = fup->orgaddr;
eval = (quad & 0x000007FFFFFFFFFFLL) | ((addr & 0xFFFFF8) << 40);
}
@ -798,7 +801,7 @@ int ResolveFixups(int sno)
case FU_DSPADR12:
if (eval >= 0x1000)
{
error("address out of range ($000-$FFF)");
error("address out of range ($0-$FFF)");
break;
}
@ -809,22 +812,22 @@ int ResolveFixups(int sno)
// This is a full DSP word containing Effective Address Extension
case FU_DSPADR24:
case FU_DSPIMM24:
if (eval >= 0x100000)
if (eval >= 0x1000000)
{
error("value out of range ($000-$FFFFFF)");
error("value out of range ($0-$FFFFFF)");
break;
}
*locp++ = (uint32_t)eval >> 16;
*locp++ = ((uint32_t)eval >> 8) & 0xFF;
*locp++ = (uint32_t)eval & 0xFF;
locp[0] = (uint8_t)((eval >> 16) & 0xFF);
locp[1] = (uint8_t)((eval >> 8) & 0xFF);
locp[2] = (uint8_t)(eval & 0xFF);
break;
// This is a 16bit absolute address into a 24bit field
case FU_DSPADR16:
if (eval >= 0x10000)
{
error("address out of range ($0000-$FFFF)");
error("address out of range ($0-$FFFF)");
break;
}
@ -838,7 +841,7 @@ int ResolveFixups(int sno)
case FU_DSPIMM12:
if (eval >= 0x1000)
{
error("immediate out of range ($000-$FFF)");
error("immediate out of range ($0-$FFF)");
break;
}
@ -851,7 +854,7 @@ int ResolveFixups(int sno)
case FU_DSPIMM8:
if (eval >= 0x100)
{
error("immediate out of range ($00-$FF)");
error("immediate out of range ($0-$FF)");
break;
}
@ -948,6 +951,12 @@ int ResolveAllFixups(void)
ResolveFixups(DATA);
DEBUG printf("Resolving 6502 sections...\n");
ResolveFixups(M6502); // Fixup 6502 section (if any)
DEBUG printf("Resolving DSP56001 P: sections...\n");
ResolveFixups(M56001P); // Fixup 56001 P: section (if any)
DEBUG printf("Resolving DSP56001 X: sections...\n");
ResolveFixups(M56001X); // Fixup 56001 X: section (if any)
DEBUG printf("Resolving DSP56001 Y: sections...\n");
ResolveFixups(M56001Y); // Fixup 56001 Y: section (if any)
return 0;
}

4
sect.h
View File

@ -54,7 +54,9 @@
#define D_ZEROFILL(n) {chcheck(n); memset(chptr, 0, n); chptr+=n; sloc+=n; \
ch_size+=n; if (orgactive) orgaddr+=n;}
#define NSECTS 16 // Max. number of sections
//OK, this is bad, mmkay? The constants defined in rmac.h are used as indices into an array which means that this was never meant to be defined this way--at least if it was, it was a compromise that has come home to bite us all in the ass. !!! FIX !!!
//#define NSECTS 16 // Max. number of sections
#define NSECTS 256 // Max. number of sections
// Tunable (storage) definitions
#define CH_THRESHOLD 32 // Minimum amount of space in code chunk

View File

@ -7,6 +7,7 @@
//
#include "symbol.h"
#include "dsp56k.h"
#include "error.h"
#include "listing.h"
#include "object.h"
@ -35,6 +36,9 @@ static uint8_t tdb_text[8] = {
'a', 't', 'd', '!', 'b', SPACE, SPACE, SPACE
};
// Internal function prototypes
static uint16_t WriteLODSection(int, uint16_t);
//
// Initialize symbol table
@ -332,6 +336,53 @@ uint32_t sy_assign_ELF(uint8_t * buf, uint8_t *(* construct)())
}
//
// Helper function for dsp_lod_symbols
//
static uint16_t WriteLODSection(int section, uint16_t symbolCount)
{
for(SYM * sy=sdecl; sy!=NULL; sy=sy->sdecl)
{
// Export vanilla labels (but don't make them global). An exception is
// made for equates, which are not exported unless they are referenced.
if (sy->stype == LABEL && lsym_flag
&& (sy->sattr & (DEFINED | REFERENCED)) != 0
&& (*sy->sname != '.')
&& (sy->sattr & GLOBAL) == 0
&& (sy->sattr & (section)))
{
sy->senv = symbolCount++;
D_printf("%-19s I %.6" PRIX64 "\n", sy->sname, sy->svalue);
}
}
return symbolCount;
}
//
// Dump LOD style symbols into the passed in buffer
//
void DumpLODSymbols(void)
{
D_printf("_SYMBOL P\n");
uint16_t count = WriteLODSection(M56001P, 0);
D_printf("_SYMBOL X\n");
count = WriteLODSection(M56001X, count);
D_printf("_SYMBOL Y\n");
count = WriteLODSection(M56001Y, count);
D_printf("_SYMBOL L\n");
count = WriteLODSection(M56001L, count);
// TODO: I've seen _SYMBOL N in there but no idea what symbols it needs...
//D_printf("_SYMBOL N\n");
//WriteLODSection(M56001?, count);
}
//
// Convert string to uppercase
//

View File

@ -51,6 +51,7 @@ void ForceUndefinedSymbolsGlobal(void);
int symtable(void);
uint32_t sy_assign(uint8_t *, uint8_t *(*)());
uint32_t sy_assign_ELF(uint8_t *, uint8_t *(*)());
void DumpLODSymbols(void);
uint8_t * GetSymbolNameByUID(uint32_t);
#endif // __SYMBOL_H__

View File

@ -1171,7 +1171,7 @@ DEBUG { printf("TokenizeLine: Calling fpop() from SRC_IFILE...\n"); }
}
// Make j = -1 if user tries to use a RISC register while in 68K mode
if (!(rgpu || rdsp) && ((TOKEN)j >= KW_R0 && (TOKEN)j <= KW_R31))
if (!(rgpu || rdsp || dsp56001) && ((TOKEN)j >= KW_R0 && (TOKEN)j <= KW_R31))
{
j = -1;
}

View File

@ -13,9 +13,9 @@
// Release Information
#define MAJOR 1 // Major version number
#define MINOR 13 // Minor version number
#define PATCH 5 // Patch release number
#define MAJOR 2 // Major version number
#define MINOR 0 // Minor version number
#define PATCH 0 // Patch release number
#endif // __VERSION_H__