cpu32

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 953b32c2d2795d9880cfdd64d3eeaf28cb7a194a
parent 215c349e8cdd79885540884c13124f469770668f
Author: Brian Swetland <swetland@frotz.net>
Date:   Sun, 19 Feb 2012 05:09:04 -0800

bugfixes and pc relative loads

- a32: fix incorrect generation of LW Rd, [Ra, imm] forms
- control: add LW Rd, [PC, imm] instruction (0x82)
- a32: add assembly and disassembly support for PC relative loads
- isa: remove obsolete branch descriptions, add new PC relative load

Diffstat:
Ma32.c | 51++++++++++++++++++++++++++++++++++++++++++---------
Misa.txt | 15+--------------
Mverilog/control.v | 1+
3 files changed, 44 insertions(+), 23 deletions(-)

diff --git a/a32.c b/a32.c @@ -36,10 +36,13 @@ int is_signed_16(unsigned n) { unsigned rom[65535]; unsigned PC = 0; +#define TYPE_BRANCH_16 1 +#define TYPE_LW_PC_16 2 + struct fixup { struct fixup *next; unsigned pc; - unsigned type; // 16, 24 + unsigned type; }; struct label { @@ -56,7 +59,16 @@ struct fixup *fixups; void fixup_branch(const char *name, int addr, int btarget, int type) { unsigned n; - n = btarget - addr - 1; + switch(type) { + case TYPE_BRANCH_16: + n = btarget - addr - 1; + break; + case TYPE_LW_PC_16: + n = 4 * (btarget - addr - 2); + break; + default: + die("unknown branch type %d\n",type); + } if (!is_signed_16(n)) { die("label '%s' at %08x is out of range of %08x\n", @@ -170,7 +182,7 @@ enum tokens { tBIS, tBIC, tSLT, tSGT, tMLO, tMHI, tASR, tMUL, tB, tBL, tBZ, tBNZ, tBLZ, tBLNZ, tLW, tSW, tR0, tR1, tR2, tR3, tR4, tR5, tR6, tR7, - rR8, tR9, tR10, tR11, tR12, tSP, tLR, tZR, + rR8, tR9, tR10, tR11, tR12, tSP, tLR, tZR, tPC, tNOP, tSNE, tNOT, tMOV, tEQU, tWORD, tASCII, tASCIIZ, NUMTOKENS, @@ -185,7 +197,7 @@ char *tnames[] = { "BIS", "BIC", "SLT", "SGT", "MLO", "MHI", "ASR", "MUL", "B", "BL", "BZ", "BNZ", "BLZ", "BLNZ", "LW", "SW", "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", - "R8", "R9", "R10", "R11", "R12", "SP", "LR", "ZR", + "R8", "R9", "R10", "R11", "R12", "SP", "LR", "ZR", "PC", "NOP", "SNE", "NOT", "MOV", "EQU", "WORD", "STRING", "ASCIIZ" }; @@ -420,6 +432,10 @@ void printinst(char *buf, unsigned pc, unsigned instr, const char *fmt) { buf = append(buf,"0x"); buf = append_u32(buf,(pc + 4 + s16)); break; + case 'l': + buf = append(buf,"0x"); + buf = append_u32(buf,(pc + 8 + ((short)i16))); + break; case 0: goto done; } @@ -445,6 +461,8 @@ struct { { 0xF0000000, 0x10000000, "@F @B, @A, @s", }, { 0xFF00FFFF, 0x22000000, "LW @B, [@A]", }, { 0xFF000000, 0x22000000, "LW @B, [@A, #@s]", }, +// { 0xFF000000, 0x82000000, "LW @B, [PC, #@s]", }, + { 0xFF000000, 0x82000000, "LW @B, [@l]", }, { 0xFF00FFFF, 0x32000000, "SW @B, [@A]", }, { 0xFF000000, 0x32000000, "SW @B, [@A, #@s]", }, { 0xFFFF0000, 0x4FFF0000, "B @r", }, @@ -479,7 +497,7 @@ void disassemble(char *buf, unsigned pc, unsigned instr) { void assemble_line(int n, unsigned *tok, unsigned *num, char **str) { unsigned instr = 0; - unsigned tmp; + unsigned tmp, tmp2; if (tok[0] == tSTRING) { if (tok[1] == tCOLON) { @@ -545,7 +563,7 @@ void assemble_line(int n, unsigned *tok, unsigned *num, char **str) { emit(0x6FF00000 | TO_D(tmp) | TO_B(to_register(tok[1]))); } else if (tok[1] == tSTRING) { emit(0x4FF00000 | TO_B(tmp)); - uselabel(str[1], PC - 1, 16); + uselabel(str[1], PC - 1, TYPE_BRANCH_16); } else if (tok[1] == tDOT) { emit(0x4FF00000 | TO_B(tmp) | TO_I16(-1)); } else { @@ -569,7 +587,7 @@ void assemble_line(int n, unsigned *tok, unsigned *num, char **str) { emit(instr | 0x20000000 | TO_D(tmp) | TO_B(to_register(tok[3]))); } else if (tok[3] == tSTRING) { emit(instr | TO_B(tmp)); - uselabel(str[3], PC - 1, 16); + uselabel(str[3], PC - 1, TYPE_BRANCH_16); } else if (tok[3] == tDOT) { emit(instr | TO_I16(-1)); } else { @@ -585,8 +603,23 @@ void assemble_line(int n, unsigned *tok, unsigned *num, char **str) { } expect_register(tok[1]); expect(tCOMMA,tok[2]); + if (tok[3] == tSTRING) { + if (tok[0] == tSW) + die("cannot store pc relative"); + emit(0x82F00000 | TO_B(to_register(tok[1]))); + uselabel(str[3], PC - 1, TYPE_LW_PC_16); + return; + } expect(tOBRACK,tok[3]); - expect_register(tok[4]); + if (tok[4] == tPC) { + if (tok[0] == tSW) + die("cannot store pc relative"); + tmp2 = 0xF; + instr = 0x82000000; + } else { + expect_register(tok[4]); + tmp2 = to_register(tok[4]); + } if (tok[5] == tCOMMA) { expect(tNUMBER, tok[6]); expect(tCBRACK, tok[7]); @@ -596,7 +629,7 @@ void assemble_line(int n, unsigned *tok, unsigned *num, char **str) { tmp = 0; } if (!is_signed_16(tmp)) die("index too large"); - instr |= TO_B(to_register(tok[1])) | TO_A(to_register(tok[4]) | TO_I16(tmp)); + instr |= TO_B(to_register(tok[1])) | TO_A(tmp2) | TO_I16(tmp); emit(instr); return; case tWORD: diff --git a/isa.txt b/isa.txt @@ -16,25 +16,12 @@ Core Instruction Set 22 LW Rd, [Ra, #I] Rd = M(Ra + I) 32 SW Rd, [Ra, #I] M(Ra + I) = Rd -40 BLZ Rd, Ra, rel if (Ra == 0) { Rd = PC + 4, PC += I } -48 BLNZ Rd, Ra, rel if (Ra != 0) { Rd = PC + 4, PC += I } -50 BLZ Rd, Ra, Rb if (Ra == 0) { Rd = PC + 4, PC = Rb } -58 BLNZ Rd, Ra, Rb if (Ra != 0) { Rd = PC + 4, PC = Rb } - 4F BLZ Rd, Ra, rel if (Ra == 0) { Rd = PC + 4, PC += I } 5F BLNZ Rd, Ra, rel if (Ra != 0) { Rd = PC + 4, PC += I } 6F BLZ Rd, Ra, Rb if (Ra == 0) { Rd = PC + 4, PC = Rb } 7F BLNZ Rd, Ra, Rb if (Ra != 0) { Rd = PC + 4, PC = Rb } -Extended Instruction Set (tbd) ------------------------- - -52 LW Rd, [PC, #I] Rd = M(PC + I) - -6X LB -7X SB -8X LH -9X SH +82 LW Rd, [PC, #I] Rd = M(PC + 8 + I) ALU Instructions (replace Rb w/ #I for immediate form) ------------------------------------------------------ diff --git a/verilog/control.v b/verilog/control.v @@ -33,6 +33,7 @@ always @ (*) begin 4'b0101: control = 7'b1010110; // BLNZ rel16 4'b0110: control = 7'b1010010; // BLZ Rb 4'b0111: control = 7'b1010010; // BLNZ Rb + 4'b1000: control = 7'b1110101; // LW Rd, [PC, #I] 4'b1110: control = 7'b1100000; // NOP default: control = 7'b0000000; endcase