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_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;
@ -491,6 +491,9 @@ static void buildline(char ly, char lx, int dx, int dy, int stride, bool left, b
// set pixel
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_rl(BLIT_CODE + ip, ASM_BCC, 6);
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_iy(BLIT_CODE + ip, ASM_AND, 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
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;
byte quad = 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;
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);
}
@ -627,7 +676,7 @@ static int muldiv(int x, int mul, int 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;
@ -711,7 +760,7 @@ void bm_line(Bitmap * bm, ClipRect * clip, int x0, int y0, int x1, int y1, char
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)

View File

@ -48,6 +48,14 @@ enum BlitOp
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];
// 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);
// 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
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
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:
if (!aexp)
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
d[offset] = aexp->mInteger - offset - 1;
}
offset++;
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
// must be last step before actual assembly
@ -11931,6 +11974,33 @@ void NativeCodeBasicBlock::BlockSizeReduction(void)
j += 2;
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
mIns[j++] = mIns[i++];
}
@ -12480,6 +12550,92 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
#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
// 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
}
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 (
@ -15602,6 +15835,12 @@ void NativeCodeProcedure::Optimize(void)
#endif
#if 1
ResetVisited();
if (mEntryBlock->OptimizeSelect(this))
{
changed = true;
}
if (step > 0)
{
ResetVisited();

View File

@ -151,6 +151,8 @@ public:
bool SimpleLoopReversal(NativeCodeProcedure* proc);
bool OptimizeInnerLoop(NativeCodeProcedure* proc, NativeCodeBasicBlock* head, NativeCodeBasicBlock* tail, GrowingArray<NativeCodeBasicBlock*>& blocks);
bool OptimizeSelect(NativeCodeProcedure* proc);
NativeCodeBasicBlock* FindTailBlock(NativeCodeBasicBlock* head);
bool OptimizeInnerLoops(NativeCodeProcedure* proc);
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;
Declaration* dec;
@ -2203,7 +2203,7 @@ Expression* Parser::ParseAssemblerBaseOperand(void)
{
case TK_SUB:
mScanner->NextToken();
exp = ParseAssemblerBaseOperand();
exp = ParseAssemblerBaseOperand(pcasm, pcoffset);
if (exp->mType == EX_CONSTANT && exp->mDecValue->mType == 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");
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:
dec = new Declaration(mScanner->mLocation, DT_CONST_INTEGER);
dec->mInteger = mScanner->mTokenInteger;
@ -2329,31 +2339,31 @@ Expression* Parser::ParseAssemblerBaseOperand(void)
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)
{
Expression* nexp = new Expression(mScanner->mLocation, EX_BINARY);
nexp->mToken = mScanner->mToken;
nexp->mLeft = exp;
mScanner->NextToken();
nexp->mRight = ParseAssemblerBaseOperand();
nexp->mRight = ParseAssemblerBaseOperand(pcasm, pcoffset);
exp = nexp->ConstantFold(mErrors);
}
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)
{
Expression* nexp = new Expression(mScanner->mLocation, EX_BINARY);
nexp->mToken = mScanner->mToken;
nexp->mLeft = exp;
mScanner->NextToken();
nexp->mRight = ParseAssemblerMulOperand();
nexp->mRight = ParseAssemblerMulOperand(pcasm, pcoffset);
if (!nexp->mLeft->mDecValue || !nexp->mRight->mDecValue)
{
mErrors->Error(mScanner->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Invalid assembler operand");
@ -2403,12 +2413,12 @@ Expression* Parser::ParseAssemblerAddOperand(void)
return exp;
}
Expression* Parser::ParseAssemblerOperand(void)
Expression* Parser::ParseAssemblerOperand(Declaration* pcasm, int pcoffset)
{
if (mScanner->mToken == TK_LESS_THAN)
{
mScanner->NextToken();
Expression* exp = ParseAssemblerOperand();
Expression* exp = ParseAssemblerOperand(pcasm, pcoffset);
if (exp->mType == EX_CONSTANT)
{
@ -2478,7 +2488,7 @@ Expression* Parser::ParseAssemblerOperand(void)
else if (mScanner->mToken == TK_GREATER_THAN)
{
mScanner->NextToken();
Expression* exp = ParseAssemblerOperand();
Expression* exp = ParseAssemblerOperand(pcasm, pcoffset);
if (exp->mType == EX_CONSTANT)
{
@ -2546,7 +2556,7 @@ Expression* Parser::ParseAssemblerOperand(void)
return exp;
}
else
return ParseAssemblerAddOperand();
return ParseAssemblerAddOperand(pcasm, pcoffset);
}
void Parser::AddAssemblerRegister(const Ident* ident, int value)
@ -2648,12 +2658,12 @@ Expression* Parser::ParseAssembler(void)
{
ilast->mAsmInsMode = ASMIM_IMMEDIATE;
mScanner->NextToken();
ilast->mLeft = ParseAssemblerOperand();
ilast->mLeft = ParseAssemblerOperand(vdasm, offset);
}
else if (mScanner->mToken == TK_OPEN_PARENTHESIS)
{
mScanner->NextToken();
ilast->mLeft = ParseAssemblerOperand();
ilast->mLeft = ParseAssemblerOperand(vdasm, offset);
if (mScanner->mToken == TK_COMMA)
{
mScanner->NextToken();
@ -2693,7 +2703,7 @@ Expression* Parser::ParseAssembler(void)
}
else
{
ilast->mLeft = ParseAssemblerOperand();
ilast->mLeft = ParseAssemblerOperand(vdasm, offset);
if (mScanner->mToken == TK_COMMA)
{
mScanner->NextToken();
@ -2960,7 +2970,7 @@ void Parser::ParsePragma(void)
{
mScanner->NextToken();
ConsumeToken(TK_OPEN_PARENTHESIS);
Expression* exp = ParseAssemblerOperand();
Expression* exp = ParseAssemblerOperand(nullptr, 0);
ConsumeToken(TK_COMMA);
if (mScanner->mToken == TK_IDENT)

View File

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

View File

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

View File

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

View File

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

View File

@ -207,23 +207,23 @@ int main(void)
bm_line(&Screen, &SRect,
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,
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,
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,
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);
// getch();
getch();
restore();

View File

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

View File

@ -74,7 +74,7 @@ int main(void)
for(int j=0; j<10; j++)
{
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.