Add "*" symbol for current address in inline assembler

This commit is contained in:
drmortalwombat 2022-01-29 13:33:57 +01:00
parent 5ca651bc36
commit 60165a7fc3
14 changed files with 373 additions and 55 deletions

View File

@ -480,7 +480,7 @@ void bm_polygon_nc_fill(Bitmap * bm, ClipRect * clip, int * px, int * py, char n
#define REG_D0 0x0a #define REG_D0 0x0a
#define REG_D1 0x0b #define REG_D1 0x0b
static void buildline(char ly, char lx, int dx, int dy, int stride, bool left, bool up) static void buildline(char ly, char lx, int dx, int dy, int stride, bool left, bool up, char pattern, LineOp op)
{ {
char ip = 0; char ip = 0;
@ -491,6 +491,9 @@ static void buildline(char ly, char lx, int dx, int dy, int stride, bool left, b
// set pixel // set pixel
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_D0); ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_D0);
switch (op)
{
case LINOP_SET:
ip += asm_zp(BLIT_CODE + ip, ASM_ASL, REG_PAT); ip += asm_zp(BLIT_CODE + ip, ASM_ASL, REG_PAT);
ip += asm_rl(BLIT_CODE + ip, ASM_BCC, 6); ip += asm_rl(BLIT_CODE + ip, ASM_BCC, 6);
ip += asm_zp(BLIT_CODE + ip, ASM_INC, REG_PAT); ip += asm_zp(BLIT_CODE + ip, ASM_INC, REG_PAT);
@ -499,6 +502,39 @@ static void buildline(char ly, char lx, int dx, int dy, int stride, bool left, b
ip += asm_im(BLIT_CODE + ip, ASM_EOR, 0xff); ip += asm_im(BLIT_CODE + ip, ASM_EOR, 0xff);
ip += asm_iy(BLIT_CODE + ip, ASM_AND, REG_SP); ip += asm_iy(BLIT_CODE + ip, ASM_AND, REG_SP);
ip += asm_iy(BLIT_CODE + ip, ASM_STA, REG_SP); ip += asm_iy(BLIT_CODE + ip, ASM_STA, REG_SP);
break;
case LINOP_OR:
if (pattern != 0xff)
{
ip += asm_zp(BLIT_CODE + ip, ASM_ASL, REG_PAT);
ip += asm_rl(BLIT_CODE + ip, ASM_BCC, 6);
ip += asm_zp(BLIT_CODE + ip, ASM_INC, REG_PAT);
}
ip += asm_iy(BLIT_CODE + ip, ASM_ORA, REG_SP);
ip += asm_iy(BLIT_CODE + ip, ASM_STA, REG_SP);
break;
case LINOP_XOR:
if (pattern != 0xff)
{
ip += asm_zp(BLIT_CODE + ip, ASM_ASL, REG_PAT);
ip += asm_rl(BLIT_CODE + ip, ASM_BCC, 6);
ip += asm_zp(BLIT_CODE + ip, ASM_INC, REG_PAT);
}
ip += asm_iy(BLIT_CODE + ip, ASM_EOR, REG_SP);
ip += asm_iy(BLIT_CODE + ip, ASM_STA, REG_SP);
break;
case LINOP_AND:
if (pattern != 0xff)
{
ip += asm_zp(BLIT_CODE + ip, ASM_ASL, REG_PAT);
ip += asm_rl(BLIT_CODE + ip, ASM_BCC, 8);
ip += asm_zp(BLIT_CODE + ip, ASM_INC, REG_PAT);
}
ip += asm_im(BLIT_CODE + ip, ASM_EOR, 0xff);
ip += asm_iy(BLIT_CODE + ip, ASM_AND, REG_SP);
ip += asm_iy(BLIT_CODE + ip, ASM_STA, REG_SP);
break;
}
// m >= 0 // m >= 0
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP + 1); ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP + 1);
@ -587,8 +623,21 @@ static inline void callline(byte * dst, byte bit, int m, char lh, char pattern)
} }
} }
void bmu_line(Bitmap * bm, int x0, int y0, int x1, int y1, char pattern) void bmu_line(Bitmap * bm, int x0, int y0, int x1, int y1, char pattern, LineOp op)
{ {
if (pattern == 0x00)
{
if (op == LINOP_SET)
{
pattern = 0xff;
op = LINOP_AND;
}
else
return;
}
else if (pattern == 0xff && op == LINOP_SET)
op = LINOP_OR;
int dx = x1 - x0, dy = y1 - y0; int dx = x1 - x0, dy = y1 - y0;
byte quad = 0; byte quad = 0;
if (dx < 0) if (dx < 0)
@ -617,7 +666,7 @@ void bmu_line(Bitmap * bm, int x0, int y0, int x1, int y1, char pattern)
char ry = y0 & 7; char ry = y0 & 7;
int stride = 8 * bm->cwidth; int stride = 8 * bm->cwidth;
buildline(ry, (l + 1) & 0xff, dx, dy, (quad & 2) ? -stride : stride, quad & 1, quad & 2); buildline(ry, (l + 1) & 0xff, dx, dy, (quad & 2) ? -stride : stride, quad & 1, quad & 2, pattern, op);
callline(dp, bit, m, l >> 8, pattern); callline(dp, bit, m, l >> 8, pattern);
} }
@ -627,7 +676,7 @@ static int muldiv(int x, int mul, int div)
return (int)((long)x * mul / div); return (int)((long)x * mul / div);
} }
void bm_line(Bitmap * bm, ClipRect * clip, int x0, int y0, int x1, int y1, char pattern) void bm_line(Bitmap * bm, ClipRect * clip, int x0, int y0, int x1, int y1, char pattern, LineOp op)
{ {
int dx = x1 - x0, dy = y1 - y0; int dx = x1 - x0, dy = y1 - y0;
@ -711,7 +760,7 @@ void bm_line(Bitmap * bm, ClipRect * clip, int x0, int y0, int x1, int y1, char
return; return;
} }
bmu_line(bm, x0, y0, x1, y1, pattern); bmu_line(bm, x0, y0, x1, y1, pattern, op);
} }
static inline void callddop(byte * src, byte * dst, byte pat) static inline void callddop(byte * src, byte * dst, byte pat)

