diff --git a/bsnes/Makefile b/bsnes/Makefile index dbd165fca..d090f05a7 100755 --- a/bsnes/Makefile +++ b/bsnes/Makefile @@ -89,6 +89,6 @@ sync: rm -r phoenix/test archive-all: - tar -cjf bsnes.tar.bz2 base data gameboy libco nall nes obj out phoenix ruby snes ui ui-debugger ui-libsnes Makefile cc.bat clean.bat + tar -cjf bsnes.tar.bz2 base data gameboy libco nall nes obj out phoenix ruby snes ui ui-debugger ui-libsnes Makefile cc.bat purge.bat help:; diff --git a/bsnes/base/base.hpp b/bsnes/base/base.hpp index 9ccfe02a4..212850664 100755 --- a/bsnes/base/base.hpp +++ b/bsnes/base/base.hpp @@ -1,7 +1,7 @@ #ifndef BASE_HPP #define BASE_HPP -const char Version[] = "086.13"; +const char Version[] = "086.14"; #include #include diff --git a/bsnes/nall/snes/cartridge.hpp b/bsnes/nall/snes/cartridge.hpp index 0dfbba856..6a350c2c5 100755 --- a/bsnes/nall/snes/cartridge.hpp +++ b/bsnes/nall/snes/cartridge.hpp @@ -529,19 +529,10 @@ SnesCartridge::SnesCartridge(const uint8_t *data, unsigned size) { if(has_st018) markup.append( " \n" - " \n" - " \n" - " \n" - ); - - #if 0 - if(has_st018) markup.append( - " \n" " \n" " \n" - " \n" + " \n" ); - #endif markup.append("\n"); } diff --git a/bsnes/clean.bat b/bsnes/purge.bat similarity index 100% rename from bsnes/clean.bat rename to bsnes/purge.bat diff --git a/bsnes/snes/chip/armdsp/armdsp.cpp b/bsnes/snes/chip/armdsp/armdsp.cpp index 37f3060f8..9fa79e399 100755 --- a/bsnes/snes/chip/armdsp/armdsp.cpp +++ b/bsnes/snes/chip/armdsp/armdsp.cpp @@ -35,13 +35,13 @@ void ArmDSP::enter() { if(pipeline.reload) { pipeline.reload = false; pipeline.prefetch.address = r[15]; - pipeline.prefetch.opcode = bus_read<4>(r[15]); + pipeline.prefetch.opcode = bus_readword(r[15]); r[15].step(); } pipeline.instruction = pipeline.prefetch; pipeline.prefetch.address = r[15]; - pipeline.prefetch.opcode = bus_read<4>(r[15]); + pipeline.prefetch.opcode = bus_readword(r[15]); r[15].step(); //if(pipeline.instruction.address == 0x0000ef5c) trace = 1; @@ -68,11 +68,15 @@ void ArmDSP::enter() { } } +//MMIO: $00-3f|80-bf:3800-38ff +//3800-3807 mirrored throughout +//a0 ignored + uint8 ArmDSP::mmio_read(unsigned addr) { cpu.synchronize_coprocessors(); uint8 data = 0x00; - addr &= 0xffff; + addr &= 0xff06; if(addr == 0x3800) { if(bridge.armtocpu.ready) { @@ -104,7 +108,7 @@ void ArmDSP::mmio_write(unsigned addr, uint8 data) { usleep(200000); } - addr &= 0xffff; + addr &= 0xff06; if(addr == 0x3802) { bridge.cputoarm.ready = true; @@ -131,12 +135,21 @@ void ArmDSP::power() { fp.read(dataROM, 32 * 1024); fp.close(); } + + filename = { dir(filename), "disassembly.txt" }; + fp.open(filename, file::mode::write); + for(unsigned n = 0; n < 128 * 1024; n += 4) { + fp.print(disassemble_opcode(n), "\n"); + } + fp.close(); } void ArmDSP::reset() { create(ArmDSP::Enter, 21477272); for(auto &rd : r) rd = 0; + shiftercarry = 0; + exception = false; pipeline.reload = true; diff --git a/bsnes/snes/chip/armdsp/armdsp.hpp b/bsnes/snes/chip/armdsp/armdsp.hpp index 50fc2e9be..ea9aa712b 100755 --- a/bsnes/snes/chip/armdsp/armdsp.hpp +++ b/bsnes/snes/chip/armdsp/armdsp.hpp @@ -42,8 +42,12 @@ struct ArmDSP : public Coprocessor { //memory.cpp uint8 bus_iread(uint32 addr); void bus_iwrite(uint32 addr, uint8 data); - template uint32 bus_read(uint32 addr); - template void bus_write(uint32 addr, uint32 data); + + uint32 bus_readbyte(uint32 addr); + uint32 bus_readword(uint32 addr); + + void bus_writebyte(uint32 addr, uint32 data); + void bus_writeword(uint32 addr, uint32 data); //disassembler.cpp string disassemble_opcode(uint32 pc); diff --git a/bsnes/snes/chip/armdsp/disassembler.cpp b/bsnes/snes/chip/armdsp/disassembler.cpp index 8a7f046be..5366b5b50 100755 --- a/bsnes/snes/chip/armdsp/disassembler.cpp +++ b/bsnes/snes/chip/armdsp/disassembler.cpp @@ -12,10 +12,11 @@ string ArmDSP::disassemble_opcode(uint32 pc) { string output{hex<8>(pc), " "}; - uint32 instruction = bus_read<4>(pc); + uint32 instruction = bus_readword(pc); output.append(hex<8>(instruction), " "); //multiply + //(mul,mla){condition}{s} rd,rm,rs,rn if((instruction & 0x0fc000f0) == 0x00000090) { uint4 condition = instruction >> 28; uint1 accumulate = instruction >> 21; @@ -33,6 +34,7 @@ string ArmDSP::disassemble_opcode(uint32 pc) { } //move to register from status register + //mrs{condition} rd,(c,s)psr if((instruction & 0x0fb000f0) == 0x01000000) { uint4 condition = instruction >> 28; uint1 psr = instruction >> 22; @@ -45,6 +47,7 @@ string ArmDSP::disassemble_opcode(uint32 pc) { } //move to status register from register + //msr{condition} (c,s)psr:{fields},rm if((instruction & 0x0fb000f0) == 0x01200000) { uint4 condition = instruction >> 28; uint1 psr = instruction >> 22; @@ -89,6 +92,34 @@ string ArmDSP::disassemble_opcode(uint32 pc) { return output; } + //data register shift + //{opcode}{condition}{s} rd,rm {shift} rs + //{opcode}{condition} rn,rm {shift} rs + //{opcode}{condition}{s} rd,rn,rm {shift} rs + if((instruction & 0x0e000090) == 0x00000010) { + uint4 condition = instruction >> 28; + uint4 opcode = instruction >> 21; + uint1 save = instruction >> 20; + uint4 rn = instruction >> 16; + uint4 rd = instruction >> 12; + uint4 rs = instruction >> 8; + uint2 mode = instruction >> 5; + uint4 rm = instruction; + + output.append(opcodes[opcode], conditions[condition]); + if(is_move(opcode)) output.append(save ? "s " : " ", registers[rd], ","); + if(is_comp(opcode)) output.append(registers[rn], ","); + if(is_math(opcode)) output.append(save ? "s " : " ", registers[rd], ",", registers[rn], ","); + output.append(registers[rm]); + if(mode == 0) output.append(" lsl "); + if(mode == 1) output.append(" lsr "); + if(mode == 2) output.append(" asr "); + if(mode == 3) output.append(" ror "); + output.append(registers[rs]); + + return output; + } + //data immediate //{opcode}{condition}{s} rd,#immediate //{opcode}{condition} rn,#immediate @@ -113,21 +144,58 @@ string ArmDSP::disassemble_opcode(uint32 pc) { } //move immediate offset - //(ldr,str){condition}{b} rd,[rn{+offset}] - //todo: support W flag + //(ldr,str){condition}{b} rd,[rn{,+/-offset}]{!} + //(ldr,str){condition}{b} rd,[rn]{,+/-offset} if((instruction & 0x0e000000) == 0x04000000) { uint4 condition = instruction >> 28; + uint1 p = instruction >> 24; uint1 u = instruction >> 23; + uint1 b = instruction >> 22; + uint1 w = instruction >> 21; uint1 load = instruction >> 20; uint4 rn = instruction >> 16; uint4 rd = instruction >> 12; uint12 immediate = instruction; - output.append(load ? "ldr" : "str", conditions[condition]); - if(instruction & 0x00400000) output.append("b"); - output.append(" ", registers[rd], ",[", registers[rn]); - if(immediate) output.append(u ? "+" : "-", "0x", hex<3>((uint12)instruction)); - output.append("]"); + output.append(load ? "ldr" : "str", conditions[condition], b ? "b " : " "); + output.append(registers[rd], ",[", registers[rn]); + if(p == 0) output.append("]"); + if(immediate) output.append(",", u ? "+" : "-", "0x", hex<3>(immediate)); + if(p == 1) output.append("]"); + if(p == 1 && w == 1) output.append("!"); + + if(rn == 15) output.append(" (0x", hex<8>(pc + 8 + (u ? +immediate : -immediate)), ")"); + + return output; + } + + //move register offset + //(ldr)(str){condition}{b} rd,[rn,rm {mode} #immediate]{!} + //(ldr)(str){condition}{b} rd,[rn],rm {mode} #immediate + if((instruction & 0x0e000010) == 0x06000000) { + uint4 condition = instruction >> 28; + uint1 p = instruction >> 24; + uint1 u = instruction >> 23; + uint1 b = instruction >> 22; + uint1 w = instruction >> 21; + uint1 load = instruction >> 20; + uint4 rn = instruction >> 16; + uint4 rd = instruction >> 12; + uint5 shift = instruction >> 7; + uint2 mode = instruction >> 5; + uint4 rm = instruction; + + output.append(load ? "ldr" : "str", conditions[condition], b ? "b " : " "); + output.append(registers[rd], ",[", registers[rn]); + if(p == 0) output.append("]"); + output.append(",", u ? "+" : "-", registers[rm]); + if(mode == 0 && shift != 0) output.append(" lsl #", shift); + if(mode == 1) output.append(" lsr #", shift == 0 ? 32u : (unsigned)shift); + if(mode == 2) output.append(" asr #", shift == 0 ? 32u : (unsigned)shift); + if(mode == 3 && shift != 0) output.append(" ror #", shift); + if(mode == 3 && shift == 0) output.append(" rrx"); + if(p == 1) output.append("]"); + if(p == 1 && w == 1) output.append("!"); return output; } @@ -166,10 +234,12 @@ string ArmDSP::disassemble_opcode(uint32 pc) { string ArmDSP::disassemble_registers() { return { "r0:", hex<8>(r[ 0]), " r1:", hex<8>(r[ 1]), " r2:", hex<8>(r[ 2]), " r3:", hex<8>(r[ 3]), - " r4:", hex<8>(r[ 4]), " r5:", hex<8>(r[ 5]), " r6:", hex<8>(r[ 6]), " r7:", hex<8>(r[ 7]), "\n", + " r4:", hex<8>(r[ 4]), " r5:", hex<8>(r[ 5]), " r6:", hex<8>(r[ 6]), " r7:", hex<8>(r[ 7]), " ", + "cpsr:", cpsr.n ? "N" : "n", cpsr.z ? "Z" : "z", cpsr.c ? "C" : "c", cpsr.v ? "V" : "v", "\n", "r8:", hex<8>(r[ 8]), " r9:", hex<8>(r[ 9]), " r10:", hex<8>(r[10]), " r11:", hex<8>(r[11]), - " r12:", hex<8>(r[12]), " r13:", hex<8>(r[13]), " r14:", hex<8>(r[14]), " r15:", hex<8>(r[15]), "\n", - "cpsr:", cpsr.n ? "N" : "n", cpsr.z ? "Z" : "z", cpsr.c ? "C" : "c", cpsr.v ? "V" : "v" + " r12:", hex<8>(r[12]), " r13:", hex<8>(r[13]), " r14:", hex<8>(r[14]), " r15:", hex<8>(r[15]), " ", + "spsr:", spsr.n ? "N" : "n", spsr.z ? "Z" : "z", spsr.c ? "C" : "c", spsr.v ? "V" : "v" + }; } diff --git a/bsnes/snes/chip/armdsp/memory.cpp b/bsnes/snes/chip/armdsp/memory.cpp index 3eab5ddd5..9bf9c321d 100755 --- a/bsnes/snes/chip/armdsp/memory.cpp +++ b/bsnes/snes/chip/armdsp/memory.cpp @@ -58,61 +58,30 @@ void ArmDSP::bus_iwrite(uint32 addr, uint8 data) { if((addr & 3) == 0) print("* ARM w", hex<8>(addr), " = ", hex<2>(data), "\n"); } -template -uint32 ArmDSP::bus_read(uint32 addr) { - uint32 data = 0; - - if(size == 1) { - uint32 mask = 255u << ((addr & ~3) << 3); - data |= bus_iread(addr) & mask; - } - - if(size == 4) { - addr &= ~3; - data |= bus_iread(addr + 0) << 0; - data |= bus_iread(addr + 1) << 8; - data |= bus_iread(addr + 2) << 16; - data |= bus_iread(addr + 3) << 24; - } - - if(0&&addr >= 0x40000000 && addr <= 0x400000ff) { - if(addr != 0x40000020 || data != 0x80) - if(data) { - if(size == 1) print("* ARM r", hex<8>(addr), " = ", hex<2>(data), "\n"); - if(size == 2) print("* ARM r", hex<8>(addr), " = ", hex<4>(data), "\n"); - if(size == 4) print("* ARM r", hex<8>(addr), " = ", hex<8>(data), "\n"); - usleep(20000); - } - } - - if(size == 1) return data & 0xff; - if(size == 2) return data & 0xffff; - return data; +uint32 ArmDSP::bus_readbyte(uint32 addr) { + return bus_iread(addr); } -template -void ArmDSP::bus_write(uint32 addr, uint32 data) { - if(0&&addr >= 0x40000000 && addr <= 0x400000ff) { - if(data) { - if(size == 1) print("* ARM w", hex<8>(addr), " = ", hex<2>(data), "\n"); - if(size == 2) print("* ARM w", hex<8>(addr), " = ", hex<4>(data), "\n"); - if(size == 4) print("* ARM w", hex<8>(addr), " = ", hex<8>(data), "\n"); - usleep(20000); - } - } +uint32 ArmDSP::bus_readword(uint32 addr) { + addr &= ~3; + return ( + (bus_iread(addr + 0) << 0) + | (bus_iread(addr + 1) << 8) + | (bus_iread(addr + 2) << 16) + | (bus_iread(addr + 3) << 24) + ); +} - if(size == 1) { - uint32 mask = 255u << ((addr & ~3) << 3); - bus_iwrite(addr, data); - } +void ArmDSP::bus_writebyte(uint32 addr, uint32 data) { + return bus_iwrite(addr, data); +} - if(size == 4) { - addr &= ~3; - bus_iwrite(addr + 0, data >> 0); - bus_iwrite(addr + 1, data >> 8); - bus_iwrite(addr + 2, data >> 16); - bus_iwrite(addr + 3, data >> 24); - } +void ArmDSP::bus_writeword(uint32 addr, uint32 data) { + addr &= ~3; + bus_iwrite(addr + 0, data >> 0); + bus_iwrite(addr + 1, data >> 8); + bus_iwrite(addr + 2, data >> 16); + bus_iwrite(addr + 3, data >> 24); } #endif diff --git a/bsnes/snes/chip/armdsp/opcodes.cpp b/bsnes/snes/chip/armdsp/opcodes.cpp index 3fda67b6b..b6425fa47 100755 --- a/bsnes/snes/chip/armdsp/opcodes.cpp +++ b/bsnes/snes/chip/armdsp/opcodes.cpp @@ -29,56 +29,53 @@ bool ArmDSP::condition() { //ro = modified target void ArmDSP::opcode(uint32 rm) { uint4 opcode = instruction >> 21; - uint1 s = instruction >> 20; + uint1 save = instruction >> 20; uint4 n = instruction >> 16; uint4 d = instruction >> 12; uint32 rn = r[n]; - auto &rd = r[d]; - uint32 ri = rd, ro; - //comparison opcodes always update flags - if(opcode >= 8 && opcode <= 11) assert(s == 1); + //comparison opcodes always update flags (debug test) + //this can be removed later: s=0 opcode=8-11 is invalid + if(opcode >= 8 && opcode <= 11) assert(save == 1); - auto bit = [&](uint32 ro) { - if(!s) return; - cpsr.n = ro >> 31; - cpsr.z = ro == 0; + auto test = [&](uint32 result) { + if(save) { + cpsr.n = result >> 31; + cpsr.z = result == 0; + cpsr.c = shiftercarry; + } + return result; }; - auto add = [&](uint32 ro) { - if(!s) return; - cpsr.n = ro >> 31; - cpsr.z = ro == 0; - cpsr.c = ro < ri; - cpsr.v = ~(ri ^ rm) & (ri ^ ro) & (1u << 31); - }; - - auto sub = [&](uint32 ro) { - if(!s) return; - cpsr.n = ro >> 31; - cpsr.z = ro == 0; - cpsr.c = ro > ri; - cpsr.v = (ri ^ rm) & (ri ^ ro) & (1u << 31); + auto math = [&](uint32 source, uint32 modify, bool carry) { + uint32 result = source + modify + carry; + if(save) { + cpsr.n = result >> 31; + cpsr.z = result == 0; + cpsr.c = result < source; + cpsr.v = ~(source ^ modify) & (source ^ result) & (1u << 31); + } + return result; }; switch(opcode) { - case 0: rd = rn & rm; bit(rd); break; //AND (logical and) - case 1: rd = rn ^ rm; bit(rd); break; //EOR (logical exclusive or) - case 2: rd = rn - rm; sub(rd); break; //SUB (subtract) - case 3: rd = rm - rn; sub(rd); break; //RSB (reverse subtract) - case 4: rd = rn + rm; add(rd); break; //ADD (add) - case 5: rd = rn + rm + cpsr.c; add(rd); break; //ADC (add with carry) - case 6: rd = rn - rm -!cpsr.c; sub(rd); break; //SBC (subtract with carry) - case 7: rd = rm - rn -!cpsr.c; sub(rd); break; //RSC (reverse subtract with carry) - case 8: ro = rn & rm; bit(ro); break; //TST (test) - case 9: ro = rn ^ rm; bit(ro); break; //TEQ (test equivalence) - case 10: ro = rn - rm; sub(ro); break; //CMP (compare) - case 11: ro = rn + rm; add(ro); break; //CMN (compare negated) - case 12: rd = rn | rm; bit(rd); break; //ORR (logical inclusive or) - case 13: rd = rm; bit(rd); break; //MOV (move) - case 14: rd = rn &~rm; bit(rd); break; //BIC (bit clear) - case 15: rd =~rm; bit(rd); break; //MVN (move not) + case 0: r[d] = test(rn & rm); break; //AND + case 1: r[d] = test(rn ^ rm); break; //EOR + case 2: r[d] = math(rn, ~rm, 1); break; //SUB + case 3: r[d] = math(rm, ~rn, 1); break; //RSB + case 4: r[d] = math(rn, rm, 0); break; //ADD + case 5: r[d] = math(rn, rm, cpsr.c); break; //ADC + case 6: r[d] = math(rn, ~rm, cpsr.c); break; //SBC + case 7: r[d] = math(rm, ~rn, cpsr.c); break; //RSC + case 8: test(rn & rm); break; //TST + case 9: test(rn ^ rm); break; //TEQ + case 10: math(rn, ~rm, 1); break; //CMP + case 11: math(rn, rm, 0); break; //CMN + case 12: r[d] = test(rn | rm); break; //ORR + case 13: r[d] = test(rm); break; //MOV + case 14: r[d] = test(rn &~rm); break; //BIC + case 15: r[d] = test(~rm); break; //MVN } } @@ -203,7 +200,7 @@ void ArmDSP::op_data_immediate_shift() { if(mode == 2) asr(c, rm, rs ? rs : 32); if(mode == 3) rs ? ror(c, rm, rs) : rrx(c, rm); - if(save) cpsr.c = c; + shiftercarry = c; opcode(rm); } @@ -232,9 +229,9 @@ void ArmDSP::op_data_register_shift() { if(mode == 0) lsl(c, rm, rs < 33 ? rs : 33); if(mode == 1) lsr(c, rm, rs < 33 ? rs : 33); if(mode == 2) asr(c, rm, rs < 32 ? rs : 32); - if(mode == 3) ror(c, rm, rs < 32 ? rs : 32); + if(mode == 3 && rs) ror(c, rm, rs & 31 == 0 ? 32 : rs & 31); - if(save) cpsr.c = c; + shiftercarry = c; opcode(rm); } @@ -254,17 +251,15 @@ void ArmDSP::op_data_immediate() { uint4 shift = instruction >> 8; uint8 immediate = instruction; - bool c = cpsr.c; - uint32 rs = shift << 1; uint32 rm = (immediate >> rs) | (immediate << (32 - rs)); - if(rs) c = immediate >> 31; + if(rs) shiftercarry = immediate >> 31; - if(save) cpsr.c = c; opcode(rm); } -//(ldr,str){condition}{b} rd,[rn{+offset}] +//(ldr,str){condition}{b} rd,[rn{,+/-offset}]{!} +//(ldr,str){condition}{b} rd,[rn]{,+/-offset} //cccc 010p ubwl nnnn dddd iiii iiii iiii //c = condition //p = pre (0 = post-indexed addressing) @@ -288,22 +283,16 @@ void ArmDSP::op_move_immediate_offset() { uint32 rn = r[n]; auto &rd = r[d]; - if(l) { - if(p == 1) rn = u ? rn + rm : rn - rm; - if(b) rd = bus_read<1>(rn); - else rd = bus_read<4>(rn); - if(p == 0) rn = u ? rn + rm : rn - rm; - } else { - if(p == 1) rn = u ? rn + rm : rn - rm; - if(b) bus_write<1>(rn, rd); - else bus_write<4>(rn, rd); - if(p == 0) rn = u ? rn + rm : rn - rm; - } + if(p == 1) rn = u ? rn + rm : rn - rm; + if(l) rd = b ? bus_readbyte(rn) : bus_readword(rn); + else b ? bus_writebyte(rn, rd) : bus_writeword(rn, rd); + if(p == 0) rn = u ? rn + rm : rn - rm; if(p == 0 || w == 1) r[n] = rn; } -//(ldr)(str){condition}{b} rd,rn,rm {mode} #immediate +//(ldr)(str){condition}{b} rd,[rn,rm {mode} #immediate]{!} +//(ldr)(str){condition}{b} rd,[rn],rm {mode} #immediate //cccc 011p ubwl nnnn dddd llll lss0 mmmm //c = condition //p = pre (0 = post-indexed addressing) @@ -339,17 +328,10 @@ void ArmDSP::op_move_register_offset() { if(mode == 2) asr(c, rm, rs ? rs : 32); if(mode == 3) rs ? ror(c, rm, rs) : rrx(c, rm); - if(l) { - if(p == 1) rn = u ? rn + rm : rn - rm; - if(b) rd = bus_read<1>(rn); - else rd = bus_read<4>(rn); - if(p == 0) rn = u ? rn + rm : rn - rm; - } else { - if(p == 1) rn = u ? rn + rm : rn - rm; - if(b) bus_write<1>(rn, rd); - else bus_write<4>(rn, rd); - if(p == 0) rn = u ? rn + rm : rn - rm; - } + if(p == 1) rn = u ? rn + rm : rn - rm; + if(l) rd = b ? bus_readbyte(rn) : bus_readword(rn); + else b ? bus_writebyte(rn, rd) : bus_writeword(rn, rd); + if(p == 0) rn = u ? rn + rm : rn - rm; if(p == 0 || w == 1) r[n] = rn; } @@ -379,19 +361,11 @@ void ArmDSP::op_move_multiple() { if(p == 1 && u == 0) rn = rn - bit::count(list) * 4 + 0; //DB if(p == 0 && u == 0) rn = rn - bit::count(list) * 4 + 4; //DA - if(l) { - for(unsigned n = 0; n < 16; n++) { - if(list & (1 << n)) { - r[n] = bus_read<4>(rn); - rn += 4; - } - } - } else { - for(unsigned n = 0; n < 16; n++) { - if(list & (1 << n)) { - bus_write<4>(rn, r[n]); - rn += 4; - } + for(unsigned n = 0; n < 16; n++) { + if(list & (1 << n)) { + if(l) r[n] = bus_readword(rn); + else bus_writeword(rn, r[n]); + rn += 4; } } diff --git a/bsnes/snes/chip/armdsp/registers.hpp b/bsnes/snes/chip/armdsp/registers.hpp index 6f3d28ba0..e46461f0b 100755 --- a/bsnes/snes/chip/armdsp/registers.hpp +++ b/bsnes/snes/chip/armdsp/registers.hpp @@ -101,6 +101,8 @@ struct Register { } } r[16]; +bool shiftercarry; + struct Pipeline { bool reload; struct Instruction {