static void op_readmem(dword opcode,int bytes) { int a,x,*d; a=op_memaddr(opcode); if(bytes>0x10) { // fpu d =&st.f[OP_RT(opcode)].d; bytes-=0x10; } else { d =&st.g[OP_RT(opcode)].d; } cpu_notify_readmem(a,bytes); switch(bytes) { case -1: x=mem_read8(a); d[0]=SIGNEXT8(x); break; case 1: x=mem_read8(a); d[0]=x; break; case -2: x=mem_read16(a); d[0]=SIGNEXT16(x); break; case 2: x=mem_read16(a); d[0]=x; break; case -4: case 4: x=mem_read32(a); d[0]=x; break; case 8: case -8: d[1]=mem_read32(a); d[0]=mem_read32(a+4); break; } }
void dma_transfer(const uint8_t value, Gameboy* const gb) { constexpr const auto nbytes = sizeof(Memory::oam); const uint16_t address = value * 0x100; if (address <= 0x7F5F) { const auto offset = eval_cart_rom_offset(gb->cart, address); memcpy(gb->memory.oam, &gb->cart.data[offset], nbytes); } else if (address <= 0x9F5F) { const auto offset = eval_vram_offset(address); memcpy(gb->memory.oam, &gb->memory.vram[offset], nbytes); } else if (address >= 0xC000 && address <= 0xFD5F) { const auto offset = eval_wram_offset(address); memcpy(gb->memory.oam, &gb->memory.wram[offset], nbytes); } else { debug_printf("DMA TRANSFER OPTIMIZATION MISSED!\n"); auto addr = address; for (auto& byte : gb->memory.oam) byte = mem_read8(*gb, addr++); } }
inline uint8_t stack_pop8(Gameboy* const gb) { return mem_read8(*gb, gb->cpu.sp++); }
u32int process_opcode(farcpu *cpu) { u8int op = cpu->regs.IR; u8int mem_add = 1; //amount to add to memory to get to next OpCode u32int PC = cpu->regs.PC + 1; //just skip the opcode, to make things easier char *memory = cpu->memory; if(op == EXOP) return process_extended_opcode(cpu); switch(op) { case NOP: asm("nop"); break; //might just remove the asm statement sometime, just fo-sho right now /* * Aritmatic functions * TODO: OVERFLOW, EXCEPTION Handeling */ case INC: set_register(cpu, mem_get8(memory, PC), get_register(cpu, mem_get8(memory, PC)) + 1); mem_add++; break; case DEC: set_register(cpu, mem_get8(memory, PC), get_register(cpu, mem_get8(memory, PC)) - 1); mem_add++; break; case ADD: set_register(cpu, AL, process_in_loc(cpu, memory, PC, &mem_add) + process_in_loc(cpu, memory, PC + mem_add-1 , &mem_add)); break; case SUB: set_register(cpu, AL, process_in_loc(cpu, memory, PC, &mem_add) - process_in_loc(cpu, memory, PC + mem_add-1, &mem_add)); break; case MUL: //TODO:OPTIMIZE set_register(cpu, AL, process_in_loc(cpu, memory, PC, &mem_add) * process_in_loc(cpu, memory, PC + mem_add-1, &mem_add)); break; case DIV: //TODO:OPTIMIZE, DIV BY 0 set_register(cpu, AL, (u32int)(process_in_loc(cpu, memory, PC, &mem_add) / process_in_loc(cpu, memory, PC + mem_add-1, &mem_add))); break; //Moving data around: TODO:ADD CONTENT!!! case MOVNM: switch(mem_read8(cpu->memory, PC)){ case 0: mem_write8(cpu->memory, mem_read32(cpu->memory, PC + 2),mem_read8(cpu->memory, PC + 1)); mem_add+=6; break; case 1: mem_write16(cpu->memory, mem_read32(cpu->memory, PC + 3), mem_read16(cpu->memory, PC + 1)); mem_add+=7; break; case 2: mem_write32(cpu->memory, mem_read32(cpu->memory, PC + 6), mem_read32(cpu->memory, PC + 1)); mem_add+=9; break; } mem_add++; break; case MOVRM: switch(reg_sizes[mem_read8(cpu->memory, PC)]){ case 1: mem_write8(cpu->memory, mem_read32(cpu->memory, PC + 1), get_register(cpu, mem_read8(cpu->memory, PC))); break; case 2: mem_write16(cpu->memory, mem_read32(cpu->memory, PC + 1), get_register(cpu, mem_read8(cpu->memory, PC))); break; case 4: mem_write32(cpu->memory, mem_read32(cpu->memory, PC + 1), get_register(cpu, mem_read8(cpu->memory, PC))); break; } mem_add += 5; break; case MOVIM: mem_write8(cpu->memory, mem_read32(cpu->memory, PC), cpu->IO); mem_add += 4; break; case MOVMM: break; case MOVMR: break; case MOVNR: switch(mem_read8(cpu->memory, PC)) { case 0: set_register(cpu, mem_read8(cpu->memory, PC+2), mem_read8(cpu->memory, PC+1)); mem_add += 3; break; //byte case 1: set_register(cpu, mem_read8(cpu->memory, PC+3), mem_read16(cpu->memory, PC+1)); mem_add += 4; break; //short case 2: set_register(cpu, mem_read8(cpu->memory, PC+5), mem_read32(cpu->memory, PC+1)); mem_add += 6; break; //long } break; case MOVIR: set_register(cpu, mem_read8(cpu->memory, PC), cpu->IO); mem_add += 1; break; case MOVRR: set_register(cpu, mem_read8(cpu->memory, PC + 1), get_register(cpu, mem_read8(cpu->memory, PC))); mem_add += 2; break; //bit-minipulating: case SHL: break; case SHR: break; case AND: break; case OR: break; case XOR: break; case NOT: break; //Low-Level: case HWU: switch(mem_read16(cpu->memory, PC)) { case 0x08: gfx_upd(cpu); } mem_add += 2; break; //branching: case JMP: cpu->regs.PC = mem_read32(cpu->memory, PC); return 1; case SJP: cpu->regs.JP = mem_read32(cpu->memory, PC); mem_add += 4; break; case JZ: if(cpu->regs.AL == 0){ cpu->regs.PC = cpu->regs.JP; return 1; }break; case JNZ: if(cpu->regs.AL != 0){ cpu->regs.PC = cpu->regs.JP; return 1; }break; case JFE: if(cpu->regs.AL == cpu->regs.BL){ cpu->regs.PC = cpu->regs.JP; return 1; }break; case JNE: if(cpu->regs.AL != cpu->regs.BL){ cpu->regs.PC = cpu->regs.JP; return 1; }break; case JGT: if(cpu->regs.AL > cpu->regs.BL){ cpu->regs.PC = cpu->regs.JP; return 1; }break; break; case JNG: if(!(cpu->regs.AL > cpu->regs.BL)){ cpu->regs.PC = cpu->regs.JP; return 1; }break; case JGE: if(cpu->regs.AL >= cpu->regs.BL){ cpu->regs.PC = cpu->regs.JP; return 1; }break; case JNGE: if(!(cpu->regs.AL >= cpu->regs.BL)){ cpu->regs.PC = cpu->regs.JP; return 1; }break; case JLT: if(cpu->regs.AL < cpu->regs.BL){ cpu->regs.PC = cpu->regs.JP; return 1; }break; case JNL: if(!(cpu->regs.AL < cpu->regs.BL)){ cpu->regs.PC = cpu->regs.JP; return 1; }break; break; case JLE: if(cpu->regs.AL <= cpu->regs.BL){ cpu->regs.PC = cpu->regs.JP; return 1; }break; break; case JNLE: if(!(cpu->regs.AL <= cpu->regs.BL)){ cpu->regs.PC = cpu->regs.JP; return 1; }break; break; case MOVNRM: switch(mem_read8(cpu->memory, PC)) { case 0: set_register(cpu, get_register(cpu, mem_get8(cpu->memory, PC + 2)), mem_read8(cpu->memory, PC+1)); mem_add += 4; break; //byte case 1: set_register(cpu, get_register(cpu, mem_get8(cpu->memory, PC + 3)), mem_read16(cpu->memory, PC+1)); mem_add += 5; break; //short case 2: set_register(cpu, get_register(cpu, mem_get8(cpu->memory, PC + 5)), mem_read32(cpu->memory, PC+1)); mem_add += 7; break; //long } break; case MOVRRM: switch(reg_sizes[mem_read8(cpu->memory, PC)]){ case 1: mem_write8(cpu->memory, get_register(cpu, mem_get8(cpu->memory, PC + 1)), get_register(cpu, mem_read8(cpu->memory, PC))); break; case 2: mem_write16(cpu->memory, get_register(cpu, mem_get8(cpu->memory, PC + 1)), get_register(cpu, mem_read8(cpu->memory, PC))); break; case 4: mem_write32(cpu->memory, get_register(cpu, mem_get8(cpu->memory, PC + 1)), get_register(cpu, mem_read8(cpu->memory, PC))); break; } mem_add += 2; break; case MOVIRM: break; case MOVMRM: break; case OUTN: D("G"); cpu->IO = mem_read8(cpu->memory, PC); D("Y"); mem_add += 1; D("H"); break; case OUTR: cpu->IO = get_register(cpu, mem_read8(cpu->memory, PC)); mem_add += 1; break; case OUTM: cpu->IO = mem_read8(cpu->memory, mem_read32(cpu->memory, PC)); mem_add += 4; break; case RET: break; } cpu->regs.PC += mem_add + 0; return 0; }
int pif_plugin_payload_scan(EXTRACTED_HEADERS_T *headers, MATCH_DATA_T *match_data) { __mem uint8_t *payload; __xread uint32_t pl_data[CHUNK_LW]; __lmem uint32_t pl_mem[CHUNK_LW]; int needle_progress = 0; int i, count, to_read; uint32_t mu_len, ctm_len; /* figure out how much data is in external memory vs ctm */ if (pif_pkt_info_global.split) { /* payload split to MU */ uint32_t sop; /* start of packet offset */ sop = PIF_PKT_SOP(pif_pkt_info_global.pkt_buf, pif_pkt_info_global.pkt_num); mu_len = pif_pkt_info_global.pkt_len - (256 << pif_pkt_info_global.ctm_size) + sop; } else /* no data in MU */ mu_len = 0; /* debug info for mu_split */ pif_mu_len = mu_len; /* get the ctm byte count: * packet length - offset to parsed headers - byte_count_in_mu * Note: the parsed headers are always in ctm */ count = pif_pkt_info_global.pkt_len - pif_pkt_info_global.pkt_pl_off - mu_len; /* Get a pointer to the ctm portion */ payload = pif_pkt_info_global.pkt_buf; /* point to just beyond the parsed headers */ payload += pif_pkt_info_global.pkt_pl_off; while (count) { /* grab a maximum of chunk */ to_read = count > CHUNK_B ? CHUNK_B : count; /* grab a chunk of memory into transfer registers */ mem_read8(&pl_data, payload, to_read); /* copy from transfer registers into local memory * we can iterate over local memory, where transfer * registers we cant */ for (i = 0; i < CHUNK_LW; i++) pl_mem[i] = pl_data[i]; /* iterate over all the bytes and do the search */ for (i = 0; i < to_read; i++) { uint8_t val = pl_mem[i/4] >> (8 * (3 - (i % 4))); if (val == needle[needle_progress]) needle_progress += 1; else needle_progress = 0; if (needle_progress >= sizeof(needle)) { mem_incr32((__mem uint32_t *)&needle_detections); /* drop if found */ return PIF_PLUGIN_RETURN_DROP; } } payload += to_read; count -= to_read; } /* same as above, but for mu. Code duplicated as a manual unroll */ if (mu_len) { payload = (__addr40 void *)((uint64_t)pif_pkt_info_global.muptr << 11); /* skip over the ctm part */ payload += 256 << pif_pkt_info_global.ctm_size; count = mu_len; while (count) { /* grab a maximum of chunk */ to_read = count > CHUNK_B ? CHUNK_B : count; /* grab a chunk of memory into transfer registers */ mem_read8(&pl_data, payload, to_read); /* copy from transfer registers into local memory * we can iterate over local memory, where transfer * registers we cant */ for (i = 0; i < CHUNK_LW; i++) pl_mem[i] = pl_data[i]; /* iterate over all the bytes and do the search */ for (i = 0; i < to_read; i++) { uint8_t val = pl_mem[i/4] >> (8 * (3 - (i % 4))); if (val == needle[needle_progress]) needle_progress += 1; else needle_progress = 0; if (needle_progress >= sizeof(needle)) { mem_incr32((__mem uint32_t *)&needle_detections); /* drop if found */ return PIF_PLUGIN_RETURN_DROP; } } payload += to_read; count -= to_read; } } return PIF_PLUGIN_RETURN_FORWARD; }