OpenCores
URL https://opencores.org/ocsvn/zipcpu/zipcpu/trunk

Subversion Repositories zipcpu

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 13 to Rev 12
    Reverse comparison

Rev 13 → Rev 12

/zipcpu/trunk/sw/zasm/zparser.cpp
4,14 → 4,7
//
// Project: Zip CPU -- a small, lightweight, RISC CPU core
//
// Purpose: This file is really mis-named. At one time it was going to
// be the parser for the Zip Assembler, zasm. Since then, I
// discovered Flex and Bison and have written a parser using
// those tools. The true parser may therefore be found in zasm.y.
// This file, however, still contains some very valuable tools.
// In particular, all of the routines used to build instructions
// from the appropriate fields are kept in this file. For example,
// op_noop() returns the instruction code for a NOOP instruction.
// Purpose:
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Tecnology, LLC
52,6 → 45,359
 
typedef ZPARSER::ZIPI ZIPI; // A Zip Instruction (i.e. uint32)
 
bool ZPARSER::iscomment(const char *line) const {
const char *sp = line;
do {
if (*sp == '\0')
return true;
else if (*sp == ';')
return true;
else if (*sp == '#')
return true;
else if (*sp == '\n')
return true;
else if (*sp == '\r')
return true;
else if ((*sp == '/')&&(sp[1] == '/'))
return true;
else if (!isspace(*sp))
return false;
} while(*sp++);
 
return true;
}
 
bool ZPARSER::islabel(const char *line) const {
const char *sp = line;
if (isspace(*line))
return false;
if (!isalpha(*line))
return false;
while((isalpha(*sp))||(isdigit(*sp))||(*sp=='_'))
sp++;
if (*sp != ':')
return false;
sp++;
return iscomment(sp);
}
 