View File

@ -48,6 +48,14 @@ enum BlitOp
BLTOP_PATTERN_AND_SRC = BLIT_SRC | BLIT_PATTERN | BLIT_AND BLTOP_PATTERN_AND_SRC = BLIT_SRC | BLIT_PATTERN | BLIT_AND
}; };
enum LineOp
{
LINOP_SET,
LINOP_OR,
LINOP_AND,
LINOP_XOR
};
extern char NineShadesOfGrey[9][8]; extern char NineShadesOfGrey[9][8];
// Fast unsigned integer square root // Fast unsigned integer square root
@ -102,10 +110,10 @@ inline bool bm_get(Bitmap * bm, int x, int y);
inline void bm_put(Bitmap * bm, int x, int y, bool c); inline void bm_put(Bitmap * bm, int x, int y, bool c);
// Draw an unclipped line using an eight bit pattern // Draw an unclipped line using an eight bit pattern
void bmu_line(Bitmap * bm, int x0, int y0, int x1, int y1, char pattern); void bmu_line(Bitmap * bm, int x0, int y0, int x1, int y1, char pattern, LineOp op);
// Draw a clipped line using an eight bit pattern // Draw a clipped line using an eight bit pattern
void bm_line(Bitmap * bm, ClipRect * clip, int x0, int y0, int x1, int y1, char pattern); void bm_line(Bitmap * bm, ClipRect * clip, int x0, int y0, int x1, int y1, char pattern, LineOp op);
// Unclipped bit blit // Unclipped bit blit
void bmu_bitblit(Bitmap * dbm, int dx, int dy, Bitmap * sbm, int sx, int sy, int w, int h, const char * pattern, BlitOp op); void bmu_bitblit(Bitmap * dbm, int dx, int dy, Bitmap * sbm, int sx, int sy, int w, int h, const char * pattern, BlitOp op);

View File

@ -545,8 +545,18 @@ void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression* ex
case ASMIM_RELATIVE: case ASMIM_RELATIVE:
if (!aexp) if (!aexp)
mErrors->Error(cexp->mLocation, EERR_ASM_INVALD_OPERAND, "Missing assembler operand"); mErrors->Error(cexp->mLocation, EERR_ASM_INVALD_OPERAND, "Missing assembler operand");
else
{
if (aexp->mType == DT_LABEL_REF)
{
if (aexp->mBase->mBase)
d[offset] = aexp->mOffset + aexp->mBase->mInteger - offset - 1;
else
mErrors->Error(aexp->mLocation, EERR_ASM_INVALD_OPERAND, "Undefined immediate operand", aexp->mBase->mIdent->mString);
}
else else
d[offset] = aexp->mInteger - offset - 1; d[offset] = aexp->mInteger - offset - 1;
}
offset++; offset++;
break; break;
} }

View File

