diff --git a/Source/Core/DSPCore/Src/DSPCodeUtil.cpp b/Source/Core/DSPCore/Src/DSPCodeUtil.cpp index 9160dae921..a31ddae8c9 100644 --- a/Source/Core/DSPCore/Src/DSPCodeUtil.cpp +++ b/Source/Core/DSPCore/Src/DSPCodeUtil.cpp @@ -35,8 +35,10 @@ bool Assemble(const char *text, std::vector *code) // TODO: fix the terrible api of the assembler. DSPAssembler assembler(settings); - if (!assembler.Assemble(text, code)) + if (!assembler.Assemble(text, code)) { printf("%s", assembler.GetErrorString().c_str()); + return false; + } return true; } diff --git a/Source/DSPSpy/tests/dsp_base.inc b/Source/DSPSpy/tests/dsp_base.inc new file mode 100644 index 0000000000..33ef0f060b --- /dev/null +++ b/Source/DSPSpy/tests/dsp_base.inc @@ -0,0 +1,356 @@ +; This is the trojan program we send to the DSP from DSPSpy to figure it out. +REGS_BASE: equ 0x0f80 +MEM_HI: equ 0x0f7E +MEM_LO: equ 0x0f7F + +; +; CODE STARTS HERE. + +; Interrupt vectors 8 vectors, 2 opcodes each + + jmp irq0 + jmp irq1 + jmp irq2 + jmp irq3 + jmp irq4 + jmp irq5 + jmp irq6 + jmp irq7 + +; Main code at 0x10 + sbset #0x02 + sbset #0x03 + sbclr #0x04 + sbset #0x05 + sbset #0x06 + + set16 + lri $CR, #0x00ff + +; Why do we have a main label here? +main: + + clr $ACC1 + clr $ACC0 + +; get address of memory dump and copy it to DRAM + + call wait_for_dsp_mbox + si @DMBH, #0x8888 + si @DMBL, #0xdead + si @DIRQ, #0x0001 + + call wait_for_cpu_mbox + lrs $AC0.M, @CMBL + andi $ac1.m, #0x7fff + + sr @MEM_HI, $AC1.M + sr @MEM_LO, $AC0.M + + lri $ax0.l, #0 + lri $ax1.l, #0 ;(DSP_CR_IMEM | DSP_CR_TO_CPU) + lri $ax0.h, #0x2000 + lr $ac0.l, @MEM_HI + lr $ac0.m, @MEM_LO + call do_dma + + +; get address of registers and DMA them to ram + + call wait_for_dsp_mbox + si @DMBH, #0x8888 + si @DMBL, #0xbeef + si @DIRQ, #0x0001 + + call wait_for_cpu_mbox + lrs $AC0.M, @CMBL + andi $ac1.m, #0x7fff + + sr @MEM_HI, $AC1.M + sr @MEM_LO, $AC0.M + + lri $ax0.l, #REGS_BASE + lri $ax1.l, #0 ;(DSP_CR_IMEM | DSP_CR_TO_CPU) + lri $ax0.h, #0x80 + lr $ac0.l, @MEM_HI + lr $ac0.m, @MEM_LO + call do_dma + +; Read in all the registers from RAM + + lri $ar0, #REGS_BASE+1 + lrri $ar1, @$ar0 + lrri $ar2, @$ar0 + lrri $ar3, @$ar0 + lrri $ix0, @$ar0 + lrri $ix1, @$ar0 + lrri $ix2, @$ar0 + lrri $ix3, @$ar0 + lrri $r08, @$ar0 + lrri $r09, @$ar0 + lrri $r10, @$ar0 + lrri $r11, @$ar0 + lrri $st0, @$ar0 + lrri $st1, @$ar0 + lrri $st2, @$ar0 + lrri $st3, @$ar0 + lrri $ac0.h, @$ar0 + lrri $ac1.h, @$ar0 + lrri $cr, @$ar0 + lrri $sr, @$ar0 + lrri $prod.l, @$ar0 + lrri $prod.m1, @$ar0 + lrri $prod.h, @$ar0 + lrri $prod.m2, @$ar0 + lrri $ax0.l, @$ar0 + lrri $ax1.l, @$ar0 + lrri $ax0.h, @$ar0 + lrri $ax1.h, @$ar0 + lrri $ac0.l, @$ar0 + lrri $ac1.l, @$ar0 + lrri $ac0.m, @$ar0 + lrri $ac1.m, @$ar0 + lr $ar0, @REGS_BASE + + jmp start_of_test + +; This is where we jump when we're done testing, see above. +end_of_test: + + nop + nop + nop + nop + nop + nop + nop + +; We just fall into a loop, playing dead until someone resets the DSP. +dead_loop: + jmp dead_loop + +; Utility function to do DMA. +; ac0.l:ac0.m - external address. +; ax0.l - address in DSP +do_dma: + sr @DSMAH, $ac0.l + sr @DSMAL, $ac0.m + sr @DSPA, $ax0.l + sr @DSCR, $ax1.l + sr @DSBL, $ax0.h ; This kicks off the DMA. + +; Waits for said DMA to complete by watching a bit in DSCR. +wait_dma: + LRS $AC1.M, @DSCR + andcf $ac1.m, #0x0004 + JLZ wait_dma + RET + +; This waits for a mail to arrive in the DSP in-mailbox. +wait_for_dsp_mbox: + lrs $AC1.M, @DMBH + andcf $ac1.m, #0x8000 + jlz wait_for_dsp_mbox + ret + +; This waits for the CPU to grab a mail that we just sent from the DSP. +wait_for_cpu_mbox: + lrs $AC1.M, @cmbh + andcf $ac1.m, #0x8000 + jlnz wait_for_cpu_mbox + ret + +; IRQ handlers. Not entirely sure what good they do currently. +irq0: + lri $ac0.m, #0x0000 + jmp irq +irq1: + lri $ac0.m, #0x0001 + jmp irq +irq2: + lri $ac0.m, #0x0002 + jmp irq +irq3: + lri $ac0.m, #0x0003 + jmp irq +irq4: + lri $ac0.m, #0x0004 + jmp irq +irq5: +; No idea what this code is doing. + set16 + mrr $st1, $ac0.l + mrr $st1, $ac0.m + clr $acc0 + mrr $ac0.m, $st1 + mrr $ac0.l, $st1 + nop ; Or why there's a nop sled here. + nop + nop + nop + nop + nop + rti + + lri $ac0.m, #0x0005 + jmp irq +irq6: + lri $ac0.m, #0x0006 + jmp irq +irq7: + lri $ac0.m, #0x0007 + jmp irq + +irq: + lrs $AC1.M, @DMBH + andcf $ac1.m, #0x8000 + jlz irq + si @DMBH, #0x8BAD + sr @DMBL, $r11 +;sr @DMBL, $ac0.m + si @DIRQ, #0x0001 + halt + +; DMA:s the current state of the registers back to the PowerPC. To do this, +; it must write the contents of all regs to DRAM. +send_back: + ; make state safe. + set16 + ; store registers to reg table + sr @REGS_BASE, $ar0 + lri $ar0, #(REGS_BASE + 1) + srri @$ar0, $ar1 + srri @$ar0, $ar2 + srri @$ar0, $ar3 + srri @$ar0, $ix0 + srri @$ar0, $ix1 + srri @$ar0, $ix2 + srri @$ar0, $ix3 + srri @$ar0, $r08 + srri @$ar0, $r09 + srri @$ar0, $r10 + srri @$ar0, $r11 + srri @$ar0, $st0 + srri @$ar0, $st1 + srri @$ar0, $st2 + srri @$ar0, $st3 + srri @$ar0, $ac0.h + srri @$ar0, $ac1.h + srri @$ar0, $cr + srri @$ar0, $sr + srri @$ar0, $prod.l + srri @$ar0, $prod.m1 + srri @$ar0, $prod.h + srri @$ar0, $prod.m2 + srri @$ar0, $ax0.l + srri @$ar0, $ax1.l + srri @$ar0, $ax0.h + srri @$ar0, $ax1.h + srri @$ar0, $ac0.l + srri @$ar0, $ac1.l + srri @$ar0, $ac0.m + srri @$ar0, $ac1.m + +; Regs are stored. Prepare DMA. + lri $ax0.l, #0x0000 + lri $ax1.l, #1 ;(DSP_CR_IMEM | DSP_CR_TO_CPU) + lri $ax0.h, #0x200 + lr $ac0.l, @MEM_HI + lr $ac0.m, @MEM_LO + + lri $ar1, #8+8 + +; Now, why are we looping here? + bloop $ar1, dma_copy + call do_dma + addi $ac0.m, #0x200 + mrr $ac1.m, $ax0.l + addi $ac1.m, #0x100 + mrr $ax0.l, $ac1.m + nop + +dma_copy: + nop + +; Wait for the CPU to send us a mail. + call wait_for_dsp_mbox + si @DMBH, #0x8888 + si @DMBL, #0xfeeb + si @DIRQ, #0x0001 + +; wait for the CPU to recieve our response before we execute the next op + call wait_for_cpu_mbox + lrs $AC0.M, @CMBL + andi $ac1.m, #0x7fff + +; Restore all regs again so we're ready to execute another op. + lri $ar0, #REGS_BASE+1 + lrri $ar1, @$ar0 + lrri $ar2, @$ar0 + lrri $ar3, @$ar0 + lrri $ix0, @$ar0 + lrri $ix1, @$ar0 + lrri $ix2, @$ar0 + lrri $ix3, @$ar0 + lrri $r08, @$ar0 + lrri $r09, @$ar0 + lrri $r10, @$ar0 + lrri $r11, @$ar0 + lrri $st0, @$ar0 + lrri $st1, @$ar0 + lrri $st2, @$ar0 + lrri $st3, @$ar0 + lrri $ac0.h, @$ar0 + lrri $ac1.h, @$ar0 + lrri $cr, @$ar0 + lrri $sr, @$ar0 + lrri $prod.l, @$ar0 + lrri $prod.m1, @$ar0 + lrri $prod.h, @$ar0 + lrri $prod.m2, @$ar0 + lrri $ax0.l, @$ar0 + lrri $ax1.l, @$ar0 + lrri $ax0.h, @$ar0 + lrri $ax1.h, @$ar0 + lrri $ac0.l, @$ar0 + lrri $ac1.l, @$ar0 + lrri $ac0.m, @$ar0 + lrri $ac1.m, @$ar0 + lr $ar0, @REGS_BASE + + ret ; from send_back + +; If you are in set40 mode, use this instead of send_back if you want to stay +; in set40 mode. +send_back_40: + set16 + call send_back + set40 + ret + +; This one's odd. Doesn't look like it should work since it uses ac0.m but +; increments acm0... (acc0) +dump_memory: + lri $ar2, #0x0000 + lri $ac0.m, #0x1000 + + lri $ar1, #0x1000 + bloop $ar1, _fill_loop2 + + mrr $ar3, $ac0.m + nx'ld : $AX0.H, $AX1.H, @$AR0 + + mrr $ac1.m, $ar0 + mrr $ar0, $ar2 + srri @$ar0, $ax1.h + mrr $ar2, $ar0 + mrr $ar0, $ac1.m + + addis $acc0, #0x1 + +_fill_loop2: + nop + ret ; from dump_memory + + +start_of_test: diff --git a/Source/DSPSpy/tests/dsp_test.ds b/Source/DSPSpy/tests/dsp_test.ds new file mode 100644 index 0000000000..ecbfe0ab5e --- /dev/null +++ b/Source/DSPSpy/tests/dsp_test.ds @@ -0,0 +1,20 @@ +include "dsp_base.inc" + +; Right here we are at a specific predetermined state. +; Ideal environment to try instructions. + +; We can call send_back at any time to send data back to the PowerPC. + +; Calling set40 here seemed to crash the dsp tester in strange ways +; until I added set16 in send_back. Seems clear that it affects something important. + + lri $AC0.M, #0x1000 + call send_back + + set40 + lri $AC0.M, #0x1000 + set16 + call send_back + +; We're done, DO NOT DELETE THIS LINE + jmp end_of_test diff --git a/Source/DSPTool/Src/main.cpp b/Source/DSPTool/Src/main.cpp index d0aa7da0b8..37d90b2640 100644 --- a/Source/DSPTool/Src/main.cpp +++ b/Source/DSPTool/Src/main.cpp @@ -210,7 +210,8 @@ int main(int argc, const char *argv[]) { if(argc == 1 || (argc == 2 && (!strcmp(argv[1], "--help") || (!strcmp(argv[1], "-?"))))) { - printf("USAGE: DSPTool [-d] [-o ] [-h ] \n"); + printf("USAGE: DSPTool [-?] [--help] [-d] [-o ] [-h ] \n"); + printf("-? / --help: Prints this message\n"); printf("-d: Disassemble\n"); printf("-o : Results from stdout redirected to a file\n"); printf("-h
: Output assembly results to a header\n"); @@ -292,7 +293,10 @@ int main(int argc, const char *argv[]) if (File::ReadFileToString(true, input_name.c_str(), &source)) { std::vector code; - Assemble(source.c_str(), &code); + if(!Assemble(source.c_str(), &code)) { + printf("Assemble: Assembly failed due to errors\n"); + return 1; + } if (!output_name.empty()) { std::string binary_code; @@ -307,5 +311,8 @@ int main(int argc, const char *argv[]) } } } + + printf("Assembly completed successfully!\n"); + return 0; } \ No newline at end of file