diff --git a/include/c64/charwin.c b/include/c64/charwin.c index 22a3b1b..8f1c315 100644 --- a/include/c64/charwin.c +++ b/include/c64/charwin.c @@ -119,7 +119,7 @@ bool cwin_cursor_up(CharWin * win) bool cwin_cursor_down(CharWin * win) { - if (win->cy + 1 < win->cy) + if (win->cy + 1 < win->wy) { win->cy++; return true; @@ -418,6 +418,8 @@ bool cwin_edit_char(CharWin * win, char ch) case 147: cwin_clear(win); + win->cx = 0; + win->cy = 0; return false; case 17: diff --git a/include/c64/kernalio.c b/include/c64/kernalio.c new file mode 100644 index 0000000..3e5e333 --- /dev/null +++ b/include/c64/kernalio.c @@ -0,0 +1,203 @@ +#include "kernalio.h" + + +void krnio_setnam(const char * name) +{ + __asm + { + lda name + ora name + 1 + beq W1 + + ldy #$ff + L1: iny + lda (name), y + bne L1 + tya + W1: ldx name + ldy name + 1 + jsr $ffbd // setnam + } +} + +bool krnio_open(char fnum, char device, char channel) +{ + __asm + { + lda #0 + sta accu + sta accu + 1 + + lda fnum + ldx device + ldy channel + jsr $ffba // setlfs + + jsr $ffc0 // open + bcc W1 + + lda fnum + jsr $ffc3 // close + jmp E2 + W1: + lda #1 + sta accu + E2: + } + +} + +void krnio_close(char fnum) +{ + __asm + { + lda fnum + jsr $ffc3 // close + } +} + +krnioerr krnio_status(void) +{ + __asm + { + jsr $ffb7 // readst + sta accu + lda #0 + sta accu + 1 + } +} + +bool krnio_chkout(char fnum) +{ + __asm + { + ldx fnum + jsr $ffc9 // chkout + lda #0 + sta accu + 1 + bcs W1 + lda #1 + W1: sta accu + } +} + +bool krnio_chkin(char fnum) +{ + __asm + { + ldx fnum + jsr $ffc6 // chkin + lda #0 + sta accu + 1 + bcs W1 + lda #1 + W1: sta accu + } +} + +void krnio_clrchn(void) +{ + __asm + { + jsr $ffcc // clrchn + } +} + +bool krnio_chrout(char ch) +{ + __asm + { + lda ch + jsr $ffd2 // chrout + sta accu + lda #0 + sta accu + 1 + } +} + +int krnio_chrin(void) +{ + __asm + { + jsr $ffcf // chrin + sta accu + jsr $ffb7 + beq W1 + lda #$ff + sta accu + W1: + sta accu + 1 + } +} + +int krnio_getch(char fnum) +{ + int ch = -1; + if (krnio_chkin(fnum)) + ch = krnio_chrin(); + krnio_clrchn(); + return ch; +} + +int krnio_puts(char fnum, const char * data) +{ + if (krnio_chkout(fnum)) + { + int i = 0; + while (data[i]) + krnio_chrout(data[i++]); + krnio_clrchn(); + return i; + } + else + return -1; +} + +int krnio_write(char fnum, const char * data, int num) +{ + if (krnio_chkout(fnum)) + { + for(int i=0; i= 0) + data[i++] = (char)ch; + krnio_clrchn(); + return i; + } + else + return -1; +} + +int krnio_gets(char fnum, char * data, int num) +{ + if (krnio_chkin(fnum)) + { + int i = 0; + int ch; + while (i + 1 < num && (ch = krnio_chrin()) >= 0) + { + data[i++] = (char)ch; + if (ch == 13 || ch == 10) + break; + } + data[i] = 0; + krnio_clrchn(); + return i; + } + else + return -1; + +} diff --git a/include/c64/kernalio.h b/include/c64/kernalio.h new file mode 100644 index 0000000..edc1cfb --- /dev/null +++ b/include/c64/kernalio.h @@ -0,0 +1,51 @@ +#ifndef C64_KERNALIO_H +#ifndef C64_KERNALIO_H + + +enum krnioerr +{ + KRNIO_OK = 0, + KRNIO_DIR = 0x01, + KRNIO_TIMEOUT = 0x02, + KRNIO_SHORT = 0x04, + KRNIO_LONG = 0x08, + KRNIO_VERIFY = 0x10, + KRNIO_CHKSUM = 0x20, + KRNIO_EOF = 0x40, + KRNIO_NODEVICE = 0x80 +}; + +void krnio_setnam(const char * name); + +bool krnio_open(char fnum, char device, char channel); + +void krnio_close(char fnum); + +krnioerr krnio_status(void); + + +bool krnio_chkout(char fnum); + +bool krnio_chkin(char fnum); + +void krnio_clrchn(void); + +bool krnio_chrout(char ch); + +int krnio_chrin(void); + +int krnio_getch(char fnum); + + + +int krnio_write(char fnum, const char * data, int num); + +int krnio_puts(char fnum, const char * data); + +int krnio_read(char fnum, char * data, int num); + +int krnio_gets(char fnum, char * data, int num); + +#pragma compile("kernalio.c") + +#endif diff --git a/include/crt.c b/include/crt.c index 8401723..6aff118 100644 --- a/include/crt.c +++ b/include/crt.c @@ -1885,6 +1885,22 @@ W1: jmp startup.yexec #pragma bytecode(BC_BINOP_SHRI_I16, inp_binop_shr_s16.inp_binop_shri_s16) #pragma bytecode(BC_BINOP_SHRR_I16, inp_binop_shr_s16.inp_binop_shrr_s16) +__asm inp_binop_adda_16 +{ + lda (ip), y + tax + clc + lda $00, x + adc accu + sta $00, x + lda $01, x + adc accu + 1 + sta $01, x + jmp startup.yexec +} + +#pragma bytecode(BC_BINOP_ADDA_16, inp_binop_adda_16) + __asm cmp16 { inp_binop_cmpr_s16: diff --git a/include/crt.h b/include/crt.h index 1b4f6ba..928e476 100644 --- a/include/crt.h +++ b/include/crt.h @@ -76,6 +76,8 @@ enum ByteCode BC_BINOP_SHRR_U16, BC_BINOP_SHRR_I16, + BC_BINOP_ADDA_16, + BC_BINOP_ADDI_16, BC_BINOP_SUBI_16, BC_BINOP_ANDI_16, diff --git a/include/setjmp.c b/include/setjmp.c new file mode 100644 index 0000000..45cce53 --- /dev/null +++ b/include/setjmp.c @@ -0,0 +1,112 @@ +#include "setjmp.h" + +int setjmp(jmp_buf env) +{ + __asm + { + ldy #0 + lda __sp + 0 + sta (env), y + iny + lda __sp + 1 + sta (env), y + iny + + lda __ip + 0 + sta (env), y + iny + lda __ip + 1 + sta (env), y + iny + + lda __fp + 0 + sta (env), y + iny + lda __fp + 1 + sta (env), y + iny + + ldx #0 + loop: + lda __sregs, x + sta (env), y + iny + inx + cpx #32 + bne loop + + tsx + txa + sta (env), y + iny + + lda $0100, x + sta (env), y + iny + + lda $0101, x + sta (env), y + iny + } + + return 0 +} + +#pragma native(setjmp) + +void longjmp(jmp_buf env, int value) +{ + __asm + { + ldy #0 + lda (env), y + sta __sp + 0 + iny + lda (env), y + sta __sp + 1 + iny + + lda (env), y + sta __ip + 0 + iny + lda (env), y + sta __ip + 1 + iny + + lda (env), y + sta __fp + 0 + iny + lda (env), y + sta __fp + 1 + iny + + ldx #0 + loop: + lda (env), y + sta __sregs, x + iny + inx + cpx #32 + bne loop + + lda (env), y + tax + txs + iny + + lda (env), y + sta $0100, x + iny + + lda (env), y + sta $0101, x + iny + + lda value + sta __accu + lda value + 1 + sta __accu + 1 + } +} + +#pragma native(longjmp) diff --git a/include/setjmp.h b/include/setjmp.h new file mode 100644 index 0000000..4f4cc2e --- /dev/null +++ b/include/setjmp.h @@ -0,0 +1,21 @@ +#ifndef SETJMP_H +#define SETJMP_H + +struct _jmp_buf +{ + void * sp, * ip, * fp; + char tmps[32]; + char cpup, cpul, cpuh; +}; + +typedef struct _jmp_buf jmp_buf[1]; + +int setjmp(jmp_buf env); + +void longjmp(jmp_buf env, int value); + + +#pragma compile("setjmp.c") + +#endif + diff --git a/include/string.c b/include/string.c index 25c4412..a105b31 100644 --- a/include/string.c +++ b/include/string.c @@ -108,6 +108,8 @@ int strlen(const char * str) return i; } +#pragma native(strlen) + char * strcat(char * dst, const char * src) { char * d = dst; @@ -121,6 +123,17 @@ char * strcat(char * dst, const char * src) return dst; } +#pragma native(strcat) + +char * cpycat(char * dst, const char * src) +{ + do {} while (*dst++ = *src++); + + return dst; +} + +#pragma native(cpycat) + void * memset(void * dst, int value, int size) { __asm diff --git a/include/string.h b/include/string.h index 75396e6..1fe3754 100644 --- a/include/string.h +++ b/include/string.h @@ -9,6 +9,8 @@ int strlen(const char * str); char * strcat(char * dst, const char * src); +char * cpycat(char * dst, const char * src); + void * memclr(void * dst, int size); void * memset(void * dst, int value, int size); diff --git a/oscar64/ByteCodeGenerator.cpp b/oscar64/ByteCodeGenerator.cpp index ded2bb2..0bdaeec 100644 --- a/oscar64/ByteCodeGenerator.cpp +++ b/oscar64/ByteCodeGenerator.cpp @@ -549,6 +549,10 @@ bool ByteCodeInstruction::CheckAccuSize(uint32 & used) used |= 0x0000ffff; break; + case BC_BINOP_ADDA_16: + used |= 0x0000ffff; + break; + case BC_BINOP_ADDI_16: if (mRegister == BC_REG_ACCU) { @@ -730,6 +734,9 @@ bool ByteCodeInstruction::UsesRegister(uint32 reg) const if (mCode >= BC_BINOP_ADD_L32 && mCode <= BC_BINOP_CMP_S32) return true; + + if (mCode == BC_BINOP_ADDA_16) + return true; } if (reg == BC_REG_ACCU) @@ -759,6 +766,8 @@ bool ByteCodeInstruction::UsesRegister(uint32 reg) const return true; if (mCode == BC_COPY || mCode == BC_STRCPY) return true; + if (mCode == BC_BINOP_ADDA_16) + return true; } if (reg == BC_REG_ADDR) @@ -797,6 +806,8 @@ bool ByteCodeInstruction::ChangesRegister(uint32 reg) const return true; if (mCode == BC_CALL) return true; + if (mCode == BC_BINOP_ADDA_16) + return true; } if (reg == BC_REG_ACCU) @@ -980,6 +991,7 @@ void ByteCodeInstruction::Assemble(ByteCodeGenerator* generator, ByteCodeBasicBl case BC_BINOP_SHLR_16: case BC_BINOP_SHRR_U16: case BC_BINOP_SHRR_I16: + case BC_BINOP_ADDA_16: block->PutCode(generator, mCode); block->PutByte(mRegister); break; @@ -4249,6 +4261,8 @@ bool ByteCodeBasicBlock::JoinTailCodeSequences(void) { ByteCodeBasicBlock* b = mEntryBlocks[i]; b->mIns.SetSize(b->mIns.Size() - 1); + if (mIns.Size() == 1) + mExitLive |= b->mExitLive; b->mExitLive = LIVE_ACCU; } changed = true; @@ -4779,6 +4793,29 @@ bool ByteCodeBasicBlock::PeepHoleOptimizer(int phase) mIns[i + 0].mRegister = BC_REG_ACCU; mIns[i + 1].mCode = BC_NOP; mIns[i + 2].mCode = BC_NOP; + progress = true; + } + else if ( + mIns[i + 0].mCode == BC_LOAD_REG_16 && + mIns[i + 1].mCode == BC_BINOP_ADDR_16 && + mIns[i + 2].mCode == BC_STORE_REG_16 && mIns[i + 0].mRegister == mIns[i + 2].mRegister && !(mIns[i + 2].mLive & LIVE_ACCU)) + { + mIns[i + 0].mRegister = mIns[i + 1].mRegister; + mIns[i + 0].mRegisterFinal = mIns[i + 1].mRegisterFinal; + mIns[i + 1].mCode = BC_NOP; + mIns[i + 2].mCode = BC_BINOP_ADDA_16; + progress = true; + } + else if ( + (mIns[i + 0].mCode == BC_LOAD_LOCAL_16 || mIns[i + 0].mCode == BC_LOAD_ABS_16 || mIns[i + 0].mCode == BC_LOAD_ADDR_16 || + mIns[i + 0].mCode == BC_LOAD_LOCAL_U8 || mIns[i + 0].mCode == BC_LOAD_ABS_U8 || mIns[i + 0].mCode == BC_LOAD_ADDR_U8) && + mIns[i + 1].mCode == BC_BINOP_ADDR_16 && mIns[i + 0].mRegister == mIns[i + 1].mRegister && mIns[i + 1].mRegisterFinal && + mIns[i + 2].mCode == BC_STORE_REG_16 && !(mIns[i + 2].mLive & LIVE_ACCU)) + { + mIns[i + 0].mRegister = mIns[i + 2].mRegister; + mIns[i + 1].mCode = BC_NOP; + mIns[i + 2].mCode = BC_BINOP_ADDA_16; + progress = true; } } #endif @@ -5037,6 +5074,24 @@ bool ByteCodeBasicBlock::PeepHoleOptimizer(int phase) mIns[i + 1].mCode = BC_NOP; progress = true; } +#if 1 + else if ( + mIns[i + 0].mCode == BC_BINOP_ADDR_16 && + mIns[i + 1].mCode == BC_STORE_REG_16 && mIns[i + 0].mRegister == mIns[i + 1].mRegister && !(mIns[i + 1].mLive & LIVE_ACCU)) + { + mIns[i + 1].mCode = BC_BINOP_ADDA_16; + mIns[i + 0].mCode = BC_NOP; + progress = true; + } + else if ( + mIns[i + 0].mCode == BC_BINOP_ADDA_16 && + mIns[i + 1].mCode == BC_LOAD_REG_16 && mIns[i + 0].mRegister == mIns[i + 1].mRegister && mIns[i + 1].mRegisterFinal) + { + mIns[i + 1].mCode = BC_BINOP_ADDR_16; + mIns[i + 0].mCode = BC_NOP; + progress = true; + } +#endif #if 1 else if ( i + 2 == mIns.Size() && mFalseJump && @@ -5049,6 +5104,7 @@ bool ByteCodeBasicBlock::PeepHoleOptimizer(int phase) mBranch = TransposeBranchCondition(mBranch); progress = true; } + #endif #if 0 diff --git a/oscar64/ByteCodeGenerator.h b/oscar64/ByteCodeGenerator.h index b073670..4a79f8c 100644 --- a/oscar64/ByteCodeGenerator.h +++ b/oscar64/ByteCodeGenerator.h @@ -77,6 +77,8 @@ enum ByteCode BC_BINOP_SHRR_U16, BC_BINOP_SHRR_I16, + BC_BINOP_ADDA_16, + BC_BINOP_ADDI_16, BC_BINOP_SUBI_16, BC_BINOP_ANDI_16, diff --git a/oscar64/Disassembler.cpp b/oscar64/Disassembler.cpp index fac686f..bc63685 100644 --- a/oscar64/Disassembler.cpp +++ b/oscar64/Disassembler.cpp @@ -246,6 +246,10 @@ void ByteCodeDisassembler::Disassemble(FILE* file, const uint8* memory, int star fprintf(file, "ADD\tACCU, %s", TempName(memory[start + i + 0], tbuffer, proc)); i += 1; break; + case BC_BINOP_ADDA_16: + fprintf(file, "ADD\t%s, ACCU", TempName(memory[start + i + 0], tbuffer, proc)); + i += 1; + break; case BC_BINOP_SUBR_16: fprintf(file, "SUB\tACCU, %s", TempName(memory[start + i + 0], tbuffer, proc)); i += 1; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index ea455f7..5a953bc 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -43,7 +43,7 @@ Declaration* Parser::ParseStructDeclaration(uint32 flags, DecType dt) Declaration* pdec = mScope->Insert(structName, dec); if (pdec) { - if (pdec->mType == dt && (pdec->mFlags & DTF_DEFINED)) + if (pdec->mType == dt && !(pdec->mFlags & DTF_DEFINED)) { dec = pdec; } @@ -68,22 +68,22 @@ Declaration* Parser::ParseStructDeclaration(uint32 flags, DecType dt) for (;;) { Declaration* mdec = ParseDeclaration(false); + + int offset = dec->mSize; + if (dt == DT_TYPE_UNION) + offset = 0; + while (mdec) { if (!(mdec->mBase->mFlags & DTF_DEFINED)) mErrors->Error(mdec->mLocation, EERR_UNDEFINED_OBJECT, "Undefined type used in struct member declaration"); mdec->mType = DT_ELEMENT; - if (dt == DT_TYPE_UNION) - { - mdec->mOffset = 0; - if (mdec->mBase->mSize > dec->mSize) - dec->mSize = mdec->mBase->mSize; - } - else - { - mdec->mOffset = dec->mSize; - dec->mSize += mdec->mBase->mSize; - } + mdec->mOffset = offset; + + offset += mdec->mBase->mSize; + if (offset > dec->mSize) + dec->mSize = offset; + dec->mScope->Insert(mdec->mIdent, mdec); if (mlast) mlast->mNext = mdec;