bool ZPARSER::parse_op(const char *line, ZPARSER::ZIPA pc,
ZPARSER::ZIPI &ins, const unsigned lineno) const {
const char *sp = line;
char cpy[128], *cp = cpy, *point, *dollar, *plus, *comma, *paren,
*opc, *opb, *opa;
ZPARSER::ZIPREG ra = ZPARSER::ZIP_Rnone, rb = ZPARSER::ZIP_Rnone;
ZIPCOND cnd = ZIPC_ALWAYS;
ZIPIMM imm = 0;
bool valid = true;
 
if (!isspace(*sp))
return false;
 
while(isspace(*sp))
sp++;
// Remove comments from our local copy
for(unsigned int i=0; i<sizeof(cpy); i++) {
if (*sp == '\0')
break;
else if (*sp == ';')
break;
else if (*sp == '#')
break;
else if (*sp == '\n')
break;
else if (*sp == '\r')
break;
else if ((*sp == '/')&&(sp[1] == '/'))
break;
*cp++ = *sp++;
} if (cp-cpy >= (int)sizeof(cpy))
return false;
*cp = '\0';
point = strchr(cpy, '.');
comma = strchr(cpy, ',');
plus = strchr(cpy, '+');
dollar= strchr(cpy, '$');
paren = strchr(cpy, '(');
if (point) *point++ = '\0';
if (comma) *comma++ = '\0';
if (plus) *plus++ = '\0';
if (dollar) *dollar++ = '\0';
// if (paren) *paren++ = '\0';
cp = cpy;
while(isalpha(*cp))
cp++;
opc = cpy;
if ((*cp == '\0')&&(point == NULL))
cp[1] = '\0';
*cp = '\0';
 
if ((point)&&(strncasecmp("DAT",point,3)!=0)) {
cp = point;
while(isalpha(*cp))
cp++;
if (*cp == '\0')
cp[1] = '\0';
*cp = '\0';
 
for(int i=1; i<8; i++) {
if (strcasecmp(&zop_ccstr[i][1], point)==0) {
cnd = (ZIPCOND)i;
break;
}
} if (cnd == ZIPC_ALWAYS) {
printf("ERR: Unrecognized condition, %s\n", point);
valid = false;
}
}
 
cp++;
while(isspace(*cp))
cp++;
opb = cp;
opa = comma;
 
if (paren) {
opb = paren+1;
if ((comma)&&(opb > comma))
opa = cp;
} else if (plus)
opb = plus;
if (dollar) {
// Figure out the base
{
char *ip = dollar, mxd = 0;
if ((*ip == '0')&&(toupper(ip[1])=='X'))
imm = strtoul(dollar, NULL, 16);
else {
bool neg = false;
if (*ip == '-') {
neg = true;
ip++;
dollar++;
}
while(isdigit(*ip)||((toupper(*ip)>='A')&&(toupper(*ip)<='F'))) {
if (isalpha(*ip))
mxd = (*ip-'a')+10;
else
mxd = (*ip-'0');
ip++;
}
 
if ((mxd <= 1)&&(*ip=='d'))
imm = strtoul(dollar, NULL, 2);
else if ((mxd <= 7)&&((*dollar == '0')||(toupper(*ip)=='O')))
imm = strtoul(dollar, NULL, 8);
else if ((mxd <= 15)&&(toupper(*ip)=='H'))
imm = strtoul(dollar, NULL, 16);
else if ((toupper(*ip)=='D')||(*ip == '+')||(isspace(*ip))||(*ip == '(')||(*ip == '\0'))
imm = atoi(dollar);
else {
printf("Cannot parse immediate, %s\n", dollar);
printf("Assuming you meant %d\n", atoi(dollar));
imm = atoi(dollar);
}
 
if (neg)
imm = -imm;
}
}
} else
imm = 0;
 
if (*opb) for(int i=31; i>=0; i--) {
// printf("%s Checking for match to opB: \'%s\' to %s", opc, opb, zop_regstr[i]);
if (NULL != strcasestr(opb, zop_regstr[i])) {
// printf(" --- Match\n");
rb = (ZIPREG)i;
break;
} // else printf(" -- nope\n");
} if (opa) for(int i=31; i>=0; i--) {
// printf("%s Checking for match to opA: ,%s to %s", opc, opa, zop_regstr[i]);
if (NULL != strcasestr(opa, zop_regstr[i])) {
ra = (ZIPREG)i;
// printf(" --- Match\n");
break;
} // else printf(" -- nope\n");
}
 
if (strcasecmp("MOV",opc)!=0) {
// Only move instructions can reference user regs
if ((ra != ZIP_Rnone)&&(ra >= ZIP_uR0))
valid = false;
if ((rb != ZIP_Rnone)&&(rb >= ZIP_uR0))
valid = false;
if (!valid)
printf("ERR: Only Mov can specify user regs\n");
}
 
if ((!*opc)&&(strncasecmp("DAT",point,3)==0)) {
ins = imm;
valid = true;
} else if (strcasecmp("CMP",opc)==0) {
if (rb != ZIP_Rnone)
ins = op_cmp(cnd, imm, rb, ra);
else ins = op_cmp(cnd, imm, ra);
} else if (strcasecmp("TST",opc)==0) {
if (rb != ZIP_Rnone)
ins = op_tst(cnd, imm, rb, ra);
else if (!dollar)
ins = op_tst(cnd, ra);
else
ins = op_tst(cnd, imm, ra);
} else if (strcasecmp("MOV",opc)==0) {
if ((rb != ZIP_Rnone)&&(ra != ZIP_Rnone))
ins = op_mov(cnd, imm, rb, ra);
else { printf("ERR MOV, ra = %d, rb = %d, imm = %d, cnd = %d\nLine was: %s", (int)ra, (int)rb, (int)imm, (int)cnd, line); valid = false; }
} else if (strcasecmp("LDI",opc)==0) {
if ((rb == ZIP_Rnone)&&(cnd == ZIPC_ALWAYS))
ins = op_ldi(imm, ra);
else valid = false;
} else if (strcasecmp("trap",opc)==0) {
if ((rb == ZIP_Rnone)&&(rb == ZIP_Rnone))
ins = op_trap(cnd, imm);
else
valid = false;
} else if (strcasecmp("CLR",opc)==0) {
if ((ra == ZIP_Rnone)&&(!dollar)&&(cnd == ZIPC_ALWAYS))
ins = op_clr(rb); // Good
else valid = false;
} else if ((strcasecmp("NOOP",opc)==0)||(strcasecmp("NOP",opc)==0)) {
if ((rb == ZIP_Rnone)&&(ra == ZIP_Rnone)&&(!dollar)&&(cnd == ZIPC_ALWAYS))
ins = op_noop();
else { printf("ERR: NOP, ra=%d, rb=%d, dollar = %s\n",
(int)ra, (int)rb, (dollar)?"true":"false"); valid = false; }
} else if ((strcasecmp("BREAK",opc)==0)||(strcasecmp("BRK",opc)==0)) {
if ((rb == ZIP_Rnone)&&(ra == ZIP_Rnone)&&(!dollar)&&(cnd == ZIPC_ALWAYS))
ins = op_break();
else { printf("ERR: BRK, ra=%d, rb=%d, dollar = %s\n",
(int)ra, (int)rb, (dollar)?"true":"false"); valid = false; }
} else if ((strcasecmp("LDIHI",opc)==0)||(strcasecmp("LODIHI",opc)==0)) {
if ((dollar)&&(ra != ZIP_Rnone))
ins = op_ldihi(cnd, imm, ra);
else valid = false;
} else if ((strcasecmp("LDILO",opc)==0)||(strcasecmp("LODILO",opc)==0)){
if ((dollar)&&(ra != ZIP_Rnone))
ins = op_ldilo(cnd, imm, ra);
else valid = false;
} else if ((strcasecmp("LOD",opc)==0)||(strcasecmp("LOAD",opc)==0)) {
if (rb != ZIP_Rnone)
ins = op_lod(cnd,imm,rb,ra);
else ins = op_lod(cnd,imm,ra);
} else if ((strcasecmp("STO",opc)==0)||(strcasecmp("STOR",opc)==0)) {
// printf("STO: Imm = %d, RA = %d, RB = %d\n", imm, ra, rb);
if (rb != ZIP_Rnone)
ins = op_sto(cnd,ra,imm,rb);
else ins = op_sto(cnd,ra,imm);
} else if (strcasecmp("SUB",opc)==0) {
if (rb != ZIP_Rnone)
ins = op_sub(cnd,imm,rb,ra);
else ins = op_sub(cnd,imm,ra);
} else if (strcasecmp("AND",opc)==0) {
if (rb != ZIP_Rnone)
ins = op_and(cnd,imm,rb,ra);
else ins = op_and(cnd,imm,ra);
} else if (strcasecmp("ADD",opc)==0) {
if (rb != ZIP_Rnone)
ins = op_add(cnd,imm,rb,ra);
else ins = op_add(cnd,imm,ra);
} else if (strcasecmp("OR",opc)==0) {
if (rb != ZIP_Rnone)
ins = op_or(cnd,imm,rb,ra);
else ins = op_or(cnd,imm,ra);
} else if (strcasecmp("XOR",opc)==0) {
if (rb != ZIP_Rnone)
ins = op_xor(cnd,imm,rb,ra);
else ins = op_xor(cnd,imm,ra);
} else if ((strcasecmp("LSL",opc)==0)||(strcasecmp("ASL",opc)==0)) {
if (rb != ZIP_Rnone)
ins = op_lsl(cnd,imm,rb,ra);
else ins = op_lsl(cnd,imm,ra);
} else if (strcasecmp("ASR",opc)==0) {
if (rb != ZIP_Rnone)
ins = op_asr(cnd,imm,rb,ra);
else ins = op_asr(cnd,imm,ra);
} else if (strcasecmp("LSR",opc)==0) {
if (rb != ZIP_Rnone)
ins = op_lsr(cnd,imm,rb,ra);
else ins = op_lsr(cnd,imm,ra);
} else if (strcasecmp("BR",opc)==0) {
if ((dollar)||(ra != ZIP_Rnone)||(rb != ZIP_Rnone))
valid = false;
else ins = op_bra(cnd, imm);
} else if (strcasecmp("BRA",opc)==0) {
if ((!dollar)||(ra != ZIP_Rnone)||(rb != ZIP_Rnone)||(cnd != ZIPC_ALWAYS))
valid = false;
else ins = op_bra(imm);
} else if (strcasecmp("BRZ",opc)==0) {
if ((!dollar)||(ra != ZIP_Rnone)||(rb != ZIP_Rnone)||(cnd != ZIPC_ALWAYS))
valid = false;
else ins = op_brz(imm);
} else if ((strcasecmp("BRNZ",opc)==0)||(strcasecmp("BNZ",opc)==0)) {
if ((!dollar)||(ra != ZIP_Rnone)||(rb != ZIP_Rnone)||(cnd != ZIPC_ALWAYS))
valid = false;
else ins = op_bnz(imm);
} else if ((strcasecmp("BRGE",opc)==0)||(strcasecmp("BGE",opc)==0)) {
if ((!dollar)||(ra != ZIP_Rnone)||(rb != ZIP_Rnone)||(cnd != ZIPC_ALWAYS))
valid = false;
else ins = op_bge(imm);
} else if ((strcasecmp("BRGT",opc)==0)||(strcasecmp("BGT",opc)==0)) {
if ((!dollar)||(ra != ZIP_Rnone)||(rb != ZIP_Rnone)||(cnd != ZIPC_ALWAYS))
valid = false;
else ins = op_bgt(imm);
} else if (strcasecmp("BRZ",opc)==0) {
} else if ((strcasecmp("BRLT",opc)==0)||(strcasecmp("BLT",opc)==0)) {
if ((!dollar)||(ra != ZIP_Rnone)||(rb != ZIP_Rnone)||(cnd != ZIPC_ALWAYS))
valid = false;
else ins = op_blt(imm);
} else if ((strcasecmp("BRC",opc)==0)||(strcasecmp("BC",opc)==0)) {
if ((!dollar)||(ra != ZIP_Rnone)||(rb != ZIP_Rnone)||(cnd != ZIPC_ALWAYS))
valid = false;
else ins = op_brc(imm);
} else if ((strcasecmp("BRV",opc)==0)||(strcasecmp("BV",opc)==0)) {
if ((!dollar)||(ra != ZIP_Rnone)||(rb != ZIP_Rnone)||(cnd != ZIPC_ALWAYS))
valid = false;
else ins = op_brv(imm);
} else if (strcasecmp("CLRF",opc)==0) {
if ((ra == ZIP_Rnone)&&(!dollar)&&(imm==0))
ins = op_clrf(cnd, rb);
else valid = false;
} else if((strcasecmp("HALT",opc)==0)||(strcasecmp("WAIT",opc)==0)) {
if ((rb == ZIP_Rnone)&&(ra==ZIP_Rnone)&&(!opa)&&(!dollar))
ins = op_halt(cnd);
else valid = false;
} else if (strcasecmp("BUSY",opc)==0) {
if ((rb == ZIP_Rnone)&&(ra==ZIP_Rnone)&&(!opa)&&(!dollar))
ins = op_busy(cnd);
else valid = false;
} else if (strcasecmp("RTU",opc)==0) {
if ((rb == ZIP_Rnone)&&(ra==ZIP_Rnone)&&(imm==0)&&(!opa)&&(!dollar))
ins = op_rtu(cnd);
else { printf("ERRR,RTU, ra=%d,rb=%d,imm=%08x,comma=%s,dollar=%s\n",
(int)ra, (int)rb, imm, (opa)?"true":"false",
(dollar)?"true":"false");
valid = false;
}
} else if (strcasecmp("JMP",opc)==0) {
if ((rb != ZIP_Rnone)&&(!opa))
ins = op_not(cnd, rb);
else valid = false;
} else if (strcasecmp("NOT",opc)==0) {
if ((rb != ZIP_Rnone)&&(ra==ZIP_Rnone)&&(!opa)&&(!dollar))
ins = op_not(cnd, rb);
else valid = false;
} else valid = false;
 
return valid;
}
 