@ -11683,6 +11683,49 @@ bool NativeCodeBasicBlock::OptimizeInnerLoops(NativeCodeProcedure* proc)
} }
bool NativeCodeBasicBlock::OptimizeSelect(NativeCodeProcedure* proc)
{
bool changed = false;
if (!mVisited)
{
mVisited = true;
if (mFalseJump && mIns.Size() > 0 && mIns.Last().ChangesAccuAndFlag() &&
mTrueJump->mIns.Size() == 1 && mFalseJump->mIns.Size() == 1 &&
!mTrueJump->mFalseJump && !mFalseJump->mFalseJump && mTrueJump->mTrueJump == mFalseJump->mTrueJump &&
mTrueJump->mIns[0].mType == ASMIT_LDA && mTrueJump->mIns[0].mMode == ASMIM_IMMEDIATE &&
mFalseJump->mIns[0].mType == ASMIT_LDA && mFalseJump->mIns[0].mMode == ASMIM_IMMEDIATE)
{
if (mBranch == ASMIT_BNE || mBranch == ASMIT_BEQ)
{
char vt = mTrueJump->mIns[0].mAddress, vf = mFalseJump->mIns[0].mAddress;
mTrueJump = mTrueJump->mTrueJump;
mFalseJump = nullptr;
if (mBranch == ASMIT_BEQ)
{
char t = vt; vt = vf; vf = t;
}
mIns.Push(NativeCodeInstruction(ASMIT_CMP, ASMIM_IMMEDIATE, 1));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, vt ^ vf));
mIns.Push(NativeCodeInstruction(ASMIT_EOR, ASMIM_IMMEDIATE, vt));
changed = true;
}
}
if (mTrueJump && mTrueJump->OptimizeSelect(proc))
changed = true;
if (mFalseJump && mFalseJump->OptimizeSelect(proc))
changed = true;
}
return changed;
}
// Size reduction violating various assumptions such as no branches in basic blocks // Size reduction violating various assumptions such as no branches in basic blocks
// must be last step before actual assembly // must be last step before actual assembly
@ -11931,6 +11974,33 @@ void NativeCodeBasicBlock::BlockSizeReduction(void)
j += 2; j += 2;
i += 3; i += 3;
} }
else if (i + 5 < mIns.Size() &&
mIns[i + 0].mType == ASMIT_LDA &&
mIns[i + 1].mType == ASMIT_CMP && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0x01 &&
mIns[i + 2].mType == ASMIT_LDA && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 0x00 &&
mIns[i + 3].mType == ASMIT_ADC && mIns[i + 3].mMode == ASMIM_IMMEDIATE && mIns[i + 3].mAddress == 0xff &&
mIns[i + 4].mType == ASMIT_AND && mIns[i + 4].mMode == ASMIM_IMMEDIATE &&
mIns[i + 5].mType == ASMIT_EOR && mIns[i + 5].mMode == ASMIM_IMMEDIATE)
{
char veq = mIns[i + 4].mAddress ^ mIns[i + 5].mAddress, vne = mIns[i + 5].mAddress;
mIns[j + 0] = mIns[i + 0];
mIns[j + 1].mType = ASMIT_BEQ; mIns[j + 1].mMode = ASMIM_RELATIVE; mIns[j + 1].mAddress = veq != 0 ? 4 : 2;
mIns[j + 2].mType = ASMIT_LDA; mIns[j + 2].mMode = ASMIM_IMMEDIATE; mIns[j + 2].mAddress = vne; mIns[j + 2].mFlags = 0;
j += 3;
if (veq != 0)
{
if (vne)
mIns[j + 0].mType = ASMIT_BNE;
else
mIns[j + 0].mType = ASMIT_BEQ;
mIns[j + 0].mMode = ASMIM_RELATIVE;
mIns[j + 0].mAddress = 2;
mIns[j + 1].mType = ASMIT_LDA; mIns[j + 1].mMode = ASMIM_IMMEDIATE; mIns[j + 1].mAddress = veq; mIns[j + 1].mFlags = 0;
j += 2;
}
i += 6;
}
else else
mIns[j++] = mIns[i++]; mIns[j++] = mIns[i++];
} }
@ -12480,6 +12550,92 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
#endif #endif
#if 1
// move iny/dey/inx/dex down
for (int i = 0; i + 1 < mIns.Size(); i++)
{
if ((mIns[i].mType == ASMIT_INY || mIns[i].mType == ASMIT_DEY) && !mIns[i + 1].ChangesYReg() && !(mIns[i + 1].mLive & LIVE_CPU_REG_Z))
{
if (!mIns[i + 1].RequiresYReg())
{
NativeCodeInstruction pins = mIns[i];
mIns[i] = mIns[i + 1];
mIns[i + 1] = pins;
}
else if (mIns[i + 1].mMode == ASMIM_ABSOLUTE_Y)
{
if (mIns[i].mType == ASMIT_INY)
mIns[i + 1].mAddress++;
else
mIns[i + 1].mAddress--;
NativeCodeInstruction pins = mIns[i];
mIns[i] = mIns[i + 1];
mIns[i + 1] = pins;
}
}
else if ((mIns[i].mType == ASMIT_INX || mIns[i].mType == ASMIT_DEX) && !mIns[i + 1].ChangesXReg() && !(mIns[i + 1].mLive & LIVE_CPU_REG_Z))
{
if (!mIns[i + 1].RequiresXReg())
{
NativeCodeInstruction pins = mIns[i];
mIns[i] = mIns[i + 1];
mIns[i + 1] = pins;
}
else if (mIns[i + 1].mMode == ASMIM_ABSOLUTE_X)
{
if (mIns[i].mType == ASMIT_INX)
mIns[i + 1].mAddress++;
else
mIns[i + 1].mAddress--;
NativeCodeInstruction pins = mIns[i];
mIns[i] = mIns[i + 1];
mIns[i + 1] = pins;
}
}
}
#endif
#if 1
// move tya/clc/adc/tay down
for (int i = 0; i + 5 < mIns.Size(); i++)
{
if (mIns[i + 0].mType == ASMIT_TYA && mIns[i + 1].mType == ASMIT_CLC && mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 3].mType == ASMIT_TAY && !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C)))
{
if (mIns[i + 4].mType == ASMIT_LDA && (mIns[i + 4].mMode == ASMIM_IMMEDIATE || mIns[i + 4].mMode == ASMIM_IMMEDIATE_ADDRESS || mIns[i + 4].mMode == ASMIM_ZERO_PAGE) &&
mIns[i + 5].mType == ASMIT_STA && !(mIns[i + 5].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)))
{
mIns[i + 4].mLive |= LIVE_CPU_REG_Y;
mIns[i + 5].mLive |= LIVE_CPU_REG_Y;
if (mIns[i + 5].mMode == ASMIM_ABSOLUTE_Y)
mIns[i + 5].mAddress += mIns[i + 2].mAddress;
mIns.Insert(i + 0, mIns[i + 4]); mIns.Remove(i + 5);
mIns.Insert(i + 1, mIns[i + 5]); mIns.Remove(i + 6);
}
#if 1
else if (i + 6 < mIns.Size() &&
mIns[i + 4].mType == ASMIT_LDA && (mIns[i + 4].mMode == ASMIM_IMMEDIATE || mIns[i + 4].mMode == ASMIM_IMMEDIATE_ADDRESS || mIns[i + 4].mMode == ASMIM_ZERO_PAGE) &&
mIns[i + 5].mType == ASMIT_STA &&
mIns[i + 6].mType == ASMIT_STA && !(mIns[i + 6].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)))
{
mIns[i + 4].mLive |= LIVE_CPU_REG_Y;
mIns[i + 5].mLive |= LIVE_CPU_REG_Y;
mIns[i + 6].mLive |= LIVE_CPU_REG_Y;
if (mIns[i + 5].mMode == ASMIM_ABSOLUTE_Y)
mIns[i + 5].mAddress += mIns[i + 2].mAddress;
if (mIns[i + 6].mMode == ASMIM_ABSOLUTE_Y)
mIns[i + 6].mAddress += mIns[i + 2].mAddress;
mIns.Insert(i + 0, mIns[i + 4]); mIns.Remove(i + 5);
mIns.Insert(i + 1, mIns[i + 5]); mIns.Remove(i + 6);
mIns.Insert(i + 2, mIns[i + 6]); mIns.Remove(i + 7);
}
#endif
}
}
#endif
#if 1 #if 1
// reverse "sta t,lda abs,clc,adc t" to "sta t,clc,adc abs,nop" // reverse "sta t,lda abs,clc,adc t" to "sta t,clc,adc abs,nop"
@ -14438,6 +14594,83 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
#endif #endif
} }
if (i + 3 < mIns.Size())
{
if (
mIns[i + 0].mType == ASMIT_INY &&
mIns[i + 1].mType == ASMIT_TYA &&
mIns[i + 2].mType == ASMIT_CLC &&
mIns[i + 3].mType == ASMIT_ADC && mIns[i + 3].mMode == ASMIM_IMMEDIATE && !(mIns[i + 3].mLive & (LIVE_CPU_REG_Y | LIVE_CPU_REG_C)))
{
mIns[i + 0].mType = ASMIT_NOP;
mIns[i + 3].mAddress++;
progress = true;
}
else if (
mIns[i + 0].mType == ASMIT_CLC &&
mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_IMMEDIATE &&
mIns[i + 2].mType == ASMIT_TAY &&
mIns[i + 3].mType == ASMIT_INY && !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C)))
{
mIns[i + 1].mAddress++;
mIns[i + 3].mType = ASMIT_NOP;
progress = true;
}
else if (
mIns[i + 0].mType == ASMIT_INX &&
mIns[i + 1].mType == ASMIT_TXA &&
mIns[i + 2].mType == ASMIT_CLC &&
mIns[i + 3].mType == ASMIT_ADC && mIns[i + 3].mMode == ASMIM_IMMEDIATE && !(mIns[i + 3].mLive & (LIVE_CPU_REG_X | LIVE_CPU_REG_C)))
{
mIns[i + 0].mType = ASMIT_NOP;
mIns[i + 3].mAddress++;
progress = true;
}
else if (
mIns[i + 0].mType == ASMIT_CLC &&
mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_IMMEDIATE &&
mIns[i + 2].mType == ASMIT_TAX &&
mIns[i + 3].mType == ASMIT_INX && !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C)))
{
mIns[i + 1].mAddress++;
mIns[i + 3].mType = ASMIT_NOP;
progress = true;
}
}
#if 1
if (pass > 2 && i + 4 < mIns.Size())
{
if (
mIns[i + 0].mType == ASMIT_INY &&
mIns[i + 1].mType == ASMIT_INY &&
mIns[i + 2].mType == ASMIT_INY &&
mIns[i + 3].mType == ASMIT_INY &&
mIns[i + 4].mType == ASMIT_INY && !(mIns[i + 4].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C)))
{
mIns[i + 0].mType = ASMIT_TYA; mIns[i + 0].mLive |= LIVE_CPU_REG_A;
mIns[i + 1].mType = ASMIT_CLC; mIns[i + 1].mLive |= LIVE_CPU_REG_A;
mIns[i + 2].mType = ASMIT_ADC; mIns[i + 2].mMode = ASMIM_IMMEDIATE; mIns[i + 2].mAddress = 5; mIns[i + 2].mLive |= LIVE_CPU_REG_A;
mIns[i + 3].mType = ASMIT_TAY;
mIns[i + 4].mType = ASMIT_NOP;
progress = true;
}
else if (
mIns[i + 0].mType == ASMIT_INX &&
mIns[i + 1].mType == ASMIT_INX &&
mIns[i + 2].mType == ASMIT_INX &&
mIns[i + 3].mType == ASMIT_INX &&
mIns[i + 4].mType == ASMIT_INX && !(mIns[i + 4].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C)))
{
mIns[i + 0].mType = ASMIT_TXA; mIns[i + 0].mLive |= LIVE_CPU_REG_A;
mIns[i + 1].mType = ASMIT_CLC; mIns[i + 1].mLive |= LIVE_CPU_REG_A;
mIns[i + 2].mType = ASMIT_ADC; mIns[i + 2].mMode = ASMIM_IMMEDIATE; mIns[i + 2].mAddress = 5; mIns[i + 2].mLive |= LIVE_CPU_REG_A;
mIns[i + 3].mType = ASMIT_TAX;
mIns[i + 4].mType = ASMIT_NOP;
progress = true;
}
}
#endif
if (i + 5 < mIns.Size()) if (i + 5 < mIns.Size())
{ {
if ( if (
@ -15602,6 +15835,12 @@ void NativeCodeProcedure::Optimize(void)
#endif #endif
#if 1 #if 1
ResetVisited();
if (mEntryBlock->OptimizeSelect(this))
{
changed = true;
}
if (step > 0) if (step > 0)
{ {
ResetVisited(); ResetVisited();

View File

@ -151,6 +151,8 @@ public:
bool SimpleLoopReversal(NativeCodeProcedure* proc); bool SimpleLoopReversal(NativeCodeProcedure* proc);
bool OptimizeInnerLoop(NativeCodeProcedure* proc, NativeCodeBasicBlock* head, NativeCodeBasicBlock* tail, GrowingArray<NativeCodeBasicBlock*>& blocks); bool OptimizeInnerLoop(NativeCodeProcedure* proc, NativeCodeBasicBlock* head, NativeCodeBasicBlock* tail, GrowingArray<NativeCodeBasicBlock*>& blocks);
bool OptimizeSelect(NativeCodeProcedure* proc);
NativeCodeBasicBlock* FindTailBlock(NativeCodeBasicBlock* head); NativeCodeBasicBlock* FindTailBlock(NativeCodeBasicBlock* head);
bool OptimizeInnerLoops(NativeCodeProcedure* proc); bool OptimizeInnerLoops(NativeCodeProcedure* proc);
void CollectInnerLoop(NativeCodeBasicBlock* head, GrowingArray<NativeCodeBasicBlock*>& lblocks); void CollectInnerLoop(NativeCodeBasicBlock* head, GrowingArray<NativeCodeBasicBlock*>& lblocks);

View File

@ -2194,7 +2194,7 @@ Expression* Parser::ParseSwitchStatement(void)
Expression* Parser::ParseAssemblerBaseOperand(void) Expression* Parser::ParseAssemblerBaseOperand(Declaration* pcasm, int pcoffset)
{ {
Expression* exp = nullptr; Expression* exp = nullptr;
Declaration* dec; Declaration* dec;
@ -2203,7 +2203,7 @@ Expression* Parser::ParseAssemblerBaseOperand(void)
{ {
case TK_SUB: case TK_SUB:
mScanner->NextToken(); mScanner->NextToken();
exp = ParseAssemblerBaseOperand(); exp = ParseAssemblerBaseOperand(pcasm, pcoffset);
if (exp->mType == EX_CONSTANT && exp->mDecValue->mType == DT_CONST_INTEGER) if (exp->mType == EX_CONSTANT && exp->mDecValue->mType == DT_CONST_INTEGER)
{ {
dec = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); dec = new Declaration(mScanner->mLocation, DT_CONST_INTEGER);
@ -2220,6 +2220,16 @@ Expression* Parser::ParseAssemblerBaseOperand(void)
mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Cannot negate expression"); mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Cannot negate expression");
break; break;
case TK_MUL:
mScanner->NextToken();
exp = new Expression(mScanner->mLocation, EX_CONSTANT);
dec = new Declaration(mScanner->mLocation, DT_LABEL);
exp->mDecType = TheUnsignedIntTypeDeclaration;
exp->mDecValue = dec;
dec->mInteger = pcoffset;
dec->mBase = pcasm;
break;
case TK_INTEGER: case TK_INTEGER:
dec = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); dec = new Declaration(mScanner->mLocation, DT_CONST_INTEGER);
dec->mInteger = mScanner->mTokenInteger; dec->mInteger = mScanner->mTokenInteger;
@ -2329,31 +2339,31 @@ Expression* Parser::ParseAssemblerBaseOperand(void)
return exp; return exp;
} }
Expression* Parser::ParseAssemblerMulOperand(void) Expression* Parser::ParseAssemblerMulOperand(Declaration* pcasm, int pcoffset)
{ {
Expression* exp = ParseAssemblerBaseOperand(); Expression* exp = ParseAssemblerBaseOperand(pcasm, pcoffset);
while (mScanner->mToken == TK_MUL || mScanner->mToken == TK_DIV || mScanner->mToken == TK_MOD) while (mScanner->mToken == TK_MUL || mScanner->mToken == TK_DIV || mScanner->mToken == TK_MOD)
{ {
Expression* nexp = new Expression(mScanner->mLocation, EX_BINARY); Expression* nexp = new Expression(mScanner->mLocation, EX_BINARY);
nexp->mToken = mScanner->mToken; nexp->mToken = mScanner->mToken;
nexp->mLeft = exp; nexp->mLeft = exp;
mScanner->NextToken(); mScanner->NextToken();
nexp->mRight = ParseAssemblerBaseOperand(); nexp->mRight = ParseAssemblerBaseOperand(pcasm, pcoffset);
exp = nexp->ConstantFold(mErrors); exp = nexp->ConstantFold(mErrors);
} }
return exp; return exp;
} }
Expression* Parser::ParseAssemblerAddOperand(void) Expression* Parser::ParseAssemblerAddOperand(Declaration* pcasm, int pcoffset)
{ {
Expression* exp = ParseAssemblerMulOperand(); Expression* exp = ParseAssemblerMulOperand(pcasm, pcoffset);
while (mScanner->mToken == TK_ADD || mScanner->mToken == TK_SUB) while (mScanner->mToken == TK_ADD || mScanner->mToken == TK_SUB)
{ {
Expression* nexp = new Expression(mScanner->mLocation, EX_BINARY); Expression* nexp = new Expression(mScanner->mLocation, EX_BINARY);
nexp->mToken = mScanner->mToken; nexp->mToken = mScanner->mToken;
nexp->mLeft = exp; nexp->mLeft = exp;
mScanner->NextToken(); mScanner->NextToken();
nexp->mRight = ParseAssemblerMulOperand(); nexp->mRight = ParseAssemblerMulOperand(pcasm, pcoffset);
if (!nexp->mLeft->mDecValue || !nexp->mRight->mDecValue) if (!nexp->mLeft->mDecValue || !nexp->mRight->mDecValue)
{ {
mErrors->Error(mScanner->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Invalid assembler operand"); mErrors->Error(mScanner->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Invalid assembler operand");
@ -2403,12 +2413,12 @@ Expression* Parser::ParseAssemblerAddOperand(void)
return exp; return exp;
} }
Expression* Parser::ParseAssemblerOperand(void) Expression* Parser::ParseAssemblerOperand(Declaration* pcasm, int pcoffset)
{ {
if (mScanner->mToken == TK_LESS_THAN) if (mScanner->mToken == TK_LESS_THAN)
{ {
mScanner->NextToken(); mScanner->NextToken();
Expression* exp = ParseAssemblerOperand(); Expression* exp = ParseAssemblerOperand(pcasm, pcoffset);
if (exp->mType == EX_CONSTANT) if (exp->mType == EX_CONSTANT)
{ {
@ -2478,7 +2488,7 @@ Expression* Parser::ParseAssemblerOperand(void)
else if (mScanner->mToken == TK_GREATER_THAN) else if (mScanner->mToken == TK_GREATER_THAN)
{ {
mScanner->NextToken(); mScanner->NextToken();
Expression* exp = ParseAssemblerOperand(); Expression* exp = ParseAssemblerOperand(pcasm, pcoffset);
if (exp->mType == EX_CONSTANT) if (exp->mType == EX_CONSTANT)
{ {
@ -2546,7 +2556,7 @@ Expression* Parser::ParseAssemblerOperand(void)
return exp; return exp;
} }
else else
return ParseAssemblerAddOperand(); return ParseAssemblerAddOperand(pcasm, pcoffset);
} }
void Parser::AddAssemblerRegister(const Ident* ident, int value) void Parser::AddAssemblerRegister(const Ident* ident, int value)
@ -2648,12 +2658,12 @@ Expression* Parser::ParseAssembler(void)
{ {
ilast->mAsmInsMode = ASMIM_IMMEDIATE; ilast->mAsmInsMode = ASMIM_IMMEDIATE;
mScanner->NextToken(); mScanner->NextToken();
ilast->mLeft = ParseAssemblerOperand(); ilast->mLeft = ParseAssemblerOperand(vdasm, offset);
} }
else if (mScanner->mToken == TK_OPEN_PARENTHESIS) else if (mScanner->mToken == TK_OPEN_PARENTHESIS)
{ {
mScanner->NextToken(); mScanner->NextToken();
ilast->mLeft = ParseAssemblerOperand(); ilast->mLeft = ParseAssemblerOperand(vdasm, offset);
if (mScanner->mToken == TK_COMMA) if (mScanner->mToken == TK_COMMA)
{ {
mScanner->NextToken(); mScanner->NextToken();
@ -2693,7 +2703,7 @@ Expression* Parser::ParseAssembler(void)
} }
else else
{ {
ilast->mLeft = ParseAssemblerOperand(); ilast->mLeft = ParseAssemblerOperand(vdasm, offset);
if (mScanner->mToken == TK_COMMA) if (mScanner->mToken == TK_COMMA)
{ {
mScanner->NextToken(); mScanner->NextToken();
@ -2960,7 +2970,7 @@ void Parser::ParsePragma(void)
{ {
mScanner->NextToken(); mScanner->NextToken();
ConsumeToken(TK_OPEN_PARENTHESIS); ConsumeToken(TK_OPEN_PARENTHESIS);
Expression* exp = ParseAssemblerOperand(); Expression* exp = ParseAssemblerOperand(nullptr, 0);
ConsumeToken(TK_COMMA); ConsumeToken(TK_COMMA);
if (mScanner->mToken == TK_IDENT) if (mScanner->mToken == TK_IDENT)

View File

@ -41,10 +41,10 @@ protected:
Expression* ParseFunction(Declaration* dec); Expression* ParseFunction(Declaration* dec);
Expression* ParseAssembler(void); Expression* ParseAssembler(void);
Expression* ParseAssemblerBaseOperand(void); Expression* ParseAssemblerBaseOperand(Declaration* pcasm, int pcoffset);
Expression* ParseAssemblerMulOperand(void); Expression* ParseAssemblerMulOperand(Declaration* pcasm, int pcoffset);
Expression* ParseAssemblerAddOperand(void); Expression* ParseAssemblerAddOperand(Declaration* pcasm, int pcoffset);
Expression* ParseAssemblerOperand(void); Expression* ParseAssemblerOperand(Declaration * pcasm, int pcoffset);
void AddAssemblerRegister(const Ident* ident, int value); void AddAssemblerRegister(const Ident* ident, int value);

View File

@ -73,7 +73,7 @@ int main(int argc, const char** argv)
#else #else
strcpy(strProductName, "oscar64"); strcpy(strProductName, "oscar64");
strcpy(strProductVersion, "1.3.72"); strcpy(strProductVersion, "1.3.73");
#ifdef __APPLE__ #ifdef __APPLE__
uint32_t length = sizeof(basePath); uint32_t length = sizeof(basePath);

View File

@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,3,72,0 FILEVERSION 1,3,73,0
PRODUCTVERSION 1,3,72,0 PRODUCTVERSION 1,3,73,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -43,12 +43,12 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "oscar64" VALUE "CompanyName", "oscar64"
VALUE "FileDescription", "oscar64 compiler" VALUE "FileDescription", "oscar64 compiler"
VALUE "FileVersion", "1.3.72.0" VALUE "FileVersion", "1.3.73.0"
VALUE "InternalName", "oscar64.exe" VALUE "InternalName", "oscar64.exe"
VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "LegalCopyright", "Copyright (C) 2021"
VALUE "OriginalFilename", "oscar64.exe" VALUE "OriginalFilename", "oscar64.exe"
VALUE "ProductName", "oscar64" VALUE "ProductName", "oscar64"
VALUE "ProductVersion", "1.3.72.0" VALUE "ProductVersion", "1.3.73.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View File

@ -3414,15 +3414,15 @@
{ {
"Name" = "8:Microsoft Visual Studio" "Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:oscar64" "ProductName" = "8:oscar64"
"ProductCode" = "8:{07197B62-14CB-4607-AF17-B93D06B4E603}" "ProductCode" = "8:{A53359B5-4B83-418F-BE3F-60133D152224}"
"PackageCode" = "8:{05C9040B-AB11-4EEF-B99C-0BC6CAB578AC}" "PackageCode" = "8:{5B0C1429-92B6-4506-ABF5-36A623D4C056}"
"UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}" "UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}"
"AspNetVersion" = "8:2.0.50727.0" "AspNetVersion" = "8:2.0.50727.0"
"RestartWWWService" = "11:FALSE" "RestartWWWService" = "11:FALSE"
"RemovePreviousVersions" = "11:TRUE" "RemovePreviousVersions" = "11:TRUE"
"DetectNewerInstalledVersion" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE"
"InstallAllUsers" = "11:FALSE" "InstallAllUsers" = "11:FALSE"
"ProductVersion" = "8:1.3.72" "ProductVersion" = "8:1.3.73"
"Manufacturer" = "8:oscar64" "Manufacturer" = "8:oscar64"
"ARPHELPTELEPHONE" = "8:" "ARPHELPTELEPHONE" = "8:"
"ARPHELPLINK" = "8:" "ARPHELPLINK" = "8:"

View File

@ -207,23 +207,23 @@ int main(void)
bm_line(&Screen, &SRect, bm_line(&Screen, &SRect,
p[iy + 0][ix + 0].x, p[iy + 0][ix + 0].y, p[iy + 0][ix + 0].x, p[iy + 0][ix + 0].y,
p[iy + 0][ix + 1].x, p[iy + 0][ix + 1].y, patt); p[iy + 0][ix + 1].x, p[iy + 0][ix + 1].y, patt, LINOP_SET);
bm_line(&Screen, &SRect, bm_line(&Screen, &SRect,
p[iy + 1][ix + 0].x, p[iy + 1][ix + 0].y, p[iy + 1][ix + 0].x, p[iy + 1][ix + 0].y,
p[iy + 1][ix + 1].x, p[iy + 1][ix + 1].y, patt); p[iy + 1][ix + 1].x, p[iy + 1][ix + 1].y, patt, LINOP_SET);
bm_line(&Screen, &SRect, bm_line(&Screen, &SRect,
p[iy + 0][ix + 0].x, p[iy + 0][ix + 0].y, p[iy + 0][ix + 0].x, p[iy + 0][ix + 0].y,
p[iy + 1][ix + 0].x, p[iy + 1][ix + 0].y, patt); p[iy + 1][ix + 0].x, p[iy + 1][ix + 0].y, patt, LINOP_SET);
bm_line(&Screen, &SRect, bm_line(&Screen, &SRect,
p[iy + 0][ix + 1].x, p[iy + 0][ix + 1].y, p[iy + 0][ix + 1].x, p[iy + 0][ix + 1].y,
p[iy + 1][ix + 1].x, p[iy + 1][ix + 1].y, patt); p[iy + 1][ix + 1].x, p[iy + 1][ix + 1].y, patt, LINOP_SET);
} }
mmap_set(MMAP_NO_BASIC); mmap_set(MMAP_NO_BASIC);
// getch(); getch();
restore(); restore();

View File

@ -40,10 +40,10 @@ void draw(ClipRect * cr, byte pattern)
{ {
for(int i=0; i<40; i ++) for(int i=0; i<40; i ++)
{ {
bm_line(&Screen, cr, 8 * i, 0, 319, 5 * i, pattern); bm_line(&Screen, cr, 8 * i, 0, 319, 5 * i, pattern, LINOP_SET);
bm_line(&Screen, cr, 319, 5 * i, 319 - 8 * i, 199, pattern); bm_line(&Screen, cr, 319, 5 * i, 319 - 8 * i, 199, pattern, LINOP_SET);
bm_line(&Screen, cr, 319 - 8 * i, 199, 0, 199 - 5 * i, pattern); bm_line(&Screen, cr, 319 - 8 * i, 199, 0, 199 - 5 * i, pattern, LINOP_SET);
bm_line(&Screen, cr, 0, 199 - 5 * i, 8 * i, 0, pattern); bm_line(&Screen, cr, 0, 199 - 5 * i, 8 * i, 0, pattern, LINOP_SET);
} }
} }

View File

@ -74,7 +74,7 @@ int main(void)
for(int j=0; j<10; j++) for(int j=0; j<10; j++)
{ {
int k = (j + 1) % 10; int k = (j + 1) % 10;
bm_line(&Screen, &cr, rpx[j], rpy[j], rpx[k], rpy[k], 0xff); bm_line(&Screen, &cr, rpx[j], rpy[j], rpx[k], rpy[k], 0xff, LINOP_SET);
} }
} }

Binary file not shown.