//
// RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
// MACH.C - Code Generation
-// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends
+// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends
// RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
// Source utilised with the kind permission of Landon Dyer
//
#include "kwtab.h"
-// Fucntion prototypes
+// Fucntion prototypes
int m_unimp(WORD, WORD), m_badmode(WORD, WORD), m_bad6mode(WORD, WORD), m_bad6inst(WORD, WORD);
int m_self(WORD, WORD);
int m_abcd(WORD, WORD);
// Include code tables
MNTAB machtab[] = {
-// { (WORD)-1, (unsigned long)-1L, (unsigned long)-1L, 0x0000, 0, m_badmode }, // 0
- { 0xFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000, 0, m_badmode }, // 0
+// { (WORD)-1, (unsigned long)-1L, (unsigned long)-1L, 0x0000, 0, m_badmode }, // 0
+ { 0xFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000, 0, m_badmode }, // 0
#include "68ktab.h"
{ 0, 0L, 0L, 0x0000, 0, m_unimp } // Last entry
};
// SIZB==>00, SIZW==>01, SIZL==>10, SIZN==>01 << 6
WORD siz_6[] = {
- (WORD)-1, // n/a
+ (WORD)-1, // n/a
0, // SIZB
- 1<<6, (WORD)-1, // SIZW, n/a
- 2<<6, (WORD)-1, (WORD)-1, (WORD)-1, // SIZL, n/a, n/a, n/a
- 1<<6 // SIZN
+ 1<<6, (WORD)-1, // SIZW, n/a
+ 2<<6, (WORD)-1, (WORD)-1, (WORD)-1, // SIZL, n/a, n/a, n/a
+ 1<<6 // SIZN
};
// Byte/word/long size for MOVE instrs
WORD siz_12[] = {
(WORD)-1,
- 0x1000, // Byte
- 0x3000, (WORD)-1, // Word
+ 0x1000, // Byte
+ 0x3000, (WORD)-1, // Word
0x2000, (WORD)-1, (WORD)-1, (WORD)-1, // Long
0x3000 // Word (SIZN)
};
//
// Do one EA in bits 0..5
-//
+//
// Bits in `inst' have the following meaning:
-//
+//
// Bit zero specifies which ea (ea0 or ea1) to generate in the lower six bits
// of the instr.
-//
+//
// If bit one is set, the OTHER ea (the one that wasn't generated by bit zero)
// is generated after the instruction. Regardless of bit 0's value, ea0 is
// always deposited in memory before ea1.
-//
+//
// If bit two is set, standard size bits are set in the instr in bits 6 and 7.
-//
+//
// If bit four is set, bit three specifies which eaXreg to place in bits 9..11
// of the instr.
//
int m_ea(WORD inst, WORD siz)
{
- WORD flg = inst; // Save flag bits
- inst &= ~0x3F; // Clobber flag bits in instr
+ WORD flg = inst; // Save flag bits
+ inst &= ~0x3F; // Clobber flag bits in instr
- // Install "standard" instr size bits
+ // Install "standard" instr size bits
if (flg & 4)
inst |= siz_6[siz];
if (flg & 16)
{
- // OR-in register number
+ // OR-in register number
if (flg & 8)
- inst |= reg_9[a1reg]; // ea1reg in bits 9..11
+ inst |= reg_9[a1reg]; // ea1reg in bits 9..11
else
- inst |= reg_9[a0reg]; // ea0reg in bits 9..11
+ inst |= reg_9[a0reg]; // ea0reg in bits 9..11
}
if (flg & 1)
{
- // Use am1
- inst |= am1 | a1reg; // Get ea1 into instr
- D_word(inst); // Deposit instr
+ // Use am1
+ inst |= am1 | a1reg; // Get ea1 into instr
+ D_word(inst); // Deposit instr
- // Generate ea0 if requested
+ // Generate ea0 if requested
if (flg & 2)
ea0gen(siz);
- ea1gen(siz); // Generate ea1
+ ea1gen(siz); // Generate ea1
}
else
{
- // Use am0
- inst |= am0 | a0reg; // Get ea0 into instr
- D_word(inst); // Deposit instr
- ea0gen(siz); // Generate ea0
+ // Use am0
+ inst |= am0 | a0reg; // Get ea0 into instr
+ D_word(inst); // Deposit instr
+ ea0gen(siz); // Generate ea0
- // Generate ea1 if requested
+ // Generate ea1 if requested
if (flg & 2)
ea1gen(siz);
}
{
if (inst & 1)
{
- // Install size bits
+ // Install size bits
inst--;
inst |= siz_6[siz];
}
{
inst |= am0 | a0reg | lwsiz_8[siz] | reg_9[a1reg];
D_word(inst);
- ea0gen(siz); // Generate EA
+ ea0gen(siz); // Generate EA
return 0;
}
//
// If bit 0 of `inst' is 1, install size bits in bits 6..7 of instr.
// If bit 1 of `inst' is 1, install a1reg in bits 9..11 of instr.
-//
+//
int m_reg(WORD inst, WORD siz)
{
if (inst & 1)
- // Install size bits
+ // Install size bits
inst |= siz_6[siz];
if (inst & 2)
- // Install other register (9..11)
+ // Install other register (9..11)
inst |= reg_9[a1reg];
- inst &= ~7; // Clear off crufty bits
- inst |= a0reg; // Install first register
+ inst &= ~7; // Clear off crufty bits
+ inst |= a0reg; // Install first register
D_word(inst);
return 0;
{
// Enforce instruction sizes
if (am1 == DREG)
- { // X,Dn must be .n or .l
+ { // X,Dn must be .n or .l
if (siz & (SIZB | SIZW))
return error(siz_error);
}
- else if (siz & (SIZW | SIZL)) // X,ea must be .n or .b
+ else if (siz & (SIZW | SIZL)) // X,ea must be .n or .b
return error(siz_error);
// Construct instr and EAs
if (am0 == IMMED)
{
D_word(inst);
- ea0gen(SIZB); // Immediate bit number
+ ea0gen(SIZB); // Immediate bit number
}
else
{
D_word(inst);
}
- // ea to bit-munch
+ // ea to bit-munch
ea1gen(SIZB);
return 0;
siz = siz;
if (am0 == DREG && am1 == DREG)
- m = 0x0040; // Dn,Dn
+ m = 0x0040; // Dn,Dn
else if (am0 == AREG && am1 == AREG)
- m = 0x0048; // An,An
+ m = 0x0048; // An,An
else
{
if (am0 == AREG)
- { // Dn,An or An,Dn
- m = a1reg; // Get AREG into a1reg
+ { // Dn,An or An,Dn
+ m = a1reg; // Get AREG into a1reg
a1reg = a0reg;
a0reg = m;
}
//
// Handle MOVE <C_ALL> <C_ALTDATA>
// MOVE <C_ALL> <M_AREG>
-//
+//
// Optimize MOVE.L #<smalldata>,D0 to a MOVEQ
//
int m_move(WORD inst, WORD size)
int siz = (int)size;
// Try to optimize to MOVEQ
- if (optim_flag && siz == SIZL && am0 == IMMED && am1 == DREG
+ if (optim_flags[OPT_MOVEL_MOVEQ] && siz == SIZL && am0 == IMMED && am1 == DREG
&& (a0exattr & (TDB|DEFINED)) == DEFINED && a0exval + 0x80 < 0x100)
{
m_moveq((WORD)0x7000, (WORD)0);
siz = siz;
if (am0 == AM_USP)
- inst |= a1reg; // USP, An
+ inst |= a1reg; // USP, An
else
- inst |= a0reg; // An, USP
+ inst |= a0reg; // An, USP
D_word(inst);
{
siz = siz;
- // Arrange for future fixup
+ // Arrange for future fixup
if (!(a0exattr & DEFINED))
{
AddFixup(FU_BYTE | FU_SEXT, sloc + 1, a0expr);
- a0exval = 0;
+ a0exval = 0;
}
else if (a0exval + 0x100 >= 0x200)
return error(range_error);
return 0;
}
-
+int movep = 0; // Global flag to indicate we're generating a movep instruction
//
// movep Dn, disp(An) -- movep disp(An), Dn
//
int m_movep(WORD inst, WORD siz)
{
+ movep = 1; // Tell ea0gen to lay off the 0(a0) optimisations on this one
if (siz == SIZL)
inst |= 0x0040;
if (am1 == AIND)
D_word(0)
- else
+ else
ea1gen(siz);
}
else
if (am0 == AIND)
D_word(0)
- else
+ else
ea0gen(siz);
}
+ movep = 0;
return 0;
}
// Optimize branch instr. size
if (siz == SIZN)
{
- if (optim_flag && v != 0 && v + 0x80 < 0x100)
+ if (optim_flags[OPT_BSR_BCC_S] && v != 0 && v + 0x80 < 0x100)
{
- // Fits in .B
+ // Fits in .B
inst |= v & 0xFF;
D_word(inst);
if (sbra_flag)
}
else
{
- // Fits in .W
+ // Fits in .W
if (v + 0x8000 > 0x10000)
return error(range_error);
if (siz == SIZB)
{
- // .B
+ // .B
AddFixup(FU_BBRA | FU_PCREL | FU_SEXT, sloc, a0expr);
D_word(inst);
return 0;
}
else
{
- // .W
+ // .W
D_word(inst);
AddFixup(FU_WORD | FU_PCREL | FU_LBRA | FU_ISBRA, sloc, a0expr);
D_word(0);
if (a0exattr & DEFINED)
{
- if (a0exval > 8 || a0exval == 0) // Range in 1..8
+ if (a0exval > 8 || a0exval == 0) // Range in 1..8
return error(range_error);
inst |= (a0exval & 7) << 9;
inst |= a0exval;
D_word(inst);
}
- else
+ else
return error(undef_error);
return 0;
if (*tok == '#')
{
- // Handle #<expr>, ea
+ // Handle #<expr>, ea
tok++;
if (abs_expr(&eval) != OK)
if (*tok >= KW_D0 && *tok <= KW_A7)
{
- // <rlist>, ea
+ // <rlist>, ea
if (reglist(&rmask) < 0)
return 0;
}
else
{
- // ea, <rlist>
+ // ea, <rlist>
if (amode(0) < 0)
return 0;
if (*tok == '#')
{
- // ea, #<expr>
+ // ea, #<expr>
tok++;
if (abs_expr(&eval) != OK)