URL
https://opencores.org/ocsvn/zipcpu/zipcpu/trunk
Subversion Repositories zipcpu
Compare Revisions
- This comparison shows the changes necessary to convert path
/zipcpu/trunk/sw
- from Rev 26 to Rev 20
- ↔ Reverse comparison
Rev 26 → Rev 20
/zipdbg/README
File deleted
/zasm/test.S
48,7 → 48,7
; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; |
#include "sys.i" |
// #include "sys.i" |
sys.bus equ 0xc0000000 |
sys.breaken equ 0x080 |
sys.step equ 0x040 |
58,7 → 58,6
sys.ccn equ 0x004 |
sys.ccc equ 0x002 |
sys.ccz equ 0x001 |
sys.cctrap equ 0x200 |
sys.bu.pic equ 0x000 |
sys.bus.wdt equ 0x001 |
sys.bus.cache equ 0x002 |
76,14 → 75,6
sys.bus.uastl equ 0x00e |
sys.bus.ustl equ 0x00f |
#define DO_TEST_ASSEMBLER |
#define BREAK_TEST |
#define OVERFLOW_TEST |
#define CARRY_TEST |
#define LOOP_TEST |
#define SHIFT_TEST |
#define TRAP_TEST |
#define MPY_TEST |
// #define PUSH_TEST |
test: |
#ifdef DO_TEST_ASSEMBLER |
; We start out by testing our assembler. We give it some instructions, which |
94,7 → 85,6
bra continue_test_with_testable_instructions |
break |
wait |
break |
busy |
rtu |
continue_test_with_testable_instructions: |
216,52 → 206,43
lod junk_address(pc),r6 |
cmp r5,r6 |
bnz test_failure |
; Now, let's test whether or not our LSR and carry flags work |
ldi -1,r0 ; First test: shifting all the way should yield zero |
lsr 32,r0 |
cmp 0,r0 |
bnz test_failure |
ldi -1,r0 ; Second test: anything greater than zero should set |
lsr 0,r0 ; the carry flag |
bc test_failure |
lsr 1,r0 |
tst sys.ccc,cc |
bz test_failure |
lsr 31,r0 |
tst sys.ccc,cc |
bz test_failure |
lsr 1,r0 |
bc test_failure |
; Now repeat the above tests, looking to see whether or not ASR works |
ldi -1,r0 |
asr 32,r0 |
cmp -1,r0 |
bnz test_failure |
ldi -1,r0 |
asr 0,r0 |
bc test_failure |
cmp -1,r0 |
bnz test_failure |
asr 1,r0 |
tst sys.ccc,r14 |
bz test_failure |
asr 30,r0 |
tst sys.ccc,r14 |
bz test_failure |
#endif |
|
#ifdef NOONE // Testing comments after ifdef |
#else ; After else |
#endif /* and after endif */ |
|
#ifdef BREAK_TEST |
breaktest: |
bra breaksupervisor |
breakuser: |
clr r0 |
mov 1+r0,r1 |
mov 1+r1,r2 |
mov 1+r2,r3 |
break ; At address 0x0100097 |
mov 1+r4,r5 |
mov 1+r5,r6 |
clr cc |
busy |
breaksupervisor: |
ldi -1,r0 |
mov breakuser(pc),upc |
rtu ; Should just keep returning immediately |
mov upc,r0 |
rtu |
rtu |
mov upc,r1 |
cmp r0,r1 |
bnz test_failure |
#endif |
|
#ifdef TRAP_TEST |
traptest: |
bra traptest_supervisor |
busy |
traptest_user: |
trap 0 |
busy |
traptest_supervisor: |
mov traptest_user(pc),upc |
rtu |
mov cc,r0 |
tst sys.cctrap,r0 |
bz test_failure |
#endif |
|
testbench: |
// Let's build a software test bench. |
ldi $c0000000h,r12 ; Set R12 to point to our peripheral address |
271,7 → 252,7
sto r0,(r12) |
rtu |
mov ucc,r0 |
cmp sys.cctrap,r0 |
tst -256,r0 |
bnz test_failure |
halt |
// Go into an infinite loop if the trap fails |
288,7 → 269,7
test_data: |
.dat __here__+0x0100000+5 |
test_start: |
ldi $0x01000,r11 |
ldi $0x0100,r11 |
lod test_data+pc,pc |
clr r11 |
noop |
297,9 → 278,8
add $1,r0 |
add $1,r0 |
|
#ifdef OVERFLOW_TEST |
// Let's test whether overflow works |
ldi $0x02000,r11 |
ldi $0x0200,r11 |
ldi $-1,r0 |
lsr $1,r0 |
add $1,r0 |
307,7 → 287,7
trap r11 |
first_overflow_passes: |
// Overflow set from subtraction |
ldi $0x03000,r11 |
ldi $0x0300,r11 |
ldi $1,r0 |
rol $31,r0 ; rol $31,r0 |
sub $1,r0 |
315,7 → 295,7
trap r11 |
subtraction_overflow_passes: |
// Overflow set from LSR |
ldi $0x04000,r11 |
ldi $0x0400,r11 |
ldi $1,r0 |
rol $31,r0 ; rol $31,r0 |
lsr $1,r0 |
323,7 → 303,7
trap r11 |
lsr_overflow_passes: |
// Overflow set from LSL |
ldi $0x05000,r11 |
ldi $0x0500,r11 |
ldi $1,r0 |
rol $30,r0 |
lsl $1,r0 |
331,34 → 311,28
trap r11 |
lsl_overflow_passes: |
// Overflow set from LSL, negative to positive |
ldi $0x06000,r11 |
ldi $0x0600,r11 |
ldi $1,r0 |
rol $31,r0 |
lsl $1,r0 |
bv second_lsl_overflow_passes |
trap r11 |
#endif // OVERFLOW_TEST |
#ifdef CARRY_TEST |
second_lsl_overflow_passes: |
// Test carry |
ldi $0x07000,r11 |
ldi $0x0700,r11 |
ldi $-1,r0 |
add $1,r0 |
tst $2,cc |
trap.z r11 |
// and carry from subtraction |
ldi $0x08000,r11 |
clr r0 |
ldi $0x0800,r11 |
sub $1,r0 |
tst $2,cc |
trap.z r11 |
#endif |
|
#ifdef LOOP_TEST |
|
// Let's try a loop: for i=0; i<5; i++) |
// We'll use R0=i, Immediates for 5 |
ldi $0x09000,r11 |
ldi $0x0800,r11 |
clr r0 |
for_loop: |
noop |
372,7 → 346,7
// R0 = 5; (from before) |
// do { |
// } while (R0 > 0); |
ldi $0x0a000,r11 |
ldi $0x0900,r11 |
bgt_loop: |
noop |
sub $1,r0 |
394,7 → 368,7
// R0 = 5; (from before) |
// do { |
// } while (R0 > 0); |
ldi $0x0b000,r11 |
ldi $0x0a00,r11 |
bra mem_loop_test |
loop_var: |
.dat 0 |
412,44 → 386,9
bgt mem_loop |
cmp $5,r2 |
trap.ne r11 |
#endif |
|
#ifdef SHIFT_TEST |
; Now, let's test whether or not our LSR and carry flags work |
ldi $0x0c000,r11 |
ldi -1,r0 ; First test: shifting all the way should yield zero |
lsr 32,r0 |
cmp 0,r0 |
bnz test_failure |
ldi -1,r0 ; Second test: anything greater than zero should set |
lsr 0,r0 ; the carry flag |
bc test_failure |
lsr 1,r0 |
tst sys.ccc,cc ; FAILS HERE!!! @0x010007c |
bz test_failure |
lsr 31,r0 |
tst sys.ccc,cc |
bz test_failure |
lsr 1,r0 |
bc test_failure |
; Now repeat the above tests, looking to see whether or not ASR works |
ldi -1,r0 |
asr 32,r0 |
cmp -1,r0 |
bnz test_failure |
ldi -1,r0 |
asr 0,r0 |
bc test_failure |
cmp -1,r0 |
bnz test_failure |
asr 1,r0 |
tst sys.ccc,r14 |
bz test_failure |
asr 30,r0 |
tst sys.ccc,r14 |
bz test_failure |
|
// Let's test whether LSL works |
ldi $0x0b00,r11 |
ldi 0x035,r2 |
lsl 8,r2 |
ldi 0x03500,r1 |
460,40 → 399,7
or r0,r2 |
cmp 0x03574,r2 |
trap.ne r11 |
#endif |
|
#ifdef MPY_TEST |
|
// We have two multiply instructions. Let's see if those work |
ldi $0x0d000,r11 // Mark our test |
ldi 23171,r0 // = sqrt(2)/2 * 32768 |
mpyu r0,r0 // Should = 2/4 * 2^30 = 2^29 or thereabouts |
ldi 536895241,r2 |
cmp r0,r2 |
trap.ne r11 |
ldi 0x0ffff,r0 |
mpyu r0,r0 |
ldi 0xfffe0001,r1 |
cmp r1,r0 |
trap.ne r11 |
ldi 0x08001,r0 |
ldi 0x07fff,r1 |
mpys r0,r1 // FAILS: result is 0x008001 ??? (pipeline prob) |
ldi 0x3fff0001,r2 |
neg r2 |
cmp r2,r1 // @0x010011c |
trap.ne r11 //TRAP FAILS TO TRIGGER ????? (R2=0x0c000ffff,R1=0x0008001 -- did mpy even happen?) |
mpys r0,r0 // FAILS: result is 0x40010001 |
ldi 0x3fff0001,r2 |
cmp r2,r0 |
trap.ne r11 // TRAP FAILS TO TRIGGER AGAIN |
ldi 0x08000,r0 |
mpys r0,r0 // R0 now equals 0x40000000 |
ldi 0x40000000,r1 |
cmp r0,r1 |
trap.ne r11 |
#endif |
|
// Return success / Test the trap interrupt |
clr r11 |
trap r11 |
/zasm/zopcodes.cpp
131,10 → 131,8
"LDILO",0xff100000, 0x4f000000, REGFIELD(16),OPUNUSED, OPUNUSED, IMMFIELD(16,0), BITFIELD(3,21), |
"LDIHI",0xff100000, 0x4f100000, REGFIELD(16),OPUNUSED, OPUNUSED, IMMFIELD(16,0), BITFIELD(3,21), |
// |
"MPYU", 0xf01f0000, 0x400f0000, REGFIELD(24), REGFIELD(24), OPUNUSED, IMMFIELD(15,0), BITFIELD(3,21), |
"MPYU", 0xf0100000, 0x40000000, REGFIELD(24), REGFIELD(24), REGFIELD(16), IMMFIELD(15,0), BITFIELD(3,21), |
"MPYS", 0xf01f0000, 0x401f0000, REGFIELD(24), REGFIELD(24), OPUNUSED, IMMFIELD(15,0), BITFIELD(3,21), |
"MPYS", 0xf0100000, 0x40100000, REGFIELD(24), REGFIELD(24), REGFIELD(16), IMMFIELD(15,0), BITFIELD(3,21), |
"MPY", 0xf0100000, 0x40000000, REGFIELD(24), REGFIELD(24), OPUNUSED, IMMFIELD(19,0), BITFIELD(3,21), |
"MPY", 0xf0100000, 0x40100000, REGFIELD(24), REGFIELD(24), REGFIELD(16), IMMFIELD(16,0), BITFIELD(3,21), |
// |
"ROL", 0xf0100000, 0x50000000, REGFIELD(24), REGFIELD(24), OPUNUSED, IMMFIELD(5,0), BITFIELD(3,21), |
"ROL", 0xf0100000, 0x50100000, REGFIELD(24), REGFIELD(24), REGFIELD(16), IMMFIELD(5,0), BITFIELD(3,21), |
/zasm/zasm.y
40,9 → 40,6
#include <string.h> |
#include "asmdata.h" |
|
#define DEFAULT_OUTPUT_FNAME "z.out" |
#define YYDEBUG 1 |
|
extern "C" int yylex(void); |
extern "C" int yyparse(void); |
// extern "C" FILE *yyin; |
78,13 → 75,6
%type <u_ln> bareop singlop dualop loadop storop line |
%type <u_ast> expr value multident |
|
%left BOOLEANOR |
%left BOOLEANAND |
%left BITWISEOR BITWISEXOR |
%left BITWISEAND |
%left PLUS MINUS |
%left TIMES '/' |
|
%% /* The grammar follows */ |
|
input: |
412,7 → 402,6
|
#include <unistd.h> |
#include <sys/types.h> |
#include <sys/wait.h> |
#include <sys/stat.h> |
#include <sys/fcntl.h> |
#include <assert.h> |
424,8 → 413,9
if (linecp) fprintf(stderr, "Offending line was: %s\n", linecp); |
} |
|
FILE *run_preprocessor(pid_t &pid, const char *path = NULL, const char *zname = NULL) { |
FILE *run_preprocessor(const char *path = NULL, const char *zname = NULL) { |
int pipefd[2]; |
int pid; |
|
if (pipe(pipefd)!=0) { |
fprintf(stderr, "PIPE FAILED!\n"); |
477,26 → 467,11
return fdopen(pipefd[0], "r"); |
} |
|
void usage(void) { |
printf("USAGE: zasm [-h] [-d] [-E] [-o <out-fname>] <asm-file> [<asm-file> ]* ...\n"); |
printf("\t-d\tTurns on debugging in the parser\n"); |
printf("\t-E\tProduces preprocessor output only\n"); |
printf("\t-h\tDisplays this message\n"); |
printf("\t-o <out-fname>\tWrites the output to <out-fname>. The\n" |
"\t\tdefault output file is \"" DEFAULT_OUTPUT_FNAME "\".\n"); |
|
printf("\t-I <dir>\tSearch <dir> for include files.\n"); |
} |
|
int main(int argc, char **argv) { |
int skp = 0; |
const char *zout_fname = NULL; |
char *path_to_zasm = NULL; |
bool preprocess_only = false; |
FILE *ppout; |
pid_t zpp_pid; |
int zpp_status; |
|
master_input_filename = NULL; |
|
// Find what directory zasm is in, so that we can find zpp when |
518,35 → 493,16
skp++; |
} else if (argv[argn+skp][1] == 'E') |
preprocess_only = true; |
else if (argv[argn+skp][1] == 'd') |
yydebug = 1; |
else if (argv[argn+skp][1] == 'h') { |
usage(); |
exit(0); |
} |
|
skp++; |
} argv[argn] = argv[argn+skp]; |
} argc -= skp; |
|
if (zout_fname) { |
for(int argn=0; argn<argc; argn++) { |
if (strcmp(zout_fname, argv[argn])==0) { |
fprintf(stderr, "ERR: Cowardly refusing to overwrite \'%s\'\n", zout_fname); |
exit(-2); |
} |
} |
} |
|
if (preprocess_only) { |
objcode.open("/dev/null"); |
if (zout_fname) |
ppout = fopen(zout_fname, "w"); |
else |
ppout = stdout; |
} else { |
if (!zout_fname) |
zout_fname = DEFAULT_OUTPUT_FNAME; |
zout_fname = "z.out"; |
|
objcode.open(zout_fname); |
} |
564,16 → 520,14
free(master_input_filename); |
master_input_filename = strdup(argv[argn]); |
if (preprocess_only) { |
FILE *fp = run_preprocessor(zpp_pid, path_to_zasm, master_input_filename); |
FILE *fp = run_preprocessor(path_to_zasm, master_input_filename); |
int ch; |
while(EOF != (ch = fgetc(fp))) |
fputc(ch, ppout); |
waitpid(zpp_pid, &zpp_status, WNOHANG); |
fputc(ch, stdout); |
} else { |
yyrestart(run_preprocessor(zpp_pid, path_to_zasm, master_input_filename)); |
yyrestart(run_preprocessor(path_to_zasm, master_input_filename)); |
yylineno = 1; |
yyparse(); |
waitpid(zpp_pid, &zpp_status, WNOHANG); |
} |
} |
} else { // Run from Stdin |
584,24 → 538,17
master_input_filename = strdup("(stdin)"); |
if (preprocess_only) { |
int ch; |
FILE *fp = run_preprocessor(zpp_pid, path_to_zasm, master_input_filename); |
FILE *fp = run_preprocessor(path_to_zasm, master_input_filename); |
while(EOF != (ch = fgetc(fp))) |
fputc(ch, ppout); |
waitpid(zpp_pid, &zpp_status, WNOHANG); |
fputc(ch, stdout); |
} else { |
yyin = run_preprocessor(zpp_pid, NULL); |
yyin = run_preprocessor(NULL); |
yyrestart(yyin); |
yyparse(); |
waitpid(zpp_pid, &zpp_status, WNOHANG); |
} |
} |
|
if (0 != WEXITSTATUS(zpp_status)) { |
if (!preprocess_only) { |
objcode.close(); |
unlink(zout_fname); |
} |
} if (!objcode.reduce()) |
if (!objcode.reduce()) |
fprintf(stderr, "Not all symbols defined!\n"); |
} |
|
/zasm/zpp.l
137,12 → 137,11
<INNOTDEF>^"#else"[ \t]*((;|"//").*)?$ { BEGIN INDEF; } |
<INNOTDEF>(.*) { } |
<INDEF>^"#elsif"[ \t]* { BEGIN NVRDEF; } |
<NVRDEF,NODEF,INDEF,INNOTDEF>^"#endif"[ \t]*((;|"//").*)?$ { yy_pop_state(); } |
<NVRDEF,NODEF,INDEF,INNOTDEF>^"#endif"[ \t]*"/*" { BEGIN COMMENT; } |
<NODEF,INDEF,INNOTDEF>^"#endif"[ \t]*((;|"//").*)?$ { yy_pop_state(); } |
<NODEF,INDEF,INNOTDEF>^"#endif"[ \t]*"/*" { BEGIN COMMENT; } |
<*>^"#endif"[ \t]* { fprintf(stderr, "ERR: Unknown endif!!\n");} |
<INITIAL,INDEF>^"#struct"[ \t]* { |
yy_push_state(GETSTRUCTID); structno = 0; } |
<*>^"#"{ID}[ \t]* { fprintf(stderr, "ERR: Unrecognized preprocessor instruction, %s\n", yytext);} |
<GETSTRUCTID>{ID}/[ \t\n;/] { BEGIN INSTRUCT; |
structid = strdup(yytext); |
} |
161,20 → 160,11
} |
<*>[ \t]*"//".*$ { /* Ignore (trailing) comment only lines */ } |
<*>[ \t]*";".*$ { /* Ignore (trailing) comment only lines */ } |
<*>"#warning".*$ { fprintf(stderr, "WARNING: %s\n", &yytext[8]); } |
<*>"#error".*$ { fprintf(stderr, "ERROR: %s\n", &yytext[8]); exit(-1); } |
<*>"/*" { yy_push_state(COMMENT); } |
<*>[ \t]+ { ECHO; } |
<*>\n { ECHO; yylineno++; mark_line(); } |
/* <*>. { printf("Unmatched \'%c\'\n", yytext[0]); } */ |
<NVRDEF,NODEF,INDEF,INNOTDEF><<EOF>> { fprintf(stderr, "Unexpected EOF! Expecting #endif\n"); } |
<IFDEFV><<EOF>> { fprintf(stderr, "Unexpected EOF! Expecting #endif\n"); } |
<COMMENT><<EOF>> { fprintf(stderr, "Unexpected EOF! Expecting */\n"); } |
<INSTRUCT><<EOF>> { fprintf(stderr, "Unexpected EOF! Expecting #endstruct\n"); } |
<GETSTRUCTID><<EOF>> { fprintf(stderr, "Unexpected EOF! Expecting #struct ID, then #endstruct\n"); } |
<DFA,DFV,DFV_EOL><<EOF>> { fprintf(stderr, "Unexpected EOF! Expecting end of line\n"); } |
<INDEF_EOL,INNOTDEF_EOL><<EOF> { fprintf(stderr, "Unexpected EOF Expecting end of line, then #endif\n"); } |
<INITIAL><<EOF>> { if (end_of_file()) yyterminate(); } |
<<EOF>> { if (end_of_file()) yyterminate(); } |
|
%% |
|
397,12 → 387,6
fprintf(fp, "#line %d \"%s\"\n", yylineno, m_fname); |
} |
|
void markline(void) { |
FILE *fp = yyout; |
if (!fp) fp = stdout; |
fprintf(fp, "#line %d\n", yylineno); |
} |
|
static void pop(void) { |
// fprintf(stderr, "POP! (%s)\n", curbs->m_fname); |
if (curbs) |
417,9 → 401,7
const char *last_marked_file = NULL; |
void mark_line(void) { |
if ((yylineno != last_marked_line+1)||(BUFSTACK::curfilename != last_marked_file)) |
if (BUFSTACK::curfilename == last_marked_file) |
BUFSTACK::curbs->markline(); |
else BUFSTACK::curbs->mark(); |
BUFSTACK::curbs->mark(); |
last_marked_line = yylineno; |
last_marked_file = BUFSTACK::curfilename; |
} |
446,7 → 428,5
// delete bs; |
} |
} |
|
return 0; |
} |
|
/zasm/zasm.l
51,12 → 51,7
|
%% |
|
"#line"[ \t]+[0-9]+[ \t]+[\"][^"]*[\"][ \t]*$ { |
/* This should really be true *only* at the beginning of a line, |
* however such line beginnings aren't matching. My guess is that |
* the reason is my line copying code at the bottom that sucks up the |
* newline for LEX. Hence, this is what we have. |
*/ |
^"#line"[ \t]+[0-9]+[ \t]+[\"][^"]*[\"][ \t]*$ { |
yylineno = atoi(&yytext[6]); |
char *bg, *en; |
bg = strchr(yytext, '\"')+1; |
66,11 → 61,8
master_input_filename = new char[en-bg+2]; |
strcpy(master_input_filename, bg); |
} |
return '\n'; |
} |
"#line"[ \t]+[0-9]+[ \t]*$ { yylineno = atoi(&yytext[6]); return '\n';} |
^"#line".*$ { printf("WARNING: Unmatched #line: %s\n", yytext); return '\n'; } |
"#line".*$ { printf("WARNING: Unmatched #line, not at beginnning: %s\n", yytext); return '\n'; } |
^"#line"[ \t]+[0-9]+[ \t]+$ { yylineno = atoi(&yytext[6]); } |
[uU][rR]1[0-5] { yylval.u_reg=(ZPARSER::ZIPREG)(26+yytext[3]-'0');return REG; } |
[sS][rR]1[0-5] { yylval.u_reg=(ZPARSER::ZIPREG)(10+yytext[3]-'0');return REG; } |
[rR]1[0-5] { yylval.u_reg=(ZPARSER::ZIPREG)(10+yytext[2]-'0');return REG; } |
77,15 → 69,15
[uU][rR][0-9] { yylval.u_reg=(ZPARSER::ZIPREG)(16+yytext[2]-'0');return REG; } |
[sS][rR][0-9] { yylval.u_reg=(ZPARSER::ZIPREG)( yytext[2]-'0');return REG; } |
[rR][0-9] { yylval.u_reg=(ZPARSER::ZIPREG)( yytext[1]-'0');return REG; } |
(?i:upc) { yylval.u_reg = ZPARSER::ZIP_uPC; return REG; } |
(?i:spc) { yylval.u_reg = ZPARSER::ZIP_PC; return REG; } |
(?i:pc) { yylval.u_reg = ZPARSER::ZIP_PC; return REG; } |
(?i:ucc) { yylval.u_reg = ZPARSER::ZIP_uCC; return REG; } |
(?i:scc) { yylval.u_reg = ZPARSER::ZIP_CC; return REG; } |
(?i:cc) { yylval.u_reg = ZPARSER::ZIP_CC; return REG; } |
(?i:usp) { yylval.u_reg = ZPARSER::ZIP_uSP; return REG; } |
(?i:ssp) { yylval.u_reg = ZPARSER::ZIP_SP; return REG; } |
(?i:sp) { yylval.u_reg = ZPARSER::ZIP_SP; return REG; } |
[uU][pP][cC] { yylval.u_reg = ZPARSER::ZIP_uPC; return REG; } |
[sS][pP][cC] { yylval.u_reg = ZPARSER::ZIP_PC; return REG; } |
[pP][cC] { yylval.u_reg = ZPARSER::ZIP_PC; return REG; } |
[uU][cC][cC] { yylval.u_reg = ZPARSER::ZIP_uCC; return REG; } |
[sS][cC][cC] { yylval.u_reg = ZPARSER::ZIP_CC; return REG; } |
[cC][cC] { yylval.u_reg = ZPARSER::ZIP_CC; return REG; } |
[uU][sS][pP] { yylval.u_reg = ZPARSER::ZIP_uSP; return REG; } |
[sS][sS][pP] { yylval.u_reg = ZPARSER::ZIP_SP; return REG; } |
[sS][pP] { yylval.u_reg = ZPARSER::ZIP_SP; return REG; } |
[bB][rR][aA] { yylval.u_op = OP_BRA; return BRANCHOP; } |
[bB][rR][zZ] { yylval.u_op = OP_BZ; return BRANCHOP; } |
[bB][zZ] { yylval.u_op = OP_BZ; return BRANCHOP; } |
100,44 → 92,42
[bB][cC] { yylval.u_op = OP_BRC; return BRANCHOP; } |
[bB][rR][vV] { yylval.u_op = OP_BRV; return BRANCHOP; } |
[bB][vV] { yylval.u_op = OP_BRV; return BRANCHOP; } |
(?i:clr) { yylval.u_op = OP_CLR; return SINGLOP; } |
(?i:clrf) {yylval.u_op = OP_CLRF;return SINGLOP; } |
(?i:int) { yylval.u_op = OP_TRAP;return SINGLOP; } |
(?i:trap) {yylval.u_op = OP_TRAP;return SINGLOP; } |
(?i:jmp) { yylval.u_op = OP_JMP; return SINGLOP; } |
[cC][lL][rR] { yylval.u_op = OP_CLR; return SINGLOP; } |
[cC][lL][rR][fF] {yylval.u_op = OP_CLRF;return SINGLOP; } |
[iI][nN][tT] { yylval.u_op = OP_TRAP;return SINGLOP; } |
[tT][rR][aA][pP] {yylval.u_op = OP_TRAP;return SINGLOP; } |
[jJ][mM][pP] { yylval.u_op = OP_JMP; return SINGLOP; } |
[lL][jJ][mM][pP] {yylval.u_op = OP_LJMP;return SINGLOP; } |
(?i:neg) { yylval.u_op = OP_NEG; return SINGLOP; } |
(?i:not) { yylval.u_op = OP_NOT; return SINGLOP; } |
(?i:cmp) { yylval.u_op = OP_CMP; return DUALOP; } |
(?i:tst) { yylval.u_op = OP_TST; return DUALOP; } |
(?i:mov) { yylval.u_op = OP_MOV; return DUALOP; } |
(?i:ldi) { yylval.u_op = OP_LDI; return LDIOP; } |
[nN][oO][tT] { yylval.u_op = OP_NOT; return SINGLOP; } |
[cC][mM][pP] { yylval.u_op = OP_CMP; return DUALOP; } |
[tT][sS][tT] { yylval.u_op = OP_TST; return DUALOP; } |
[mM][oO][vV] { yylval.u_op = OP_MOV; return DUALOP; } |
[lL][dD][iI] { yylval.u_op = OP_LDI; return LDIOP; } |
[lL][dD][iI][hH][iI] { yylval.u_op =OP_LDIHI; return LDHLOP; } |
[lL][dD][iI][lL][oO] { yylval.u_op =OP_LDILO; return LDHLOP; } |
(?i:mpyu) { yylval.u_op = OP_MPYU; return DUALOP; } |
(?i:mpys) { yylval.u_op = OP_MPYS; return DUALOP; } |
(?i:rol) { yylval.u_op = OP_ROL; return DUALOP; } |
(?i:sub) { yylval.u_op = OP_SUB; return DUALOP; } |
(?i:and) { yylval.u_op = OP_AND; return DUALOP; } |
(?i:add) { yylval.u_op = OP_ADD; return DUALOP; } |
(?i:or) { yylval.u_op = OP_OR; return DUALOP;; } |
(?i:xor) { yylval.u_op = OP_XOR; return DUALOP; } |
(?i:lsl) { yylval.u_op = OP_LSL; return DUALOP; } |
(?i:asr) { yylval.u_op = OP_ASR; return DUALOP; } |
(?i:lsr) { yylval.u_op = OP_LSR; return DUALOP; } |
(?i:lod) { yylval.u_op = OP_LOD; return LOADOP; } |
(?i:sto) { yylval.u_op = OP_STO; return STOROP; } |
(?i:halt) { yylval.u_op = OP_HALT; return BAREOP; } |
(?i:wait) { yylval.u_op = OP_HALT; return BAREOP; } |
(?i:rtu) { yylval.u_op = OP_RTU; return BAREOP; } |
(?i:nop) { yylval.u_op = OP_NOOP; return BAREOP; } |
(?i:noop) { yylval.u_op = OP_NOOP; return BAREOP; } |
(?i:break) { yylval.u_op = OP_BREAK; return BAREOP; } |
(?i:brk) { yylval.u_op = OP_BREAK; return BAREOP; } |
(?i:busy) { yylval.u_op = OP_BUSY; return BAREOP; } |
(?i:equ) { return EQU; } |
(?i:fill) { return FILL; } |
(?i:word) { return WORD; } |
[mM][pP][yY] { yylval.u_op = OP_MPY; return DUALOP; } |
[rR][oO][lL] { yylval.u_op = OP_ROL; return DUALOP; } |
[sS][uU][bB] { yylval.u_op = OP_SUB; return DUALOP; } |
[aA][nN][dD] { yylval.u_op = OP_AND; return DUALOP; } |
[aA][dD][dD] { yylval.u_op = OP_ADD; return DUALOP; } |
[oO][rR] { yylval.u_op = OP_OR; return DUALOP;; } |
[xX][oO][rR] { yylval.u_op = OP_XOR; return DUALOP; } |
[lL][sS][lL] { yylval.u_op = OP_LSL; return DUALOP; } |
[aA][sS][rR] { yylval.u_op = OP_ASR; return DUALOP; } |
[lL][sS][rR] { yylval.u_op = OP_LSR; return DUALOP; } |
[lL][oO][dD] { yylval.u_op = OP_LOD; return LOADOP; } |
[sS][tT][oO] { yylval.u_op = OP_STO; return STOROP; } |
[hH][aA][lL][tT] { yylval.u_op = OP_HALT; return BAREOP; } |
[wW][aA][iI][tT] { yylval.u_op = OP_HALT; return BAREOP; } |
[rR][tT][uU] { yylval.u_op = OP_RTU; return BAREOP; } |
[nN][oO][pP] { yylval.u_op = OP_NOOP; return BAREOP; } |
[nN][oO][oO][pP] { yylval.u_op = OP_NOOP; return BAREOP; } |
[bB][rR][eE][aA][kK] { yylval.u_op = OP_BREAK; return BAREOP; } |
[bB][rR][kK] { yylval.u_op = OP_BREAK; return BAREOP; } |
[bB][uU][sS][yY] { yylval.u_op = OP_BUSY; return BAREOP; } |
[eE][qQ][uU] { return EQU; } |
[fF][iI][lL][lL] { return FILL; } |
[wW][oO][rR][dD] { return WORD; } |
"__"[hH][eE][rR][eE]"__" { return HERE; } |
[\.][dD][aA][tT] { return WORD; } |
[\.][zZ]/[ \t\n] { yylval.u_cond = ZPARSER::ZIPC_Z; return COND; } |
155,27 → 145,6
"$"?[-]?[1-9][0-9]* { yylval.u_ival = strtoul(yytext+(((*yytext)=='$')?1:0),NULL,10);return INT;} |
"$"?[-]?[1-9A-Fa-f][0-9A-Fa-f]*h {yylval.u_ival=strtoul(yytext+(((*yytext)=='$')?1:0),NULL,16); return INT;} |
"$"?[-]?[0-7]+o { yylval.u_ival = strtoul(yytext+(((*yytext)=='$')?1:0),NULL, 8);return INT;} |
"\'"[^\\\']"\'" { printf("Match char, %s\n", yytext); yylval.u_ival = yytext[1]&0x0ff; return INT; } |
"\'\\"[abnr\\]"\'" { |
yylval.u_ival = yytext[2]; |
if (yytext[2] == 'a') yylval.u_ival = '\a'; |
else if (yytext[2] == 'b') yylval.u_ival = '\b'; |
else if (yytext[2] == 'f') yylval.u_ival = '\f'; |
else if (yytext[2] == 'n') yylval.u_ival = '\n'; |
else if (yytext[2] == 'r') yylval.u_ival = '\r'; |
else if (yytext[2] == 't') yylval.u_ival = '\t'; |
else if (yytext[2] == 'v') yylval.u_ival = '\v'; |
else if (yytext[2] == '0') yylval.u_ival = '\0'; |
else if (yytext[2] == '\\') yylval.u_ival = '\\'; |
return INT; } |
"\'"[^\\\'][^\\\']"\'" { yylval.u_ival = ((yytext[1]&0x0ff)<<8)+(yytext[2]&0x0ff); return INT; } |
"\'"[^\\\'][^\\\'][^\\\']"\'" { yylval.u_ival = ((yytext[1]&0x0ff)<<16) |
+((yytext[2]&0x0ff)<<8) |
+(yytext[3]&0x0ff); return INT; } |
"\'"[^\\\'][^\\\'][^\\\'][^\\\']"\'" { yylval.u_ival = ((yytext[1]&0x0ff)<<24) |
+((yytext[2]&0x0ff)<<16) |
+((yytext[3]&0x0ff)<<8) |
+(yytext[4]&0x0ff); return INT; } |
"$"?"0" { yylval.u_ival = 0;return INT;} |
"$" { return DOLLAR; } |
"," { return COMMA; } |
/zasm/asmdata.cpp
68,9 → 68,6
m_lines = new ASMLINE *[1]; |
m_lines[m_nlines++] = line; |
} |
|
if (m_lineno > line->m_lineno) |
m_lineno = line->m_lineno; |
}; |
|
bool LLINE::isdefined(void) { |
204,7 → 201,6
fwrite(buf, sizeof(ZIPI), 1, m_fp); |
} |
} else { |
fprintf(stderr, "Line %d contains an undefined symbol: ", ln->m_lineno); |
fprintf(stderr, "PC = 0x%08x isn\'t ready yet\n", i->m_pc); |
i->m_ln->dump(stderr); |
all_reduced = false; |
296,24 → 292,9
yyerror("16-bit Immediate out of range"); |
in = zp.op_ldilo(m_cond, imm, m_opa); |
break; |
case OP_MPYU: |
if ((m_opb == zp.ZIP_PC)||(m_opb == zp.ZIP_CC) |
||(m_opa == zp.ZIP_PC)||(m_opa == zp.ZIP_CC)) |
yyerror("MPYU does not support PC or CC register operands or results"); |
else if (m_opb == zp.ZIP_Rnone) |
in = zp.op_mpyu(m_cond, imm, m_opa); |
else |
in = zp.op_mpyu(m_cond, imm, m_opb, m_opa); |
case OP_MPY: |
in = zp.op_mpy(m_cond, imm, m_opb, m_opa); |
break; |
case OP_MPYS: |
if ((m_opb == zp.ZIP_PC)||(m_opb == zp.ZIP_CC) |
||(m_opa == zp.ZIP_PC)||(m_opa == zp.ZIP_CC)) |
yyerror("MPYS does not support PC or CC register operands or results"); |
else if (m_opb == zp.ZIP_Rnone) |
in = zp.op_mpys(m_cond, imm, m_opa); |
else |
in = zp.op_mpys(m_cond, imm, m_opb, m_opa); |
break; |
case OP_ROL: |
if (m_opa == zp.ZIP_Rnone) |
yyerror("ROL needs a register result"); |
365,7 → 346,6
LLINE *lln = new LLINE; |
lln->addline(new ILINE(zp.op_ldihi(m_cond, (imm>>16)&0x0ffff, m_opa))); |
lln->addline(new ILINE(zp.op_ldilo(m_cond, imm&0x0ffff, m_opa))); |
lln->m_lineno = m_lineno; |
return lln; |
} else |
in = zp.op_ldi(imm, m_opa); |
376,15 → 356,6
case OP_NOT: |
in = zp.op_not(m_cond, m_opb); |
break; |
case OP_NEG: |
if (m_cond != zp.ZIPC_ALWAYS) { |
yyerror("Illegal operation: Conditional negate. Negates cannot handle conditions"); |
} else { |
LLINE *lln = new LLINE; |
lln->addline(new ILINE(zp.op_not(m_opb))); |
lln->addline(new ILINE(zp.op_add(1,m_opb))); |
return lln; |
}break; |
case OP_JMP: |
if (!fitsin(imm, 16)) |
yyerror("JMP: Immediate out of range"); |
447,9 → 418,7
yyerror(ebuf); |
in = zp.op_noop(); break; |
} |
} |
ILINE *rs = new ILINE(in); |
rs->m_lineno = m_lineno; |
} return new ILINE(in); |
} |
|
int TLINE::nlines(void) { |
474,11 → 443,11
|
void TLINE::dump(FILE *fp) { |
if (m_state == 'V') |
fprintf(fp, "Void @%d\n", m_lineno); |
fprintf(fp, "Void\n"); |
else if (m_state != 'T') |
fprintf(fp, "TLINE state != T (== %c)\n", m_state); |
else { |
fprintf(fp, "TLINE @%d\n", m_lineno); |
fprintf(fp, "TLINE\n"); |
switch(m_opcode) { |
case OP_CMP: fprintf(fp, "\tTLINE OP = CMP\n"); |
break; |
486,14 → 455,12
break; |
case OP_MOV: fprintf(fp, "\tTLINE OP = MOV\n"); |
break; |
case OP_LDIHI:fprintf(fp,"\tTLINE OP = LDIHI\n"); |
case OP_LDIHI: fprintf(fp, "\tTLINE OP = LDIHI\n"); |
break; |
case OP_LDILO:fprintf(fp,"\tTLINE OP = LDILO\n"); |
case OP_LDILO: fprintf(fp, "\tTLINE OP = LDILO\n"); |
break; |
case OP_MPYU: fprintf(fp,"\tTLINE OP = MPYU\n"); |
case OP_MPY: fprintf(fp, "\tTLINE OP = MPY\n"); |
break; |
case OP_MPYS: fprintf(fp,"\tTLINE OP = MPYS\n"); |
break; |
case OP_ROL: fprintf(fp, "\tTLINE OP = ROL\n"); |
break; |
case OP_SUB: fprintf(fp, "\tTLINE OP = SUB\n"); |
537,8 → 504,6
break; |
case OP_CLR: fprintf(fp, "\tTLINE OP = CLR\n"); |
break; |
case OP_NEG: fprintf(fp, "\tTLINE OP = NEG\n"); |
break; |
case OP_TRAP: fprintf(fp, "\tTLINE OP = TRAP\n"); |
break; |
case OP_HALT: fprintf(fp, "\tTLINE OP = HALT\n"); |
/zasm/asmdata.h
49,12 → 49,11
#include "zparser.h" |
|
extern "C" char *linecp; |
extern int yylineno; |
|
typedef enum { |
// TST OPCND |
// Dual operand instructions that take conditions |
OP_CMP, OP_TST, OP_MOV, OP_LDIHI, OP_LDILO, OP_MPYU, OP_MPYS, OP_ROL, |
OP_CMP, OP_TST, OP_MOV, OP_LDIHI, OP_LDILO, OP_MPY, OP_ROL, |
OP_SUB, OP_AND, OP_ADD, OP_OR, OP_XOR, |
OP_LSL, OP_ASR, OP_LSR, |
// Memory operands/operators |
66,7 → 65,7
// Branch operands |
OP_BRA, OP_BZ, OP_BNZ, OP_BGE, OP_BGT, OP_BLT, OP_BRC, OP_BRV, |
// Single operand instructions that have no explicit conditions |
OP_CLR, OP_TRAP, OP_NEG, |
OP_CLR, OP_TRAP, |
// BAREOPs that can have conditions |
OP_HALT, OP_RTU, OP_BUSY, |
// BAREOPs without conditions |
80,7 → 79,6
class ASMLINE { |
public: |
char m_state; |
int m_lineno; |
virtual bool isdefined(void) { return true; }; |
virtual ~ASMLINE(void) {}; |
virtual int nlines(void) { return 0; } |
119,7 → 117,7
class ILINE : public ASMLINE { // Instruction line |
public: |
ZIPI m_in; |
ILINE(const ZIPI in) : m_in(in) { m_state = 'I'; m_lineno = yylineno; }; |
ILINE(const ZIPI in) : m_in(in) { m_state = 'I'; }; |
virtual bool isdefined(void) { return true; }; |
virtual int nlines(void) { return 1; } |
virtual unsigned int eval(const int lno); |
128,7 → 126,7
|
class VLINE : public ASMLINE { // Void line |
public: |
VLINE(void) { m_state = 'V'; m_lineno = yylineno; }; |
VLINE(void) { m_state = 'V'; }; |
virtual bool isdefined(void) { return true; }; |
virtual int nlines(void) { return 0; } |
virtual unsigned int eval(const int lno); |
138,7 → 136,7
class DLINE : public ASMLINE { // Data line |
public: |
ZIPI m_data; |
DLINE(const ZIPI dat) : m_data(dat) { m_state = 'D'; m_lineno = yylineno; }; |
DLINE(const ZIPI dat) : m_data(dat) { m_state = 'D'; }; |
virtual bool isdefined(void) { return true; }; |
virtual int nlines(void) { return 1; } |
virtual unsigned int eval(const int lno); |
150,7 → 148,7
public: |
int m_nlines; |
ASMLINE **m_lines; |
LLINE(void) : m_nlines(0), m_lines(NULL) { m_state = 'L'; m_lineno = yylineno; }; |
LLINE(void) : m_nlines(0), m_lines(NULL) { m_state = 'L'; }; |
void addline(ASMLINE *line) ; |
virtual bool isdefined(void); |
~LLINE(void); |
171,7 → 169,7
|
TLINE(void) : m_opcode(OP_NONE), m_cond(ZPARSER::ZIPC_ALWAYS), |
m_imm(NULL), m_opa(ZPARSER::ZIP_Rnone), m_opb(ZPARSER::ZIP_Rnone) |
{ m_state = 'T'; m_lineno = yylineno; }; |
{ m_state = 'T'; }; |
virtual bool isdefined(void) { |
if (m_imm != NULL) { |
bool answer = m_imm->isdefined(); |
262,7 → 260,6
public: |
OBJFILE(void) { m_fp = NULL; m_pc = 0; } |
void open(const char *fname); |
void close(void) { fclose(m_fp); }; |
unsigned int pc(void) { return m_pc; } |
void operator+=(ASMLINE *ln); |
bool reduce(void); |
/zasm/zparser.cpp
122,18 → 122,12
return in; |
} |
|
ZIPI ZPARSER::op_mpyu(ZIPCOND cnd, ZIPIMM imm, ZIPREG b, ZIPREG a) const { |
return (0x04<<28)|((a&0x0f)<<24)|((cnd&0x7)<<21)|(0<<20)|((b&0x0f)<<16)|(imm & 0x0ffff); |
} ZIPI ZPARSER::op_mpyu(ZIPCOND cnd, ZIPIMM imm, ZIPREG a) const { |
return (0x04<<28)|((a&0x0f)<<24)|((cnd&0x7)<<21)|(0<<20)|((0x0f)<<16)|(imm & 0x0ffff); |
ZIPI ZPARSER::op_mpy(ZIPCOND cnd, ZIPIMM imm, ZIPREG b, ZIPREG a) const { |
return DBLREGOP(0x4, cnd, imm, b, a); |
} ZIPI ZPARSER::op_mpy(ZIPCOND cnd, ZIPIMM imm, ZIPREG a) const { |
return IMMOP(0x4, cnd, imm, a); |
} |
|
ZIPI ZPARSER::op_mpys(ZIPCOND cnd, ZIPIMM imm, ZIPREG b, ZIPREG a) const { |
return (0x04<<28)|((a&0x0f)<<24)|((cnd&0x7)<<21)|(1<<20)|((b&0x0f)<<16)|(imm & 0x0ffff); |
} ZIPI ZPARSER::op_mpys(ZIPCOND cnd, ZIPIMM imm, ZIPREG a) const { |
return (0x04<<28)|((a&0x0f)<<24)|((cnd&0x7)<<21)|(1<<20)|((0x0f)<<16)|(imm & 0x0ffff); |
} |
|
ZIPI ZPARSER::op_rol(ZIPCOND cnd, ZIPIMM imm, ZIPREG b, ZIPREG a) const { |
return DBLREGOP(0x5, cnd, imm, b, a); |
} ZIPI ZPARSER::op_rol(ZIPCOND cnd, ZIPIMM imm, ZIPREG a) const { |
157,10 → 151,6
ZIPI ZPARSER::op_sub(ZIPCOND cnd, ZIPIMM imm, ZIPREG b, ZIPREG a) const { |
return DBLREGOP(0x8, cnd, imm, b, a); |
} ZIPI ZPARSER::op_sub(ZIPCOND cnd, ZIPIMM imm, ZIPREG a) const { |
// While it seems like we might do well replacing a subtract immediate |
// with an add of the negative same, the conditions aren't the same |
// when doing so. Hence this is an invalid substitution. |
// return IMMOP(0xa, cnd, -imm, a); // Do an add of the negative of imm |
return IMMOP(0x8, cnd, imm, a); |
} |
|
/zasm/obj-pc/depends.txt
1,6 → 1,7
obj-pc/asmdata.o: asmdata.cpp asmdata.h zopcodes.h zparser.h |
obj-pc/optest.o: optest.cpp zopcodes.h |
obj-pc/twoc.o: twoc.cpp twoc.h |
obj-pc/zasm.o: zasm.cpp zopcodes.h zparser.h |
obj-pc/zdump.o: zdump.cpp zopcodes.h |
obj-pc/zopcodes.o: zopcodes.cpp twoc.h zopcodes.h |
obj-pc/zparser.o: zparser.cpp zparser.h zopcodes.h |
/zasm/zparser.h
100,20 → 100,13
ZIPI op_ldilo(ZIPIMM imm, ZIPREG a) const |
{ return op_ldilo(ZIPC_ALWAYS, imm, a); } |
|
ZIPI op_mpyu(ZIPCOND cnd, ZIPIMM imm, ZIPREG b, ZIPREG a) const; |
ZIPI op_mpyu(ZIPCOND cnd, ZIPIMM imm, ZIPREG a) const; |
ZIPI op_mpyu(ZIPIMM imm, ZIPREG b, ZIPREG a) const |
{ return op_mpyu(ZIPC_ALWAYS, imm, b, a); } |
ZIPI op_mpyu(ZIPIMM imm, ZIPREG a) const |
{ return op_mpyu(ZIPC_ALWAYS, imm, a); } |
ZIPI op_mpy(ZIPCOND cnd, ZIPIMM imm, ZIPREG b, ZIPREG a) const; |
ZIPI op_mpy(ZIPCOND cnd, ZIPIMM imm, ZIPREG a) const; |
ZIPI op_mpy(ZIPIMM imm, ZIPREG b, ZIPREG a) const |
{ return op_mpy(ZIPC_ALWAYS, imm, b, a); } |
ZIPI op_mpy(ZIPIMM imm, ZIPREG a) const |
{ return op_mpy(ZIPC_ALWAYS, imm, a); } |
|
ZIPI op_mpys(ZIPCOND cnd, ZIPIMM imm, ZIPREG b, ZIPREG a) const; |
ZIPI op_mpys(ZIPCOND cnd, ZIPIMM imm, ZIPREG a) const; |
ZIPI op_mpys(ZIPIMM imm, ZIPREG b, ZIPREG a) const |
{ return op_mpys(ZIPC_ALWAYS, imm, b, a); } |
ZIPI op_mpys(ZIPIMM imm, ZIPREG a) const |
{ return op_mpys(ZIPC_ALWAYS, imm, a); } |
|
ZIPI op_rol(ZIPCOND cnd, ZIPIMM imm, ZIPREG b, ZIPREG a) const; |
ZIPI op_rol(ZIPCOND cnd, ZIPIMM imm, ZIPREG a) const; |
ZIPI op_rol(ZIPIMM imm, ZIPREG b, ZIPREG a) const |
/zasm/Makefile
95,7 → 95,7
|
.PHONY: test |
test: dumpd.txt |
z.out: test.S zasm zdump zpp |
z.out: test.S zasm zdump |
./zasm test.S -o z.out |
dumpd.txt: z.out zdump |
./zdump z.out > dumpd.txt |