bool ZPARSER::parse(const char *line, ZPARSER::ZIPA &pc, ZPARSER::ZIPI &instruction, const unsigned int lineno) {
bool v = parse_op(line, pc, instruction, lineno);
pc = pc + 1;
return v;
}
 
#define IMMOP(OP,CND,IMM,A) (((OP&0x0f)<<28)|((A&0x0f)<<24)|((CND&0x07)<<21) \
| (IMM & 0x0fffff))
 
93,12 → 439,8
 
ZIPI ZPARSER::op_trap(ZIPCOND cnd, ZIPIMM imm) const {
ZIPI in;
if (cnd != ZIPC_ALWAYS)
return op_ldilo(cnd, imm, ZIP_CC);
else
return op_ldi(imm, ZIP_CC);
// in = ((0x4f)<<24)|((cnd&0x07)<<21)|(1<<20)|((0x0e)<<16);
// in |= (imm & 0x0ffff);
in = ((0x4f)<<24)|((cnd&0x07)<<21)|(1<<20)|((0x0e)<<16);
in |= (imm & 0x0ffff);
return in;
}
 
/zipcpu/trunk/sw/zasm/zopcodes.cpp
4,10 → 4,7
//
// Project: Zip CPU -- a small, lightweight, RISC CPU core
//
// Purpose: A simple program to handle the disassembly and definition
// of the various Zip Assembly opcodes. The primary function
// of this file is the zipi_to_string, or Zip Instruction to
// string (disassemble) conversion.
// Purpose:
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Tecnology, LLC
68,7 → 65,6
// Special case instructions. These are general instructions, but with
// special opcodes
// Conditional branches
"BUSY", 0xffffffff, 0x2f0f7fff, OPUNUSED, OPUNUSED, OPUNUSED, OPUNUSED, BITFIELD(3,21),
"BRA", 0xffff8000, 0x2f0f0000, OPUNUSED, OPUNUSED, OPUNUSED, IMMFIELD(15,0), OPUNUSED,
"BRZ", 0xffff8000, 0x2f2f0000, OPUNUSED, OPUNUSED, OPUNUSED, IMMFIELD(15,0), OPUNUSED,
"BNZ", 0xffff8000, 0x2f4f0000, OPUNUSED, OPUNUSED, OPUNUSED, IMMFIELD(15,0), OPUNUSED,
/zipcpu/trunk/sw/zasm/zparser.h
4,14 → 4,7
//
// Project: Zip CPU -- a small, lightweight, RISC CPU core
//
// Purpose: This file is really mis-named. At one time it was going to
// be header file for the parser for the Zip Assembler, zasm.
// Since then, I discovered Flex and Bison and have written a
// parser using those tools. The true parser may therefore be
// found in zasm.y. This file, however, still declares some
// very valuable tools. In particular, all of the routines used
// to build instructions from the appropriate fields are declared
// in this file.
// Purpose: The beginnings of a parser for Zip CPU assembly.
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Tecnology, LLC
63,6 → 56,10
ZIPC_C, ZIPC_V
} ZIPCOND;
 
