- Corner case in ([bd,An/PC],Xn,od) addressing mode where bd is suppressed
- 68060 specific instructions (68ktab, mach.c)
- PMMU instruction fixes (68ktab, mach.c)
- FMOVEM fixes (amode.c)
- Switching CPU state fixes (direct.c)
- Bitfield instruction fixes (mach.c)
- pflush fixes (68ktab, mach.c)
- Various warnings silenced (mark.c, riscasm.c)
- Formatting ;)
link NWL M_AREG M_IMMED %0100111001010rrr m_link
link NWL M_AREG M_IMMED %0100111001010rrr m_link
+lpstop NW M_IMMED M_AM_NONE %1111100000000000 m_lpstop
+
lsl NBWL M_DREG M_DREG %1110rrr1ss101rrr m_shr +
- NBWL M_IMMED M_DREG %1110ccc1ss001rrr m_shi +
- NBWL C_ALTMEM M_AM_NONE %1110001111eee000 m_ea +
lsl NBWL M_DREG M_DREG %1110rrr1ss101rrr m_shr +
- NBWL M_IMMED M_DREG %1110ccc1ss001rrr m_shi +
- NBWL C_ALTMEM M_AM_NONE %1110001111eee000 m_ea +
pflush ! M_AM_NONE M_AM_NONE %1111000000eeeeee m_pflush
pflushn ! M_AM_NONE M_AM_NONE %1111010100000111 m_pflush
pflush ! M_AM_NONE M_AM_NONE %1111000000eeeeee m_pflush
pflushn ! M_AM_NONE M_AM_NONE %1111010100000111 m_pflush
-pflushan N M_AM_NONE M_AM_NONE %1111010100010000 m_self
+pflushan N M_AM_NONE M_AM_NONE %1111010100010000 m_pflushan
pflusha N M_AM_NONE M_AM_NONE %1111000000000000 m_pflusha
pflushr N C_ALL030 M_AM_NONE %1111000000eeeeee m_pflushr
ploadr N M_FC C_PMOVE %1111000000eeeeee m_ploadr
pflusha N M_AM_NONE M_AM_NONE %1111000000000000 m_pflusha
pflushr N C_ALL030 M_AM_NONE %1111000000eeeeee m_pflushr
ploadr N M_FC C_PMOVE %1111000000eeeeee m_ploadr
-ploadw N M_FC C_PMOVE %1111000000eeeeee m_ploadw
+ploadw N M_FC C_PMOVE %1111000000eeeeee m_ploadw
+
+plpa N M_AIND M_AM_NONE %1111010110001rrr m_plpa
pmove NWLD M_MRN C_PMOVE %1111000000eeeeee m_pmove +
- NWLD C_PMOVE M_MRN %1111000000eeeeee m_pmove
pmove NWLD M_MRN C_PMOVE %1111000000eeeeee m_pmove +
- NWLD C_PMOVE M_MRN %1111000000eeeeee m_pmove
int fpu_reglist_right(WORD * a_rmask)
{
static WORD msktab_plus[] = {
int fpu_reglist_right(WORD * a_rmask)
{
static WORD msktab_plus[] = {
- 0x0001, 0x0002, 0x0004, 0x0008,
- 0x0010, 0x0020, 0x0040, 0x0080
+ 0x0080, 0x0040, 0x0020, 0x0010,
+ 0x0008, 0x0004, 0x0002, 0x0001
// Function prototypes
int d_unimpl(void);
int d_68000(void);
// Function prototypes
int d_unimpl(void);
int d_68000(void);
int d_68020(void);
int d_68030(void);
int d_68040(void);
int d_68020(void);
int d_68030(void);
int d_68040(void);
{
d_68000();
activecpu = CPU_68060;
{
d_68000();
activecpu = CPU_68060;
-// .68881 - Back to 68000 TEXT segment and select 68881 FPU
+// .68881 - Back to 680x0 TEXT segment and select 68881 FPU
activefpu = FPU_68881;
return 0;
}
//
activefpu = FPU_68881;
return 0;
}
//
-// .68882 - Back to 68000 TEXT segment and select 68882 FPU
+// .68882 - Back to 680x0 TEXT segment and select 68882 FPU
- d_68000();
- activefpu = FPU_68881;
+ //d_68000();
+ activefpu = FPU_68882;
// RMAC - Reboot's Macro Assembler for all Atari computers
// EXPR.C - Expression Analyzer
// Copyright (C) 199x Landon Dyer, 2011-2017 Reboot and Friends
// RMAC - Reboot's Macro Assembler for all Atari computers
// EXPR.C - Expression Analyzer
// Copyright (C) 199x Landon Dyer, 2011-2017 Reboot and Friends
int movep = 0; // Global flag to indicate we're generating a movep instruction
// Function prototypes
int movep = 0; // Global flag to indicate we're generating a movep instruction
// Function prototypes
-int m_unimp(WORD, WORD), m_badmode(WORD, WORD), m_bad6mode(WORD, WORD), m_bad6inst(WORD, WORD);
+int m_unimp(WORD, WORD), m_badmode(WORD, WORD);
int m_self(WORD, WORD);
int m_abcd(WORD, WORD);
int m_reg(WORD, WORD);
int m_self(WORD, WORD);
int m_abcd(WORD, WORD);
int m_reg(WORD, WORD);
int m_cprest(WORD inst, WORD siz);
int m_movec(WORD inst, WORD siz);
int m_moves(WORD inst, WORD siz);
int m_cprest(WORD inst, WORD siz);
int m_movec(WORD inst, WORD siz);
int m_moves(WORD inst, WORD siz);
+int m_lpstop(WORD inst, WORD siz);
+int m_plpa(WORD inst, WORD siz);
// PMMU
int m_pbcc(WORD inst, WORD siz);
int m_pflusha(WORD inst, WORD siz);
int m_pflush(WORD inst, WORD siz);
int m_pflushr(WORD inst, WORD siz);
// PMMU
int m_pbcc(WORD inst, WORD siz);
int m_pflusha(WORD inst, WORD siz);
int m_pflush(WORD inst, WORD siz);
int m_pflushr(WORD inst, WORD siz);
+int m_pflushan(WORD inst, WORD siz);
int m_pload(WORD inst, WORD siz, WORD extension);
int m_pmove(WORD inst, WORD siz);
int m_pmovefd(WORD inst, WORD siz);
int m_pload(WORD inst, WORD siz, WORD extension);
int m_pmove(WORD inst, WORD siz);
int m_pmovefd(WORD inst, WORD siz);
if ((a1exattr & TDB) != cursect)
return error(rel_error);
if ((a1exattr & TDB) != cursect)
return error(rel_error);
- uint32_t v = a1exval - sloc;
+ uint32_t v = (uint32_t)a1exval - sloc;
if (v + 0x8000 > 0x10000)
return error(range_error);
if (v + 0x8000 > 0x10000)
return error(range_error);
rmask = 0;
for(i=0x8000; i; i>>=1, w>>=1)
rmask = 0;
for(i=0x8000; i; i>>=1, w>>=1)
- rmask = (WORD)((rmask << 1) | w & 1);
+ rmask = (WORD)((rmask << 1) | (w & 1));
else
bfparam1 = bfval1 << 12;
else
bfparam1 = bfval1 << 12;
- D_word((inst | am0 | a0reg | am1 | a1reg));
+ //D_word((inst | am0 | a0reg | am1 | a1reg));
+ if (inst == B16(11101111, 11000000))
+ // bfins special case
+ D_word((inst | am1 | a1reg));
+ else
+ D_word((inst | am0 | a0reg));
+
ea0gen(siz); // Generate EA
// Second instruction word - Dest register (if exists), Do, Offset, Dw, Width
ea0gen(siz); // Generate EA
// Second instruction word - Dest register (if exists), Do, Offset, Dw, Width
- inst = bfparam1 | bfparam2;
+ if (inst == B16(11101111, 11000000))
+ {
+ // bfins special case
+ inst = bfparam1 | bfparam2;
- if (am1 == DREG)
- inst |= a1reg << 0;
+ if (am1 == DREG)
+ inst |= a0reg << 12;
- if (am0 == DREG)
- inst |= a0reg << 12;
+ D_word(inst);
+ }
+ else
+ {
+ inst = bfparam1 | bfparam2;
+ if (am1 == DREG)
+ inst |= a0reg << 0;
+
+ if (am0 == DREG)
+ inst |= a1reg << 12;
+
+ D_word(inst);
+ }
+// cpbcc(68020, 68030, 68040 (FBcc), 68060 (FBcc))
+// TODO: Better checks for different instructions?
//
int m_cpbr(WORD inst, WORD siz)
{
//
int m_cpbr(WORD inst, WORD siz)
{
- if ((activecpu & (CPU_68020 | CPU_68030)) == 0)
+ if ((activecpu & (CPU_68020 | CPU_68030)) && (!activefpu == 0))
return error(unsupport);
if (a0exattr & DEFINED)
return error(unsupport);
if (a0exattr & DEFINED)
{
if ((v + 0x8000) >= 0x10000)
return error(range_error);
{
if ((v + 0x8000) >= 0x10000)
return error(range_error);
return error("Wasn't this suppose to call m_move16a???");
else
{
return error("Wasn't this suppose to call m_move16a???");
else
{
+ // move16 (ax)+,(xxx).L
inst |= 0 << 3;
v = (int)a1exval;
}
inst |= 0 << 3;
v = (int)a1exval;
}
+ // move16 (xxx).L,(ax)+
inst |= 1 << 3;
v = (int)a0exval;
}
inst |= 1 << 3;
v = (int)a0exval;
}
inst |= 3 << 3;
v = (int)a0exval;
}
}
else if (am0 == AIND)
{
inst |= 3 << 3;
v = (int)a0exval;
}
}
else if (am0 == AIND)
{
inst |= 2 << 3;
v = (int)a1exval;
}
inst |= 2 << 3;
v = (int)a1exval;
}
+// cinvl/p/a (68040/68060)
//
int m_cinv(WORD inst, WORD siz)
{
//
int m_cinv(WORD inst, WORD siz)
{
-// movec (68010, 68020, 68030, 68040, CPU32)
+// movec (68010, 68020, 68030, 68040, 68060, CPU32)
//
int m_movec(WORD inst, WORD siz)
{
//
int m_movec(WORD inst, WORD siz)
{
if ((a0exattr & DEFINED) == 0)
return error("function code immediate should be defined");
if ((a0exattr & DEFINED) == 0)
return error("function code immediate should be defined");
- if (a0exval > 7 && a0exval < 0)
return error("function code out of range (0-7)");
fc = (uint16_t)a0exval;
return error("function code out of range (0-7)");
fc = (uint16_t)a0exval;
if ((a0exattr & DEFINED) == 0)
return error("mask immediate value should be defined");
if ((a0exattr & DEFINED) == 0)
return error("mask immediate value should be defined");
- if (a0exval > 7 && a0exval < 0)
return error("function code out of range (0-7)");
mask = (uint16_t)a0exval << 5;
return error("function code out of range (0-7)");
mask = (uint16_t)a0exval << 5;
+//
+// pflushan (68040, 68060)
+//
+int m_pflushan(WORD inst, WORD siz)
+{
+ if (activecpu == CPU_68040 || activecpu == CPU_68060)
+ D_word(inst);
+
+ return OK;
+}
+
+
// The instruction is a quad-word (8 byte) operation
// for the CPU root pointer and the supervisor root pointer.
// The instruction is a quad-word (8 byte) operation
// for the CPU root pointer and the supervisor root pointer.
- // It is a long - word operation for the translation control register
+ // It is a long-word operation for the translation control register
// and the transparent translation registers(TT0 and TT1).
// It is a word operation for the MMU status register.
// and the transparent translation registers(TT0 and TT1).
// It is a word operation for the MMU status register.
}
else if (am1 == CREG)
{
}
else if (am1 == CREG)
{
//
int m_ptrapcc(WORD inst, WORD siz)
{
//
int m_ptrapcc(WORD inst, WORD siz)
{
// We stash the 5 condition bits inside the opcode in 68ktab (bits 0-4),
// so we need to extract them first and fill in the clobbered bits.
WORD opcode = inst & 0x1F;
// We stash the 5 condition bits inside the opcode in 68ktab (bits 0-4),
// so we need to extract them first and fill in the clobbered bits.
WORD opcode = inst & 0x1F;
return gen_fpu(inst, siz, B8(00010001), FPU_FPSP);
}
return gen_fpu(inst, siz, B8(00010001), FPU_FPSP);
}
+
+/////////////////////////////////
+// //
+// 68060 specific instructions //
+// //
+/////////////////////////////////
+
+
+//
+// lpstop (68060)
+//
+int m_lpstop(WORD inst, WORD siz)
+{
+ CHECKNO60;
+ D_word(B16(00000001, 11000000));
+
+ if (a0exattr&DEFINED)
+ D_word(a0exval);
+ else
+ {
+ AddFixup(FU_WORD, sloc, a0expr);
+ D_word(0);
+ }
+
+ return OK;
+}
+
+
+//
+// plpa (68060)
+//
+int m_plpa(WORD inst, WORD siz)
+{
+ CHECKNO60;
+ inst |= a0reg; // Install register
+ D_word(inst);
+
+ return OK;
+}
+
w |= symbol->senv << 3;
*wp++ = w >> 8;
w |= symbol->senv << 3;
*wp++ = w >> 8;
// It might be (Dn[.wl][*scale],od)
// Maybe this is wrong and we have to write some code here
// instead of reusing that path...
// It might be (Dn[.wl][*scale],od)
// Maybe this is wrong and we have to write some code here
// instead of reusing that path...
- AnEXTEN |= EXT_BDSIZE0; // Base displacement null - suppressed
+ AnEXTEN |= EXT_FULLWORD; // Definitely using full extension format, so set bit 8
+ AnEXTEN |= EXT_BS; // Base displacement null - suppressed
+ AnEXTEN |= AnIXREG << 12;
}
else if ((*tok >= KW_A0) && (*tok <= KW_A7))
{ // ([bd,An,...
}
else if ((*tok >= KW_A0) && (*tok <= KW_A7))
{ // ([bd,An,...
- AnREG = (6 << 3) | *tok & 7;
+ AnREG = (6 << 3) | (*tok & 7);
tok++;
}
else if ((*tok >= KW_D0) && (*tok <= KW_D7))
tok++;
}
else if ((*tok >= KW_D0) && (*tok <= KW_D7))
if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
goto badmode;
if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
goto badmode;
- if (CHECK_OPTS(OPT_BASE_DISP) && (AnEXVAL == 0))
+ if (CHECK_OPTS(OPT_BASE_DISP) && (AnEXATTR & DEFINED) && (AnEXVAL == 0))
{
// od=0 so optimise it out
AMn = MEMPOST; // let's say it's ([bd,An],Xn,od) with od=0 then
{
// od=0 so optimise it out
AMn = MEMPOST; // let's say it's ([bd,An],Xn,od) with od=0 then
if (*tok == DOTL)
{
// expr.L
if (*tok == DOTL)
{
// expr.L
- AnEXTEN |= EXT_IISPOSL; // Long outer displacement
+ if (!(AnEXTEN & EXT_BS))
+ AnEXTEN |= EXT_IISPOSL; // Long outer displacement
+ else
+ {
+ // bd is suppressed, so sticking the od size in bd
+ AnEXTEN |= EXT_BDSIZEL;
+ // And of course the expression has to be copied to
+ // AnBEXPR instead of AnEXPR. Yay. :-/
+ int i = 0;
+
+ do
+ {
+ AnBEXPR[i] = AnEXPR[i];
+ i++;
+ }
+ while (AnEXPR[i] != 'E');
+
+ AnBEXPR[i] = 'E';
+ }
+
}
else if (*tok == ',')
{
}
else if (*tok == ',')
{
- *tok++; // ([bd,An,Xn.size*scale],od)
+ tok++; // ([bd,An,Xn.size*scale],od)
if ((*tok >= KW_A0) && (*tok <= KW_A7))
{
AnEXTEN |= ((*tok & 7) << 12);
if ((*tok >= KW_A0) && (*tok <= KW_A7))
{
AnEXTEN |= ((*tok & 7) << 12);
- // ([bd,An/PC],Xn.W/L...)
- switch ((int)*tok)
+ // ([bd,An/PC],Xn.W/L...)
+ switch ((int)*tok)
{
// Index reg size: <empty> | .W | .L
case DOTW:
{
// Index reg size: <empty> | .W | .L
case DOTW:
- if (*tok == '*') // ([bd,An/PC],Xn*...)
- { // scale: *1, *2, *4, *8
+ if (*tok == '*') // ([bd,An/PC],Xn*...)
+ { // scale: *1, *2, *4, *8
tok++;
if (*tok == SYMBOL)
tok++;
if (*tok == SYMBOL)
}
// If we got a register in range (0-31), return it
}
// If we got a register in range (0-31), return it
- if ((eval >= 0) && (eval <= 31))
return (int)eval;
// Otherwise, it's out of range & we flag an error
return (int)eval;
// Otherwise, it's out of range & we flag an error
ccsym = lookup(string[tok[1]], LABEL, 0);
if (ccsym && (ccsym->sattre & EQUATEDCC) && !(ccsym->sattre & UNDEF_CC))
ccsym = lookup(string[tok[1]], LABEL, 0);
if (ccsym && (ccsym->sattre & EQUATEDCC) && !(ccsym->sattre & UNDEF_CC))
+ val = (int)ccsym->svalue;
else
return error("unknown condition code");
}
else
return error("unknown condition code");
}
// and export all global-referenced labels. Not sure if this is
// required but it's here nonetheless
// and export all global-referenced labels. Not sure if this is
// required but it's here nonetheless
- //for(sy=sdecl; sy!=NULL; sy=sy->sorder)
for(SYM * sy=sdecl; sy!=NULL; sy=sy->sdecl)
{
if ((sy->stype == LABEL)
for(SYM * sy=sdecl; sy!=NULL; sy=sy->sdecl)
{
if ((sy->stype == LABEL)