comparison m68k_to_x86.c @ 350:91aa2aa05e68

Refactor code gen for read/write functions
author Mike Pavone <pavone@retrodev.com>
date Tue, 21 May 2013 19:26:20 -0700
parents 3923dbc2dcc4
children 2f264d2a60c2
comparison
equal deleted inserted replaced
349:ad493d38964e 350:91aa2aa05e68
4137 context->aregs[7] = context->mem_pointers[0][0] << 16 | context->mem_pointers[0][1]; 4137 context->aregs[7] = context->mem_pointers[0][0] << 16 | context->mem_pointers[0][1];
4138 uint32_t address = context->mem_pointers[0][2] << 16 | context->mem_pointers[0][3]; 4138 uint32_t address = context->mem_pointers[0][2] << 16 | context->mem_pointers[0][3];
4139 start_68k_context(context, address); 4139 start_68k_context(context, address);
4140 } 4140 }
4141 4141
4142 typedef enum {
4143 READ_16,
4144 READ_8,
4145 WRITE_16,
4146 WRITE_8
4147 } ftype;
4148
4149 uint8_t * gen_mem_fun(x86_68k_options * opts, memmap_chunk * memmap, uint32_t num_chunks, ftype fun_type)
4150 {
4151 uint8_t * dst = opts->cur_code;
4152 uint8_t * start = dst;
4153 dst = check_cycles(dst);
4154 dst = cycles(dst, BUS);
4155 dst = and_ir(dst, 0xFFFFFF, SCRATCH1, SZ_D);
4156 uint8_t *lb_jcc = NULL, *ub_jcc = NULL;
4157 uint8_t is_write = fun_type == WRITE_16 || fun_type == WRITE_8;
4158 uint8_t adr_reg = is_write ? SCRATCH2 : SCRATCH1;
4159 uint16_t access_flag = is_write ? MMAP_WRITE : MMAP_READ;
4160 uint8_t size = (fun_type == READ_16 || fun_type == WRITE_16) ? SZ_W : SZ_B;
4161 for (uint32_t chunk = 0; chunk < num_chunks; chunk++)
4162 {
4163 if (memmap[chunk].start > 0) {
4164 dst = cmp_ir(dst, memmap[chunk].start, adr_reg, SZ_D);
4165 lb_jcc = dst + 1;
4166 dst = jcc(dst, CC_C, dst+2);
4167 }
4168 if (memmap[chunk].end < 0x1000000) {
4169 dst = cmp_ir(dst, memmap[chunk].end, adr_reg, SZ_D);
4170 ub_jcc = dst + 1;
4171 dst = jcc(dst, CC_NC, dst+2);
4172 }
4173
4174 if (memmap[chunk].mask != 0xFFFFFF) {
4175 dst = and_ir(dst, memmap[chunk].mask, adr_reg, SZ_D);
4176 }
4177 void * cfun;
4178 switch (fun_type)
4179 {
4180 case READ_16:
4181 cfun = memmap[chunk].read_16;
4182 break;
4183 case READ_8:
4184 cfun = memmap[chunk].read_8;
4185 break;
4186 case WRITE_16:
4187 cfun = memmap[chunk].write_16;
4188 break;
4189 case WRITE_8:
4190 cfun = memmap[chunk].write_8;
4191 break;
4192 default:
4193 cfun = NULL;
4194 }
4195 if (cfun) {
4196 dst = call(dst, (uint8_t *)m68k_save_context);
4197 if (is_write) {
4198 //SCRATCH2 is RDI, so no need to move it there
4199 dst = mov_rr(dst, SCRATCH1, RDX, size);
4200 } else {
4201 dst = push_r(dst, CONTEXT);
4202 dst = mov_rr(dst, SCRATCH1, RDI, SZ_D);
4203 }
4204 dst = call(dst, cfun);
4205 if (is_write) {
4206 dst = mov_rr(dst, RAX, CONTEXT, SZ_Q);
4207 } else {
4208 dst = pop_r(dst, CONTEXT);
4209 dst = mov_rr(dst, RAX, SCRATCH1, size);
4210 }
4211 dst = jmp(dst, (uint8_t *)m68k_load_context);
4212 } else if(memmap[chunk].buffer && memmap[chunk].flags & access_flag) {
4213 if (size == SZ_B) {
4214 dst = xor_ir(dst, 1, adr_reg, SZ_D);
4215 }
4216 if ((int64_t)memmap[chunk].buffer <= 0x7FFFFFFF && (int64_t)memmap[chunk].buffer >= -2147483648) {
4217 if (is_write) {
4218 dst = mov_rrdisp32(dst, SCRATCH1, SCRATCH2, (int64_t)memmap[chunk].buffer, size);
4219 } else {
4220 dst = mov_rdisp32r(dst, SCRATCH1, (int64_t)memmap[chunk].buffer, SCRATCH1, size);
4221 }
4222 } else {
4223 if (is_write) {
4224 dst = push_r(dst, SCRATCH1);
4225 dst = mov_ir(dst, (int64_t)memmap[chunk].buffer, SCRATCH1, SZ_Q);
4226 dst = add_rr(dst, SCRATCH1, SCRATCH2, SZ_Q);
4227 dst = pop_r(dst, SCRATCH1);
4228 dst = mov_rrind(dst, SCRATCH1, SCRATCH2, size);
4229 } else {
4230 dst = mov_ir(dst, (int64_t)memmap[chunk].buffer, SCRATCH2, SZ_Q);
4231 dst = mov_rindexr(dst, SCRATCH2, SCRATCH1, 1, SCRATCH1, size);
4232 }
4233 }
4234 if (is_write && (memmap[chunk].flags & MMAP_CODE)) {
4235 dst = mov_rr(dst, SCRATCH2, SCRATCH1, SZ_D);
4236 dst = shr_ir(dst, 11, SCRATCH1, SZ_D);
4237 dst = bt_rrdisp32(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, ram_code_flags), SZ_D);
4238 uint8_t * not_code = dst+1;
4239 dst = jcc(dst, CC_NC, dst+2);
4240 dst = call(dst, (uint8_t *)m68k_save_context);
4241 dst = call(dst, (uint8_t *)m68k_handle_code_write);
4242 dst = mov_rr(dst, RAX, CONTEXT, SZ_Q);
4243 dst = call(dst, (uint8_t *)m68k_load_context);
4244 *not_code = dst - (not_code+1);
4245 }
4246 dst = retn(dst);
4247 } else {
4248 //Not sure the best course of action here
4249 if (!is_write) {
4250 dst = mov_ir(dst, size == SZ_B ? 0xFF : 0xFFFF, SCRATCH1, size);
4251 }
4252 dst = retn(dst);
4253 }
4254 if (lb_jcc) {
4255 *lb_jcc = dst - (lb_jcc+1);
4256 lb_jcc = NULL;
4257 }
4258 if (ub_jcc) {
4259 *ub_jcc = dst - (ub_jcc+1);
4260 ub_jcc = NULL;
4261 }
4262 }
4263 if (!is_write) {
4264 dst = mov_ir(dst, size == SZ_B ? 0xFF : 0xFFFF, SCRATCH1, size);
4265 }
4266 dst = retn(dst);
4267 opts->cur_code = dst;
4268 return start;
4269 }
4270
4142 void init_x86_68k_opts(x86_68k_options * opts, memmap_chunk * memmap, uint32_t num_chunks) 4271 void init_x86_68k_opts(x86_68k_options * opts, memmap_chunk * memmap, uint32_t num_chunks)
4143 { 4272 {
4144 opts->flags = 0; 4273 opts->flags = 0;
4145 for (int i = 0; i < 8; i++) 4274 for (int i = 0; i < 8; i++)
4146 opts->dregs[i] = opts->aregs[i] = -1; 4275 opts->dregs[i] = opts->aregs[i] = -1;
4156 size_t size = 1024 * 1024; 4285 size_t size = 1024 * 1024;
4157 opts->cur_code = alloc_code(&size); 4286 opts->cur_code = alloc_code(&size);
4158 opts->code_end = opts->cur_code + size; 4287 opts->code_end = opts->cur_code + size;
4159 opts->ram_inst_sizes = malloc(sizeof(uint8_t *) * 64); 4288 opts->ram_inst_sizes = malloc(sizeof(uint8_t *) * 64);
4160 memset(opts->ram_inst_sizes, 0, sizeof(uint8_t *) * 64); 4289 memset(opts->ram_inst_sizes, 0, sizeof(uint8_t *) * 64);
4161 uint8_t * dst = opts->read_16 = opts->cur_code;
4162 dst = check_cycles(dst);
4163 dst = cycles(dst, BUS);
4164 dst = and_ir(dst, 0xFFFFFF, SCRATCH1, SZ_D);
4165 uint8_t *lb_jcc = NULL, *ub_jcc = NULL;
4166 for (uint32_t chunk = 0; chunk < num_chunks; chunk++)
4167 {
4168 if (lb_jcc) {
4169 *lb_jcc = dst - (lb_jcc+1);
4170 lb_jcc = NULL;
4171 }
4172 if (ub_jcc) {
4173 *ub_jcc = dst - (ub_jcc+1);
4174 ub_jcc = NULL;
4175 }
4176 if (memmap[chunk].start > 0) {
4177 dst = cmp_ir(dst, memmap[chunk].start, SCRATCH1, SZ_D);
4178 lb_jcc = dst + 1;
4179 dst = jcc(dst, CC_C, dst+2);
4180 }
4181 if (memmap[chunk].end < 0x1000000) {
4182 dst = cmp_ir(dst, memmap[chunk].end, SCRATCH1, SZ_D);
4183 ub_jcc = dst + 1;
4184 dst = jcc(dst, CC_NC, dst+2);
4185 }
4186
4187 if (memmap[chunk].mask != 0xFFFFFF) {
4188 dst = and_ir(dst, memmap[chunk].mask, SCRATCH1, SZ_D);
4189 }
4190
4191 if (memmap[chunk].read_16) {
4192 dst = call(dst, (uint8_t *)m68k_save_context);
4193 dst = push_r(dst, CONTEXT);
4194 dst = mov_rr(dst, SCRATCH1, RDI, SZ_D);
4195 dst = call(dst, (uint8_t *)memmap[chunk].read_16);
4196 dst = pop_r(dst, CONTEXT);
4197 dst = mov_rr(dst, RAX, SCRATCH1, SZ_W);
4198 dst = jmp(dst, (uint8_t *)m68k_load_context);
4199 } else if(memmap[chunk].buffer && memmap[chunk].flags & MMAP_READ) {
4200 if ((int64_t)memmap[chunk].buffer <= 0x7FFFFFFF && (int64_t)memmap[chunk].buffer >= -2147483648) {
4201 dst = mov_rdisp32r(dst, SCRATCH1, (int64_t)memmap[chunk].buffer, SCRATCH1, SZ_W);
4202 } else {
4203 dst = mov_ir(dst, (int64_t)memmap[chunk].buffer, SCRATCH2, SZ_Q);
4204 dst = mov_rindexr(dst, SCRATCH2, SCRATCH1, 1, SCRATCH1, SZ_W);
4205 }
4206 dst = retn(dst);
4207 } else {
4208 //Not sure the best course of action here
4209 dst = mov_ir(dst, 0xFFFF, SCRATCH1, SZ_W);
4210 dst = retn(dst);
4211 }
4212 }
4213 if (lb_jcc) {
4214 *lb_jcc = dst - (lb_jcc+1);
4215 lb_jcc = NULL;
4216 }
4217 if (ub_jcc) {
4218 *ub_jcc = dst - (ub_jcc+1);
4219 ub_jcc = NULL;
4220 }
4221 dst = mov_ir(dst, 0xFFFF, SCRATCH1, SZ_W);
4222 dst = retn(dst);
4223 4290
4224 opts->write_16 = dst; 4291 opts->read_16 = gen_mem_fun(opts, memmap, num_chunks, READ_16);
4225 dst = check_cycles(dst); 4292 opts->read_8 = gen_mem_fun(opts, memmap, num_chunks, READ_8);
4226 dst = cycles(dst, BUS); 4293 opts->write_16 = gen_mem_fun(opts, memmap, num_chunks, WRITE_16);
4227 dst = and_ir(dst, 0xFFFFFF, SCRATCH2, SZ_D); 4294 opts->write_8 = gen_mem_fun(opts, memmap, num_chunks, WRITE_8);
4228 for (uint32_t chunk = 0; chunk < num_chunks; chunk++)
4229 {
4230 if (lb_jcc) {
4231 *lb_jcc = dst - (lb_jcc+1);
4232 lb_jcc = NULL;
4233 }
4234 if (ub_jcc) {
4235 *ub_jcc = dst - (ub_jcc+1);
4236 ub_jcc = NULL;
4237 }
4238 if (memmap[chunk].start > 0) {
4239 dst = cmp_ir(dst, memmap[chunk].start, SCRATCH2, SZ_D);
4240 lb_jcc = dst + 1;
4241 dst = jcc(dst, CC_C, dst+2);
4242 }
4243 if (memmap[chunk].end < 0x1000000) {
4244 dst = cmp_ir(dst, memmap[chunk].end, SCRATCH2, SZ_D);
4245 ub_jcc = dst + 1;
4246 dst = jcc(dst, CC_NC, dst+2);
4247 }
4248
4249 if (memmap[chunk].mask != 0xFFFFFF) {
4250 dst = and_ir(dst, memmap[chunk].mask, SCRATCH2, SZ_D);
4251 }
4252
4253 if (memmap[chunk].write_16) {
4254 dst = call(dst, (uint8_t *)m68k_save_context);
4255 //SCRATCH2 is RDI, so no need to move it there
4256 dst = mov_rr(dst, SCRATCH1, RDX, SZ_W);
4257 dst = call(dst, (uint8_t *)memmap[chunk].write_16);
4258 dst = mov_rr(dst, RAX, CONTEXT, SZ_Q);
4259 dst = jmp(dst, (uint8_t *)m68k_load_context);
4260 } else if(memmap[chunk].buffer && memmap[chunk].flags & MMAP_WRITE) {
4261 if ((int64_t)memmap[chunk].buffer <= 0x7FFFFFFF && (int64_t)memmap[chunk].buffer >= -2147483648) {
4262 dst = mov_rrdisp32(dst, SCRATCH1, SCRATCH2, (int64_t)memmap[chunk].buffer, SZ_W);
4263 } else {
4264 dst = push_r(dst, SCRATCH1);
4265 dst = mov_ir(dst, (int64_t)memmap[chunk].buffer, SCRATCH1, SZ_Q);
4266 dst = add_rr(dst, SCRATCH1, SCRATCH2, SZ_Q);
4267 dst = pop_r(dst, SCRATCH1);
4268 dst = mov_rrind(dst, SCRATCH1, SCRATCH2, SZ_W);
4269 }
4270 if (memmap[chunk].flags & MMAP_CODE) {
4271 dst = mov_rr(dst, SCRATCH2, SCRATCH1, SZ_D);
4272 dst = shr_ir(dst, 11, SCRATCH1, SZ_D);
4273 dst = bt_rrdisp32(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, ram_code_flags), SZ_D);
4274 uint8_t * not_code = dst+1;
4275 dst = jcc(dst, CC_NC, dst+2);
4276 dst = call(dst, (uint8_t *)m68k_save_context);
4277 dst = call(dst, (uint8_t *)m68k_handle_code_write);
4278 dst = mov_rr(dst, RAX, CONTEXT, SZ_Q);
4279 dst = call(dst, (uint8_t *)m68k_load_context);
4280 *not_code = dst - (not_code+1);
4281 }
4282 dst = retn(dst);
4283 } else {
4284 //Not sure the best course of action here
4285 dst = retn(dst);
4286 }
4287 }
4288 if (lb_jcc) {
4289 *lb_jcc = dst - (lb_jcc+1);
4290 lb_jcc = NULL;
4291 }
4292 if (ub_jcc) {
4293 *ub_jcc = dst - (ub_jcc+1);
4294 ub_jcc = NULL;
4295 }
4296 dst = retn(dst);
4297 4295
4298 opts->read_8 = dst; 4296 uint8_t * dst = opts->cur_code;
4299 dst = check_cycles(dst);
4300 dst = cycles(dst, BUS);
4301 dst = and_ir(dst, 0xFFFFFF, SCRATCH1, SZ_D);
4302 for (uint32_t chunk = 0; chunk < num_chunks; chunk++)
4303 {
4304 if (lb_jcc) {
4305 *lb_jcc = dst - (lb_jcc+1);
4306 lb_jcc = NULL;
4307 }
4308 if (ub_jcc) {
4309 *ub_jcc = dst - (ub_jcc+1);
4310 ub_jcc = NULL;
4311 }
4312 if (memmap[chunk].start > 0) {
4313 dst = cmp_ir(dst, memmap[chunk].start, SCRATCH1, SZ_D);
4314 lb_jcc = dst + 1;
4315 dst = jcc(dst, CC_C, dst+2);
4316 }
4317 if (memmap[chunk].end < 0x1000000) {
4318 dst = cmp_ir(dst, memmap[chunk].end, SCRATCH1, SZ_D);
4319 ub_jcc = dst + 1;
4320 dst = jcc(dst, CC_NC, dst+2);
4321 }
4322
4323 if (memmap[chunk].mask != 0xFFFFFF) {
4324 dst = and_ir(dst, memmap[chunk].mask, SCRATCH1, SZ_D);
4325 }
4326
4327 if (memmap[chunk].read_8) {
4328 dst = call(dst, (uint8_t *)m68k_save_context);
4329 dst = push_r(dst, CONTEXT);
4330 dst = mov_rr(dst, SCRATCH1, RDI, SZ_D);
4331 dst = call(dst, (uint8_t *)memmap[chunk].read_8);
4332 dst = pop_r(dst, CONTEXT);
4333 dst = mov_rr(dst, RAX, SCRATCH1, SZ_B);
4334 dst = jmp(dst, (uint8_t *)m68k_load_context);
4335 } else if(memmap[chunk].buffer && memmap[chunk].flags & MMAP_READ) {
4336 dst = xor_ir(dst, 1, SCRATCH1, SZ_D);
4337 if ((int64_t)memmap[chunk].buffer <= 0x7FFFFFFF && (int64_t)memmap[chunk].buffer >= -2147483648) {
4338 dst = mov_rdisp32r(dst, SCRATCH1, (int64_t)memmap[chunk].buffer, SCRATCH1, SZ_B);
4339 } else {
4340 dst = mov_ir(dst, (int64_t)memmap[chunk].buffer, SCRATCH2, SZ_Q);
4341 dst = mov_rindexr(dst, SCRATCH2, SCRATCH1, 1, SCRATCH1, SZ_B);
4342 }
4343 dst = retn(dst);
4344 } else {
4345 //Not sure the best course of action here
4346 dst = mov_ir(dst, 0xFF, SCRATCH1, SZ_B);
4347 dst = retn(dst);
4348 }
4349 }
4350 if (lb_jcc) {
4351 *lb_jcc = dst - (lb_jcc+1);
4352 lb_jcc = NULL;
4353 }
4354 if (ub_jcc) {
4355 *ub_jcc = dst - (ub_jcc+1);
4356 ub_jcc = NULL;
4357 }
4358 dst = mov_ir(dst, 0xFFFF, SCRATCH1, SZ_W);
4359 dst = retn(dst);
4360
4361 opts->write_8 = dst;
4362 dst = check_cycles(dst);
4363 dst = cycles(dst, BUS);
4364 dst = and_ir(dst, 0xFFFFFF, SCRATCH2, SZ_D);
4365 for (uint32_t chunk = 0; chunk < num_chunks; chunk++)
4366 {
4367 if (lb_jcc) {
4368 *lb_jcc = dst - (lb_jcc+1);
4369 lb_jcc = NULL;
4370 }
4371 if (ub_jcc) {
4372 *ub_jcc = dst - (ub_jcc+1);
4373 ub_jcc = NULL;
4374 }
4375 if (memmap[chunk].start > 0) {
4376 dst = cmp_ir(dst, memmap[chunk].start, SCRATCH2, SZ_D);
4377 lb_jcc = dst + 1;
4378 dst = jcc(dst, CC_C, dst+2);
4379 }
4380 if (memmap[chunk].end < 0x1000000) {
4381 dst = cmp_ir(dst, memmap[chunk].end, SCRATCH2, SZ_D);
4382 ub_jcc = dst + 1;
4383 dst = jcc(dst, CC_NC, dst+2);
4384 }
4385
4386 if (memmap[chunk].mask != 0xFFFFFF) {
4387 dst = and_ir(dst, memmap[chunk].mask, SCRATCH2, SZ_D);
4388 }
4389
4390 if (memmap[chunk].write_8) {
4391 dst = call(dst, (uint8_t *)m68k_save_context);
4392 //SCRATCH2 is RDI, so no need to move it there
4393 dst = mov_rr(dst, SCRATCH1, RDX, SZ_B);
4394 dst = call(dst, (uint8_t *)memmap[chunk].write_8);
4395 dst = mov_rr(dst, RAX, CONTEXT, SZ_Q);
4396 dst = jmp(dst, (uint8_t *)m68k_load_context);
4397 } else if(memmap[chunk].buffer && memmap[chunk].flags & MMAP_WRITE) {
4398 dst = xor_ir(dst, 1, SCRATCH2, SZ_D);
4399 if ((int64_t)memmap[chunk].buffer <= 0x7FFFFFFF && (int64_t)memmap[chunk].buffer >= -2147483648) {
4400 dst = mov_rrdisp32(dst, SCRATCH1, SCRATCH2, (int64_t)memmap[chunk].buffer, SZ_B);
4401 } else {
4402 dst = push_r(dst, SCRATCH1);
4403 dst = mov_ir(dst, (int64_t)memmap[chunk].buffer, SCRATCH1, SZ_Q);
4404 dst = add_rr(dst, SCRATCH1, SCRATCH2, SZ_Q);
4405 dst = pop_r(dst, SCRATCH1);
4406 dst = mov_rrind(dst, SCRATCH1, SCRATCH2, SZ_B);
4407 }
4408 if (memmap[chunk].flags & MMAP_CODE) {
4409 dst = mov_rr(dst, SCRATCH2, SCRATCH1, SZ_D);
4410 dst = shr_ir(dst, 11, SCRATCH1, SZ_D);
4411 dst = bt_rrdisp32(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, ram_code_flags), SZ_D);
4412 uint8_t * not_code = dst+1;
4413 dst = jcc(dst, CC_NC, dst+2);
4414 dst = xor_ir(dst, 1, SCRATCH2, SZ_D);
4415 dst = call(dst, (uint8_t *)m68k_save_context);
4416 dst = call(dst, (uint8_t *)m68k_handle_code_write);
4417 dst = mov_rr(dst, RAX, CONTEXT, SZ_Q);
4418 dst = call(dst, (uint8_t *)m68k_load_context);
4419 *not_code = dst - (not_code+1);
4420 }
4421 dst = retn(dst);
4422 } else {
4423 //Not sure the best course of action here
4424 dst = retn(dst);
4425 }
4426 }
4427 if (lb_jcc) {
4428 *lb_jcc = dst - (lb_jcc+1);
4429 lb_jcc = NULL;
4430 }
4431 if (ub_jcc) {
4432 *ub_jcc = dst - (ub_jcc+1);
4433 ub_jcc = NULL;
4434 }
4435 dst = retn(dst);
4436 4297
4437 opts->read_32 = dst; 4298 opts->read_32 = dst;
4438 dst = push_r(dst, SCRATCH1); 4299 dst = push_r(dst, SCRATCH1);
4439 dst = call(dst, opts->read_16); 4300 dst = call(dst, opts->read_16);
4440 dst = mov_rr(dst, SCRATCH1, SCRATCH2, SZ_W); 4301 dst = mov_rr(dst, SCRATCH1, SCRATCH2, SZ_W);