bool iscomment(const char *line) const;
bool islabel(const char *line) const;
bool parse_op(const char *line, ZIPA pc, ZIPI &instruction, const unsigned lineno) const;
bool parse(const char *line, ZIPA &pc, ZIPI &instruction, const unsigned lineno);
 
ZIPI op_cmp(ZIPCOND cnd, ZIPIMM imm, ZIPREG b, ZIPREG a) const;
ZIPI op_cmp(ZIPCOND cnd, ZIPIMM imm, ZIPREG a) const;
/zipcpu/trunk/sw/zasm/optest.cpp
4,10 → 4,7
//
// Project: Zip CPU -- a small, lightweight, RISC CPU core
//
// Purpose: A quick test of whether we can decode opcodes properly. This
// test bypasses the assembler, and is useful when the assembler
// isn't working. Now that we've got the assembler running, this
// code isn't nearly as useful anymore.
// Purpose: A quick test of whether we can decode opcodes properly.
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Tecnology, LLC
/zipcpu/trunk/sw/zasm/test.S
8,8 → 8,8
; the CPU. As a disorganized test, it doesn't prove anything
; beyond the generic operation of the CPU.
;
; Status: As of August, 2015, this file assembles, builds, and passes
; all of its tests in the Verilator simulator.
; Status: As of July, 2015, the assembler isn't sophisticated enough
; to handle the address resolution needed to assemble this file.
;
; Creator: Dan Gisselquist, Ph.D.
; Gisselquist Tecnology, LLC
34,135 → 34,9
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
sys.bus equ 0xc0000000
sys.breaken equ 0x080
sys.step equ 0x040
sys.gie equ 0x020
sys.sleep equ 0x010
sys.ccv equ 0x008
sys.ccn equ 0x004
sys.ccc equ 0x002
sys.ccz equ 0x001
sys.bu.pic equ 0x000
sys.bus.wdt equ 0x001
sys.bus.cache equ 0x002
sys.bus.ctrpic equ 0x003
sys.bus.tma equ 0x004
sys.bus.tmb equ 0x005
sys.bus.tmc equ 0x006
sys.bus.jiffies equ 0x007
sys.bus.mtask equ 0x008
sys.bus.mpstl equ 0x009
sys.bus.mastl equ 0x00a
sys.bus.mstl equ 0x00b
sys.bus.utask equ 0x00c
sys.bus.upstl equ 0x00d
sys.bus.uastl equ 0x00e
sys.bus.ustl equ 0x00f
#define DO_TEST_ASSEMBLER
test:
#ifdef DO_TEST_ASSEMBLER
; We start out by testing our assembler. We give it some instructions, which
; are then manually checked by disassembling/dumping the result and making
; certain they match. This is not an automated test, but it is an important
; one.
noop
bra continue_test_with_testable_instructions
break
wait
busy
rtu
continue_test_with_testable_instructions:
; Now, let's place the assembler into a known state
clr r0
clr r1
clr r2
clr r3
clr r4
clr r5
clr r6
clr r7
clr r9
clr r10
clr r11
clr r12
clr r13
; Don't clear the CC register
; Don't clear the SP register
; And repeat for the user registers
mov R0,uR0
mov R0,uR1
mov R0,uR2
mov R0,uR3
mov R0,uR4
mov R0,uR5
mov R0,uR6
mov R0,uR7
mov R0,uR8
mov R0,uR9
mov R0,uR10
mov R0,uR11
mov R0,uR12
mov R0,uR13
mov R0,uCC
; Don't clear the user PC register
; Now, let's try loading some constants into registers
dead_beef equ 0xdeadbeef
ldi 0x0dead,r5
ldi 0x0beef,r6
ldi 0xdeadbeef,r7
ldihi 0xdead, r8
ldilo 0xbeef, r8
ldi dead_beef,r9
cmp r5,r6
bz test_failure
cmp r7,r8
bnz test_failure
ldi $deadbeefh,r7 ; Try loading with the $[HEX]h mneumonic
cmp r7,r8
bnz test_failure
cmp r7,r9
bnz test_failure
bra skip_dead_beef
dead_beef.base:
word 0
fill 5,dead_beef
word 0
dead_beef.zero equ 0
dead_beef.values equ 1
skip_dead_beef:
lod dead_beef.base(pc),r10 ; Should load a zero here
cmp r10,r11 ; r11 should still be zero from init abv
bnz test_failure
mov dead_beef.base(pc),r10 ; Now, let's get the address
lod dead_beef.values(r10),r10 ; r10 now equals 0xdeadbeef
cmp r10,r9
bnz test_failure
; Test whether or not we can properly decode OCTAL values
clr r0 ; Re-clear our register set first
clr r1
clr r2
clr r3
clr r4
clr r5
clr r6
clr r7
clr r9
clr r10
clr r11
clr r12
clr r13
;
ldi $024o,r0
ldi $20,r1
cmp r0,r1
bnz test_failure
ldi $024,r0
cmp r0,r1
bnz test_failure
clr r0
clr r1
mov r0,r1
mov $1+r0,r2
mov $2+r0,r3
mov $22h+r0,r4
172,76 → 46,30
add r2,r0
add $32,r0
add $-33,r0
bnz test_failure
not.z r0
bge test_failure
junk_address:
clrf r0
bnz test_failure
ldi $5,r1
cmp $0+r0,r1
not.lt r0
not.ge r1
mov junk_address(pc),r2 ; Test pc-relative addressing
mov junk_address(pc),r3
cmp r2,r3
bnz test_failure
lod junk_address(pc),r5 ; Test loads with pc-relative addressing
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
lod $-7+pc,r2
ldihi $deadh,r3
ldihi $beefh,r3
 
#ifdef NOONE // Testing comments after ifdef
#else ; After else
#endif /* and after endif */
testbench:
// Let's build a software test bench.
ldi $c0000000h,r12 ; Set R12 to point to our peripheral address
clr r12 ; R12 will point to our peripherals
ldihi $c000h,r12
mov r12,ur12
mov test_start(pc),upc
ldi 0x8000ffff,r0 ; Clear interrupts, turn all vectors off
sto r0,(r12)
mov test_start,upc
ldihi $8001,r0
ldilo $-1,r0
sto r0,$1+r12
rtu
mov ucc,r0
tst -256,r0
bnz test_failure
lod r12,r0
cmp $0,r0
bnz $1
halt
// Go into an infinite loop if the trap fails
// Permanent loop instruction -- a busy halt if you will
test_failure:
busy
 
; Now for a series of tests. If the test fails, call the trap
248,77 → 76,77
; interrupt with the test number that failed. Upon completion,
; call the trap with #0.
 
; Now for a series of tests. If the test fails, call the trap
; interrupt with the test number that failed. Upon completion,
; call the trap with #0.
 
; Test LDI to PC
; Some data registers
test_data:
.dat __here__+0x0100000+5
.dat __here__+5
test_start:
ldi $0x0100,r11
lod test_data+pc,pc
ldi $2,r11
lod $-3+pc,pc
clr r11
noop
cmp $0,r11
trap.z r11
sto.z r11,(r12)
add $1,r0
add $1,r0
 
// Let's test whether overflow works
ldi $0x0200,r11
ldi $3,r11
ldi $-1,r0
lsr $1,r0
add $1,r0
bv first_overflow_passes
trap r11
first_overflow_passes:
bv $1
sto r11,(r12)
// Overflow set from subtraction
ldi $0x0300,r11
ldi $4,r11
ldi $1,r0
rol $31,r0 ; rol $31,r0
.dat 0x5000001f ; rol $31,r0
sub $1,r0
bv subtraction_overflow_passes
trap r11
subtraction_overflow_passes:
bv $1
sto r11,(r12)
// Overflow set from LSR
ldi $0x0400,r11
ldi $5,r11
ldi $1,r0
rol $31,r0 ; rol $31,r0
.dat 0x5000001f ; rol $31,r0
lsr $1,r0
bv lsr_overflow_passes
trap r11
lsr_overflow_passes:
bv $1
sto r11,(r12)
// Overflow set from LSL
ldi $0x0500,r11
ldi $6,r11
ldi $1,r0
rol $30,r0
.dat 0x5000001e
lsl $1,r0
bv lsl_overflow_passes
trap r11
lsl_overflow_passes:
bv $1
sto r11,(r12)
 
// Overflow set from LSL, negative to positive
ldi $0x0600,r11
ldi $7,r11
ldi $1,r0
rol $31,r0
.dat 0x5000001f; // E: ROL $30,R0
lsl $1,r0
bv second_lsl_overflow_passes
trap r11
second_lsl_overflow_passes:
bv $1
sto r11,(r12)
 
// Test carry
ldi $0x0700,r11
ldi $0x010,r11
ldi $-1,r0
add $1,r0
tst $2,cc
trap.z r11
sto.z r11,(r12)
// and carry from subtraction
ldi $0x0800,r11
ldi $17,r11
sub $1,r0
tst $2,cc
trap.z r11
sto.z r11,(r12)
 
// Let's try a loop: for i=0; i<5; i++)
// We'll use R0=i, Immediates for 5
ldi $0x0800,r11
for_loop:
ldi $18,r11
clr r0
for_loop:
noop
add $1,r0
cmp $5,r0
330,8 → 158,8
// R0 = 5; (from before)
// do {
// } while (R0 > 0);
ldi $0x0900,r11
bgt_loop:
ldi $19,r11
noop
sub $1,r0
bgt bgt_loop
340,7 → 168,7
// R1 = 5; // Need to do this explicitly
// do {
// } while(R1 >= 0);
ldi $20,r0
ldi $20,r00
ldi $5,r1
bge_loop:
noop
352,31 → 180,31
// R0 = 5; (from before)
// do {
// } while (R0 > 0);
ldi $0x0a00,r11
bra mem_loop_test
ldi $21,r11
bra $1
loop_var:
.dat 0
mem_loop_test:
mov loop_var(pc),r1
mem_loop:
mov $-2+pc,r1
clr r2
ldi $5,r0
clr r2
sto r0,(r1)
mem_loop:
sto r1,(r0)
add $1,r2
add $14,r0
lod (r1),r0
sub $1,r0
sto r0,(r1)
bgt mem_loop
bgt $-6
cmp $5,r2
trap.ne r11
sto.ne r11,(r12)
 
// Return success / Test the trap interrupt
clr r11
trap r11
sto r11,(r12)
noop
noop
 
// Go into an infinite loop if the trap fails
// Permanent loop instruction -- a busy halt if you will
busy
 
// And, in case we miss a halt ...
/zipcpu/trunk/sw/zasm/obj-pc/depends.txt
1,4 → 1,3
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
/zipcpu/trunk/sw/zasm/zopcodes.h
48,7 → 48,7
#define IMMFIELD(LN,MN) (0x40000000 + (((LN&0x0ff)<<8)+(MN&0x0ff))) // Sgn extnd
// #define REGVAL(V) ((V & 0x0f)+0x020)
 
typedef unsigned int ZIPI; // A Zip CPU instruction
typedef unsigned int ZIPI;
 
typedef struct {
char s_opstr[8];
/zipcpu/trunk/sw/zasm/Makefile
4,19 → 4,9
#
# Project: Zip CPU -- a small, lightweight, RISC CPU soft core
#
# Purpose: This makefile builds an assembler preprocessor (zpp), an
# assembler (zasm) and a disassembler (zdump). Make with no
# arguments will produce these files. Other targets include:
# Purpose: This makefile builds an assembler and disassembler.
#
# make clean
# make test
# Assembles a test file and then produces a disassembly of it.
# make depends
# Doesn't work. Dependencies are currently all hand coded.
# make optest
# make tags
#
#
# Creator: Dan Gisselquist, Ph.D.
# Gisselquist Tecnology, LLC
#
40,16 → 30,16
#
################################################################################
#
.PHONY: all
all: zasm optest zdump
OBJDIR= obj-pc
CXX= g++
CC= gcc
YACC= bison
LEX= flex
YYMMDD=`date +%Y%m%d`
DBGFLAGS= -g -O0
OPTFLAGS= -O3
CCFLAGS= $(DBGFLAGS)
PROGRAMS= zasm optest zdump zpp
PROGRAMS= zasm optest zdump
 
.PHONY: programs
all: $(OBJDIR)/ programs
56,29 → 46,11
 
programs: $(PROGRAMS)
 
$(OBJDIR)/zpp.cpp: zpp.l
$(LEX) -o $@ $^
$(OBJDIR)/zpp.o: $(OBJDIR)/zpp.cpp
$(CXX) -c $(CCFLAGS) $(OBJDIR)/zpp.cpp -o $@
zpp: $(OBJDIR)/zpp.o
$(CXX) -o $@ $(CCFLAGS) $^
ZASMSRC= zasm.cpp zopcodes.cpp zparser.cpp twoc.cpp
ZASMOBJ= $(addprefix $(OBJDIR)/,$(subst .cpp,.o,$(ZASMSRC)))
zasm: $(ZASMOBJ)
$(CXX) $(CCFLAGS) $(ZASMOBJ) -o $@
 
$(OBJDIR)/zasm.tab.h: zasm.y asmdata.h zparser.h
$(YACC) -b $(OBJDIR)/zasm -d zasm.y
zasm.output: zasm.y asmdata.h
$(YACC) -v -b $(OBJDIR)/zasm -d zasm.y
$(OBJDIR)/zasm.lex.cpp: zasm.l $(OBJDIR)/zasm.tab.h
$(LEX) -o $@ zasm.l
$(OBJDIR)/zasm.lex.o: $(OBJDIR)/zasm.lex.cpp
$(CXX) -c -I. -I$(OBJDIR)/ $(CCFLAGS) $(OBJDIR)/zasm.lex.cpp -o $@
$(OBJDIR)/zasm.tab.o: $(OBJDIR)/zasm.tab.c
$(CXX) -c -I. -I$(OBJDIR)/ $(CCFLAGS) $(OBJDIR)/zasm.tab.c -o $@
$(OBJDIR)/asmdata.o: asmdata.cpp zopcodes.h zparser.h
$(CXX) -c -I. $(CCFLAGS) asmdata.cpp -o $@
zasm: $(OBJDIR)/zasm.lex.o $(OBJDIR)/zasm.tab.o $(OBJDIR)/asmdata.o
zasm: $(OBJDIR)/zparser.o $(OBJDIR)/zopcodes.o $(OBJDIR)/twoc.o
$(CXX) -o $@ $(CCFLAGS) $^
 
optest: optest.cpp zopcodes.cpp twoc.cpp twoc.h zopcodes.h
$(CXX) $(CCFLAGS) optest.cpp zopcodes.cpp twoc.cpp -o optest
 
93,16 → 65,9
$(OBJDIR)/:
@bash -c "if [ ! -e $(OBJDIR) ]; then mkdir -p $(OBJDIR); fi"
 
.PHONY: test
test: dumpd.txt
z.out: test.S zasm zdump
./zasm test.S -o z.out
dumpd.txt: z.out zdump
./zdump z.out > dumpd.txt
 
define build-depends
@echo "Building dependency file(s)"
@$(CXX) -I $(OBJDIR)/ $(CCFLAGS) -MM *.cpp > xd.txt
@$(CXX) $(CCFLAGS) -MM *.cpp > xd.txt
@sed -e 's/^.*.o: /$(OBJDIR)\/&/' < xd.txt > $(OBJDIR)/depends.txt
@rm xd.txt
endef
115,13 → 80,19
depends: tags
$(build-depends)
 
$(OBJDIR)/depends.txt: $(SOURCES) $(HEADERS)
$(OBJDIR)/depends.txt: $(OBJDIR)/ $(SOURCES) $(HEADERS)
$(build-depends)
 
.PHONY: clean
clean:
rm -rf $(OBJDIR) $(PROGRAMS) z.out dumpd.txt
rm -rf $(OBJDIR) $(PROGRAMS)
 
-include $(OBJDIR)/depends.txt
 
 
 
 
 
 
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.